diff options
66 files changed, 1689 insertions, 2013 deletions
@@ -674,6 +674,11 @@ <version>3.2.7</version> </dependency> <dependency> + <groupId>org.nanohttpd</groupId> + <artifactId>nanohttpd</artifactId> + <version>2.3.0</version> + </dependency> + <dependency> <groupId>org.picocontainer</groupId> <artifactId>picocontainer</artifactId> <version>2.15</version> diff --git a/server/sonar-ce/pom.xml b/server/sonar-ce/pom.xml index f9ead798b1d..593799b9ad5 100644 --- a/server/sonar-ce/pom.xml +++ b/server/sonar-ce/pom.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.sonarsource.sonarqube</groupId> @@ -17,6 +18,14 @@ <version>${project.version}</version> <scope>provided</scope> </dependency> + <dependency> + <groupId>org.nanohttpd</groupId> + <artifactId>nanohttpd</artifactId> + </dependency> + <dependency> + <groupId>com.google.protobuf</groupId> + <artifactId>protobuf-java</artifactId> + </dependency> <dependency> <groupId>com.google.code.findbugs</groupId> diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java b/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java index cc98def1ecf..12a117288d9 100644 --- a/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java +++ b/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java @@ -104,7 +104,6 @@ import org.sonar.server.platform.ServerImpl; import org.sonar.server.platform.ServerLifecycleNotifier; import org.sonar.server.platform.ServerLogging; import org.sonar.server.platform.TempFolderProvider; -import org.sonar.server.platform.monitoring.JmxConnectionFactoryProvider; import org.sonar.server.plugins.InstalledPluginReferentialFactory; import org.sonar.server.plugins.ServerExtensionInstaller; import org.sonar.server.plugins.privileged.PrivilegedPluginsBootstraper; @@ -137,7 +136,6 @@ public class ComputeEngineContainerImpl implements ComputeEngineContainer { private static final Object[] LEVEL_1_COMPONENTS = new Object[] { ComputeEngineSettings.class, SonarQubeVersionFactory.create(System2.INSTANCE), - new JmxConnectionFactoryProvider(), ServerImpl.class, UuidFactoryImpl.INSTANCE, // no EmbeddedDatabaseFactory.class, creating H2 DB if responsibility of WebServer diff --git a/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java b/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java index 4345cd88fe4..66d1080984f 100644 --- a/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java +++ b/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java @@ -31,9 +31,12 @@ import org.picocontainer.MutablePicoContainer; import org.sonar.api.database.DatabaseProperties; import org.sonar.api.utils.System2; import org.sonar.db.DbTester; +import org.sonar.process.ProcessId; import org.sonar.process.Props; +import static java.lang.String.valueOf; import static org.assertj.core.api.Assertions.assertThat; +import static org.sonar.process.ProcessEntryPoint.PROPERTY_PROCESS_INDEX; import static org.sonar.process.ProcessEntryPoint.PROPERTY_SHARED_PATH; import static org.sonar.process.ProcessProperties.PATH_DATA; import static org.sonar.process.ProcessProperties.PATH_HOME; @@ -62,10 +65,11 @@ public class ComputeEngineContainerImplTest { File homeDir = tempFolder.newFolder(); File dataDir = new File(homeDir, "data"); File tmpDir = new File(homeDir, "tmp"); - properties.setProperty(STARTED_AT, String.valueOf(new Date().getTime())); + properties.setProperty(STARTED_AT, valueOf(new Date().getTime())); properties.setProperty(PATH_HOME, homeDir.getAbsolutePath()); properties.setProperty(PATH_DATA, dataDir.getAbsolutePath()); properties.setProperty(PATH_TEMP, tmpDir.getAbsolutePath()); + properties.setProperty(PROPERTY_PROCESS_INDEX, valueOf(ProcessId.COMPUTE_ENGINE.getIpcIndex())); properties.setProperty(PROPERTY_SHARED_PATH, tmpDir.getAbsolutePath()); String url = ((BasicDataSource) dbTester.database().getDataSource()).getUrl(); properties.setProperty(DatabaseProperties.PROP_URL, url); @@ -80,7 +84,7 @@ public class ComputeEngineContainerImplTest { .hasSize( CONTAINER_ITSELF + 75 // level 4 - + 5 // content of CeModule + + 7 // content of CeModule + 7 // content of CeQueueModule + 4 // content of ReportProcessingModule + 4 // content of CeTaskProcessorModule @@ -95,7 +99,7 @@ public class ComputeEngineContainerImplTest { ); assertThat(picoContainer.getParent().getParent().getParent().getComponentAdapters()).hasSize( COMPONENTS_IN_LEVEL_1_AT_CONSTRUCTION - + 23 // level 1 + + 22 // level 1 + 45 // content of DaoModule + 1 // content of EsSearchModule + 56 // content of CorePropertyDefinitions diff --git a/server/sonar-process/pom.xml b/server/sonar-process/pom.xml index 3bd9cfc33d7..ee7d279fc2f 100644 --- a/server/sonar-process/pom.xml +++ b/server/sonar-process/pom.xml @@ -29,12 +29,23 @@ <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> </dependency> - <dependency> <groupId>com.google.code.findbugs</groupId> <artifactId>jsr305</artifactId> <scope>provided</scope> </dependency> + <dependency> + <!-- only if org.sonar.process.systeminfo HTTP server is being used --> + <groupId>org.nanohttpd</groupId> + <artifactId>nanohttpd</artifactId> + <optional>true</optional> + </dependency> + <dependency> + <!-- only if org.sonar.process.systeminfo.protobuf classes are used --> + <groupId>com.google.protobuf</groupId> + <artifactId>protobuf-java</artifactId> + <optional>true</optional> + </dependency> <dependency> <groupId>${project.groupId}</groupId> @@ -56,6 +67,11 @@ <artifactId>jetty-server</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>com.squareup.okhttp</groupId> + <artifactId>okhttp</artifactId> + <scope>test</scope> + </dependency> </dependencies> <build> <plugins> diff --git a/server/sonar-process/src/main/java/org/sonar/process/AllProcessesCommands.java b/server/sonar-process/src/main/java/org/sonar/process/AllProcessesCommands.java index 9652aca6795..f5e0954f6ff 100644 --- a/server/sonar-process/src/main/java/org/sonar/process/AllProcessesCommands.java +++ b/server/sonar-process/src/main/java/org/sonar/process/AllProcessesCommands.java @@ -69,11 +69,11 @@ public class AllProcessesCommands implements AutoCloseable { private static final int RESTART_BYTE_OFFSET = 2; private static final int OPERATIONAL_BYTE_OFFSET = 3; private static final int PING_BYTE_OFFSET = 4; - private static final int JMX_URL_BYTE_OFFSET = PING_BYTE_OFFSET + 8; + private static final int SYSTEM_INFO_URL_BYTE_OFFSET = PING_BYTE_OFFSET + 8; - private static final int JMX_URL_SIZE_IN_BYTES = 500; + private static final int SYSTEM_INFO_URL_SIZE_IN_BYTES = 500; - private static final int BYTE_LENGTH_FOR_ONE_PROCESS = 1 + 1 + 1 + 1 + 8 + JMX_URL_SIZE_IN_BYTES; + private static final int BYTE_LENGTH_FOR_ONE_PROCESS = 1 + 1 + 1 + 1 + 8 + SYSTEM_INFO_URL_SIZE_IN_BYTES; // With this shared memory we can handle up to MAX_PROCESSES processes private static final int MAX_SHARED_MEMORY = BYTE_LENGTH_FOR_ONE_PROCESS * MAX_PROCESSES; @@ -148,17 +148,17 @@ public class AllProcessesCommands implements AutoCloseable { return readLong(processNumber, PING_BYTE_OFFSET); } - String getJmxUrl(int processNumber) { - byte[] urlBytes = readBytes(processNumber, JMX_URL_BYTE_OFFSET, JMX_URL_SIZE_IN_BYTES); + String getSystemInfoUrl(int processNumber) { + byte[] urlBytes = readBytes(processNumber, SYSTEM_INFO_URL_BYTE_OFFSET, SYSTEM_INFO_URL_SIZE_IN_BYTES); return new String(urlBytes, StandardCharsets.US_ASCII).trim(); } - void setJmxUrl(int processNumber, String jmxUrl) { - byte[] urlBytes = rightPad(jmxUrl, JMX_URL_SIZE_IN_BYTES).getBytes(StandardCharsets.US_ASCII); - if (urlBytes.length > JMX_URL_SIZE_IN_BYTES) { - throw new IllegalArgumentException(format("JMX URL is too long. Max is %d bytes. Got: %s", JMX_URL_SIZE_IN_BYTES, jmxUrl)); + void setSystemInfoUrl(int processNumber, String url) { + byte[] urlBytes = rightPad(url, SYSTEM_INFO_URL_SIZE_IN_BYTES).getBytes(StandardCharsets.US_ASCII); + if (urlBytes.length > SYSTEM_INFO_URL_SIZE_IN_BYTES) { + throw new IllegalArgumentException(format("System Info URL is too long. Max is %d bytes. Got: %s", SYSTEM_INFO_URL_SIZE_IN_BYTES, url)); } - writeBytes(processNumber, JMX_URL_BYTE_OFFSET, urlBytes); + writeBytes(processNumber, SYSTEM_INFO_URL_BYTE_OFFSET, urlBytes); } /** @@ -277,13 +277,13 @@ public class AllProcessesCommands implements AutoCloseable { } @Override - public void setJmxUrl(String s) { - AllProcessesCommands.this.setJmxUrl(processNumber, s); + public void setSystemInfoUrl(String s) { + AllProcessesCommands.this.setSystemInfoUrl(processNumber, s); } @Override - public String getJmxUrl() { - return AllProcessesCommands.this.getJmxUrl(processNumber); + public String getSystemInfoUrl() { + return AllProcessesCommands.this.getSystemInfoUrl(processNumber); } @Override diff --git a/server/sonar-process/src/main/java/org/sonar/process/DefaultProcessCommands.java b/server/sonar-process/src/main/java/org/sonar/process/DefaultProcessCommands.java index d8c9975a4ba..dade6ab6265 100644 --- a/server/sonar-process/src/main/java/org/sonar/process/DefaultProcessCommands.java +++ b/server/sonar-process/src/main/java/org/sonar/process/DefaultProcessCommands.java @@ -83,13 +83,13 @@ public class DefaultProcessCommands implements ProcessCommands { } @Override - public void setJmxUrl(String s) { - delegate.setJmxUrl(s); + public void setSystemInfoUrl(String s) { + delegate.setSystemInfoUrl(s); } @Override - public String getJmxUrl() { - return delegate.getJmxUrl(); + public String getSystemInfoUrl() { + return delegate.getSystemInfoUrl(); } @Override diff --git a/server/sonar-process/src/main/java/org/sonar/process/jmx/Jmx.java b/server/sonar-process/src/main/java/org/sonar/process/Jmx.java index 62375a32e83..76a7b03c639 100644 --- a/server/sonar-process/src/main/java/org/sonar/process/jmx/Jmx.java +++ b/server/sonar-process/src/main/java/org/sonar/process/Jmx.java @@ -17,7 +17,7 @@ * 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.jmx; +package org.sonar.process; import java.lang.management.ManagementFactory; import javax.management.InstanceAlreadyExistsException; diff --git a/server/sonar-process/src/main/java/org/sonar/process/ProcessCommands.java b/server/sonar-process/src/main/java/org/sonar/process/ProcessCommands.java index 01ece9a7060..9c2f4a35a62 100644 --- a/server/sonar-process/src/main/java/org/sonar/process/ProcessCommands.java +++ b/server/sonar-process/src/main/java/org/sonar/process/ProcessCommands.java @@ -55,9 +55,9 @@ public interface ProcessCommands extends AutoCloseable { long getLastPing(); - void setJmxUrl(String s); + void setSystemInfoUrl(String s); - String getJmxUrl(); + String getSystemInfoUrl(); /** * To be executed by monitor process to ask for child process termination diff --git a/server/sonar-process/src/main/java/org/sonar/process/ProcessEntryPoint.java b/server/sonar-process/src/main/java/org/sonar/process/ProcessEntryPoint.java index f77cc7c292a..2ca262205ce 100644 --- a/server/sonar-process/src/main/java/org/sonar/process/ProcessEntryPoint.java +++ b/server/sonar-process/src/main/java/org/sonar/process/ProcessEntryPoint.java @@ -22,7 +22,6 @@ package org.sonar.process; import java.io.File; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import sun.misc.VMSupport; public class ProcessEntryPoint implements Stoppable { @@ -107,10 +106,6 @@ public class ProcessEntryPoint implements Stoppable { Thread.sleep(20L); } - String jmxUrl = guessJmxUrl(); - logger.debug("JMX URL is {}", jmxUrl); - commands.setJmxUrl(jmxUrl); - // notify monitor that process is ready commands.setUp(); @@ -125,15 +120,6 @@ public class ProcessEntryPoint implements Stoppable { } } - private static String guessJmxUrl() { - // this property is set by the agent management-agent.jar enabled by org.sonar.process.monitor.JavaProcessLauncher. - String jmxUrl = VMSupport.getAgentProperties().getProperty("com.sun.management.jmxremote.localConnectorAddress"); - if (jmxUrl == null) { - throw new IllegalStateException("Fail to load the JMX URL of JVM " + System.getProperty("java.vm.name")); - } - return jmxUrl; - } - boolean isStarted() { return lifecycle.getState() == Lifecycle.State.STARTED; } diff --git a/server/sonar-process/src/main/java/org/sonar/process/jmx/JmxConnection.java b/server/sonar-process/src/main/java/org/sonar/process/jmx/JmxConnection.java deleted file mode 100644 index 4c2eaca5452..00000000000 --- a/server/sonar-process/src/main/java/org/sonar/process/jmx/JmxConnection.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program 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. - * - * This program 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.jmx; - -import java.io.IOException; -import java.lang.management.ManagementFactory; -import java.lang.management.MemoryMXBean; -import java.lang.management.MemoryUsage; -import java.lang.management.ThreadMXBean; -import java.util.LinkedHashMap; -import java.util.Map; -import javax.annotation.CheckForNull; -import javax.management.JMX; -import javax.management.MBeanServerConnection; -import javax.management.ObjectName; -import javax.management.remote.JMXConnector; - -import static java.lang.String.format; - -public class JmxConnection implements AutoCloseable { - - private static final long MEGABYTE = 1024L * 1024L; - private final JMXConnector jmxConnector; - - JmxConnection(JMXConnector jmxConnector) { - this.jmxConnector = jmxConnector; - } - - /** - * Get a MBean from a remote JMX server. - * @throws IllegalStateException if a valid - * connection to remote server cannot be created, for instance because the connection to has - * not yet been established (with {@link JMXConnector#connect()}), or it has been closed/broken. - */ - public <M> M getMBean(String mBeanName, Class<M> mBeanInterfaceClass) { - try { - MBeanServerConnection connection = jmxConnector.getMBeanServerConnection(); - if (mBeanName.startsWith("java.lang")) { - return ManagementFactory.newPlatformMXBeanProxy(connection, mBeanName, mBeanInterfaceClass); - } - return JMX.newMBeanProxy(connection, new ObjectName(mBeanName), mBeanInterfaceClass); - } catch (Exception e) { - throw new IllegalStateException(format("Fail to connect to MBean [%s]", mBeanName), e); - } - } - - public Map<String, Object> getSystemState() { - Map<String, Object> props = new LinkedHashMap<>(); - MemoryMXBean memory = getMBean(ManagementFactory.MEMORY_MXBEAN_NAME, MemoryMXBean.class); - MemoryUsage heap = memory.getHeapMemoryUsage(); - props.put("Heap Committed (MB)", toMegaBytes(heap.getCommitted())); - props.put("Heap Init (MB)", toMegaBytes(heap.getInit())); - props.put("Heap Max (MB)", toMegaBytes(heap.getMax())); - props.put("Heap Used (MB)", toMegaBytes(heap.getUsed())); - MemoryUsage nonHeap = memory.getNonHeapMemoryUsage(); - props.put("Non Heap Committed (MB)", toMegaBytes(nonHeap.getCommitted())); - props.put("Non Heap Init (MB)", toMegaBytes(nonHeap.getInit())); - props.put("Non Heap Max (MB)", toMegaBytes(nonHeap.getMax())); - props.put("Non Heap Used (MB)", toMegaBytes(nonHeap.getUsed())); - ThreadMXBean thread = getMBean(ManagementFactory.THREAD_MXBEAN_NAME, ThreadMXBean.class); - props.put("Thread Count", thread.getThreadCount()); - return props; - } - - // visible for testing - @CheckForNull - static Long toMegaBytes(long bytes) { - if (bytes < 0L) { - return null; - } - return bytes / MEGABYTE; - } - - @Override - public void close() { - try { - jmxConnector.close(); - } catch (IOException e) { - throw new IllegalStateException("Can not close JMX connector", e); - } - } -} diff --git a/server/sonar-process/src/main/java/org/sonar/process/systeminfo/ProcessStateSystemInfo.java b/server/sonar-process/src/main/java/org/sonar/process/systeminfo/ProcessStateSystemInfo.java new file mode 100644 index 00000000000..1ca9297ee33 --- /dev/null +++ b/server/sonar-process/src/main/java/org/sonar/process/systeminfo/ProcessStateSystemInfo.java @@ -0,0 +1,65 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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.systeminfo; + +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryMXBean; +import java.lang.management.MemoryUsage; +import java.lang.management.ThreadMXBean; +import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo; + +public class ProcessStateSystemInfo implements SystemInfoSection { + private static final long MEGABYTE = 1024L * 1024L; + private final String name; + + public ProcessStateSystemInfo(String name) { + this.name = name; + } + + @Override + public ProtobufSystemInfo.Section toProtobuf() { + return toProtobuf(ManagementFactory.getMemoryMXBean()); + } + + // Visible for testing + ProtobufSystemInfo.Section toProtobuf(MemoryMXBean memoryBean) { + ProtobufSystemInfo.Section.Builder builder = ProtobufSystemInfo.Section.newBuilder(); + builder.setName(name); + MemoryUsage heap = memoryBean.getHeapMemoryUsage(); + addAttributeInMb(builder, "Heap Committed (MB)", heap.getCommitted()); + addAttributeInMb(builder, "Heap Init (MB)", heap.getInit()); + addAttributeInMb(builder, "Heap Max (MB)", heap.getMax()); + addAttributeInMb(builder, "Heap Used (MB)", heap.getUsed()); + MemoryUsage nonHeap = memoryBean.getNonHeapMemoryUsage(); + addAttributeInMb(builder, "Non Heap Committed (MB)", nonHeap.getCommitted()); + addAttributeInMb(builder, "Non Heap Init (MB)", nonHeap.getInit()); + addAttributeInMb(builder, "Non Heap Max (MB)", nonHeap.getMax()); + addAttributeInMb(builder, "Non Heap Used (MB)", nonHeap.getUsed()); + ThreadMXBean thread = ManagementFactory.getThreadMXBean(); + builder.addAttributesBuilder().setKey("Thread Count").setLongValue(thread.getThreadCount()).build(); + return builder.build(); + } + + private void addAttributeInMb(ProtobufSystemInfo.Section.Builder builder, String key, long valueInBytes) { + if (valueInBytes >= 0L) { + builder.addAttributesBuilder().setKey(key).setLongValue(valueInBytes / MEGABYTE).build(); + } + } +} diff --git a/server/sonar-process/src/main/java/org/sonar/process/systeminfo/SystemInfoHttpServer.java b/server/sonar-process/src/main/java/org/sonar/process/systeminfo/SystemInfoHttpServer.java new file mode 100644 index 00000000000..b8c08f3b90c --- /dev/null +++ b/server/sonar-process/src/main/java/org/sonar/process/systeminfo/SystemInfoHttpServer.java @@ -0,0 +1,104 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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.systeminfo; + +import fi.iki.elonen.NanoHTTPD; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.List; +import java.util.Properties; +import org.slf4j.LoggerFactory; +import org.sonar.process.DefaultProcessCommands; +import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo; + +import static java.lang.Integer.parseInt; +import static org.sonar.process.ProcessEntryPoint.PROPERTY_PROCESS_INDEX; +import static org.sonar.process.ProcessEntryPoint.PROPERTY_SHARED_PATH; + +/** + * This HTTP server exports data required for display of System Info page (and the related web service). + * It listens on loopback address only, so it does not need to be secure (no HTTPS, no authentication). + */ +public class SystemInfoHttpServer { + + private static final String PROTOBUF_MIME_TYPE = "application/x-protobuf"; + + private final Properties processProps; + private final List<SystemInfoSection> sectionProviders; + private final SystemInfoNanoHttpd nanoHttpd; + + public SystemInfoHttpServer(Properties processProps, List<SystemInfoSection> sectionProviders) throws UnknownHostException { + this.processProps = processProps; + this.sectionProviders = sectionProviders; + InetAddress loopbackAddress = InetAddress.getByName(null); + this.nanoHttpd = new SystemInfoNanoHttpd(loopbackAddress.getHostAddress(), 0); + } + + // do not rename. This naming convention is required for picocontainer. + public void start() { + try { + nanoHttpd.start(); + registerHttpUrl(); + } catch (IOException e) { + throw new IllegalStateException("Can not start local HTTP server for System Info monitoring", e); + } + } + + private void registerHttpUrl() { + int processNumber = parseInt(processProps.getProperty(PROPERTY_PROCESS_INDEX)); + File shareDir = new File(processProps.getProperty(PROPERTY_SHARED_PATH)); + try (DefaultProcessCommands commands = DefaultProcessCommands.secondary(shareDir, processNumber)) { + String url = getUrl(); + commands.setSystemInfoUrl(url); + LoggerFactory.getLogger(getClass()).debug("System Info HTTP server listening at {}", url); + } + } + + // do not rename. This naming convention is required for picocontainer. + public void stop() { + nanoHttpd.stop(); + } + + // visible for testing + String getUrl() { + return "http://" + nanoHttpd.getHostname() + ":" + nanoHttpd.getListeningPort(); + } + + private class SystemInfoNanoHttpd extends NanoHTTPD { + + SystemInfoNanoHttpd(String hostname, int port) { + super(hostname, port); + } + + @Override + public Response serve(IHTTPSession session) { + ProtobufSystemInfo.SystemInfo.Builder infoBuilder = ProtobufSystemInfo.SystemInfo.newBuilder(); + for (SystemInfoSection sectionProvider : sectionProviders) { + ProtobufSystemInfo.Section section = sectionProvider.toProtobuf(); + infoBuilder.addSections(section); + } + byte[] bytes = infoBuilder.build().toByteArray(); + return newFixedLengthResponse(Response.Status.OK, PROTOBUF_MIME_TYPE, new ByteArrayInputStream(bytes), bytes.length); + } + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/EsStateMonitor.java b/server/sonar-process/src/main/java/org/sonar/process/systeminfo/SystemInfoSection.java index 779019be924..c990cacb96b 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/EsStateMonitor.java +++ b/server/sonar-process/src/main/java/org/sonar/process/systeminfo/SystemInfoSection.java @@ -17,34 +17,12 @@ * 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.server.platform.monitoring; +package org.sonar.process.systeminfo; -import com.google.common.base.Optional; -import java.util.Map; -import org.sonar.process.ProcessId; -import org.sonar.process.jmx.JmxConnection; -import org.sonar.process.jmx.JmxConnectionFactory; +import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo; -public class EsStateMonitor implements Monitor { +public interface SystemInfoSection { - private final JmxConnectionFactory jmxConnectionFactory; + ProtobufSystemInfo.Section toProtobuf(); - public EsStateMonitor(JmxConnectionFactory jmxConnectionFactory) { - this.jmxConnectionFactory = jmxConnectionFactory; - } - - @Override - public String name() { - return "Elasticsearch State"; - } - - @Override - public Optional<Map<String, Object>> attributes() { - try (JmxConnection connection = jmxConnectionFactory.create(ProcessId.ELASTICSEARCH)) { - if (connection == null) { - return Optional.absent(); - } - return Optional.of(connection.getSystemState()); - } - } } diff --git a/server/sonar-process/src/main/java/org/sonar/process/jmx/package-info.java b/server/sonar-process/src/main/java/org/sonar/process/systeminfo/package-info.java index bb4fb97207f..3ae1af74953 100644 --- a/server/sonar-process/src/main/java/org/sonar/process/jmx/package-info.java +++ b/server/sonar-process/src/main/java/org/sonar/process/systeminfo/package-info.java @@ -18,6 +18,6 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ @ParametersAreNonnullByDefault -package org.sonar.process.jmx; +package org.sonar.process.systeminfo; import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-process/src/main/protobuf/process_system_info.proto b/server/sonar-process/src/main/protobuf/process_system_info.proto new file mode 100644 index 00000000000..8780b677596 --- /dev/null +++ b/server/sonar-process/src/main/protobuf/process_system_info.proto @@ -0,0 +1,43 @@ +// SonarQube, open source software quality management tool. +// Copyright (C) 2008-2016 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. + +syntax = "proto3"; + +option java_package = "org.sonar.process.systeminfo.protobuf"; +option java_outer_classname = "ProtobufSystemInfo"; + +option optimize_for = SPEED; + +message SystemInfo { + repeated Section sections = 1; +} + +message Section { + string name = 1; + repeated Attribute attributes = 2; +} + +message Attribute { + string key = 1; + oneof value { + bool boolean_value = 2; + int64 long_value = 3; + double double_value = 4; + string string_value = 5; + } +} diff --git a/server/sonar-process/src/test/java/org/sonar/process/AllProcessesCommandsTest.java b/server/sonar-process/src/test/java/org/sonar/process/AllProcessesCommandsTest.java index e834fce905f..1c26836fc1e 100644 --- a/server/sonar-process/src/test/java/org/sonar/process/AllProcessesCommandsTest.java +++ b/server/sonar-process/src/test/java/org/sonar/process/AllProcessesCommandsTest.java @@ -105,9 +105,9 @@ public class AllProcessesCommandsTest { assertThat(readByte(commands, offset + i)).isEqualTo(EMPTY); } - commands.setJmxUrl(PROCESS_NUMBER, "jmx:foo"); + commands.setSystemInfoUrl(PROCESS_NUMBER, "jmx:foo"); assertThat(readByte(commands, offset)).isNotEqualTo(EMPTY); - assertThat(commands.getJmxUrl(PROCESS_NUMBER)).isEqualTo("jmx:foo"); + assertThat(commands.getSystemInfoUrl(PROCESS_NUMBER)).isEqualTo("jmx:foo"); } @Test diff --git a/server/sonar-process/src/test/java/org/sonar/process/jmx/JmxTest.java b/server/sonar-process/src/test/java/org/sonar/process/JmxTest.java index 9b241accac3..7df06238d94 100644 --- a/server/sonar-process/src/test/java/org/sonar/process/jmx/JmxTest.java +++ b/server/sonar-process/src/test/java/org/sonar/process/JmxTest.java @@ -17,7 +17,7 @@ * 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.jmx; +package org.sonar.process; import java.lang.management.ManagementFactory; import javax.annotation.CheckForNull; @@ -27,6 +27,8 @@ import javax.management.ObjectName; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.sonar.process.jmx.Fake; +import org.sonar.process.jmx.FakeMBean; import static org.assertj.core.api.Assertions.assertThat; @@ -65,6 +67,14 @@ public class JmxTest { } @Test + public void register_fails_if_name_is_not_valid() { + expectedException.expect(IllegalStateException.class); + expectedException.expectMessage("Can not register MBean [/]"); + + Jmx.register("/", new Fake()); + } + + @Test public void support_implementation_in_different_package_than_interface() throws Exception { assertThat(lookupMBean()).isNull(); diff --git a/server/sonar-process/src/test/java/org/sonar/process/jmx/JmxConnectionFactoryTest.java b/server/sonar-process/src/test/java/org/sonar/process/jmx/JmxConnectionFactoryTest.java deleted file mode 100644 index 4709acb83d3..00000000000 --- a/server/sonar-process/src/test/java/org/sonar/process/jmx/JmxConnectionFactoryTest.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program 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. - * - * This program 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.jmx; - -import java.io.File; -import java.util.Properties; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; -import org.sonar.process.DefaultProcessCommands; -import org.sonar.process.ProcessId; -import org.sonar.process.Props; - -import static org.assertj.core.api.Assertions.assertThat; - -public class JmxConnectionFactoryTest { - - @Rule - public TemporaryFolder temp = new TemporaryFolder(); - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @Rule - public JmxTestServer jmxServer = new JmxTestServer(); - - @Test - public void create_returns_null_if_process_is_down() throws Exception { - File ipcSharedDir = temp.newFolder(); - JmxConnectionFactory underTest = new JmxConnectionFactory(ipcSharedDir); - - JmxConnection connection = underTest.create(ProcessId.COMPUTE_ENGINE); - - assertThat(connection).isNull(); - } - - @Test - public void create_connection_if_process_is_up() throws Exception { - File ipcSharedDir = temp.newFolder(); - try (DefaultProcessCommands processCommands = DefaultProcessCommands.secondary(ipcSharedDir, ProcessId.COMPUTE_ENGINE.getIpcIndex())) { - processCommands.setUp(); - processCommands.setJmxUrl(jmxServer.getAddress().toString()); - } - - JmxConnection connection = new JmxConnectionFactory(ipcSharedDir).create(ProcessId.COMPUTE_ENGINE); - assertThat(connection).isNotNull(); - } - - @Test - public void create_throws_ISE_if_fails_to_connect_to_process() throws Exception { - File ipcSharedDir = temp.newFolder(); - try (DefaultProcessCommands processCommands = DefaultProcessCommands.secondary(ipcSharedDir, ProcessId.COMPUTE_ENGINE.getIpcIndex())) { - // process is up but does not have any JMX URL - processCommands.setUp(); - } - - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage("Can not connect to process " + ProcessId.COMPUTE_ENGINE.toString()); - new JmxConnectionFactory(ipcSharedDir).create(ProcessId.COMPUTE_ENGINE); - } - - @Test - public void load_ipc_shared_dir_from_props() throws Exception { - File ipcSharedDir = temp.newFolder(); - Properties props = new Properties(); - props.setProperty("process.sharedDir", ipcSharedDir.getAbsolutePath()); - - JmxConnectionFactory underTest = new JmxConnectionFactory(new Props(props)); - - assertThat(underTest.getIpcSharedDir().getCanonicalPath()).isEqualTo(ipcSharedDir.getCanonicalPath()); - } - -} diff --git a/server/sonar-process/src/test/java/org/sonar/process/jmx/JmxConnectionTest.java b/server/sonar-process/src/test/java/org/sonar/process/jmx/JmxConnectionTest.java deleted file mode 100644 index efb7f83701f..00000000000 --- a/server/sonar-process/src/test/java/org/sonar/process/jmx/JmxConnectionTest.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program 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. - * - * This program 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.jmx; - -import java.lang.management.ManagementFactory; -import java.lang.management.RuntimeMXBean; -import java.util.Map; -import javax.management.ObjectName; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXConnectorFactory; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import static org.assertj.core.api.Assertions.assertThat; - -public class JmxConnectionTest { - - private static final String CUSTOM_OBJECT_NAME = "Test:name=test"; - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @Rule - public JmxTestServer jmxServer = new JmxTestServer(); - - JmxConnection underTest; - - @Before - public void setUp() throws Exception { - jmxServer.getMBeanServer().registerMBean(new Fake(), new ObjectName(CUSTOM_OBJECT_NAME)); - JMXConnector jmxConnector = JMXConnectorFactory.newJMXConnector(jmxServer.getAddress(), null); - jmxConnector.connect(); - underTest = new JmxConnection(jmxConnector); - } - - @After - public void tearDown() throws Exception { - underTest.close(); - jmxServer.getMBeanServer().unregisterMBean(new ObjectName(CUSTOM_OBJECT_NAME)); - } - - @Test - public void toMegaBytes() { - assertThat(JmxConnection.toMegaBytes(-1)).isNull(); - assertThat(JmxConnection.toMegaBytes(0L)).isEqualTo(0L); - assertThat(JmxConnection.toMegaBytes(500L)).isEqualTo(0L); - assertThat(JmxConnection.toMegaBytes(500_000L)).isEqualTo(0L); - assertThat(JmxConnection.toMegaBytes(500_000_000L)).isEqualTo(476L); - } - - @Test - public void get_platform_mbean() throws Exception { - RuntimeMXBean runtimeMBean = underTest.getMBean(ManagementFactory.RUNTIME_MXBEAN_NAME, RuntimeMXBean.class); - - assertThat(runtimeMBean).isNotNull(); - } - - @Test - public void get_custom_mbean() throws Exception { - FakeMBean mbean = underTest.getMBean(CUSTOM_OBJECT_NAME, FakeMBean.class); - - assertThat(mbean).isNotNull(); - } - - @Test - public void getMBean_fails_if_does_not_exist() throws Exception { - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage("Fail to connect to MBean [unknown]"); - underTest.getMBean("unknown", FakeMBean.class); - } - - @Test - public void getSystemState() throws Exception { - Map<String, Object> state = underTest.getSystemState(); - assertThat(state).containsKey("Heap Max (MB)"); - assertThat((int) state.get("Thread Count")).isGreaterThan(0); - } -} diff --git a/server/sonar-process/src/test/java/org/sonar/process/jmx/JmxTestServer.java b/server/sonar-process/src/test/java/org/sonar/process/jmx/JmxTestServer.java deleted file mode 100644 index 9ffe8413bef..00000000000 --- a/server/sonar-process/src/test/java/org/sonar/process/jmx/JmxTestServer.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program 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. - * - * This program 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.jmx; - -import com.google.common.base.Throwables; -import java.io.IOException; -import java.lang.management.ManagementFactory; -import java.rmi.registry.LocateRegistry; -import java.util.HashMap; -import javax.management.MBeanServer; -import javax.management.remote.JMXConnectorServer; -import javax.management.remote.JMXConnectorServerFactory; -import javax.management.remote.JMXServiceURL; -import org.junit.rules.ExternalResource; -import org.sonar.process.NetworkUtils; - -public class JmxTestServer extends ExternalResource { - - private final int jmxPort = NetworkUtils.freePort(); - private JMXConnectorServer jmxServer; - - @Override - protected void before() throws Throwable { - LocateRegistry.createRegistry(jmxPort); - JMXServiceURL serviceUrl = new JMXServiceURL("service:jmx:rmi://localhost:" + jmxPort + "/jndi/rmi://localhost:" + jmxPort + "/jmxrmi"); - MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer(); - jmxServer = JMXConnectorServerFactory.newJMXConnectorServer(serviceUrl, new HashMap<String, Object>(), mbeanServer); - jmxServer.start(); - - } - - @Override - protected void after() { - if (jmxServer != null) { - try { - jmxServer.stop(); - } catch (IOException e) { - throw Throwables.propagate(e); - } - } - } - - public int getPort() { - return jmxPort; - } - - public MBeanServer getMBeanServer() { - return jmxServer.getMBeanServer(); - } - - public JMXServiceURL getAddress() { - return jmxServer.getAddress(); - } -} diff --git a/server/sonar-process/src/test/java/org/sonar/process/systeminfo/ProcessStateSystemInfoTest.java b/server/sonar-process/src/test/java/org/sonar/process/systeminfo/ProcessStateSystemInfoTest.java new file mode 100644 index 00000000000..b1088a07584 --- /dev/null +++ b/server/sonar-process/src/test/java/org/sonar/process/systeminfo/ProcessStateSystemInfoTest.java @@ -0,0 +1,58 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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.systeminfo; + +import java.lang.management.MemoryMXBean; +import org.junit.Test; +import org.mockito.Mockito; +import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class ProcessStateSystemInfoTest { + + public static final String PROCESS_NAME = "the process name"; + + @Test + public void toSystemInfoSection() { + ProcessStateSystemInfo underTest = new ProcessStateSystemInfo(PROCESS_NAME); + ProtobufSystemInfo.Section section = underTest.toProtobuf(); + + assertThat(section.getName()).isEqualTo(PROCESS_NAME); + assertThat(section.getAttributesCount()).isEqualTo(9); + assertThat(section.getAttributes(0).getKey()).isEqualTo("Heap Committed (MB)"); + assertThat(section.getAttributes(0).getLongValue()).isGreaterThan(1L); + assertThat(section.getAttributes(8).getKey()).isEqualTo("Thread Count"); + assertThat(section.getAttributes(8).getLongValue()).isGreaterThan(1L); + } + + @Test + public void should_hide_attributes_without_values() { + MemoryMXBean memoryBean = mock(MemoryMXBean.class, Mockito.RETURNS_DEEP_STUBS); + when(memoryBean.getHeapMemoryUsage().getCommitted()).thenReturn(-1L); + + ProcessStateSystemInfo underTest = new ProcessStateSystemInfo(PROCESS_NAME); + ProtobufSystemInfo.Section section = underTest.toProtobuf(memoryBean); + + assertThat(section.getAttributesList()).extracting("key").doesNotContain("Heap Committed (MB)"); + } +} diff --git a/server/sonar-process/src/test/java/org/sonar/process/systeminfo/SystemInfoHttpServerTest.java b/server/sonar-process/src/test/java/org/sonar/process/systeminfo/SystemInfoHttpServerTest.java new file mode 100644 index 00000000000..31f7f48f08f --- /dev/null +++ b/server/sonar-process/src/test/java/org/sonar/process/systeminfo/SystemInfoHttpServerTest.java @@ -0,0 +1,89 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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.systeminfo; + +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Response; +import java.io.IOException; +import java.net.ConnectException; +import java.util.Arrays; +import java.util.Properties; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.rules.TemporaryFolder; +import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.sonar.process.ProcessEntryPoint.PROPERTY_PROCESS_INDEX; +import static org.sonar.process.ProcessEntryPoint.PROPERTY_SHARED_PATH; + +public class SystemInfoHttpServerTest { + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + SystemInfoSection stateProvider1 = new ProcessStateSystemInfo("state1"); + SystemInfoSection stateProvider2 = new ProcessStateSystemInfo("state2"); + SystemInfoHttpServer underTest; + + @Before + public void setUp() throws Exception { + Properties properties = new Properties(); + properties.setProperty(PROPERTY_PROCESS_INDEX, "1"); + properties.setProperty(PROPERTY_SHARED_PATH, temp.newFolder().getAbsolutePath()); + underTest = new SystemInfoHttpServer(properties, Arrays.asList(stateProvider1, stateProvider2)); + } + + @After + public void tearDown() { + underTest.stop(); + } + + @Test + public void start_starts_http_server_and_publishes_URL_in_IPC() throws Exception { + underTest.start(); + Response response = call(underTest.getUrl()); + assertThat(response.code()).isEqualTo(200); + ProtobufSystemInfo.SystemInfo systemInfo = ProtobufSystemInfo.SystemInfo.parseFrom(response.body().bytes()); + assertThat(systemInfo.getSectionsCount()).isEqualTo(2); + assertThat(systemInfo.getSections(0).getName()).isEqualTo("state1"); + assertThat(systemInfo.getSections(1).getName()).isEqualTo("state2"); + } + + @Test + public void stop_stops_http_server() throws Exception { + underTest.start(); + underTest.stop(); + expectedException.expect(ConnectException.class); + call(underTest.getUrl()); + } + + private static Response call(String url) throws IOException { + Request request = new Request.Builder().get().url(url).build(); + return new OkHttpClient().newCall(request).execute(); + } +} diff --git a/server/sonar-search/src/main/java/org/sonar/search/EsSettings.java b/server/sonar-search/src/main/java/org/sonar/search/EsSettings.java index 2f0986e1e45..50802429918 100644 --- a/server/sonar-search/src/main/java/org/sonar/search/EsSettings.java +++ b/server/sonar-search/src/main/java/org/sonar/search/EsSettings.java @@ -33,7 +33,6 @@ import org.slf4j.LoggerFactory; import org.sonar.process.MessageException; import org.sonar.process.ProcessProperties; import org.sonar.process.Props; -import org.sonar.process.jmx.EsSettingsMBean; public class EsSettings implements EsSettingsMBean { diff --git a/server/sonar-process/src/main/java/org/sonar/process/jmx/EsSettingsMBean.java b/server/sonar-search/src/main/java/org/sonar/search/EsSettingsMBean.java index 197dc35051c..9d5d2a4e712 100644 --- a/server/sonar-process/src/main/java/org/sonar/process/jmx/EsSettingsMBean.java +++ b/server/sonar-search/src/main/java/org/sonar/search/EsSettingsMBean.java @@ -17,7 +17,7 @@ * 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.jmx; +package org.sonar.search; /** * MBean registered in the Elasticsearch process diff --git a/server/sonar-search/src/main/java/org/sonar/search/SearchServer.java b/server/sonar-search/src/main/java/org/sonar/search/SearchServer.java index 31541ad259f..eda960f22b3 100644 --- a/server/sonar-search/src/main/java/org/sonar/search/SearchServer.java +++ b/server/sonar-search/src/main/java/org/sonar/search/SearchServer.java @@ -22,12 +22,11 @@ package org.sonar.search; import org.elasticsearch.action.admin.cluster.health.ClusterHealthStatus; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.node.internal.InternalNode; +import org.sonar.process.Jmx; import org.sonar.process.MinimumViableSystem; import org.sonar.process.Monitored; import org.sonar.process.ProcessEntryPoint; import org.sonar.process.Props; -import org.sonar.process.jmx.EsSettingsMBean; -import org.sonar.process.jmx.Jmx; public class SearchServer implements Monitored { diff --git a/server/sonar-server/pom.xml b/server/sonar-server/pom.xml index 2b1a4860dbb..12253497147 100644 --- a/server/sonar-server/pom.xml +++ b/server/sonar-server/pom.xml @@ -160,6 +160,10 @@ <artifactId>elasticsearch</artifactId> </dependency> <dependency> + <groupId>com.google.protobuf</groupId> + <artifactId>protobuf-java</artifactId> + </dependency> + <dependency> <groupId>${project.groupId}</groupId> <artifactId>sonar-ws</artifactId> <version>${project.version}</version> @@ -223,6 +227,11 @@ <artifactId>subethasmtp</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>com.squareup.okhttp</groupId> + <artifactId>mockwebserver</artifactId> + <scope>test</scope> + </dependency> </dependencies> diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/CeModule.java b/server/sonar-server/src/main/java/org/sonar/server/computation/CeModule.java index 4cdf80747d4..2051a4929e2 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/CeModule.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/CeModule.java @@ -22,6 +22,8 @@ package org.sonar.server.computation; import org.sonar.ce.log.CeLogging; import org.sonar.core.platform.Module; import org.sonar.db.purge.period.DefaultPeriodCleaner; +import org.sonar.process.systeminfo.ProcessStateSystemInfo; +import org.sonar.process.systeminfo.SystemInfoHttpServer; import org.sonar.server.computation.configuration.CeConfigurationImpl; import org.sonar.server.computation.dbcleaner.IndexPurgeListener; import org.sonar.server.computation.dbcleaner.ProjectCleaner; @@ -37,6 +39,8 @@ public class CeModule extends Module { CeConfigurationImpl.class, CeLogging.class, CeDatabaseMBeanImpl.class, + SystemInfoHttpServer.class, + new ProcessStateSystemInfo("Compute Engine State"), DefaultPeriodCleaner.class, ProjectCleaner.class, diff --git a/server/sonar-process/src/main/java/org/sonar/process/jmx/CeDatabaseMBean.java b/server/sonar-server/src/main/java/org/sonar/server/computation/monitoring/CeDatabaseMBean.java index 354ce0db734..6f20edc66c4 100644 --- a/server/sonar-process/src/main/java/org/sonar/process/jmx/CeDatabaseMBean.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/monitoring/CeDatabaseMBean.java @@ -17,11 +17,11 @@ * 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.jmx; +package org.sonar.server.computation.monitoring; public interface CeDatabaseMBean { - String OBJECT_NAME = "SonarQube:name=ComputeEngineDatabase"; + String OBJECT_NAME = "SonarQube:name=ComputeEngineDatabaseConnection"; int getPoolActiveConnections(); diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/monitoring/CeDatabaseMBeanImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/monitoring/CeDatabaseMBeanImpl.java index 4b7e43a3fa5..e0315abcad4 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/monitoring/CeDatabaseMBeanImpl.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/monitoring/CeDatabaseMBeanImpl.java @@ -22,10 +22,11 @@ package org.sonar.server.computation.monitoring; import org.apache.commons.dbcp.BasicDataSource; import org.picocontainer.Startable; import org.sonar.db.DbClient; -import org.sonar.process.jmx.CeDatabaseMBean; -import org.sonar.process.jmx.Jmx; +import org.sonar.process.Jmx; +import org.sonar.process.systeminfo.SystemInfoSection; +import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo; -public class CeDatabaseMBeanImpl implements CeDatabaseMBean, Startable { +public class CeDatabaseMBeanImpl implements CeDatabaseMBean, Startable, SystemInfoSection { private final DbClient dbClient; public CeDatabaseMBeanImpl(DbClient dbClient) { @@ -94,4 +95,19 @@ public class CeDatabaseMBeanImpl implements CeDatabaseMBean, Startable { return (BasicDataSource) dbClient.getDatabase().getDataSource(); } + @Override + public ProtobufSystemInfo.Section toProtobuf() { + ProtobufSystemInfo.Section.Builder builder = ProtobufSystemInfo.Section.newBuilder(); + builder.setName("Compute Engine Database Connection"); + builder.addAttributesBuilder().setKey("Pool Initial Size").setLongValue(getPoolInitialSize()).build(); + builder.addAttributesBuilder().setKey("Pool Active Connections").setLongValue(getPoolActiveConnections()).build(); + builder.addAttributesBuilder().setKey("Pool Idle Connections").setLongValue(getPoolIdleConnections()).build(); + builder.addAttributesBuilder().setKey("Pool Max Active Connections").setLongValue(getPoolMaxActiveConnections()).build(); + builder.addAttributesBuilder().setKey("Pool Max Idle Connections").setLongValue(getPoolMaxIdleConnections()).build(); + builder.addAttributesBuilder().setKey("Pool Min Idle Connections").setLongValue(getPoolMinIdleConnections()).build(); + builder.addAttributesBuilder().setKey("Pool Max Wait (ms)").setLongValue(getPoolMaxWaitMillis()).build(); + builder.addAttributesBuilder().setKey("Pool Remove Abandoned").setBooleanValue(getPoolRemoveAbandoned()).build(); + builder.addAttributesBuilder().setKey("Pool Remove Abandoned Timeout (sec)").setLongValue(getPoolRemoveAbandonedTimeoutSeconds()).build(); + return builder.build(); + } } diff --git a/server/sonar-process/src/main/java/org/sonar/process/jmx/CeTasksMBean.java b/server/sonar-server/src/main/java/org/sonar/server/computation/monitoring/CeTasksMBean.java index 968dabc52b2..227e9f6be8c 100644 --- a/server/sonar-process/src/main/java/org/sonar/process/jmx/CeTasksMBean.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/monitoring/CeTasksMBean.java @@ -17,7 +17,7 @@ * 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.jmx; +package org.sonar.server.computation.monitoring; public interface CeTasksMBean { diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/monitoring/CeTasksMBeanImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/monitoring/CeTasksMBeanImpl.java index 57b08e356de..df7e68ec989 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/monitoring/CeTasksMBeanImpl.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/monitoring/CeTasksMBeanImpl.java @@ -21,11 +21,12 @@ package org.sonar.server.computation.monitoring; import org.picocontainer.Startable; import org.sonar.ce.monitoring.CEQueueStatus; -import org.sonar.process.jmx.CeTasksMBean; -import org.sonar.process.jmx.Jmx; +import org.sonar.process.Jmx; +import org.sonar.process.systeminfo.SystemInfoSection; +import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo; import org.sonar.server.computation.configuration.CeConfiguration; -public class CeTasksMBeanImpl implements CeTasksMBean, Startable { +public class CeTasksMBeanImpl implements CeTasksMBean, Startable, SystemInfoSection { private final CEQueueStatus queueStatus; private final CeConfiguration ceConfiguration; @@ -76,4 +77,17 @@ public class CeTasksMBeanImpl implements CeTasksMBean, Startable { public int getWorkerCount() { return ceConfiguration.getWorkerCount(); } + + @Override + public ProtobufSystemInfo.Section toProtobuf() { + ProtobufSystemInfo.Section.Builder builder = ProtobufSystemInfo.Section.newBuilder(); + builder.setName("Compute Engine Tasks"); + builder.addAttributesBuilder().setKey("Pending").setLongValue(getPendingCount()).build(); + builder.addAttributesBuilder().setKey("In Progress").setLongValue(getInProgressCount()).build(); + builder.addAttributesBuilder().setKey("Processed With Error").setLongValue(getErrorCount()).build(); + builder.addAttributesBuilder().setKey("Processed With Success").setLongValue(getSuccessCount()).build(); + builder.addAttributesBuilder().setKey("Processing Time (ms)").setLongValue(getProcessingTime()).build(); + builder.addAttributesBuilder().setKey("Worker Count").setLongValue(getWorkerCount()).build(); + return builder.build(); + } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/BaseMonitorMBean.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/BaseMonitorMBean.java index b56d9a9346e..44f63304eec 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/BaseMonitorMBean.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/BaseMonitorMBean.java @@ -20,7 +20,7 @@ package org.sonar.server.platform.monitoring; import org.picocontainer.Startable; -import org.sonar.process.jmx.Jmx; +import org.sonar.process.Jmx; /** * Base implementation of a {@link org.sonar.server.platform.monitoring.Monitor} diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/CeDatabaseMonitor.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/CeDatabaseMonitor.java deleted file mode 100644 index 052d3ff5634..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/CeDatabaseMonitor.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program 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. - * - * This program 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.server.platform.monitoring; - -import com.google.common.base.Optional; -import java.util.LinkedHashMap; -import java.util.Map; -import org.sonar.process.ProcessId; -import org.sonar.process.jmx.CeDatabaseMBean; -import org.sonar.process.jmx.JmxConnection; -import org.sonar.process.jmx.JmxConnectionFactory; - -public class CeDatabaseMonitor implements Monitor { - - private static final int NUMBER_OF_ATTRIBUTES = 9; - - private final JmxConnectionFactory jmxConnectionFactory; - - public CeDatabaseMonitor(JmxConnectionFactory jmxConnectionFactory) { - this.jmxConnectionFactory = jmxConnectionFactory; - } - - @Override - public String name() { - return "Compute Engine Database Connection"; - } - - @Override - public Optional<Map<String, Object>> attributes() { - try (JmxConnection connection = jmxConnectionFactory.create(ProcessId.COMPUTE_ENGINE)) { - if (connection == null) { - return Optional.absent(); - } - Map<String, Object> result = new LinkedHashMap<>(NUMBER_OF_ATTRIBUTES); - CeDatabaseMBean mbean = connection.getMBean(CeDatabaseMBean.OBJECT_NAME, CeDatabaseMBean.class); - result.put("Pool Initial Size", mbean.getPoolInitialSize()); - result.put("Pool Active Connections", mbean.getPoolActiveConnections()); - result.put("Pool Idle Connections", mbean.getPoolIdleConnections()); - result.put("Pool Max Active Connections", mbean.getPoolMaxActiveConnections()); - result.put("Pool Max Idle Connections", mbean.getPoolMaxIdleConnections()); - result.put("Pool Min Idle Connections", mbean.getPoolMinIdleConnections()); - result.put("Pool Max Wait (ms)", mbean.getPoolMaxWaitMillis()); - result.put("Pool Remove Abandoned", mbean.getPoolRemoveAbandoned()); - result.put("Pool Remove Abandoned Timeout (sec)", mbean.getPoolRemoveAbandonedTimeoutSeconds()); - return Optional.of(result); - } - } -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/CeStateMonitor.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/CeStateMonitor.java deleted file mode 100644 index d920607edb6..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/CeStateMonitor.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program 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. - * - * This program 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.server.platform.monitoring; - -import com.google.common.base.Optional; -import java.util.Map; -import org.sonar.process.ProcessId; -import org.sonar.process.jmx.JmxConnection; -import org.sonar.process.jmx.JmxConnectionFactory; - -public class CeStateMonitor implements Monitor { - - private final JmxConnectionFactory jmxConnectionFactory; - - public CeStateMonitor(JmxConnectionFactory jmxConnectionFactory) { - this.jmxConnectionFactory = jmxConnectionFactory; - } - - @Override - public String name() { - return "Compute Engine State"; - } - - @Override - public Optional<Map<String, Object>> attributes() { - try (JmxConnection connection = jmxConnectionFactory.create(ProcessId.COMPUTE_ENGINE)) { - if (connection == null) { - return Optional.absent(); - } - return Optional.of(connection.getSystemState()); - } - } -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/CeTasksMonitor.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/CeTasksMonitor.java deleted file mode 100644 index fbdd08ba5dd..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/CeTasksMonitor.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program 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. - * - * This program 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.server.platform.monitoring; - -import com.google.common.base.Optional; -import java.util.LinkedHashMap; -import java.util.Map; -import org.sonar.process.ProcessId; -import org.sonar.process.jmx.CeTasksMBean; -import org.sonar.process.jmx.JmxConnection; -import org.sonar.process.jmx.JmxConnectionFactory; - -public class CeTasksMonitor implements Monitor { - - private static final int NUMBER_OF_ATTRIBUTES = 6; - - private final JmxConnectionFactory jmxConnectionFactory; - - public CeTasksMonitor(JmxConnectionFactory jmxConnectionFactory) { - this.jmxConnectionFactory = jmxConnectionFactory; - } - - @Override - public String name() { - return "Compute Engine Tasks"; - } - - @Override - public Optional<Map<String, Object>> attributes() { - try (JmxConnection connection = jmxConnectionFactory.create(ProcessId.COMPUTE_ENGINE)) { - if (connection == null) { - return Optional.absent(); - } - Map<String, Object> result = new LinkedHashMap<>(NUMBER_OF_ATTRIBUTES); - CeTasksMBean ceMBean = connection.getMBean(CeTasksMBean.OBJECT_NAME, CeTasksMBean.class); - result.put("Pending", ceMBean.getPendingCount()); - result.put("In Progress", ceMBean.getInProgressCount()); - result.put("Processed With Success", ceMBean.getSuccessCount()); - result.put("Processed With Error", ceMBean.getErrorCount()); - result.put("Processing Time (ms)", ceMBean.getProcessingTime()); - result.put("Worker Count", ceMBean.getWorkerCount()); - return Optional.of(result); - } - } -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/DatabaseMonitor.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/DatabaseMonitor.java index f71f841b6e6..4e957180552 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/DatabaseMonitor.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/DatabaseMonitor.java @@ -19,7 +19,6 @@ */ package org.sonar.server.platform.monitoring; -import com.google.common.base.Optional; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.SQLException; @@ -101,11 +100,11 @@ public class DatabaseMonitor extends BaseMonitorMBean implements DatabaseMonitor } @Override - public Optional<Map<String, Object>> attributes() { + public Map<String, Object> attributes() { Map<String, Object> attributes = new LinkedHashMap<>(); completeDbAttributes(attributes); completePoolAttributes(attributes); - return Optional.of(attributes); + return attributes; } private void completePoolAttributes(Map<String, Object> attributes) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/EsMonitor.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/EsMonitor.java index 686ae56880a..7f37d2b0f31 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/EsMonitor.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/EsMonitor.java @@ -19,7 +19,6 @@ */ package org.sonar.server.platform.monitoring; -import com.google.common.base.Optional; import java.util.LinkedHashMap; import java.util.Map; import org.elasticsearch.action.admin.cluster.health.ClusterHealthStatus; @@ -30,21 +29,15 @@ import org.elasticsearch.action.admin.indices.stats.IndexStats; import org.elasticsearch.action.admin.indices.stats.IndicesStatsResponse; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.common.breaker.CircuitBreaker; -import org.sonar.process.ProcessId; -import org.sonar.process.jmx.EsSettingsMBean; -import org.sonar.process.jmx.JmxConnection; -import org.sonar.process.jmx.JmxConnectionFactory; import org.sonar.server.es.EsClient; import static org.apache.commons.io.FileUtils.byteCountToDisplaySize; public class EsMonitor extends BaseMonitorMBean implements EsMonitorMBean { - private final JmxConnectionFactory jmxConnectionFactory; private final EsClient esClient; - public EsMonitor(JmxConnectionFactory jmxConnectionFactory, EsClient esClient) { - this.jmxConnectionFactory = jmxConnectionFactory; + public EsMonitor(EsClient esClient) { this.esClient = esClient; } @@ -72,22 +65,13 @@ public class EsMonitor extends BaseMonitorMBean implements EsMonitorMBean { } @Override - public Optional<Map<String, Object>> attributes() { + public Map<String, Object> attributes() { Map<String, Object> attributes = new LinkedHashMap<>(); - - try (JmxConnection connection = jmxConnectionFactory.create(ProcessId.ELASTICSEARCH)) { - if (connection != null) { - EsSettingsMBean mbean = connection.getMBean(EsSettingsMBean.OBJECT_NAME, EsSettingsMBean.class); - attributes.put("Cluster Name", mbean.getClusterName()); - attributes.put("Node Name", mbean.getNodeName()); - attributes.put("HTTP Port", mbean.getHttpPort()); - } - } attributes.put("State", getStateAsEnum()); attributes.put("Indices", indexAttributes()); attributes.put("Number of Nodes", getNumberOfNodes()); attributes.put("Nodes", nodeAttributes()); - return Optional.of(attributes); + return attributes; } private LinkedHashMap<String, LinkedHashMap<String, Object>> indexAttributes() { diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/JmxConnectionFactoryProvider.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/JmxConnectionFactoryProvider.java deleted file mode 100644 index ebc98c1dddf..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/JmxConnectionFactoryProvider.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program 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. - * - * This program 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.server.platform.monitoring; - -import java.io.File; -import org.picocontainer.injectors.ProviderAdapter; -import org.sonar.api.config.Settings; -import org.sonar.process.jmx.JmxConnectionFactory; - -import static com.google.common.base.Preconditions.checkArgument; -import static org.sonar.process.ProcessEntryPoint.PROPERTY_SHARED_PATH; - -public class JmxConnectionFactoryProvider extends ProviderAdapter { - - private JmxConnectionFactory singleton = null; - - public synchronized JmxConnectionFactory provide(Settings settings) { - if (singleton == null) { - singleton = new JmxConnectionFactory(nonNullValueAsFile(settings, PROPERTY_SHARED_PATH)); - } - return singleton; - } - - private static File nonNullValueAsFile(Settings settings, String key) { - String s = settings.getString(key); - checkArgument(s != null, "Property %s is not set", key); - return new File(s); - } -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/JvmPropsMonitor.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/JvmPropsMonitor.java index 26f642b7e6b..d49a1e172d5 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/JvmPropsMonitor.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/JvmPropsMonitor.java @@ -19,7 +19,6 @@ */ package org.sonar.server.platform.monitoring; -import com.google.common.base.Optional; import java.util.Map; import java.util.Objects; import java.util.TreeMap; @@ -31,11 +30,11 @@ public class JvmPropsMonitor implements Monitor { } @Override - public Optional<Map<String, Object>> attributes() { + public Map<String, Object> attributes() { Map<String, Object> sortedProps = new TreeMap<>(); for (Map.Entry<Object, Object> systemProp : System.getProperties().entrySet()) { sortedProps.put(Objects.toString(systemProp.getKey()), Objects.toString(systemProp.getValue())); } - return Optional.of(sortedProps); + return sortedProps; } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/Monitor.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/Monitor.java index d4d6808865a..a268b43e5fe 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/Monitor.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/Monitor.java @@ -19,9 +19,7 @@ */ package org.sonar.server.platform.monitoring; -import com.google.common.base.Optional; import java.util.Map; -import org.sonar.api.ce.ComputeEngineSide; import org.sonar.api.server.ServerSide; import org.sonar.server.platform.ws.InfoAction; @@ -29,7 +27,6 @@ import org.sonar.server.platform.ws.InfoAction; * Any component that is involved in the information returned by the web service api/system/info */ @ServerSide -@ComputeEngineSide public interface Monitor { /** * Name of section in System Info page @@ -39,9 +36,6 @@ public interface Monitor { /** * Type of attribute values must be supported by {@link org.sonar.api.utils.text.JsonWriter#valueObject(Object)} * because of JSON export by {@link InfoAction}. - * - * @return map of attributes, or Optional.absent() if the monitored component is not up. In the latter case - * nothing is returned in the web service api/system/info. */ - Optional<Map<String, Object>> attributes(); + Map<String, Object> attributes(); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/PluginsMonitor.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/PluginsMonitor.java index 6edb3cef096..afed7b16f48 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/PluginsMonitor.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/PluginsMonitor.java @@ -19,7 +19,6 @@ */ package org.sonar.server.platform.monitoring; -import com.google.common.base.Optional; import java.util.LinkedHashMap; import java.util.Map; import org.sonar.core.platform.PluginInfo; @@ -42,7 +41,7 @@ public class PluginsMonitor implements Monitor { } @Override - public Optional<Map<String, Object>> attributes() { + public Map<String, Object> attributes() { Map<String, Object> attributes = new LinkedHashMap<>(); for (PluginInfo plugin : repository.getPluginInfos()) { LinkedHashMap<String, Object> pluginAttributes = new LinkedHashMap<>(); @@ -53,6 +52,6 @@ public class PluginsMonitor implements Monitor { } attributes.put(plugin.getKey(), pluginAttributes); } - return Optional.of(attributes); + return attributes; } } diff --git a/server/sonar-process/src/main/java/org/sonar/process/jmx/JmxConnectionFactory.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/ProcessSystemInfoClient.java index 29383cc211e..3968a2792a0 100644 --- a/server/sonar-process/src/main/java/org/sonar/process/jmx/JmxConnectionFactory.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/ProcessSystemInfoClient.java @@ -17,51 +17,45 @@ * 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.jmx; +package org.sonar.server.platform.monitoring; +import com.google.common.base.Optional; import java.io.File; -import javax.annotation.CheckForNull; -import javax.annotation.concurrent.Immutable; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXConnectorFactory; -import javax.management.remote.JMXServiceURL; +import java.net.URI; +import org.apache.commons.io.IOUtils; +import org.sonar.api.config.Settings; import org.sonar.process.DefaultProcessCommands; -import org.sonar.process.ProcessEntryPoint; import org.sonar.process.ProcessId; -import org.sonar.process.Props; +import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo; + +import static org.sonar.process.ProcessEntryPoint.PROPERTY_SHARED_PATH; /** - * Connects to JMX of other JVM processes + * Connects to the System Info HTTP server of another JVM process. */ -@Immutable -public class JmxConnectionFactory { - private final File ipcSharedDir; +public class ProcessSystemInfoClient { - public JmxConnectionFactory(File ipcSharedDir) { - this.ipcSharedDir = ipcSharedDir; - } + private final File ipcSharedDir; - public JmxConnectionFactory(Props props) { - this.ipcSharedDir = props.nonNullValueAsFile(ProcessEntryPoint.PROPERTY_SHARED_PATH); + public ProcessSystemInfoClient(Settings props) { + this.ipcSharedDir = new File(props.getString(PROPERTY_SHARED_PATH)); } - @CheckForNull - public JmxConnection create(ProcessId processId) { + /** + * Connects to the specified JVM process and requests system information. + * @return the system info, or absent if the process is not up or if its HTTP URL + * is not registered into IPC. + */ + public Optional<ProtobufSystemInfo.SystemInfo> connect(ProcessId processId) { try (DefaultProcessCommands commands = DefaultProcessCommands.secondary(ipcSharedDir, processId.getIpcIndex())) { if (commands.isUp()) { - String url = commands.getJmxUrl(); - JMXConnector jmxConnector = JMXConnectorFactory.newJMXConnector(new JMXServiceURL(url), null); - jmxConnector.connect(); - return new JmxConnection(jmxConnector); + String url = commands.getSystemInfoUrl(); + byte[] protobuf = IOUtils.toByteArray(new URI(url)); + return Optional.of(ProtobufSystemInfo.SystemInfo.parseFrom(protobuf)); } - return null; + return Optional.absent(); } catch (Exception e) { - throw new IllegalStateException("Can not connect to process " + processId, e); + throw new IllegalStateException("Can not get system info of process " + processId, e); } } - - // visible for testing - File getIpcSharedDir() { - return ipcSharedDir; - } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/SonarQubeMonitor.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/SonarQubeMonitor.java index 7d6c3bd00ba..ab513629d81 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/SonarQubeMonitor.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/SonarQubeMonitor.java @@ -19,7 +19,6 @@ */ package org.sonar.server.platform.monitoring; -import com.google.common.base.Optional; import java.io.File; import java.util.LinkedHashMap; import java.util.Map; @@ -97,7 +96,7 @@ public class SonarQubeMonitor extends BaseMonitorMBean implements SonarQubeMonit } @Override - public Optional<Map<String, Object>> attributes() { + public Map<String, Object> attributes() { Map<String, Object> attributes = new LinkedHashMap<>(); attributes.put("Server ID", getServerId()); attributes.put("Version", getVersion()); @@ -111,7 +110,7 @@ public class SonarQubeMonitor extends BaseMonitorMBean implements SonarQubeMonit attributes.put("Temp Dir", settings.getString(ProcessProperties.PATH_TEMP)); attributes.put("Logs Dir", settings.getString(ProcessProperties.PATH_LOGS)); attributes.put("Logs Level", getLogLevel()); - return Optional.of(attributes); + return attributes; } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/SystemMonitor.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/SystemMonitor.java index d7d279d94c9..b5788d847ae 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/SystemMonitor.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/SystemMonitor.java @@ -19,7 +19,6 @@ */ package org.sonar.server.platform.monitoring; -import com.google.common.base.Optional; import java.lang.management.ClassLoadingMXBean; import java.lang.management.ManagementFactory; import java.lang.management.MemoryMXBean; @@ -53,7 +52,7 @@ public class SystemMonitor implements Monitor { } @Override - public Optional<Map<String, Object>> attributes() { + public Map<String, Object> attributes() { Map<String, Object> attributes = new LinkedHashMap<>(); attributes.put("System Date", formatDateTime(new Date(system.now()))); attributes.put("Start Time", formatDateTime(new Date(runtimeMXBean().getStartTime()))); @@ -76,7 +75,7 @@ public class SystemMonitor implements Monitor { attributes.put("Threads", threadMXBean().getThreadCount()); attributes.put("Threads Peak", threadMXBean().getPeakThreadCount()); attributes.put("Daemon Thread", threadMXBean().getDaemonThreadCount()); - return Optional.of(attributes); + return attributes; } private static RuntimeMXBean runtimeMXBean() { diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java index 7d4549f10a8..b617008eb74 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java @@ -149,15 +149,11 @@ import org.sonar.server.permission.ws.PermissionsWsModule; import org.sonar.server.platform.BackendCleanup; import org.sonar.server.platform.ServerLogging; import org.sonar.server.platform.SettingsChangeNotifier; -import org.sonar.server.platform.monitoring.CeDatabaseMonitor; -import org.sonar.server.platform.monitoring.CeStateMonitor; -import org.sonar.server.platform.monitoring.CeTasksMonitor; import org.sonar.server.platform.monitoring.DatabaseMonitor; import org.sonar.server.platform.monitoring.EsMonitor; -import org.sonar.server.platform.monitoring.EsStateMonitor; -import org.sonar.server.platform.monitoring.JmxConnectionFactoryProvider; import org.sonar.server.platform.monitoring.JvmPropsMonitor; import org.sonar.server.platform.monitoring.PluginsMonitor; +import org.sonar.server.platform.monitoring.ProcessSystemInfoClient; import org.sonar.server.platform.monitoring.SonarQubeMonitor; import org.sonar.server.platform.monitoring.SystemMonitor; import org.sonar.server.platform.ws.ChangeLogLevelAction; @@ -635,7 +631,7 @@ public class PlatformLevel4 extends PlatformLevel { TypeValidationModule.class, // System - new JmxConnectionFactoryProvider(), + ProcessSystemInfoClient.class, ServerLogging.class, RestartAction.class, InfoAction.class, @@ -648,10 +644,6 @@ public class PlatformLevel4 extends PlatformLevel { PluginsMonitor.class, JvmPropsMonitor.class, DatabaseMonitor.class, - EsStateMonitor.class, - CeStateMonitor.class, - CeTasksMonitor.class, - CeDatabaseMonitor.class, MigrateDbAction.class, LogsAction.class, ChangeLogLevelAction.class, diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/InfoAction.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/InfoAction.java index 3512a9eb632..7f68912e96d 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/InfoAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/InfoAction.java @@ -26,7 +26,10 @@ import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; import org.sonar.api.utils.text.JsonWriter; import org.sonar.core.permission.GlobalPermissions; +import org.sonar.process.ProcessId; +import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo; import org.sonar.server.platform.monitoring.Monitor; +import org.sonar.server.platform.monitoring.ProcessSystemInfoClient; import org.sonar.server.user.UserSession; /** @@ -34,11 +37,13 @@ import org.sonar.server.user.UserSession; */ public class InfoAction implements SystemWsAction { - private final Monitor[] monitors; private final UserSession userSession; + private final ProcessSystemInfoClient processSystemInfoClient; + private final Monitor[] monitors; - public InfoAction(UserSession userSession, Monitor... monitors) { + public InfoAction(UserSession userSession, ProcessSystemInfoClient processSystemInfoClient, Monitor... monitors) { this.userSession = userSession; + this.processSystemInfoClient = processSystemInfoClient; this.monitors = monitors; } @@ -64,12 +69,38 @@ public class InfoAction implements SystemWsAction { private void writeJson(JsonWriter json) { json.beginObject(); for (Monitor monitor : monitors) { - Optional<Map<String, Object>> attributes = monitor.attributes(); - if (attributes.isPresent()) { - json.name(monitor.name()); + Map<String, Object> attributes = monitor.attributes(); + json.name(monitor.name()); + json.beginObject(); + for (Map.Entry<String, Object> attribute : attributes.entrySet()) { + json.name(attribute.getKey()).valueObject(attribute.getValue()); + } + json.endObject(); + } + Optional<ProtobufSystemInfo.SystemInfo> ceSysInfo = processSystemInfoClient.connect(ProcessId.COMPUTE_ENGINE); + if (ceSysInfo.isPresent()) { + for (ProtobufSystemInfo.Section section : ceSysInfo.get().getSectionsList()) { + json.name(section.getName()); json.beginObject(); - for (Map.Entry<String, Object> attribute : attributes.get().entrySet()) { - json.name(attribute.getKey()).valueObject(attribute.getValue()); + for (ProtobufSystemInfo.Attribute attribute : section.getAttributesList()) { + switch (attribute.getValueCase()) { + case BOOLEAN_VALUE: + json.name(attribute.getKey()).valueObject(attribute.getBooleanValue()); + break; + case LONG_VALUE: + json.name(attribute.getKey()).valueObject(attribute.getLongValue()); + break; + case DOUBLE_VALUE: + json.name(attribute.getKey()).valueObject(attribute.getDoubleValue()); + break; + case STRING_VALUE: + json.name(attribute.getKey()).valueObject(attribute.getStringValue()); + break; + case VALUE_NOT_SET: + break; + default: + throw new IllegalArgumentException("Unsupported type: " + attribute.getValueCase()); + } } json.endObject(); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/monitoring/CeDatabaseMBeanImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/monitoring/CeDatabaseMBeanImplTest.java new file mode 100644 index 00000000000..a81a7d8d69e --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/monitoring/CeDatabaseMBeanImplTest.java @@ -0,0 +1,70 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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.server.computation.monitoring; + +import java.lang.management.ManagementFactory; +import javax.annotation.CheckForNull; +import javax.management.InstanceNotFoundException; +import javax.management.ObjectInstance; +import javax.management.ObjectName; +import org.junit.Rule; +import org.junit.Test; +import org.sonar.api.utils.System2; +import org.sonar.db.DbTester; +import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo; + +import static org.assertj.core.api.Assertions.assertThat; + +public class CeDatabaseMBeanImplTest { + + @Rule + public DbTester dbTester = DbTester.create(System2.INSTANCE); + + CeDatabaseMBeanImpl underTest = new CeDatabaseMBeanImpl(dbTester.getDbClient()); + + @Test + public void register_and_unregister() throws Exception { + assertThat(getMBean()).isNull(); + + underTest.start(); + assertThat(getMBean()).isNotNull(); + + underTest.stop(); + assertThat(getMBean()).isNull(); + } + + @Test + public void export_system_info() { + ProtobufSystemInfo.Section section = underTest.toProtobuf(); + assertThat(section.getName()).isEqualTo("Compute Engine Database Connection"); + assertThat(section.getAttributesCount()).isEqualTo(9); + assertThat(section.getAttributes(0).getKey()).isEqualTo("Pool Initial Size"); + assertThat(section.getAttributes(0).getLongValue()).isGreaterThanOrEqualTo(0); + } + + @CheckForNull + private ObjectInstance getMBean() throws Exception { + try { + return ManagementFactory.getPlatformMBeanServer().getObjectInstance(new ObjectName(CeDatabaseMBean.OBJECT_NAME)); + } catch (InstanceNotFoundException e) { + return null; + } + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/monitoring/CeTasksMBeanImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/monitoring/CeTasksMBeanImplTest.java index 9b5bc7becc8..a891f1d5569 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/monitoring/CeTasksMBeanImplTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/monitoring/CeTasksMBeanImplTest.java @@ -26,7 +26,7 @@ import javax.management.ObjectInstance; import javax.management.ObjectName; import org.junit.Test; import org.sonar.ce.monitoring.CEQueueStatus; -import org.sonar.process.jmx.CeTasksMBean; +import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo; import org.sonar.server.computation.configuration.CeConfiguration; import static org.assertj.core.api.Assertions.assertThat; @@ -66,6 +66,13 @@ public class CeTasksMBeanImplTest { assertThat(underTest.getWorkerCount()).isEqualTo(WORKER_COUNT); } + @Test + public void export_system_info() { + ProtobufSystemInfo.Section section = underTest.toProtobuf(); + assertThat(section.getName()).isEqualTo("Compute Engine Tasks"); + assertThat(section.getAttributesCount()).isEqualTo(6); + } + /** * Dumb implementation of CEQueueStatus which returns constant values for get methods and throws UnsupportedOperationException * for other methods. diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/CeDatabaseMonitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/CeDatabaseMonitorTest.java deleted file mode 100644 index 9758471ffcb..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/CeDatabaseMonitorTest.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program 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. - * - * This program 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.server.platform.monitoring; - -import com.google.common.base.Optional; -import java.util.Map; -import org.junit.Test; -import org.mockito.Mockito; -import org.sonar.process.ProcessId; -import org.sonar.process.jmx.CeDatabaseMBean; -import org.sonar.process.jmx.JmxConnectionFactory; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class CeDatabaseMonitorTest { - - JmxConnectionFactory jmxConnectionFactory = mock(JmxConnectionFactory.class, Mockito.RETURNS_DEEP_STUBS); - CeDatabaseMonitor underTest = new CeDatabaseMonitor(jmxConnectionFactory); - - @Test - public void testName() { - assertThat(underTest.name()).isNotEmpty(); - } - - @Test - public void attributes() { - CeDatabaseMBean mbean = mock(CeDatabaseMBean.class, Mockito.RETURNS_DEFAULTS); - - when(jmxConnectionFactory.create(ProcessId.COMPUTE_ENGINE).getMBean(CeDatabaseMBean.OBJECT_NAME, CeDatabaseMBean.class)) - .thenReturn(mbean); - Optional<Map<String, Object>> attributes = underTest.attributes(); - assertThat(attributes.get()).containsKeys("Pool Initial Size", "Pool Active Connections"); - assertThat(attributes.get()).hasSize(9); - } - - @Test - public void absent_attributes_if_CE_is_down() { - when(jmxConnectionFactory.create(ProcessId.COMPUTE_ENGINE)).thenReturn(null); - Optional<Map<String, Object>> attributes = underTest.attributes(); - assertThat(attributes.isPresent()).isFalse(); - } -} diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/CeStateMonitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/CeStateMonitorTest.java deleted file mode 100644 index 1154bcff55c..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/CeStateMonitorTest.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program 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. - * - * This program 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.server.platform.monitoring; - -import com.google.common.base.Optional; -import com.google.common.collect.ImmutableSortedMap; -import java.util.Map; -import org.assertj.core.data.MapEntry; -import org.junit.Test; -import org.mockito.Mockito; -import org.sonar.process.ProcessId; -import org.sonar.process.jmx.JmxConnectionFactory; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class CeStateMonitorTest { - - JmxConnectionFactory jmxConnectionFactory = mock(JmxConnectionFactory.class, Mockito.RETURNS_DEEP_STUBS); - CeStateMonitor underTest = new CeStateMonitor(jmxConnectionFactory); - - @Test - public void testName() { - assertThat(underTest.name()).isNotEmpty(); - } - - @Test - public void testAttributes() { - when(jmxConnectionFactory.create(ProcessId.COMPUTE_ENGINE).getSystemState()).thenReturn(ImmutableSortedMap.<String, Object>of( - "foo", "foo_val", "bar", "bar_val")); - Optional<Map<String, Object>> attributes = underTest.attributes(); - assertThat(attributes.get()).containsExactly( - MapEntry.entry("bar", "bar_val"), - MapEntry.entry("foo", "foo_val")); - } - - @Test - public void absent_attributes_if_CE_is_down() { - when(jmxConnectionFactory.create(ProcessId.COMPUTE_ENGINE)).thenReturn(null); - Optional<Map<String, Object>> attributes = underTest.attributes(); - assertThat(attributes.isPresent()).isFalse(); - } -} diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/CeTasksMonitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/CeTasksMonitorTest.java deleted file mode 100644 index c9d7626aa5a..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/CeTasksMonitorTest.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program 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. - * - * This program 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.server.platform.monitoring; - -import com.google.common.base.Optional; -import java.util.Map; -import org.junit.Test; -import org.mockito.Mockito; -import org.sonar.process.ProcessId; -import org.sonar.process.jmx.CeTasksMBean; -import org.sonar.process.jmx.JmxConnectionFactory; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class CeTasksMonitorTest { - - JmxConnectionFactory jmxConnectionFactory = mock(JmxConnectionFactory.class, Mockito.RETURNS_DEEP_STUBS); - CeTasksMonitor underTest = new CeTasksMonitor(jmxConnectionFactory); - - @Test - public void testName() { - assertThat(underTest.name()).isNotEmpty(); - } - - @Test - public void testAttributes() { - CeTasksMBean mbean = mock(CeTasksMBean.class, Mockito.RETURNS_DEFAULTS); - - when(jmxConnectionFactory.create(ProcessId.COMPUTE_ENGINE).getMBean(CeTasksMBean.OBJECT_NAME, CeTasksMBean.class)) - .thenReturn(mbean); - Optional<Map<String, Object>> attributes = underTest.attributes(); - assertThat(attributes.get()).containsKeys("Pending"); - assertThat(attributes.get()).hasSize(6); - } - - @Test - public void absent_attributes_if_CE_is_down() { - when(jmxConnectionFactory.create(ProcessId.COMPUTE_ENGINE)).thenReturn(null); - Optional<Map<String, Object>> attributes = underTest.attributes(); - assertThat(attributes.isPresent()).isFalse(); - } -} diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/DatabaseMonitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/DatabaseMonitorTest.java index 5ed384ce7b0..5941af2a2ba 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/DatabaseMonitorTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/DatabaseMonitorTest.java @@ -49,7 +49,7 @@ public class DatabaseMonitorTest { @Test public void db_info() { - Map<String, Object> attributes = underTest.attributes().get(); + Map<String, Object> attributes = underTest.attributes(); assertThat(attributes.get("Database")).isEqualTo("H2"); assertThat(attributes.get("Database Version").toString()).startsWith("1."); assertThat(attributes.get("Username")).isEqualTo("SONAR"); @@ -58,7 +58,7 @@ public class DatabaseMonitorTest { @Test public void pool_info() { - Map<String, Object> attributes = underTest.attributes().get(); + Map<String, Object> attributes = underTest.attributes(); assertThat((int) attributes.get("Pool Max Connections")).isGreaterThan(0); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/EsMonitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/EsMonitorTest.java index 6379c5d0779..47ec8a30311 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/EsMonitorTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/EsMonitorTest.java @@ -21,35 +21,21 @@ package org.sonar.server.platform.monitoring; import java.util.Map; import org.elasticsearch.action.admin.cluster.health.ClusterHealthStatus; -import org.junit.Before; import org.junit.ClassRule; import org.junit.Test; -import org.mockito.Mockito; import org.sonar.api.config.Settings; -import org.sonar.process.ProcessId; -import org.sonar.process.jmx.EsSettingsMBean; -import org.sonar.process.jmx.JmxConnectionFactory; import org.sonar.server.es.EsTester; import org.sonar.server.es.NewIndex; import org.sonar.server.issue.index.IssueIndexDefinition; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; public class EsMonitorTest { @ClassRule public static EsTester esTester = new EsTester().addDefinitions(new IssueIndexDefinition(new Settings())); - JmxConnectionFactory jmxConnectionFactory = mock(JmxConnectionFactory.class, Mockito.RETURNS_DEEP_STUBS); - EsSettingsMBean settingsMBean = mock(EsSettingsMBean.class); - EsMonitor underTest = new EsMonitor(jmxConnectionFactory, esTester.client()); - - @Before - public void setUp() throws Exception { - when(jmxConnectionFactory.create(ProcessId.ELASTICSEARCH).getMBean(EsSettingsMBean.OBJECT_NAME, EsSettingsMBean.class)).thenReturn(settingsMBean); - } + EsMonitor underTest = new EsMonitor(esTester.client()); @Test public void name() { @@ -58,7 +44,7 @@ public class EsMonitorTest { @Test public void cluster_attributes() { - Map<String, Object> attributes = underTest.attributes().get(); + Map<String, Object> attributes = underTest.attributes(); assertThat(underTest.getState()).isEqualTo(ClusterHealthStatus.GREEN.name()); assertThat(attributes.get("State")).isEqualTo(ClusterHealthStatus.GREEN); assertThat(attributes.get("Number of Nodes")).isEqualTo(1); @@ -66,7 +52,7 @@ public class EsMonitorTest { @Test public void node_attributes() { - Map<String, Object> attributes = underTest.attributes().get(); + Map<String, Object> attributes = underTest.attributes(); Map nodesAttributes = (Map) attributes.get("Nodes"); // one node @@ -78,7 +64,7 @@ public class EsMonitorTest { @Test public void index_attributes() { - Map<String, Object> attributes = underTest.attributes().get(); + Map<String, Object> attributes = underTest.attributes(); Map indicesAttributes = (Map) attributes.get("Indices"); // one index "issues" diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/EsStateMonitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/EsStateMonitorTest.java deleted file mode 100644 index 7618fedfbd8..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/EsStateMonitorTest.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program 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. - * - * This program 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.server.platform.monitoring; - -import com.google.common.base.Optional; -import com.google.common.collect.ImmutableSortedMap; -import java.util.Map; -import org.assertj.core.data.MapEntry; -import org.junit.Test; -import org.mockito.Mockito; -import org.sonar.process.ProcessId; -import org.sonar.process.jmx.JmxConnectionFactory; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class EsStateMonitorTest { - JmxConnectionFactory jmxConnectionFactory = mock(JmxConnectionFactory.class, Mockito.RETURNS_DEEP_STUBS); - EsStateMonitor underTest = new EsStateMonitor(jmxConnectionFactory); - - @Test - public void testName() { - assertThat(underTest.name()).isNotEmpty(); - } - - @Test - public void testAttributes() { - when(jmxConnectionFactory.create(ProcessId.ELASTICSEARCH).getSystemState()).thenReturn(ImmutableSortedMap.<String, Object>of( - "foo", "foo_val", "bar", "bar_val")); - Optional<Map<String, Object>> attributes = underTest.attributes(); - assertThat(attributes.get()).containsExactly( - MapEntry.entry("bar", "bar_val"), - MapEntry.entry("foo", "foo_val")); - } - - @Test - public void absent_attributes_if_CE_is_down() { - when(jmxConnectionFactory.create(ProcessId.ELASTICSEARCH)).thenReturn(null); - Optional<Map<String, Object>> attributes = underTest.attributes(); - assertThat(attributes.isPresent()).isFalse(); - } -} diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/FakeMonitor.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/FakeMonitor.java index 879b65f8405..7ef3801ee09 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/FakeMonitor.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/FakeMonitor.java @@ -19,7 +19,6 @@ */ package org.sonar.server.platform.monitoring; -import com.google.common.base.Optional; import java.util.Collections; import java.util.Map; @@ -36,7 +35,7 @@ public class FakeMonitor extends BaseMonitorMBean implements FakeMonitorMBean { } @Override - public Optional<Map<String, Object>> attributes() { - return Optional.of(Collections.<String, Object>emptyMap()); + public Map<String, Object> attributes() { + return Collections.emptyMap(); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/JmxConnectionFactoryProviderTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/JmxConnectionFactoryProviderTest.java deleted file mode 100644 index 03998a76cde..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/JmxConnectionFactoryProviderTest.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program 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. - * - * This program 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.server.platform.monitoring; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.sonar.api.config.Settings; -import org.sonar.process.ProcessEntryPoint; -import org.sonar.process.jmx.JmxConnectionFactory; - -import static org.assertj.core.api.Assertions.assertThat; - -public class JmxConnectionFactoryProviderTest { - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - Settings settings = new Settings(); - JmxConnectionFactoryProvider underTest = new JmxConnectionFactoryProvider(); - - @Test - public void provide_JmxConnector() { - settings.setProperty(ProcessEntryPoint.PROPERTY_SHARED_PATH, "path/"); - JmxConnectionFactory connector = underTest.provide(settings); - - assertThat(connector).isNotNull(); - // cache - assertThat(underTest.provide(settings)).isSameAs(connector); - } - - @Test - public void throw_IAE_if_ipc_shared_path_is_not_set() { - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("Property process.sharedDir is not set"); - - underTest.provide(settings); - } -} diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/JvmPropsMonitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/JvmPropsMonitorTest.java index 0a534035280..0e8d4090f04 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/JvmPropsMonitorTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/JvmPropsMonitorTest.java @@ -19,7 +19,6 @@ */ package org.sonar.server.platform.monitoring; -import com.google.common.base.Optional; import java.util.Map; import org.junit.Test; @@ -36,8 +35,8 @@ public class JvmPropsMonitorTest { @Test public void attributes() { - Optional<Map<String, Object>> attributes = underTest.attributes(); + Map<String, Object> attributes = underTest.attributes(); - assertThat(attributes.get()).containsKeys("java.vm.vendor", "os.name"); + assertThat(attributes).containsKeys("java.vm.vendor", "os.name"); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/PluginsMonitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/PluginsMonitorTest.java index c5c4b1a4f51..e3a5f374163 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/PluginsMonitorTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/PluginsMonitorTest.java @@ -52,7 +52,7 @@ public class PluginsMonitorTest { new PluginInfo("no-version") .setName("No Version"))); - Map<String, Object> attributes = underTest.attributes().get(); + Map<String, Object> attributes = underTest.attributes(); assertThat(attributes).containsKeys("key-1", "key-2"); assertThat((Map) attributes.get("key-1")) diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/ProcessSystemInfoClientTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/ProcessSystemInfoClientTest.java new file mode 100644 index 00000000000..ff3016a7dfc --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/ProcessSystemInfoClientTest.java @@ -0,0 +1,99 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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.server.platform.monitoring; + +import com.google.common.base.Optional; +import com.squareup.okhttp.mockwebserver.MockResponse; +import com.squareup.okhttp.mockwebserver.MockWebServer; +import java.io.File; +import okio.Buffer; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.rules.TemporaryFolder; +import org.sonar.api.config.Settings; +import org.sonar.process.DefaultProcessCommands; +import org.sonar.process.ProcessEntryPoint; +import org.sonar.process.ProcessId; +import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo; + +import static java.lang.String.format; +import static org.assertj.core.api.Assertions.assertThat; + +public class ProcessSystemInfoClientTest { + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Rule + public MockWebServer server = new MockWebServer(); + + File ipcSharedDir; + ProcessSystemInfoClient underTest; + + @Before + public void setUp() throws Exception { + ipcSharedDir = temp.newFolder(); + Settings settings = new Settings(); + settings.setProperty(ProcessEntryPoint.PROPERTY_SHARED_PATH, ipcSharedDir.getAbsolutePath()); + underTest = new ProcessSystemInfoClient(settings); + } + + @Test + public void connect_returns_absent_if_process_is_down() throws Exception { + Optional<ProtobufSystemInfo.SystemInfo> info = underTest.connect(ProcessId.COMPUTE_ENGINE); + + assertThat(info.isPresent()).isFalse(); + } + + @Test + public void get_information_if_process_is_up() throws Exception { + Buffer response = new Buffer(); + response.read(ProtobufSystemInfo.Section.newBuilder().build().toByteArray()); + server.enqueue(new MockResponse().setBody(response)); + + // initialize registration of process + try (DefaultProcessCommands processCommands = DefaultProcessCommands.secondary(ipcSharedDir, ProcessId.COMPUTE_ENGINE.getIpcIndex())) { + processCommands.setUp(); + processCommands.setSystemInfoUrl(format("http://%s:%d", server.getHostName(), server.getPort())); + } + + Optional<ProtobufSystemInfo.SystemInfo> info = underTest.connect(ProcessId.COMPUTE_ENGINE); + assertThat(info.get().getSectionsCount()).isEqualTo(0); + } + + @Test + public void throws_ISE_if_http_error() throws Exception { + server.enqueue(new MockResponse().setResponseCode(500)); + + // initialize registration of process + try (DefaultProcessCommands processCommands = DefaultProcessCommands.secondary(ipcSharedDir, ProcessId.COMPUTE_ENGINE.getIpcIndex())) { + processCommands.setUp(); + processCommands.setSystemInfoUrl(format("http://%s:%d", server.getHostName(), server.getPort())); + } + + expectedException.expect(IllegalStateException.class); + expectedException.expectMessage("Can not get system info of process " + ProcessId.COMPUTE_ENGINE); + underTest.connect(ProcessId.COMPUTE_ENGINE); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/SonarQubeMonitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/SonarQubeMonitorTest.java index 70155ae82f9..a522c1df767 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/SonarQubeMonitorTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/SonarQubeMonitorTest.java @@ -19,7 +19,6 @@ */ package org.sonar.server.platform.monitoring; -import com.google.common.base.Optional; import java.io.File; import java.util.Map; import org.apache.commons.io.FileUtils; @@ -62,8 +61,8 @@ public class SonarQubeMonitorTest { when(server.getStartedAt()).thenReturn(DateUtils.parseDate("2015-01-01")); SonarQubeMonitor monitor = new SonarQubeMonitor(settings, new SecurityRealmFactory(settings), server, serverLogging); - Optional<Map<String, Object>> attributes = monitor.attributes(); - assertThat(attributes.get()).containsKeys("Server ID", "Version"); + Map<String, Object> attributes = monitor.attributes(); + assertThat(attributes).containsKeys("Server ID", "Version"); } @Test @@ -74,8 +73,8 @@ public class SonarQubeMonitorTest { when(server.getRootDir()).thenReturn(rootDir); SonarQubeMonitor monitor = new SonarQubeMonitor(settings, new SecurityRealmFactory(settings), server, serverLogging); - Optional<Map<String, Object>> attributes = monitor.attributes(); - assertThat(attributes.get()).containsEntry("Official Distribution", Boolean.TRUE); + Map<String, Object> attributes = monitor.attributes(); + assertThat(attributes).containsEntry("Official Distribution", Boolean.TRUE); } @Test @@ -85,15 +84,15 @@ public class SonarQubeMonitorTest { when(server.getRootDir()).thenReturn(rootDir); SonarQubeMonitor monitor = new SonarQubeMonitor(settings, new SecurityRealmFactory(settings), server, serverLogging); - Optional<Map<String, Object>> attributes = monitor.attributes(); - assertThat(attributes.get()).containsEntry("Official Distribution", Boolean.FALSE); + Map<String, Object> attributes = monitor.attributes(); + assertThat(attributes).containsEntry("Official Distribution", Boolean.FALSE); } @Test public void get_log_level() throws Exception { SonarQubeMonitor monitor = new SonarQubeMonitor(settings, new SecurityRealmFactory(settings), server, serverLogging); - Optional<Map<String, Object>> attributes = monitor.attributes(); - assertThat(attributes.get()).containsEntry("Logs Level", "DEBUG"); + Map<String, Object> attributes = monitor.attributes(); + assertThat(attributes).containsEntry("Logs Level", "DEBUG"); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/SystemMonitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/SystemMonitorTest.java index 07510691802..e8290638a65 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/SystemMonitorTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/SystemMonitorTest.java @@ -35,7 +35,7 @@ public class SystemMonitorTest { @Test public void system_properties() { - Map<String, Object> attributes = underTest.attributes().get(); + Map<String, Object> attributes = underTest.attributes(); assertThat(attributes).containsKeys("System Date", "Processors"); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/ws/InfoActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/InfoActionTest.java index 41a0a6788b9..c4a61be4f80 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/ws/InfoActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/InfoActionTest.java @@ -19,17 +19,18 @@ */ package org.sonar.server.platform.ws; -import com.google.common.base.Optional; import java.util.LinkedHashMap; import java.util.Map; import org.junit.Rule; import org.junit.Test; +import org.mockito.Mockito; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.internal.SimpleGetRequest; import org.sonar.core.permission.GlobalPermissions; import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.platform.monitoring.Monitor; +import org.sonar.server.platform.monitoring.ProcessSystemInfoClient; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.ws.WsTester; @@ -40,12 +41,12 @@ import static org.mockito.Mockito.when; public class InfoActionTest { @Rule public UserSessionRule userSessionRule = UserSessionRule.standalone().login("login") - .setName("name"); + .setName("name"); Monitor monitor1 = mock(Monitor.class); Monitor monitor2 = mock(Monitor.class); - Monitor monitor3 = mock(Monitor.class); - InfoAction underTest = new InfoAction(userSessionRule, monitor1, monitor2, monitor3); + ProcessSystemInfoClient processSystemInfoClient = mock(ProcessSystemInfoClient.class, Mockito.RETURNS_MOCKS); + InfoAction underTest = new InfoAction(userSessionRule, processSystemInfoClient, monitor1, monitor2); @Test(expected = ForbiddenException.class) public void should_fail_when_does_not_have_admin_right() { @@ -64,11 +65,9 @@ public class InfoActionTest { attributes2.put("one", 1); attributes2.put("two", 2); when(monitor1.name()).thenReturn("Monitor One"); - when(monitor1.attributes()).thenReturn(Optional.of(attributes1)); + when(monitor1.attributes()).thenReturn(attributes1); when(monitor2.name()).thenReturn("Monitor Two"); - when(monitor2.attributes()).thenReturn(Optional.of(attributes2)); - when(monitor3.name()).thenReturn("Monitor Three"); - when(monitor3.attributes()).thenReturn(Optional.<Map<String, Object>>absent()); + when(monitor2.attributes()).thenReturn(attributes2); WsTester.TestResponse response = new WsTester.TestResponse(); underTest.handle(new SimpleGetRequest(), response); diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/ws/SystemWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/SystemWsTest.java index 773e6d5b0a5..adda7539e6b 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/ws/SystemWsTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/SystemWsTest.java @@ -24,6 +24,7 @@ import org.sonar.api.config.Settings; import org.sonar.api.server.ws.WebService; import org.sonar.server.app.ProcessCommandWrapper; import org.sonar.server.platform.Platform; +import org.sonar.server.platform.monitoring.ProcessSystemInfoClient; import org.sonar.server.tester.AnonymousMockUserSession; import org.sonar.server.user.UserSession; @@ -32,10 +33,12 @@ import static org.mockito.Mockito.mock; public class SystemWsTest { + ProcessSystemInfoClient processSystemInfoClient = mock(ProcessSystemInfoClient.class); + @Test public void define() { RestartAction action1 = new RestartAction(mock(UserSession.class), mock(Settings.class), mock(Platform.class), mock(ProcessCommandWrapper.class)); - InfoAction action2 = new InfoAction(new AnonymousMockUserSession()); + InfoAction action2 = new InfoAction(new AnonymousMockUserSession(), processSystemInfoClient); SystemWs ws = new SystemWs(action1, action2); WebService.Context context = new WebService.Context(); diff --git a/sonar-application/assembly.xml b/sonar-application/assembly.xml index 069bd23add4..b04e3a21437 100644 --- a/sonar-application/assembly.xml +++ b/sonar-application/assembly.xml @@ -71,8 +71,8 @@ <dependencySet> <outputDirectory>lib/ce</outputDirectory> <useProjectArtifact>false</useProjectArtifact> - <useTransitiveDependencies>false</useTransitiveDependencies> - <useTransitiveFiltering>false</useTransitiveFiltering> + <useTransitiveDependencies>true</useTransitiveDependencies> + <useTransitiveFiltering>true</useTransitiveFiltering> <includes> <include>org.sonarsource.sonarqube:sonar-ce</include> </includes> diff --git a/tests/upgrade/projects/struts-1.3.9-diet/core/src/main/resources/org/apache/struts/resources/web-app_2_3.dtd b/tests/upgrade/projects/struts-1.3.9-diet/core/src/main/resources/org/apache/struts/resources/web-app_2_3.dtd index b110d76de39..ba39dc9135c 100644 --- a/tests/upgrade/projects/struts-1.3.9-diet/core/src/main/resources/org/apache/struts/resources/web-app_2_3.dtd +++ b/tests/upgrade/projects/struts-1.3.9-diet/core/src/main/resources/org/apache/struts/resources/web-app_2_3.dtd @@ -71,989 +71,989 @@ TOUTE GARANTIE IMPLICITE RELATIVE A LA QUALITE MARCHANDE, A L'APTITUDE A UNE UTILISATION PARTICULIERE OU A L'ABSENCE DE CONTREFACON. --> -<!-- -This is the XML DTD for the Servlet 2.3 deployment descriptor. -All Servlet 2.3 deployment descriptors must include a DOCTYPE -of the following form: - - <!DOCTYPE web-app PUBLIC - "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" - "http://java.sun.com/dtd/web-app_2_3.dtd"> - ---> - -<!-- -The following conventions apply to all J2EE deployment descriptor -elements unless indicated otherwise. - -- In elements that contain PCDATA, leading and trailing whitespace - in the data may be ignored. - -- In elements whose value is an "enumerated type", the value is - case sensitive. - -- In elements that specify a pathname to a file within the same - JAR file, relative filenames (i.e., those not starting with "/") - are considered relative to the root of the JAR file's namespace. - Absolute filenames (i.e., those starting with "/") also specify - names in the root of the JAR file's namespace. In general, relative - names are preferred. The exception is .war files where absolute - names are preferred for consistency with the servlet API. ---> - - -<!-- -The web-app element is the root of the deployment descriptor for -a web application. ---> -<!ELEMENT web-app (icon?, display-name?, description?, distributable?, -context-param*, filter*, filter-mapping*, listener*, servlet*, -servlet-mapping*, session-config?, mime-mapping*, welcome-file-list?, -error-page*, taglib*, resource-env-ref*, resource-ref*, security-constraint*, -login-config?, security-role*, env-entry*, ejb-ref*, ejb-local-ref*)> - -<!-- -The auth-constraint element indicates the user roles that should -be permitted access to this resource collection. The role-name -used here must either correspond to the role-name of one of the -security-role elements defined for this web application, or be -the specially reserved role-name "*" that is a compact syntax for -indicating all roles in the web application. If both "*" and -rolenames appear, the container interprets this as all roles. -If no roles are defined, no user is allowed access to the portion of -the web application described by the containing security-constraint. -The container matches role names case sensitively when determining -access. - - -Used in: security-constraint ---> -<!ELEMENT auth-constraint (description?, role-name*)> - -<!-- -The auth-method element is used to configure the authentication -mechanism for the web application. As a prerequisite to gaining access to any web resources which are protected by an authorization -constraint, a user must have authenticated using the configured -mechanism. Legal values for this element are "BASIC", "DIGEST", -"FORM", or "CLIENT-CERT". - -Used in: login-config ---> -<!ELEMENT auth-method (#PCDATA)> - -<!-- -The context-param element contains the declaration of a web -application's servlet context initialization parameters. - -Used in: web-app ---> -<!ELEMENT context-param (param-name, param-value, description?)> - -<!-- -The description element is used to provide text describing the parent -element. The description element should include any information that -the web application war file producer wants to provide to the consumer of -the web application war file (i.e., to the Deployer). Typically, the tools -used by the web application war file consumer will display the description -when processing the parent element that contains the description. - -Used in: auth-constraint, context-param, ejb-local-ref, ejb-ref, -env-entry, filter, init-param, resource-env-ref, resource-ref, run-as, -security-role, security-role-ref, servlet, user-data-constraint, -web-app, web-resource-collection ---> -<!ELEMENT description (#PCDATA)> - -<!-- -The display-name element contains a short name that is intended to be -displayed by tools. The display name need not be unique. - -Used in: filter, security-constraint, servlet, web-app - -Example: - -<display-name>Employee Self Service</display-name> ---> -<!ELEMENT display-name (#PCDATA)> - -<!-- -The distributable element, by its presence in a web application -deployment descriptor, indicates that this web application is -programmed appropriately to be deployed into a distributed servlet -container - -Used in: web-app ---> -<!ELEMENT distributable EMPTY> - -<!-- -The ejb-link element is used in the ejb-ref or ejb-local-ref -elements to specify that an EJB reference is linked to an -enterprise bean. - -The name in the ejb-link element is composed of a -path name specifying the ejb-jar containing the referenced enterprise -bean with the ejb-name of the target bean appended and separated from -the path name by "#". The path name is relative to the war file -containing the web application that is referencing the enterprise bean. -This allows multiple enterprise beans with the same ejb-name to be -uniquely identified. - -Used in: ejb-local-ref, ejb-ref - -Examples: - - <ejb-link>EmployeeRecord</ejb-link> - - <ejb-link>../products/product.jar#ProductEJB</ejb-link> - ---> -<!ELEMENT ejb-link (#PCDATA)> - -<!-- -The ejb-local-ref element is used for the declaration of a reference to -an enterprise bean's local home. The declaration consists of: - - - an optional description - - the EJB reference name used in the code of the web application - that's referencing the enterprise bean - - the expected type of the referenced enterprise bean - - the expected local home and local interfaces of the referenced - enterprise bean - - optional ejb-link information, used to specify the referenced - enterprise bean - -Used in: web-app ---> -<!ELEMENT ejb-local-ref (description?, ejb-ref-name, ejb-ref-type, + <!-- + This is the XML DTD for the Servlet 2.3 deployment descriptor. + All Servlet 2.3 deployment descriptors must include a DOCTYPE + of the following form: + + <!DOCTYPE web-app PUBLIC + "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" + "http://java.sun.com/dtd/web-app_2_3.dtd"> + + --> + + <!-- + The following conventions apply to all J2EE deployment descriptor + elements unless indicated otherwise. + + - In elements that contain PCDATA, leading and trailing whitespace + in the data may be ignored. + + - In elements whose value is an "enumerated type", the value is + case sensitive. + + - In elements that specify a pathname to a file within the same + JAR file, relative filenames (i.e., those not starting with "/") + are considered relative to the root of the JAR file's namespace. + Absolute filenames (i.e., those starting with "/") also specify + names in the root of the JAR file's namespace. In general, relative + names are preferred. The exception is .war files where absolute + names are preferred for consistency with the servlet API. + --> + + + <!-- + The web-app element is the root of the deployment descriptor for + a web application. + --> + <!ELEMENT web-app (icon?, display-name?, description?, distributable?, + context-param*, filter*, filter-mapping*, listener*, servlet*, + servlet-mapping*, session-config?, mime-mapping*, welcome-file-list?, + error-page*, taglib*, resource-env-ref*, resource-ref*, security-constraint*, + login-config?, security-role*, env-entry*, ejb-ref*, ejb-local-ref*)> + + <!-- + The auth-constraint element indicates the user roles that should + be permitted access to this resource collection. The role-name + used here must either correspond to the role-name of one of the + security-role elements defined for this web application, or be + the specially reserved role-name "*" that is a compact syntax for + indicating all roles in the web application. If both "*" and + rolenames appear, the container interprets this as all roles. + If no roles are defined, no user is allowed access to the portion of + the web application described by the containing security-constraint. + The container matches role names case sensitively when determining + access. + + + Used in: security-constraint + --> + <!ELEMENT auth-constraint (description?, role-name*)> + + <!-- + The auth-method element is used to configure the authentication + mechanism for the web application. As a prerequisite to gaining access to any web resources which are protected by an authorization + constraint, a user must have authenticated using the configured + mechanism. Legal values for this element are "BASIC", "DIGEST", + "FORM", or "CLIENT-CERT". + + Used in: login-config + --> + <!ELEMENT auth-method (#PCDATA)> + + <!-- + The context-param element contains the declaration of a web + application's servlet context initialization parameters. + + Used in: web-app + --> + <!ELEMENT context-param (param-name, param-value, description?)> + + <!-- + The description element is used to provide text describing the parent + element. The description element should include any information that + the web application war file producer wants to provide to the consumer of + the web application war file (i.e., to the Deployer). Typically, the tools + used by the web application war file consumer will display the description + when processing the parent element that contains the description. + + Used in: auth-constraint, context-param, ejb-local-ref, ejb-ref, + env-entry, filter, init-param, resource-env-ref, resource-ref, run-as, + security-role, security-role-ref, servlet, user-data-constraint, + web-app, web-resource-collection + --> + <!ELEMENT description (#PCDATA)> + + <!-- + The display-name element contains a short name that is intended to be + displayed by tools. The display name need not be unique. + + Used in: filter, security-constraint, servlet, web-app + + Example: + + <display-name>Employee Self Service</display-name> + --> + <!ELEMENT display-name (#PCDATA)> + + <!-- + The distributable element, by its presence in a web application + deployment descriptor, indicates that this web application is + programmed appropriately to be deployed into a distributed servlet + container + + Used in: web-app + --> + <!ELEMENT distributable EMPTY> + + <!-- + The ejb-link element is used in the ejb-ref or ejb-local-ref + elements to specify that an EJB reference is linked to an + enterprise bean. + + The name in the ejb-link element is composed of a + path name specifying the ejb-jar containing the referenced enterprise + bean with the ejb-name of the target bean appended and separated from + the path name by "#". The path name is relative to the war file + containing the web application that is referencing the enterprise bean. + This allows multiple enterprise beans with the same ejb-name to be + uniquely identified. + + Used in: ejb-local-ref, ejb-ref + + Examples: + + <ejb-link>EmployeeRecord</ejb-link> + + <ejb-link>../products/product.jar#ProductEJB</ejb-link> + + --> + <!ELEMENT ejb-link (#PCDATA)> + + <!-- + The ejb-local-ref element is used for the declaration of a reference to + an enterprise bean's local home. The declaration consists of: + + - an optional description + - the EJB reference name used in the code of the web application + that's referencing the enterprise bean + - the expected type of the referenced enterprise bean + - the expected local home and local interfaces of the referenced + enterprise bean + - optional ejb-link information, used to specify the referenced + enterprise bean + + Used in: web-app + --> + <!ELEMENT ejb-local-ref (description?, ejb-ref-name, ejb-ref-type, local-home, local, ejb-link?)> -<!-- -The ejb-ref element is used for the declaration of a reference to -an enterprise bean's home. The declaration consists of: - - - an optional description - - the EJB reference name used in the code of - the web application that's referencing the enterprise bean - - the expected type of the referenced enterprise bean - - the expected home and remote interfaces of the referenced - enterprise bean - - optional ejb-link information, used to specify the referenced - enterprise bean - -Used in: web-app ---> -<!ELEMENT ejb-ref (description?, ejb-ref-name, ejb-ref-type, + <!-- + The ejb-ref element is used for the declaration of a reference to + an enterprise bean's home. The declaration consists of: + + - an optional description + - the EJB reference name used in the code of + the web application that's referencing the enterprise bean + - the expected type of the referenced enterprise bean + - the expected home and remote interfaces of the referenced + enterprise bean + - optional ejb-link information, used to specify the referenced + enterprise bean + + Used in: web-app + --> + <!ELEMENT ejb-ref (description?, ejb-ref-name, ejb-ref-type, home, remote, ejb-link?)> -<!-- -The ejb-ref-name element contains the name of an EJB reference. The -EJB reference is an entry in the web application's environment and is -relative to the java:comp/env context. The name must be unique -within the web application. + <!-- + The ejb-ref-name element contains the name of an EJB reference. The + EJB reference is an entry in the web application's environment and is + relative to the java:comp/env context. The name must be unique + within the web application. -It is recommended that name is prefixed with "ejb/". + It is recommended that name is prefixed with "ejb/". -Used in: ejb-local-ref, ejb-ref + Used in: ejb-local-ref, ejb-ref -Example: + Example: -<ejb-ref-name>ejb/Payroll</ejb-ref-name> ---> -<!ELEMENT ejb-ref-name (#PCDATA)> + <ejb-ref-name>ejb/Payroll</ejb-ref-name> + --> + <!ELEMENT ejb-ref-name (#PCDATA)> -<!-- -The ejb-ref-type element contains the expected type of the -referenced enterprise bean. + <!-- + The ejb-ref-type element contains the expected type of the + referenced enterprise bean. -The ejb-ref-type element must be one of the following: + The ejb-ref-type element must be one of the following: - <ejb-ref-type>Entity</ejb-ref-type> - <ejb-ref-type>Session</ejb-ref-type> + <ejb-ref-type>Entity</ejb-ref-type> + <ejb-ref-type>Session</ejb-ref-type> -Used in: ejb-local-ref, ejb-ref ---> -<!ELEMENT ejb-ref-type (#PCDATA)> + Used in: ejb-local-ref, ejb-ref + --> + <!ELEMENT ejb-ref-type (#PCDATA)> -<!-- -The env-entry element contains the declaration of a web application's -environment entry. The declaration consists of an optional -description, the name of the environment entry, and an optional -value. If a value is not specified, one must be supplied -during deployment. ---> -<!ELEMENT env-entry (description?, env-entry-name, env-entry-value?, -env-entry-type)> + <!-- + The env-entry element contains the declaration of a web application's + environment entry. The declaration consists of an optional + description, the name of the environment entry, and an optional + value. If a value is not specified, one must be supplied + during deployment. + --> + <!ELEMENT env-entry (description?, env-entry-name, env-entry-value?, + env-entry-type)> -<!-- -The env-entry-name element contains the name of a web applications's -environment entry. The name is a JNDI name relative to the -java:comp/env context. The name must be unique within a web application. + <!-- + The env-entry-name element contains the name of a web applications's + environment entry. The name is a JNDI name relative to the + java:comp/env context. The name must be unique within a web application. + + Example: + + <env-entry-name>minAmount</env-entry-name> + + Used in: env-entry + --> + <!ELEMENT env-entry-name (#PCDATA)> + + <!-- + The env-entry-type element contains the fully-qualified Java type of + the environment entry value that is expected by the web application's + code. + + The following are the legal values of env-entry-type: + + java.lang.Boolean + java.lang.Byte + java.lang.Character + java.lang.String + java.lang.Short + java.lang.Integer + java.lang.Long + java.lang.Float + java.lang.Double + + Used in: env-entry + --> + <!ELEMENT env-entry-type (#PCDATA)> + + <!-- + The env-entry-value element contains the value of a web application's + environment entry. The value must be a String that is valid for the + constructor of the specified type that takes a single String + parameter, or for java.lang.Character, a single character. + + Example: + + <env-entry-value>100.00</env-entry-value> + + Used in: env-entry + --> + <!ELEMENT env-entry-value (#PCDATA)> + + <!-- + The error-code contains an HTTP error code, ex: 404 + + Used in: error-page + --> + <!ELEMENT error-code (#PCDATA)> + + <!-- + The error-page element contains a mapping between an error code + or exception type to the path of a resource in the web application + + Used in: web-app + --> + <!ELEMENT error-page ((error-code | exception-type), location)> + + <!-- + The exception type contains a fully qualified class name of a + Java exception type. + + Used in: error-page + --> + <!ELEMENT exception-type (#PCDATA)> + + <!-- + The extension element contains a string describing an + extension. example: "txt" + + Used in: mime-mapping + --> + <!ELEMENT extension (#PCDATA)> + + <!-- + Declares a filter in the web application. The filter is mapped to + either a servlet or a URL pattern in the filter-mapping element, using + the filter-name value to reference. Filters can access the + initialization parameters declared in the deployment descriptor at + runtime via the FilterConfig interface. + + Used in: web-app + --> + <!ELEMENT filter (icon?, filter-name, display-name?, description?, + filter-class, init-param*)> + + <!-- + The fully qualified classname of the filter. + + Used in: filter + --> + <!ELEMENT filter-class (#PCDATA)> + + <!-- + Declaration of the filter mappings in this web application. The + container uses the filter-mapping declarations to decide which filters + to apply to a request, and in what order. The container matches the + request URI to a Servlet in the normal way. To determine which filters + to apply it matches filter-mapping declarations either on servlet-name, + or on url-pattern for each filter-mapping element, depending on which + style is used. The order in which filters are invoked is the order in + which filter-mapping declarations that match a request URI for a + servlet appear in the list of filter-mapping elements.The filter-name + value must be the value of the <filter-name> sub-elements of one of the + <filter> declarations in the deployment descriptor. + + Used in: web-app + --> + <!ELEMENT filter-mapping (filter-name, (url-pattern | servlet-name))> + + <!-- + The logical name of the filter. This name is used to map the filter. + Each filter name is unique within the web application. + + Used in: filter, filter-mapping + --> + <!ELEMENT filter-name (#PCDATA)> + + <!-- + The form-error-page element defines the location in the web app + where the error page that is displayed when login is not successful + can be found. The path begins with a leading / and is interpreted + relative to the root of the WAR. -Example: + Used in: form-login-config + --> + <!ELEMENT form-error-page (#PCDATA)> + + <!-- + The form-login-config element specifies the login and error pages + that should be used in form based login. If form based authentication + is not used, these elements are ignored. + + Used in: login-config + --> + <!ELEMENT form-login-config (form-login-page, form-error-page)> + + <!-- + The form-login-page element defines the location in the web app + where the page that can be used for login can be found. The path + begins with a leading / and is interpreted relative to the root of the WAR. + + Used in: form-login-config + --> + <!ELEMENT form-login-page (#PCDATA)> + + <!-- + The home element contains the fully-qualified name of the enterprise + bean's home interface. + + Used in: ejb-ref + + Example: + + <home>com.aardvark.payroll.PayrollHome</home> + --> + <!ELEMENT home (#PCDATA)> + + <!-- + The http-method contains an HTTP method (GET | POST |...). + + Used in: web-resource-collection + --> + <!ELEMENT http-method (#PCDATA)> + + <!-- + The icon element contains small-icon and large-icon elements that + specify the file names for small and a large GIF or JPEG icon images + used to represent the parent element in a GUI tool. + + Used in: filter, servlet, web-app + --> + <!ELEMENT icon (small-icon?, large-icon?)> + + <!-- + The init-param element contains a name/value pair as an + initialization param of the servlet + + Used in: filter, servlet + --> + <!ELEMENT init-param (param-name, param-value, description?)> + + <!-- + The jsp-file element contains the full path to a JSP file within + the web application beginning with a `/'. + + Used in: servlet + --> + <!ELEMENT jsp-file (#PCDATA)> + + <!-- + The large-icon element contains the name of a file + containing a large (32 x 32) icon image. The file + name is a relative path within the web application's + war file. + + The image may be either in the JPEG or GIF format. + The icon can be used by tools. + + Used in: icon -<env-entry-name>minAmount</env-entry-name> - -Used in: env-entry ---> -<!ELEMENT env-entry-name (#PCDATA)> + Example: -<!-- -The env-entry-type element contains the fully-qualified Java type of -the environment entry value that is expected by the web application's -code. - -The following are the legal values of env-entry-type: - - java.lang.Boolean - java.lang.Byte - java.lang.Character - java.lang.String - java.lang.Short - java.lang.Integer - java.lang.Long - java.lang.Float - java.lang.Double - -Used in: env-entry ---> -<!ELEMENT env-entry-type (#PCDATA)> - -<!-- -The env-entry-value element contains the value of a web application's -environment entry. The value must be a String that is valid for the -constructor of the specified type that takes a single String -parameter, or for java.lang.Character, a single character. + <large-icon>employee-service-icon32x32.jpg</large-icon> + --> + <!ELEMENT large-icon (#PCDATA)> -Example: + <!-- + The listener element indicates the deployment properties for a web + application listener bean. -<env-entry-value>100.00</env-entry-value> - -Used in: env-entry ---> -<!ELEMENT env-entry-value (#PCDATA)> - -<!-- -The error-code contains an HTTP error code, ex: 404 - -Used in: error-page ---> -<!ELEMENT error-code (#PCDATA)> - -<!-- -The error-page element contains a mapping between an error code -or exception type to the path of a resource in the web application + Used in: web-app + --> + <!ELEMENT listener (listener-class)> -Used in: web-app ---> -<!ELEMENT error-page ((error-code | exception-type), location)> - -<!-- -The exception type contains a fully qualified class name of a -Java exception type. - -Used in: error-page ---> -<!ELEMENT exception-type (#PCDATA)> - -<!-- -The extension element contains a string describing an -extension. example: "txt" - -Used in: mime-mapping ---> -<!ELEMENT extension (#PCDATA)> - -<!-- -Declares a filter in the web application. The filter is mapped to -either a servlet or a URL pattern in the filter-mapping element, using -the filter-name value to reference. Filters can access the -initialization parameters declared in the deployment descriptor at -runtime via the FilterConfig interface. - -Used in: web-app ---> -<!ELEMENT filter (icon?, filter-name, display-name?, description?, -filter-class, init-param*)> - -<!-- -The fully qualified classname of the filter. - -Used in: filter ---> -<!ELEMENT filter-class (#PCDATA)> - -<!-- -Declaration of the filter mappings in this web application. The -container uses the filter-mapping declarations to decide which filters -to apply to a request, and in what order. The container matches the -request URI to a Servlet in the normal way. To determine which filters -to apply it matches filter-mapping declarations either on servlet-name, -or on url-pattern for each filter-mapping element, depending on which -style is used. The order in which filters are invoked is the order in -which filter-mapping declarations that match a request URI for a -servlet appear in the list of filter-mapping elements.The filter-name -value must be the value of the <filter-name> sub-elements of one of the -<filter> declarations in the deployment descriptor. - -Used in: web-app ---> -<!ELEMENT filter-mapping (filter-name, (url-pattern | servlet-name))> - -<!-- -The logical name of the filter. This name is used to map the filter. -Each filter name is unique within the web application. - -Used in: filter, filter-mapping ---> -<!ELEMENT filter-name (#PCDATA)> - -<!-- -The form-error-page element defines the location in the web app -where the error page that is displayed when login is not successful -can be found. The path begins with a leading / and is interpreted -relative to the root of the WAR. - -Used in: form-login-config ---> -<!ELEMENT form-error-page (#PCDATA)> - -<!-- -The form-login-config element specifies the login and error pages -that should be used in form based login. If form based authentication -is not used, these elements are ignored. - -Used in: login-config ---> -<!ELEMENT form-login-config (form-login-page, form-error-page)> - -<!-- -The form-login-page element defines the location in the web app -where the page that can be used for login can be found. The path -begins with a leading / and is interpreted relative to the root of the WAR. - -Used in: form-login-config ---> -<!ELEMENT form-login-page (#PCDATA)> - -<!-- -The home element contains the fully-qualified name of the enterprise -bean's home interface. - -Used in: ejb-ref - -Example: - -<home>com.aardvark.payroll.PayrollHome</home> ---> -<!ELEMENT home (#PCDATA)> - -<!-- -The http-method contains an HTTP method (GET | POST |...). - -Used in: web-resource-collection ---> -<!ELEMENT http-method (#PCDATA)> - -<!-- -The icon element contains small-icon and large-icon elements that -specify the file names for small and a large GIF or JPEG icon images -used to represent the parent element in a GUI tool. - -Used in: filter, servlet, web-app ---> -<!ELEMENT icon (small-icon?, large-icon?)> - -<!-- -The init-param element contains a name/value pair as an -initialization param of the servlet - -Used in: filter, servlet ---> -<!ELEMENT init-param (param-name, param-value, description?)> - -<!-- -The jsp-file element contains the full path to a JSP file within -the web application beginning with a `/'. - -Used in: servlet ---> -<!ELEMENT jsp-file (#PCDATA)> - -<!-- -The large-icon element contains the name of a file -containing a large (32 x 32) icon image. The file -name is a relative path within the web application's -war file. - -The image may be either in the JPEG or GIF format. -The icon can be used by tools. - -Used in: icon - -Example: - -<large-icon>employee-service-icon32x32.jpg</large-icon> ---> -<!ELEMENT large-icon (#PCDATA)> - -<!-- -The listener element indicates the deployment properties for a web -application listener bean. - -Used in: web-app ---> -<!ELEMENT listener (listener-class)> + <!-- + The listener-class element declares a class in the application must be + registered as a web application listener bean. The value is the fully qualified classname of the listener class. -<!-- -The listener-class element declares a class in the application must be -registered as a web application listener bean. The value is the fully qualified classname of the listener class. + Used in: listener + --> + <!ELEMENT listener-class (#PCDATA)> -Used in: listener ---> -<!ELEMENT listener-class (#PCDATA)> + <!-- + The load-on-startup element indicates that this servlet should be + loaded (instantiated and have its init() called) on the startup + of the web application. The optional contents of + these element must be an integer indicating the order in which + the servlet should be loaded. If the value is a negative integer, + or the element is not present, the container is free to load the + servlet whenever it chooses. If the value is a positive integer + or 0, the container must load and initialize the servlet as the + application is deployed. The container must guarantee that + servlets marked with lower integers are loaded before servlets + marked with higher integers. The container may choose the order + of loading of servlets with the same load-on-start-up value. -<!-- -The load-on-startup element indicates that this servlet should be -loaded (instantiated and have its init() called) on the startup -of the web application. The optional contents of -these element must be an integer indicating the order in which -the servlet should be loaded. If the value is a negative integer, -or the element is not present, the container is free to load the -servlet whenever it chooses. If the value is a positive integer -or 0, the container must load and initialize the servlet as the -application is deployed. The container must guarantee that -servlets marked with lower integers are loaded before servlets -marked with higher integers. The container may choose the order -of loading of servlets with the same load-on-start-up value. - -Used in: servlet ---> -<!ELEMENT load-on-startup (#PCDATA)> + Used in: servlet + --> + <!ELEMENT load-on-startup (#PCDATA)> -<!-- + <!-- -The local element contains the fully-qualified name of the -enterprise bean's local interface. + The local element contains the fully-qualified name of the + enterprise bean's local interface. -Used in: ejb-local-ref + Used in: ejb-local-ref ---> -<!ELEMENT local (#PCDATA)> + --> + <!ELEMENT local (#PCDATA)> -<!-- + <!-- -The local-home element contains the fully-qualified name of the -enterprise bean's local home interface. + The local-home element contains the fully-qualified name of the + enterprise bean's local home interface. -Used in: ejb-local-ref ---> -<!ELEMENT local-home (#PCDATA)> + Used in: ejb-local-ref + --> + <!ELEMENT local-home (#PCDATA)> -<!-- -The location element contains the location of the resource in the web -application relative to the root of the web application. The value of -the location must have a leading `/'. + <!-- + The location element contains the location of the resource in the web + application relative to the root of the web application. The value of + the location must have a leading `/'. -Used in: error-page ---> -<!ELEMENT location (#PCDATA)> + Used in: error-page + --> + <!ELEMENT location (#PCDATA)> -<!-- -The login-config element is used to configure the authentication -method that should be used, the realm name that should be used for -this application, and the attributes that are needed by the form login -mechanism. + <!-- + The login-config element is used to configure the authentication + method that should be used, the realm name that should be used for + this application, and the attributes that are needed by the form login + mechanism. -Used in: web-app ---> -<!ELEMENT login-config (auth-method?, realm-name?, form-login-config?)> + Used in: web-app + --> + <!ELEMENT login-config (auth-method?, realm-name?, form-login-config?)> -<!-- -The mime-mapping element defines a mapping between an extension -and a mime type. + <!-- + The mime-mapping element defines a mapping between an extension + and a mime type. -Used in: web-app ---> -<!ELEMENT mime-mapping (extension, mime-type)> + Used in: web-app + --> + <!ELEMENT mime-mapping (extension, mime-type)> -<!-- -The mime-type element contains a defined mime type. example: -"text/plain" + <!-- + The mime-type element contains a defined mime type. example: + "text/plain" -Used in: mime-mapping ---> -<!ELEMENT mime-type (#PCDATA)> + Used in: mime-mapping + --> + <!ELEMENT mime-type (#PCDATA)> -<!-- -The param-name element contains the name of a parameter. Each parameter -name must be unique in the web application. + <!-- + The param-name element contains the name of a parameter. Each parameter + name must be unique in the web application. -Used in: context-param, init-param ---> -<!ELEMENT param-name (#PCDATA)> + Used in: context-param, init-param + --> + <!ELEMENT param-name (#PCDATA)> -<!-- -The param-value element contains the value of a parameter. + <!-- + The param-value element contains the value of a parameter. -Used in: context-param, init-param ---> -<!ELEMENT param-value (#PCDATA)> + Used in: context-param, init-param + --> + <!ELEMENT param-value (#PCDATA)> -<!-- -The realm name element specifies the realm name to use in HTTP -Basic authorization. + <!-- + The realm name element specifies the realm name to use in HTTP + Basic authorization. -Used in: login-config ---> -<!ELEMENT realm-name (#PCDATA)> + Used in: login-config + --> + <!ELEMENT realm-name (#PCDATA)> -<!-- -The remote element contains the fully-qualified name of the enterprise -bean's remote interface. + <!-- + The remote element contains the fully-qualified name of the enterprise + bean's remote interface. -Used in: ejb-ref + Used in: ejb-ref -Example: + Example: -<remote>com.wombat.empl.EmployeeService</remote> ---> -<!ELEMENT remote (#PCDATA)> + <remote>com.wombat.empl.EmployeeService</remote> + --> + <!ELEMENT remote (#PCDATA)> -<!-- -The res-auth element specifies whether the web application code signs -on programmatically to the resource manager, or whether the Container -will sign on to the resource manager on behalf of the web application. In the -latter case, the Container uses information that is supplied by the -Deployer. + <!-- + The res-auth element specifies whether the web application code signs + on programmatically to the resource manager, or whether the Container + will sign on to the resource manager on behalf of the web application. In the + latter case, the Container uses information that is supplied by the + Deployer. -The value of this element must be one of the two following: + The value of this element must be one of the two following: - <res-auth>Application</res-auth> - <res-auth>Container</res-auth> + <res-auth>Application</res-auth> + <res-auth>Container</res-auth> -Used in: resource-ref ---> -<!ELEMENT res-auth (#PCDATA)> + Used in: resource-ref + --> + <!ELEMENT res-auth (#PCDATA)> -<!-- -The res-ref-name element specifies the name of a resource manager -connection factory reference. The name is a JNDI name relative to the -java:comp/env context. The name must be unique within a web application. + <!-- + The res-ref-name element specifies the name of a resource manager + connection factory reference. The name is a JNDI name relative to the + java:comp/env context. The name must be unique within a web application. -Used in: resource-ref ---> -<!ELEMENT res-ref-name (#PCDATA)> + Used in: resource-ref + --> + <!ELEMENT res-ref-name (#PCDATA)> -<!-- -The res-sharing-scope element specifies whether connections obtained -through the given resource manager connection factory reference can be -shared. The value of this element, if specified, must be one of the -two following: + <!-- + The res-sharing-scope element specifies whether connections obtained + through the given resource manager connection factory reference can be + shared. The value of this element, if specified, must be one of the + two following: - <res-sharing-scope>Shareable</res-sharing-scope> - <res-sharing-scope>Unshareable</res-sharing-scope> + <res-sharing-scope>Shareable</res-sharing-scope> + <res-sharing-scope>Unshareable</res-sharing-scope> -The default value is Shareable. + The default value is Shareable. -Used in: resource-ref ---> -<!ELEMENT res-sharing-scope (#PCDATA)> + Used in: resource-ref + --> + <!ELEMENT res-sharing-scope (#PCDATA)> -<!-- -The res-type element specifies the type of the data source. The type -is specified by the fully qualified Java language class or interface -expected to be implemented by the data source. + <!-- + The res-type element specifies the type of the data source. The type + is specified by the fully qualified Java language class or interface + expected to be implemented by the data source. -Used in: resource-ref ---> -<!ELEMENT res-type (#PCDATA)> + Used in: resource-ref + --> + <!ELEMENT res-type (#PCDATA)> -<!-- -The resource-env-ref element contains a declaration of a web application's -reference to an administered object associated with a resource -in the web application's environment. It consists of an optional -description, the resource environment reference name, and an -indication of the resource environment reference type expected by -the web application code. + <!-- + The resource-env-ref element contains a declaration of a web application's + reference to an administered object associated with a resource + in the web application's environment. It consists of an optional + description, the resource environment reference name, and an + indication of the resource environment reference type expected by + the web application code. -Used in: web-app + Used in: web-app -Example: + Example: -<resource-env-ref> - <resource-env-ref-name>jms/StockQueue</resource-env-ref-name> - <resource-env-ref-type>javax.jms.Queue</resource-env-ref-type> -</resource-env-ref> ---> -<!ELEMENT resource-env-ref (description?, resource-env-ref-name, + <resource-env-ref> + <resource-env-ref-name>jms/StockQueue</resource-env-ref-name> + <resource-env-ref-type>javax.jms.Queue</resource-env-ref-type> + </resource-env-ref> + --> + <!ELEMENT resource-env-ref (description?, resource-env-ref-name, resource-env-ref-type)> -<!-- -The resource-env-ref-name element specifies the name of a resource -environment reference; its value is the environment entry name used in -the web application code. The name is a JNDI name relative to the -java:comp/env context and must be unique within a web application. - -Used in: resource-env-ref ---> -<!ELEMENT resource-env-ref-name (#PCDATA)> - -<!-- -The resource-env-ref-type element specifies the type of a resource -environment reference. It is the fully qualified name of a Java -language class or interface. - -Used in: resource-env-ref ---> -<!ELEMENT resource-env-ref-type (#PCDATA)> - -<!-- -The resource-ref element contains a declaration of a web application's -reference to an external resource. It consists of an optional -description, the resource manager connection factory reference name, -the indication of the resource manager connection factory type -expected by the web application code, the type of authentication -(Application or Container), and an optional specification of the -shareability of connections obtained from the resource (Shareable or -Unshareable). - -Used in: web-app - -Example: - - <resource-ref> - <res-ref-name>jdbc/EmployeeAppDB</res-ref-name> - <res-type>javax.sql.DataSource</res-type> - <res-auth>Container</res-auth> - <res-sharing-scope>Shareable</res-sharing-scope> - </resource-ref> ---> -<!ELEMENT resource-ref (description?, res-ref-name, res-type, res-auth, + <!-- + The resource-env-ref-name element specifies the name of a resource + environment reference; its value is the environment entry name used in + the web application code. The name is a JNDI name relative to the + java:comp/env context and must be unique within a web application. + + Used in: resource-env-ref + --> + <!ELEMENT resource-env-ref-name (#PCDATA)> + + <!-- + The resource-env-ref-type element specifies the type of a resource + environment reference. It is the fully qualified name of a Java + language class or interface. + + Used in: resource-env-ref + --> + <!ELEMENT resource-env-ref-type (#PCDATA)> + + <!-- + The resource-ref element contains a declaration of a web application's + reference to an external resource. It consists of an optional + description, the resource manager connection factory reference name, + the indication of the resource manager connection factory type + expected by the web application code, the type of authentication + (Application or Container), and an optional specification of the + shareability of connections obtained from the resource (Shareable or + Unshareable). + + Used in: web-app + + Example: + + <resource-ref> + <res-ref-name>jdbc/EmployeeAppDB</res-ref-name> + <res-type>javax.sql.DataSource</res-type> + <res-auth>Container</res-auth> + <res-sharing-scope>Shareable</res-sharing-scope> + </resource-ref> + --> + <!ELEMENT resource-ref (description?, res-ref-name, res-type, res-auth, res-sharing-scope?)> -<!-- -The role-link element is a reference to a defined security role. The -role-link element must contain the name of one of the security roles -defined in the security-role elements. + <!-- + The role-link element is a reference to a defined security role. The + role-link element must contain the name of one of the security roles + defined in the security-role elements. -Used in: security-role-ref ---> -<!ELEMENT role-link (#PCDATA)> + Used in: security-role-ref + --> + <!ELEMENT role-link (#PCDATA)> -<!-- -The role-name element contains the name of a security role. + <!-- + The role-name element contains the name of a security role. + + The name must conform to the lexical rules for an NMTOKEN. -The name must conform to the lexical rules for an NMTOKEN. + Used in: auth-constraint, run-as, security-role, security-role-ref + --> + <!ELEMENT role-name (#PCDATA)> + + <!-- + The run-as element specifies the run-as identity to be used for the + execution of the web application. It contains an optional description, and + the name of a security role. + + Used in: servlet + --> + <!ELEMENT run-as (description?, role-name)> + + <!-- + The security-constraint element is used to associate security + constraints with one or more web resource collections + + Used in: web-app + --> + <!ELEMENT security-constraint (display-name?, web-resource-collection+, + auth-constraint?, user-data-constraint?)> + + <!-- + The security-role element contains the definition of a security + role. The definition consists of an optional description of the + security role, and the security role name. -Used in: auth-constraint, run-as, security-role, security-role-ref ---> -<!ELEMENT role-name (#PCDATA)> + Used in: web-app + + Example: -<!-- -The run-as element specifies the run-as identity to be used for the -execution of the web application. It contains an optional description, and -the name of a security role. - -Used in: servlet ---> -<!ELEMENT run-as (description?, role-name)> - -<!-- -The security-constraint element is used to associate security -constraints with one or more web resource collections + <security-role> + <description> + This role includes all employees who are authorized + to access the employee service application. + </description> + <role-name>employee</role-name> + </security-role> + --> + <!ELEMENT security-role (description?, role-name)> + + <!-- + The security-role-ref element contains the declaration of a security + role reference in the web application's code. The declaration consists + of an optional description, the security role name used in the code, + and an optional link to a security role. If the security role is not + specified, the Deployer must choose an appropriate security role. -Used in: web-app ---> -<!ELEMENT security-constraint (display-name?, web-resource-collection+, -auth-constraint?, user-data-constraint?)> - -<!-- -The security-role element contains the definition of a security -role. The definition consists of an optional description of the -security role, and the security role name. - -Used in: web-app - -Example: - - <security-role> - <description> - This role includes all employees who are authorized - to access the employee service application. - </description> - <role-name>employee</role-name> - </security-role> ---> -<!ELEMENT security-role (description?, role-name)> - -<!-- -The security-role-ref element contains the declaration of a security -role reference in the web application's code. The declaration consists -of an optional description, the security role name used in the code, -and an optional link to a security role. If the security role is not -specified, the Deployer must choose an appropriate security role. - -The value of the role-name element must be the String used as the -parameter to the EJBContext.isCallerInRole(String roleName) method -or the HttpServletRequest.isUserInRole(String role) method. - -Used in: servlet - ---> -<!ELEMENT security-role-ref (description?, role-name, role-link?)> - -<!-- -The servlet element contains the declarative data of a -servlet. If a jsp-file is specified and the load-on-startup element is -present, then the JSP should be precompiled and loaded. - -Used in: web-app ---> -<!ELEMENT servlet (icon?, servlet-name, display-name?, description?, -(servlet-class|jsp-file), init-param*, load-on-startup?, run-as?, security-role-ref*)> - -<!-- -The servlet-class element contains the fully qualified class name -of the servlet. - -Used in: servlet ---> -<!ELEMENT servlet-class (#PCDATA)> - -<!-- -The servlet-mapping element defines a mapping between a servlet -and a url pattern - -Used in: web-app ---> -<!ELEMENT servlet-mapping (servlet-name, url-pattern)> - -<!-- -The servlet-name element contains the canonical name of the -servlet. Each servlet name is unique within the web application. - -Used in: filter-mapping, servlet, servlet-mapping ---> -<!ELEMENT servlet-name (#PCDATA)> - -<!-- -The session-config element defines the session parameters for -this web application. - -Used in: web-app ---> -<!ELEMENT session-config (session-timeout?)> - -<!-- -The session-timeout element defines the default session timeout -interval for all sessions created in this web application. The -specified timeout must be expressed in a whole number of minutes. -If the timeout is 0 or less, the container ensures the default -behaviour of sessions is never to time out. - -Used in: session-config ---> -<!ELEMENT session-timeout (#PCDATA)> - -<!-- -The small-icon element contains the name of a file -containing a small (16 x 16) icon image. The file -name is a relative path within the web application's -war file. - -The image may be either in the JPEG or GIF format. -The icon can be used by tools. - -Used in: icon - -Example: - -<small-icon>employee-service-icon16x16.jpg</small-icon> ---> -<!ELEMENT small-icon (#PCDATA)> - -<!-- -The taglib element is used to describe a JSP tag library. - -Used in: web-app ---> -<!ELEMENT taglib (taglib-uri, taglib-location)> - -<!-- -the taglib-location element contains the location (as a resource -relative to the root of the web application) where to find the Tag -Libary Description file for the tag library. - -Used in: taglib ---> -<!ELEMENT taglib-location (#PCDATA)> - -<!-- -The taglib-uri element describes a URI, relative to the location -of the web.xml document, identifying a Tag Library used in the Web -Application. - -Used in: taglib ---> -<!ELEMENT taglib-uri (#PCDATA)> - -<!-- -The transport-guarantee element specifies that the communication -between client and server should be NONE, INTEGRAL, or -CONFIDENTIAL. NONE means that the application does not require any -transport guarantees. A value of INTEGRAL means that the application -requires that the data sent between the client and server be sent in -such a way that it can't be changed in transit. CONFIDENTIAL means -that the application requires that the data be transmitted in a -fashion that prevents other entities from observing the contents of -the transmission. In most cases, the presence of the INTEGRAL or -CONFIDENTIAL flag will indicate that the use of SSL is required. - -Used in: user-data-constraint ---> -<!ELEMENT transport-guarantee (#PCDATA)> - -<!-- -The url-pattern element contains the url pattern of the mapping. Must -follow the rules specified in Section 11.2 of the Servlet API -Specification. - -Used in: filter-mapping, servlet-mapping, web-resource-collection ---> -<!ELEMENT url-pattern (#PCDATA)> - -<!-- -The user-data-constraint element is used to indicate how data -communicated between the client and container should be protected. - -Used in: security-constraint ---> -<!ELEMENT user-data-constraint (description?, transport-guarantee)> - -<!-- -The web-resource-collection element is used to identify a subset -of the resources and HTTP methods on those resources within a web -application to which a security constraint applies. If no HTTP methods -are specified, then the security constraint applies to all HTTP -methods. - -Used in: security-constraint ---> -<!ELEMENT web-resource-collection (web-resource-name, description?, -url-pattern*, http-method*)> - -<!-- -The web-resource-name contains the name of this web resource -collection. - -Used in: web-resource-collection ---> -<!ELEMENT web-resource-name (#PCDATA)> - -<!-- -The welcome-file element contains file name to use as a default -welcome file, such as index.html - -Used in: welcome-file-list ---> -<!ELEMENT welcome-file (#PCDATA)> - -<!-- -The welcome-file-list contains an ordered list of welcome files -elements. - -Used in: web-app ---> -<!ELEMENT welcome-file-list (welcome-file+)> - -<!-- -The ID mechanism is to allow tools that produce additional deployment -information (i.e., information beyond the standard deployment -descriptor information) to store the non-standard information in a -separate file, and easily refer from these tool-specific files to the -information in the standard deployment descriptor. - -Tools are not allowed to add the non-standard information into the -standard deployment descriptor. ---> + The value of the role-name element must be the String used as the + parameter to the EJBContext.isCallerInRole(String roleName) method + or the HttpServletRequest.isUserInRole(String role) method. -<!ATTLIST auth-constraint id ID #IMPLIED> -<!ATTLIST auth-method id ID #IMPLIED> -<!ATTLIST context-param id ID #IMPLIED> -<!ATTLIST description id ID #IMPLIED> -<!ATTLIST display-name id ID #IMPLIED> -<!ATTLIST distributable id ID #IMPLIED> -<!ATTLIST ejb-link id ID #IMPLIED> -<!ATTLIST ejb-local-ref id ID #IMPLIED> -<!ATTLIST ejb-ref id ID #IMPLIED> -<!ATTLIST ejb-ref-name id ID #IMPLIED> -<!ATTLIST ejb-ref-type id ID #IMPLIED> -<!ATTLIST env-entry id ID #IMPLIED> -<!ATTLIST env-entry-name id ID #IMPLIED> -<!ATTLIST env-entry-type id ID #IMPLIED> -<!ATTLIST env-entry-value id ID #IMPLIED> -<!ATTLIST error-code id ID #IMPLIED> -<!ATTLIST error-page id ID #IMPLIED> -<!ATTLIST exception-type id ID #IMPLIED> -<!ATTLIST extension id ID #IMPLIED> -<!ATTLIST filter id ID #IMPLIED> -<!ATTLIST filter-class id ID #IMPLIED> -<!ATTLIST filter-mapping id ID #IMPLIED> -<!ATTLIST filter-name id ID #IMPLIED> -<!ATTLIST form-error-page id ID #IMPLIED> -<!ATTLIST form-login-config id ID #IMPLIED> -<!ATTLIST form-login-page id ID #IMPLIED> -<!ATTLIST home id ID #IMPLIED> -<!ATTLIST http-method id ID #IMPLIED> -<!ATTLIST icon id ID #IMPLIED> -<!ATTLIST init-param id ID #IMPLIED> -<!ATTLIST jsp-file id ID #IMPLIED> -<!ATTLIST large-icon id ID #IMPLIED> -<!ATTLIST listener id ID #IMPLIED> -<!ATTLIST listener-class id ID #IMPLIED> -<!ATTLIST load-on-startup id ID #IMPLIED> -<!ATTLIST local id ID #IMPLIED> -<!ATTLIST local-home id ID #IMPLIED> -<!ATTLIST location id ID #IMPLIED> -<!ATTLIST login-config id ID #IMPLIED> -<!ATTLIST mime-mapping id ID #IMPLIED> -<!ATTLIST mime-type id ID #IMPLIED> -<!ATTLIST param-name id ID #IMPLIED> -<!ATTLIST param-value id ID #IMPLIED> -<!ATTLIST realm-name id ID #IMPLIED> -<!ATTLIST remote id ID #IMPLIED> -<!ATTLIST res-auth id ID #IMPLIED> -<!ATTLIST res-ref-name id ID #IMPLIED> -<!ATTLIST res-sharing-scope id ID #IMPLIED> -<!ATTLIST res-type id ID #IMPLIED> -<!ATTLIST resource-env-ref id ID #IMPLIED> -<!ATTLIST resource-env-ref-name id ID #IMPLIED> -<!ATTLIST resource-env-ref-type id ID #IMPLIED> -<!ATTLIST resource-ref id ID #IMPLIED> -<!ATTLIST role-link id ID #IMPLIED> -<!ATTLIST role-name id ID #IMPLIED> -<!ATTLIST run-as id ID #IMPLIED> -<!ATTLIST security-constraint id ID #IMPLIED> -<!ATTLIST security-role id ID #IMPLIED> -<!ATTLIST security-role-ref id ID #IMPLIED> -<!ATTLIST servlet id ID #IMPLIED> -<!ATTLIST servlet-class id ID #IMPLIED> -<!ATTLIST servlet-mapping id ID #IMPLIED> -<!ATTLIST servlet-name id ID #IMPLIED> -<!ATTLIST session-config id ID #IMPLIED> -<!ATTLIST session-timeout id ID #IMPLIED> -<!ATTLIST small-icon id ID #IMPLIED> -<!ATTLIST taglib id ID #IMPLIED> -<!ATTLIST taglib-location id ID #IMPLIED> -<!ATTLIST taglib-uri id ID #IMPLIED> -<!ATTLIST transport-guarantee id ID #IMPLIED> -<!ATTLIST url-pattern id ID #IMPLIED> -<!ATTLIST user-data-constraint id ID #IMPLIED> -<!ATTLIST web-app id ID #IMPLIED> -<!ATTLIST web-resource-collection id ID #IMPLIED> -<!ATTLIST web-resource-name id ID #IMPLIED> -<!ATTLIST welcome-file id ID #IMPLIED> -<!ATTLIST welcome-file-list id ID #IMPLIED> + Used in: servlet + + --> + <!ELEMENT security-role-ref (description?, role-name, role-link?)> + + <!-- + The servlet element contains the declarative data of a + servlet. If a jsp-file is specified and the load-on-startup element is + present, then the JSP should be precompiled and loaded. + + Used in: web-app + --> + <!ELEMENT servlet (icon?, servlet-name, display-name?, description?, + (servlet-class|jsp-file), init-param*, load-on-startup?, run-as?, security-role-ref*)> + + <!-- + The servlet-class element contains the fully qualified class name + of the servlet. + + Used in: servlet + --> + <!ELEMENT servlet-class (#PCDATA)> + + <!-- + The servlet-mapping element defines a mapping between a servlet + and a url pattern + + Used in: web-app + --> + <!ELEMENT servlet-mapping (servlet-name, url-pattern)> + + <!-- + The servlet-name element contains the canonical name of the + servlet. Each servlet name is unique within the web application. + + Used in: filter-mapping, servlet, servlet-mapping + --> + <!ELEMENT servlet-name (#PCDATA)> + + <!-- + The session-config element defines the session parameters for + this web application. + + Used in: web-app + --> + <!ELEMENT session-config (session-timeout?)> + + <!-- + The session-timeout element defines the default session timeout + interval for all sessions created in this web application. The + specified timeout must be expressed in a whole number of minutes. + If the timeout is 0 or less, the container ensures the default + behaviour of sessions is never to time out. + + Used in: session-config + --> + <!ELEMENT session-timeout (#PCDATA)> + + <!-- + The small-icon element contains the name of a file + containing a small (16 x 16) icon image. The file + name is a relative path within the web application's + war file. + + The image may be either in the JPEG or GIF format. + The icon can be used by tools. + + Used in: icon + + Example: + + <small-icon>employee-service-icon16x16.jpg</small-icon> + --> + <!ELEMENT small-icon (#PCDATA)> + + <!-- + The taglib element is used to describe a JSP tag library. + + Used in: web-app + --> + <!ELEMENT taglib (taglib-uri, taglib-location)> + + <!-- + the taglib-location element contains the location (as a resource + relative to the root of the web application) where to find the Tag + Libary Description file for the tag library. + + Used in: taglib + --> + <!ELEMENT taglib-location (#PCDATA)> + + <!-- + The taglib-uri element describes a URI, relative to the location + of the web.xml document, identifying a Tag Library used in the Web + Application. + + Used in: taglib + --> + <!ELEMENT taglib-uri (#PCDATA)> + + <!-- + The transport-guarantee element specifies that the communication + between client and server should be NONE, INTEGRAL, or + CONFIDENTIAL. NONE means that the application does not require any + transport guarantees. A value of INTEGRAL means that the application + requires that the data sent between the client and server be sent in + such a way that it can't be changed in transit. CONFIDENTIAL means + that the application requires that the data be transmitted in a + fashion that prevents other entities from observing the contents of + the transmission. In most cases, the presence of the INTEGRAL or + CONFIDENTIAL flag will indicate that the use of SSL is required. + + Used in: user-data-constraint + --> + <!ELEMENT transport-guarantee (#PCDATA)> + + <!-- + The url-pattern element contains the url pattern of the mapping. Must + follow the rules specified in Section 11.2 of the Servlet API + Specification. + + Used in: filter-mapping, servlet-mapping, web-resource-collection + --> + <!ELEMENT url-pattern (#PCDATA)> + + <!-- + The user-data-constraint element is used to indicate how data + communicated between the client and container should be protected. + + Used in: security-constraint + --> + <!ELEMENT user-data-constraint (description?, transport-guarantee)> + + <!-- + The web-resource-collection element is used to identify a subset + of the resources and HTTP methods on those resources within a web + application to which a security constraint applies. If no HTTP methods + are specified, then the security constraint applies to all HTTP + methods. + + Used in: security-constraint + --> + <!ELEMENT web-resource-collection (web-resource-name, description?, + url-pattern*, http-method*)> + + <!-- + The web-resource-name contains the name of this web resource + collection. + + Used in: web-resource-collection + --> + <!ELEMENT web-resource-name (#PCDATA)> + + <!-- + The welcome-file element contains file name to use as a default + welcome file, such as index.html + + Used in: welcome-file-list + --> + <!ELEMENT welcome-file (#PCDATA)> + + <!-- + The welcome-file-list contains an ordered list of welcome files + elements. + + Used in: web-app + --> + <!ELEMENT welcome-file-list (welcome-file+)> + + <!-- + The ID mechanism is to allow tools that produce additional deployment + information (i.e., information beyond the standard deployment + descriptor information) to store the non-standard information in a + separate file, and easily refer from these tool-specific files to the + information in the standard deployment descriptor. + + Tools are not allowed to add the non-standard information into the + standard deployment descriptor. + --> + + <!ATTLIST auth-constraint id ID #IMPLIED> + <!ATTLIST auth-method id ID #IMPLIED> + <!ATTLIST context-param id ID #IMPLIED> + <!ATTLIST description id ID #IMPLIED> + <!ATTLIST display-name id ID #IMPLIED> + <!ATTLIST distributable id ID #IMPLIED> + <!ATTLIST ejb-link id ID #IMPLIED> + <!ATTLIST ejb-local-ref id ID #IMPLIED> + <!ATTLIST ejb-ref id ID #IMPLIED> + <!ATTLIST ejb-ref-name id ID #IMPLIED> + <!ATTLIST ejb-ref-type id ID #IMPLIED> + <!ATTLIST env-entry id ID #IMPLIED> + <!ATTLIST env-entry-name id ID #IMPLIED> + <!ATTLIST env-entry-type id ID #IMPLIED> + <!ATTLIST env-entry-value id ID #IMPLIED> + <!ATTLIST error-code id ID #IMPLIED> + <!ATTLIST error-page id ID #IMPLIED> + <!ATTLIST exception-type id ID #IMPLIED> + <!ATTLIST extension id ID #IMPLIED> + <!ATTLIST filter id ID #IMPLIED> + <!ATTLIST filter-class id ID #IMPLIED> + <!ATTLIST filter-mapping id ID #IMPLIED> + <!ATTLIST filter-name id ID #IMPLIED> + <!ATTLIST form-error-page id ID #IMPLIED> + <!ATTLIST form-login-config id ID #IMPLIED> + <!ATTLIST form-login-page id ID #IMPLIED> + <!ATTLIST home id ID #IMPLIED> + <!ATTLIST http-method id ID #IMPLIED> + <!ATTLIST icon id ID #IMPLIED> + <!ATTLIST init-param id ID #IMPLIED> + <!ATTLIST jsp-file id ID #IMPLIED> + <!ATTLIST large-icon id ID #IMPLIED> + <!ATTLIST listener id ID #IMPLIED> + <!ATTLIST listener-class id ID #IMPLIED> + <!ATTLIST load-on-startup id ID #IMPLIED> + <!ATTLIST local id ID #IMPLIED> + <!ATTLIST local-home id ID #IMPLIED> + <!ATTLIST location id ID #IMPLIED> + <!ATTLIST login-config id ID #IMPLIED> + <!ATTLIST mime-mapping id ID #IMPLIED> + <!ATTLIST mime-type id ID #IMPLIED> + <!ATTLIST param-name id ID #IMPLIED> + <!ATTLIST param-value id ID #IMPLIED> + <!ATTLIST realm-name id ID #IMPLIED> + <!ATTLIST remote id ID #IMPLIED> + <!ATTLIST res-auth id ID #IMPLIED> + <!ATTLIST res-ref-name id ID #IMPLIED> + <!ATTLIST res-sharing-scope id ID #IMPLIED> + <!ATTLIST res-type id ID #IMPLIED> + <!ATTLIST resource-env-ref id ID #IMPLIED> + <!ATTLIST resource-env-ref-name id ID #IMPLIED> + <!ATTLIST resource-env-ref-type id ID #IMPLIED> + <!ATTLIST resource-ref id ID #IMPLIED> + <!ATTLIST role-link id ID #IMPLIED> + <!ATTLIST role-name id ID #IMPLIED> + <!ATTLIST run-as id ID #IMPLIED> + <!ATTLIST security-constraint id ID #IMPLIED> + <!ATTLIST security-role id ID #IMPLIED> + <!ATTLIST security-role-ref id ID #IMPLIED> + <!ATTLIST servlet id ID #IMPLIED> + <!ATTLIST servlet-class id ID #IMPLIED> + <!ATTLIST servlet-mapping id ID #IMPLIED> + <!ATTLIST servlet-name id ID #IMPLIED> + <!ATTLIST session-config id ID #IMPLIED> + <!ATTLIST session-timeout id ID #IMPLIED> + <!ATTLIST small-icon id ID #IMPLIED> + <!ATTLIST taglib id ID #IMPLIED> + <!ATTLIST taglib-location id ID #IMPLIED> + <!ATTLIST taglib-uri id ID #IMPLIED> + <!ATTLIST transport-guarantee id ID #IMPLIED> + <!ATTLIST url-pattern id ID #IMPLIED> + <!ATTLIST user-data-constraint id ID #IMPLIED> + <!ATTLIST web-app id ID #IMPLIED> + <!ATTLIST web-resource-collection id ID #IMPLIED> + <!ATTLIST web-resource-name id ID #IMPLIED> + <!ATTLIST welcome-file id ID #IMPLIED> + <!ATTLIST welcome-file-list id ID #IMPLIED> |