0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017: package org.apache.servicemix.jbi.container;
0018:
0019: import java.io.File;
0020: import java.util.Calendar;
0021: import java.util.Collection;
0022: import java.util.EventListener;
0023: import java.util.MissingResourceException;
0024: import java.util.concurrent.atomic.AtomicBoolean;
0025: import java.util.logging.Logger;
0026:
0027: import javax.jbi.JBIException;
0028: import javax.jbi.component.Component;
0029: import javax.jbi.component.ComponentLifeCycle;
0030: import javax.jbi.component.ServiceUnitManager;
0031: import javax.jbi.management.DeploymentException;
0032: import javax.jbi.management.LifeCycleMBean;
0033: import javax.jbi.messaging.ExchangeStatus;
0034: import javax.jbi.messaging.MessageExchange;
0035: import javax.jbi.messaging.MessagingException;
0036: import javax.jbi.servicedesc.ServiceEndpoint;
0037: import javax.management.JMException;
0038: import javax.management.MBeanServer;
0039: import javax.management.ObjectName;
0040: import javax.naming.InitialContext;
0041: import javax.naming.NamingException;
0042: import javax.swing.event.EventListenerList;
0043: import javax.transaction.TransactionManager;
0044: import javax.xml.namespace.QName;
0045:
0046: import org.w3c.dom.DocumentFragment;
0047:
0048: import org.apache.commons.logging.Log;
0049: import org.apache.commons.logging.LogFactory;
0050: import org.apache.servicemix.JbiConstants;
0051: import org.apache.servicemix.MessageExchangeListener;
0052: import org.apache.servicemix.components.util.ComponentAdaptor;
0053: import org.apache.servicemix.components.util.ComponentAdaptorMEListener;
0054: import org.apache.servicemix.components.util.ComponentSupport;
0055: import org.apache.servicemix.components.util.PojoLifecycleAdaptor;
0056: import org.apache.servicemix.components.util.PojoSupport;
0057: import org.apache.servicemix.executors.ExecutorFactory;
0058: import org.apache.servicemix.executors.impl.ExecutorFactoryImpl;
0059: import org.apache.servicemix.id.IdGenerator;
0060: import org.apache.servicemix.jbi.event.ComponentListener;
0061: import org.apache.servicemix.jbi.event.ContainerAware;
0062: import org.apache.servicemix.jbi.event.DeploymentListener;
0063: import org.apache.servicemix.jbi.event.EndpointListener;
0064: import org.apache.servicemix.jbi.event.ExchangeEvent;
0065: import org.apache.servicemix.jbi.event.ExchangeListener;
0066: import org.apache.servicemix.jbi.event.ServiceAssemblyListener;
0067: import org.apache.servicemix.jbi.event.ServiceUnitListener;
0068: import org.apache.servicemix.jbi.framework.AdminCommandsService;
0069: import org.apache.servicemix.jbi.framework.AutoDeploymentService;
0070: import org.apache.servicemix.jbi.framework.ClientFactory;
0071: import org.apache.servicemix.jbi.framework.ComponentContextImpl;
0072: import org.apache.servicemix.jbi.framework.ComponentMBeanImpl;
0073: import org.apache.servicemix.jbi.framework.ComponentNameSpace;
0074: import org.apache.servicemix.jbi.framework.DeploymentService;
0075: import org.apache.servicemix.jbi.framework.InstallationService;
0076: import org.apache.servicemix.jbi.framework.Registry;
0077: import org.apache.servicemix.jbi.management.BaseLifeCycle;
0078: import org.apache.servicemix.jbi.management.BaseSystemService;
0079: import org.apache.servicemix.jbi.management.ManagementContext;
0080: import org.apache.servicemix.jbi.messaging.MessageExchangeImpl;
0081: import org.apache.servicemix.jbi.nmr.Broker;
0082: import org.apache.servicemix.jbi.nmr.DefaultBroker;
0083: import org.apache.servicemix.jbi.nmr.flow.Flow;
0084:
0085: /**
0086: * The main container
0087: *
0088: * @version $Revision: 619345 $
0089: */
0090: public class JBIContainer extends BaseLifeCycle {
0091: /**
0092: * Default Container name - must be unique if used in a cluster
0093: */
0094: public static final String DEFAULT_NAME = "ServiceMix";
0095:
0096: private static final Log LOG = LogFactory
0097: .getLog(JBIContainer.class);
0098:
0099: protected Broker broker = new DefaultBroker();
0100: protected ServiceUnitManager serviceManager;
0101: protected ManagementContext managementContext = new ManagementContext();
0102: protected EnvironmentContext environmentContext = new EnvironmentContext();
0103: protected InstallationService installationService = new InstallationService();
0104: protected DeploymentService deploymentService = new DeploymentService();
0105: protected AutoDeploymentService autoDeployService = new AutoDeploymentService();
0106: protected AdminCommandsService adminCommandsService = new AdminCommandsService();
0107: protected BaseSystemService[] services;
0108: protected ClientFactory clientFactory = new ClientFactory();
0109: protected Registry registry = new Registry();
0110: protected boolean autoEnlistInTransaction;
0111: protected boolean persistent;
0112: protected boolean embedded;
0113: protected boolean notifyStatistics;
0114: protected EventListenerList listeners = new EventListenerList();
0115: protected EventListener[] configuredListeners;
0116: protected boolean useShutdownHook = true;
0117: protected transient Thread shutdownHook;
0118: protected ExecutorFactory executorFactory;
0119: private String name = DEFAULT_NAME;
0120: private InitialContext namingContext;
0121: private MBeanServer mbeanServer;
0122: private TransactionManager transactionManager;
0123: private String rootDir;
0124: private String generatedRootDirPrefix = "target/rootDirs/rootDir";
0125: private boolean generateRootDir;
0126: private AtomicBoolean started = new AtomicBoolean(false);
0127: private AtomicBoolean containerInitialized = new AtomicBoolean(
0128: false);
0129: private IdGenerator idGenerator = new IdGenerator();
0130:
0131: /**
0132: * Default Constructor
0133: */
0134: public JBIContainer() {
0135: }
0136:
0137: /**
0138: * @return Returns the unique nam for the Container
0139: */
0140: public String getName() {
0141: return name;
0142: }
0143:
0144: /**
0145: * @param name The name to set (must be unique within a cluster)
0146: */
0147: public void setName(String name) {
0148: this .name = name;
0149: }
0150:
0151: /**
0152: * Get the description
0153: *
0154: * @return descrption
0155: */
0156: public String getDescription() {
0157: return "ServiceMix JBI Container";
0158: }
0159:
0160: /**
0161: * @return Returns the flowName.
0162: */
0163: public String getFlowName() {
0164: String flowNames = getDefaultBroker().getFlowNames();
0165: if (flowNames == null) {
0166: return null;
0167: }
0168: String[] flows = flowNames.split(",");
0169: if (flows.length > 1) {
0170: throw new IllegalStateException(
0171: "Multiple flows have been defined");
0172: }
0173: return flows[0];
0174: }
0175:
0176: /**
0177: * @param flowName The flow to set.
0178: */
0179: public void setFlowName(String flowName) {
0180: getDefaultBroker().setFlowNames(flowName);
0181: }
0182:
0183: /**
0184: * @return Returns the flowNames.
0185: */
0186: public String getFlowNames() {
0187: return getDefaultBroker().getFlowNames();
0188: }
0189:
0190: /**
0191: * @param flowNames The flows to set.
0192: */
0193: public void setFlowNames(String flowNames) {
0194: getDefaultBroker().setFlowNames(flowNames);
0195: }
0196:
0197: /**
0198: * @return the subscriptionFlowName
0199: */
0200: public String getSubscriptionFlowName() {
0201: return getDefaultBroker().getSubscriptionFlowName();
0202: }
0203:
0204: /**
0205: * Set the subscription flow name
0206: * @param subscriptionFlowName
0207: */
0208: public void setSubscriptionFlowName(String subscriptionFlowName) {
0209: getDefaultBroker()
0210: .setSubscriptionFlowName(subscriptionFlowName);
0211: }
0212:
0213: /**
0214: * Set the broker message flow
0215: *
0216: * @param flow
0217: */
0218: public void setFlow(Flow flow) {
0219: getDefaultBroker().setFlows(new Flow[] { flow });
0220: }
0221:
0222: /**
0223: * @return the broker message Flow
0224: */
0225: public Flow getFlow() {
0226: Flow[] flows = getDefaultBroker().getFlows();
0227: if (flows == null || flows.length == 0) {
0228: return null;
0229: } else if (flows.length > 1) {
0230: throw new IllegalStateException(
0231: "Multiple flows have been defined");
0232: } else {
0233: return flows[0];
0234: }
0235: }
0236:
0237: /**
0238: * Set the broker message flows
0239: *
0240: * @param flow
0241: */
0242: public void setFlows(Flow[] flows) {
0243: getDefaultBroker().setFlows(flows);
0244: }
0245:
0246: /**
0247: * @return the broker message Flows
0248: */
0249: public Flow[] getFlows() {
0250: return getDefaultBroker().getFlows();
0251: }
0252:
0253: public boolean isUseShutdownHook() {
0254: return useShutdownHook;
0255: }
0256:
0257: /**
0258: * Sets whether or not we should use a shutdown handler to close down the
0259: * broker cleanly if the JVM is terminated. It is recommended you leave this
0260: * enabled.
0261: */
0262: public void setUseShutdownHook(boolean useShutdownHook) {
0263: this .useShutdownHook = useShutdownHook;
0264: }
0265:
0266: /**
0267: * @return the services
0268: */
0269: public BaseSystemService[] getServices() {
0270: return services;
0271: }
0272:
0273: /**
0274: * @param services the services to set
0275: */
0276: public void setServices(BaseSystemService[] services) {
0277: this .services = services;
0278: }
0279:
0280: /**
0281: * Get the ManagementContext
0282: *
0283: * @return the ManagementContext
0284: */
0285: public ManagementContext getManagementContext() {
0286: return managementContext;
0287: }
0288:
0289: /**
0290: * @return Return the EnvironmentContext
0291: */
0292: public EnvironmentContext getEnvironmentContext() {
0293: return environmentContext;
0294: }
0295:
0296: /**
0297: * @return Return the registry
0298: */
0299: public Registry getRegistry() {
0300: return registry;
0301: }
0302:
0303: /**
0304: * Return the DefaultBroker instance
0305: */
0306: public DefaultBroker getDefaultBroker() {
0307: if (!(broker instanceof DefaultBroker)) {
0308: throw new IllegalStateException(
0309: "Broker is not a DefaultBroker");
0310: }
0311: return (DefaultBroker) broker;
0312: }
0313:
0314: /**
0315: * @return Return the NMR broker
0316: */
0317: public Broker getBroker() {
0318: return broker;
0319: }
0320:
0321: /**
0322: * Set the Broker to use
0323: */
0324: public void setBroker(Broker broker) {
0325: this .broker = broker;
0326: }
0327:
0328: /**
0329: * @return true if creates own MBeanServer if none supplied
0330: */
0331: public boolean isCreateMBeanServer() {
0332: return managementContext.isCreateMBeanServer();
0333: }
0334:
0335: /**
0336: * Set the flag to create own MBeanServer if none supplied
0337: *
0338: * @param enableJMX
0339: */
0340: public void setCreateMBeanServer(boolean enableJMX) {
0341: managementContext.setCreateMBeanServer(enableJMX);
0342: }
0343:
0344: /**
0345: * @return Returns the useMBeanServer.
0346: */
0347: public boolean isUseMBeanServer() {
0348: return managementContext.isUseMBeanServer();
0349: }
0350:
0351: /**
0352: * @param useMBeanServer The useMBeanServer to set.
0353: */
0354: public void setUseMBeanServer(boolean useMBeanServer) {
0355: managementContext.setUseMBeanServer(useMBeanServer);
0356: }
0357:
0358: /**
0359: * @return Returns the useMBeanServer.
0360: */
0361: public boolean isCreateJmxConnector() {
0362: return managementContext.isCreateJmxConnector();
0363: }
0364:
0365: /**
0366: * @param createJmxConnector The createJmxConnector to set.
0367: */
0368: public void setCreateJmxConnector(boolean createJmxConnector) {
0369: managementContext.setCreateJmxConnector(createJmxConnector);
0370: }
0371:
0372: /**
0373: * @return Returns the monitorInstallationDirectory.
0374: */
0375: public boolean isMonitorInstallationDirectory() {
0376: return autoDeployService.isMonitorInstallationDirectory();
0377: }
0378:
0379: /**
0380: * @param monitorInstallationDirectory The monitorInstallationDirectory to set.
0381: */
0382: public void setMonitorInstallationDirectory(
0383: boolean monitorInstallationDirectory) {
0384: autoDeployService
0385: .setMonitorInstallationDirectory(monitorInstallationDirectory);
0386: }
0387:
0388: /**
0389: * @return Returns the monitorDeploymentDirectory.
0390: */
0391: public boolean isMonitorDeploymentDirectory() {
0392: return autoDeployService.isMonitorDeploymentDirectory();
0393: }
0394:
0395: /**
0396: * @param monitorDeploymentDirectory The monitorDeploymentDirectory to set.
0397: */
0398: public void setMonitorDeploymentDirectory(
0399: boolean monitorDeploymentDirectory) {
0400: autoDeployService
0401: .setMonitorDeploymentDirectory(monitorDeploymentDirectory);
0402: }
0403:
0404: /**
0405: * @return Returns the installationDir.
0406: */
0407: public String getInstallationDirPath() {
0408: File dir = environmentContext.getInstallationDir();
0409: return dir != null ? dir.getAbsolutePath() : "";
0410: }
0411:
0412: /**
0413: * Set the installationDir - rge default location is root/<container name>/installation
0414: *
0415: * @param installationDir
0416: */
0417: public void setInstallationDirPath(String installationDir) {
0418: if (installationDir != null && installationDir.length() > 0) {
0419: environmentContext.setInstallationDir(new File(
0420: installationDir));
0421: }
0422: }
0423:
0424: /**
0425: * @return Returns the deploymentDir.
0426: */
0427: public String getDeploymentDirPath() {
0428: File dir = environmentContext.getDeploymentDir();
0429: return dir != null ? dir.getAbsolutePath() : "";
0430: }
0431:
0432: /**
0433: * @param deploymentDir The deploymentDir to set.
0434: */
0435: public void setDeploymentDirPath(String deploymentDir) {
0436: if (deploymentDir != null && deploymentDir.length() > 0) {
0437: environmentContext
0438: .setDeploymentDir(new File(deploymentDir));
0439: }
0440: }
0441:
0442: /**
0443: * @return Returns the monitorInterval (in secs).
0444: */
0445: public int getMonitorInterval() {
0446: return autoDeployService.getMonitorInterval();
0447: }
0448:
0449: /**
0450: * @param monitorInterval The monitorInterval to set (in secs).
0451: */
0452: public void setMonitorInterval(int monitorInterval) {
0453: autoDeployService.setMonitorInterval(monitorInterval);
0454: }
0455:
0456: /**
0457: * @return the deploymentExtensions
0458: */
0459: public String getDeploymentExtensions() {
0460: return autoDeployService.getExtensions();
0461: }
0462:
0463: /**
0464: * @param deploymentExtensions the deploymentExtensions to set
0465: */
0466: public void setDeploymentExtensions(String deploymentExtensions) {
0467: autoDeployService.setExtensions(deploymentExtensions);
0468: }
0469:
0470: /**
0471: * Install an component from a url
0472: *
0473: * @param url
0474: * @throws DeploymentException
0475: */
0476: public void installArchive(String url) throws DeploymentException {
0477: installationService.install(url, null, true);
0478: }
0479:
0480: /**
0481: * load an archive from an external location.
0482: * The archive can be a Component, Service Assembly or Shared Library.
0483: * @param location - can either be a url or filename (if relative - must be relative to the container)
0484: * @param autoStart - if true will start the component/service assembly
0485: * @throws DeploymentException
0486: */
0487: public void updateExternalArchive(String location, boolean autoStart)
0488: throws DeploymentException {
0489: autoDeployService.updateExternalArchive(location, autoStart);
0490: }
0491:
0492: /**
0493: * load an archive from an external location and starts it
0494: * The archive can be a Component, Service Assembly or Shared Library.
0495: * @param location - can either be a url or filename (if relative - must be relative to the container)
0496: * @throws DeploymentException
0497: */
0498: public void updateExternalArchive(String location)
0499: throws DeploymentException {
0500: updateExternalArchive(location, true);
0501: }
0502:
0503: /**
0504: * @return Returns the deploymentService.
0505: */
0506: public DeploymentService getDeploymentService() {
0507: return deploymentService;
0508: }
0509:
0510: /**
0511: * @return Returns the installationService.
0512: */
0513: public InstallationService getInstallationService() {
0514: return installationService;
0515: }
0516:
0517: /**
0518: * @return the AutomDeploymentService
0519: */
0520: public AutoDeploymentService getAutoDeploymentService() {
0521: return autoDeployService;
0522: }
0523:
0524: /**
0525: *
0526: * @return the AdminCommandsService
0527: */
0528: public AdminCommandsService getAdminCommandsService() {
0529: return adminCommandsService;
0530: }
0531:
0532: public ClientFactory getClientFactory() {
0533: return clientFactory;
0534: }
0535:
0536: public String getGeneratedRootDirPrefix() {
0537: return generatedRootDirPrefix;
0538: }
0539:
0540: /**
0541: * Sets the prefix used when auto-creating a rootDir property value
0542: * which is useful for integration testing inside JUnit test cases
0543: * letting each test case create its own empty servicemix install
0544: *
0545: * @param generatedRootDirPrefix the prefix used to auto-create the
0546: * rootDir
0547: * @see #setRootDir(String)
0548: * @see #setGeneratedRootDirPrefix(String)
0549: */
0550: public void setGeneratedRootDirPrefix(String generatedRootDirPrefix) {
0551: this .generatedRootDirPrefix = generatedRootDirPrefix;
0552: }
0553:
0554: public boolean isGenerateRootDir() {
0555: return generateRootDir;
0556: }
0557:
0558: /**
0559: * Creates an auto-generated rootDir which is useful for integration testing
0560: * in JUnit test cases allowing installations of deployments inside an empty
0561: * installation of ServiceMix
0562: *
0563: * @param generateRootDir if true this will enable the auto-generation of the rootDir
0564: * if the rootDir property is not configured
0565: *
0566: * @see #setRootDir(String)
0567: * @see #setGeneratedRootDirPrefix(String)
0568: */
0569: public void setGenerateRootDir(boolean generateRootDir) {
0570: this .generateRootDir = generateRootDir;
0571: }
0572:
0573: /**
0574: * light weight initialization - default values for mbeanServer, TransactionManager etc are null
0575: *
0576: * @throws JBIException
0577: */
0578: public void init() throws JBIException {
0579: if (containerInitialized.compareAndSet(false, true)) {
0580: LOG.info("ServiceMix " + EnvironmentContext.getVersion()
0581: + " JBI Container (" + getName() + ") is starting");
0582: LOG
0583: .info("For help or more information please see: http://servicemix.apache.org/");
0584: addShutdownHook();
0585: if (this .executorFactory == null) {
0586: this .executorFactory = createExecutorFactory();
0587: }
0588: if (this .namingContext == null) {
0589: try {
0590: this .namingContext = new InitialContext();
0591: } catch (NamingException e) {
0592: // Log a warning, with exception only in debug
0593: if (LOG.isDebugEnabled()) {
0594: LOG.warn("Failed to set InitialContext", e);
0595: } else {
0596: LOG.warn("Failed to set InitialContext");
0597: }
0598: }
0599: }
0600: managementContext.init(this , getMBeanServer());
0601: mbeanServer = this .managementContext.getMBeanServer(); // just in case ManagementContext creates it
0602: environmentContext.init(this , getRootDir());
0603: clientFactory.init(this );
0604: if (services != null) {
0605: for (int i = 0; i < services.length; i++) {
0606: services[i].init(this );
0607: }
0608: }
0609: registry.init(this );
0610: broker.init(this );
0611: installationService.init(this );
0612: deploymentService.init(this );
0613: autoDeployService.init(this );
0614: adminCommandsService.init(this );
0615:
0616: // register self with the ManagementContext
0617: try {
0618: managementContext.registerMBean(ManagementContext
0619: .getContainerObjectName(managementContext
0620: .getJmxDomainName(), getName()), this ,
0621: LifeCycleMBean.class);
0622: } catch (JMException e) {
0623: throw new JBIException(e);
0624: }
0625:
0626: // Initialize listeners after the whole container has been initialized
0627: // so that they can register themselves as JMX mbeans for example
0628: if (configuredListeners != null) {
0629: for (int i = 0; i < configuredListeners.length; i++) {
0630: EventListener listener = configuredListeners[i];
0631: addListener(listener);
0632: }
0633: }
0634: }
0635: }
0636:
0637: /**
0638: * start processing
0639: *
0640: * @throws JBIException
0641: */
0642: public void start() throws JBIException {
0643: checkInitialized();
0644: if (started.compareAndSet(false, true)) {
0645: managementContext.start();
0646: environmentContext.start();
0647: clientFactory.start();
0648: if (services != null) {
0649: for (int i = 0; i < services.length; i++) {
0650: services[i].start();
0651: }
0652: }
0653: broker.start();
0654: registry.start();
0655: installationService.start();
0656: deploymentService.start();
0657: autoDeployService.start();
0658: adminCommandsService.start();
0659: super .start();
0660: LOG.info("ServiceMix JBI Container (" + getName()
0661: + ") started");
0662: }
0663: }
0664:
0665: /**
0666: * stop the container from processing
0667: *
0668: * @throws JBIException
0669: */
0670: public void stop() throws JBIException {
0671: checkInitialized();
0672: if (started.compareAndSet(true, false)) {
0673: LOG.info("ServiceMix JBI Container (" + getName()
0674: + ") stopping");
0675: adminCommandsService.stop();
0676: autoDeployService.stop();
0677: deploymentService.stop();
0678: installationService.stop();
0679: registry.stop();
0680: broker.stop();
0681: if (services != null) {
0682: for (int i = services.length - 1; i >= 0; i--) {
0683: services[i].stop();
0684: }
0685: }
0686: clientFactory.stop();
0687: environmentContext.stop();
0688: managementContext.stop();
0689: super .stop();
0690: }
0691: }
0692:
0693: /**
0694: * After a shutdown the container will require an init before a start ...
0695: *
0696: * @throws JBIException
0697: */
0698: public void shutDown() throws JBIException {
0699: if (containerInitialized.compareAndSet(true, false)) {
0700: LOG.info("Shutting down ServiceMix JBI Container ("
0701: + getName() + ") stopped");
0702: removeShutdownHook();
0703: adminCommandsService.shutDown();
0704: autoDeployService.shutDown();
0705: deploymentService.shutDown();
0706: installationService.shutDown();
0707: // Shutdown broker before registry to avoid the JCA/JMS flow to send
0708: // lots of messages when components and endpoints are stopped.
0709: broker.shutDown();
0710: registry.shutDown();
0711: if (services != null) {
0712: for (int i = services.length - 1; i >= 0; i--) {
0713: services[i].shutDown();
0714: }
0715: }
0716: clientFactory.shutDown();
0717: environmentContext.shutDown();
0718: // shutdown the management context last, because it will close the mbean server
0719: super .shutDown();
0720: managementContext.unregisterMBean(this );
0721: managementContext.shutDown();
0722: LOG.info("ServiceMix JBI Container (" + getName()
0723: + ") stopped");
0724: }
0725: }
0726:
0727: protected void addShutdownHook() {
0728: if (useShutdownHook) {
0729: shutdownHook = new Thread("ServiceMix ShutdownHook") {
0730: public void run() {
0731: containerShutdown();
0732: }
0733: };
0734: Runtime.getRuntime().addShutdownHook(shutdownHook);
0735: }
0736: }
0737:
0738: protected void removeShutdownHook() {
0739: if (shutdownHook != null) {
0740: try {
0741: Runtime.getRuntime().removeShutdownHook(shutdownHook);
0742: } catch (Exception e) {
0743: LOG.debug("Caught exception, must be shutting down: "
0744: + e);
0745: }
0746: }
0747: }
0748:
0749: /**
0750: * Causes a clean shutdown of the container when the VM is being shut down
0751: */
0752: protected void containerShutdown() {
0753: try {
0754: shutDown();
0755: } catch (Throwable e) {
0756: System.err.println("Failed to shut down: " + e);
0757: }
0758: }
0759:
0760: /**
0761: * @return theMBean server assocated with the JBI
0762: */
0763: public synchronized MBeanServer getMBeanServer() {
0764: return mbeanServer;
0765: }
0766:
0767: /**
0768: * Set the MBeanServer
0769: *
0770: * @param mbs
0771: */
0772: public synchronized void setMBeanServer(MBeanServer mbs) {
0773: this .mbeanServer = mbs;
0774: }
0775:
0776: /**
0777: * @return the naming context
0778: */
0779: public synchronized InitialContext getNamingContext() {
0780: return namingContext;
0781: }
0782:
0783: /**
0784: * Set the naming context
0785: *
0786: * @param ic
0787: */
0788: public synchronized void setNamingContext(InitialContext ic) {
0789: this .namingContext = ic;
0790: }
0791:
0792: /**
0793: * @return the TransactionManager for this implementation
0794: */
0795: public synchronized Object getTransactionManager() {
0796: if (transactionManager == null && namingContext != null) {
0797: try {
0798: transactionManager = (TransactionManager) namingContext
0799: .lookup("java:appserver/TransactionManager");
0800: } catch (NamingException e) {
0801: LOG
0802: .debug("No transaction manager found from naming context: "
0803: + e.getMessage());
0804: try {
0805: transactionManager = (TransactionManager) namingContext
0806: .lookup("javax.transaction.TransactionManager");
0807: } catch (NamingException e1) {
0808: LOG
0809: .debug("No transaction manager found from naming context: "
0810: + e1.getMessage());
0811: }
0812: }
0813: }
0814: return transactionManager;
0815: }
0816:
0817: /**
0818: * Set the transaction manager
0819: *
0820: * @param tm
0821: */
0822: public synchronized void setTransactionManager(Object tm) {
0823: this .transactionManager = (TransactionManager) tm;
0824: }
0825:
0826: /**
0827: * @return the root directory path
0828: */
0829: public synchronized String getRootDir() {
0830: if (rootDir == null) {
0831: if (isGenerateRootDir()) {
0832: rootDir = createRootDir();
0833: } else {
0834: rootDir = "." + File.separator + "rootDir";
0835: }
0836: LOG.debug("Defaulting to rootDir: " + rootDir);
0837: }
0838: return this .rootDir;
0839: }
0840:
0841: /**
0842: * Set the workspace root
0843: *
0844: * @param root
0845: */
0846: public synchronized void setRootDir(String root) {
0847: this .rootDir = root;
0848: }
0849:
0850: /**
0851: * Route an ExchangePacket to a destination
0852: *
0853: * @param exchange
0854: * @throws MessagingException
0855: */
0856: public void sendExchange(MessageExchangeImpl exchange)
0857: throws MessagingException {
0858: try {
0859: broker.sendExchangePacket(exchange);
0860: } catch (MessagingException e) {
0861: throw e;
0862: } catch (JBIException e) {
0863: throw new MessagingException(e);
0864: }
0865: }
0866:
0867: /**
0868: * @param context
0869: * @param externalEndpoint
0870: * @throws JBIException
0871: */
0872: public void registerExternalEndpoint(ComponentNameSpace cns,
0873: ServiceEndpoint externalEndpoint) throws JBIException {
0874: registry.registerExternalEndpoint(cns, externalEndpoint);
0875: }
0876:
0877: /**
0878: * @param context
0879: * @param externalEndpoint
0880: * @throws JBIException
0881: */
0882: public void deregisterExternalEndpoint(ComponentNameSpace cns,
0883: ServiceEndpoint externalEndpoint) throws JBIException {
0884: registry.deregisterExternalEndpoint(cns, externalEndpoint);
0885: }
0886:
0887: /**
0888: * @param context
0889: * @param epr
0890: * @return matching endpoint or null
0891: */
0892: public ServiceEndpoint resolveEndpointReference(
0893: ComponentContextImpl context, DocumentFragment epr) {
0894: return registry.resolveEndpointReference(epr);
0895: }
0896:
0897: /**
0898: * @param context
0899: * @param service
0900: * @param endpointName
0901: * @return the matching endpoint
0902: */
0903: public ServiceEndpoint getEndpoint(ComponentContextImpl context,
0904: QName service, String endpointName) {
0905: return registry.getEndpoint(service, endpointName);
0906: }
0907:
0908: /**
0909: * @param context
0910: * @param interfaceName
0911: * @return endpoints that match the interface name
0912: */
0913: public ServiceEndpoint[] getEndpoints(ComponentContextImpl context,
0914: QName interfaceName) {
0915: return registry.getEndpointsForInterface(interfaceName);
0916: }
0917:
0918: /**
0919: * @param context
0920: * @param serviceName
0921: * @return endpoints for a given service
0922: */
0923: public ServiceEndpoint[] getEndpointsForService(
0924: ComponentContextImpl context, QName serviceName) {
0925: return registry.getEndpointsForService(serviceName);
0926: }
0927:
0928: /**
0929: * @param context
0930: * @param interfaceName
0931: * @return endpoints matching the interface name
0932: */
0933: public ServiceEndpoint[] getExternalEndpoints(
0934: ComponentContextImpl context, QName interfaceName) {
0935: return registry.getExternalEndpoints(interfaceName);
0936: }
0937:
0938: /**
0939: * @param context
0940: * @param serviceName
0941: * @return external endpoints
0942: */
0943: public ServiceEndpoint[] getExternalEndpointsForService(
0944: ComponentContextImpl context, QName serviceName) {
0945: return registry.getExternalEndpointsForService(serviceName);
0946: }
0947:
0948: /**
0949: * @param suffix
0950: * @param resourceBundleName
0951: * @return the Logger
0952: * @throws MissingResourceException
0953: * @throws JBIException
0954: */
0955: public Logger getLogger(String suffix, String resourceBundleName)
0956: throws MissingResourceException, JBIException {
0957: try {
0958: return Logger.getLogger(suffix, resourceBundleName);
0959: } catch (IllegalArgumentException e) {
0960: throw new JBIException(
0961: "A logger can not be created using resource bundle "
0962: + resourceBundleName);
0963: }
0964: }
0965:
0966: /**
0967: * Used for Simple POJO's
0968: *
0969: * @param componentName - the unique component ID
0970: * @throws JBIException
0971: */
0972: public void deactivateComponent(String componentName)
0973: throws JBIException {
0974: ComponentMBeanImpl component = registry
0975: .getComponent(componentName);
0976: if (component != null) {
0977: component.doShutDown();
0978: component.unregisterMbeans(managementContext);
0979: registry.deregisterComponent(component);
0980: environmentContext.unreregister(component);
0981: component.dispose();
0982: LOG.info("Deactivating component " + componentName);
0983: } else {
0984: throw new JBIException("Could not find component "
0985: + componentName);
0986: }
0987: }
0988:
0989: /**
0990: * Delete a Component
0991: *
0992: * @param id
0993: * @throws JBIException
0994: */
0995: public void deleteComponent(String id) throws JBIException {
0996: deactivateComponent(id);
0997: environmentContext.removeComponentRootDirectory(id);
0998: }
0999:
1000: /**
1001: * Get the component associated with the given component ID
1002: *
1003: * @param componentName
1004: * @return the component
1005: */
1006: public ComponentMBeanImpl getComponent(String componentName) {
1007: return registry.getComponent(componentName);
1008: }
1009:
1010: /**
1011: * @return all local ComponentConnectors
1012: */
1013: public Collection getLocalComponentConnectors() {
1014: return registry.getComponents();
1015: }
1016:
1017: /**
1018: * Activates a new component
1019: *
1020: * @param activationSpec
1021: * @return Component
1022: * @throws JBIException
1023: */
1024: public Component activateComponent(ActivationSpec activationSpec)
1025: throws JBIException {
1026: if (activationSpec.getId() == null) {
1027: if (activationSpec.getComponentName() == null) {
1028: // lets generate one
1029: activationSpec.setId(createComponentID());
1030: } else {
1031: activationSpec.setId(activationSpec.getComponentName());
1032: }
1033: }
1034: String id = activationSpec.getId();
1035: if (id == null) {
1036: throw new IllegalArgumentException(
1037: "A Registration must have an ID");
1038: }
1039: if (activationSpec.getEndpoint() == null
1040: && activationSpec.getService() != null) {
1041: // lets default to the ID
1042: activationSpec.setEndpoint(id);
1043: }
1044: if (activationSpec.getComponentName() == null) {
1045: activationSpec.setComponentName(id);
1046: }
1047: Object bean = activationSpec.getComponent();
1048: if (bean == null) {
1049: throw new IllegalArgumentException(
1050: "A Registration must have a component associated with it");
1051: }
1052: if (bean instanceof Component) {
1053: Component component = (Component) bean;
1054: if (component instanceof ComponentSupport) {
1055: defaultComponentServiceAndEndpoint(
1056: (ComponentSupport) component, activationSpec);
1057: }
1058: activateComponent(component, activationSpec);
1059: return component;
1060: } else if (bean instanceof ComponentLifeCycle) {
1061: // lets support just plain lifecycle pojos
1062: ComponentLifeCycle lifeCycle = (ComponentLifeCycle) bean;
1063: if (bean instanceof PojoSupport) {
1064: defaultComponentServiceAndEndpoint((PojoSupport) bean,
1065: activationSpec);
1066: }
1067: Component adaptor = createComponentAdaptor(lifeCycle,
1068: activationSpec);
1069: activateComponent(adaptor, activationSpec);
1070: return adaptor;
1071: } else if (bean instanceof MessageExchangeListener) {
1072: // lets support just plain listener pojos
1073: MessageExchangeListener listener = (MessageExchangeListener) bean;
1074: Component adaptor = createComponentAdaptor(listener,
1075: activationSpec);
1076: activateComponent(adaptor, activationSpec);
1077: return adaptor;
1078: } else {
1079: throw new IllegalArgumentException(
1080: "Component name: "
1081: + id
1082: + " is bound to an object which is not a JBI component, it is of type: "
1083: + bean.getClass().getName());
1084: }
1085: }
1086:
1087: /**
1088: * Activate a POJO Component
1089: *
1090: * @param component
1091: * @param componentName
1092: * @return the ObjectName of the MBean for the Component
1093: * @throws JBIException
1094: */
1095: public ObjectName activateComponent(Component component,
1096: String componentName) throws JBIException {
1097: ActivationSpec activationSpec = new ActivationSpec();
1098: ComponentNameSpace cns = new ComponentNameSpace(getName(),
1099: componentName);
1100: activationSpec.setComponent(component);
1101: activationSpec.setComponentName(cns.getName());
1102: return activateComponent(component, activationSpec);
1103: }
1104:
1105: /**
1106: * Activate A POJO Component
1107: *
1108: * @param component
1109: * @param activationSpec
1110: * @return the ObjectName of the MBean for the Component
1111: * @throws JBIException
1112: */
1113: public ObjectName activateComponent(Component component,
1114: ActivationSpec activationSpec) throws JBIException {
1115: return activateComponent(component, "POJO Component",
1116: activationSpec, true, false, false, null);
1117: }
1118:
1119: /**
1120: * Called by the Installer MBean
1121: *
1122: * @param installDir
1123: * @param component
1124: * @param description
1125: * @param context
1126: * @param binding
1127: * @param service
1128: * @return the ObjectName of the Component's MBean
1129: * @throws JBIException
1130: */
1131: public ObjectName activateComponent(File installDir,
1132: Component component, String description,
1133: ComponentContextImpl context, boolean binding,
1134: boolean service, String[] sharedLibraries)
1135: throws JBIException {
1136: ComponentNameSpace cns = context.getComponentNameSpace();
1137: ActivationSpec activationSpec = new ActivationSpec();
1138: activationSpec.setComponent(component);
1139: activationSpec.setComponentName(cns.getName());
1140: return activateComponent(installDir, component, description,
1141: context, activationSpec, false, binding, service,
1142: sharedLibraries);
1143: }
1144:
1145: /**
1146: * @param component
1147: * @param description
1148: * @param activationSpec
1149: * @param pojo
1150: * @param binding
1151: * @param service
1152: * @return the ObjectName of the Component's MBean
1153: * @throws JBIException
1154: */
1155: public ObjectName activateComponent(Component component,
1156: String description, ActivationSpec activationSpec,
1157: boolean pojo, boolean binding, boolean service,
1158: String[] sharedLibraries) throws JBIException {
1159: ComponentNameSpace cns = new ComponentNameSpace(getName(),
1160: activationSpec.getComponentName());
1161: if (registry.getComponent(cns) != null) {
1162: throw new JBIException(
1163: "A component is already registered for " + cns);
1164: }
1165: ComponentContextImpl context = new ComponentContextImpl(this ,
1166: cns);
1167: return activateComponent(new File("."), component, description,
1168: context, activationSpec, pojo, binding, service,
1169: sharedLibraries);
1170: }
1171:
1172: /**
1173: * @param installationDir
1174: * @param component
1175: * @param description
1176: * @param context
1177: * @param activationSpec
1178: * @param pojo
1179: * @param binding
1180: * @param service
1181: * @return the ObjectName of the Component's MBean
1182: * @throws JBIException
1183: */
1184: public ObjectName activateComponent(File installationDir,
1185: Component component, String description,
1186: ComponentContextImpl context,
1187: ActivationSpec activationSpec, boolean pojo,
1188: boolean binding, boolean service, String[] sharedLibraries)
1189: throws JBIException {
1190: ObjectName result = null;
1191: ComponentNameSpace cns = new ComponentNameSpace(getName(),
1192: activationSpec.getComponentName());
1193: if (LOG.isDebugEnabled()) {
1194: LOG.info("Activating component for: " + cns
1195: + " with service: " + activationSpec.getService()
1196: + " component: " + component);
1197: }
1198: ComponentMBeanImpl lcc = registry.registerComponent(cns,
1199: description, component, binding, service,
1200: sharedLibraries);
1201: if (lcc != null) {
1202: lcc.setPojo(pojo);
1203: ComponentEnvironment env = environmentContext
1204: .registerComponent(context.getEnvironment(), lcc);
1205: if (env.getInstallRoot() == null) {
1206: env.setInstallRoot(installationDir);
1207: }
1208: context.activate(component, env, activationSpec);
1209: lcc.setContext(context);
1210: lcc.setActivationSpec(activationSpec);
1211:
1212: if (lcc.isPojo()) {
1213: //non-pojo's are either started by the auto deployer
1214: //or manually
1215: lcc.init();
1216: } else {
1217: lcc.doShutDown();
1218: }
1219: result = lcc.registerMBeans(managementContext);
1220: // Start the component after mbeans have been registered
1221: // This can be usefull if listeners use them
1222: if (lcc.isPojo() && started.get()) {
1223: lcc.start();
1224: }
1225: }
1226: return result;
1227: }
1228:
1229: /**
1230: * Allow the service and endpoint name to be configured from the registration, to reduce the amount of XML which is
1231: * required to configure a ServiceMix component
1232: *
1233: * @param component
1234: * @param activationSpec
1235: */
1236: protected void defaultComponentServiceAndEndpoint(
1237: PojoSupport component, ActivationSpec activationSpec) {
1238: if (activationSpec.getService() != null) {
1239: component.setService(activationSpec.getService());
1240: }
1241: if (activationSpec.getEndpoint() != null) {
1242: component.setEndpoint(activationSpec.getEndpoint());
1243: }
1244: }
1245:
1246: protected ExecutorFactory createExecutorFactory()
1247: throws JBIException {
1248: return new ExecutorFactoryImpl();
1249: }
1250:
1251: /**
1252: * Factory method to create a new component adaptor from the given lifecycle
1253: *
1254: * @param lifeCycle
1255: * @param activationSpec
1256: * @return Component
1257: */
1258: protected Component createComponentAdaptor(
1259: ComponentLifeCycle lifeCycle, ActivationSpec activationSpec) {
1260: ComponentAdaptor answer = null;
1261: if (lifeCycle instanceof MessageExchangeListener) {
1262: answer = new ComponentAdaptorMEListener(lifeCycle,
1263: activationSpec.getService(), activationSpec
1264: .getEndpoint(),
1265: (MessageExchangeListener) lifeCycle);
1266: } else {
1267: answer = new ComponentAdaptor(lifeCycle, activationSpec
1268: .getService(), activationSpec.getEndpoint());
1269: }
1270: answer.setServiceManager(serviceManager);
1271: return answer;
1272: }
1273:
1274: protected Component createComponentAdaptor(
1275: MessageExchangeListener listener,
1276: ActivationSpec activationSpec) {
1277: ComponentLifeCycle lifecCycle = new PojoLifecycleAdaptor(
1278: listener, activationSpec.getService(), activationSpec
1279: .getEndpoint());
1280: return new ComponentAdaptorMEListener(lifecCycle, listener);
1281: }
1282:
1283: /**
1284: * Factory method to create a new component ID if none is specified
1285: *
1286: * @return uniqueId
1287: */
1288: protected String createComponentID() {
1289: return idGenerator.generateId();
1290: }
1291:
1292: protected void checkInitialized() throws JBIException {
1293: if (!containerInitialized.get()) {
1294: throw new JBIException(
1295: "The Container is not initialized - please call init(...)");
1296: }
1297: }
1298:
1299: /**
1300: * Retrieve the value for automatic transaction enlistment.
1301: * @return
1302: */
1303: public boolean isAutoEnlistInTransaction() {
1304: return autoEnlistInTransaction;
1305: }
1306:
1307: /**
1308: * Set the new value for automatic transaction enlistment.
1309: * When this parameter is set to <code>true</code> and a transaction
1310: * is running when sending / receiving an exchange, this operation will
1311: * automatically be done in the current transaction.
1312: *
1313: * @param autoEnlistInTransaction
1314: */
1315: public void setAutoEnlistInTransaction(
1316: boolean autoEnlistInTransaction) {
1317: this .autoEnlistInTransaction = autoEnlistInTransaction;
1318: }
1319:
1320: public boolean isPersistent() {
1321: return persistent;
1322: }
1323:
1324: /**
1325: * Set the new default value for exchange persistence.
1326: * This value will be the default if none is configured on
1327: * the activation spec of the component or on the message.
1328: *
1329: * @param persistent
1330: */
1331: public void setPersistent(boolean persistent) {
1332: this .persistent = persistent;
1333: }
1334:
1335: public void addListener(EventListener listener) {
1336: LOG.debug("Adding listener: " + listener.getClass());
1337: if (listener instanceof ContainerAware) {
1338: ContainerAware containerAware = (ContainerAware) listener;
1339: containerAware.setContainer(this );
1340: }
1341: if (listener instanceof ExchangeListener) {
1342: listeners.add(ExchangeListener.class,
1343: (ExchangeListener) listener);
1344: }
1345: if (listener instanceof ComponentListener) {
1346: listeners.add(ComponentListener.class,
1347: (ComponentListener) listener);
1348: }
1349: if (listener instanceof ServiceAssemblyListener) {
1350: listeners.add(ServiceAssemblyListener.class,
1351: (ServiceAssemblyListener) listener);
1352: }
1353: if (listener instanceof ServiceUnitListener) {
1354: listeners.add(ServiceUnitListener.class,
1355: (ServiceUnitListener) listener);
1356: }
1357: if (listener instanceof EndpointListener) {
1358: listeners.add(EndpointListener.class,
1359: (EndpointListener) listener);
1360: }
1361: if (listener instanceof DeploymentListener) {
1362: listeners.add(DeploymentListener.class,
1363: (DeploymentListener) listener);
1364: }
1365: }
1366:
1367: public void removeListener(EventListener listener) {
1368: LOG.debug("Removing listener: " + listener.getClass());
1369: if (listener instanceof ExchangeListener) {
1370: listeners.remove(ExchangeListener.class,
1371: (ExchangeListener) listener);
1372: }
1373: if (listener instanceof ComponentListener) {
1374: listeners.remove(ComponentListener.class,
1375: (ComponentListener) listener);
1376: }
1377: if (listener instanceof ServiceAssemblyListener) {
1378: listeners.remove(ServiceAssemblyListener.class,
1379: (ServiceAssemblyListener) listener);
1380: }
1381: if (listener instanceof ServiceUnitListener) {
1382: listeners.remove(ServiceUnitListener.class,
1383: (ServiceUnitListener) listener);
1384: }
1385: if (listener instanceof EndpointListener) {
1386: listeners.remove(EndpointListener.class,
1387: (EndpointListener) listener);
1388: }
1389: if (listener instanceof DeploymentListener) {
1390: listeners.remove(DeploymentListener.class,
1391: (DeploymentListener) listener);
1392: }
1393: }
1394:
1395: public Object[] getListeners(Class lc) {
1396: return listeners.getListeners(lc);
1397: }
1398:
1399: public void setListeners(EventListener[] listeners) {
1400: configuredListeners = listeners;
1401: }
1402:
1403: public void resendExchange(MessageExchange exchange)
1404: throws JBIException {
1405: if (!(exchange instanceof MessageExchangeImpl)) {
1406: throw new IllegalArgumentException(
1407: "exchange should be a MessageExchangeImpl");
1408: }
1409: MessageExchangeImpl me = (MessageExchangeImpl) exchange;
1410: me.getPacket().setExchangeId(new IdGenerator().generateId());
1411: me.getPacket().setOut(null);
1412: me.getPacket().setFault(null);
1413: me.getPacket().setError(null);
1414: me.getPacket().setStatus(ExchangeStatus.ACTIVE);
1415: me.getPacket().setProperty(
1416: JbiConstants.DATESTAMP_PROPERTY_NAME,
1417: Calendar.getInstance());
1418: ExchangeListener[] l = (ExchangeListener[]) listeners
1419: .getListeners(ExchangeListener.class);
1420: ExchangeEvent event = new ExchangeEvent(me,
1421: ExchangeEvent.EXCHANGE_SENT);
1422: for (int i = 0; i < l.length; i++) {
1423: try {
1424: l[i].exchangeSent(event);
1425: } catch (Exception e) {
1426: LOG
1427: .warn("Error calling listener: "
1428: + e.getMessage(), e);
1429: }
1430: }
1431: me.handleSend(false);
1432: sendExchange(me.getMirror());
1433: }
1434:
1435: public boolean isEmbedded() {
1436: return embedded;
1437: }
1438:
1439: public void setEmbedded(boolean embedded) {
1440: this .embedded = embedded;
1441: }
1442:
1443: public void setRmiPort(int portNum) {
1444: getManagementContext().setNamingPort(portNum);
1445: }
1446:
1447: public int getRmiPort() {
1448: return getManagementContext().getNamingPort();
1449: }
1450:
1451: /**
1452: * @return Returns the notifyStatistics.
1453: */
1454: public boolean isNotifyStatistics() {
1455: return notifyStatistics;
1456: }
1457:
1458: /**
1459: * @param notifyStatistics The notifyStatistics to set.
1460: */
1461: public void setNotifyStatistics(boolean notifyStatistics) {
1462: this .notifyStatistics = notifyStatistics;
1463: }
1464:
1465: /**
1466: * @return the executorFactory
1467: */
1468: public ExecutorFactory getExecutorFactory() {
1469: return executorFactory;
1470: }
1471:
1472: /**
1473: * @param executorFactory the executorFactory to set
1474: */
1475: public void setExecutorFactory(ExecutorFactory executorFactory) {
1476: this .executorFactory = executorFactory;
1477: }
1478:
1479: /**
1480: * Creates a new rootDir
1481: */
1482: protected String createRootDir() {
1483: String prefix = getGeneratedRootDirPrefix();
1484: for (int i = 1; true; i++) {
1485: File file = new File(prefix + i);
1486: if (!file.exists()) {
1487: file.mkdirs();
1488: return file.getAbsolutePath();
1489: }
1490: }
1491: }
1492: }
|