001: /*
002: * BEGIN_HEADER - DO NOT EDIT
003: *
004: * The contents of this file are subject to the terms
005: * of the Common Development and Distribution License
006: * (the "License"). You may not use this file except
007: * in compliance with the License.
008: *
009: * You can obtain a copy of the license at
010: * https://open-esb.dev.java.net/public/CDDLv1.0.html.
011: * See the License for the specific language governing
012: * permissions and limitations under the License.
013: *
014: * When distributing Covered Code, include this CDDL
015: * HEADER in each file and include the License file at
016: * https://open-esb.dev.java.net/public/CDDLv1.0.html.
017: * If applicable add the following below this CDDL HEADER,
018: * with the fields enclosed by brackets "[]" replaced with
019: * your own identifying information: Portions Copyright
020: * [year] [name of copyright owner]
021: */
022:
023: /*
024: * @(#)ComponentContext.java
025: * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
026: *
027: * END_HEADER - DO NOT EDIT
028: */
029: package com.sun.jbi.framework;
030:
031: import com.sun.jbi.StringTranslator;
032: import com.sun.jbi.management.ManagementMessageFactory;
033: import com.sun.jbi.security.KeyStoreUtil;
034: import com.sun.jbi.wsdl2.WsdlFactory;
035: import com.sun.jbi.wsdl2.WsdlException;
036:
037: import java.io.File;
038: import java.util.logging.Logger;
039: import java.util.logging.Level;
040:
041: import javax.jbi.JBIException;
042: import javax.jbi.messaging.DeliveryChannel;
043: import javax.jbi.servicedesc.ServiceEndpoint;
044:
045: import javax.management.MBeanServer;
046: import javax.management.ObjectName;
047: import javax.naming.InitialContext;
048:
049: import javax.transaction.xa.XAResource;
050:
051: /**
052: * Contains global JBI information for a component to use during its processing.
053: * During installation/uninstallation processing, the component can access this
054: * context through the <CODE>InstallationContext</CODE>. Only the following
055: * methods can be called during this time:
056: * <UL>
057: * <LI><CODE>getMBeanNames()</CODE></LI>
058: * <LI><CODE>getMBeanServer()</CODE></LI>
059: * <LI><CODE>getNamingContext()</CODE></LI>
060: * <LI><CODE>getTransactionManager()</CODE></LI>
061: * </UL>
062: *
063: * During all other processing, the component can call any of the methods at
064: * any time.
065: *
066: * @author Sun Microsystems, Inc.
067: */
068: public class ComponentContext implements
069: com.sun.jbi.component.ComponentContext,
070: javax.jbi.management.MBeanNames {
071: /**
072: * Component instance representing this component.
073: */
074: private Component mComponent;
075:
076: /**
077: * Component name.
078: */
079: private String mComponentName;
080:
081: /**
082: * Handle to the JBI EnvironmentContext.
083: */
084: private EnvironmentContext mContext;
085:
086: /**
087: * Delivery Channel for communicating with the NMR.
088: */
089: private com.sun.jbi.messaging.DeliveryChannelImpl mDeliveryChannel;
090:
091: /**
092: * StringTranslator instance for constructing messages.
093: */
094: private StringTranslator mTranslator;
095:
096: /**
097: * Prefix for logger names for components. This is public so that the
098: * junit tests have access to it.
099: */
100: public static final String LOGGER_NAME_PREFIX = "com.sun.jbi.component.";
101:
102: /**
103: * Period for logger name construction.
104: */
105: private static final String PERIOD = ".";
106:
107: /**
108: * Constructor.
109: * @param component the Component instance representing the component for
110: * which this context is being created.
111: * @param jbiContext the JBI EnvironmentContext instance.
112: */
113: public ComponentContext(Component component,
114: EnvironmentContext jbiContext) {
115: mComponent = component;
116: mComponentName = component.getName();
117: mContext = jbiContext;
118: mTranslator = (StringTranslator) mContext
119: .getStringTranslatorFor(this );
120: }
121:
122: //
123: // ---------- Methods defined in javax.jbi.component.ComponentContext ---------
124: //
125:
126: /**
127: * Activates the named endpoint with the NMR. This makes the endpoint
128: * available to the NMR so it can send requests to the endpoint.
129: * @param serviceName the qualified name of the service exposed by the
130: * endpoint.
131: * @param endpointName the name of the endpoint to be activated.
132: * @return a reference to the activated endpoint.
133: * @throws javax.jbi.JBIException if the endpoint cannot be activated.
134: */
135: public ServiceEndpoint activateEndpoint(
136: javax.xml.namespace.QName serviceName, String endpointName)
137: throws javax.jbi.JBIException {
138: if (null != mDeliveryChannel) {
139: return mDeliveryChannel.activateEndpoint(serviceName,
140: endpointName);
141: } else {
142: throw new java.lang.IllegalStateException(mTranslator
143: .getString(LocalStringKeys.CC_NO_DC_AVAILABLE,
144: mComponentName));
145: }
146: }
147:
148: /**
149: * Deactivates the specified endpoint with the NMR. Deactivation indicates
150: * to the NMR that this component will no longer process requests sent to
151: * the named endpoint.
152: * @param endpoint reference to the endpoint to be deactivated.
153: * @throws javax.jbi.JBIException if the endpoint cannot be deactivated.
154: */
155: public void deactivateEndpoint(ServiceEndpoint endpoint)
156: throws javax.jbi.JBIException {
157: if (null != mDeliveryChannel) {
158: mDeliveryChannel.deactivateEndpoint(endpoint);
159: } else {
160: throw new java.lang.IllegalStateException(mTranslator
161: .getString(LocalStringKeys.CC_NO_DC_AVAILABLE,
162: mComponentName));
163: }
164: }
165:
166: /**
167: * Deregisters the specified external endpoint with the NMR. This indicates
168: * to the NMR that external service consumers can no longer access the
169: * internal service by this name.
170: * @param externalEndpoint the external endpoint to be deregistered.
171: * @throws javax.jbi.JBIException if the endpoint cannot be deregistered.
172: */
173: public void deregisterExternalEndpoint(
174: ServiceEndpoint externalEndpoint)
175: throws javax.jbi.JBIException {
176: if (null != mDeliveryChannel) {
177: mDeliveryChannel
178: .deregisterExternalEndpoint(externalEndpoint);
179: } else {
180: throw new java.lang.IllegalStateException(mTranslator
181: .getString(LocalStringKeys.CC_NO_DC_AVAILABLE,
182: mComponentName));
183: }
184: }
185:
186: /**
187: * Get the unique component name for the component for which this context
188: * was created.
189: * @return the component's unique name.
190: */
191: public String getComponentName() {
192: return mComponentName;
193: }
194:
195: /**
196: * Get the DeliveryChannel for the component to use to communicate with
197: * the Normalized Message Router. If the component has not yet been
198: * initialized, a DeliveryChannel cannot be created.
199: * <p>This method is visible to the component, and calls the internal
200: * framework-only method to obtain the channel.
201: * @return the delivery channel.
202: * @throws javax.jbi.messaging.MessagingException if the channel cannot
203: * be activated.
204: */
205: public DeliveryChannel getDeliveryChannel()
206: throws javax.jbi.messaging.MessagingException {
207: return getDeliveryChannel(true);
208: }
209:
210: /**
211: * Get the DeliveryChannel for the component to use to communicate with
212: * the Normalized Message Router. If it has not yet been activated, activate
213: * it and save it. If it has been closed, replace it with a new one.
214: * <p>This method is visible only to the framework.
215: * @param activateNewChannel Set to true to allow activation of a new
216: * channel if one is not already active; set to false to prevent activation
217: * of a new channel.
218: * @return the delivery channel or null if there is none.
219: * @throws javax.jbi.messaging.MessagingException if the channel cannot be
220: * activated.
221: */
222: DeliveryChannel getDeliveryChannel(boolean activateNewChannel)
223: throws javax.jbi.messaging.MessagingException {
224: if (activateNewChannel) {
225: if (null == mDeliveryChannel || mDeliveryChannel.isClosed()) {
226: mDeliveryChannel = (com.sun.jbi.messaging.DeliveryChannelImpl) mContext
227: .getNormalizedMessageService().activateChannel(
228: mComponentName, null);
229: }
230: }
231: return (DeliveryChannel) mDeliveryChannel;
232: }
233:
234: /**
235: * Get the service description for the named endpoint, if any exists.
236: * @param service the qualified name of the endpoint's service.
237: * @param name the name of the endpoint.
238: * @return the named endpoint, or <code>null</code> if the named endpoint
239: * is not active.
240: */
241: public ServiceEndpoint getEndpoint(
242: javax.xml.namespace.QName service, String name) {
243: if (null != mDeliveryChannel) {
244: return mDeliveryChannel.getEndpoint(service, name);
245: } else {
246: throw new java.lang.IllegalStateException(mTranslator
247: .getString(LocalStringKeys.CC_NO_DC_AVAILABLE,
248: mComponentName));
249: }
250: }
251:
252: /**
253: * Retrieve metadata for the specified endpoint.
254: * @param endpoint reference to the endpoint.
255: * @return the metadata describing the endpoint or <code>null</code> if
256: * metadata is unavailable.
257: * @throws javax.jbi.JBIException if the endpoint reference is invalid.
258: */
259: public org.w3c.dom.Document getEndpointDescriptor(
260: ServiceEndpoint endpoint) throws javax.jbi.JBIException {
261: if (null != mDeliveryChannel) {
262: return mDeliveryChannel.getEndpointDescriptor(endpoint);
263: } else {
264: throw new java.lang.IllegalStateException(mTranslator
265: .getString(LocalStringKeys.CC_NO_DC_AVAILABLE,
266: mComponentName));
267: }
268: }
269:
270: /**
271: * Queries the NMR for registered endpoints that implement the specified
272: * interface. This will return the endpoints for all services and endpoints
273: * that implement the named interface.
274: * @param serviceName the qualified name of the interface/portType that
275: * is implemented by the endpoint.
276: * @return array of available endpoints for the specified interface name;
277: * can be empty if none exist.
278: */
279: public ServiceEndpoint[] getEndpointsForService(
280: javax.xml.namespace.QName serviceName) {
281: if (null != mDeliveryChannel) {
282: return mDeliveryChannel.getEndpointsForService(serviceName);
283: } else {
284: throw new java.lang.IllegalStateException(mTranslator
285: .getString(LocalStringKeys.CC_NO_DC_AVAILABLE,
286: mComponentName));
287: }
288: }
289:
290: /**
291: * Queries the NMR for external endpoints that implement the specified
292: * interface name.
293: * @param interfaceName the qualified name of the interface/portType that
294: * is implemented by the endpoints.
295: * @return array of available external endpoints for the specified interface
296: * name; can be empty if none exist.
297: */
298: public ServiceEndpoint[] getExternalEndpoints(
299: javax.xml.namespace.QName interfaceName) {
300: if (null != mDeliveryChannel) {
301: return mDeliveryChannel.getExternalEndpoints(interfaceName);
302: } else {
303: throw new java.lang.IllegalStateException(mTranslator
304: .getString(LocalStringKeys.CC_NO_DC_AVAILABLE,
305: mComponentName));
306: }
307: }
308:
309: /**
310: * Queries the NMR for active endpoints that implement the given interface.
311: * This will return the endpoints for all services and endpoints that
312: * implement the named interface (portType in WSDL 1.1). This method does
313: * NOT include external endpoints (those registered using
314: * registerExternalEndpoint(ServiceEndpoint)).
315: * @param interfaceName qualified name of interface/portType that is
316: * implemented by the endpoint
317: * @return ServiceEndpoint[] list of available endpoints for the specified
318: * interface name; potentially zero-length.
319: */
320: public ServiceEndpoint[] getEndpoints(
321: javax.xml.namespace.QName interfaceName) {
322: if (null != mDeliveryChannel) {
323: return mDeliveryChannel.getEndpoints(interfaceName);
324: } else {
325: throw new java.lang.IllegalStateException(mTranslator
326: .getString(LocalStringKeys.CC_NO_DC_AVAILABLE,
327: mComponentName));
328: }
329: }
330:
331: /**
332: * Queries the NMR for external endpoints that are part of the specified
333: * service.
334: * @param serviceName the qualified name of the service that contains the
335: * endpoints.
336: * @return array of available external endpoints for the specified service
337: * name; can be empty if none exist.
338: */
339: public ServiceEndpoint[] getExternalEndpointsForService(
340: javax.xml.namespace.QName serviceName) {
341: if (null != mDeliveryChannel) {
342: return mDeliveryChannel.getEndpointsForService(serviceName);
343: } else {
344: throw new java.lang.IllegalStateException(mTranslator
345: .getString(LocalStringKeys.CC_NO_DC_AVAILABLE,
346: mComponentName));
347: }
348: }
349:
350: /**
351: * Get the installation root directory for this component.
352: * @return the installation root directory path.
353: */
354: public String getInstallRoot() {
355: if (File.separator.equals("/")) {
356: return mComponent.getInstallRoot();
357: } else {
358: return mComponent.getInstallRoot().replace('/',
359: File.separatorChar);
360: }
361: }
362:
363: /**
364: * Get a logger instance from JBI. Loggers supplied by JBI are guaranteed
365: * to have unique names such that they avoid name collisions with loggers
366: * from other components created using this method. The suffix parameter
367: * allows for the creation of subloggers as needed. The JBI specification
368: * says nothing about the exact names to be used, only that they must be
369: * unique across components and the JBI implementation itself.
370: *
371: * In addition to creating the logger instance, this implementation also
372: * adds the logger instance to a list used by the ComponentLoggerMBean to
373: * display and control of the logger level via the administrative tools.
374: *
375: * In this implementation, the main logger always has its logger name set
376: * to the component name, and all sub-loggers are prefixed with the
377: * component name. This provides the ability to set the log levels for
378: * all of a component's loggers by setting the main logger's level.
379: * However, it is important to note that if the log level is explicitly
380: * set for a sub-logger, that level stays in effect regardless of the main
381: * logger's level, until the sub-logger's level is explicitly changed.
382: *
383: * If a component does not call this method to create a main logger before
384: * calling it to create a sub-logger, the main logger is created
385: * automatically before the sub-logger is created.
386: *
387: * @param suffix logger name suffix for creating subloggers; empty string
388: * for base logger.
389: * @param resourceBundleName name of <code>ResourceBundle</code> to be used
390: * for localizing messages for the logger. May be <code>null</code> if none
391: * of the messages require localization. The resource, if non-null, must be
392: * loadable using the component's class loader as the initiating loader.
393: * @return a standard logger, named uniquely for this component (plus the
394: * given suffix, if applicable)
395: * @throws java.util.MissingResourceException if the resourceBundleName is
396: * non-null and no corresponding resource can be found.
397: * @throws javax.jbi.JBIException if any other error occurs.
398: */
399: public Logger getLogger(String suffix, String resourceBundleName)
400: throws java.util.MissingResourceException,
401: javax.jbi.JBIException {
402: Logger log = null;
403: String logName = null;
404:
405: // Per the JBI specification, the suffix argument cannot be null.
406:
407: if (null == suffix) {
408: throw new java.lang.IllegalArgumentException(mTranslator
409: .getString(LocalStringKeys.CC_LOGGER_NULL_SUFFIX));
410: }
411:
412: // Construct the logger name using the component name and the caller-
413: // provided suffix.
414:
415: if (0 == suffix.length()) // request for a main logger
416: {
417: logName = mComponentName;
418: } else // request for a sub-logger
419: {
420: // If the caller-provided value does not start with a period, add
421: // one.
422:
423: if (suffix.startsWith(PERIOD)) {
424: logName = mComponentName + suffix;
425: } else {
426: logName = mComponentName + PERIOD + suffix;
427: }
428: }
429:
430: // Now obtain the requested logger, using the caller-supplied resource
431: // bundle name if it is not null.
432:
433: if (null != resourceBundleName) {
434: try {
435: log = Logger.getLogger(logName, resourceBundleName);
436: } catch (java.util.MissingResourceException mrEx) {
437: mContext
438: .getLogger()
439: .log(
440: Level.WARNING,
441: mTranslator
442: .getString(
443: LocalStringKeys.CC_LOGGER_MISSING_RESOURCE,
444: logName,
445: resourceBundleName),
446: mrEx);
447: throw mrEx;
448: } catch (IllegalArgumentException iaEx) {
449: String msg = mTranslator.getString(
450: LocalStringKeys.CC_LOGGER_DIFFERENT_RESOURCE,
451: logName, resourceBundleName, Logger.getLogger(
452: logName).getResourceBundleName());
453: mContext.getLogger().log(Level.WARNING, msg, iaEx);
454: throw new javax.jbi.JBIException(msg, iaEx);
455: }
456: } else {
457: log = Logger.getLogger(logName);
458: }
459:
460: // If this is the main logger for the component, set its parent
461: // to the global JBI logger.
462:
463: if (logName.equals(mComponentName)) {
464: log.setParent(mContext.getJbiLogger());
465: }
466:
467: // If this is the first request for this logger, add it to the logger
468: // table for the component.
469:
470: ComponentLogger logMBean = mComponent.getLoggerInstance();
471:
472: if (null != logMBean && !logMBean.isLoggerRegistered(logName)) {
473: // Create a reasonable display name for the logger. This uses the
474: // last level of the name, which for the main logger is the same
475: // as the component name.
476:
477: String displayName;
478: int lastDot = logName.lastIndexOf(".");
479: if (-1 < lastDot) {
480: displayName = logName.substring(lastDot + 1);
481: } else {
482: displayName = logName;
483: }
484:
485: // Add the logger to the table and restore its level setting.
486:
487: logMBean.addLogger(log, displayName);
488: }
489: return log;
490: }
491:
492: /**
493: * Get the JMX MBean naming service handle. This method returns this
494: * instance, as it has the methods defined by the public API. These
495: * methods in turn use the IPI implementation to perform the operations.
496: * @return the JMX MBean naming service handle.
497: */
498: public javax.jbi.management.MBeanNames getMBeanNames() {
499: return this ;
500: }
501:
502: /**
503: * Get the JMX MBean server with which all MBeans are registered.
504: * This method delegates to the JBI EnvironmentContext method.
505: * @return the main JMX MBean server.
506: */
507: public MBeanServer getMBeanServer() {
508: return mContext.getMBeanServer();
509: }
510:
511: /**
512: * Get the JNDI naming context currently in effect.
513: * This method delegates to the JBI EnvironmentContext method.
514: * @return the JNDI naming context.
515: */
516: public InitialContext getNamingContext() {
517: return mContext.getNamingContext();
518: }
519:
520: /**
521: * Get the TransactionManager for the current implementation.
522: * This method delegates to the JBI EnvironmentContext method.
523: * @return the TransactionManager instance.
524: */
525: public Object getTransactionManager() {
526: return (Object) mContext.getTransactionManager();
527: }
528:
529: /**
530: * Get the workspace root directory for this component.
531: * @return the component's workspace directory path.
532: */
533: public String getWorkspaceRoot() {
534: if (File.separator.equals("/")) {
535: return mComponent.getWorkspaceRoot();
536: } else {
537: return mComponent.getWorkspaceRoot().replace('/',
538: File.separatorChar);
539: }
540: }
541:
542: /**
543: * Registers the specified external endpoint with the NMR. This indicates
544: * to the NMR that the specified endpoint is used as a proxy for external
545: * service consumers to access an internal service by the same name.
546: * @param externalEndpoint the external endpoint to be registered.
547: * @throws javax.jbi.JBIException if the endpoint is already registered.
548: */
549: public void registerExternalEndpoint(
550: ServiceEndpoint externalEndpoint)
551: throws javax.jbi.JBIException {
552: if (null != mDeliveryChannel) {
553: mDeliveryChannel.registerExternalEndpoint(externalEndpoint);
554: } else {
555: throw new java.lang.IllegalStateException(mTranslator
556: .getString(LocalStringKeys.CC_NO_DC_AVAILABLE,
557: mComponentName));
558: }
559: }
560:
561: /**
562: * Resolves the specified endpoint reference into a service endpoint. This
563: * is called by the component when it has an endpoint reference that it
564: * needs to resolve into a service endpoint.
565: * @param endpointReference the endpoint reference as an XML fragment.
566: * @return the service endpoint corresponding to the specified endpoint
567: * reference, or <code>null</code> if the reference cannot be resolved.
568: */
569: public ServiceEndpoint resolveEndpointReference(
570: org.w3c.dom.DocumentFragment endpointReference) {
571: if (null != mDeliveryChannel) {
572: return mDeliveryChannel
573: .resolveEndpointReference(endpointReference);
574: } else {
575: throw new java.lang.IllegalStateException(mTranslator
576: .getString(LocalStringKeys.CC_NO_DC_AVAILABLE,
577: mComponentName));
578: }
579: }
580:
581: //
582: // -------- Methods defined in com.sun.jbi.component.ComponentContext ---------
583: //
584:
585: /**
586: * Get the management message factory which enables JBI components
587: * to construct status and exception messages.
588: * This method delegates to the JBI EnvironmentContext method.
589: * @return the management message factory handle.
590: */
591: public ManagementMessageFactory getManagementMessageFactory() {
592: return mContext.getManagementMessageFactory();
593: }
594:
595: /**
596: * Get a StringTranslator for use in constructing messages using
597: * resource bundles.
598: * This method delegates to the JBI EnvironmentContext method.
599: * @param packageName the name of the package that contains the
600: * resource bundle to be used by the StringTranslator.
601: * @return the StringTranslator for the specified package name.
602: */
603: public StringTranslator getStringTranslator(String packageName) {
604: return mContext
605: .getStringTranslator(packageName, mComponentName);
606: }
607:
608: /**
609: * Get a StringTranslator for use in constructing messages using
610: * resource bundles.
611: * This method delegates to the JBI EnvironmentContext method.
612: * @param object an object that is in the same package as the
613: * resource bundle to be used by the StringTranslator.
614: * @return the StringTranslator for the specified package.
615: */
616: public StringTranslator getStringTranslatorFor(Object object) {
617: return mContext.getStringTranslator(object.getClass()
618: .getPackage().getName(), mComponentName);
619: }
620:
621: /**
622: * Get a copy of the WSDL factory. This needs to be done before
623: * any reading, writing, or manipulation of WSDL documents can
624: * be performed using the WSDL API.
625: *
626: * @return An instance of the WSDL factory.
627: * @exception WsdlException If the factory cannot be instantiated.
628: */
629: public WsdlFactory getWsdlFactory() throws WsdlException {
630: return mContext.getWsdlFactory();
631: }
632:
633: /**
634: * Used by a component to register an internal XAResource with the JBI
635: * runtime.
636: * @param resource to be registered
637: * @exception JBIException if something is wrong with the XAResource.
638: */
639: public void registerXAResource(XAResource resource)
640: throws JBIException {
641: ((com.sun.jbi.messaging.DeliveryChannelImpl) getDeliveryChannel(true))
642: .registerXAResource(resource);
643: }
644:
645: /**
646: * Returns a KeyStoreUtil object that allows components to create,
647: * read, update, and delete keys
648: *
649: * @return An instance of a KeyStoreUtil
650: */
651: public KeyStoreUtil getKeyStoreUtil() {
652: return mContext.getPlatformContext().getKeyStoreUtil();
653: }
654:
655: //
656: // ------------ Methods defined in javax.jbi.management.MBeanNames ------------
657: //
658:
659: /**
660: * Formulate and return the MBean ObjectName of a custom control MBean for
661: * a JBI component.
662: *
663: * @param customName the name of the custom control.
664: * @return the JMX ObjectName of the MBean, or <code>null</code> if
665: * <code>customName</code> is invalid.
666: */
667: public ObjectName createCustomComponentMBeanName(String customName) {
668: if (mComponent.isBinding()) {
669: return mContext.getMBeanNames().getCustomBindingMBeanName(
670: customName, mComponentName);
671: } else {
672: return mContext.getMBeanNames().getCustomEngineMBeanName(
673: customName, mComponentName);
674: }
675: }
676:
677: /**
678: * Retrieve the default JMX Domain Name for MBeans registered in this
679: * instance of the JBI implementation.
680: *
681: * @return the JMX domain name for this instance of the JBI implementation.
682: */
683: public String getJmxDomainName() {
684: return mContext.getMBeanNames().getJmxDomainName();
685: }
686:
687: }
|