# NhttpUtil.java

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

    import org.apache.axiom.om.OMOutputFormat;
    import org.apache.axis2.Constants;
    import org.apache.axis2.addressing.EndpointReference;
    import org.apache.axis2.context.MessageContext;
    import org.apache.axis2.transport.TransportUtils;
    import org.apache.axis2.transport.http.HTTPConstants;
    import org.apache.http.HttpRequest;

    import java.net.InetAddress;

    /**
     * A useful set of utility methods for the HTTP transport
     */
    public class NhttpUtil {

        /**
         * This method tries to determine the hostname of the given InetAddress without
         * triggering a reverse DNS lookup.  {@link java.net.InetAddress#getHostName()}
         * triggers a reverse DNS lookup which can be very costly in cases where reverse
         * DNS fails. Tries to parse a symbolic hostname from {@link java.net.InetAddress#toString()},
         * which is documented to return a String of the form "hostname / literal IP address"
         * with 'hostname' blank if not already computed & stored in <code>address</code<.
         * <p/>
         * If the hostname cannot be determined from InetAddress.toString(),
         * the value of {@link java.net.InetAddress#getHostAddress()} is returned.
         *
         * @param address The InetAddress whose hostname has to be determined
         * @return hostsname, if it can be determined. hostaddress, if not.
         *
         * TODO: We may introduce a System property or some other method of configuration
         * TODO: which will specify whether to allow reverse DNS lookup or not
         */
        public static String getHostName(InetAddress address) {
            String result;
            String hostAddress = address.getHostAddress();
            String inetAddr = address.toString();
            int index1 = inetAddr.lastIndexOf('/');
            int index2 = inetAddr.indexOf(hostAddress);
            if (index2 == index1 + 1) {
                if (index1 == 0) {
                    result = hostAddress;
                } else {
                    result = inetAddr.substring(0, index1);
                }
            } else {
                result = hostAddress;
            }
            return result;
        }

        /**
         * Get the EPR for the message passed in
         * @param msgContext the message context
         * @return the destination EPR
         */
        public static EndpointReference getDestinationEPR(MessageContext msgContext) {

            // Trasnport URL can be different from the WSA-To
            String transportURL = (String) msgContext.getProperty(
                Constants.Configuration.TRANSPORT_URL);

            if (transportURL != null) {
                return new EndpointReference(transportURL);
            } else if (
                (msgContext.getTo() != null) && !msgContext.getTo().hasAnonymousAddress()) {
                return msgContext.getTo();
            }
            return null;
        }

        /**
         * Retirn the OMOutputFormat to be used for the message context passed in
         * @param msgContext the message context
         * @return the OMOutputFormat to be used
         */
        public static OMOutputFormat getOMOutputFormat(MessageContext msgContext) {

            OMOutputFormat format = new OMOutputFormat();
            msgContext.setDoingMTOM(TransportUtils.doWriteMTOM(msgContext));
            msgContext.setDoingSwA(TransportUtils.doWriteSwA(msgContext));
            msgContext.setDoingREST(TransportUtils.isDoingREST(msgContext));
            format.setSOAP11(msgContext.isSOAP11());
            format.setDoOptimize(msgContext.isDoingMTOM());
            format.setDoingSWA(msgContext.isDoingSwA());

            format.setCharSetEncoding(TransportUtils.getCharSetEncoding(msgContext));
            Object mimeBoundaryProperty = msgContext.getProperty(Constants.Configuration.MIME_BOUNDARY);
            if (mimeBoundaryProperty != null) {
                format.setMimeBoundary((String) mimeBoundaryProperty);
            }

            return format;
        }

        /**
         * Get the content type for the message passed in
         * @param msgContext the message
         * @return content type of the message
         */
        public static String getContentType(MessageContext msgContext) {
            Object contentTypeObject = msgContext.getProperty(Constants.Configuration.CONTENT_TYPE);
            if (contentTypeObject != null) {
                return (String) contentTypeObject;
            } else if (msgContext.isDoingREST()) {
                return HTTPConstants.MEDIA_TYPE_APPLICATION_XML;
            } else {
                return getOMOutputFormat(msgContext).getContentType();
            }
        }

        /**
         * Calculate the REST_URL_POSTFIX from the request URI
         * @param uri  - The Request URI - String
         * @param servicePath  String
         * @return  REST_URL_POSTFIX String
         */
        public static String getRestUrlPostfix(String uri, String servicePath){

            String contextServicePath = "/" + servicePath;
            if (uri.startsWith(contextServicePath)) {
                // discard upto servicePath
                uri = uri.substring(uri.indexOf(contextServicePath) +
                		contextServicePath.length());
                // discard [proxy] service name if any
                int pos = uri.indexOf("/", 1);
                if (pos > 0) {
                    uri = uri.substring(pos);
                } else {
                    pos = uri.indexOf("?");
                    if (pos != -1) {
                        uri = uri.substring(pos);
                    } else {
                        uri = "";
                    }
                }
            } else {
                // remove any absolute prefix if any
                int pos = uri.indexOf("://");
                //compute index of beginning of Query Parameter
                int indexOfQueryStart = uri.indexOf("?");

                //Check if there exist a absolute prefix '://' and it is before query parameters
                //To allow query parameters with URLs. ex: /test?a=http://asddd
                if (pos != -1 && ((indexOfQueryStart == -1 || pos < indexOfQueryStart))) {
                    uri = uri.substring(pos + 3);
                }
                pos = uri.indexOf("/");
                if (pos != -1) {
                    uri = uri.substring(pos + 1);
                }
    			// Remove the service prefix
    			if (uri.startsWith(servicePath)) {
    				// discard upto servicePath
    				uri = uri.substring(uri.indexOf(contextServicePath)
    						+ contextServicePath.length());
    				// discard [proxy] service name if any
    				pos = uri.indexOf("/", 1);
    				if (pos > 0) {
    					uri = uri.substring(pos);
    				} else {
    					pos = uri.indexOf("?");
    					if (pos != -1) {
    						uri = uri.substring(pos);
    					} else {
    						uri = "";
    					}
    				}
    			}
            }

            return uri;
        }
    }