*/
package org.sonar.process;
-import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final long AUTOKILL_TIMEOUT_MS = 30000L;
private static final long AUTOKILL_CHECK_DELAY_MS = 2000L;
public static final String NAME_PROPERTY = "pName";
- public static final String MISSING_NAME_ARGUMENT = "Missing Name argument";
private Long lastPing;
private final String name;
protected MonitoredProcess(Props props, boolean monitor) {
this.isMonitored = monitor;
this.props = props;
- this.name = props.of(NAME_PROPERTY);
-
- // Testing required properties
- if (StringUtils.isEmpty(name)) {
- throw new IllegalStateException(MISSING_NAME_ARGUMENT);
- }
+ this.name = props.nonNullValue(NAME_PROPERTY);
JmxUtils.registerMBean(this, name);
ProcessUtils.addSelfShutdownHook(this);
JoranConfigurator configurator = new JoranConfigurator();
configurator.setContext(context);
context.reset();
- context.putProperty(PATH_LOGS_PROPERTY, props.of(PATH_LOGS_PROPERTY));
+ context.putProperty(PATH_LOGS_PROPERTY, props.nonNullValue(PATH_LOGS_PROPERTY));
doConfigure(configurator, logbackXmlResource);
} catch (JoranException ignored) {
// StatusPrinter will handle this
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
+
import java.io.File;
import java.util.Properties;
}
@CheckForNull
- public String of(String key) {
+ public String value(String key) {
String value = properties.getProperty(key);
if (value != null && encryption.isEncrypted(value)) {
value = encryption.decrypt(value);
return value;
}
- public String of(String key, @Nullable String defaultValue) {
- String s = of(key);
+ public String nonNullValue(String key) {
+ String value = value(key);
+ if (value == null) {
+ throw new IllegalArgumentException("Missing property: " + key);
+ }
+ return value;
+ }
+
+ @CheckForNull
+ public String value(String key, @Nullable String defaultValue) {
+ String s = value(key);
return s == null ? defaultValue : s;
}
- public boolean booleanOf(String key) {
- String s = of(key);
+ public boolean valueAsBoolean(String key) {
+ String s = value(key);
return s != null && Boolean.parseBoolean(s);
}
- public boolean booleanOf(String key, boolean defaultValue) {
- String s = of(key);
+ public boolean valueAsBoolean(String key, boolean defaultValue) {
+ String s = value(key);
return s != null ? Boolean.parseBoolean(s) : defaultValue;
}
- @CheckForNull
- public File fileOf(String key) {
- String s = of(key);
- return s != null ? new File(s) : null;
+ public File nonNullValueAsFile(String key) {
+ String s = value(key);
+ if (s == null) {
+ throw new IllegalArgumentException("Property " + key + " is missing");
+ }
+ return new File(s);
}
- public Integer intOf(String key) {
- String s = of(key);
+ @CheckForNull
+ public Integer valueAsInt(String key) {
+ String s = value(key);
if (s != null && !"".equals(s)) {
try {
return Integer.parseInt(s);
return null;
}
- public int intOf(String key, int defaultValue) {
- Integer i = intOf(key);
+ public int valueAsInt(String key, int defaultValue) {
+ Integer i = valueAsInt(key);
return i == null ? defaultValue : i;
}
--- /dev/null
+/*
+ * 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.process;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.rules.TemporaryFolder;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.ServerSocket;
+
+public abstract class BaseProcessTest {
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ public static final String DUMMY_OK_APP = "org.sonar.application.DummyOkProcess";
+
+ int freePort;
+ File dummyAppJar;
+ Process proc;
+
+ @Before
+ public void setup() throws IOException {
+ ServerSocket socket = new ServerSocket(0);
+ freePort = socket.getLocalPort();
+ socket.close();
+
+ dummyAppJar = FileUtils.toFile(getClass().getResource("/sonar-dummy-app.jar"));
+ }
+
+ @After
+ public void tearDown() {
+ if (proc != null) {
+ ProcessUtils.destroyQuietly(proc);
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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.process;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.FilenameUtils;
+import org.junit.Test;
+
+import java.io.File;
+import java.util.Properties;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+
+public class BaseProcessWrapperTest extends BaseProcessTest {
+
+ @Test
+ public void has_dummy_app() {
+ assertThat(dummyAppJar).isFile();
+ assertThat(dummyAppJar).exists();
+ }
+
+ private void assertCanStart(ProcessWrapper process) {
+ assertThat(process.execute()).isTrue();
+ proc = process.process();
+ }
+
+ private void assertCanBeReady(ProcessWrapper process) throws InterruptedException {
+ int count = 0;
+ while (!process.isReady() && count < 5) {
+ Thread.sleep(500);
+ }
+ assertThat(process.getProcessMXBean().isReady()).isTrue();
+ }
+
+ private void assertPing(ProcessWrapper process) {
+ long now = System.currentTimeMillis();
+ long ping = process.getProcessMXBean().ping();
+ assertThat(ping - now).isLessThan(3000L);
+ }
+
+
+ @Test
+ public void execute_dummy_app() throws Exception {
+
+ ProcessWrapper process = new ProcessWrapper("DummyOkProcess")
+ .addProperty(MonitoredProcess.NAME_PROPERTY, "DummyOkProcess")
+ .addClasspath(dummyAppJar.getAbsolutePath())
+ .setWorkDir(temp.getRoot())
+ .setTempDirectory(temp.getRoot())
+ .setJmxPort(freePort)
+ .setClassName(DUMMY_OK_APP);
+
+ assertThat(process.isAlive()).isFalse();
+ assertCanStart(process);
+ process.start();
+ assertCanBeReady(process);
+ assertThat(process.isAlive()).isTrue();
+ assertPing(process);
+ process.terminate();
+ try {
+ assertPing(process);
+ fail();
+ } catch (Exception e) {
+
+ }
+ }
+
+
+ @Test
+ public void execute_dummy_in_space_folder_app() throws Exception {
+
+ // 0 create a home with space...
+ File home = temp.newFolder("t est");
+ assertThat(home.canWrite()).isTrue();
+ File lib = new File(home, "lib");
+ File tempdir = new File(home, "temp");
+ FileUtils.copyFileToDirectory(dummyAppJar, lib);
+
+ // 1 Create Properties
+ Props props = new Props(new Properties());
+ props.set("spaceHome", home.getAbsolutePath());
+
+ // 3 start dummy app
+ File effectiveHome = props.nonNullValueAsFile("spaceHome");
+
+ String cp = FilenameUtils.concat(new File(effectiveHome, "lib").getAbsolutePath(), "*");
+ System.out.println("cp = " + cp);
+ ProcessWrapper process = new ProcessWrapper("DummyOkProcess")
+ .addProperty(MonitoredProcess.NAME_PROPERTY, "DummyOkProcess")
+ .setTempDirectory(tempdir)
+ .addClasspath(cp)
+ .setWorkDir(home)
+ .setJmxPort(freePort)
+ .setClassName(DUMMY_OK_APP);
+
+ assertThat(process.isAlive()).isFalse();
+ assertCanStart(process);
+ }
+}
FileUtils.write(propsFile, "foo=bar");
Props result = ConfigurationUtils.loadPropsFromCommandLineArgs(new String[] {propsFile.getAbsolutePath()});
- assertThat(result.of("foo")).isEqualTo("bar");
+ assertThat(result.value("foo")).isEqualTo("bar");
assertThat(result.rawProperties()).hasSize(1);
}
+++ /dev/null
-/*
- * 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.process;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import static org.fest.assertions.Assertions.assertThat;
-
-public class MonitorTest extends ProcessTest {
-
-
- Monitor monitor;
-
- @Before
- public void setUpMonitor() throws Exception {
- monitor = new Monitor();
- }
-
- @After
- public void downMonitor() throws Exception {
- if (monitor != null) {
- monitor.interrupt();
- monitor = null;
- }
- }
-
- @Test
- public void monitor_can_start_and_stop() {
- assertThat(monitor.isAlive()).isFalse();
- monitor.start();
- assertThat(monitor.isAlive()).isTrue();
- monitor.terminate();
- assertThat(monitor.isAlive()).isFalse();
- }
-
- @Test(timeout = 2500L)
- public void monitor_should_interrupt_process() throws Exception {
- // 0 start the dummyProcess
- ProcessWrapper process = new ProcessWrapper("DummyOkProcess")
- .addProperty(MonitoredProcess.NAME_PROPERTY, "DummyOkProcess")
- .addClasspath(dummyAppJar.getAbsolutePath())
- .setWorkDir(temp.getRoot())
- .setTempDirectory(temp.getRoot())
- .setJmxPort(freePort)
- .setClassName(DUMMY_OK_APP);
-
- assertThat(process.execute());
-
-
- // 1 start my monitor & register process
- monitor.start();
- monitor.registerProcess(process);
-
- // 2 terminate monitor, assert process is terminated
- monitor.terminate();
- assertThat(monitor.isAlive()).isFalse();
- assertThat(process.isAlive()).isFalse();
- }
-}
\ No newline at end of file
--- /dev/null
+/*
+ * 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.process;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class MonitorTestBase extends BaseProcessTest {
+
+
+ Monitor monitor;
+
+ @Before
+ public void setUpMonitor() throws Exception {
+ monitor = new Monitor();
+ }
+
+ @After
+ public void downMonitor() throws Exception {
+ if (monitor != null) {
+ monitor.interrupt();
+ monitor = null;
+ }
+ }
+
+ @Test
+ public void monitor_can_start_and_stop() {
+ assertThat(monitor.isAlive()).isFalse();
+ monitor.start();
+ assertThat(monitor.isAlive()).isTrue();
+ monitor.terminate();
+ assertThat(monitor.isAlive()).isFalse();
+ }
+
+ @Test(timeout = 2500L)
+ public void monitor_should_interrupt_process() throws Exception {
+ // 0 start the dummyProcess
+ ProcessWrapper process = new ProcessWrapper("DummyOkProcess")
+ .addProperty(MonitoredProcess.NAME_PROPERTY, "DummyOkProcess")
+ .addClasspath(dummyAppJar.getAbsolutePath())
+ .setWorkDir(temp.getRoot())
+ .setTempDirectory(temp.getRoot())
+ .setJmxPort(freePort)
+ .setClassName(DUMMY_OK_APP);
+
+ assertThat(process.execute());
+
+
+ // 1 start my monitor & register process
+ monitor.start();
+ monitor.registerProcess(process);
+
+ // 2 terminate monitor, assert process is terminated
+ monitor.terminate();
+ assertThat(monitor.isAlive()).isFalse();
+ assertThat(process.isAlive()).isFalse();
+ }
+}
try {
new DummyProcess(new Props(properties), true);
fail();
- } catch (Exception e) {
- assertThat(e.getMessage()).isEqualTo("Missing Name argument");
+ } catch (IllegalArgumentException e) {
+ assertThat(e.getMessage()).isEqualTo("Missing property: pName");
}
properties.setProperty(MonitoredProcess.NAME_PROPERTY, DummyProcess.NAME);
+++ /dev/null
-/*
- * 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.process;
-
-import org.apache.commons.io.FileUtils;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.rules.TemporaryFolder;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.ServerSocket;
-
-public abstract class ProcessTest {
-
- @Rule
- public TemporaryFolder temp = new TemporaryFolder();
-
- public static final String DUMMY_OK_APP = "org.sonar.application.DummyOkProcess";
-
- int freePort;
- File dummyAppJar;
- Process proc;
-
- @Before
- public void setup() throws IOException {
- ServerSocket socket = new ServerSocket(0);
- freePort = socket.getLocalPort();
- socket.close();
-
- dummyAppJar = FileUtils.toFile(getClass().getResource("/sonar-dummy-app.jar"));
- }
-
-
- @After
- public void tearDown() {
- if (proc != null) {
- proc.destroy();
- }
- }
-
-}
+++ /dev/null
-/*
- * 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.process;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.FilenameUtils;
-import org.junit.Test;
-
-import java.io.File;
-import java.util.Properties;
-
-import static org.fest.assertions.Assertions.assertThat;
-import static org.fest.assertions.Fail.fail;
-
-
-public class ProcessWrapperTest extends ProcessTest {
-
- @Test
- public void has_dummy_app() {
- assertThat(dummyAppJar).isFile();
- assertThat(dummyAppJar).exists();
- }
-
- private void assertCanStart(ProcessWrapper process) {
- assertThat(process.execute()).isTrue();
- proc = process.process();
- }
-
- private void assertCanBeReady(ProcessWrapper process) throws InterruptedException {
- int count = 0;
- while (!process.isReady() && count < 5) {
- Thread.sleep(500);
- }
- assertThat(process.getProcessMXBean().isReady()).isTrue();
- }
-
- private void assertPing(ProcessWrapper process) {
- long now = System.currentTimeMillis();
- long ping = process.getProcessMXBean().ping();
- assertThat(ping - now).isLessThan(3000L);
- }
-
-
- @Test
- public void execute_dummy_app() throws Exception {
-
- ProcessWrapper process = new ProcessWrapper("DummyOkProcess")
- .addProperty(MonitoredProcess.NAME_PROPERTY, "DummyOkProcess")
- .addClasspath(dummyAppJar.getAbsolutePath())
- .setWorkDir(temp.getRoot())
- .setTempDirectory(temp.getRoot())
- .setJmxPort(freePort)
- .setClassName(DUMMY_OK_APP);
-
- assertThat(process.isAlive()).isFalse();
- assertCanStart(process);
- process.start();
- assertCanBeReady(process);
- assertThat(process.isAlive()).isTrue();
- assertPing(process);
- process.terminate();
- try {
- assertPing(process);
- fail();
- } catch (Exception e) {
-
- }
- }
-
-
- @Test
- public void execute_dummy_in_space_folder_app() throws Exception {
-
- // 0 create a home with space...
- File home = temp.newFolder("t est");
- assertThat(home.canWrite()).isTrue();
- File lib = new File(home, "lib");
- File tempdir = new File(home, "temp");
- FileUtils.copyFileToDirectory(dummyAppJar, lib);
-
- // 1 Create Properties
- Props props = new Props(new Properties());
- props.set("spaceHome", home.getAbsolutePath());
-
- // 3 start dummy app
- File effectiveHome = props.fileOf("spaceHome");
-
- String cp = FilenameUtils.concat(new File(effectiveHome, "lib").getAbsolutePath(), "*");
- System.out.println("cp = " + cp);
- ProcessWrapper process = new ProcessWrapper("DummyOkProcess")
- .addProperty(MonitoredProcess.NAME_PROPERTY, "DummyOkProcess")
- .setTempDirectory(tempdir)
- .addClasspath(cp)
- .setWorkDir(home)
- .setJmxPort(freePort)
- .setClassName(DUMMY_OK_APP);
-
- assertThat(process.isAlive()).isFalse();
- assertCanStart(process);
- }
-}
\ No newline at end of file
p.setProperty("foo", "bar");
Props props = new Props(p);
- assertThat(props.of("foo")).isEqualTo("bar");
- assertThat(props.of("foo", "default value")).isEqualTo("bar");
- assertThat(props.of("unknown")).isNull();
- assertThat(props.of("unknown", "default value")).isEqualTo("default value");
+ assertThat(props.value("foo")).isEqualTo("bar");
+ assertThat(props.value("foo", "default value")).isEqualTo("bar");
+ assertThat(props.value("unknown")).isNull();
+ assertThat(props.value("unknown", "default value")).isEqualTo("default value");
}
@Test
p.setProperty("blank", "");
Props props = new Props(p);
- assertThat(props.intOf("foo")).isEqualTo(33);
- assertThat(props.intOf("foo", 44)).isEqualTo(33);
- assertThat(props.intOf("blank")).isNull();
- assertThat(props.intOf("blank", 55)).isEqualTo(55);
- assertThat(props.intOf("unknown")).isNull();
- assertThat(props.intOf("unknown", 44)).isEqualTo(44);
+ assertThat(props.valueAsInt("foo")).isEqualTo(33);
+ assertThat(props.valueAsInt("foo", 44)).isEqualTo(33);
+ assertThat(props.valueAsInt("blank")).isNull();
+ assertThat(props.valueAsInt("blank", 55)).isEqualTo(55);
+ assertThat(props.valueAsInt("unknown")).isNull();
+ assertThat(props.valueAsInt("unknown", 44)).isEqualTo(44);
}
@Test
Props props = new Props(p);
try {
- props.intOf("foo");
+ props.valueAsInt("foo");
fail();
} catch (IllegalStateException e) {
assertThat(e).hasMessage("Value of property foo is not an integer: bar");
p.setProperty("bar", "false");
Props props = new Props(p);
- assertThat(props.booleanOf("foo")).isTrue();
- assertThat(props.booleanOf("bar")).isFalse();
- assertThat(props.booleanOf("unknown")).isFalse();
+ assertThat(props.valueAsBoolean("foo")).isTrue();
+ assertThat(props.valueAsBoolean("bar")).isFalse();
+ assertThat(props.valueAsBoolean("unknown")).isFalse();
}
@Test
p.setProperty("bar", "false");
Props props = new Props(p);
- assertThat(props.booleanOf("unset", false)).isFalse();
- assertThat(props.booleanOf("unset", true)).isTrue();
- assertThat(props.booleanOf("foo", false)).isTrue();
- assertThat(props.booleanOf("bar", true)).isFalse();
+ assertThat(props.valueAsBoolean("unset", false)).isFalse();
+ assertThat(props.valueAsBoolean("unset", true)).isTrue();
+ assertThat(props.valueAsBoolean("foo", false)).isTrue();
+ assertThat(props.valueAsBoolean("bar", true)).isFalse();
}
@Test
props.setDefault("foo", "foo_def");
props.setDefault("bar", "bar_def");
- assertThat(props.of("foo")).isEqualTo("foo_value");
- assertThat(props.of("bar")).isEqualTo("bar_def");
- assertThat(props.of("other")).isNull();
+ assertThat(props.value("foo")).isEqualTo("foo_value");
+ assertThat(props.value("bar")).isEqualTo("bar_def");
+ assertThat(props.value("other")).isNull();
}
@Test
props.set("foo", "new_foo");
props.set("bar", "new_bar");
- assertThat(props.of("foo")).isEqualTo("new_foo");
- assertThat(props.of("bar")).isEqualTo("new_bar");
+ assertThat(props.value("foo")).isEqualTo("new_foo");
+ assertThat(props.value("bar")).isEqualTo("new_bar");
}
@Test
this.isBlocking = blocking;
new MinimumViableSystem().check();
- String esNodesInets = props.of(ES_CLUSTER_INET);
+ String esNodesInets = props.value(ES_CLUSTER_INET);
if (StringUtils.isNotEmpty(esNodesInets)) {
Collections.addAll(nodes, esNodesInets.split(","));
}
this.isBlocking = true;
new MinimumViableSystem().check();
- String esNodesInets = props.of(ES_CLUSTER_INET);
+ String esNodesInets = props.value(ES_CLUSTER_INET);
if (StringUtils.isNotEmpty(esNodesInets)) {
Collections.addAll(nodes, esNodesInets.split(","));
}
@Override
protected void doStart() {
-
- Integer port = props.intOf(ES_PORT_PROPERTY);
- String clusterName = props.of(ES_CLUSTER_PROPERTY);
+ Integer port = props.valueAsInt(ES_PORT_PROPERTY);
+ String clusterName = props.value(ES_CLUSTER_PROPERTY);
LoggerFactory.getLogger(SearchServer.class).info("Starting ES[{}] on port: {}", clusterName, port);
// Disable MCast
.put("discovery.zen.ping.multicast.enabled", "false")
- // Index storage policies
+ // Index storage policies
.put("index.merge.policy.max_merge_at_once", "200")
.put("index.merge.policy.segments_per_tier", "200")
.put("index.number_of_shards", "1")
.put("indices.store.throttle.type", "merge")
.put("indices.store.throttle.max_bytes_per_sec", "200mb")
- // Install our own listUpdate scripts
+ // Install our own listUpdate scripts
.put("script.default_lang", "native")
.put("script.native." + ListUpdate.NAME + ".type", ListUpdate.UpdateListScriptFactory.class.getName())
- // Node is pure transport
+ // Node is pure transport
.put("transport.tcp.port", port)
.put("http.enabled", false)
- // Setting up ES paths
+ // Setting up ES paths
.put("path.data", esDataDir().getAbsolutePath())
.put("path.work", esWorkDir().getAbsolutePath())
.put("path.logs", esLogDir().getAbsolutePath());
// Set cluster coordinates
esSettings.put("cluster.name", clusterName);
- esSettings.put("node.rack_id", StringUtils.defaultIfEmpty(props.of(SONAR_NODE_NAME), "unknown"));
+ esSettings.put("node.rack_id", props.value(SONAR_NODE_NAME, "unknown"));
esSettings.put("cluster.routing.allocation.awareness.attributes", "rack_id");
if (props.contains(SONAR_NODE_NAME)) {
- esSettings.put("node.name", props.of(SONAR_NODE_NAME));
+ esSettings.put("node.name", props.value(SONAR_NODE_NAME));
} else {
try {
esSettings.put("node.name", InetAddress.getLocalHost().getHostName());
// Disallow dynamic mapping (too expensive)
.put("index.mapper.dynamic", false)
- // Sortable text analyzer
+ // Sortable text analyzer
.put("index.analysis.analyzer.sortable.type", "custom")
.put("index.analysis.analyzer.sortable.tokenizer", "keyword")
.putArray("index.analysis.analyzer.sortable.filter", "trim", "lowercase", "truncate")
- // Edge NGram index-analyzer
+ // Edge NGram index-analyzer
.put("index.analysis.analyzer.index_grams.type", "custom")
.put("index.analysis.analyzer.index_grams.tokenizer", "whitespace")
.putArray("index.analysis.analyzer.index_grams.filter", "trim", "lowercase", "gram_filter")
- // Edge NGram search-analyzer
+ // Edge NGram search-analyzer
.put("index.analysis.analyzer.search_grams.type", "custom")
.put("index.analysis.analyzer.search_grams.tokenizer", "whitespace")
.putArray("index.analysis.analyzer.search_grams.filter", "trim", "lowercase")
- // Word index-analyzer
+ // Word index-analyzer
.put("index.analysis.analyzer.index_words.type", "custom")
.put("index.analysis.analyzer.index_words.tokenizer", "standard")
.putArray("index.analysis.analyzer.index_words.filter",
"standard", "word_filter", "lowercase", "stop", "asciifolding", "porter_stem")
- // Word search-analyzer
+ // Word search-analyzer
.put("index.analysis.analyzer.search_words.type", "custom")
.put("index.analysis.analyzer.search_words.tokenizer", "standard")
.putArray("index.analysis.analyzer.search_words.filter",
"standard", "lowercase", "stop", "asciifolding", "porter_stem")
- // Edge NGram filter
+ // Edge NGram filter
.put("index.analysis.filter.gram_filter.type", "edgeNGram")
.put("index.analysis.filter.gram_filter.min_gram", 2)
.put("index.analysis.filter.gram_filter.max_gram", 15)
.putArray("index.analysis.filter.gram_filter.token_chars", "letter", "digit", "punctuation", "symbol")
- // Word filter
+ // Word filter
.put("index.analysis.filter.word_filter.type", "word_delimiter")
.put("index.analysis.filter.word_filter.generate_word_parts", true)
.put("index.analysis.filter.word_filter.catenate_words", true)
.put("index.analysis.filter.word_filter.split_on_numerics", true)
.put("index.analysis.filter.word_filter.stem_english_possessive", true)
- // Path Analyzer
+ // Path Analyzer
.put("index.analysis.analyzer.path_analyzer.type", "custom")
.put("index.analysis.analyzer.path_analyzer.tokenizer", "path_hierarchy");
}
private File esHomeDir() {
- String homeDir = props.of(SONAR_PATH_HOME);
- if (StringUtils.isEmpty(homeDir)) {
- throw new IllegalStateException("property 'sonar.path.home' is required");
- } else {
- return new File(homeDir);
- }
+ return props.nonNullValueAsFile(SONAR_PATH_HOME);
}
private File esDataDir() {
- String dataDir = props.of(SONAR_PATH_DATA);
+ String dataDir = props.value(SONAR_PATH_DATA);
if (StringUtils.isNotEmpty(dataDir)) {
return new File(dataDir, "es");
- } else {
- return new File(esHomeDir(), "data/es");
}
+ return new File(esHomeDir(), "data/es");
}
private File esLogDir() {
- String logDir = props.of(SONAR_PATH_LOG);
+ String logDir = props.value(SONAR_PATH_LOG);
if (StringUtils.isNotEmpty(logDir)) {
return new File(logDir);
- } else {
- return new File(esHomeDir(), "log");
}
+ return new File(esHomeDir(), "log");
}
private File esWorkDir() {
- String workDir = props.of(SONAR_PATH_TEMP);
+ String workDir = props.value(SONAR_PATH_TEMP);
if (StringUtils.isNotEmpty(workDir)) {
return new File(workDir);
- } else {
- return new File(esHomeDir(), "temp");
}
+ return new File(esHomeDir(), "temp");
}
@Override
private static Connector newHttpConnector(Props props) {
Connector connector = null;
// Not named "sonar.web.http.port" to keep backward-compatibility
- int port = props.intOf("sonar.web.port", 9000);
+ int port = props.valueAsInt("sonar.web.port", 9000);
if (port > DISABLED_PORT) {
connector = newConnector(props, HTTP_PROTOCOL, "http");
connector.setPort(port);
@Nullable
private static Connector newAjpConnector(Props props) {
Connector connector = null;
- int port = props.intOf("sonar.ajp.port", DISABLED_PORT);
+ int port = props.valueAsInt("sonar.ajp.port", DISABLED_PORT);
if (port > DISABLED_PORT) {
connector = newConnector(props, AJP_PROTOCOL, "http");
connector.setPort(port);
@Nullable
private static Connector newHttpsConnector(Props props) {
Connector connector = null;
- int port = props.intOf("sonar.web.https.port", DISABLED_PORT);
+ int port = props.valueAsInt("sonar.web.https.port", DISABLED_PORT);
if (port > DISABLED_PORT) {
connector = newConnector(props, HTTP_PROTOCOL, "https");
connector.setPort(port);
connector.setSecure(true);
connector.setScheme("https");
- setConnectorAttribute(connector, "keyAlias", props.of("sonar.web.https.keyAlias"));
- String keyPassword = props.of("sonar.web.https.keyPass", "changeit");
+ setConnectorAttribute(connector, "keyAlias", props.value("sonar.web.https.keyAlias"));
+ String keyPassword = props.value("sonar.web.https.keyPass", "changeit");
setConnectorAttribute(connector, "keyPass", keyPassword);
- setConnectorAttribute(connector, "keystorePass", props.of("sonar.web.https.keystorePass", keyPassword));
- setConnectorAttribute(connector, "keystoreFile", props.of("sonar.web.https.keystoreFile"));
- setConnectorAttribute(connector, "keystoreType", props.of("sonar.web.https.keystoreType", "JKS"));
- setConnectorAttribute(connector, "keystoreProvider", props.of("sonar.web.https.keystoreProvider"));
- setConnectorAttribute(connector, "truststorePass", props.of("sonar.web.https.truststorePass", "changeit"));
- setConnectorAttribute(connector, "truststoreFile", props.of("sonar.web.https.truststoreFile"));
- setConnectorAttribute(connector, "truststoreType", props.of("sonar.web.https.truststoreType", "JKS"));
- setConnectorAttribute(connector, "truststoreProvider", props.of("sonar.web.https.truststoreProvider"));
- setConnectorAttribute(connector, "clientAuth", props.of("sonar.web.https.clientAuth", "false"));
+ setConnectorAttribute(connector, "keystorePass", props.value("sonar.web.https.keystorePass", keyPassword));
+ setConnectorAttribute(connector, "keystoreFile", props.value("sonar.web.https.keystoreFile"));
+ setConnectorAttribute(connector, "keystoreType", props.value("sonar.web.https.keystoreType", "JKS"));
+ setConnectorAttribute(connector, "keystoreProvider", props.value("sonar.web.https.keystoreProvider"));
+ setConnectorAttribute(connector, "truststorePass", props.value("sonar.web.https.truststorePass", "changeit"));
+ setConnectorAttribute(connector, "truststoreFile", props.value("sonar.web.https.truststoreFile"));
+ setConnectorAttribute(connector, "truststoreType", props.value("sonar.web.https.truststoreType", "JKS"));
+ setConnectorAttribute(connector, "truststoreProvider", props.value("sonar.web.https.truststoreProvider"));
+ setConnectorAttribute(connector, "clientAuth", props.value("sonar.web.https.clientAuth", "false"));
setConnectorAttribute(connector, "sslProtocol", "TLS");
setConnectorAttribute(connector, "SSLEnabled", true);
info("HTTPS connector is enabled on port " + port);
private static Connector newConnector(Props props, String protocol, String scheme) {
Connector connector = new Connector(protocol);
connector.setURIEncoding("UTF-8");
- connector.setProperty("address", props.of("sonar.web.host", "0.0.0.0"));
+ connector.setProperty("address", props.value("sonar.web.host", "0.0.0.0"));
configurePool(props, connector, scheme);
configureCompression(connector);
return connector;
private static void configurePool(Props props, Connector connector, String scheme) {
connector.setProperty("acceptorThreadCount", String.valueOf(2));
- connector.setProperty("minSpareThreads", String.valueOf(props.intOf("sonar.web." + scheme + ".minThreads", 5)));
- connector.setProperty("maxThreads", String.valueOf(props.intOf("sonar.web." + scheme + ".maxThreads", 50)));
- connector.setProperty("acceptCount", String.valueOf(props.intOf("sonar.web." + scheme + ".acceptCount", 25)));
+ connector.setProperty("minSpareThreads", String.valueOf(props.valueAsInt("sonar.web." + scheme + ".minThreads", 5)));
+ connector.setProperty("maxThreads", String.valueOf(props.valueAsInt("sonar.web." + scheme + ".maxThreads", 50)));
+ connector.setProperty("acceptCount", String.valueOf(props.valueAsInt("sonar.web." + scheme + ".acceptCount", 25)));
}
private static void configureCompression(Connector connector) {
}
private File tomcatBasedir() {
- return new File(props.of("sonar.path.temp"), "tc");
+ return new File(props.value("sonar.path.temp"), "tc");
}
boolean isReady() {
* Configure Logback from classpath, with configuration from sonar.properties
*/
private static void configureLogback(Props props) {
- String configProfilingLevel = props.of(Profiling.CONFIG_PROFILING_LEVEL, "NONE");
+ String configProfilingLevel = props.value(Profiling.CONFIG_PROFILING_LEVEL, "NONE");
Profiling.Level profilingLevel = Profiling.Level.fromConfigString(configProfilingLevel);
- String consoleEnabled = props.of(CONFIG_LOG_CONSOLE, "false");
+ String consoleEnabled = props.value(CONFIG_LOG_CONSOLE, "false");
Map<String, String> variables = ImmutableMap.of(
- "sonar.path.logs", props.of("sonar.path.logs"),
+ "sonar.path.logs", props.nonNullValue("sonar.path.logs"),
"LOGFILE_LOGGING_FORMAT", profilingLevel == Profiling.Level.FULL ? LOGFILE_FULL_LOGGING_FORMAT : LOGFILE_STANDARD_LOGGING_FORMAT,
"CONSOLE_LOGGING_FORMAT", profilingLevel == Profiling.Level.FULL ? CONSOLE_FULL_LOGGING_FORMAT : CONSOLE_STANDARD_LOGGING_FORMAT,
"CONSOLE_ENABLED", consoleEnabled);
}
private static void configureLogbackAccess(Tomcat tomcat, Props props) {
- if (props.booleanOf(PROPERTY_ENABLE_ACCESS_LOGS, true)) {
+ if (props.valueAsBoolean(PROPERTY_ENABLE_ACCESS_LOGS, true)) {
LogbackValve valve = new LogbackValve();
valve.setQuiet(true);
- valve.setFilename(new File(props.of("sonar.path.web"), ACCESS_RELATIVE_PATH).getAbsolutePath());
+ valve.setFilename(new File(props.nonNullValue("sonar.path.web"), ACCESS_RELATIVE_PATH).getAbsolutePath());
tomcat.getHost().getPipeline().addValve(valve);
}
}
}
static String getContextPath(Props props) {
- String context = props.of(PROPERTY_CONTEXT, "");
+ String context = props.value(PROPERTY_CONTEXT, "");
if ("/".equals(context)) {
context = "";
} else if (!"".equals(context) && !context.startsWith("/")) {
static void configureRails(Props props, Context context) {
// sonar.dev is kept for backward-compatibility
- if (props.booleanOf("sonar.dev", false)) {
+ if (props.valueAsBoolean("sonar.dev", false)) {
props.set("sonar.web.dev", "true");
}
- if (props.booleanOf("sonar.web.dev", false)) {
+ if (props.valueAsBoolean("sonar.web.dev", false)) {
context.addParameter(RAILS_ENV, "development");
context.addParameter(JRUBY_MAX_RUNTIMES, "3");
LoggerFactory.getLogger(Webapp.class).warn("WEB DEVELOPMENT MODE IS ENABLED - DO NOT USE FOR PRODUCTION USAGE");
}
static String webappPath(Props props) {
- String webDir = props.of("sonar.web.dev.sources");
+ String webDir = props.value("sonar.web.dev.sources");
if (StringUtils.isEmpty(webDir)) {
- webDir = new File(props.of("sonar.path.home"), "web").getAbsolutePath();
+ webDir = new File(props.value("sonar.path.home"), "web").getAbsolutePath();
}
LoggerFactory.getLogger(Webapp.class).info(String.format("Webapp directory: %s", webDir));
return webDir;
import org.sonar.process.JmxUtils;
import org.sonar.process.MinimumViableSystem;
import org.sonar.process.Monitor;
-import org.sonar.process.MonitoredProcess;
import org.sonar.process.ProcessLogging;
import org.sonar.process.ProcessMXBean;
import org.sonar.process.ProcessUtils;
import org.sonar.search.SearchServer;
import java.io.File;
-import java.io.IOException;
-import java.net.URISyntaxException;
import java.util.Properties;
/**
monitor.start();
- File homeDir = props.fileOf("sonar.path.home");
- File tempDir = props.fileOf("sonar.path.temp");
+ File homeDir = props.nonNullValueAsFile("sonar.path.home");
+ File tempDir = props.nonNullValueAsFile("sonar.path.temp");
elasticsearch = new ProcessWrapper(JmxUtils.SEARCH_SERVER_NAME);
elasticsearch
.setWorkDir(homeDir)
- .setJmxPort(props.intOf(DefaultSettings.SEARCH_JMX_PORT))
- .addJavaOpts(props.of(DefaultSettings.SEARCH_JAVA_OPTS))
+ .setJmxPort(props.valueAsInt(DefaultSettings.SEARCH_JMX_PORT))
+ .addJavaOpts(props.value(DefaultSettings.SEARCH_JAVA_OPTS))
.setTempDirectory(tempDir.getAbsoluteFile())
.setClassName("org.sonar.search.SearchServer")
.addProperties(props.rawProperties())
logger.info("search server is up");
// do not yet start SQ in cluster mode. See SONAR-5483 & SONAR-5391
- if (StringUtils.isEmpty(props.of(DefaultSettings.CLUSTER_MASTER, null))) {
+ if (StringUtils.isEmpty(props.value(DefaultSettings.CLUSTER_MASTER))) {
server = new ProcessWrapper(JmxUtils.WEB_SERVER_NAME)
.setWorkDir(homeDir)
- .setJmxPort(props.intOf(DefaultSettings.WEB_JMX_PORT))
- .addJavaOpts(props.of(DefaultSettings.WEB_JAVA_OPTS))
+ .setJmxPort(props.valueAsInt(DefaultSettings.WEB_JMX_PORT))
+ .addJavaOpts(props.nonNullValue(DefaultSettings.WEB_JAVA_OPTS))
.setTempDirectory(tempDir.getAbsoluteFile())
- // required for logback tomcat valve
- .setLogDir(props.fileOf("sonar.path.logs"))
+ // required for logback tomcat valve
+ .setLogDir(props.nonNullValueAsFile("sonar.path.logs"))
.setClassName("org.sonar.server.app.WebServer")
.addProperties(props.rawProperties())
.addClasspath("./lib/common/*")
.addClasspath("./lib/server/*");
- String driverPath = props.of(JdbcSettings.PROPERTY_DRIVER_PATH);
+ String driverPath = props.value(JdbcSettings.PROPERTY_DRIVER_PATH);
if (driverPath != null) {
server.addClasspath(driverPath);
}
}
public static void main(String[] args) {
-
new MinimumViableSystem().check();
CommandLineParser cli = new CommandLineParser();
Properties rawProperties = cli.parseArguments(args);
- Props props = null;
+ Props props;
try {
props = new PropsBuilder(rawProperties, new JdbcSettings()).build();
new ProcessLogging().configure(props, "/org/sonar/application/logback.xml");
- } catch (IOException e) {
- throw new IllegalStateException(e.getMessage());
- } catch (URISyntaxException e) {
- throw new IllegalStateException(e.getMessage());
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
}
App app = new App();
-
try {
// start and wait for shutdown command
if (props.contains(SearchServer.ES_CLUSTER_INET)) {
- LoggerFactory.getLogger(App.class).info("SonarQube slave configured to join SonarQube master : {}", props.of(SearchServer.ES_CLUSTER_INET));
+ LoggerFactory.getLogger(App.class).info("SonarQube slave configured to join SonarQube master : {}", props.value(SearchServer.ES_CLUSTER_INET));
}
app.start(props);
} catch (InterruptedException e) {
// init ports
for (Map.Entry<String, Integer> entry : defaultPorts().entrySet()) {
String key = entry.getKey();
- int port = props.intOf(key, -1);
+ int port = props.valueAsInt(key, -1);
if (port == -1) {
// default port
props.set(key, String.valueOf((int) entry.getValue()));
}
public void checkAndComplete(File homeDir, Props props) {
- String url = props.of(DefaultSettings.JDBC_URL);
+ String url = props.value(DefaultSettings.JDBC_URL);
Provider provider = driverProvider(url);
checkUrlParameters(provider, url);
String driverPath = driverPath(homeDir, provider);
}
private File configureDir(Props props, String propKey, String defaultRelativePath) {
- String path = props.of(propKey, defaultRelativePath);
+ String path = props.value(propKey, defaultRelativePath);
File d = new File(path);
if (!d.isAbsolute()) {
d = new File(homeDir, path);
Props props = new Props(new Properties());
DefaultSettings.init(props);
- assertThat(props.of("sonar.search.javaOpts")).contains("-Xmx");
- assertThat(props.intOf("sonar.web.jmxPort")).isEqualTo(9003);
- assertThat(props.intOf("sonar.search.jmxPort")).isEqualTo(9002);
- assertThat(props.of("sonar.jdbc.username")).isEqualTo("sonar");
+ assertThat(props.value("sonar.search.javaOpts")).contains("-Xmx");
+ assertThat(props.valueAsInt("sonar.web.jmxPort")).isEqualTo(9003);
+ assertThat(props.valueAsInt("sonar.search.jmxPort")).isEqualTo(9002);
+ assertThat(props.value("sonar.jdbc.username")).isEqualTo("sonar");
}
@Test
Props props = new Props(p);
DefaultSettings.init(props);
- assertThat(props.of("sonar.jdbc.username")).isEqualTo("angela");
+ assertThat(props.value("sonar.jdbc.username")).isEqualTo("angela");
}
@Test
Props props = new Props(p);
DefaultSettings.init(props);
- assertThat(props.intOf("sonar.web.jmxPort")).isGreaterThan(0);
+ assertThat(props.valueAsInt("sonar.web.jmxPort")).isGreaterThan(0);
}
}
Props props = new Props(new Properties());
props.set("sonar.jdbc.url", "jdbc:oracle:thin:@localhost/XE");
settings.checkAndComplete(home, props);
- assertThat(props.fileOf(JdbcSettings.PROPERTY_DRIVER_PATH)).isEqualTo(driverFile);
+ assertThat(props.nonNullValueAsFile(JdbcSettings.PROPERTY_DRIVER_PATH)).isEqualTo(driverFile);
}
@Test
Props props = new Props(new Properties());
props.set("sonar.jdbc.url", "jdbc:h2:tcp://localhost:9092/sonar");
settings.checkAndComplete(home, props);
- assertThat(props.fileOf(JdbcSettings.PROPERTY_DRIVER_PATH)).isNull();
+ assertThat(props.value(JdbcSettings.PROPERTY_DRIVER_PATH)).isNull();
}
@Test
Props props = new Props(new Properties());
props.set("sonar.jdbc.url", "jdbc:postgresql://localhost/sonar");
settings.checkAndComplete(home, props);
- assertThat(props.fileOf(JdbcSettings.PROPERTY_DRIVER_PATH)).isEqualTo(driverFile);
+ assertThat(props.nonNullValueAsFile(JdbcSettings.PROPERTY_DRIVER_PATH)).isEqualTo(driverFile);
}
@Test
Props props = new Props(new Properties());
props.set("sonar.jdbc.url", "jdbc:jtds:sqlserver://localhost/sonar;SelectMethod=Cursor");
settings.checkAndComplete(home, props);
- assertThat(props.fileOf(JdbcSettings.PROPERTY_DRIVER_PATH)).isEqualTo(driverFile);
+ assertThat(props.nonNullValueAsFile(JdbcSettings.PROPERTY_DRIVER_PATH)).isEqualTo(driverFile);
}
@Test
Props props = new PropsBuilder(rawProperties, jdbcSettings, homeDir).build();
- assertThat(props.fileOf("sonar.path.logs")).isEqualTo(logsDir);
- assertThat(props.fileOf("sonar.path.home")).isEqualTo(homeDir);
+ assertThat(props.nonNullValueAsFile("sonar.path.logs")).isEqualTo(logsDir);
+ assertThat(props.nonNullValueAsFile("sonar.path.home")).isEqualTo(homeDir);
// create <HOME>/temp
- File tempDir = props.fileOf("sonar.path.temp");
+ File tempDir = props.nonNullValueAsFile("sonar.path.temp");
assertThat(tempDir).isDirectory().exists();
assertThat(tempDir.getName()).isEqualTo("temp");
assertThat(tempDir.getParentFile()).isEqualTo(homeDir);
- assertThat(props.of("foo")).isEqualTo("bar");
- assertThat(props.of("unknown")).isNull();
+ assertThat(props.value("foo")).isEqualTo("bar");
+ assertThat(props.value("unknown")).isNull();
// default properties
- assertThat(props.intOf("sonar.search.port")).isEqualTo(9001);
+ assertThat(props.valueAsInt("sonar.search.port")).isEqualTo(9001);
}
@Test
rawProperties.setProperty("sonar.origin", "raw");
Props props = new PropsBuilder(rawProperties, jdbcSettings, homeDir).build();
- assertThat(props.of("sonar.jdbc.username")).isEqualTo("angela");
+ assertThat(props.value("sonar.jdbc.username")).isEqualTo("angela");
// command-line arguments override sonar.properties file
- assertThat(props.of("sonar.origin")).isEqualTo("raw");
+ assertThat(props.value("sonar.origin")).isEqualTo("raw");
}
}