001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.servicemix.jbi.framework;
018
019 import java.util.MissingResourceException;
020 import java.util.logging.Logger;
021
022 import javax.jbi.JBIException;
023 import javax.jbi.component.Component;
024 import javax.jbi.component.ComponentContext;
025 import javax.jbi.management.MBeanNames;
026 import javax.jbi.messaging.DeliveryChannel;
027 import javax.jbi.servicedesc.ServiceEndpoint;
028 import javax.management.MBeanServer;
029 import javax.management.ObjectName;
030 import javax.naming.InitialContext;
031 import javax.xml.namespace.QName;
032
033 import org.w3c.dom.Document;
034 import org.w3c.dom.DocumentFragment;
035
036 import org.apache.commons.logging.Log;
037 import org.apache.commons.logging.LogFactory;
038 import org.apache.servicemix.jbi.container.ActivationSpec;
039 import org.apache.servicemix.jbi.container.ComponentEnvironment;
040 import org.apache.servicemix.jbi.container.JBIContainer;
041 import org.apache.servicemix.jbi.container.SubscriptionSpec;
042 import org.apache.servicemix.jbi.servicedesc.InternalEndpoint;
043
044 /**
045 * This context provides access to data needed by all JBI components running in the JBI environment.
046 *
047 * @version $Revision: 564374 $
048 */
049 public class ComponentContextImpl implements ComponentContext, MBeanNames {
050
051 private static final Log LOG = LogFactory.getLog(ComponentContextImpl.class);
052
053 private ComponentNameSpace componentName;
054 private ComponentEnvironment environment;
055 private JBIContainer container;
056 private Component component;
057 private DeliveryChannel deliveryChannel;
058 private ActivationSpec activationSpec;
059 private boolean activated;
060
061 /**
062 * Constructor
063 *
064 * @param container
065 * @param componentName
066 */
067 public ComponentContextImpl(JBIContainer container, ComponentNameSpace componentName) {
068 this.componentName = componentName;
069 this.container = container;
070 }
071
072 /**
073 * Activate the ComponentContext
074 *
075 * @param comp
076 * @param channel
077 * @param env
078 * @param spec
079 * @param installRoot
080 */
081 public void activate(Component comp,
082 ComponentEnvironment env,
083 ActivationSpec spec) {
084 this.component = comp;
085 this.environment = env;
086 this.activationSpec = spec;
087 activated = true;
088 //activate and subscriptions
089 container.getRegistry().registerSubscriptions(this, spec);
090 }
091
092 /**
093 * get the id of the ComponentConnector
094 *
095 * @return the id
096 */
097 public ComponentNameSpace getComponentNameSpace() {
098 return componentName;
099 }
100
101 /**
102 * @return the unique component name
103 */
104 public String getComponentName() {
105 return componentName.getName();
106 }
107
108 /**
109 * @return this component instance
110 */
111 public Component getComponent() {
112 return component;
113 }
114
115 /**
116 * @param serviceName
117 * @param endpointName
118 * @return EndPointReference
119 * @throws JBIException
120 */
121 public ServiceEndpoint activateEndpoint(QName serviceName, String endpointName) throws JBIException {
122 checkActivated();
123 if (LOG.isDebugEnabled()) {
124 LOG.debug("Component: " + componentName.getName() + " activated endpoint: " + serviceName + " : " + endpointName);
125 }
126 return container.getRegistry().activateEndpoint(this, serviceName, endpointName);
127 }
128
129 /**
130 * @param serviceName
131 * @return endpoints registered against the service
132 * @throws JBIException
133 */
134 public ServiceEndpoint[] availableEndpoints(QName serviceName) throws JBIException {
135 checkActivated();
136 return container.getRegistry().getEndpointsForService(serviceName);
137 }
138
139 /**
140 * Deregister the endpoint with the NMR
141 *
142 * @param endpoint
143 * @throws JBIException
144 */
145 public void deactivateEndpoint(ServiceEndpoint endpoint) throws JBIException {
146 checkActivated();
147 container.getRegistry().deactivateEndpoint(this, (InternalEndpoint) endpoint);
148 }
149
150 /**
151 * Register All subscriptions
152 * @param context
153 * @param as
154 */
155 public void registerSubscriptions(ComponentContextImpl context, ActivationSpec as) {
156 checkActivated();
157 container.getRegistry().registerSubscriptions(context, as);
158 }
159
160 /**
161 * Deregister All subscriptions
162 * @param context
163 * @param as
164 */
165 public void deregisterSubscriptions(ComponentContextImpl context, ActivationSpec as) {
166 checkActivated();
167 container.getRegistry().deregisterSubscriptions(context, as);
168 }
169
170 /**
171 * @param context
172 * @param subscription
173 * @param endpoint
174 */
175 public void registerSubscription(ComponentContextImpl context, SubscriptionSpec subscription, ServiceEndpoint endpoint) {
176 checkActivated();
177 container.getRegistry().registerSubscription(context, subscription, endpoint);
178 }
179
180 /**
181 * @param context
182 * @param subscription
183 * @return the ServiceEndpoint
184 */
185 public InternalEndpoint deregisterSubscription(ComponentContextImpl context, SubscriptionSpec subscription) {
186 checkActivated();
187 return container.getRegistry().deregisterSubscription(context, subscription);
188 }
189
190
191 /**
192 * @return the Delivery Channel
193 * @throws MessagingException
194 */
195 public DeliveryChannel getDeliveryChannel() {
196 return deliveryChannel;
197 }
198
199 /**
200 * Retrieve the default JMX Domain Name for MBeans registered in this instance of the JBI implementation.
201 *
202 * @return the JMX domain name for this instance of the JBI implementation.
203 */
204 public String getJmxDomainName() {
205 return container.getManagementContext().getJmxDomainName();
206 }
207
208 /**
209 * Formulate and return the MBean ObjectName of a custom control MBean for a JBI component.
210 *
211 * @param customName the name of the custom control.
212 * @return the JMX ObjectName of the MBean, or <code>null</code> if <code>customName</code> is invalid.
213 */
214 public ObjectName createCustomComponentMBeanName(String customName) {
215 return container.getManagementContext().createCustomComponentMBeanName(customName, componentName.getName());
216 }
217
218 /**
219 * @return the MBeanNames service
220 */
221 public MBeanNames getMBeanNames() {
222 return this;
223 }
224
225 /**
226 * @return theMBean server assocated with the JBI
227 */
228 public MBeanServer getMBeanServer() {
229 return container.getMBeanServer();
230 }
231
232 /**
233 * @return the naming context
234 */
235 public InitialContext getNamingContext() {
236 return container.getNamingContext();
237 }
238
239 /**
240 * Get the TransactionManager for this implementation. The instance returned is an implementation of the standard
241 * JTA interface. If none is available, this method returns <code>null</code>.
242 * <p>
243 * The object returned by this method is untyped, to allow this interface to be compiled in environments that do not
244 * support JTA. If not null, the object returned must be of type <code>javax.transaction.TransactionManager</code>.
245 * <p>
246 * This downcast is necessary because JBI is used in environments that do not support JTA (i.e., J2SE). Explicit use
247 * of JTA types would cause compilation failures in such environments.
248 *
249 * @return A TransactionManager instance, or <code>null</code> if none is available in the execution environment.
250 */
251 public Object getTransactionManager() {
252 return container.getTransactionManager();
253 }
254
255 /**
256 * @return the root directory path
257 */
258 public String getWorkspaceRoot() {
259 if (environment.getWorkspaceRoot() != null) {
260 return environment.getWorkspaceRoot().getAbsolutePath();
261 }
262 return null;
263 }
264
265 /**
266 * @return Returns the container.
267 */
268 public JBIContainer getContainer() {
269 return container;
270 }
271
272 /**
273 * @return Returns the ComponentEnvironment
274 */
275 public ComponentEnvironment getEnvironment() {
276 return environment;
277 }
278
279 /**
280 * Set the ComponentEnvironment
281 * @param ce
282 */
283 public void setEnvironment(ComponentEnvironment ce) {
284 this.environment = ce;
285 }
286
287 /**
288 * @param container The container to set.
289 */
290 public void setContainer(JBIContainer container) {
291 this.container = container;
292 }
293
294 /**
295 * @param deliveryChannel The deliveryChannel to set.
296 */
297 public void setDeliveryChannel(DeliveryChannel deliveryChannel) {
298 this.deliveryChannel = deliveryChannel;
299 }
300
301 /**
302 * Registers the given external endpoint with the NMR. This indicates to the NMR that the given endpoint is used as
303 * a proxy for external service consumers to access an internal service of the same service name (but a different
304 * endpoint name).
305 *
306 * @param externalEndpoint the external endpoint to be registered, must be non-null.
307 * @exception JBIException if an external endpoint with the same name is already registered, by this or another
308 * component.
309 */
310 public void registerExternalEndpoint(ServiceEndpoint externalEndpoint) throws JBIException {
311 checkActivated();
312 if (externalEndpoint == null) {
313 throw new IllegalArgumentException("externalEndpoint should be non null");
314 }
315 container.getRegistry().registerExternalEndpoint(getComponentNameSpace(), externalEndpoint);
316 }
317
318 /**
319 * Deregisters the given external endpoint with the NMR. This indicates to the NMR that the given external endpoint
320 * can no longer be used as a proxy for external service consumers to access an internal service of the same service
321 * name.
322 *
323 * @param externalEndpoint the external endpoint to be deregistered; must be non-null.
324 * @exception JBIException if the given external endpoint was not previously registered.
325 */
326 public void deregisterExternalEndpoint(ServiceEndpoint externalEndpoint) throws JBIException {
327 checkActivated();
328 container.getRegistry().deregisterExternalEndpoint(getComponentNameSpace(), externalEndpoint);
329 }
330
331 /**
332 * Resolve the given endpoint reference into a service endpoint. This is called by the component when it has an EPR
333 * that it wants to resolve into a service endpoint.
334 * <p>
335 * Note that the service endpoint returned refers to a dynamic endpoint; the endpoint will exist only as long as
336 * this component retains a strong reference to the object returned by this method. The endpoint may not be included
337 * in the list of "activated" endpoints.
338 *
339 * @param epr endpoint reference as an XML fragment; must be non-null.
340 * @return the service endpoint corresponding to the given endpoint reference; <code>null</code> if the reference
341 * cannot be resolved.
342 */
343 public ServiceEndpoint resolveEndpointReference(DocumentFragment epr) {
344 checkActivated();
345 return container.getRegistry().resolveEndpointReference(epr);
346 }
347
348 /**
349 * Get the service endpoint for the named activated endpoint, if any.
350 *
351 * @param service qualified-name of the endpoint's service; must be non-null.
352 * @param name name of the endpoint; must be non-null.
353 * @return the named endpoint, or <code>null</code> if the named endpoint is not activated.
354 */
355 public ServiceEndpoint getEndpoint(QName service, String name) {
356 checkActivated();
357 return container.getRegistry().getEndpoint(service, name);
358 }
359
360 /**
361 * Retrieve the service description metadata for the specified endpoint.
362 * <p>
363 * Note that the result can use either the WSDL 1.1 or WSDL 2.0 description language.
364 *
365 * @param endpoint endpoint reference; must be non-null.
366 * @return metadata describing endpoint, or <code>null</code> if metadata is unavailable.
367 * @exception JBIException invalid endpoint reference.
368 */
369 public Document getEndpointDescriptor(ServiceEndpoint endpoint) throws JBIException {
370 checkActivated();
371 return container.getRegistry().getEndpointDescriptor(endpoint);
372 }
373
374 /**
375 * Queries the NMR for active endpoints that implement the given interface. This will return the endpoints for all
376 * services and endpoints that implement the named interface (portType in WSDL 1.1). This method does NOT include
377 * external endpoints (those registered using {@link #registerExternalEndpoint(ServiceEndpoint)}.
378 *
379 * @param interfaceName qualified name of interface/portType that is implemented by the endpoint; if
380 * <code>null</code> then all activated endpoints in the JBI environment must be returned.
381 * @return an array of available endpoints for the specified interface name; must be non-null; may be empty.
382 */
383 public ServiceEndpoint[] getEndpoints(QName interfaceName) {
384 checkActivated();
385 return container.getRegistry().getEndpointsForInterface(interfaceName);
386 }
387
388 /**
389 * Queries the NMR for active endpoints belonging to the given service. This method does NOT include external
390 * endpoints (those registered using {@link #registerExternalEndpoint(ServiceEndpoint)}.
391 *
392 * @param serviceName qualified name of the service that the endpoints are part of; must be non-null.
393 * @return an array of available endpoints for the specified service name; must be non-null; may be empty.
394 */
395 public ServiceEndpoint[] getEndpointsForService(QName serviceName) {
396 checkActivated();
397 return container.getRegistry().getEndpointsForService(serviceName);
398 }
399
400 /**
401 * Queries the NMR for external endpoints that implement the given interface name. This methods returns only
402 * registered external endpoints (see {@link #registerExternalEndpoint(ServiceEndpoint)}.
403 *
404 * @param interfaceName qualified name of interface implemented by the endpoints; must be non-null.
405 * @return an array of available external endpoints for the specified interface name; must be non-null; may be
406 * empty.
407 */
408 public ServiceEndpoint[] getExternalEndpoints(QName interfaceName) {
409 checkActivated();
410 return container.getRegistry().getExternalEndpoints(interfaceName);
411 }
412
413 /**
414 * Queries the NMR for external endpoints that are part of the given service.
415 *
416 * @param serviceName qualified name of service that contains the endpoints; must be non-null.
417 * @return an array of available external endpoints for the specified service name; must be non-null; may be empty.
418 */
419 public ServiceEndpoint[] getExternalEndpointsForService(QName serviceName) {
420 checkActivated();
421 return container.getRegistry().getExternalEndpointsForService(serviceName);
422 }
423
424 /**
425 * Get the installation root directory path for this component.
426 * <p>
427 * This method MUST return the file path formatted for the underlying platform.
428 *
429 * @return the installation root directory path, in platform-specific form; must be non-null and non-empty.
430 */
431 public String getInstallRoot() {
432 if (environment.getInstallRoot() != null) {
433 return environment.getInstallRoot().getAbsolutePath();
434 }
435 return null;
436 }
437
438 /**
439 * Get a logger instance from JBI. Loggers supplied by JBI are guaranteed to have unique names such that they avoid
440 * name collisions with loggers from other components created using this method. The suffix parameter allows for the
441 * creation of subloggers as needed. The JBI specification says nothing about the exact names to be used, only that
442 * they must be unique across components and the JBI implementation itself.
443 *
444 * @param suffix for creating subloggers; use an empty string for the base component logger; must be non-null.
445 * @param resourceBundleName name of <code>ResourceBundle</code> to be used for localizing messages for the
446 * logger. May be <code>null</code> if none of the messages require localization. The resource, if non-null, must
447 * be loadable using the component's class loader as the initiating loader.
448 * @return a standard logger, named uniquely for this component (plus the given suffix, if applicable); must be
449 * non-null.
450 * @exception MissingResourceException if the ResourceBundleName is non-null and no corresponding resource can be
451 * found.
452 * @exception JBIException if the resourceBundleName has changed from a previous invocation by this component of
453 * this method with the same suffix.
454 */
455 public Logger getLogger(String suffix, String resourceBundleName) throws MissingResourceException, JBIException {
456 String name = suffix != null ? suffix : "";
457 name += componentName.getName();
458 return container.getLogger(name, resourceBundleName);
459 }
460
461 /**
462 * @return the ActivationSpec
463 */
464 public ActivationSpec getActivationSpec() {
465 return activationSpec;
466 }
467
468 private void checkActivated() {
469 if (!activated) {
470 throw new IllegalStateException("ComponentContext not activated");
471 }
472 }
473 }