# ListenerContextBuilder.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;

    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.net.InetAddress;
    import java.net.UnknownHostException;
    import java.util.Locale;
    import java.util.Properties;

    import javax.xml.namespace.QName;
    import javax.xml.stream.XMLStreamException;

    import org.apache.axiom.om.OMAttribute;
    import org.apache.axiom.om.OMElement;
    import org.apache.axiom.om.impl.builder.StAXOMBuilder;
    import org.apache.axis2.AxisFault;
    import org.apache.axis2.description.Parameter;
    import org.apache.axis2.description.TransportInDescription;
    import org.apache.axis2.transport.TransportListener;
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.apache.synapse.commons.evaluators.EvaluatorConstants;
    import org.apache.synapse.commons.evaluators.EvaluatorException;
    import org.apache.synapse.commons.evaluators.Parser;
    import org.apache.synapse.commons.executors.ExecutorConstants;
    import org.apache.synapse.commons.executors.PriorityExecutor;
    import org.apache.synapse.commons.executors.config.PriorityExecutorFactory;

    class ListenerContextBuilder {

        private final Log log = LogFactory.getLog(ListenerContextBuilder.class);

        private final TransportInDescription transportIn;
        private final String name;

        private String host = "localhost";
        private int port = 8280;
        private PriorityExecutor executor = null;
        private Parser parser = null;
        private boolean restDispatching = true;
        private HttpGetRequestProcessor httpGetRequestProcessor = null;
        private InetAddress bindAddress;

        public ListenerContextBuilder(final TransportInDescription transportIn) {
            this.transportIn = transportIn;
            this.name = transportIn.getName().toUpperCase(Locale.US);
        }

        public ListenerContextBuilder parse() throws AxisFault {
            Parameter param = transportIn.getParameter(TransportListener.HOST_ADDRESS);
            if (param != null) {
                host = ((String) param.getValue()).trim();
            } else {
                try {
                    host = InetAddress.getLocalHost().getHostName();
                } catch (UnknownHostException e) {
                    log.warn("Unable to lookup local host name, using 'localhost'");
                }
            }

            param = transportIn.getParameter(TransportListener.PARAM_PORT);
            if (param != null) {
                port = Integer.parseInt((String) param.getValue());
            }

            int portOffset = 0;

            try {
                portOffset = Integer.parseInt(System.getProperty(NhttpConstants.PORT_OFFSET, "0"));
            } catch (NumberFormatException e) {
                handleException("portOffset System property should be a valid Integer", e);
            }

            port = port + portOffset;

            if (param != null) {
                param.setValue(String.valueOf(port));
                param.getParameterElement().setText(String.valueOf(port));
            }

            param = transportIn.getParameter(NhttpConstants.BIND_ADDRESS);
            if (param != null) {
                String s = ((String) param.getValue()).trim();
                try {
                    bindAddress = InetAddress.getByName(s);
                } catch (UnknownHostException ex) {
                    throw AxisFault.makeFault(ex);
                }
            }

            // create the priority based executor and parser
            param = transportIn.getParameter(NhttpConstants.PRIORITY_CONFIG_FILE_NAME);
            if (param != null && param.getValue() != null) {
                String fileName = param.getValue().toString();
                OMElement definitions = null;
                try {
                    FileInputStream fis = new FileInputStream(fileName);
                    definitions = new StAXOMBuilder(fis).getDocumentElement();
                    definitions.build();
                } catch (FileNotFoundException e) {
                    handleException("Priority configuration file cannot be found : " + fileName, e);
                } catch (XMLStreamException e) {
                    handleException("Error parsing priority configuration xml file " + fileName, e);
                }

                executor = createPriorityExecutor(definitions);
                parser = createParser(definitions);

                if (log.isInfoEnabled()) {
                    log.info(name + " Created a priority based executor from the configuration: " +
                        fileName);
                }
            }

            param = transportIn.getParameter(NhttpConstants.DISABLE_REST_SERVICE_DISPATCHING);
            if (param != null && param.getValue() != null) {
                if (param.getValue().equals("true")) {
                    restDispatching = false;
                }
            }

            // create http Get processor
            param = transportIn.getParameter(NhttpConstants.HTTP_GET_PROCESSOR);
            if (param != null && param.getValue() != null) {
                httpGetRequestProcessor = createHttpGetProcessor(param.getValue().toString());
                if (httpGetRequestProcessor == null) {
                    handleException("Cannot create HttpGetRequestProcessor");
                }
            } else {
                httpGetRequestProcessor = new DefaultHttpGetProcessor();
            }
            return this;
        }

        private PriorityExecutor createPriorityExecutor(final OMElement definitions) throws AxisFault {
            assert definitions != null;
            OMElement executorElem = definitions.getFirstChildWithName(
                    new QName(ExecutorConstants.PRIORITY_EXECUTOR));

            if (executorElem == null) {
                handleException(ExecutorConstants.PRIORITY_EXECUTOR +
                        " configuration is mandatory for priority based routing");
            }

            PriorityExecutor executor = PriorityExecutorFactory.createExecutor(
                    null, executorElem, false, new Properties());
            executor.init();
            return executor;
        }

        private Parser createParser(final OMElement definitions) throws AxisFault {
            OMElement conditionsElem = definitions.getFirstChildWithName(
                new QName(EvaluatorConstants.CONDITIONS));
            if (conditionsElem == null) {
                handleException("Conditions configuration is mandatory for priority based routing");
            }

            assert conditionsElem != null;
            OMAttribute defPriorityAttr = conditionsElem.getAttribute(
                    new QName(EvaluatorConstants.DEFAULT_PRIORITY));
            Parser parser;
            if (defPriorityAttr != null) {
                parser = new Parser(Integer.parseInt(defPriorityAttr.getAttributeValue()));
            } else {
                parser = new Parser();
            }

            try {
                parser.init(conditionsElem);
            } catch (EvaluatorException e) {
                handleException("Invalid " + EvaluatorConstants.CONDITIONS +
                        " configuration for priority based mediation", e);
            }
            return parser;
        }

        private HttpGetRequestProcessor createHttpGetProcessor(String str) throws AxisFault {
            Object obj = null;
            try {
                obj = Class.forName(str).newInstance();
            } catch (ClassNotFoundException e) {
                handleException("Error creating WSDL processor", e);
            } catch (InstantiationException e) {
                handleException("Error creating WSDL processor", e);
            } catch (IllegalAccessException e) {
                handleException("Error creating WSDL processor", e);
            }

            if (obj instanceof HttpGetRequestProcessor) {
                return (HttpGetRequestProcessor) obj;
            } else {
                handleException("Error creating WSDL processor. The HttpProcessor should be of type " +
                        "org.apache.synapse.transport.nhttp.HttpGetRequestProcessor");
            }

            return null;
        }

        private void handleException(String msg, Exception e) throws AxisFault {
            log.error(name + " " + msg, e);
            throw new AxisFault(msg, e);
        }

        private void handleException(String msg) throws AxisFault {
            log.error(name + " " + msg);
            throw new AxisFault(msg);
        }

        public ListenerContext build() throws AxisFault {
            return new ListenerContext(
                transportIn, executor, parser, restDispatching,
                httpGetRequestProcessor,  host, port, bindAddress);
        }

    }