# SourceConfiguration.java

    /*
     *  Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
     *
     *  WSO2 Inc. 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.netty.config;

    import org.apache.axis2.AxisFault;
    import org.apache.axis2.context.ConfigurationContext;
    import org.apache.axis2.description.Parameter;
    import org.apache.axis2.description.TransportInDescription;
    import org.apache.axis2.transport.base.ParamUtils;
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.apache.synapse.commons.handlers.MessagingHandler;
    import org.apache.synapse.transport.http.conn.Scheme;
    import org.apache.synapse.transport.netty.BridgeConstants;

    import java.net.UnknownHostException;
    import java.util.List;
    import java.util.Objects;

    /**
     * This class stores the configurations specific to the Listener.
     */
    public class SourceConfiguration extends BaseConfiguration {

        private static final Log LOG = LogFactory.getLog(SourceConfiguration.class);

        private int port;
        private String host;
        private Scheme scheme;
        private String protocol = "2.0";

        private final TransportInDescription inDescription;

        /**
         * WSDL processor for GET requests.
         */
        private HttpGetRequestProcessor httpGetRequestProcessor = null;

        /**
         * The list of handlers to handle the inbound HTTP requests.
         */
        private List<MessagingHandler> messagingHandlers;

        public SourceConfiguration(ConfigurationContext configurationContext, TransportInDescription inDescription,
                                   Scheme scheme, List<MessagingHandler> messagingHandler) {

            super(configurationContext);
            this.inDescription = inDescription;
            this.scheme = scheme;
            this.messagingHandlers = messagingHandlers;
        }

        public void build() throws AxisFault {

            super.build();

            populatePort();

            populateHostname();

            populateHTTPProtocol();

            populateHTTPGETRequestProcessor();

            populatePreserveHTTPHeaders(conf.getResponsePreserveHttpHeaders());
        }

        private void populatePort() throws AxisFault {
            port = ParamUtils.getRequiredParamInt(inDescription, BridgeConstants.PORT_PARAM);
            if (port == 0) {
                throw new AxisFault("Listener port is not defined!");
            }
        }

        private void populateHostname() {
            Parameter hostParameter = inDescription.getParameter(BridgeConstants.HOSTNAME_PARAM);
            if (Objects.nonNull(hostParameter) && Objects.nonNull(hostParameter.getValue())) {
                host = ((String) hostParameter.getValue()).trim();
            } else if (conf.getServerHostname() != null) {
                host = conf.getServerHostname().trim();
            } else {
                try {
                    host = java.net.InetAddress.getLocalHost().getHostName();
                } catch (UnknownHostException e) {
                    LOG.warn("Unable to lookup local host name. Hence, using 'localhost'");
                    host = BridgeConstants.HTTP_DEFAULT_HOST;
                }
            }
        }

        private void populateHTTPProtocol() {
            Parameter protocolParameter = inDescription.getParameter(BridgeConstants.HTTP_PROTOCOL_VERSIONS_PARAM);
            if (Objects.nonNull(protocolParameter) && Objects.nonNull(protocolParameter.getValue())) {
                String protocol = ((String) protocolParameter.getValue()).trim();
                if (!protocol.isEmpty()) {
                    this.protocol = protocol;
                }
            }
        }

        private void populateHTTPGETRequestProcessor() throws AxisFault {
            String httpGetRequestProcessorClass = conf.getHttpGetRequestProcessorClass();
            httpGetRequestProcessor = createHttpGetProcessor(httpGetRequestProcessorClass);
            if (httpGetRequestProcessor == null) {
                handleException("Cannot create HttpGetRequestProcessor");
            }
        }

        private HttpGetRequestProcessor createHttpGetProcessor(String clss) throws AxisFault {

            Object obj = null;
            try {
                obj = Class.forName(clss).newInstance();
            } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
                handleException("Error occurred while creating HTTPGETRequestProcessor", e);
            }

            if (obj instanceof HttpGetRequestProcessor) {
                return (HttpGetRequestProcessor) obj;
            } else {
                handleException("Error occurred while creating HTTPGETRequestProcessor. The provided class should be" +
                        "an implementation of interface org.apache.synapse.transport.netty.config.HttpGetRequestProcessor");
            }
            return null;
        }

        private void handleException(String msg, Exception e) throws AxisFault {

            LOG.error(msg, e);
            throw new AxisFault(msg, e);
        }

        private void handleException(String msg) throws AxisFault {

            LOG.error(msg);
            throw new AxisFault(msg);
        }

        public int getPort() {

            return port;
        }

        public void setPort(int port) {

            this.port = port;
        }

        public String getHost() {

            return host;
        }

        public void setHost(String host) {

            this.host = host;
        }

        public Scheme getScheme() {

            return scheme;
        }

        public void setScheme(Scheme scheme) {

            this.scheme = scheme;
        }

        public HttpGetRequestProcessor getHttpGetRequestProcessor() {

            return httpGetRequestProcessor;
        }

        public List<MessagingHandler> getMessagingHandlers() {

            return messagingHandlers;
        }

        public void setMessagingHandlers(List<MessagingHandler> messagingHandlers) {

            this.messagingHandlers = messagingHandlers;
        }

        public String getProtocol() {

            return protocol;
        }

        public void setProtocol(String protocol) {

            this.protocol = protocol;
        }

        public TransportInDescription getInDescription() {

            return inDescription;
        }
    }