/* * 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.apache.synapse.inbound; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.synapse.ManagedLifecycle; import org.apache.synapse.SynapseException; import org.apache.synapse.aspects.AspectConfigurable; import org.apache.synapse.aspects.AspectConfiguration; import org.apache.synapse.aspects.ComponentType; import org.apache.synapse.aspects.flow.statistics.StatisticIdentityGenerator; import org.apache.synapse.aspects.flow.statistics.data.artifact.ArtifactHolder; import org.apache.synapse.core.SynapseEnvironment; import org.apache.synapse.mediators.Value; import org.apache.synapse.util.xpath.SynapseXPath; import org.jaxen.JaxenException; import sun.misc.Service; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; import java.util.Properties; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Entity which is responsible for exposing ESB message flow as an endpoint which can be invoked * by Clients. InboundEndpoint is an artifact type which can be created/modified dynamically. */ public class InboundEndpoint implements AspectConfigurable, ManagedLifecycle { protected static final Log log = LogFactory.getLog(InboundEndpoint.class); private String name; private String protocol; private String classImpl; private boolean isSuspend; private String injectingSeq; private String onErrorSeq; private Map<String, String> parametersMap = new LinkedHashMap<String, String>(); private Map<String, String> parameterKeyMap = new LinkedHashMap<String, String>(); private String fileName; private SynapseEnvironment synapseEnvironment; private InboundRequestProcessor inboundRequestProcessor; /** car file name which this endpoint deployed from */ private String artifactContainerName; /** Whether the deployed inbound endpoint is edited via the management console */ private boolean isEdited; private AspectConfiguration aspectConfiguration; /** regex for secure vault expression */ private static final String secureVaultRegex = "\\{wso2:vault-lookup\\('(.*?)'\\)\\}"; public void init(SynapseEnvironment se) { log.info("Initializing Inbound Endpoint: " + getName()); synapseEnvironment = se; if(isSuspend){ log.info("Inbound endpoint " + name + " is currently suspended."); return; } inboundRequestProcessor = getInboundRequestProcessor(); if (inboundRequestProcessor != null) { try { inboundRequestProcessor.init(); } catch (Exception e) { String msg = "Error initializing inbound endpoint " + getName(); log.error(msg); throw new SynapseException(msg,e); } } else { String msg = "Inbound Request processor not found for Inbound EP : " + name + " Protocol: " + protocol + " Class" + classImpl; log.error(msg); throw new SynapseException(msg); } } /** * Get plug-able InboundRequest processors from the classpath * <p/> * This looks for JAR files containing a META-INF/services that adheres to the following * http://docs.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html * * @return InboundRequest processor */ private InboundRequestProcessor getInboundRequestProcessor() { if (log.isDebugEnabled()) { log.debug("Trying to fetch InboundRequestProcessor from classpath.. "); } Iterator<InboundRequestProcessorFactory> it = Service.providers(InboundRequestProcessorFactory.class); InboundProcessorParams params = populateParams(); while (it.hasNext()) { InboundRequestProcessorFactory factory = it.next(); InboundRequestProcessor inboundRequestProcessor = factory.createInboundProcessor(params); if (inboundRequestProcessor != null) { if (log.isDebugEnabled()) { log.debug("Inbound Request Processor found in factory : " + factory.getClass().getName()); } return inboundRequestProcessor; } } return null; } /** * Populate inbound processor parameters and create object which holds parameters * * @return entity holding InboundProcessorParams */ private InboundProcessorParams populateParams() { InboundProcessorParams inboundProcessorParams = new InboundProcessorParams(); inboundProcessorParams.setProtocol(protocol); inboundProcessorParams.setClassImpl(classImpl); inboundProcessorParams.setName(name); inboundProcessorParams.setInjectingSeq(injectingSeq); inboundProcessorParams.setOnErrorSeq(onErrorSeq); inboundProcessorParams.setSynapseEnvironment(synapseEnvironment); Properties props = Utils.paramsToProperties(parametersMap); //replacing values by secure vault resolveSecureVaultExpressions(props); inboundProcessorParams.setProperties(props); return inboundProcessorParams; } public void destroy() { log.info("Destroying Inbound Endpoint: " + getName()); if (inboundRequestProcessor != null) { inboundRequestProcessor.destroy(); } } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getProtocol() { return protocol; } public void setProtocol(String protocol) { this.protocol = protocol; } public boolean isSuspend() { return isSuspend; } public void setSuspend(boolean isSuspend) { this.isSuspend = isSuspend; } public String getInjectingSeq() { return injectingSeq; } public void setInjectingSeq(String injectingSeq) { this.injectingSeq = injectingSeq; } public String getOnErrorSeq() { return onErrorSeq; } public void setOnErrorSeq(String onErrorSeq) { this.onErrorSeq = onErrorSeq; } public String getFileName() { return fileName; } public void setFileName(String fileName) { this.fileName = fileName; } public Map<String, String> getParametersMap() { return parametersMap; } public void addParameter(String name, String value) { parametersMap.put(name, value); } public void addParameter(String name, String value, String key) { addParameter(name, value); parameterKeyMap.put(name, key); } public String getParameter(String name) { return parametersMap.get(name); } public String getParameterKey(String name) { return parameterKeyMap.get(name); } public String getClassImpl() { return classImpl; } public void setClassImpl(String classImpl) { this.classImpl = classImpl; } public void setArtifactContainerName (String name) { artifactContainerName = name; } public String getArtifactContainerName () { return artifactContainerName; } public boolean getIsEdited() { return isEdited; } public void setIsEdited(boolean isEdited) { this.isEdited = isEdited; } @Override public void configure(AspectConfiguration aspectConfiguration) { this.aspectConfiguration = aspectConfiguration; } @Override public AspectConfiguration getAspectConfiguration() { return aspectConfiguration; } public void setComponentStatisticsId(ArtifactHolder holder){ if (aspectConfiguration == null) { aspectConfiguration = new AspectConfiguration(name); } String apiId = StatisticIdentityGenerator.getIdForComponent(name, ComponentType.INBOUNDENDPOINT, holder); aspectConfiguration.setUniqueId(apiId); String childId = null; if (injectingSeq != null) { childId = StatisticIdentityGenerator.getIdReferencingComponent(injectingSeq, ComponentType.SEQUENCE, holder); StatisticIdentityGenerator.reportingEndEvent(childId, ComponentType.SEQUENCE, holder); } if (onErrorSeq != null) { childId = StatisticIdentityGenerator.getIdReferencingComponent(onErrorSeq, ComponentType.SEQUENCE, holder); StatisticIdentityGenerator.reportingEndEvent(childId, ComponentType.SEQUENCE, holder); } StatisticIdentityGenerator.reportingEndEvent(apiId, ComponentType.INBOUNDENDPOINT, holder); } private void resolveSecureVaultExpressions(Properties props) { Pattern vaultLookupPattern = Pattern.compile(secureVaultRegex); for (Map.Entry<Object, Object> entry : props.entrySet()) { String value = (String) entry.getValue(); Matcher lookupMatcher = vaultLookupPattern.matcher(value); //setting value initially String newParamValue = value; while (lookupMatcher.find()) { Value expression = null; //getting the expression with out curly brackets String expressionStr = lookupMatcher.group(0).substring(1, lookupMatcher.group(0).length() - 1); try { expression = new Value(new SynapseXPath(expressionStr)); } catch (JaxenException e) { log.error("Error while building the expression : " + expressionStr); } if (expression != null) { String resolvedValue = expression.evaluateValue(synapseEnvironment.createMessageContext()); if (resolvedValue == null || resolvedValue.isEmpty()) { log.warn("Found Empty value for expression : " + expression.getExpression()); resolvedValue = ""; } //replacing the expression with resolved value newParamValue = newParamValue.replaceFirst(secureVaultRegex, resolvedValue); props.put(entry.getKey(), newParamValue); } } } } }