001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.camel.component.jhc;
018    
019    import java.io.IOException;
020    import java.io.InterruptedIOException;
021    import java.net.InetSocketAddress;
022    import java.net.SocketAddress;
023    import java.util.concurrent.ThreadFactory;
024    
025    import javax.net.ssl.SSLContext;
026    
027    import org.apache.commons.logging.Log;
028    import org.apache.commons.logging.LogFactory;
029    import org.apache.http.impl.nio.DefaultServerIOEventDispatch;
030    import org.apache.http.impl.nio.reactor.DefaultListeningIOReactor;
031    import org.apache.http.impl.nio.reactor.SSLServerIOEventDispatch;
032    import org.apache.http.nio.reactor.IOEventDispatch;
033    import org.apache.http.nio.reactor.IOReactorException;
034    import org.apache.http.nio.reactor.ListeningIOReactor;
035    import org.apache.http.params.HttpParams;
036    import org.apache.http.protocol.HttpRequestHandlerRegistry;
037    
038    public class JhcServerEngine {
039        private static final Log LOG = LogFactory.getLog(JhcServerEngine.class);
040        private final HttpParams params;
041        private int port;
042        private String protocol;
043        private int nbThreads = 2;
044        private ListeningIOReactor ioReactor;
045        private ThreadFactory threadFactory;
046        private Thread runner;
047        private SSLContext sslContext;
048        private AsyncBufferingHttpServiceHandler serviceHandler;
049        private HttpRequestHandlerRegistry handlerRegistry;
050        private boolean isStarted;
051        private int referenceCounter;
052    
053        JhcServerEngine(HttpParams params, int port, String protocol) {
054            this.params = params;
055            serviceHandler = new AsyncBufferingHttpServiceHandler(params);
056            handlerRegistry = new HttpRequestHandlerRegistry();
057            serviceHandler.setHandlerResolver(handlerRegistry);
058            this.port = port;
059            this.protocol = protocol;
060        }
061    
062    
063        public int getPort() {
064            return port;
065        }
066    
067        public String getProtocol() {
068            return this.protocol;
069        }
070    
071        public void setSslContext(SSLContext sslContext) {
072            this.sslContext = sslContext;
073        }
074    
075        public SSLContext getSslContext() {
076            return this.sslContext;
077        }
078    
079        public synchronized void register(String pattern, AsyncHttpRequestHandler handler) {
080            handlerRegistry.register(pattern, handler);
081            referenceCounter++;
082        }
083    
084        public synchronized void unregister(String pattern) {
085            handlerRegistry.unregister(pattern);
086            referenceCounter--;
087        }
088    
089        public int getReferenceCounter() {
090            return referenceCounter;
091        }
092    
093        public boolean isStarted() {
094            return isStarted;
095        }
096    
097        public void start() throws IOReactorException {
098            final SocketAddress addr = new InetSocketAddress(port);
099            ioReactor = new DefaultListeningIOReactor(nbThreads, threadFactory, params);
100    
101            final IOEventDispatch ioEventDispatch;
102            if ("https".equals(protocol)) {
103                ioEventDispatch = new SSLServerIOEventDispatch(serviceHandler, sslContext, params);
104            } else {
105                ioEventDispatch = new DefaultServerIOEventDispatch(serviceHandler, params);
106            }
107            runner = new Thread() {
108                public void run() {
109                    try {
110                        ioReactor.listen(addr);
111                        isStarted = true;
112                        ioReactor.execute(ioEventDispatch);
113                    } catch (InterruptedIOException ex) {
114                        LOG.info("Interrupted");
115                    } catch (IOException e) {
116                        LOG.warn("I/O error: " + e.getMessage());
117                    }
118                    LOG.debug("Shutdown");
119                }
120            };
121            runner.start();
122        }
123    
124        public void stop() throws IOException {
125            LOG.debug("Stopping the jhc ioReactor ");
126            ioReactor.shutdown();
127            LOG.debug("Waiting the runner");
128            try {
129                runner.join();
130            } catch (InterruptedException e) {
131                //do nothing here
132            }
133            isStarted = false;
134            LOG.debug("Runner stopped");
135        }
136    }