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.http;
018    
019    import java.util.HashMap;
020    
021    import org.mortbay.jetty.Connector;
022    import org.mortbay.jetty.Server;
023    import org.mortbay.jetty.nio.SelectChannelConnector;
024    import org.mortbay.jetty.security.SslSocketConnector;
025    import org.mortbay.jetty.servlet.Context;
026    import org.mortbay.jetty.servlet.ServletHolder;
027    
028    /**
029     * An HttpComponent which starts an embedded Jetty for to handle consuming from
030     * http endpoints.
031     * 
032     * @version $Revision: 525142 $
033     */
034    public class JettyHttpComponent extends HttpComponent {
035    
036        Server server;
037    
038        class ConnectorRef {
039            Connector connector;
040            int refCount;
041    
042            public ConnectorRef(Connector connector) {
043                this.connector = connector;
044                increment();
045            }
046    
047            public int increment() {
048                return ++refCount;
049            }
050    
051            public int decrement() {
052                return --refCount;
053            }
054        }
055    
056        final HashMap<String, ConnectorRef> connectors = new HashMap<String, ConnectorRef>();
057    
058        @Override
059        protected void doStart() throws Exception {
060            server = createServer();
061            super.doStart();
062        }
063    
064        private Server createServer() throws Exception {
065            setCamelServlet(new CamelServlet());
066    
067            Server server = new Server();
068            Context context = new Context(Context.NO_SECURITY | Context.NO_SESSIONS);
069    
070            context.setContextPath("/");
071            ServletHolder holder = new ServletHolder();
072            holder.setServlet(getCamelServlet());
073            context.addServlet(holder, "/*");
074            server.setHandler(context);
075    
076            server.start();
077            return server;
078        }
079    
080        @Override
081        protected void doStop() throws Exception {
082            for (ConnectorRef connectorRef : connectors.values()) {
083                connectorRef.connector.stop();
084            }
085            connectors.clear();
086    
087            server.stop();
088            super.doStop();
089        }
090    
091        @Override
092        public void connect(HttpConsumer consumer) throws Exception {
093    
094            // Make sure that there is a connector for the requested endpoint.
095            HttpEndpoint endpoint = (HttpEndpoint)consumer.getEndpoint();
096            String connectorKey = endpoint.getProtocol() + ":" + endpoint.getPort();
097    
098            synchronized (connectors) {
099                ConnectorRef connectorRef = connectors.get(connectorKey);
100                if (connectorRef == null) {
101                    Connector connector;
102                    if ("https".equals(endpoint.getProtocol())) {
103                        connector = new SslSocketConnector();
104                    } else {
105                        connector = new SelectChannelConnector();
106                    }
107                    connector.setPort(endpoint.getPort());
108                    server.addConnector(connector);
109                    connector.start();
110                    connectorRef = new ConnectorRef(connector);
111                } else {
112                    // ref track the connector
113                    connectorRef.increment();
114                }
115            }
116    
117            super.connect(consumer);
118        }
119    
120        @Override
121        public void disconnect(HttpConsumer consumer) throws Exception {
122            super.disconnect(consumer);
123    
124            // If the connector is not needed anymore.. then stop it.
125            HttpEndpoint endpoint = (HttpEndpoint)consumer.getEndpoint();
126            String connectorKey = endpoint.getProtocol() + ":" + endpoint.getPort();
127    
128            synchronized (connectors) {
129                ConnectorRef connectorRef = connectors.get(connectorKey);
130                if (connectorRef != null) {
131                    if (connectorRef.decrement() == 0) {
132                        server.removeConnector(connectorRef.connector);
133                        connectorRef.connector.stop();
134                        connectors.remove(connectorKey);
135                    }
136                }
137            }
138        }
139    }