/* * 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.synapse.endpoints; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.synapse.MessageContext; import org.apache.synapse.SynapseConstants; import org.apache.synapse.SynapseException; import org.apache.synapse.aspects.AspectConfigurable; import org.apache.synapse.aspects.AspectConfiguration; import org.apache.synapse.config.SynapseConfigUtils; import org.apache.synapse.config.xml.SynapsePath; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * An Endpoint definition contains the information about an endpoint. It is used by leaf * level endpoints to store this information (e.g. AddressEndpoint and WSDLEndpoint). */ public class EndpointDefinition implements AspectConfigurable { private static final Log log = LogFactory.getLog(EndpointDefinition.class); public static final String DYNAMIC_URL_VALUE = "DYNAMIC_URL_VALUE"; /** Who is the leaf level Endpoint which uses me? */ private Endpoint leafEndpoint = null; /** * The simple address this endpoint resolves to - if explicitly specified */ private String address = null; /** * Should messages be sent in an WS-RM Sequence ? */ @Deprecated private boolean reliableMessagingOn = false; /** * Should messages be sent using WS-A? */ private boolean addressingOn = false; /** * The addressing namespace version */ private String addressingVersion = null; /** * Should messages be sent using WS-Security? */ private boolean securityOn = false; /** * The "key" for any WS-RM Policy overrides to be used */ @Deprecated private String wsRMPolicyKey = null; /** * The "key" for any Rampart Security Policy to be used */ private String wsSecPolicyKey = null; /** * The "key" for any Rampart Security Policy to be used for inbound messages */ private String inboundWsSecPolicyKey = null; /** * The "key" for any Rampart Security Policy to be used for outbound messages */ private String outboundWsSecPolicyKey = null; /** * use a separate listener - implies addressing is on * */ private boolean useSeparateListener = false; /** * force REST (POST) on * */ private boolean forcePOX = false; /** * force REST (GET) on * */ private boolean forceGET = false; /** * force SOAP11 on * */ private boolean forceSOAP11 = false; /** * force SOAP11 on * */ private boolean forceSOAP12 = false; /** * force REST on ? */ private boolean forceREST = false; /** * HTTP Endpoint */ private boolean isHTTPEndpoint = false; /** * use MTOM * */ private boolean useMTOM = false; /** * use SWA * */ private boolean useSwa = false; /** * Endpoint message format. pox/soap11/soap12 */ private String format = null; /** * The charset encoding for messages sent to the endpoint. */ private String charSetEncoding; /** * The expression to evaluate dynamic timeout. */ private SynapsePath dynamicTimeout = null; /** * Whether endpoint state replication should be disabled or not (only valid in clustered setups) */ private boolean replicationDisabled = false; /** * timeout duration for waiting for a response in ms. if the user has set some timeout action * and the timeout duration is not set, default is set to 0. note that if the user has * not set any timeout configuration, default timeout action is set to NONE, which won't do * anything for timeouts. */ private long timeoutDuration = 0; /** * Effective timeout interval for the endpoint */ private long effectiveTimeout = 0; /** * action to perform when a timeout occurs (NONE | DISCARD | DISCARD_AND_FAULT) * */ private int timeoutAction = SynapseConstants.NONE; /** The initial suspend duration when an endpoint is marked inactive */ private long initialSuspendDuration = -1; /** The suspend duration ratio for the next duration - this is the geometric series multipler */ private float suspendProgressionFactor = 1; /** This is the maximum duration for which a node will be suspended */ private long suspendMaximumDuration = Long.MAX_VALUE; /** A list of error codes, which directly puts an endpoint into suspend mode */ private final List<Integer> suspendErrorCodes = new ArrayList<Integer>(); /** No of retries to attempt on timeout, before an endpoint is makred inactive */ private int retriesOnTimeoutBeforeSuspend = 0; /** The delay between retries for a timeout out endpoint */ private int retryDurationOnTimeout = 0; /** A list of error codes which puts the endpoint into timeout mode */ private final List<Integer> timeoutErrorCodes = new ArrayList<Integer>(); private AspectConfiguration aspectConfiguration; /** A list of error codes which permit the retries */ private final List<Integer> retryDisabledErrorCodes = new ArrayList<Integer>(); /** A list of error codes which permit the retries for Enabled error Codes */ private final List<Integer> retryEnabledErrorCodes = new ArrayList<Integer>(); /** Variable to depict the effective timeout type **/ private SynapseConstants.ENDPOINT_TIMEOUT_TYPE endpointTimeoutType; public EndpointDefinition() { try { // Set the timeout value to global timeout value. // This will be overridden if endpoint timeout is set effectiveTimeout = SynapseConfigUtils.getGlobalTimeoutInterval(); this.endpointTimeoutType = SynapseConstants.ENDPOINT_TIMEOUT_TYPE.GLOBAL_TIMEOUT; } catch (Exception ex) { String msg = "Error while reading global timeout interval"; log.error(msg, ex); throw new SynapseException(msg, ex); } } public void setDynamicTimeoutExpression(SynapsePath expression) { this.dynamicTimeout = expression; } public SynapsePath getDynamicTimeoutExpression() { return this.dynamicTimeout; } public boolean isDynamicTimeoutEndpoint() { if (this.dynamicTimeout != null) { return true; } else { return false; } } public long evaluateDynamicEndpointTimeout(MessageContext synCtx) { long timeoutMilliSeconds; try { String stringValue = dynamicTimeout.stringValueOf(synCtx); if (stringValue != null) { timeoutMilliSeconds = Long.parseLong(stringValue.trim()); } else { log.warn("Error while evaluating dynamic endpoint timeout expression." + "Synapse global timeout is taken as effective timeout."); timeoutMilliSeconds = effectiveTimeout; } } catch (NumberFormatException e) { log.warn("Error while evaluating dynamic endpoint timeout expression." + "Synapse global timeout is taken as effective timeout."); timeoutMilliSeconds = effectiveTimeout; } if (timeoutMilliSeconds > effectiveTimeout) { return effectiveTimeout; } return timeoutMilliSeconds; } /** * This should return the absolute EPR address referenced by the named endpoint. This may be * possibly computed. * * @return an absolute address to be used to reference the named endpoint */ public String getAddress() { return address; } /** * This should return the absolute EPR address referenced by the named endpoint. This may be * possibly computed if the ${} properties specified in the URL. * * @param messageContext the current message context against the address is computed * @return an absolute address to be used to reference the named endpoint */ public String getAddress(MessageContext messageContext) { if (address == null) { return null; } String addressString = address; String dynamicUrl = (String) messageContext.getProperty(DYNAMIC_URL_VALUE); // See ESBJAVA-3183. if (dynamicUrl != null && !dynamicUrl.isEmpty()) { addressString = dynamicUrl; } boolean matches = false; int s = 0; Pattern pattern = Pattern.compile("\\$\\{.*?\\}"); StringBuffer computedAddress = new StringBuffer(); Matcher matcher = pattern.matcher(addressString); while (matcher.find()) { Object property = messageContext.getProperty( addressString.substring(matcher.start() + 2, matcher.end() - 1)); if (property != null) { computedAddress.append(addressString.substring(s, matcher.start())); computedAddress.append(property.toString()); s = matcher.end(); matches = true; } } if (!matches) { return addressString; } else { computedAddress.append(addressString.substring(s, addressString.length())); return computedAddress.toString(); } } /** * Set an absolute URL as the address for this named endpoint * * @param address the absolute address to be used */ public void setAddress(String address) { this.address = address; } /** * Is RM turned on on this endpoint? * * @return true if on */ @Deprecated public boolean isReliableMessagingOn() { return reliableMessagingOn; } /** * Request that RM be turned on/off on this endpoint * * @param reliableMessagingOn a boolean flag indicating RM is on or not */ @Deprecated public void setReliableMessagingOn(boolean reliableMessagingOn) { this.reliableMessagingOn = reliableMessagingOn; } /** * Is WS-A turned on on this endpoint? * * @return true if on */ public boolean isAddressingOn() { return addressingOn; } /** * Request that WS-A be turned on/off on this endpoint * * @param addressingOn a boolean flag indicating addressing is on or not */ public void setAddressingOn(boolean addressingOn) { this.addressingOn = addressingOn; } /** * Get the addressing namespace version * * @return the adressing version */ public String getAddressingVersion() { return addressingVersion; } /** * Set the addressing namespace version * * @param addressingVersion Version of the addressing spec to use */ public void setAddressingVersion(String addressingVersion) { this.addressingVersion = addressingVersion; } /** * Is WS-Security turned on on this endpoint? * * @return true if on */ public boolean isSecurityOn() { return securityOn; } /** * Request that WS-Sec be turned on/off on this endpoint * * @param securityOn a boolean flag indicating security is on or not */ public void setSecurityOn(boolean securityOn) { this.securityOn = securityOn; } /** * Return the Rampart Security configuration policys' 'key' to be used (See Rampart) * * @return the Rampart Security configuration policys' 'key' to be used (See Rampart) */ public String getWsSecPolicyKey() { return wsSecPolicyKey; } /** * Set the Rampart Security configuration policys' 'key' to be used (See Rampart) * * @param wsSecPolicyKey the Rampart Security configuration policys' 'key' to be used */ public void setWsSecPolicyKey(String wsSecPolicyKey) { this.wsSecPolicyKey = wsSecPolicyKey; } /** * Return the Rampart Security configuration policys' 'key' to be used for inbound messages * (See Rampart) * * @return the Rampart Security configuration policys' 'key' to be used for inbound messages */ public String getInboundWsSecPolicyKey() { return inboundWsSecPolicyKey; } /** * Set the Rampart Security configuration policys' 'key' to be used for inbound messages * (See Rampart) * * @param inboundWsSecPolicyKey the Rampart Security configuration policys' 'key' to be used */ public void setInboundWsSecPolicyKey(String inboundWsSecPolicyKey) { this.inboundWsSecPolicyKey = inboundWsSecPolicyKey; } /** * Return the Rampart Security configuration policys' 'key' to be used for outbound messages * (See Rampart) * * @return the ORampart Security configuration policys' 'key' to be used for outbound messages */ public String getOutboundWsSecPolicyKey() { return outboundWsSecPolicyKey; } /** * Set the Rampart Security configuration policys' 'key' to be used (See Rampart) * * @param outboundWsSecPolicyKey the Rampart Security configuration policys' 'key' to be used */ public void setOutboundWsSecPolicyKey(String outboundWsSecPolicyKey) { this.outboundWsSecPolicyKey = outboundWsSecPolicyKey; } /** * Get the WS-RM configuration policys' 'key' to be used * * @return the WS-RM configuration policys' 'key' to be used */ @Deprecated public String getWsRMPolicyKey() { return wsRMPolicyKey; } /** * Set the WS-RM configuration policys' 'key' to be used * * @param wsRMPolicyKey the WS-RM configuration policys' 'key' to be used */ @Deprecated public void setWsRMPolicyKey(String wsRMPolicyKey) { this.wsRMPolicyKey = wsRMPolicyKey; } public void setUseSeparateListener(boolean b) { this.useSeparateListener = b; } public boolean isUseSeparateListener() { return useSeparateListener; } public void setForcePOX(boolean forcePOX) { this.forcePOX = forcePOX; } public boolean isForcePOX() { return forcePOX; } public boolean isForceGET() { return forceGET; } public void setForceGET(boolean forceGET) { this.forceGET = forceGET; } public void setForceSOAP11(boolean forceSOAP11) { this.forceSOAP11 = forceSOAP11; } public boolean isForceSOAP11() { return forceSOAP11; } public void setForceSOAP12(boolean forceSOAP12) { this.forceSOAP12 = forceSOAP12; } public boolean isForceSOAP12() { return forceSOAP12; } public boolean isForceREST() { return forceREST; } public void setForceREST(boolean forceREST) { this.forceREST = forceREST; } public boolean isUseMTOM() { return useMTOM; } public void setUseMTOM(boolean useMTOM) { this.useMTOM = useMTOM; } public boolean isUseSwa() { return useSwa; } public void setUseSwa(boolean useSwa) { this.useSwa = useSwa; } public long getTimeoutDuration() { return timeoutDuration; } /** * Get the effective timeout duration for the endpoint * * If endpoint timeout is set explicitly this will return that, * If not global timeout interval is returned * * @return effective timeout duration for the endpoint */ public long getEffectiveTimeout() { return effectiveTimeout; } /** * Set the timeout duration. * * @param timeoutDuration a duration in milliseconds */ public void setTimeoutDuration(long timeoutDuration) { this.timeoutDuration = timeoutDuration; this.effectiveTimeout = timeoutDuration; this.endpointTimeoutType = SynapseConstants.ENDPOINT_TIMEOUT_TYPE.ENDPOINT_TIMEOUT; } public int getTimeoutAction() { return timeoutAction; } public void setTimeoutAction(int timeoutAction) { this.timeoutAction = timeoutAction; } public String getFormat() { return format; } public void setFormat(String format) { this.format = format; } /** * Get the charset encoding for messages sent to the endpoint. * * @return charSetEncoding */ public String getCharSetEncoding() { return charSetEncoding; } /** * Set the charset encoding for messages sent to the endpoint. * * @param charSetEncoding the charset encoding or <code>null</code> */ public void setCharSetEncoding(String charSetEncoding) { this.charSetEncoding = charSetEncoding; } /** * Get the suspend on fail duration. * * @return suspendOnFailDuration */ public long getInitialSuspendDuration() { return initialSuspendDuration; } /** * Set the suspend on fail duration. * * @param initialSuspendDuration a duration in milliseconds */ public void setInitialSuspendDuration(long initialSuspendDuration) { this.initialSuspendDuration = initialSuspendDuration; } // public int getTraceState() { // return traceState; // } // // public void setTraceState(int traceState) { // this.traceState = traceState; // } public float getSuspendProgressionFactor() { return suspendProgressionFactor; } public void setSuspendProgressionFactor(float suspendProgressionFactor) { this.suspendProgressionFactor = suspendProgressionFactor; } public long getSuspendMaximumDuration() { return suspendMaximumDuration; } public void setSuspendMaximumDuration(long suspendMaximumDuration) { this.suspendMaximumDuration = suspendMaximumDuration; } public int getRetriesOnTimeoutBeforeSuspend() { return retriesOnTimeoutBeforeSuspend; } public void setRetriesOnTimeoutBeforeSuspend(int retriesOnTimeoutBeforeSuspend) { this.retriesOnTimeoutBeforeSuspend = retriesOnTimeoutBeforeSuspend; } public int getRetryDurationOnTimeout() { return retryDurationOnTimeout; } public void setRetryDurationOnTimeout(int retryDurationOnTimeout) { this.retryDurationOnTimeout = retryDurationOnTimeout; } public List<Integer> getSuspendErrorCodes() { return suspendErrorCodes; } public List<Integer> getTimeoutErrorCodes() { return timeoutErrorCodes; } public List<Integer> getRetryDisabledErrorCodes() { return retryDisabledErrorCodes; } public List<Integer> getRetryEnableErrorCodes() { return retryEnabledErrorCodes; } public boolean isReplicationDisabled() { return replicationDisabled; } public void setReplicationDisabled(boolean replicationDisabled) { this.replicationDisabled = replicationDisabled; } public void addSuspendErrorCode(int code) { suspendErrorCodes.add(code); } public void addTimeoutErrorCode(int code) { timeoutErrorCodes.add(code); } public void addRetryDisabledErrorCode(int code) { retryDisabledErrorCodes.add(code); } public void addRetryEnabledErrorCode(int code) { retryEnabledErrorCodes.add(code); } public boolean isHTTPEndpoint() { return isHTTPEndpoint; } public void setHTTPEndpoint(boolean HTTPEndpoint) { isHTTPEndpoint = HTTPEndpoint; } public String toString() { if (leafEndpoint != null) { return leafEndpoint.toString(); } else if (address != null) { return "Address [" + address + "]"; } return "[unknown endpoint]"; } public void setLeafEndpoint(Endpoint leafEndpoint) { this.leafEndpoint = leafEndpoint; } public boolean isStatisticsEnable() { return this.aspectConfiguration != null && this.aspectConfiguration.isStatisticsEnable(); } public void disableStatistics() { if (this.aspectConfiguration != null) { this.aspectConfiguration.disableStatistics(); } } public void enableStatistics() { if (this.aspectConfiguration != null) { this.aspectConfiguration.enableStatistics(); } } public boolean isTracingEnabled() { return this.aspectConfiguration != null && this.aspectConfiguration.isTracingEnabled(); } public void disableTracing() { if (this.aspectConfiguration != null) { this.aspectConfiguration.disableTracing(); } } public void enableTracing() { if (this.aspectConfiguration != null) { this.aspectConfiguration.enableTracing(); } } public void configure(AspectConfiguration aspectConfiguration) { this.aspectConfiguration = aspectConfiguration; } public AspectConfiguration getAspectConfiguration() { return this.aspectConfiguration; } public SynapseConstants.ENDPOINT_TIMEOUT_TYPE getEndpointTimeoutType() { return endpointTimeoutType; } public void setEndpointTimeoutType(SynapseConstants.ENDPOINT_TIMEOUT_TYPE endpointTimeoutType) { this.endpointTimeoutType = endpointTimeoutType; } }