@@ -30,6 +30,7 @@ import javax.management.MBeanServer; | |||
import javax.management.MalformedObjectNameException; | |||
import javax.management.NotCompliantMBeanException; | |||
import javax.management.ObjectName; | |||
import java.io.File; | |||
import java.io.FileReader; | |||
import java.io.IOException; | |||
@@ -150,17 +151,17 @@ public abstract class Process implements ProcessMXBean { | |||
public abstract void onTerminate(); | |||
public final void start() { | |||
LOGGER.debug("Process[{}]::start() START", name); | |||
LOGGER.debug("Process[{}] starting", name); | |||
if (this.port != null) { | |||
lastPing = System.currentTimeMillis(); | |||
pingTask = monitor.scheduleWithFixedDelay(breakOnMissingPing, 5, 5, TimeUnit.SECONDS); | |||
} | |||
this.onStart(); | |||
LOGGER.trace("Process[{}]::start() END", name); | |||
LOGGER.debug("Process[{}] started", name); | |||
} | |||
public final void terminate() { | |||
LOGGER.debug("Process[{}]::terminate() START", name); | |||
LOGGER.debug("Process[{}] terminating", name); | |||
if (monitor != null) { | |||
this.monitor.shutdownNow(); | |||
this.monitor = null; | |||
@@ -170,6 +171,6 @@ public abstract class Process implements ProcessMXBean { | |||
} | |||
this.onTerminate(); | |||
} | |||
LOGGER.trace("Process[{}]::terminate() END", name); | |||
LOGGER.debug("Process[{}] terminated", name); | |||
} | |||
} |
@@ -31,6 +31,7 @@ import javax.management.MBeanServerConnection; | |||
import javax.management.remote.JMXConnector; | |||
import javax.management.remote.JMXConnectorFactory; | |||
import javax.management.remote.JMXServiceURL; | |||
import java.io.BufferedReader; | |||
import java.io.File; | |||
import java.io.FileOutputStream; | |||
@@ -130,7 +131,7 @@ public class ProcessWrapper extends Thread { | |||
processBuilder.environment().putAll(envProperties); | |||
try { | |||
LOGGER.debug("ProcessWrapper::executeProcess() -- Starting process with command '{}'", StringUtils.join(command, " ")); | |||
LOGGER.debug("Execute command: {}", StringUtils.join(command, " ")); | |||
process = processBuilder.start(); | |||
errorGobbler = new StreamGobbler(process.getErrorStream(), this.getName() + "-ERROR"); | |||
outputGobbler = new StreamGobbler(process.getInputStream(), this.getName()); | |||
@@ -253,11 +254,6 @@ public class ProcessWrapper extends Thread { | |||
public void terminate() { | |||
if (processMXBean != null) { | |||
processMXBean.terminate(); | |||
// try { | |||
// Thread.sleep(10000L); | |||
// } catch (InterruptedException e) { | |||
// LOGGER.warn("Could bnit", e); | |||
// } | |||
this.interrupt(); | |||
} | |||
} |
@@ -100,7 +100,7 @@ | |||
</dependencySet> | |||
<!-- Server --> | |||
<dependencySet> | |||
<outputDirectory>lib/web</outputDirectory> | |||
<outputDirectory>web</outputDirectory> | |||
<includes> | |||
<include>org.codehaus.sonar:sonar-web</include> | |||
</includes> |
@@ -0,0 +1,44 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2014 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.application; | |||
import ch.qos.logback.classic.LoggerContext; | |||
import ch.qos.logback.classic.joran.JoranConfigurator; | |||
import ch.qos.logback.core.joran.spi.JoranException; | |||
import ch.qos.logback.core.util.StatusPrinter; | |||
import org.slf4j.LoggerFactory; | |||
class AppLogging { | |||
void configure(Installation installation) { | |||
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); | |||
try { | |||
context.putProperty(DefaultSettings.PATH_LOGS_KEY, installation.logsDir().getAbsolutePath()); | |||
JoranConfigurator configurator = new JoranConfigurator(); | |||
configurator.setContext(context); | |||
context.reset(); | |||
configurator.doConfigure(getClass().getResource("/org/sonar/application/logback.xml")); | |||
} catch (JoranException je) { | |||
// StatusPrinter will handle this | |||
} | |||
StatusPrinter.printInCaseOfErrorsOrWarnings(context); | |||
} | |||
} |
@@ -28,6 +28,8 @@ class DefaultSettings { | |||
// only static stuff | |||
} | |||
static final String PATH_LOGS_KEY = "sonar.path.logs"; | |||
static final String ES_PORT_KEY = "sonar.es.port"; | |||
private static final int ES_PORT_DEFVAL = 9001; | |||
@@ -22,12 +22,11 @@ package org.sonar.application; | |||
import org.apache.commons.io.FileUtils; | |||
import org.apache.commons.io.FilenameUtils; | |||
import org.apache.commons.io.IOUtils; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import org.sonar.process.Props; | |||
import javax.annotation.CheckForNull; | |||
import javax.annotation.Nullable; | |||
import java.io.File; | |||
import java.io.FileReader; | |||
import java.io.IOException; | |||
@@ -35,8 +34,6 @@ import java.net.URISyntaxException; | |||
import java.util.Properties; | |||
public class Installation { | |||
private static final Logger LOG = LoggerFactory.getLogger(Installation.class); | |||
private final File homeDir; | |||
private final File tempDir, logsDir; | |||
private final Props props; | |||
@@ -50,7 +47,7 @@ public class Installation { | |||
// init file system | |||
initExistingDir("sonar.path.data", "data"); | |||
initExistingDir("sonar.path.web", "lib/web"); | |||
initExistingDir("sonar.path.web", "web"); | |||
this.tempDir = initTempDir("sonar.path.temp", "temp"); | |||
this.logsDir = initExistingDir("sonar.path.logs", "logs"); | |||
} | |||
@@ -73,8 +70,6 @@ public class Installation { | |||
} finally { | |||
IOUtils.closeQuietly(reader); | |||
} | |||
} else { | |||
LOG.info("Configuration file not found: " + propsFile.getAbsolutePath()); | |||
} | |||
p.putAll(System.getenv()); | |||
p.putAll(System.getProperties()); |
@@ -19,7 +19,6 @@ | |||
*/ | |||
package org.sonar.application; | |||
import com.google.common.annotations.VisibleForTesting; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import org.sonar.process.Monitor; | |||
@@ -32,6 +31,7 @@ import javax.management.InstanceAlreadyExistsException; | |||
import javax.management.MBeanRegistrationException; | |||
import javax.management.MBeanServer; | |||
import javax.management.NotCompliantMBeanException; | |||
import java.lang.management.ManagementFactory; | |||
public class StartServer implements ProcessMXBean { | |||
@@ -45,11 +45,6 @@ public class StartServer implements ProcessMXBean { | |||
private static Logger LOGGER = LoggerFactory.getLogger(StartServer.class); | |||
public StartServer() throws Exception { | |||
this(new Installation()); | |||
} | |||
@VisibleForTesting | |||
StartServer(Installation installation) throws Exception { | |||
this.installation = installation; | |||
@@ -75,17 +70,15 @@ public class StartServer implements ProcessMXBean { | |||
} | |||
monitor = new Monitor(); | |||
} | |||
private void start(){ | |||
private void start() { | |||
elasticsearch = new ProcessWrapper("ES") | |||
.setWorkDir(installation.homeDir()) | |||
.setJmxPort(Integer.parseInt(installation.prop(DefaultSettings.ES_JMX_PORT_KEY))) | |||
.addJavaOpts(installation.prop(DefaultSettings.ES_JAVA_OPTS_KEY)) | |||
.addJavaOpts("-Djava.io.tmpdir=" + installation.tempDir().getAbsolutePath()) | |||
.addJavaOpts("-Dsonar.path.logs=" + installation.logsDir().getAbsolutePath()) | |||
.addJavaOpts(String.format("-Djava.io.tmpdir=%s", installation.tempDir().getAbsolutePath())) | |||
.addJavaOpts(String.format("-D%s=%s", DefaultSettings.PATH_LOGS_KEY, installation.logsDir().getAbsolutePath())) | |||
.setClassName("org.sonar.search.ElasticSearch") | |||
.setProperties(installation.props().cryptedProperties()) | |||
.addClasspath(installation.starPath("lib/common")) | |||
@@ -93,14 +86,13 @@ public class StartServer implements ProcessMXBean { | |||
.execute(); | |||
monitor.registerProcess(elasticsearch); | |||
server = new ProcessWrapper("SQ") | |||
.setWorkDir(installation.homeDir()) | |||
.setJmxPort(Integer.parseInt(installation.prop(DefaultSettings.WEB_JMX_PORT_KEY))) | |||
.addJavaOpts(installation.prop(DefaultSettings.WEB_JAVA_OPTS_KEY)) | |||
.addJavaOpts(DefaultSettings.WEB_JAVA_OPTS_APPENDED_VAL) | |||
.addJavaOpts("-Djava.io.tmpdir=" + installation.tempDir().getAbsolutePath()) | |||
.addJavaOpts("-Dsonar.path.logs=" + installation.logsDir().getAbsolutePath()) | |||
.addJavaOpts(String.format("-Djava.io.tmpdir=%s", installation.tempDir().getAbsolutePath())) | |||
.addJavaOpts(String.format("-D%s=%s", DefaultSettings.PATH_LOGS_KEY, installation.logsDir().getAbsolutePath())) | |||
.setClassName("org.sonar.server.app.ServerProcess") | |||
.setProperties(installation.props().cryptedProperties()) | |||
.addClasspath(installation.starPath("extensions/jdbc-driver/mysql")) | |||
@@ -153,10 +145,6 @@ public class StartServer implements ProcessMXBean { | |||
} | |||
} | |||
public static void main(String[] args) throws Exception { | |||
new StartServer().start(); | |||
} | |||
@Override | |||
public boolean isReady() { | |||
return monitor.isAlive(); | |||
@@ -166,4 +154,10 @@ public class StartServer implements ProcessMXBean { | |||
public long ping() { | |||
return System.currentTimeMillis(); | |||
} | |||
public static void main(String[] args) throws Exception { | |||
Installation installation = new Installation(); | |||
new AppLogging().configure(installation); | |||
new StartServer(installation).start(); | |||
} | |||
} |
@@ -10,9 +10,9 @@ | |||
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator"/> | |||
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> | |||
<File>${SONAR_HOME}/logs/sonar.log</File> | |||
<File>${sonar.path.logs}/sonar.log</File> | |||
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> | |||
<param name="FileNamePattern" value="${SONAR_HOME}/logs/sonar.%i.log"/> | |||
<param name="FileNamePattern" value="${sonar.path.logs}/sonar.%i.log"/> | |||
<param name="MinIndex" value="1"/> | |||
<param name="MaxIndex" value="3"/> | |||
</rollingPolicy> |
@@ -58,7 +58,6 @@ public class StartServerTest { | |||
@Test | |||
public void should_register_mbean() throws Exception { | |||
Installation installation = mock(Installation.class); | |||
when(installation.detectHomeDir()).thenReturn(sonarHome.getRoot()); | |||
@@ -95,4 +94,4 @@ public class StartServerTest { | |||
assertThat(e.getMessage()).isEqualTo("No such operation: xoxo"); | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,38 @@ | |||
<?xml version="1.0" encoding="UTF-8" ?> | |||
<!-- | |||
Configuration for default logger. Only used while embedded server is starting, | |||
before proper logging configuration is loaded. | |||
See http://logback.qos.ch/manual/configuration.html | |||
--> | |||
<configuration debug="false"> | |||
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator"/> | |||
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> | |||
<filter class="ch.qos.logback.classic.filter.LevelFilter"> | |||
<level>INFO</level> | |||
<onMatch>ACCEPT</onMatch> | |||
<onMismatch>DENY</onMismatch> | |||
</filter> | |||
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> | |||
<pattern> | |||
%d{yyyy.MM.dd HH:mm:ss} %-5level %msg%n | |||
</pattern> | |||
</encoder> | |||
</appender> | |||
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> | |||
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> | |||
<pattern> | |||
%d{yyyy.MM.dd HH:mm:ss} %-5level %msg%n | |||
</pattern> | |||
</encoder> | |||
</appender> | |||
<root> | |||
<level value="DEBUG"/> | |||
<appender-ref ref="CONSOLE"/> | |||
</root> | |||
</configuration> |