@@ -33,7 +33,7 @@ import java.io.IOException; | |||
import java.security.Key; | |||
import java.security.SecureRandom; | |||
final class AesCipher extends Cipher { | |||
final class AesCipher implements Cipher { | |||
// Can't be increased because of Java 6 policy files : | |||
// https://confluence.terena.org/display/~visser/No+256+bit+ciphers+for+Java+apps | |||
@@ -54,7 +54,7 @@ final class AesCipher extends Cipher { | |||
} | |||
@Override | |||
String encrypt(String clearText) { | |||
public String encrypt(String clearText) { | |||
try { | |||
javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance(CRYPTO_KEY); | |||
cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, loadSecretFile()); | |||
@@ -67,7 +67,7 @@ final class AesCipher extends Cipher { | |||
} | |||
@Override | |||
String decrypt(String encryptedText) { | |||
public String decrypt(String encryptedText) { | |||
try { | |||
javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance(CRYPTO_KEY); | |||
cipher.init(javax.crypto.Cipher.DECRYPT_MODE, loadSecretFile()); |
@@ -22,14 +22,14 @@ package org.sonar.process; | |||
import org.apache.commons.codec.binary.Base64; | |||
final class Base64Cipher extends Cipher { | |||
final class Base64Cipher implements Cipher { | |||
@Override | |||
String encrypt(String clearText) { | |||
public String encrypt(String clearText) { | |||
return new String(Base64.encodeBase64(clearText.getBytes())); | |||
} | |||
@Override | |||
String decrypt(String encryptedText) { | |||
public String decrypt(String encryptedText) { | |||
return new String(Base64.decodeBase64(encryptedText)); | |||
} | |||
} |
@@ -20,8 +20,8 @@ | |||
package org.sonar.process; | |||
abstract class Cipher { | |||
abstract String encrypt(String clearText); | |||
interface Cipher { | |||
String encrypt(String clearText); | |||
abstract String decrypt(String encryptedText); | |||
String decrypt(String encryptedText); | |||
} |
@@ -31,12 +31,13 @@ import java.util.concurrent.TimeUnit; | |||
public class Monitor extends Thread implements Terminable { | |||
private static final long PING_DELAY_MS = 3000L; | |||
private final static Logger LOGGER = LoggerFactory.getLogger(Monitor.class); | |||
private static final long PING_DELAY_MS = 3000L; | |||
private volatile List<ProcessWrapper> processes; | |||
private final ScheduledFuture<?> watch; | |||
private final ScheduledExecutorService monitor; | |||
private final ScheduledExecutorService monitorExecutionService; | |||
/** | |||
* Starts another thread to send ping to all registered processes | |||
@@ -44,8 +45,8 @@ public class Monitor extends Thread implements Terminable { | |||
public Monitor() { | |||
super("Process Monitor"); | |||
processes = new ArrayList<ProcessWrapper>(); | |||
monitor = Executors.newScheduledThreadPool(1); | |||
watch = monitor.scheduleAtFixedRate(new ProcessWatch(), 0L, PING_DELAY_MS, TimeUnit.MILLISECONDS); | |||
monitorExecutionService = Executors.newScheduledThreadPool(1); | |||
watch = monitorExecutionService.scheduleAtFixedRate(new ProcessWatch(), 0L, PING_DELAY_MS, TimeUnit.MILLISECONDS); | |||
} | |||
private class ProcessWatch extends Thread { | |||
@@ -63,7 +64,8 @@ public class Monitor extends Thread implements Terminable { | |||
mBean.ping(); | |||
} | |||
} catch (Exception e) { | |||
// fail to ping, do nothing | |||
LOGGER.debug("Could not ping process[{}]", process.getName()); | |||
LOGGER.trace("Ping failure", e); | |||
} | |||
} | |||
} | |||
@@ -107,8 +109,8 @@ public class Monitor extends Thread implements Terminable { | |||
@Override | |||
public void terminate() { | |||
if (!monitor.isShutdown()) { | |||
monitor.shutdownNow(); | |||
if (!monitorExecutionService.isShutdown()) { | |||
monitorExecutionService.shutdownNow(); | |||
} | |||
if (!watch.isCancelled()) { | |||
watch.cancel(true); |
@@ -154,6 +154,7 @@ public abstract class MonitoredProcess implements ProcessMXBean { | |||
try { | |||
return doIsReady(); | |||
} catch (Exception ignored) { | |||
LOGGER.trace("Exception while checking if ready", ignored); | |||
return false; | |||
} | |||
} |
@@ -40,6 +40,7 @@ import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.io.InputStreamReader; | |||
import java.io.OutputStream; | |||
import java.net.MalformedURLException; | |||
import java.util.ArrayList; | |||
import java.util.Arrays; | |||
import java.util.Collections; | |||
@@ -178,6 +179,7 @@ public class ProcessWrapper extends Thread implements Terminable { | |||
} | |||
} catch (Exception e) { | |||
LOGGER.info("ProcessThread has been interrupted. Killing process."); | |||
LOGGER.trace("Process exception", e); | |||
} finally { | |||
waitUntilFinish(outputGobbler); | |||
waitUntilFinish(errorGobbler); | |||
@@ -210,7 +212,7 @@ public class ProcessWrapper extends Thread implements Terminable { | |||
"bin" + separator + "java").getAbsolutePath(); | |||
} | |||
private List<String> buildJMXOptions() throws Exception { | |||
private List<String> buildJMXOptions() { | |||
if (jmxPort < 1) { | |||
throw new IllegalStateException("JMX port is not set"); | |||
} | |||
@@ -246,10 +248,15 @@ public class ProcessWrapper extends Thread implements Terminable { | |||
* Wait for JMX RMI to be ready. Return <code>null</code> | |||
*/ | |||
@CheckForNull | |||
private ProcessMXBean waitForJMX() throws Exception { | |||
private ProcessMXBean waitForJMX() { | |||
String loopbackAddress = localAddress(); | |||
String path = "/jndi/rmi://" + loopbackAddress + ":" + jmxPort + "/jmxrmi"; | |||
JMXServiceURL jmxUrl = new JMXServiceURL("rmi", loopbackAddress, jmxPort, path); | |||
JMXServiceURL jmxUrl = null; | |||
try { | |||
jmxUrl = new JMXServiceURL("rmi", loopbackAddress, jmxPort, path); | |||
} catch (MalformedURLException e) { | |||
throw new IllegalStateException("JMX url does not look well formed", e); | |||
} | |||
for (int i = 0; i < 5; i++) { | |||
try { | |||
@@ -266,7 +273,7 @@ public class ProcessWrapper extends Thread implements Terminable { | |||
ProcessMXBean bean = JMX.newMBeanProxy(mBeanServer, JmxUtils.objectName(processName), ProcessMXBean.class); | |||
return bean; | |||
} catch (Exception ignored) { | |||
// ignored | |||
LOGGER.trace("Could not connect JMX yet", ignored); | |||
} | |||
} | |||
// failed to connect | |||
@@ -299,8 +306,7 @@ public class ProcessWrapper extends Thread implements Terminable { | |||
LOGGER.info("{} stopped", getName()); | |||
} catch (Exception ignored) { | |||
// ignore | |||
LOGGER.trace("Could not terminate process", ignored); | |||
} finally { | |||
killer.shutdownNow(); | |||
} | |||
@@ -326,7 +332,7 @@ public class ProcessWrapper extends Thread implements Terminable { | |||
return true; | |||
} | |||
} catch (Exception e) { | |||
// ignore | |||
LOGGER.trace("Process is not ready yet", e); | |||
} | |||
Thread.sleep(wait); | |||
now += wait; | |||
@@ -354,8 +360,7 @@ public class ProcessWrapper extends Thread implements Terminable { | |||
logger.info(line); | |||
} | |||
} catch (Exception ignored) { | |||
// ignored | |||
LOGGER.trace("Error while Gobbling", ignored); | |||
} finally { | |||
IOUtils.closeQuietly(br); | |||
IOUtils.closeQuietly(isr); |
@@ -29,21 +29,21 @@ import java.util.Properties; | |||
public class Props { | |||
private final Properties props; | |||
private final Properties properties; | |||
private final Encryption encryption; | |||
public Props(Properties props) { | |||
this.props = props; | |||
this.properties = props; | |||
this.encryption = new Encryption(props.getProperty(AesCipher.ENCRYPTION_SECRET_KEY_PATH)); | |||
} | |||
public boolean contains(String key) { | |||
return props.containsKey(key); | |||
return properties.containsKey(key); | |||
} | |||
@CheckForNull | |||
public String of(String key) { | |||
String value = props.getProperty(key); | |||
String value = properties.getProperty(key); | |||
if (value != null && encryption.isEncrypted(value)) { | |||
value = encryption.decrypt(value); | |||
} | |||
@@ -89,18 +89,20 @@ public class Props { | |||
} | |||
public Properties rawProperties() { | |||
return props; | |||
return properties; | |||
} | |||
public Props set(String key, @Nullable String value) { | |||
props.setProperty(key, value); | |||
if (value != null) { | |||
properties.setProperty(key, value); | |||
} | |||
return this; | |||
} | |||
public void setDefault(String key, String value) { | |||
String s = props.getProperty(key); | |||
String s = properties.getProperty(key); | |||
if (StringUtils.isBlank(s)) { | |||
props.setProperty(key, value); | |||
properties.setProperty(key, value); | |||
} | |||
} | |||
} |