blob: 5e33e54f53fe67220d1f93368eddc94577b3cfa0 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.servicemix.jbi.container;
import java.io.File;
import java.io.IOException;
import java.util.Calendar;
import java.util.Collection;
import java.util.EventListener;
import java.util.MissingResourceException;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.jbi.JBIException;
import javax.jbi.component.Component;
import javax.jbi.component.ComponentLifeCycle;
import javax.jbi.component.ServiceUnitManager;
import javax.jbi.management.DeploymentException;
import javax.jbi.management.LifeCycleMBean;
import javax.jbi.messaging.ExchangeStatus;
import javax.jbi.messaging.MessageExchange;
import javax.jbi.messaging.MessagingException;
import javax.jbi.servicedesc.ServiceEndpoint;
import javax.management.JMException;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.swing.event.EventListenerList;
import javax.transaction.TransactionManager;
import javax.xml.namespace.QName;
import org.w3c.dom.DocumentFragment;
import org.apache.servicemix.JbiConstants;
import org.apache.servicemix.components.util.ComponentAdaptor;
import org.apache.servicemix.components.util.ComponentAdaptorMEListener;
import org.apache.servicemix.components.util.ComponentSupport;
import org.apache.servicemix.components.util.PojoLifecycleAdaptor;
import org.apache.servicemix.components.util.PojoSupport;
import org.apache.servicemix.executors.ExecutorFactory;
import org.apache.servicemix.id.IdGenerator;
import org.apache.servicemix.jbi.api.Container;
import org.apache.servicemix.jbi.event.ComponentListener;
import org.apache.servicemix.jbi.event.ContainerAware;
import org.apache.servicemix.jbi.event.DeploymentListener;
import org.apache.servicemix.jbi.event.EndpointListener;
import org.apache.servicemix.jbi.event.ExchangeEvent;
import org.apache.servicemix.jbi.event.ExchangeListener;
import org.apache.servicemix.jbi.event.ServiceAssemblyListener;
import org.apache.servicemix.jbi.event.ServiceUnitListener;
import org.apache.servicemix.jbi.framework.AdminCommandsService;
import org.apache.servicemix.jbi.framework.AutoDeploymentService;
import org.apache.servicemix.jbi.framework.ClientFactory;
import org.apache.servicemix.jbi.framework.ComponentContextImpl;
import org.apache.servicemix.jbi.framework.ComponentMBeanImpl;
import org.apache.servicemix.jbi.framework.ComponentNameSpace;
import org.apache.servicemix.jbi.framework.DeploymentService;
import org.apache.servicemix.jbi.framework.InstallationService;
import org.apache.servicemix.jbi.framework.Registry;
import org.apache.servicemix.jbi.listener.MessageExchangeListener;
import org.apache.servicemix.jbi.management.BaseLifeCycle;
import org.apache.servicemix.jbi.management.BaseSystemService;
import org.apache.servicemix.jbi.management.ManagementContext;
import org.apache.servicemix.jbi.messaging.MessageExchangeImpl;
import org.apache.servicemix.jbi.nmr.Broker;
import org.apache.servicemix.jbi.nmr.DefaultBroker;
import org.apache.servicemix.jbi.nmr.flow.Flow;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The main container
*
* @version $Revision$
*/
public class JBIContainer extends BaseLifeCycle implements Container {
/**
* Default Container name - must be unique if used in a cluster
*/
public static final String DEFAULT_NAME = "ServiceMix";
private static final Logger LOGGER = LoggerFactory.getLogger(JBIContainer.class);
protected Broker broker = new DefaultBroker();
protected ServiceUnitManager serviceManager;
protected ManagementContext managementContext = new ManagementContext();
protected EnvironmentContext environmentContext = new EnvironmentContext();
protected InstallationService installationService = new InstallationService();
protected DeploymentService deploymentService = new DeploymentService();
protected AutoDeploymentService autoDeployService = new AutoDeploymentService();
protected AdminCommandsService adminCommandsService = new AdminCommandsService();
protected BaseSystemService[] services;
protected ClientFactory clientFactory = new ClientFactory();
protected Registry registry = new Registry();
protected boolean autoEnlistInTransaction;
protected boolean persistent;
protected boolean embedded;
protected boolean notifyStatistics;
protected EventListenerList listeners = new EventListenerList();
protected EventListener[] configuredListeners;
protected boolean useShutdownHook = true;
protected boolean useNewTransactionModel;
protected transient Thread shutdownHook;
protected ExecutorFactory executorFactory;
private String name = DEFAULT_NAME;
private InitialContext namingContext;
private MBeanServer mbeanServer;
private String completeStartMarkupFileName;
private TransactionManager transactionManager;
private String rootDir;
private String generatedRootDirPrefix = "target/rootDirs/rootDir";
private boolean generateRootDir;
private AtomicBoolean started = new AtomicBoolean(false);
private AtomicBoolean containerInitialized = new AtomicBoolean(false);
private IdGenerator idGenerator = new IdGenerator();
private long forceShutdown;
private boolean optimizedDelivery = true;
/**
* Default Constructor
*/
public JBIContainer() {
}
/**
* @return Returns the unique nam for the Container
*/
public String getName() {
return name;
}
/**
* @param name The name to set (must be unique within a cluster)
*/
public void setName(String name) {
this.name = name;
}
/**
* Get the description
*
* @return descrption
*/
public String getDescription() {
return "ServiceMix JBI Container";
}
/**
* @return Returns the flowName.
*/
public String getFlowName() {
String flowNames = getDefaultBroker().getFlowNames();
if (flowNames == null) {
return null;
}
String[] flows = flowNames.split(",");
if (flows.length > 1) {
throw new IllegalStateException("Multiple flows have been defined");
}
return flows[0];
}
/**
* @param flowName The flow to set.
*/
public void setFlowName(String flowName) {
getDefaultBroker().setFlowNames(flowName);
}
/**
* @return Returns the flowNames.
*/
public String getFlowNames() {
return getDefaultBroker().getFlowNames();
}
/**
* @param flowNames The flows to set.
*/
public void setFlowNames(String flowNames) {
getDefaultBroker().setFlowNames(flowNames);
}
/**
* @return the subscriptionFlowName
*/
public String getSubscriptionFlowName() {
return getDefaultBroker().getSubscriptionFlowName();
}
/**
* Set the subscription flow name
*
* @param subscriptionFlowName
*/
public void setSubscriptionFlowName(String subscriptionFlowName) {
getDefaultBroker().setSubscriptionFlowName(subscriptionFlowName);
}
/**
* Set the broker message flow
*
* @param flow
*/
public void setFlow(Flow flow) {
getDefaultBroker().setFlows(new Flow[]{flow});
}
/**
* @return the broker message Flow
*/
public Flow getFlow() {
Flow[] flows = getDefaultBroker().getFlows();
if (flows == null || flows.length == 0) {
return null;
} else if (flows.length > 1) {
throw new IllegalStateException("Multiple flows have been defined");
} else {
return flows[0];
}
}
/**
* Set the broker message flows
*
* @param flows
*/
public void setFlows(Flow[] flows) {
getDefaultBroker().setFlows(flows);
}
/**
* @return the broker message Flows
*/
public Flow[] getFlows() {
return getDefaultBroker().getFlows();
}
public boolean isUseShutdownHook() {
return useShutdownHook;
}
/**
* Sets whether or not we should use a shutdown handler to close down the
* broker cleanly if the JVM is terminated. It is recommended you leave this
* enabled.
*/
public void setUseShutdownHook(boolean useShutdownHook) {
this.useShutdownHook = useShutdownHook;
}
public boolean isUseNewTransactionModel() {
return useNewTransactionModel;
}
/**
* Sets whether the new transaction model should be used.
*
* @param useNewTransactionModel
*/
public void setUseNewTransactionModel(boolean useNewTransactionModel) {
this.useNewTransactionModel = useNewTransactionModel;
}
/**
* @return the services
*/
public BaseSystemService[] getServices() {
return services;
}
/**
* @param services the services to set
*/
public void setServices(BaseSystemService[] services) {
this.services = services;
}
/**
* Gets name of file that is created when container finished starting.
*
* @return the name of the markup file in container root directory.
*/
public String getCompleteStartMarkupFileName() {
return this.completeStartMarkupFileName;
}
/**
* Sets name of file that is created when container finishes starting.
*
* @param completeStartMarkupFileName name of the marker file in container root directory.
*/
public void setCompleteStartMarkupFileName(String completeStartMarkupFileName) {
this.completeStartMarkupFileName = completeStartMarkupFileName;
}
/**
* Get the ManagementContext
*
* @return the ManagementContext
*/
public ManagementContext getManagementContext() {
return managementContext;
}
/**
* @return Return the EnvironmentContext
*/
public EnvironmentContext getEnvironmentContext() {
return environmentContext;
}
/**
* @return Return the registry
*/
public Registry getRegistry() {
return registry;
}
/**
* Return the DefaultBroker instance
*/
public DefaultBroker getDefaultBroker() {
if (!(broker instanceof DefaultBroker)) {
throw new IllegalStateException("Broker is not a DefaultBroker");
}
return (DefaultBroker) broker;
}
/**
* @return Return the NMR broker
*/
public Broker getBroker() {
return broker;
}
/**
* Set the Broker to use
*/
public void setBroker(Broker broker) {
this.broker = broker;
}
/**
* @return true if creates own MBeanServer if none supplied
*/
public boolean isCreateMBeanServer() {
return managementContext.isCreateMBeanServer();
}
/**
* Set the flag to create own MBeanServer if none supplied
*
* @param enableJMX
*/
public void setCreateMBeanServer(boolean enableJMX) {
managementContext.setCreateMBeanServer(enableJMX);
}
/**
* @return Returns the useMBeanServer.
*/
public boolean isUseMBeanServer() {
return managementContext.isUseMBeanServer();
}
/**
* @param useMBeanServer The useMBeanServer to set.
*/
public void setUseMBeanServer(boolean useMBeanServer) {
managementContext.setUseMBeanServer(useMBeanServer);
}
/**
* @return Returns the useMBeanServer.
*/
public boolean isCreateJmxConnector() {
return managementContext.isCreateJmxConnector();
}
/**
* @param createJmxConnector The createJmxConnector to set.
*/
public void setCreateJmxConnector(boolean createJmxConnector) {
managementContext.setCreateJmxConnector(createJmxConnector);
}
/**
* @return Returns the monitorInstallationDirectory.
*/
public boolean isMonitorInstallationDirectory() {
return autoDeployService.isMonitorInstallationDirectory();
}
/**
* @param monitorInstallationDirectory The monitorInstallationDirectory to set.
*/
public void setMonitorInstallationDirectory(boolean monitorInstallationDirectory) {
autoDeployService.setMonitorInstallationDirectory(monitorInstallationDirectory);
}
/**
* @return Returns the monitorDeploymentDirectory.
*/
public boolean isMonitorDeploymentDirectory() {
return autoDeployService.isMonitorDeploymentDirectory();
}
/**
* @param monitorDeploymentDirectory The monitorDeploymentDirectory to set.
*/
public void setMonitorDeploymentDirectory(boolean monitorDeploymentDirectory) {
autoDeployService.setMonitorDeploymentDirectory(monitorDeploymentDirectory);
}
/**
* @return Returns the installationDir.
*/
public String getInstallationDirPath() {
File dir = environmentContext.getInstallationDir();
return dir != null ? dir.getAbsolutePath() : "";
}
/**
* Set the installationDir - rge default location is root/<container name>/installation
*
* @param installationDir
*/
public void setInstallationDirPath(String installationDir) {
if (installationDir != null && installationDir.length() > 0) {
environmentContext.setInstallationDir(new File(installationDir));
}
}
/**
* @return Returns the deploymentDir.
*/
public String getDeploymentDirPath() {
File dir = environmentContext.getDeploymentDir();
return dir != null ? dir.getAbsolutePath() : "";
}
/**
* @param deploymentDir The deploymentDir to set.
*/
public void setDeploymentDirPath(String deploymentDir) {
if (deploymentDir != null && deploymentDir.length() > 0) {
environmentContext.setDeploymentDir(new File(deploymentDir));
}
}
/**
* @return Returns the monitorInterval (in secs).
*/
public int getMonitorInterval() {
return autoDeployService.getMonitorInterval();
}
/**
* @param monitorInterval The monitorInterval to set (in secs).
*/
public void setMonitorInterval(int monitorInterval) {
autoDeployService.setMonitorInterval(monitorInterval);
}
/**
* @return the deploymentExtensions
*/
public String getDeploymentExtensions() {
return autoDeployService.getExtensions();
}
/**
* @param deploymentExtensions the deploymentExtensions to set
*/
public void setDeploymentExtensions(String deploymentExtensions) {
autoDeployService.setExtensions(deploymentExtensions);
}
/**
* Install an component from a url
*
* @param url
* @throws DeploymentException
*/
public void installArchive(String url) throws DeploymentException {
installationService.install(url, null, true);
}
/**
* load an archive from an external location.
* The archive can be a Component, Service Assembly or Shared Library.
*
* @param location - can either be a url or filename (if relative - must be relative to the container)
* @param autoStart - if true will start the component/service assembly
* @throws DeploymentException
*/
public void updateExternalArchive(String location, boolean autoStart) throws DeploymentException {
autoDeployService.updateExternalArchive(location, autoStart);
}
/**
* load an archive from an external location and starts it
* The archive can be a Component, Service Assembly or Shared Library.
*
* @param location - can either be a url or filename (if relative - must be relative to the container)
* @throws DeploymentException
*/
public void updateExternalArchive(String location) throws DeploymentException {
updateExternalArchive(location, true);
}
/**
* @return Returns the deploymentService.
*/
public DeploymentService getDeploymentService() {
return deploymentService;
}
/**
* @return Returns the installationService.
*/
public InstallationService getInstallationService() {
return installationService;
}
/**
* @return the AutomDeploymentService
*/
public AutoDeploymentService getAutoDeploymentService() {
return autoDeployService;
}
/**
* @return the AdminCommandsService
*/
public AdminCommandsService getAdminCommandsService() {
return adminCommandsService;
}
public ClientFactory getClientFactory() {
return clientFactory;
}
public String getGeneratedRootDirPrefix() {
return generatedRootDirPrefix;
}
/**
* Sets the prefix used when auto-creating a rootDir property value
* which is useful for integration testing inside JUnit test cases
* letting each test case create its own empty servicemix install
*
* @param generatedRootDirPrefix the prefix used to auto-create the
* rootDir
* @see #setRootDir(String)
* @see #setGeneratedRootDirPrefix(String)
*/
public void setGeneratedRootDirPrefix(String generatedRootDirPrefix) {
this.generatedRootDirPrefix = generatedRootDirPrefix;
}
public boolean isGenerateRootDir() {
return generateRootDir;
}
public long getForceShutdown() {
return forceShutdown;
}
/**
* Set the timeout (in ms) before a shutdown is forced by cancelling all pending exchanges.
* The default value is 0 -- no forced shutdown
*
* @param forceShutdown the timeout in ms
*/
public void setForceShutdown(long forceShutdown) {
this.forceShutdown = forceShutdown;
}
/**
* Creates an auto-generated rootDir which is useful for integration testing
* in JUnit test cases allowing installations of deployments inside an empty
* installation of ServiceMix
*
* @param generateRootDir if true this will enable the auto-generation of the rootDir
* if the rootDir property is not configured
* @see #setRootDir(String)
* @see #setGeneratedRootDirPrefix(String)
*/
public void setGenerateRootDir(boolean generateRootDir) {
this.generateRootDir = generateRootDir;
}
/**
* light weight initialization - default values for mbeanServer, TransactionManager etc are null
*
* @throws JBIException
*/
public void init() throws JBIException {
if (containerInitialized.compareAndSet(false, true)) {
LOGGER.info("ServiceMix {} JBI Container ({}) is starting", EnvironmentContext.getVersion(), getName());
LOGGER.info("For help or more information please see: http://servicemix.apache.org/");
addShutdownHook();
if (this.executorFactory == null) {
this.executorFactory = createExecutorFactory();
}
if (this.namingContext == null) {
try {
this.namingContext = new InitialContext();
} catch (NamingException e) {
// Log a warning, with exception only in debug
if (LOGGER.isDebugEnabled()) {
LOGGER.warn("Failed to set InitialContext", e);
} else {
LOGGER.warn("Failed to set InitialContext");
}
}
}
managementContext.init(this, getMBeanServer());
mbeanServer = this.managementContext.getMBeanServer(); // just in case ManagementContext creates it
environmentContext.init(this, getRootDir());
clientFactory.init(this);
if (services != null) {
for (int i = 0; i < services.length; i++) {
services[i].init(this);
}
}
registry.init(this);
broker.init(this);
installationService.init(this);
deploymentService.init(this);
autoDeployService.init(this);
adminCommandsService.init(this);
// register self with the ManagementContext
try {
managementContext.registerMBean(ManagementContext.getContainerObjectName(managementContext.getJmxDomainName(), getName()),
this, LifeCycleMBean.class);
} catch (JMException e) {
throw new JBIException(e);
}
// Initialize listeners after the whole container has been initialized
// so that they can register themselves as JMX mbeans for example
if (configuredListeners != null) {
for (int i = 0; i < configuredListeners.length; i++) {
EventListener listener = configuredListeners[i];
addListener(listener);
}
}
}
}
/**
* start processing
*
* @throws JBIException
*/
public void start() throws JBIException {
checkInitialized();
if (started.compareAndSet(false, true)) {
managementContext.start();
environmentContext.start();
clientFactory.start();
if (services != null) {
for (int i = 0; i < services.length; i++) {
services[i].start();
}
}
broker.start();
registry.start();
installationService.start();
deploymentService.start();
autoDeployService.start();
adminCommandsService.start();
super.start();
this.notifyContainerStarted();
}
}
private void notifyContainerStarted() throws JBIException {
if (completeStartMarkupFileName != null) {
File startMarkupFile = new File(rootDir, completeStartMarkupFileName);
try {
if (!startMarkupFile.exists()) {
File parent = startMarkupFile.getParentFile();
if (parent != null && !parent.exists()) {
parent.mkdirs();
}
startMarkupFile.createNewFile();
}
startMarkupFile.setLastModified(System.currentTimeMillis());
} catch (IOException ioException) {
throw new JBIException("Cannot create startup markup file " + startMarkupFile.getAbsolutePath(), ioException);
}
}
LOGGER.info("ServiceMix JBI Container (" + this.getName() + ") started");
}
/**
* stop the container from processing
*
* @throws JBIException
*/
public void stop() throws JBIException {
checkInitialized();
if (started.compareAndSet(true, false)) {
LOGGER.info("ServiceMix JBI Container ({})", getName());
adminCommandsService.stop();
autoDeployService.stop();
deploymentService.stop();
installationService.stop();
registry.stop();
broker.stop();
if (services != null) {
for (int i = services.length - 1; i >= 0; i--) {
services[i].stop();
}
}
clientFactory.stop();
environmentContext.stop();
managementContext.stop();
super.stop();
}
}
/**
* After a shutdown the container will require an init before a start ...
*
* @throws JBIException
*/
public void shutDown() throws JBIException {
if (containerInitialized.compareAndSet(true, false)) {
LOGGER.info("Shutting down ServiceMix JBI Container ({})", getName());
removeShutdownHook();
adminCommandsService.shutDown();
autoDeployService.shutDown();
deploymentService.shutDown();
installationService.shutDown();
shutdownRegistry();
broker.shutDown();
shutdownServices();
clientFactory.shutDown();
environmentContext.shutDown();
// shutdown the management context last, because it will close the mbean server
super.shutDown();
managementContext.unregisterMBean(this);
managementContext.shutDown();
LOGGER.info("ServiceMix JBI Container ({})", getName());
}
}
private void shutdownServices() throws JBIException {
if (services != null) {
for (int i = services.length - 1; i >= 0; i--) {
services[i].shutDown();
}
}
}
private void shutdownRegistry() throws JBIException {
FutureTask<Boolean> shutdown = new FutureTask<Boolean>(new Callable<Boolean>() {
public Boolean call() throws Exception {
registry.shutDown();
return true;
}
});
//use daemon thread to run this shutdown task
//fix the container hang when shutdown container from the jmx console
Thread daemonShutDownThread = new Thread(shutdown);
daemonShutDownThread.setDaemon(true);
daemonShutDownThread.start();
try {
if (forceShutdown > 0) {
LOGGER.info("Waiting another {} ms for complete shutdown of the components and service assemblies", forceShutdown);
shutdown.get(forceShutdown, TimeUnit.MILLISECONDS);
} else {
LOGGER.info("Waiting for complete shutdown of the components and service assemblies");
shutdown.get();
}
LOGGER.info("Components and service assemblies have been shut down");
} catch (Exception e) {
forceShutdown(e);
}
}
/**
* Force a container shutdown by canceling all pending exchanges
*
* @param e the exception that caused the forced container shutdown
*/
protected void forceShutdown(Exception e) {
LOGGER.warn("Unable to shutdown components and service assemblies normally: {}", e, e);
LOGGER.warn("Forcing shutdown by cancelling all pending exchanges");
registry.cancelPendingExchanges();
}
protected void addShutdownHook() {
if (useShutdownHook) {
shutdownHook = new Thread("ServiceMix ShutdownHook") {
public void run() {
containerShutdown();
}
};
Runtime.getRuntime().addShutdownHook(shutdownHook);
}
}
protected void removeShutdownHook() {
if (shutdownHook != null) {
try {
Runtime.getRuntime().removeShutdownHook(shutdownHook);
} catch (Exception e) {
LOGGER.debug("Caught exception, must be shutting down: {}", e, e);
}
}
}
/**
* Causes a clean shutdown of the container when the VM is being shut down
*/
protected void containerShutdown() {
try {
shutDown();
} catch (Throwable e) {
System.err.println("Failed to shut down: " + e);
}
}
/**
* @return theMBean server assocated with the JBI
*/
public synchronized MBeanServer getMBeanServer() {
return mbeanServer;
}
/**
* Set the MBeanServer
*
* @param mbs
*/
public synchronized void setMBeanServer(MBeanServer mbs) {
this.mbeanServer = mbs;
if (this.mbeanServer != null
&& this.executorFactory != null
&& this.executorFactory instanceof org.apache.servicemix.executors.impl.ExecutorFactoryImpl) {
((org.apache.servicemix.executors.impl.ExecutorFactoryImpl) this.executorFactory).setMbeanServer(this.mbeanServer);
}
}
/**
* @return the naming context
*/
public synchronized InitialContext getNamingContext() {
return namingContext;
}
/**
* Set the naming context
*
* @param ic
*/
public synchronized void setNamingContext(InitialContext ic) {
this.namingContext = ic;
}
/**
* @return the TransactionManager for this implementation
*/
public synchronized Object getTransactionManager() {
if (transactionManager == null && namingContext != null) {
try {
transactionManager = (TransactionManager) namingContext.lookup("java:appserver/TransactionManager");
} catch (NamingException e) {
LOGGER.debug("No transaction manager found from naming context: {}", e.getMessage());
try {
transactionManager = (TransactionManager) namingContext.lookup("javax.transaction.TransactionManager");
} catch (NamingException e1) {
LOGGER.debug("No transaction manager found from naming context: {}", e1.getMessage());
}
}
}
return transactionManager;
}
/**
* Set the transaction manager
*
* @param tm
*/
public synchronized void setTransactionManager(Object tm) {
this.transactionManager = (TransactionManager) tm;
}
/**
* @return the root directory path
*/
public synchronized String getRootDir() {
if (rootDir == null) {
if (isGenerateRootDir()) {
rootDir = createRootDir();
} else {
rootDir = "." + File.separator + "rootDir";
}
LOGGER.debug("Defaulting to rootDir: {}", rootDir);
}
return this.rootDir;
}
/**
* Set the workspace root
*
* @param root
*/
public synchronized void setRootDir(String root) {
this.rootDir = root;
}
/**
* Route an ExchangePacket to a destination
*
* @param exchange
* @throws MessagingException
*/
public void sendExchange(MessageExchangeImpl exchange) throws MessagingException {
try {
broker.sendExchangePacket(exchange);
} catch (MessagingException e) {
throw e;
} catch (JBIException e) {
throw new MessagingException(e);
}
}
/**
* @param cns
* @param externalEndpoint
* @throws JBIException
*/
public void registerExternalEndpoint(ComponentNameSpace cns, ServiceEndpoint externalEndpoint) throws JBIException {
registry.registerExternalEndpoint(cns, externalEndpoint);
}
/**
* @param cns
* @param externalEndpoint
* @throws JBIException
*/
public void deregisterExternalEndpoint(ComponentNameSpace cns, ServiceEndpoint externalEndpoint) throws JBIException {
registry.deregisterExternalEndpoint(cns, externalEndpoint);
}
/**
* @param context
* @param epr
* @return matching endpoint or null
*/
public ServiceEndpoint resolveEndpointReference(ComponentContextImpl context, DocumentFragment epr) {
return registry.resolveEndpointReference(epr);
}
/**
* @param context
* @param service
* @param endpointName
* @return the matching endpoint
*/
public ServiceEndpoint getEndpoint(ComponentContextImpl context, QName service, String endpointName) {
return registry.getEndpoint(service, endpointName);
}
/**
* @param context
* @param interfaceName
* @return endpoints that match the interface name
*/
public ServiceEndpoint[] getEndpoints(ComponentContextImpl context, QName interfaceName) {
return registry.getEndpointsForInterface(interfaceName);
}
/**
* @param context
* @param serviceName
* @return endpoints for a given service
*/
public ServiceEndpoint[] getEndpointsForService(ComponentContextImpl context, QName serviceName) {
return registry.getEndpointsForService(serviceName);
}
/**
* @param context
* @param interfaceName
* @return endpoints matching the interface name
*/
public ServiceEndpoint[] getExternalEndpoints(ComponentContextImpl context, QName interfaceName) {
return registry.getExternalEndpoints(interfaceName);
}
/**
* @param context
* @param serviceName
* @return external endpoints
*/
public ServiceEndpoint[] getExternalEndpointsForService(ComponentContextImpl context, QName serviceName) {
return registry.getExternalEndpointsForService(serviceName);
}
/**
* @param suffix
* @param resourceBundleName
* @return the Logger
* @throws MissingResourceException
* @throws JBIException
*/
public java.util.logging.Logger getLogger(String suffix, String resourceBundleName) throws MissingResourceException, JBIException {
try {
return java.util.logging.Logger.getLogger(suffix, resourceBundleName);
} catch (IllegalArgumentException e) {
throw new JBIException("A LOGGER can not be created using resource bundle " + resourceBundleName);
}
}
/**
* Used for Simple POJO's
*
* @param componentName - the unique component ID
* @throws JBIException
*/
public void deactivateComponent(String componentName) throws JBIException {
ComponentMBeanImpl component = registry.getComponent(componentName);
if (component != null) {
component.doShutDown();
component.unregisterMbeans(managementContext);
registry.deregisterComponent(component);
environmentContext.unreregister(component);
component.dispose();
LOGGER.info("Deactivating component {}", componentName);
} else {
throw new JBIException("Could not find component " + componentName);
}
}
/**
* Delete a Component
*
* @param id
* @throws JBIException
*/
public void deleteComponent(String id) throws JBIException {
deactivateComponent(id);
environmentContext.removeComponentRootDirectory(id);
}
/**
* Get the component associated with the given component ID
*
* @param componentName
* @return the component
*/
public ComponentMBeanImpl getComponent(String componentName) {
return registry.getComponent(componentName);
}
/**
* @return all local ComponentConnectors
*/
public Collection getLocalComponentConnectors() {
return registry.getComponents();
}
/**
* Activates a new component
*
* @param activationSpec
* @return Component
* @throws JBIException
*/
public Component activateComponent(ActivationSpec activationSpec) throws JBIException {
if (activationSpec.getId() == null) {
if (activationSpec.getComponentName() == null) {
// lets generate one
activationSpec.setId(createComponentID());
} else {
activationSpec.setId(activationSpec.getComponentName());
}
}
String id = activationSpec.getId();
if (id == null) {
throw new IllegalArgumentException("A Registration must have an ID");
}
if (activationSpec.getEndpoint() == null && activationSpec.getService() != null) {
// lets default to the ID
activationSpec.setEndpoint(id);
}
if (activationSpec.getComponentName() == null) {
activationSpec.setComponentName(id);
}
Object bean = activationSpec.getComponent();
if (bean == null) {
throw new IllegalArgumentException("A Registration must have a component associated with it");
}
if (bean instanceof Component) {
Component component = (Component) bean;
if (component instanceof ComponentSupport) {
defaultComponentServiceAndEndpoint((ComponentSupport) component, activationSpec);
}
activateComponent(component, activationSpec);
return component;
} else if (bean instanceof ComponentLifeCycle) {
// lets support just plain lifecycle pojos
ComponentLifeCycle lifeCycle = (ComponentLifeCycle) bean;
if (bean instanceof PojoSupport) {
defaultComponentServiceAndEndpoint((PojoSupport) bean, activationSpec);
}
Component adaptor = createComponentAdaptor(lifeCycle, activationSpec);
activateComponent(adaptor, activationSpec);
return adaptor;
} else if (bean instanceof MessageExchangeListener) {
// lets support just plain listener pojos
MessageExchangeListener listener = (MessageExchangeListener) bean;
Component adaptor = createComponentAdaptor(listener, activationSpec);
activateComponent(adaptor, activationSpec);
return adaptor;
} else {
throw new IllegalArgumentException("Component name: " + id
+ " is bound to an object which is not a JBI component, it is of type: " + bean.getClass().getName());
}
}
/**
* Activate a POJO Component
*
* @param component
* @param componentName
* @return the ObjectName of the MBean for the Component
* @throws JBIException
*/
public ObjectName activateComponent(Component component, String componentName) throws JBIException {
ActivationSpec activationSpec = new ActivationSpec();
ComponentNameSpace cns = new ComponentNameSpace(getName(), componentName);
activationSpec.setComponent(component);
activationSpec.setComponentName(cns.getName());
return activateComponent(component, activationSpec);
}
/**
* Activate A POJO Component
*
* @param component
* @param activationSpec
* @return the ObjectName of the MBean for the Component
* @throws JBIException
*/
public ObjectName activateComponent(Component component, ActivationSpec activationSpec) throws JBIException {
return activateComponent(component, "POJO Component", activationSpec, true, false, false, null);
}
/**
* Called by the Installer MBean
*
* @param installDir
* @param component
* @param description
* @param context
* @param binding
* @param service
* @return the ObjectName of the Component's MBean
* @throws JBIException
*/
public ObjectName activateComponent(File installDir, Component component, String description, ComponentContextImpl context,
boolean binding, boolean service, String[] sharedLibraries) throws JBIException {
ComponentNameSpace cns = context.getComponentNameSpace();
ActivationSpec activationSpec = new ActivationSpec();
activationSpec.setComponent(component);
activationSpec.setComponentName(cns.getName());
return activateComponent(installDir, component, description, context, activationSpec, false, binding, service, sharedLibraries);
}
/**
* @param component
* @param description
* @param activationSpec
* @param pojo
* @param binding
* @param service
* @return the ObjectName of the Component's MBean
* @throws JBIException
*/
public ObjectName activateComponent(Component component, String description, ActivationSpec activationSpec, boolean pojo,
boolean binding, boolean service, String[] sharedLibraries) throws JBIException {
ComponentNameSpace cns = new ComponentNameSpace(getName(), activationSpec.getComponentName());
if (registry.getComponent(cns) != null) {
throw new JBIException("A component is already registered for " + cns);
}
ComponentContextImpl context = new ComponentContextImpl(this, cns);
return activateComponent(new File("."), component, description, context, activationSpec, pojo, binding, service, sharedLibraries);
}
/**
* @param installationDir
* @param component
* @param description
* @param context
* @param activationSpec
* @param pojo
* @param binding
* @param service
* @return the ObjectName of the Component's MBean
* @throws JBIException
*/
public ObjectName activateComponent(File installationDir, Component component,
String description, ComponentContextImpl context,
ActivationSpec activationSpec, boolean pojo,
boolean binding, boolean service, String[] sharedLibraries) throws JBIException {
ObjectName result = null;
ComponentNameSpace cns = new ComponentNameSpace(getName(), activationSpec.getComponentName());
LOGGER.info("Activating component {}", cns);
ComponentMBeanImpl lcc = registry.registerComponent(cns, description, component, binding, service, sharedLibraries);
if (lcc != null) {
lcc.setPojo(pojo);
ComponentEnvironment env = environmentContext.registerComponent(context.getEnvironment(), lcc);
if (env.getInstallRoot() == null) {
env.setInstallRoot(installationDir);
}
context.activate(component, env, activationSpec);
lcc.setContext(context);
lcc.setActivationSpec(activationSpec);
if (lcc.isPojo()) {
//non-pojo's are either started by the auto deployer
//or manually
lcc.init();
} else {
lcc.doShutDown();
}
result = lcc.registerMBeans(managementContext);
// Start the component after mbeans have been registered
// This can be usefull if listeners use them
if (lcc.isPojo() && started.get()) {
lcc.start();
}
}
return result;
}
/**
* Allow the service and endpoint name to be configured from the registration, to reduce the amount of XML which is
* required to configure a ServiceMix component
*
* @param component
* @param activationSpec
*/
protected void defaultComponentServiceAndEndpoint(PojoSupport component, ActivationSpec activationSpec) {
if (activationSpec.getService() != null) {
component.setService(activationSpec.getService());
}
if (activationSpec.getEndpoint() != null) {
component.setEndpoint(activationSpec.getEndpoint());
}
}
protected ExecutorFactory createExecutorFactory() throws JBIException {
return getExecutorFactory() != null ? getExecutorFactory() : new org.apache.servicemix.executors.impl.ExecutorFactoryImpl();
}
/**
* Factory method to create a new component adaptor from the given lifecycle
*
* @param lifeCycle
* @param activationSpec
* @return Component
*/
protected Component createComponentAdaptor(ComponentLifeCycle lifeCycle, ActivationSpec activationSpec) {
ComponentAdaptor answer = null;
if (lifeCycle instanceof MessageExchangeListener) {
answer = new ComponentAdaptorMEListener(lifeCycle, activationSpec.getService(), activationSpec.getEndpoint(),
(MessageExchangeListener) lifeCycle);
} else {
answer = new ComponentAdaptor(lifeCycle, activationSpec.getService(), activationSpec.getEndpoint());
}
answer.setServiceManager(serviceManager);
return answer;
}
protected Component createComponentAdaptor(MessageExchangeListener listener, ActivationSpec activationSpec) {
ComponentLifeCycle lifecCycle = new PojoLifecycleAdaptor(listener, activationSpec.getService(), activationSpec.getEndpoint());
return new ComponentAdaptorMEListener(lifecCycle, listener);
}
/**
* Factory method to create a new component ID if none is specified
*
* @return uniqueId
*/
protected String createComponentID() {
return idGenerator.generateId();
}
protected void checkInitialized() throws JBIException {
if (!containerInitialized.get()) {
throw new JBIException("The Container is not initialized - please call init(...)");
}
}
/**
* Retrieve the value for automatic transaction enlistment.
*
* @return
*/
public boolean isAutoEnlistInTransaction() {
return autoEnlistInTransaction;
}
/**
* Set the new value for automatic transaction enlistment.
* When this parameter is set to <code>true</code> and a transaction
* is running when sending / receiving an exchange, this operation will
* automatically be done in the current transaction.
*
* @param autoEnlistInTransaction
*/
public void setAutoEnlistInTransaction(boolean autoEnlistInTransaction) {
this.autoEnlistInTransaction = autoEnlistInTransaction;
}
public boolean isPersistent() {
return persistent;
}
/**
* Set the new default value for exchange persistence.
* This value will be the default if none is configured on
* the activation spec of the component or on the message.
*
* @param persistent
*/
public void setPersistent(boolean persistent) {
this.persistent = persistent;
}
public void addListener(EventListener listener) {
LOGGER.debug("Adding listener: {}", listener.getClass());
if (listener instanceof ContainerAware) {
ContainerAware containerAware = (ContainerAware) listener;
containerAware.setContainer(this);
}
if (listener instanceof ExchangeListener) {
listeners.add(ExchangeListener.class, (ExchangeListener) listener);
}
if (listener instanceof ComponentListener) {
listeners.add(ComponentListener.class, (ComponentListener) listener);
}
if (listener instanceof ServiceAssemblyListener) {
listeners.add(ServiceAssemblyListener.class, (ServiceAssemblyListener) listener);
}
if (listener instanceof ServiceUnitListener) {
listeners.add(ServiceUnitListener.class, (ServiceUnitListener) listener);
}
if (listener instanceof EndpointListener) {
listeners.add(EndpointListener.class, (EndpointListener) listener);
}
if (listener instanceof DeploymentListener) {
listeners.add(DeploymentListener.class, (DeploymentListener) listener);
}
}
public void removeListener(EventListener listener) {
LOGGER.debug("Removing listener: {}", listener.getClass());
if (listener instanceof ExchangeListener) {
listeners.remove(ExchangeListener.class, (ExchangeListener) listener);
}
if (listener instanceof ComponentListener) {
listeners.remove(ComponentListener.class, (ComponentListener) listener);
}
if (listener instanceof ServiceAssemblyListener) {
listeners.remove(ServiceAssemblyListener.class, (ServiceAssemblyListener) listener);
}
if (listener instanceof ServiceUnitListener) {
listeners.remove(ServiceUnitListener.class, (ServiceUnitListener) listener);
}
if (listener instanceof EndpointListener) {
listeners.remove(EndpointListener.class, (EndpointListener) listener);
}
if (listener instanceof DeploymentListener) {
listeners.remove(DeploymentListener.class, (DeploymentListener) listener);
}
}
public Object[] getListeners(Class lc) {
return listeners.getListeners(lc);
}
public void setListeners(EventListener[] listeners) {
configuredListeners = listeners;
}
public void resendExchange(MessageExchange exchange) throws JBIException {
if (!(exchange instanceof MessageExchangeImpl)) {
throw new IllegalArgumentException("exchange should be a MessageExchangeImpl");
}
MessageExchangeImpl me = (MessageExchangeImpl) exchange;
me.getPacket().setExchangeId(new IdGenerator().generateId());
me.getPacket().setOut(null);
me.getPacket().setFault(null);
me.getPacket().setError(null);
me.getPacket().setStatus(ExchangeStatus.ACTIVE);
me.getPacket().setProperty(JbiConstants.DATESTAMP_PROPERTY_NAME, Calendar.getInstance());
ExchangeListener[] l = (ExchangeListener[]) listeners.getListeners(ExchangeListener.class);
ExchangeEvent event = new ExchangeEvent(me, ExchangeEvent.EXCHANGE_SENT);
for (int i = 0; i < l.length; i++) {
try {
l[i].exchangeSent(event);
} catch (Exception e) {
LOGGER.warn("Error calling listener: {}", e.getMessage(), e);
}
}
me.handleSend(false);
sendExchange(me.getMirror());
}
public boolean isEmbedded() {
return embedded;
}
public void setEmbedded(boolean embedded) {
this.embedded = embedded;
}
public void setRmiPort(int portNum) {
getManagementContext().setNamingPort(portNum);
}
public int getRmiPort() {
return getManagementContext().getNamingPort();
}
/**
* @return Returns the notifyStatistics.
*/
public boolean isNotifyStatistics() {
return notifyStatistics;
}
/**
* @param notifyStatistics The notifyStatistics to set.
*/
public void setNotifyStatistics(boolean notifyStatistics) {
this.notifyStatistics = notifyStatistics;
}
/**
* @return the executorFactory
*/
public ExecutorFactory getExecutorFactory() {
return executorFactory;
}
/**
* @param executorFactory the executorFactory to set
*/
public void setExecutorFactory(ExecutorFactory executorFactory) {
this.executorFactory = executorFactory;
if (this.executorFactory != null && this.executorFactory instanceof org.apache.servicemix.executors.impl.ExecutorFactoryImpl) {
((org.apache.servicemix.executors.impl.ExecutorFactoryImpl) this.executorFactory).setMbeanServer(getMBeanServer());
}
}
/**
* Creates a new rootDir
*/
protected String createRootDir() {
String prefix = getGeneratedRootDirPrefix();
for (int i = 1; true; i++) {
File file = new File(prefix + i);
if (!file.exists()) {
file.mkdirs();
return file.getAbsolutePath();
}
}
}
public boolean isOptimizedDelivery() {
return optimizedDelivery;
}
public void setOptimizedDelivery(boolean optimizedDelivery) {
this.optimizedDelivery = optimizedDelivery;
}
}