001 /* 002 * Sonar, open source software quality management tool. 003 * Copyright (C) 2008-2012 SonarSource 004 * mailto:contact AT sonarsource DOT com 005 * 006 * Sonar is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 3 of the License, or (at your option) any later version. 010 * 011 * Sonar is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with Sonar; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 019 */ 020 package org.sonar.application; 021 022 import org.apache.commons.io.FileUtils; 023 import org.mortbay.jetty.NCSARequestLog; 024 import org.mortbay.jetty.Server; 025 import org.mortbay.jetty.handler.RequestLogHandler; 026 import org.mortbay.jetty.nio.SelectChannelConnector; 027 import org.mortbay.jetty.webapp.WebAppContext; 028 import org.mortbay.thread.QueuedThreadPool; 029 import org.mortbay.xml.XmlConfiguration; 030 031 import java.io.File; 032 import java.io.IOException; 033 import java.net.URISyntaxException; 034 import java.net.URL; 035 import java.util.ArrayList; 036 import java.util.Collection; 037 import java.util.List; 038 039 public class JettyEmbedder { 040 041 private final Server server; 042 private final String host; 043 private final int port; 044 private final String contextPath; 045 046 public JettyEmbedder(String host, int port, String contextPath, URL configurationURL) throws Exception { 047 this.host = host.trim(); 048 this.port = port; 049 this.contextPath = contextPath; 050 server = new Server(); 051 052 if (configurationURL == null) { 053 configureProgrammatically(); 054 055 } else { 056 System.setProperty("jetty.host", this.host); 057 System.setProperty("jetty.port", String.valueOf(port)); 058 System.setProperty("jetty.context", contextPath); 059 XmlConfiguration configuration = new XmlConfiguration(configurationURL); 060 configuration.configure(server); 061 } 062 } 063 064 /** 065 * for tests 066 */ 067 JettyEmbedder(String host, int port) throws Exception { 068 this(host, port, null, null); 069 } 070 071 public void start() throws Exception { 072 server.start(); 073 074 Runtime.getRuntime().addShutdownHook(new Thread() { 075 @Override 076 public void run() { 077 try { 078 server.stop(); 079 } catch (Exception e) { 080 System.err.println("Can not stop the Jetty server"); 081 e.printStackTrace(); 082 } 083 } 084 }); 085 } 086 087 private Server configureProgrammatically() throws URISyntaxException, IOException { 088 configureServer(); 089 WebAppContext context = new WebAppContext(getPath("/war/sonar-server"), contextPath); 090 server.addHandler(context); 091 return server; 092 } 093 094 public void configureRequestLogs(String filenamePattern) { 095 RequestLogHandler requestLogHandler = new RequestLogHandler(); 096 NCSARequestLog requestLog = new NCSARequestLog(filenamePattern); 097 requestLog.setRetainDays(7); 098 requestLog.setAppend(true); 099 requestLog.setExtended(true); 100 requestLog.setLogTimeZone("GMT"); 101 requestLogHandler.setRequestLog(requestLog); 102 server.addHandler(requestLogHandler); 103 } 104 105 private void configureServer() throws URISyntaxException { 106 QueuedThreadPool threadPool = new QueuedThreadPool(); 107 threadPool.setMinThreads(5); 108 threadPool.setMaxThreads(50); 109 threadPool.setLowThreads(10); 110 server.setThreadPool(threadPool); 111 SelectChannelConnector connector = new SelectChannelConnector(); 112 connector.setHost(host); 113 connector.setPort(port); 114 connector.setStatsOn(false); 115 connector.setAcceptors(2); 116 connector.setConfidentialPort(8443); 117 server.addConnector(connector); 118 server.setStopAtShutdown(true); 119 server.setSendServerVersion(false); 120 server.setSendDateHeader(true); 121 server.setGracefulShutdown(1000); 122 } 123 124 final String getPluginsClasspath(String pluginsPathFromClassloader) throws URISyntaxException, IOException { 125 final URL resource = getClass().getResource(pluginsPathFromClassloader); 126 if (resource != null) { 127 File pluginsDir = new File(resource.toURI()); 128 List<String> paths = new ArrayList<String>(); 129 paths.add(pluginsDir.getCanonicalPath() + System.getProperty("file.separator")); 130 131 Collection<File> files = FileUtils.listFiles(pluginsDir, new String[]{"jar"}, false); 132 if (files != null) { 133 for (File file : files) { 134 paths.add(file.getCanonicalPath()); 135 } 136 } 137 return join(paths, ","); 138 } 139 return null; 140 } 141 142 private String join(List<String> paths, String separator) { 143 StringBuilder sb = new StringBuilder(); 144 boolean first = true; 145 for (String path : paths) { 146 if (!first) { 147 sb.append(separator); 148 } 149 sb.append(path); 150 first = false; 151 } 152 return sb.toString(); 153 } 154 155 private String getPath(String resourcePath) throws URISyntaxException { 156 URL resource = getClass().getResource(resourcePath); 157 if (resource != null) { 158 return resource.toURI().toString(); 159 } 160 return null; 161 } 162 163 Server getServer() { 164 return server; 165 } 166 167 @Override 168 public String toString() { 169 return new StringBuilder().append("http://").append(host).append(":").append(port).append(contextPath).toString(); 170 } 171 }