/* * Copyright (c) 2005-2014, 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.inbound.endpoint.common; 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.SynapseConstants; import org.apache.synapse.core.SynapseEnvironment; import org.apache.synapse.inbound.InboundRequestProcessor; import org.apache.synapse.startup.quartz.StartUpController; import org.apache.synapse.task.Task; import org.apache.synapse.task.TaskDescription; import org.wso2.carbon.CarbonConstants; import org.wso2.carbon.base.MultitenantConstants; import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.inbound.endpoint.osgi.service.ServiceReferenceHolder; import org.wso2.carbon.inbound.endpoint.persistence.InboundEndpointsDataStore; import org.wso2.carbon.inbound.endpoint.protocol.PollingConstants; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.*; /** * * This class provides the common implementation for polling protocol processors * */ public abstract class InboundRequestProcessorImpl implements InboundRequestProcessor { protected SynapseEnvironment synapseEnvironment; protected long interval; protected String name; protected boolean coordination; private List<StartUpController> startUpControllersList = new ArrayList<>(); private HashMap<Thread, InboundRunner> inboundRunnersThreadsMap = new HashMap<>(); private static final Log log = LogFactory.getLog(InboundRequestProcessorImpl.class); private InboundEndpointsDataStore dataStore; protected final static String COMMON_ENDPOINT_POSTFIX = "--SYNAPSE_INBOUND_ENDPOINT"; public InboundRequestProcessorImpl(){ dataStore = InboundEndpointsDataStore.getInstance(); } /** * * Based on the coordination option schedule the task with NTASK or run as a * background thread * * @param task * @param endpointPostfix */ protected void start(InboundTask task, String endpointPostfix) { log.info("Starting the inbound endpoint " + name + ", with coordination " + coordination + ". Interval : " + interval + ". Type : " + endpointPostfix); if (coordination) { try { TaskDescription taskDescription = new TaskDescription(); taskDescription.setName(name + "-" + endpointPostfix); taskDescription.setTaskGroup(endpointPostfix); if (interval < InboundTask.TASK_THRESHOLD_INTERVAL) { taskDescription.setInterval(InboundTask.TASK_THRESHOLD_INTERVAL); } else { taskDescription.setInterval(interval); } taskDescription.setIntervalInMs(true); taskDescription.addResource(TaskDescription.INSTANCE, task); taskDescription.addResource(TaskDescription.CLASSNAME, task.getClass().getName()); StartUpController startUpController = new StartUpController(); startUpController.setTaskDescription(taskDescription); startUpController.init(synapseEnvironment); startUpControllersList.add(startUpController); } catch (Exception e) { log.error("Error starting the inbound endpoint " + name + ". Unable to schedule the task. " + e.getLocalizedMessage(), e); } } else { PrivilegedCarbonContext carbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext(); int tenantId = carbonContext.getTenantId(); String tenantDomain = null; if (tenantId != MultitenantConstants.SUPER_TENANT_ID) { tenantDomain = carbonContext.getTenantDomain(); if(!dataStore.isPollingEndpointRegistered(tenantDomain, name)){ dataStore.registerPollingingEndpoint(tenantDomain, name); } } // When coordination is false, we sometimes require pinned server concept ex: when clustering // is not available. if (isPinnedServerEnabled(task.getInboundProperties())) { if (isPinnedServer(task.getInboundProperties())) { startInboundRunnerThread(task, tenantDomain, true); } else { log.info("Inbound Endpoint " + name + " not started as it is not pinned to this server"); } } else { startInboundRunnerThread(task, tenantDomain, false); } } } private void startInboundRunnerThread(InboundTask task, String tenantDomain, boolean mgrOverride) { InboundRunner inboundRunner = new InboundRunner(task, interval, tenantDomain, mgrOverride); Thread runningThread = new Thread(inboundRunner); inboundRunnersThreadsMap.put(runningThread, inboundRunner); runningThread.start(); } /** * Stop the inbound polling processor This will be called when inbound is * undeployed/redeployed or when server stop */ public void destroy() { log.info("Inbound endpoint " + name + " stopping."); PrivilegedCarbonContext carbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext(); int tenantId = carbonContext.getTenantId(); if(tenantId != MultitenantConstants.SUPER_TENANT_ID){ dataStore.unregisterPollingEndpoint(carbonContext.getTenantDomain(), name); } if (!startUpControllersList.isEmpty()) { for (StartUpController sc : startUpControllersList) { sc.destroy(); } startUpControllersList.clear(); } else if (!inboundRunnersThreadsMap.isEmpty()) { Iterator itr = inboundRunnersThreadsMap.entrySet().iterator(); while (itr.hasNext()) { Map.Entry entry = (Map.Entry)itr.next(); Thread thread = (Thread)entry.getKey(); InboundRunner inboundRunner = (InboundRunner)entry.getValue(); inboundRunner.terminate(); try { thread.join(); } catch (InterruptedException e) { log.error("Error while stopping the inbound thread."); } } inboundRunnersThreadsMap.clear(); } } protected static boolean isPinnedServerEnabled(Properties inboundProperties) { if (inboundProperties != null && inboundProperties.getProperty(PollingConstants.INBOUND_PINNED_SERVER) != null) { return true; } return false; } protected boolean isPinnedServer(Properties inboundProperties) { String thisServerName = System.getProperty("pinServerName", null); if (thisServerName == null || "".equals(thisServerName)) { thisServerName = getAxis2ParameterValue(ServiceReferenceHolder.getInstance() .getConfigurationContextService().getServerConfigContext().getAxisConfiguration(), SynapseConstants.Axis2Param.SYNAPSE_SERVER_NAME); if (thisServerName == null || "".equals(thisServerName)) { thisServerName = System.getProperty("SynapseServerName", null); if (thisServerName == null || "".equals(thisServerName)) { thisServerName = getServerHost(); if (thisServerName == null || "".equals(thisServerName)) { thisServerName = "localhost"; } } } } String pinnedServersValue = inboundProperties.getProperty( PollingConstants.INBOUND_PINNED_SERVER, null); List<String> pinnedServers = getPinnedServers(pinnedServersValue); if (pinnedServers != null && !pinnedServers.isEmpty()) { if (pinnedServers.contains(thisServerName)) { return true; } } return false; } /** * Helper method to get a value of a parameters in the AxisConfiguration * * @param axisConfiguration AxisConfiguration instance * @param paramKey The name / key of the parameter * @return The value of the parameter */ private static String getAxis2ParameterValue(AxisConfiguration axisConfiguration, String paramKey) { Parameter parameter = axisConfiguration.getParameter(paramKey); if (parameter == null) { return null; } Object value = parameter.getValue(); if (value != null && value instanceof String) { return (String) parameter.getValue(); } else { return null; } } private List<String> getPinnedServers(String pinnedServersValue) { StringTokenizer st = new StringTokenizer(pinnedServersValue, " ,"); List<String> pinnedServersList = new ArrayList<String>(); while (st.hasMoreTokens()) { String token = st.nextToken(); if (token.length() != 0) { pinnedServersList.add(token); } } return pinnedServersList; } private String getServerHost() { try { InetAddress addr = InetAddress.getLocalHost(); if (addr != null) { return addr.getHostName(); } } catch (UnknownHostException e) { log.warn("Unable to get the hostName or IP address of the server", e); } return null; } }