/*
 * 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.transport.http.util;

import org.apache.axiom.om.OMElement;
import org.apache.axis2.AxisFault;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.description.WSDL20DefaultValueHolder;
import org.apache.axis2.description.WSDL2Constants;
import org.apache.axis2.util.WSDL20Util;

import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Iterator;


/**
 * This util is used on the client side for creating the URL's for all request (WSDL 2.0 allws to
 * change the URL's of SOAP messages too). It resolves WSDL 2.0 httplocation property and also
 * append parameters to URL's when needed.
 */
public class URLTemplatingUtil {

    /**
     * Appends Query parameters to the URL
     *
     * @param messageContext - The MessageContext of the request
     * @param url            - Original url string
     * @return String containing the appended query parameters
     */
    public static URL appendQueryParameters(MessageContext messageContext, URL url) throws AxisFault {

        String urlString = url.toString();
        OMElement firstElement;
        String queryParameterSeparator = (String) messageContext
                .getProperty(WSDL2Constants.ATTR_WHTTP_QUERY_PARAMETER_SEPARATOR);
        // In case queryParameterSeparator is null we better use the default value

        if (queryParameterSeparator == null) {
            queryParameterSeparator = WSDL20DefaultValueHolder
                    .getDefaultValue(WSDL2Constants.ATTR_WHTTP_QUERY_PARAMETER_SEPARATOR);
        }

        firstElement = messageContext.getEnvelope().getBody().getFirstElement();
        String params = "";

        if (firstElement != null) {
            Iterator iter = firstElement.getChildElements();

            String legalCharacters = WSDL2Constants.LEGAL_CHARACTERS_IN_QUERY.replaceAll(queryParameterSeparator, "");

            while (iter.hasNext()) {
                OMElement element = (OMElement) iter.next();
                try {
                    params = params + URIEncoderDecoder.quoteIllegal(element.getLocalName(), legalCharacters) + "=" + URIEncoderDecoder.quoteIllegal(element.getText(), legalCharacters) +
                            queryParameterSeparator;
                } catch (UnsupportedEncodingException e) {
                    throw AxisFault.makeFault(e);
                }
            }
        }

        if (!"".equals(params)) {
            int index = urlString.indexOf("?");
            if (index == -1) {
                urlString = urlString + "?" + params.substring(0, params.length() - 1);
            } else if (index == urlString.length() - 1) {
                urlString = urlString + params.substring(0, params.length() - 1);

            } else {
                urlString = urlString + queryParameterSeparator + params.substring(0, params.length() - 1);
            }

            try {
                return new URL(urlString);
            } catch (MalformedURLException e) {
                throw AxisFault.makeFault(e);
            }
        }
        return url;
    }

    /**
     * Returns the templated URL given the original URL
     *
     * @param targetURL      - The original URL
     * @param messageContext - The MessageContext of the request
     * @param detach         - Boolean value specifying whether the element should be detached from the
     *                       envelop. When serializing data as application/x-form-urlencoded what goes in the body is the
     *                       remainder and therefore we should detach the element from the envelop.
     * @return The templated URL
     * @throws AxisFault - Thrown in case an exception occurs
     */
    public static URL getTemplatedURL(URL targetURL, MessageContext messageContext, boolean detach)
            throws AxisFault {

        String httpLocation = (String) messageContext.getProperty(WSDL2Constants.ATTR_WHTTP_LOCATION);

//        String urlString = targetURL.toString();
        if (httpLocation != null) {
        String replacedQuery = httpLocation;
        int separator = httpLocation.indexOf('{');
            try {

        if (separator > -1) {
            replacedQuery = URIEncoderDecoder.quoteIllegal(
                    WSDL20Util.applyURITemplating(messageContext, httpLocation, detach),
                    WSDL2Constants.LEGAL_CHARACTERS_IN_URL);

        }
                URI targetURI;
                URI appendedURI;
                if (replacedQuery.charAt(0) == '?') {
                    appendedURI = new URI(targetURL.toString () + replacedQuery);
                } else {
                     String uriString = targetURL.toString();
                    if (!uriString.endsWith("/")) {
                    targetURI = new URI(uriString + "/");
                    } else {
                        targetURI = new URI(uriString);
                    }
                    appendedURI = targetURI.resolve(replacedQuery);
                }
                
                targetURL = appendedURI.toURL();

            } catch (MalformedURLException e) {
                throw new AxisFault("An error occured while trying to create request URL");
            } catch (URISyntaxException e) {
                throw new AxisFault("An error occured while trying to create request URL");
            } catch (UnsupportedEncodingException e) {
                throw new AxisFault("An error occured while trying to create request URL");
            }
        }

        return targetURL;
    }

}

@@ -1214,110 +1214,9 @@
 net.
-MalformedURLException;%0D%0Aimport java.net.URI;%0D%0Aimport java.net.URISyntaxException;%0D%0Aimport java.net.URL
+*
 ;%0D%0Ai
@@ -2529,16 +2529,52 @@
 s = %22%22;%0D
+%0A        String encoding = %22UTF-8%22;%0D
 %0A%0D%0A     
@@ -2673,130 +2673,8 @@
 %0D%0A%0D%0A
-            String legalCharacters = WSDL2Constants.LEGAL_CHARACTERS_IN_QUERY.replaceAll(queryParameterSeparator, %22%22);%0D%0A%0D%0A
     
@@ -2703,24 +2703,60 @@
 sNext()) %7B%0D%0A
+                String parameter ;%0D%0A
             
@@ -2857,52 +2857,15 @@
 aram
-s = params + URIEncoderDecoder.quoteIllegal(
+eter = 
 elem
@@ -2882,34 +2882,16 @@
 alName()
-, legalCharacters)
  + %22=%22 +
@@ -2897,36 +2897,23 @@
 + UR
-I
+L
 Encoder
-De
+.en
 code
-r.quoteIllegal
 (ele
@@ -2932,56 +2932,38 @@
 (), 
-legalCharacters) +%0D%0A                            
+encoding).replace(%22+%22, %22%2520%22)+
 quer
@@ -2982,16 +2982,17 @@
 parator;
+;
 %0D%0A      
@@ -3088,32 +3088,32 @@
 .makeFault(e);%0D%0A
-
                 
@@ -3107,32 +3107,113 @@
              %7D%0D%0A
+                params = %22%22.equals(params) ? parameter : (params  + parameter);%0D%0A
             %7D%0D%0A 

fix for ESBJAVA-3746