summaryrefslogtreecommitdiffstats
path: root/branches/sca-java-integration/sca/services/transports/http.jetty/src/main/java/org/apache/tuscany/service/jetty/JettyServiceImpl.java
diff options
context:
space:
mode:
Diffstat (limited to 'branches/sca-java-integration/sca/services/transports/http.jetty/src/main/java/org/apache/tuscany/service/jetty/JettyServiceImpl.java')
-rw-r--r--branches/sca-java-integration/sca/services/transports/http.jetty/src/main/java/org/apache/tuscany/service/jetty/JettyServiceImpl.java356
1 files changed, 356 insertions, 0 deletions
diff --git a/branches/sca-java-integration/sca/services/transports/http.jetty/src/main/java/org/apache/tuscany/service/jetty/JettyServiceImpl.java b/branches/sca-java-integration/sca/services/transports/http.jetty/src/main/java/org/apache/tuscany/service/jetty/JettyServiceImpl.java
new file mode 100644
index 0000000000..e71e8333d6
--- /dev/null
+++ b/branches/sca-java-integration/sca/services/transports/http.jetty/src/main/java/org/apache/tuscany/service/jetty/JettyServiceImpl.java
@@ -0,0 +1,356 @@
+/*
+ * 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.tuscany.service.jetty;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.resource.spi.work.Work;
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+
+import org.apache.tuscany.api.annotation.Monitor;
+import org.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.component.SCAObjectStartException;
+import org.apache.tuscany.spi.host.ServletHost;
+import org.apache.tuscany.spi.services.work.WorkScheduler;
+import org.mortbay.jetty.Connector;
+import org.mortbay.jetty.Server;
+import org.mortbay.jetty.handler.ContextHandler;
+import org.mortbay.jetty.nio.SelectChannelConnector;
+import org.mortbay.jetty.security.SslSocketConnector;
+import org.mortbay.jetty.servlet.ServletHandler;
+import org.mortbay.jetty.servlet.ServletHolder;
+import org.mortbay.jetty.servlet.ServletMapping;
+import org.mortbay.jetty.servlet.SessionHandler;
+import org.mortbay.log.Log;
+import org.mortbay.log.Logger;
+import org.mortbay.thread.BoundedThreadPool;
+import org.mortbay.thread.ThreadPool;
+import org.osoa.sca.annotations.Destroy;
+import org.osoa.sca.annotations.EagerInit;
+import org.osoa.sca.annotations.Init;
+import org.osoa.sca.annotations.Property;
+import org.osoa.sca.annotations.Scope;
+import org.osoa.sca.annotations.Service;
+
+/**
+ * Implements an HTTP transport service using Jetty.
+ *
+ * @version $$Rev$$ $$Date: 2007-02-21 13:28:30 +0000 (Wed, 21 Feb
+ * 2007) $$
+ */
+@Scope("COMPOSITE")
+@Service(ServletHost.class)
+@EagerInit
+public class JettyServiceImpl implements JettyService {
+
+ private static final String ROOT = "/";
+ private static final int ERROR = 0;
+ private static final int UNINITIALIZED = 0;
+ private static final int STARTING = 1;
+ private static final int STARTED = 2;
+ private static final int STOPPING = 3;
+ private static final int STOPPED = 4;
+
+ private final Object joinLock = new Object();
+ private int state = UNINITIALIZED;
+ private int httpPort = 8080;
+ private int httpsPort = 8484;
+ private String keystore;
+ private String certPassword;
+ private String keyPassword;
+ private boolean sendServerVersion;
+ private boolean https;
+ private TransportMonitor monitor;
+ private WorkScheduler scheduler;
+ private boolean debug;
+ private Server server;
+ private Connector connector;
+ private ServletHandler servletHandler;
+
+ static {
+ // hack to replace the static Jetty logger
+ System.setProperty("org.mortbay.log.class", JettyLogger.class.getName());
+
+ }
+
+ public JettyServiceImpl(@Monitor
+ TransportMonitor monitor, @Autowire
+ WorkScheduler scheduler) {
+ this.monitor = monitor;
+ this.scheduler = scheduler;
+ // Jetty uses a static logger, so jam in the monitor into a static
+ // reference
+ Logger logger = Log.getLogger(null);
+ if (logger instanceof JettyLogger) {
+ JettyLogger jettyLogger = (JettyLogger)logger;
+ jettyLogger.setMonitor(this.monitor);
+ if (debug) {
+ jettyLogger.setDebugEnabled(true);
+ }
+ }
+
+ httpPort = Integer.getInteger("Tuscany.JettyService.httpPort", httpPort);
+
+ }
+
+ @Property
+ public void setHttpPort(int httpPort) {
+ this.httpPort = httpPort;
+ }
+
+ @Property
+ public void setHttpsPort(int httpsPort) {
+ this.httpsPort = httpsPort;
+ }
+
+ @Property
+ public void setSendServerVersion(boolean sendServerVersion) {
+ this.sendServerVersion = sendServerVersion;
+ }
+
+ @Property
+ public void setHttps(boolean https) {
+ this.https = https;
+ }
+
+ @Property
+ public void setKeystore(String keystore) {
+ this.keystore = keystore;
+ }
+
+ @Property
+ public void setCertPassword(String certPassword) {
+ this.certPassword = certPassword;
+ }
+
+ @Property
+ public void setKeyPassword(String keyPassword) {
+ this.keyPassword = keyPassword;
+ }
+
+ @Property
+ public void setDebug(boolean val) {
+ debug = val;
+ }
+
+ @Init
+ public void init() throws Exception {
+ state = STARTING;
+ }
+
+ @Destroy
+ public void destroy() throws Exception {
+ if (state == STARTED) {
+ state = STOPPING;
+ synchronized (joinLock) {
+ joinLock.notifyAll();
+ }
+ server.stop();
+ state = STOPPED;
+ // monitor.shutdown();
+ }
+ }
+
+ public void registerMapping(String path, Servlet servlet) {
+ if (state == STARTING) {
+
+ try {
+ server = new Server();
+ if (scheduler == null) {
+ BoundedThreadPool threadPool = new BoundedThreadPool();
+ threadPool.setMaxThreads(100);
+ server.setThreadPool(threadPool);
+ } else {
+ server.setThreadPool(new TuscanyThreadPool());
+ }
+ if (connector == null) {
+ if (https) {
+ Connector httpConnector = new SelectChannelConnector();
+ httpConnector.setPort(httpPort);
+ SslSocketConnector sslConnector = new SslSocketConnector();
+ sslConnector.setPort(httpsPort);
+ sslConnector.setKeystore(keystore);
+ sslConnector.setPassword(certPassword);
+ sslConnector.setKeyPassword(keyPassword);
+ server.setConnectors(new Connector[] {httpConnector, sslConnector});
+ } else {
+ SelectChannelConnector selectConnector = new SelectChannelConnector();
+ selectConnector.setPort(httpPort);
+ server.setConnectors(new Connector[] {selectConnector});
+ }
+ } else {
+ connector.setPort(httpPort);
+ server.setConnectors(new Connector[] {connector});
+ }
+
+ ContextHandler contextHandler = new ContextHandler();
+ contextHandler.setContextPath(ROOT);
+ server.setHandler(contextHandler);
+
+ SessionHandler sessionHandler = new SessionHandler();
+ servletHandler = new ServletHandler();
+ sessionHandler.addHandler(servletHandler);
+
+ contextHandler.setHandler(sessionHandler);
+
+ server.setStopAtShutdown(true);
+ server.setSendServerVersion(sendServerVersion);
+ // monitor.started();
+ server.start();
+ state = STARTED;
+ } catch (Exception e) {
+ state = ERROR;
+ throw new SCAObjectStartException(e);
+ }
+ }
+
+ ServletHolder holder = new ServletHolder(servlet);
+ servletHandler.addServlet(holder);
+ ServletMapping mapping = new ServletMapping();
+ mapping.setServletName(holder.getName());
+ mapping.setPathSpec(path);
+ servletHandler.addServletMapping(mapping);
+ }
+
+ public Servlet unregisterMapping(String path) {
+ Servlet removedServlet = null;
+ List<ServletMapping> mappings = new ArrayList(Arrays.asList(servletHandler.getServletMappings()));
+ for (ServletMapping mapping : mappings) {
+ if (Arrays.asList(mapping.getPathSpecs()).contains(path)) {
+ try {
+ removedServlet = servletHandler.getServlet(mapping.getServletName()).getServlet();
+ } catch (ServletException e) {
+ throw new IllegalStateException(e);
+ }
+ mappings.remove(mapping);
+ break;
+ }
+ }
+ if (removedServlet != null) {
+ servletHandler.setServletMappings((ServletMapping[])mappings.toArray(new ServletMapping[mappings.size()]));
+ }
+ return removedServlet;
+ }
+
+ public boolean isMappingRegistered(String path) {
+ ServletMapping[] mappings = servletHandler.getServletMappings();
+ for (ServletMapping mapping : mappings) {
+ if (Arrays.asList(mapping.getPathSpecs()).contains(path)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void registerComposite(File compositeLocation) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public Server getServer() {
+ return server;
+ }
+
+ public int getHttpPort() {
+ return httpPort;
+ }
+
+ /**
+ * An integration wrapper to enable use of a {@link WorkScheduler} with
+ * Jetty
+ */
+ private class TuscanyThreadPool implements ThreadPool {
+
+ public boolean dispatch(Runnable job) {
+ scheduler.scheduleWork(new TuscanyWork(job));
+ return true;
+ }
+
+ public void join() throws InterruptedException {
+ synchronized (joinLock) {
+ joinLock.wait();
+ }
+ }
+
+ public int getThreads() {
+ throw new UnsupportedOperationException();
+ }
+
+ public int getIdleThreads() {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean isLowOnThreads() {
+ // TODO FIXME
+ return false;
+ }
+
+ public void start() throws Exception {
+
+ }
+
+ public void stop() throws Exception {
+
+ }
+
+ public boolean isRunning() {
+ return state == STARTING || state == STARTED;
+ }
+
+ public boolean isStarted() {
+ return state == STARTED;
+ }
+
+ public boolean isStarting() {
+ return state == STARTING;
+ }
+
+ public boolean isStopping() {
+ return state == STOPPING;
+ }
+
+ public boolean isFailed() {
+ return state == ERROR;
+ }
+ }
+
+ /**
+ * A unit of work dispatched to the runtime work scheduler
+ */
+ private class TuscanyWork implements Work {
+
+ Runnable job;
+
+ public TuscanyWork(Runnable job) {
+ this.job = job;
+ }
+
+ public void release() {
+ }
+
+ public void run() {
+ job.run();
+ }
+ }
+
+}