/* * 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.axis2.addressing.wsdl; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import javax.wsdl.Definition; import javax.wsdl.Fault; import javax.wsdl.Input; import javax.wsdl.Operation; import javax.wsdl.OperationType; import javax.wsdl.Output; import javax.wsdl.PortType; /** * Generates a wsa:Action value using the Default Action Pattern defined at * http://www.w3.org/TR/2006/WD-ws-addr-wsdl-20060216/#defactionwsdl11 */ public class WSDL11DefaultActionPatternHelper { private static final Log log = LogFactory.getLog(WSDL11DefaultActionPatternHelper.class); // String constants used extensively in this class private static final String URN = "urn"; private static final String SLASH = "/"; private static final String COLON = ":"; private static final String REQUEST = "Request"; private static final String RESPONSE = "Response"; private static final String SOLICIT = "Solicit"; private static final String FAULT = "Fault"; /** * Generate the Action for an Input using the Default Action Pattern * <p/> * Pattern is defined as [target namespace][delimiter][port type name][delimiter][input name] * * @param def is required to obtain the targetNamespace * @param wsdl4jPortType is required to obtain the portType name * @param op is required to generate the input name if not explicitly specified * @param input is required for its name if specified * @return a wsa:Action value based on the Default Action Pattern and the provided objects */ public static String generateActionFromInputElement(Definition def, PortType wsdl4jPortType, Operation op, Input input) { // Get the targetNamespace of the wsdl:definitions String targetNamespace = def.getTargetNamespace(); // Determine the delimiter. Per the spec: 'is ":" when the [target namespace] is a URN, otherwise "/". // Note that for IRI schemes other than URNs which aren't path-based (i.e. those that outlaw the "/" // character), the default action value may not conform to the rules of the IRI scheme. Authors // are advised to specify explicit values in the WSDL in this case.' String delimiter = SLASH; if (targetNamespace.toLowerCase().startsWith(URN)) { delimiter = COLON; } // Get the portType name (as a string to be included in the action) String portTypeName = wsdl4jPortType.getQName().getLocalPart(); // Get the name of the input element (and generate one if none explicitly specified) String inputName = getNameFromInputElement(op, input); // Append the bits together StringBuffer sb = new StringBuffer(); sb.append(targetNamespace); // Deal with the problem that the targetNamespace may or may not have a trailing delimiter if (!targetNamespace.endsWith(delimiter)) { sb.append(delimiter); } sb.append(portTypeName); sb.append(delimiter); sb.append(inputName); // Resolve the action from the StringBuffer String result = sb.toString(); if (log.isTraceEnabled()) { log.trace("generateActionFromInputElement result: " + result); } return result; } /** * Get the name of the specified Input element using the rules defined in WSDL 1.1 * Section 2.4.5 http://www.w3.org/TR/wsdl#_names */ private static String getNameFromInputElement(Operation op, Input input) { // Get the name from the input element if specified. String result = input.getName(); // If not we'll have to generate it. if (result == null) { // If Request-Response or Solicit-Response do something special per // WSDL 1.1 Section 2.4.5 OperationType operationType = op.getStyle(); if (null != operationType) { if (operationType.equals(OperationType.REQUEST_RESPONSE)) { result = op.getName() + REQUEST; } else if (operationType.equals(OperationType.SOLICIT_RESPONSE)) { result = op.getName() + RESPONSE; } } // If the OperationType was not available for some reason, assume on-way or notification if (result == null) { result = op.getName(); } } return result; } protected static String getInputActionFromStringInformation(String messageExchangePattern, String targetNamespace, String portTypeName, String operationName, String inputName) { if (messageExchangePattern == null && inputName == null) { throw new IllegalArgumentException( "One of messageExchangePattern or inputName must the non-null to generate an action."); } // Determine the delimiter. Per the spec: 'is ":" when the [target namespace] is a URN, otherwise "/". // Note that for IRI schemes other than URNs which aren't path-based (i.e. those that outlaw the "/" // character), the default action value may not conform to the rules of the IRI scheme. Authors // are advised to specify explicit values in the WSDL in this case.' String delimiter = SLASH; if (targetNamespace.toLowerCase().startsWith(URN)) { delimiter = COLON; } // N.B. Unlike core Axis2 processing WSDL, JAX-WS accotation processing passes in the // out-in MEP when constructing the client, hence we need to take account of it here // in addition to the expected in-out if (inputName == null) { inputName = operationName; if (messageExchangePattern.indexOf("in-out") >= 0) { inputName += REQUEST; } else if (messageExchangePattern.indexOf("out-in") >= 0) { inputName += RESPONSE; } } // Append the bits together StringBuffer sb = new StringBuffer(); sb.append(targetNamespace); // Deal with the problem that the targetNamespace may or may not have a trailing delimiter if (!targetNamespace.endsWith(delimiter)) { sb.append(delimiter); } sb.append(portTypeName); sb.append(delimiter); sb.append(inputName); // Resolve the action from the StringBuffer String result = sb.toString(); if (log.isTraceEnabled()) { log.trace("getInputActionFromStringInformation result: " + result); } return result; } /** * Generate the Action for an Output using the Default Action Pattern * <p/> * Pattern is defined as [target namespace][delimiter][port type name][delimiter][output name] * * @param def is required to obtain the targetNamespace * @param wsdl4jPortType is required to obtain the portType name * @param op is required to generate the output name if not explicitly specified * @param output is required for its name if specified * @return a wsa:Action value based on the Default Action Pattern and the provided objects */ public static String generateActionFromOutputElement(Definition def, PortType wsdl4jPortType, Operation op, Output output) { // Get the targetNamespace of the wsdl:definition String targetNamespace = def.getTargetNamespace(); // Determine the delimiter. Per the spec: 'is ":" when the [target namespace] is a URN, otherwise "/". // Note that for IRI schemes other than URNs which aren't path-based (i.e. those that outlaw the "/" // character), the default action value may not conform to the rules of the IRI scheme. Authors // are advised to specify explicit values in the WSDL in this case.' String delimiter = SLASH; if (targetNamespace.toLowerCase().startsWith(URN)) { delimiter = COLON; } // Get the portType name (as a string to be included in the action) String portTypeName = wsdl4jPortType.getQName().getLocalPart(); // Get the name of the output element (and generate one if none explicitly specified) String outputName = getNameFromOutputElement(op, output); // Append the bits together StringBuffer sb = new StringBuffer(); sb.append(targetNamespace); // Deal with the problem that the targetNamespace may or may not have a trailing delimiter if (!targetNamespace.endsWith(delimiter)) { sb.append(delimiter); } sb.append(portTypeName); sb.append(delimiter); sb.append(outputName); // Resolve the action from the StringBuffer String result = sb.toString(); if (log.isTraceEnabled()) { log.trace("generateActionFromOutputElement result: " + result); } return result; } /** * Get the name of the specified Output element using the rules defined in WSDL 1.1 * Section 2.4.5 http://www.w3.org/TR/wsdl#_names */ private static String getNameFromOutputElement(Operation op, Output output) { // Get the name from the output element if specified. String result = output.getName(); // If not we'll have to generate it. if (result == null) { // If Request-Response or Solicit-Response do something special per // WSDL 1.1 Section 2.4.5 OperationType operationType = op.getStyle(); if (null != operationType) { if (operationType.equals(OperationType.REQUEST_RESPONSE)) { return op.getName() + RESPONSE; } else if (operationType.equals(OperationType.SOLICIT_RESPONSE)) { return op.getName() + SOLICIT; } } // If the OperationType was not available for some reason, assume on-way or notification if (result == null) { result = op.getName(); } } return result; } protected static String getOutputActionFromStringInformation(String messageExchangePattern, String targetNamespace, String portTypeName, String operationName, String outputName) { if (messageExchangePattern == null && outputName == null) { throw new IllegalArgumentException( "One of messageExchangePattern or outputName must the non-null to generate an action."); } // Determine the delimiter. Per the spec: 'is ":" when the [target namespace] is a URN, otherwise "/". // Note that for IRI schemes other than URNs which aren't path-based (i.e. those that outlaw the "/" // character), the default action value may not conform to the rules of the IRI scheme. Authors // are advised to specify explicit values in the WSDL in this case.' String delimiter = SLASH; if (targetNamespace.toLowerCase().startsWith(URN)) { delimiter = COLON; } // N.B. Unlike core Axis2 processing WSDL, JAX-WS annotation processing passes in the // out-in MEP when constructing the client, hence we need to take account of it here // in addition to the expected in-out if (outputName == null) { outputName = operationName; if (messageExchangePattern.indexOf("in-out") >= 0) { outputName += RESPONSE; } else if (messageExchangePattern.indexOf("out-in") >= 0) { outputName += REQUEST; } } // Append the bits together StringBuffer sb = new StringBuffer(); sb.append(targetNamespace); // Deal with the problem that the targetNamespace may or may not have a trailing delimiter if (!targetNamespace.endsWith(delimiter)) { sb.append(delimiter); } sb.append(portTypeName); sb.append(delimiter); sb.append(outputName); // Resolve the action from the StringBuffer String result = sb.toString(); if (log.isTraceEnabled()) { log.trace("getOutputActionFromStringInformation result: " + result); } return result; } /** * Generate the Action for a Fault using the Default Action Pattern * <p/> * Pattern is defined as [target namespace][delimiter][port type name][delimiter][operation name][delimiter]Fault[delimiter][fault name] * * @param def is required to obtain the targetNamespace * @param wsdl4jPortType is required to obtain the portType name * @param op is required to obtain the operation name * @param fault is required to obtain the fault name * @return a wsa:Action value based on the Default Action Pattern and the provided objects */ public static String generateActionFromFaultElement(Definition def, PortType wsdl4jPortType, Operation op, Fault fault) { // Get the targetNamespace of the wsdl:definition String targetNamespace = def.getTargetNamespace(); // Determine the delimiter. Per the spec: 'is ":" when the [target namespace] is a URN, otherwise "/". // Note that for IRI schemes other than URNs which aren't path-based (i.e. those that outlaw the "/" // character), the default action value may not conform to the rules of the IRI scheme. Authors // are advised to specify explicit values in the WSDL in this case.' String delimiter = SLASH; if (targetNamespace.toLowerCase().startsWith(URN)) { delimiter = COLON; } // Get the portType name (as a string to be included in the action) String portTypeName = wsdl4jPortType.getQName().getLocalPart(); // Get the operation name (as a string to be included in the action) String operationName = op.getName(); // Get the name of the fault element (name is mandatory on fault elements) String faultName = fault.getName(); // Append the bits together StringBuffer sb = new StringBuffer(); sb.append(targetNamespace); // Deal with the problem that the targetNamespace may or may not have a trailing delimiter if (!targetNamespace.endsWith(delimiter)) { sb.append(delimiter); } sb.append(portTypeName); sb.append(delimiter); sb.append(operationName); sb.append(delimiter); sb.append(FAULT); sb.append(delimiter); sb.append(faultName); // Resolve the action from the StringBuffer String result = sb.toString(); if (log.isTraceEnabled()) { log.trace("generateActionFromFaultElement result: " + result); } return result; } protected static String getFaultActionFromStringInformation(String targetNamespace, String portTypeName, String operationName, String faultName) { // Determine the delimiter. Per the spec: 'is ":" when the [target namespace] is a URN, otherwise "/". // Note that for IRI schemes other than URNs which aren't path-based (i.e. those that outlaw the "/" // character), the default action value may not conform to the rules of the IRI scheme. Authors // are advised to specify explicit values in the WSDL in this case.' String delimiter = SLASH; if (targetNamespace.toLowerCase().startsWith(URN)) { delimiter = COLON; } // Append the bits together StringBuffer sb = new StringBuffer(); sb.append(targetNamespace); // Deal with the problem that the targetNamespace may or may not have a trailing delimiter if (!targetNamespace.endsWith(delimiter)) { sb.append(delimiter); } sb.append(portTypeName); sb.append(delimiter); sb.append(operationName); sb.append(delimiter); sb.append(FAULT); sb.append(delimiter); sb.append(faultName); // Resolve the action from the StringBuffer String result = sb.toString(); if (log.isTraceEnabled()) { log.trace("getFaultActionFromStringInformation result: " + result); } return result; } }