/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 2009 Bull S.A.S.
 * Contact: jonas-team@ow2.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 *
 * --------------------------------------------------------------------------
 * $Id: URLUtils.java 20050 2010-07-02 13:40:21Z benoitf $
 * --------------------------------------------------------------------------
 */

package org.ow2.jonas.web.tomcat7.ws;

import org.apache.catalina.Engine;
import org.apache.catalina.Host;
import org.apache.catalina.Service;
import org.apache.catalina.connector.Connector;
import org.ow2.jonas.ws.jaxws.PortMetaData;

/**
 * The URLUtils a helper class for URL management operations.
 *
 * @author Guillaume Sauthier
 */
public class URLUtils {

    /**
     * Compute a possible local endpoint URL.
     * @param portMetadata port related metadata
     * @param host host deploying the new context
     * @return a possible local endpoint URL or null if computation was impossible
     */
    static String getEndpointURL(final PortMetaData portMetadata, final Host host) {

        // Find hostname
        String hostname = host.getName();

        // Find url-pattern
        String pattern = portMetadata.getUrlPattern();

        // Find the connectors associated to this Host
        Engine engine = (Engine) host.getParent();
        Service service = engine.getService();
        Connector[] connectors = service.findConnectors();

        // Find an HTTP and/or an HTTPS Connector
        Connector httpConnector = null;
        Connector httpsConnector = null;
        for (Connector connector : connectors) {
            String scheme = connector.getScheme();

            if ("https".equals(scheme)) {
                httpsConnector = connector;
            }

            if ("http".equals(scheme)) {
                httpConnector = connector;
            }
        }

        // Compute the endpoint URL
        StringBuffer sb = new StringBuffer();
        if (httpConnector != null) {
            // Prefer HTTP
            sb.append("http://");
            sb.append(hostname);
            sb.append(":");
            int port = httpConnector.getPort();
            int proxyPort = httpConnector.getProxyPort();
            if (proxyPort != 0) {
                port = proxyPort;
            }
            sb.append(port);
            sb.append(getContextRoot(portMetadata));
            sb.append(pattern);

            return sb.toString();
        } else if (httpsConnector != null) {
            // Fallback on HTTPS if available
            sb.append("https://");
            sb.append(hostname);
            sb.append(":");
            int port = httpsConnector.getPort();
            int proxyPort = httpsConnector.getProxyPort();
            if (proxyPort != 0) {
                port = proxyPort;
            }
            sb.append(port);
            sb.append(getContextRoot(portMetadata));
            sb.append(pattern);

            return sb.toString();
        }

        return null;
    }

    /**
     * Fix the context-root by prefixing it with a leading '/' (if missing).
     * @param portMetadata port related metadata
     * @return a valid context-root from the port metadata
     */
    protected static String getContextRoot(final PortMetaData portMetadata) {
        String contextName = portMetadata.getContextRoot();
        if (!contextName.startsWith("/")) {
            contextName = "/" + contextName;
        }
        return contextName;
    }

    /**
     * @param mappings candidates mappins
     * @return a valid mapping selected from the candidates
     */
    public static String findValidUrlPattern(final String[] mappings) {
        if ((mappings == null) || (mappings.length == 0)) {
            // Empty mappings
            return null;
        }

        for (String mapping : mappings) {
            if (containsNoWildcards(mapping)) {
                return mapping;
            }
        }

        // Found no suitable mapping
        return null;
    }

    /**
     * @param mapping candidate
     * @return true if the candidate is a valid mapping value.
     */
    private static boolean containsNoWildcards(final String mapping) {
        return (mapping.indexOf('*') == -1);
    }
}
