1 17 package org.apache.servicemix.http.jetty; 18 19 import java.io.IOException ; 20 import java.io.OutputStream ; 21 import java.net.InetAddress ; 22 import java.net.URL ; 23 import java.net.UnknownHostException ; 24 import java.util.HashMap ; 25 import java.util.Iterator ; 26 import java.util.Map ; 27 import java.util.Set ; 28 29 import javax.jbi.JBIException; 30 import javax.management.MBeanServer ; 31 import javax.servlet.ServletException ; 32 import javax.servlet.http.HttpServletRequest ; 33 import javax.servlet.http.HttpServletResponse ; 34 35 import org.apache.commons.logging.Log; 36 import org.apache.commons.logging.LogFactory; 37 import org.apache.servicemix.http.ContextManager; 38 import org.apache.servicemix.http.HttpBridgeServlet; 39 import org.apache.servicemix.http.HttpConfiguration; 40 import org.apache.servicemix.http.HttpProcessor; 41 import org.apache.servicemix.http.SslParameters; 42 import org.mortbay.component.AbstractLifeCycle; 43 import org.mortbay.jetty.AbstractConnector; 44 import org.mortbay.jetty.Connector; 45 import org.mortbay.jetty.Handler; 46 import org.mortbay.jetty.HttpConnection; 47 import org.mortbay.jetty.HttpMethods; 48 import org.mortbay.jetty.MimeTypes; 49 import org.mortbay.jetty.Server; 50 import org.mortbay.jetty.handler.AbstractHandler; 51 import org.mortbay.jetty.handler.ContextHandler; 52 import org.mortbay.jetty.handler.ContextHandlerCollection; 53 import org.mortbay.jetty.handler.HandlerCollection; 54 import org.mortbay.jetty.security.Constraint; 55 import org.mortbay.jetty.security.ConstraintMapping; 56 import org.mortbay.jetty.security.SecurityHandler; 57 import org.mortbay.jetty.security.SslSocketConnector; 58 import org.mortbay.jetty.servlet.ServletHandler; 59 import org.mortbay.jetty.servlet.ServletHolder; 60 import org.mortbay.jetty.servlet.ServletMapping; 61 import org.mortbay.management.MBeanContainer; 62 import org.mortbay.thread.BoundedThreadPool; 63 import org.mortbay.thread.ThreadPool; 64 import org.mortbay.util.ByteArrayISO8859Writer; 65 import org.mortbay.util.LazyList; 66 import org.mortbay.util.StringUtil; 67 import org.springframework.core.io.ClassPathResource; 68 69 public class JettyContextManager implements ContextManager { 70 71 private static final Log logger = LogFactory.getLog(JettyContextManager.class); 72 73 private Map servers; 74 private HttpConfiguration configuration; 75 private BoundedThreadPool threadPool; 76 private Map sslParams; 77 private MBeanServer mbeanServer; 78 private MBeanContainer mbeanContainer; 79 80 83 public MBeanServer getMBeanServer() { 84 return mbeanServer; 85 } 86 87 90 public void setMBeanServer(MBeanServer mbeanServer) { 91 this.mbeanServer = mbeanServer; 92 } 93 94 public void init() throws Exception { 95 if (configuration == null) { 96 configuration = new HttpConfiguration(); 97 } 98 if (mbeanServer != null && !configuration.isManaged() && configuration.isJettyManagement()) { 99 mbeanContainer = new MBeanContainer(mbeanServer); 100 } 101 servers = new HashMap (); 102 sslParams = new HashMap (); 103 BoundedThreadPool btp = new BoundedThreadPool(); 104 btp.setMaxThreads(this.configuration.getJettyThreadPoolSize()); 105 threadPool = btp; 106 } 107 108 public void shutDown() throws Exception { 109 stop(); 110 } 111 112 public void start() throws Exception { 113 threadPool.start(); 114 for (Iterator it = servers.values().iterator(); it.hasNext();) { 115 Server server = (Server ) it.next(); 116 server.start(); 117 } 118 } 119 120 public void stop() throws Exception { 121 for (Iterator it = servers.values().iterator(); it.hasNext();) { 122 Server server = (Server ) it.next(); 123 server.stop(); 124 } 125 for (Iterator it = servers.values().iterator(); it.hasNext();) { 126 Server server = (Server ) it.next(); 127 server.join(); 128 Connector[] connectors = server.getConnectors(); 129 for (int i = 0; i < connectors.length; i++) { 130 if (connectors[i] instanceof AbstractConnector) { 131 ((AbstractConnector) connectors[i]).join(); 132 } 133 } 134 } 135 threadPool.stop(); 136 } 137 138 public synchronized Object createContext(String strUrl, 139 HttpProcessor processor) throws Exception { 140 URL url = new URL (strUrl); 141 Server server = getServer(url); 142 if (server == null) { 143 server = createServer(url, processor.getSsl()); 144 } else { 145 SslParameters ssl = (SslParameters) sslParams.get(getKey(url)); 147 if (ssl != null && !ssl.equals(processor.getSsl())) { 148 throw new Exception ("An https server is already created on port " + url.getPort() + " but SSL parameters do not match"); 149 } 150 } 151 String path = url.getPath(); 152 if (!path.startsWith("/")) { 153 path = "/" + path; 154 } 155 if (path.endsWith("/")) { 156 path = path.substring(0, path.length() - 1); 157 } 158 HandlerCollection handlerCollection = (HandlerCollection) server.getHandler(); 160 ContextHandlerCollection contexts = (ContextHandlerCollection) handlerCollection.getHandlers()[0]; 161 Handler[] handlers = contexts.getHandlers(); 162 if (handlers != null) { 163 for (int i = 0; i < handlers.length; i++) { 164 if (handlers[i] instanceof ContextHandler) { 165 ContextHandler h = (ContextHandler) handlers[i]; 166 if (h.getContextPath().startsWith(path) || 167 path.startsWith(h.getContextPath())) { 168 throw new Exception ("The requested context for path '" + path + "' overlaps with an existing context for path: '" + h.getContextPath() + "'"); 169 } 170 } 171 } 172 } 173 ContextHandler context = new ContextHandler(); 175 context.setContextPath(path); 176 ServletHolder holder = new ServletHolder(); 177 holder.setName("jbiServlet"); 178 holder.setClassName(HttpBridgeServlet.class.getName()); 179 ServletHandler handler = new ServletHandler(); 180 handler.setServlets(new ServletHolder[] { holder }); 181 ServletMapping mapping = new ServletMapping(); 182 mapping.setServletName("jbiServlet"); 183 mapping.setPathSpec("/*"); 184 handler.setServletMappings(new ServletMapping[] { mapping }); 185 if (processor.getAuthMethod() != null) { 186 SecurityHandler secHandler = new SecurityHandler(); 187 ConstraintMapping constraintMapping = new ConstraintMapping(); 188 Constraint constraint = new Constraint(); 189 constraint.setAuthenticate(true); 190 constraint.setRoles(new String [] { "*" }); 191 constraintMapping.setConstraint(constraint); 192 constraintMapping.setPathSpec("/"); 193 secHandler.setConstraintMappings(new ConstraintMapping[] { constraintMapping }); 194 secHandler.setHandler(handler); 195 secHandler.setAuthMethod(processor.getAuthMethod()); 196 secHandler.setUserRealm(new JaasUserRealm()); 197 context.setHandler(secHandler); 198 } else { 199 context.setHandler(handler); 200 } 201 context.setAttribute("processor", processor); 202 contexts.addHandler(context); 204 context.start(); 205 return context; 206 } 207 208 public synchronized void remove(Object context) throws Exception { 209 ((ContextHandler) context).stop(); 210 for (Iterator it = servers.values().iterator(); it.hasNext();) { 211 Server server = (Server ) it.next(); 212 HandlerCollection handlerCollection = (HandlerCollection) server.getHandler(); 213 ContextHandlerCollection contexts = (ContextHandlerCollection) handlerCollection.getHandlers()[0]; 214 Handler[] handlers = contexts.getHandlers(); 215 if (handlers != null && handlers.length > 0) { 216 contexts.setHandlers((Handler[])LazyList.removeFromArray(handlers, context)); 217 } 218 } 219 } 220 221 protected Server getServer(URL url) { 222 Server server = (Server ) servers.get(getKey(url)); 223 return server; 224 } 225 226 protected String getKey(URL url) { 227 String host = url.getHost(); 228 try { 229 InetAddress addr = InetAddress.getByName(host); 230 if (addr.isAnyLocalAddress()) { 231 host = InetAddress.getLocalHost().getHostName(); 232 } 233 } catch (UnknownHostException e) { 234 } 235 String key = url.getProtocol() + "://" + host + ":" + url.getPort(); 236 return key; 237 } 238 239 protected Server createServer(URL url, SslParameters ssl) throws Exception { 240 boolean isSsl = false; 241 if (url.getProtocol().equals("https")) { 242 if (ssl == null) { 244 throw new IllegalArgumentException ("https protocol required but no ssl parameters found"); 245 } 246 isSsl = true; 247 } else if (!url.getProtocol().equals("http")) { 248 throw new UnsupportedOperationException ("Protocol " + url.getProtocol() + " is not supported"); 249 } 250 Connector connector; 252 if (isSsl && ssl.isManaged()) { 253 String keyStore = ssl.getKeyStore(); 254 if (keyStore == null) { 255 throw new IllegalArgumentException ("keyStore must be set"); 256 } 257 ServiceMixSslSocketConnector sslConnector = new ServiceMixSslSocketConnector(); 258 sslConnector.setSslKeyManagerFactoryAlgorithm(ssl.getKeyManagerFactoryAlgorithm()); 259 sslConnector.setSslTrustManagerFactoryAlgorithm(ssl.getTrustManagerFactoryAlgorithm()); 260 sslConnector.setProtocol(ssl.getProtocol()); 261 sslConnector.setConfidentialPort(url.getPort()); 262 sslConnector.setKeystore(keyStore); 263 sslConnector.setKeyAlias(ssl.getKeyAlias()); 264 sslConnector.setTrustStore(ssl.getTrustStore()); 265 sslConnector.setNeedClientAuth(ssl.isNeedClientAuth()); 266 sslConnector.setWantClientAuth(ssl.isWantClientAuth()); 267 sslConnector.setKeystoreManager(getConfiguration().getKeystoreManager()); 268 connector = sslConnector; 269 } else if (isSsl) { 270 String keyStore = ssl.getKeyStore(); 271 if (keyStore == null) { 272 keyStore = System.getProperty("javax.net.ssl.keyStore", ""); 273 if (keyStore == null) { 274 throw new IllegalArgumentException ("keyStore or system property javax.net.ssl.keyStore must be set"); 275 } 276 } 277 if (keyStore.startsWith("classpath:")) { 278 try { 279 String res = keyStore.substring(10); 280 URL resurl = new ClassPathResource(res).getURL(); 281 keyStore = resurl.toString(); 282 } catch (IOException e) { 283 throw new JBIException("Unable to find keystore " + keyStore, e); 284 } 285 } 286 String keyStorePassword = ssl.getKeyStorePassword(); 287 if (keyStorePassword == null) { 288 keyStorePassword = System.getProperty("javax.net.ssl.keyStorePassword"); 289 if (keyStorePassword == null) { 290 throw new IllegalArgumentException ("keyStorePassword or system property javax.net.ssl.keyStorePassword must be set"); 291 } 292 } 293 SslSocketConnector sslConnector = new SslSocketConnector(); 294 sslConnector.setSslKeyManagerFactoryAlgorithm(ssl.getKeyManagerFactoryAlgorithm()); 295 sslConnector.setSslTrustManagerFactoryAlgorithm(ssl.getTrustManagerFactoryAlgorithm()); 296 sslConnector.setProtocol(ssl.getProtocol()); 297 sslConnector.setConfidentialPort(url.getPort()); 298 sslConnector.setPassword(ssl.getKeyStorePassword()); 299 sslConnector.setKeyPassword(ssl.getKeyPassword() != null ? ssl.getKeyPassword() : keyStorePassword); 300 sslConnector.setKeystore(keyStore); 301 sslConnector.setKeystoreType(ssl.getKeyStoreType()); 302 sslConnector.setNeedClientAuth(ssl.isNeedClientAuth()); 303 sslConnector.setWantClientAuth(ssl.isWantClientAuth()); 304 connector = sslConnector; 305 } else { 306 String connectorClassName = configuration.getJettyConnectorClassName(); 307 try { 308 connector = (Connector) Class.forName(connectorClassName).newInstance(); 309 } catch (Exception e) { 310 logger.warn("Could not create a jetty connector of class '" + connectorClassName + "'. Defaulting to " + HttpConfiguration.DEFAULT_JETTY_CONNECTOR_CLASS_NAME); 311 if (logger.isDebugEnabled()) { 312 logger.debug("Reason: " + e.getMessage(), e); 313 } 314 connector = (Connector) Class.forName(HttpConfiguration.DEFAULT_JETTY_CONNECTOR_CLASS_NAME).newInstance(); 315 } 316 } 317 connector.setHost(url.getHost()); 318 connector.setPort(url.getPort()); 319 Server server = new Server (); 320 server.setThreadPool(new ThreadPoolWrapper()); 321 server.setConnectors(new Connector[] { connector }); 322 ContextHandlerCollection contexts = new ContextHandlerCollection(); 323 HandlerCollection handlers = new HandlerCollection(); 324 handlers.setHandlers(new Handler[] { contexts, new DisplayServiceHandler() }); 325 server.setHandler(handlers); 326 server.start(); 327 servers.put(getKey(url), server); 328 sslParams.put(getKey(url), isSsl ? ssl : null); 329 if (mbeanContainer != null) { 330 server.getContainer().addEventListener(mbeanContainer); 331 } 332 return server; 333 } 334 335 public HttpConfiguration getConfiguration() { 336 return configuration; 337 } 338 339 public void setConfiguration(HttpConfiguration configuration) { 340 this.configuration = configuration; 341 } 342 343 public ThreadPool getThreadPool() { 344 return threadPool; 345 } 346 347 protected class DisplayServiceHandler extends AbstractHandler { 348 349 public void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch) throws IOException , ServletException { 350 if (response.isCommitted() || HttpConnection.getCurrentConnection().getRequest().isHandled()) 351 return; 352 353 String method = request.getMethod(); 354 355 if (!method.equals(HttpMethods.GET) || !request.getRequestURI().equals("/")) { 356 response.sendError(404); 357 return; 358 } 359 360 response.setStatus(404); 361 response.setContentType(MimeTypes.TEXT_HTML); 362 363 ByteArrayISO8859Writer writer = new ByteArrayISO8859Writer(1500); 364 365 String uri = request.getRequestURI(); 366 uri = StringUtil.replace(uri, "<", "<"); 367 uri = StringUtil.replace(uri, ">", ">"); 368 369 writer.write("<HTML>\n<HEAD>\n<TITLE>Error 404 - Not Found"); 370 writer.write("</TITLE>\n<BODY>\n<H2>Error 404 - Not Found.</H2>\n"); 371 writer.write("No service matched or handled this request.<BR>"); 372 writer.write("Known services are: <ul>"); 373 374 Set servers = JettyContextManager.this.servers.keySet(); 375 for (Iterator iter = servers.iterator(); iter.hasNext();) { 376 String serverUri = (String ) iter.next(); 377 Server server = (Server ) JettyContextManager.this.servers.get(serverUri); 378 Handler[] handlers = server.getChildHandlersByClass(ContextHandler.class); 379 for (int i = 0; handlers != null && i < handlers.length; i++) { 380 if (!(handlers[i] instanceof ContextHandler)) { 381 continue; 382 } 383 ContextHandler context = (ContextHandler) handlers[i]; 384 if (context.isStarted()) { 385 writer.write("<li><a HREF=\""); 386 writer.write(serverUri); 387 if (!context.getContextPath().startsWith("/")) { 388 writer.write("/"); 389 } 390 writer.write(context.getContextPath()); 391 if (!context.getContextPath().endsWith("/")) { 392 writer.write("/"); 393 } 394 writer.write("?wsdl\">"); 395 writer.write(serverUri); 396 writer.write(context.getContextPath()); 397 writer.write("</a></li>\n"); 398 } else { 399 writer.write("<li>"); 400 writer.write(serverUri); 401 writer.write(context.getContextPath()); 402 writer.write(" [Stopped]</li>\n"); 403 } 404 } 405 } 406 407 for (int i=0; i < 10; i++) { 408 writer.write("\n<!-- Padding for IE -->"); 409 } 410 411 writer.write("\n</BODY>\n</HTML>\n"); 412 writer.flush(); 413 response.setContentLength(writer.size()); 414 OutputStream out = response.getOutputStream(); 415 writer.writeTo(out); 416 out.close(); 417 } 418 419 } 420 421 protected class ThreadPoolWrapper extends AbstractLifeCycle implements ThreadPool { 422 423 public boolean dispatch(Runnable job) { 424 if (logger.isDebugEnabled()) { 425 logger.debug("Dispatching job: " + job); 426 } 427 return threadPool.dispatch(job); 428 } 429 430 public int getIdleThreads() { 431 return threadPool.getIdleThreads(); 432 } 433 434 public int getThreads() { 435 return threadPool.getThreads(); 436 } 437 438 public void join() throws InterruptedException { 439 } 440 441 public boolean isLowOnThreads() { 442 return threadPool.isLowOnThreads(); 443 } 444 } 445 446 public HttpProcessor getMainProcessor() { 447 throw new IllegalStateException ("ServerManager is not managed"); 448 } 449 450 } 451 | Popular Tags |