/* * Copyright (c) 2005-2008, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. 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.wso2.carbon.mediation.initializer.multitenancy; import org.apache.axis2.AxisFault; import org.apache.axis2.context.ConfigurationContext; import org.apache.axis2.deployment.DeploymentEngine; import org.apache.axis2.description.AxisServiceGroup; import org.apache.axis2.description.Parameter; import org.apache.axis2.engine.AxisConfiguration; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.synapse.ServerConfigurationInformation; import org.apache.synapse.ServerConfigurationInformationFactory; import org.apache.synapse.ServerContextInformation; import org.apache.synapse.ServerManager; import org.apache.synapse.SynapseConstants; import org.apache.synapse.config.SynapseConfiguration; import org.apache.synapse.config.SynapseConfigurationBuilder; import org.apache.synapse.config.xml.MultiXMLConfigurationBuilder; import org.apache.synapse.config.xml.MultiXMLConfigurationSerializer; import org.apache.synapse.core.SynapseEnvironment; import org.apache.synapse.debug.SynapseDebugInterface; import org.apache.synapse.debug.SynapseDebugManager; import org.apache.synapse.deployers.ExtensionDeployer; import org.apache.synapse.deployers.InboundEndpointDeployer; import org.apache.synapse.deployers.SynapseArtifactDeploymentStore; import org.apache.synapse.inbound.InboundEndpoint; import org.apache.synapse.mediators.base.SequenceMediator; import org.apache.synapse.registry.Registry; import org.apache.synapse.task.TaskConstants; import org.apache.synapse.task.TaskDescriptionRepository; import org.apache.synapse.task.TaskManager; import org.apache.synapse.task.TaskScheduler; import org.osgi.framework.ServiceRegistration; import org.wso2.carbon.base.ServerConfiguration; import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.context.RegistryType; import org.wso2.carbon.event.core.EventBroker; import org.wso2.carbon.mediation.dependency.mgt.services.ConfigurationTrackingService; import org.wso2.carbon.mediation.initializer.CarbonSynapseController; import org.wso2.carbon.mediation.initializer.ServiceBusConstants; import org.wso2.carbon.mediation.initializer.ServiceBusInitializer; import org.wso2.carbon.mediation.initializer.ServiceBusUtils; import org.wso2.carbon.mediation.initializer.configurations.ConfigurationManager; import org.wso2.carbon.mediation.initializer.handler.SynapseExternalPropertyConfigurator; import org.wso2.carbon.mediation.initializer.persistence.MediationPersistenceManager; import org.wso2.carbon.mediation.initializer.services.SynapseConfigurationService; import org.wso2.carbon.mediation.initializer.services.SynapseConfigurationServiceImpl; import org.wso2.carbon.mediation.initializer.services.SynapseEnvironmentService; import org.wso2.carbon.mediation.initializer.services.SynapseEnvironmentServiceImpl; import org.wso2.carbon.mediation.initializer.services.SynapseRegistrationsService; import org.wso2.carbon.mediation.initializer.services.SynapseRegistrationsServiceImpl; import org.wso2.carbon.mediation.initializer.utils.ConfigurationHolder; import org.wso2.carbon.mediation.ntask.NTaskTaskManager; import org.wso2.carbon.mediation.registry.WSO2Registry; import org.wso2.carbon.registry.core.exceptions.RegistryException; import org.wso2.carbon.registry.core.session.UserRegistry; import org.wso2.carbon.utils.AbstractAxis2ConfigurationContextObserver; import org.wso2.carbon.utils.CarbonUtils; import org.wso2.carbon.utils.ServerConstants; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.file.Paths; import java.util.Properties; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * This creates the {@link org.apache.synapse.config.SynapseConfiguration} * for the respective tenants. */ public class TenantServiceBusInitializer extends AbstractAxis2ConfigurationContextObserver { private static final Log log = LogFactory.getLog(TenantServiceBusInitializer.class); // private Map<Integer, ServiceRegistration> tenantRegistrations = // new HashMap<Integer, ServiceRegistration>(); public void createdConfigurationContext(ConfigurationContext configurationContext) { ServerContextInformation contextInfo; String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); log.info("Intializing the ESB Configuration for the tenant domain : " + tenantDomain); try { // first check which configuration should be active org.wso2.carbon.registry.core.Registry registry = (org.wso2.carbon.registry.core.Registry) PrivilegedCarbonContext .getThreadLocalCarbonContext(). getRegistry(RegistryType.SYSTEM_CONFIGURATION); AxisConfiguration axisConfig = configurationContext.getAxisConfiguration(); // initialize the lock Lock lock = new ReentrantLock(); axisConfig.addParameter(ServiceBusConstants.SYNAPSE_CONFIG_LOCK, lock); // creates the synapse configuration directory hierarchy if not exists // useful at the initial tenant creation File tenantAxis2Repo = new File( configurationContext.getAxisConfiguration().getRepository().getFile()); File synapseConfigsDir = new File(tenantAxis2Repo, ServiceBusConstants.SYNAPSE_CONFIGS); if (!synapseConfigsDir.exists()) { if (!synapseConfigsDir.mkdir()) { log.fatal("Couldn't create the synapse-config root on the file system " + "for the tenant domain : " + tenantDomain); return; } } String synapseConfigsDirLocation = synapseConfigsDir.getAbsolutePath(); // set the required configuration parameters to initialize the ESB axisConfig.addParameter(SynapseConstants.Axis2Param.SYNAPSE_CONFIG_LOCATION, synapseConfigsDirLocation); // init the multiple configuration tracker ConfigurationManager manger = new ConfigurationManager((UserRegistry) registry, configurationContext); manger.init(); File synapseConfigDir = new File(synapseConfigsDir, manger.getTracker().getCurrentConfigurationName()); if (!synapseConfigDir.exists()) { createTenantSynapseConfigHierarchy(synapseConfigDir, tenantDomain); } axisConfig.addParameter(SynapseConstants.Axis2Param.SYNAPSE_HOME, tenantAxis2Repo.getAbsolutePath()); axisConfig.addParameter(SynapseConstants.Axis2Param.SYNAPSE_SERVER_NAME, "synapse." + tenantDomain); axisConfig.addParameter(SynapseConstants.Axis2Param.SYNAPSE_RESOLVE_ROOT, tenantAxis2Repo.getAbsolutePath()); // Initialize Synapse contextInfo = initESB(manger.getTracker().getCurrentConfigurationName(), configurationContext,tenantDomain); if (contextInfo == null) { handleFatal("Failed to intilize the ESB for tenent:" + tenantDomain); } initPersistence(manger.getTracker().getCurrentConfigurationName(), configurationContext, contextInfo); configurationContext.setProperty( ConfigurationManager.CONFIGURATION_MANAGER, manger); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); // populate the SynapseEnv service and SynapseConfig OSGI Services so that other // components get to know about the availability of the new synapse configuration //Properties props = new Properties(); SynapseConfigurationService synCfgSvc = new SynapseConfigurationServiceImpl(contextInfo.getSynapseConfiguration(), tenantId, configurationContext); ServiceRegistration confRegistration = ConfigurationHolder.getInstance().getBundleContext().registerService( SynapseConfigurationService.class.getName(), synCfgSvc, null); SynapseEnvironment synapseEnvironment = contextInfo.getSynapseEnvironment(); //props = new Properties(); SynapseEnvironmentService synEnvSvc = new SynapseEnvironmentServiceImpl(synapseEnvironment, tenantId, configurationContext); ServiceRegistration envRegistration = ConfigurationHolder.getInstance().getBundleContext().registerService( SynapseEnvironmentService.class.getName(), synEnvSvc, null); synapseEnvironment.registerSynapseHandler(new SynapseExternalPropertyConfigurator()); //props = new Properties(); SynapseRegistrationsService synRegistrationsSvc = new SynapseRegistrationsServiceImpl( confRegistration, envRegistration, tenantId, configurationContext); ServiceRegistration synapseRegistration = ConfigurationHolder.getInstance().getBundleContext().registerService( SynapseRegistrationsService.class.getName(), synRegistrationsSvc, null); //creating secure-vault specific location if (!isRepoExists(registry)) { org.wso2.carbon.registry.core.Collection secureVaultCollection = registry .newCollection(); registry.put(ServiceBusConstants.CONNECTOR_SECURE_VAULT_CONFIG_REPOSITORY, secureVaultCollection); } ConfigurationTrackingService trackingService = ServiceBusInitializer. getConfigurationTrackingService(); if (trackingService != null) { trackingService.setSynapseConfiguration(contextInfo.getSynapseConfiguration()); } // set the event broker as a property for tenants EventBroker eventBroker = ServiceBusInitializer.getEventBroker(); if (eventBroker != null) { configurationContext.setProperty("mediation.event.broker", eventBroker); } ConfigurationHolder.getInstance().addSynapseRegistration(tenantId, synapseRegistration); registerInboundDeployer(axisConfig, contextInfo.getSynapseEnvironment()); } catch (Exception e) { handleFatal("Couldn't initialize the ESB for tenant:" + tenantDomain, e); } catch (Throwable t) { log.fatal("Failed to initialize ESB for tenant:" + tenantDomain + "due to a fatal error", t); } } /** * Register for inbound hot depoyment * */ private void registerInboundDeployer(AxisConfiguration axisConfig, SynapseEnvironment synEnv) { DeploymentEngine deploymentEngine = (DeploymentEngine) axisConfig .getConfigurator(); SynapseArtifactDeploymentStore deploymentStore = synEnv .getSynapseConfiguration().getArtifactDeploymentStore(); String synapseConfigPath = ServiceBusUtils .getSynapseConfigAbsPath(synEnv.getServerContextInformation()); String inboundDirPath = synapseConfigPath + File.separator + MultiXMLConfigurationBuilder.INBOUND_ENDPOINT_DIR; for (InboundEndpoint inboundEndpoint : synEnv.getSynapseConfiguration() .getInboundEndpoints()) { if (inboundEndpoint.getFileName() != null) { deploymentStore.addRestoredArtifact(inboundDirPath + File.separator + inboundEndpoint.getFileName()); } } deploymentEngine.addDeployer(new InboundEndpointDeployer(), inboundDirPath, ServiceBusConstants.ARTIFACT_EXTENSION); } public void terminatingConfigurationContext(ConfigurationContext configurationContext) { String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); log.info("Shutting down the persistence manager for the tenant: " + tenantDomain); Parameter p = configurationContext.getAxisConfiguration().getParameter( ServiceBusConstants.PERSISTENCE_MANAGER); if (p != null && p.getValue() instanceof MediationPersistenceManager) { ((MediationPersistenceManager) p.getValue()).destroy(); } // unregister the service so that components get to know about the tenant termination int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); ServiceRegistration tenantRegistration = ConfigurationHolder.getInstance(). getSynapseRegistration(tenantId); if (tenantRegistration != null) { ConfigurationHolder.getInstance().getBundleContext().ungetService( tenantRegistration.getReference()); } } private void initPersistence(String configName, ConfigurationContext configurationContext, ServerContextInformation contextInfo) throws RegistryException, AxisFault { // Initialize the mediation persistence manager if required ServerConfiguration serverConf = ServerConfiguration.getInstance(); String persistence = serverConf.getFirstProperty(ServiceBusConstants.PERSISTENCE); org.wso2.carbon.registry.core.Registry configRegistry = (org.wso2.carbon.registry.core.Registry) PrivilegedCarbonContext .getThreadLocalCarbonContext(). getRegistry(RegistryType.SYSTEM_CONFIGURATION); // Check whether persistence is disabled if (!ServiceBusConstants.DISABLED.equals(persistence)) { // Check registry persistence is disabled or not String regPersistence = serverConf.getFirstProperty( ServiceBusConstants.REGISTRY_PERSISTENCE); UserRegistry registry = ServiceBusConstants.ENABLED.equals(regPersistence) ? (UserRegistry) configRegistry : null; // Check the worker interval is set or not String interval = serverConf.getFirstProperty(ServiceBusConstants.WORKER_INTERVAL); long intervalInMillis = 5000L; if (interval != null && !"".equals(interval)) { try { intervalInMillis = Long.parseLong(interval); } catch (NumberFormatException e) { log.error("Invalid value " + interval + " specified for the mediation " + "persistence worker interval, Using defaults", e); } } MediationPersistenceManager pm = new MediationPersistenceManager(registry, contextInfo.getServerConfigurationInformation().getSynapseXMLLocation(), contextInfo.getSynapseConfiguration(), intervalInMillis, configName); configurationContext.getAxisConfiguration().addParameter( new Parameter(ServiceBusConstants.PERSISTENCE_MANAGER, pm)); } else { log.info("Persistence for mediation configuration is disabled"); } } private ServerContextInformation initESB(String configurationName, ConfigurationContext configurationContext, String tenantDomain) throws AxisFault { ServerConfigurationInformation configurationInformation = ServerConfigurationInformationFactory.createServerConfigurationInformation( configurationContext.getAxisConfiguration()); // ability to specify the SynapseServerName as a system property if (System.getProperty("SynapseServerName") != null) { configurationInformation.setServerName(System.getProperty("SynapseServerName")); } // for now we override the default configuration location with the value in registry configurationInformation.setSynapseXMLLocation( configurationInformation.getSynapseXMLLocation() + File.separator + configurationName); configurationInformation.setCreateNewInstance(false); configurationInformation.setServerControllerProvider( CarbonSynapseController.class.getName()); if (isRunningSamplesMode()) { configurationInformation.setSynapseXMLLocation("repository" + File.separator + "samples" + File.separator + "synapse_sample_" + System.getProperty( ServiceBusConstants.ESB_SAMPLE_SYSTEM_PROPERTY) + ".xml"); } ServerManager serverManager = new ServerManager(); ServerContextInformation contextInfo = new ServerContextInformation(configurationContext, configurationInformation); /*if (dataSourceInformationRepositoryService != null) { DataSourceInformationRepository repository = dataSourceInformationRepositoryService.getDataSourceInformationRepository(); contextInfo.addProperty(DataSourceConstants.DATA_SOURCE_INFORMATION_REPOSITORY, repository); }*/ TaskScheduler scheduler; if (configurationContext.getProperty(ServiceBusConstants.CARBON_TASK_SCHEDULER) == null) { scheduler = new TaskScheduler(TaskConstants.TASK_SCHEDULER); configurationContext.setProperty(ServiceBusConstants.CARBON_TASK_SCHEDULER, scheduler); } else { scheduler = (TaskScheduler) configurationContext.getProperty( ServiceBusConstants.CARBON_TASK_SCHEDULER); } contextInfo.addProperty(TaskConstants.TASK_SCHEDULER, scheduler); TaskDescriptionRepository repository; if (configurationContext.getProperty(ServiceBusConstants.CARBON_TASK_REPOSITORY) == null) { repository = new TaskDescriptionRepository(); configurationContext.setProperty( ServiceBusConstants.CARBON_TASK_REPOSITORY, repository); } else { repository = (TaskDescriptionRepository) configurationContext .getProperty(ServiceBusConstants.CARBON_TASK_REPOSITORY); } contextInfo.addProperty(TaskConstants.TASK_DESCRIPTION_REPOSITORY, repository); /* if (secretCallbackHandlerService != null) { contextInfo.addProperty(SecurityConstants.PROP_SECRET_CALLBACK_HANDLER, secretCallbackHandlerService.getSecretCallbackHandler()); }*/ AxisConfiguration axisConf = configurationContext.getAxisConfiguration(); axisConf.addParameter(new Parameter( ServiceBusConstants.SYNAPSE_CURRENT_CONFIGURATION, configurationName)); if (isRunningDebugMode(tenantDomain)) { log.info("ESB Started in Debug mode for " + tenantDomain); createSynapseDebugEnvironment(contextInfo); } serverManager.init(configurationInformation, contextInfo); serverManager.start(); AxisServiceGroup serviceGroup = axisConf.getServiceGroup( SynapseConstants.SYNAPSE_SERVICE_NAME); serviceGroup.addParameter("hiddenService", "true"); addDeployers(configurationContext,contextInfo); return contextInfo; } /** * Create the file system for holding the synapse configuration for a new tanent. * @param synapseConfigDir configuration directory where synapse configuration is created * @param tenantDomain name of the tenent */ @SuppressWarnings({"ResultOfMethodCallIgnored"}) private void createTenantSynapseConfigHierarchy(File synapseConfigDir, String tenantDomain) { if (!synapseConfigDir.mkdir()) { log.fatal("Couldn't create the synapse-config root on the file system " + "for the tenant domain : " + tenantDomain); return; } File sequencesDir = new File( synapseConfigDir, MultiXMLConfigurationBuilder.SEQUENCES_DIR); File endpointsDir = new File( synapseConfigDir, MultiXMLConfigurationBuilder.ENDPOINTS_DIR); File entriesDir = new File( synapseConfigDir, MultiXMLConfigurationBuilder.LOCAL_ENTRY_DIR); File proxyServicesDir = new File( synapseConfigDir, MultiXMLConfigurationBuilder.PROXY_SERVICES_DIR); File eventSourcesDir = new File( synapseConfigDir, MultiXMLConfigurationBuilder.EVENTS_DIR); File tasksDir = new File( synapseConfigDir, MultiXMLConfigurationBuilder.TASKS_DIR); File executorsDir = new File( synapseConfigDir, MultiXMLConfigurationBuilder.EXECUTORS_DIR); if(!sequencesDir.mkdir()) { log.warn("Could not create " + sequencesDir); } if(!endpointsDir.mkdir()) { log.warn("Could not create " + endpointsDir); } if(!entriesDir.mkdir()) { log.warn("Could not create " + entriesDir); } if(!proxyServicesDir.mkdir()) { log.warn("Could not create " + proxyServicesDir); } if(!eventSourcesDir.mkdir()) { log.warn("Could not create " + eventSourcesDir); } if(!tasksDir.mkdir()) { log.warn("Could not create " + tasksDir); } if(!executorsDir.mkdir()) { log.warn("Could not create " + executorsDir); } SynapseConfiguration initialSynCfg = SynapseConfigurationBuilder.getDefaultConfiguration(); SequenceMediator mainSequence = (SequenceMediator) initialSynCfg.getMainSequence(); SequenceMediator faultSequence = (SequenceMediator) initialSynCfg.getFaultSequence(); mainSequence.setFileName(SynapseConstants.MAIN_SEQUENCE_KEY + ".xml"); faultSequence.setFileName(SynapseConstants.FAULT_SEQUENCE_KEY + ".xml"); Registry registry = new WSO2Registry(); registry.getConfigurationProperties().setProperty("cachableDuration", "1500"); initialSynCfg.setRegistry(registry); //Add the default NTask Manager to config TaskManager taskManager = new NTaskTaskManager(); initialSynCfg.setTaskManager(taskManager); MultiXMLConfigurationSerializer serializer = new MultiXMLConfigurationSerializer(synapseConfigDir.getAbsolutePath()); try { serializer.serializeSequence(mainSequence, initialSynCfg, null); serializer.serializeSequence(faultSequence, initialSynCfg, null); serializer.serializeSynapseRegistry(registry, initialSynCfg, null); serializer.serializeSynapseXML(initialSynCfg); } catch (Exception e) { handleException("Couldn't serialise the initial synapse configuration " + "for the domain : " + tenantDomain, e); } } private void addDeployers(ConfigurationContext configurationContext,ServerContextInformation contextInfo) { AxisConfiguration axisConfig = configurationContext.getAxisConfiguration(); synchronized (axisConfig) { DeploymentEngine deploymentEngine = (DeploymentEngine) axisConfig.getConfigurator(); String carbonRepoPath = configurationContext.getAxisConfiguration().getRepository().getFile(); String mediatorsPath = carbonRepoPath + File.separator + "mediators"; String extensionsPath = carbonRepoPath + File.separator + "extensions"; ExtensionDeployer deployer = new ExtensionDeployer(); deploymentEngine.addDeployer(deployer, mediatorsPath, "xar"); deploymentEngine.addDeployer(deployer, extensionsPath, "xar"); deploymentEngine.addDeployer(deployer, mediatorsPath, "jar"); deploymentEngine.addDeployer(deployer, extensionsPath, "jar"); } } /** * creates Synapse debug environment * creates TCP channels using command and event ports which initializes the interface to outer debugger * set the relevant information in the server configuration so that it can be used when Synapse environment * initializes * * @param contextInfo Server Context Information */ public void createSynapseDebugEnvironment(ServerContextInformation contextInfo) { try { File synapseProperties = Paths.get(CarbonUtils.getCarbonConfigDirPath(), "synapse.properties").toFile(); Properties properties = new Properties(); InputStream inputStream = new FileInputStream(synapseProperties); properties.load(inputStream); inputStream.close(); int event_port = Integer.parseInt(properties.getProperty(ServiceBusConstants.ESB_DEBUG_EVENT_PORT)); int command_port = Integer.parseInt(properties.getProperty(ServiceBusConstants.ESB_DEBUG_COMMAND_PORT)); SynapseDebugInterface debugInterface = SynapseDebugInterface.getInstance(); debugInterface.init(command_port, event_port); contextInfo.setServerDebugModeEnabled(true); contextInfo.setSynapseDebugInterface(debugInterface); SynapseDebugManager debugManager = SynapseDebugManager.getInstance(); contextInfo.setSynapseDebugManager(debugManager); log.info("Synapse debug Environment created successfully"); } catch (IOException ex) { log.error("Error while creating Synapse debug environment ", ex); } catch (InterruptedException ex) { log.error("Error while creating Synapse debug environment ", ex); } } /** * Checks whether the given repository already existing. * * @return */ protected boolean isRepoExists(org.wso2.carbon.registry.core.Registry registry) { try { registry.get(ServiceBusConstants.CONNECTOR_SECURE_VAULT_CONFIG_REPOSITORY); } catch (RegistryException e) { return false; } return true; } public boolean isRunningDebugMode(String tenantDomain) { if (tenantDomain == null) { return false; } return tenantDomain.equals(System.getProperty(ServiceBusConstants.ESB_DEBUG_SYSTEM_PROPERTY)); } public String getProviderClass() { return this.getClass().getName(); } public static boolean isRunningSamplesMode() { return System.getProperty(ServiceBusConstants.ESB_SAMPLE_SYSTEM_PROPERTY) != null; } private void handleFatal(String message) { log.fatal(message); } private void handleFatal(String message, Exception e) { log.fatal(message, e); } private void handleException(String message, Exception e) { log.error(message, e); } }