blob: 9472d29fad617c22712481b9f4d79ecea3e34543 [file] [log] [blame]
/*
* 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;
}
}