/* * 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.builder; import org.apache.axiom.om.OMAbstractFactory; import org.apache.axiom.om.OMElement; import org.apache.axiom.soap.SOAP11Constants; import org.apache.axiom.soap.SOAP12Constants; import org.apache.axiom.soap.SOAPFactory; import org.apache.axis2.AxisFault; import org.apache.axis2.Constants; import org.apache.axis2.java.security.AccessController; import org.apache.axis2.addressing.EndpointReference; import org.apache.axis2.context.MessageContext; import org.apache.axis2.description.AxisBinding; import org.apache.axis2.description.AxisBindingOperation; import org.apache.axis2.description.AxisEndpoint; import org.apache.axis2.description.WSDL20DefaultValueHolder; import org.apache.axis2.description.WSDL2Constants; import org.apache.axis2.i18n.Messages; import org.apache.axis2.transport.http.util.URIEncoderDecoder; import org.apache.axis2.util.MultipleEntryHashMap; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.security.PrivilegedAction; import java.security.PrivilegedExceptionAction; import java.security.PrivilegedActionException; public class XFormURLEncodedBuilder implements Builder { private static final Log log = LogFactory.getLog(XFormURLEncodedBuilder.class); /** * @return Returns the document element. */ public OMElement processDocument(InputStream inputStream, String contentType, MessageContext messageContext) throws AxisFault { MultipleEntryHashMap parameterMap = new MultipleEntryHashMap(); SOAPFactory soapFactory; AxisBindingOperation axisBindingOperation = (AxisBindingOperation) messageContext.getProperty( Constants.AXIS_BINDING_OPERATION); String queryParameterSeparator = null; String templatedPath = null; if (axisBindingOperation != null) { queryParameterSeparator = (String) axisBindingOperation .getProperty(WSDL2Constants.ATTR_WHTTP_QUERY_PARAMETER_SEPARATOR); templatedPath = (String) axisBindingOperation.getProperty(WSDL2Constants.ATTR_WHTTP_LOCATION); } if (queryParameterSeparator == null) { queryParameterSeparator = WSDL20DefaultValueHolder.ATTR_WHTTP_QUERY_PARAMETER_SEPARATOR_DEFAULT; } AxisEndpoint axisEndpoint = (AxisEndpoint) messageContext.getProperty(WSDL2Constants.ENDPOINT_LOCAL_NAME); if (axisEndpoint != null) { AxisBinding axisBinding = axisEndpoint.getBinding(); String soapVersion = (String) axisBinding.getProperty(WSDL2Constants.ATTR_WSOAP_VERSION); soapFactory = getSOAPFactory(soapVersion); } else { soapFactory = getSOAPFactory(SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI); } EndpointReference endpointReference = messageContext.getTo(); if (endpointReference == null) { throw new AxisFault("Cannot create DocumentElement without destination EPR"); } String requestURL = endpointReference.getAddress(); try { requestURL = extractParametersUsingHttpLocation(templatedPath, parameterMap, requestURL, queryParameterSeparator); } catch (UnsupportedEncodingException e) { throw AxisFault.makeFault(e); } String query = requestURL; int index; if ((index = requestURL.indexOf("?")) > -1) { query = requestURL.substring(index + 1); } extractParametersFromRequest(parameterMap, query, queryParameterSeparator, (String) messageContext.getProperty( Constants.Configuration.CHARACTER_SET_ENCODING), inputStream); messageContext.setProperty(Constants.REQUEST_PARAMETER_MAP, parameterMap); return BuilderUtil.buildsoapMessage(messageContext, parameterMap, soapFactory); } protected void extractParametersFromRequest(MultipleEntryHashMap parameterMap, String query, String queryParamSeparator, final String charsetEncoding, final InputStream inputStream) throws AxisFault { if (query != null && !"".equals(query)) { String parts[] = query.split(queryParamSeparator); for (int i = 0; i < parts.length; i++) { int separator = parts[i].indexOf("="); if (separator > 0) { String value = parts[i].substring(separator + 1); try { value = URIEncoderDecoder.decode(value); } catch (UnsupportedEncodingException e) { throw AxisFault.makeFault(e); } parameterMap .put(parts[i].substring(0, separator), value); } } } if (inputStream != null) { try { InputStreamReader inputStreamReader = null; try { inputStreamReader = (InputStreamReader) AccessController.doPrivileged( new PrivilegedExceptionAction() { public Object run() throws UnsupportedEncodingException { return new InputStreamReader(inputStream, charsetEncoding); } } ); } catch (PrivilegedActionException e) { throw (UnsupportedEncodingException) e.getException(); } BufferedReader bufferedReader = new BufferedReader(inputStreamReader); while (true) { String line = bufferedReader.readLine(); if (line != null) { String parts[] = line.split( WSDL20DefaultValueHolder.ATTR_WHTTP_QUERY_PARAMETER_SEPARATOR_DEFAULT); for (int i = 0; i < parts.length; i++) { int separator = parts[i].indexOf("="); String value = parts[i].substring(separator + 1); parameterMap.put(parts[i].substring(0, separator), URIEncoderDecoder.decode(value)); } } else { break; } } } catch (IOException e) { throw AxisFault.makeFault(e); } } } /** * Here is what I will try to do here. I will first try to identify the location of the first * template element in the request URI. I am trying to deduce the location of that location * using the httpLocation element of the binding (it is passed in to this * method). * If there is a contant part in the httpLocation, then I will identify it. For this, I get * the index of {, from httpLocation param, and whatever to the left of it is the contant part. * Then I search for this constant part inside the url. This will give us the access to the first * template parameter. * To find the end of this parameter, we need to get the index of the next constant, from * httpLocation attribute. Likewise we keep on discovering parameters. * <p/> * Assumptions : * 1. User will always append the value of httpLocation to the address given in the * endpoint. * 2. I was talking about the constants in the httpLocation. Those constants will not occur, * to a reasonable extend, before the constant we are looking for. * * @param templatedPath * @param parameterMap */ protected String extractParametersUsingHttpLocation(String templatedPath, MultipleEntryHashMap parameterMap, String requestURL, String queryParameterSeparator) throws AxisFault, UnsupportedEncodingException { if (templatedPath != null && !"".equals(templatedPath) && templatedPath.indexOf("{") > -1) { StringBuffer pathTemplate = new StringBuffer(templatedPath); // this will hold the index, from which we need to process the request URI int startIndex = 0; int templateStartIndex = 0; int templateEndIndex = 0; int indexOfNextConstant = 0; StringBuffer requestURIBuffer = new StringBuffer(requestURL); while (startIndex < requestURIBuffer.length()) { // this will always hold the starting index of a template parameter templateStartIndex = pathTemplate.indexOf("{", templateStartIndex); if (templateStartIndex > 0) { // get the preceding constant part from the template String constantPart = pathTemplate.substring(templateEndIndex + 1, templateStartIndex); constantPart = constantPart.replaceAll("\\{\\{","{"); constantPart = constantPart.replaceAll("}}","}"); // get the index of the end of this template param templateEndIndex = pathTemplate.indexOf("}", templateStartIndex); if ((pathTemplate.length() -1) > templateEndIndex && pathTemplate.charAt(templateEndIndex +1) == '}') { templateEndIndex = pathTemplate.indexOf("}", templateEndIndex +2); } String parameterName = pathTemplate.substring(templateStartIndex + 1, templateEndIndex); // next try to find the next constant templateStartIndex = pathTemplate.indexOf("{", templateEndIndex); if (pathTemplate.charAt(templateStartIndex +1) == '{') { templateStartIndex = pathTemplate.indexOf("{", templateStartIndex +2); } int endIndexOfConstant = requestURIBuffer .indexOf(constantPart, indexOfNextConstant) + constantPart.length(); if (templateStartIndex == -1) { if (templateEndIndex == pathTemplate.length() - 1) { // We may have occations where we have templates of the form foo/{name}. // In this case the next connstant will be ? and not the // queryParameterSeparator indexOfNextConstant = requestURIBuffer .indexOf("?", endIndexOfConstant); if (indexOfNextConstant == -1) { indexOfNextConstant = requestURIBuffer .indexOf(queryParameterSeparator, endIndexOfConstant); } if (indexOfNextConstant > 0) { addParameterToMap(parameterMap, parameterName, requestURIBuffer.substring(endIndexOfConstant, indexOfNextConstant)); return requestURL.substring(indexOfNextConstant); } else { addParameterToMap(parameterMap, parameterName, requestURIBuffer.substring( endIndexOfConstant)); return ""; } } else { constantPart = pathTemplate.substring(templateEndIndex + 1, pathTemplate.length()); constantPart = constantPart.replaceAll("\\{\\{","{"); constantPart = constantPart.replaceAll("}}","}"); indexOfNextConstant = requestURIBuffer.indexOf(constantPart, endIndexOfConstant); addParameterToMap(parameterMap, parameterName, requestURIBuffer.substring( endIndexOfConstant, indexOfNextConstant)); if (requestURIBuffer.length() > indexOfNextConstant + 1) { return requestURIBuffer.substring(indexOfNextConstant + 1); } return ""; } } else { // this is the next constant from the template constantPart = pathTemplate .substring(templateEndIndex + 1, templateStartIndex); constantPart = constantPart.replaceAll("\\{\\{","{"); constantPart = constantPart.replaceAll("}}","}"); indexOfNextConstant = requestURIBuffer.indexOf(constantPart, endIndexOfConstant); addParameterToMap(parameterMap, parameterName, requestURIBuffer.substring( endIndexOfConstant, indexOfNextConstant)); startIndex = indexOfNextConstant; } } } } return requestURL; } private void addParameterToMap(MultipleEntryHashMap parameterMap, String paramName, String paramValue) throws UnsupportedEncodingException, AxisFault { try { paramValue = URIEncoderDecoder.decode(paramValue); } catch (UnsupportedEncodingException e) { throw AxisFault.makeFault(e); } if (paramName.startsWith(WSDL2Constants.TEMPLATE_ENCODE_ESCAPING_CHARACTER)) { parameterMap.put(paramName.substring(1), paramValue); } else { parameterMap.put(paramName, paramValue); } } private SOAPFactory getSOAPFactory(String nsURI) throws AxisFault { if (nsURI == null) { return OMAbstractFactory.getSOAP12Factory(); } else if (SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI.equals(nsURI)) { return OMAbstractFactory.getSOAP12Factory(); } else if (SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI.equals(nsURI)) { return OMAbstractFactory.getSOAP11Factory(); } else { throw new AxisFault(Messages.getMessage("invalidSOAPversion")); } } }