You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by se...@apache.org on 2015/05/11 21:43:51 UTC
incubator-ignite git commit: # IGNITE-888 Web interface to monitoring
cluster state. Initial commit.
Repository: incubator-ignite
Updated Branches:
refs/heads/ignite-888 [created] c7a8427d5
# IGNITE-888 Web interface to monitoring cluster state.
Initial commit.
Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/c7a8427d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/c7a8427d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/c7a8427d
Branch: refs/heads/ignite-888
Commit: c7a8427d57bfb8e57347cfe1733d076035c3045b
Parents: 942abe4
Author: sevdokimov <se...@jetbrains.com>
Authored: Mon May 11 22:43:25 2015 +0300
Committer: sevdokimov <se...@jetbrains.com>
Committed: Mon May 11 22:43:25 2015 +0300
----------------------------------------------------------------------
.../apache/ignite/internal/util/DebugUtil.java | 76 +++++
modules/webVisor/pom.xml | 292 +++++++++++++++++++
.../ignite/webVisor/IgniteNameRepository.java | 128 ++++++++
.../ignite/webVisor/NodeSwitchFilter.java | 140 +++++++++
.../org/apache/ignite/webVisor/VisorServer.java | 181 ++++++++++++
.../apache/ignite/webVisor/WebVisorPlugin.java | 27 ++
.../webVisor/WebVisorPluginConfiguration.java | 59 ++++
.../ignite/webVisor/WebVisorPluginProvider.java | 137 +++++++++
.../apache/ignite/webVisor/WebVisorUtils.java | 50 ++++
.../webVisor/render/AbstractPageBean.java | 60 ++++
.../ignite/webVisor/render/ClusterPage.java | 77 +++++
.../ignite/webVisor/render/NodeInfoPage.java | 34 +++
.../org/apache/ignite/webVisor/render/WU.java | 72 +++++
.../org.apache.ignite.plugin.PluginProvider | 1 +
.../src/main/webapp/WEB-INF/sitemesh3.xml | 3 +
.../webVisor/src/main/webapp/WEB-INF/web.xml | 28 ++
modules/webVisor/src/main/webapp/caches.jsp | 15 +
modules/webVisor/src/main/webapp/cluster.jsp | 52 ++++
.../webVisor/src/main/webapp/css/cluster.css | 10 +
modules/webVisor/src/main/webapp/css/main.css | 3 +
modules/webVisor/src/main/webapp/decorator.jsp | 59 ++++
.../webVisor/src/main/webapp/igniteNotFound.jsp | 14 +
.../src/main/webapp/moreThenOneIgnite.jsp | 14 +
.../webVisor/src/main/webapp/noIgnitesFound.jsp | 14 +
modules/webVisor/src/main/webapp/nodeInfo.jsp | 19 ++
25 files changed, 1565 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/c7a8427d/modules/core/src/main/java/org/apache/ignite/internal/util/DebugUtil.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/DebugUtil.java b/modules/core/src/main/java/org/apache/ignite/internal/util/DebugUtil.java
new file mode 100644
index 0000000..4876656
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/DebugUtil.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.util;
+
+import java.util.*;
+
+/**
+ *
+ */
+public class DebugUtil {
+ /** */
+ private static final DebugUtil INSTANCE = new DebugUtil();
+
+ /** */
+ private final Set<Thread> hangThreads = new HashSet<>();
+
+ /**
+ *
+ */
+ private synchronized void hang0() {
+ hangThreads.add(Thread.currentThread());
+
+ try {
+ while (hangThreads.contains(Thread.currentThread()))
+ wait();
+ }
+ catch (InterruptedException e) {
+ Thread.interrupted();
+ }
+ }
+
+ /**
+ *
+ */
+ public synchronized Set<Thread> getHangThreads() {
+ return new HashSet<>(hangThreads);
+ }
+
+ /**
+ *
+ */
+ public synchronized void resumeAll() {
+ hangThreads.clear();
+
+ notifyAll();
+ }
+
+ /**
+ *
+ */
+ public static void hang() {
+ INSTANCE.hang0();
+ }
+
+ /**
+ *
+ */
+ public static DebugUtil getInstance() {
+ return INSTANCE;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/c7a8427d/modules/webVisor/pom.xml
----------------------------------------------------------------------
diff --git a/modules/webVisor/pom.xml b/modules/webVisor/pom.xml
new file mode 100644
index 0000000..b8aeed7
--- /dev/null
+++ b/modules/webVisor/pom.xml
@@ -0,0 +1,292 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!--
+ POM file.
+-->
+<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.apache.ignite</groupId>
+ <artifactId>ignite-parent</artifactId>
+ <version>1</version>
+ <relativePath>../../parent</relativePath>
+ </parent>
+
+ <artifactId>ignite-web-visor</artifactId>
+ <version>1.1.0-SNAPSHOT</version>
+
+ <properties>
+ <jetty.version>9.2.10.v20150310</jetty.version>
+ </properties>
+
+ <dependencies>
+ <!--<dependency>-->
+ <!--<groupId>javax.servlet</groupId>-->
+ <!--<artifactId>javax.servlet-api</artifactId>-->
+ <!--<version>3.1.0</version>-->
+ <!--</dependency>-->
+
+ <!--<dependency>-->
+ <!--<groupId>javax.servlet.jsp</groupId>-->
+ <!--<artifactId>javax.servlet.jsp-api</artifactId>-->
+ <!--<version>2.3.2-b01</version>-->
+ <!--</dependency>-->
+
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-servlets</artifactId>
+ <version>${jetty.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.sitemesh</groupId>
+ <artifactId>sitemesh</artifactId>
+ <version>3.0.0</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-webapp</artifactId>
+ <version>${jetty.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-annotations</artifactId>
+ <version>${jetty.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-jsp</artifactId>
+ <version>${jetty.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>tomcat</groupId>
+ <artifactId>jasper-runtime</artifactId>
+ <version>5.5.23</version>
+
+ <exclusions>
+ <exclusion>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <!-- Ignite -->
+ <dependency>
+ <groupId>org.apache.ignite</groupId>
+ <artifactId>ignite-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.ignite</groupId>
+ <artifactId>ignite-core</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.ignite</groupId>
+ <artifactId>ignite-spring</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.ignite</groupId>
+ <artifactId>ignite-indexing</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.11</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ </resource>
+ <resource>
+ <directory>src/main/webapp</directory>
+ <targetPath>webapp</targetPath>
+ <excludes>
+ <exclude>*.jsp</exclude>
+ </excludes>
+ </resource>
+ </resources>
+
+ <plugins>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.1</version>
+ <configuration>
+ <source>1.7</source>
+ <target>1.7</target>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <version>2.8</version>
+ <executions>
+ <execution>
+ <id>Copy dependencies</id>
+ <phase>package</phase>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+
+ <configuration>
+ <outputDirectory>target/web-libs</outputDirectory>
+
+ <excludeGroupIds>org.apache.ignite,org.glassfish.web,org.glassfish,org.eclipse.jetty.orbit</excludeGroupIds>
+ <excludeArtifactIds>jetty-annotations,jetty-jsp,jetty-schemas</excludeArtifactIds>
+ </configuration>
+ </execution>
+ <!--<execution>-->
+ <!--<id>Copy</id>-->
+ <!--<phase>package</phase>-->
+ <!--<goals>-->
+ <!--<goal>copy</goal>-->
+ <!--</goals>-->
+
+ <!--<configuration>-->
+ <!--<outputDirectory>target/web-libs</outputDirectory>-->
+
+ <!--<artifactItems>-->
+ <!--<artifactItem>-->
+ <!--<groupId>javax.servlet</groupId>-->
+ <!--<artifactId>javax.servlet-api</artifactId>-->
+ <!--</artifactItem>-->
+
+ <!--<artifactItem>-->
+ <!--<groupId>javax.servlet.jsp</groupId>-->
+ <!--<artifactId>javax.servlet.jsp-api</artifactId>-->
+ <!--</artifactItem>-->
+
+ <!--<artifactItem>-->
+ <!--<groupId>org.eclipse.jetty</groupId>-->
+ <!--<artifactId>jetty-servlets</artifactId>-->
+ <!--<version>${jetty.version}</version>-->
+ <!--</artifactItem>-->
+
+
+ <!--<artifactItem>-->
+ <!--<groupId>org.eclipse.jetty</groupId>-->
+ <!--<artifactId>jetty-continuation</artifactId>-->
+ <!--<version>${jetty.version}</version>-->
+ <!--</artifactItem>-->
+
+ <!--<artifactItem>-->
+ <!--<groupId>org.eclipse.jetty</groupId>-->
+ <!--<artifactId>jetty-http</artifactId>-->
+ <!--<version>${jetty.version}</version>-->
+ <!--</artifactItem>-->
+
+ <!--<artifactItem>-->
+ <!--<groupId>org.eclipse.jetty</groupId>-->
+ <!--<artifactId>jetty-util</artifactId>-->
+ <!--<version>${jetty.version}</version>-->
+ <!--</artifactItem>-->
+
+ <!--<artifactItem>-->
+ <!--<groupId>org.eclipse.jetty</groupId>-->
+ <!--<artifactId>jetty-io</artifactId>-->
+ <!--<version>${jetty.version}</version>-->
+ <!--</artifactItem>-->
+
+ <!--<artifactItem>-->
+ <!--<groupId>org.eclipse.jetty</groupId>-->
+ <!--<artifactId>jetty-webapp</artifactId>-->
+ <!--<version>${jetty.version}</version>-->
+ <!--</artifactItem>-->
+
+ <!--<artifactItem>-->
+ <!--<groupId>org.eclipse.jetty</groupId>-->
+ <!--<artifactId>jetty-xml</artifactId>-->
+ <!--<version>${jetty.version}</version>-->
+ <!--</artifactItem>-->
+
+ <!--<artifactItem>-->
+ <!--<groupId>org.eclipse.jetty</groupId>-->
+ <!--<artifactId>jetty-servlet</artifactId>-->
+ <!--<version>${jetty.version}</version>-->
+ <!--</artifactItem>-->
+
+ <!--<artifactItem>-->
+ <!--<groupId>org.eclipse.jetty</groupId>-->
+ <!--<artifactId>jetty-security</artifactId>-->
+ <!--<version>${jetty.version}</version>-->
+ <!--</artifactItem>-->
+
+ <!--<artifactItem>-->
+ <!--<groupId>org.eclipse.jetty</groupId>-->
+ <!--<artifactId>jetty-server</artifactId>-->
+ <!--<version>${jetty.version}</version>-->
+ <!--</artifactItem>-->
+
+ <!--<artifactItem>-->
+ <!--<groupId>tomcat</groupId>-->
+ <!--<artifactId>jasper-runtime</artifactId>-->
+ <!--<version>5.5.23</version>-->
+ <!--</artifactItem>-->
+ <!--</artifactItems>-->
+ <!--</configuration>-->
+ <!--</execution>-->
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-jspc-maven-plugin</artifactId>
+ <version>${jetty.version}</version>
+ <executions>
+ <execution>
+ <id>jspc</id>
+ <goals>
+ <goal>jspc</goal>
+ </goals>
+ <configuration>
+ <webXmlFragment>${basedir}/target/classes/webapp/WEB-INF/webfrag.xml</webXmlFragment>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/c7a8427d/modules/webVisor/src/main/java/org/apache/ignite/webVisor/IgniteNameRepository.java
----------------------------------------------------------------------
diff --git a/modules/webVisor/src/main/java/org/apache/ignite/webVisor/IgniteNameRepository.java b/modules/webVisor/src/main/java/org/apache/ignite/webVisor/IgniteNameRepository.java
new file mode 100644
index 0000000..be41060
--- /dev/null
+++ b/modules/webVisor/src/main/java/org/apache/ignite/webVisor/IgniteNameRepository.java
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.webVisor;
+
+import org.apache.ignite.*;
+import org.jetbrains.annotations.*;
+
+import java.util.*;
+import java.util.regex.*;
+
+/**
+ * Each unit test starts several nodes with name like "partitioned.GridCachePartitionedAtomicReferenceApiSelfTest0".
+ * Utl like http://localhost:8100/partitioned.GridCachePartitionedAtomicReferenceApiSelfTest0 lookslooks bad, We should
+ * cut it to http://localhost:8100/g_0 , Ignite started by startGrids(1) will has suffix "g_1", Ignite started with
+ * startGrids(2) will has suffix "g_2"
+ */
+public class IgniteNameRepository {
+ /** */
+ private static final IgniteNameRepository instance = new IgniteNameRepository();
+
+ /**
+ * Names that should not be cut, For example TcpClientDiscoverySelfTest starts nodes with names like "server-1",
+ * "client-2", in this case URL like http://localhost:8100/server-1 looks good.
+ */
+ private static final Pattern GOOD_NAME_PATTERN = Pattern.compile("[0-9a-zA-Z\\-\\._]{1,15}");
+
+ /** Map short name to ignite name */
+ private final Map<String, String> shortName2Name = new HashMap<>();
+
+ /** Map short name to ignite name */
+ private final Map<String, String> name2shortName = new HashMap<>();
+
+ /**
+ * Default constructor.
+ */
+ private IgniteNameRepository() {
+ Ignition.addListener(new IgnitionListener() {
+ @Override public void onStateChange(@Nullable String name, IgniteState state) {
+ if (name != null && (state == IgniteState.STOPPED || state == IgniteState.STOPPED_ON_SEGMENTATION)) {
+ synchronized (IgniteNameRepository.this) {
+ String shortName = name2shortName.remove(name);
+
+ shortName2Name.remove(shortName);
+ }
+ }
+ }
+ });
+ }
+
+ /**
+ * @param shortName Short name.
+ */
+ @Nullable public synchronized String igniteName(@NotNull String shortName) {
+ return shortName2Name.get(shortName);
+ }
+
+ /**
+ * @param igniteName Ignite name.
+ */
+ public synchronized String getOrRegisterShortName(@NotNull String igniteName) {
+ assert !igniteName.isEmpty();
+
+ String res = name2shortName.get(igniteName);
+
+ if (res != null)
+ return res;
+
+ if (GOOD_NAME_PATTERN.matcher(igniteName).matches()) {
+ if (!shortName2Name.containsKey(igniteName)) {
+ shortName2Name.put(igniteName, igniteName);
+
+ name2shortName.put(igniteName, igniteName);
+
+ return igniteName;
+ }
+ }
+
+ char lastC = igniteName.charAt(igniteName.length() - 1);
+
+ if (lastC >= '0' && lastC <= '9') {
+ String oneNumName = igniteName.substring(igniteName.length() - 1);
+
+ if (!shortName2Name.containsKey(oneNumName)) {
+ shortName2Name.put(oneNumName, igniteName);
+
+ name2shortName.put(igniteName, oneNumName);
+
+ return oneNumName;
+ }
+ }
+
+ int idx = 100;
+
+ while (true) {
+ String shortName = "n" + idx;
+
+ if (!shortName2Name.containsKey(shortName)) {
+ shortName2Name.put(shortName, igniteName);
+
+ name2shortName.put(igniteName, shortName);
+
+ return shortName;
+ }
+ }
+ }
+
+ /**
+ * @return Instance
+ */
+ public static IgniteNameRepository instance() {
+ return instance;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/c7a8427d/modules/webVisor/src/main/java/org/apache/ignite/webVisor/NodeSwitchFilter.java
----------------------------------------------------------------------
diff --git a/modules/webVisor/src/main/java/org/apache/ignite/webVisor/NodeSwitchFilter.java b/modules/webVisor/src/main/java/org/apache/ignite/webVisor/NodeSwitchFilter.java
new file mode 100644
index 0000000..c314a6a
--- /dev/null
+++ b/modules/webVisor/src/main/java/org/apache/ignite/webVisor/NodeSwitchFilter.java
@@ -0,0 +1,140 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.webVisor;
+
+import org.apache.ignite.*;
+import org.apache.ignite.webVisor.render.*;
+
+import javax.servlet.*;
+import javax.servlet.http.*;
+import java.io.*;
+import java.util.*;
+import java.util.regex.*;
+
+/**
+ *
+ */
+public class NodeSwitchFilter implements Filter {
+ /** */
+ private static final Pattern GRID_NAME_PATTERN = Pattern.compile("/g_([0-9a-zA-Z\\-\\._]+)(/.*)?");
+
+ /** {@inheritDoc} */
+ @Override public void init(FilterConfig cfg) throws ServletException {
+ // No-op.
+ }
+
+ /**
+ * @param req Request.
+ * @param ignite Ignite.
+ */
+ private void initAttributes(HttpServletRequest req, Ignite ignite) {
+ req.setAttribute("g", ignite);
+ req.setAttribute("wu", new WU(ignite));
+ }
+
+ /** {@inheritDoc} */
+ @Override public void doFilter(ServletRequest req, ServletResponse res,
+ FilterChain chain) throws IOException, ServletException {
+ HttpServletRequest httpReq = (HttpServletRequest)req;
+ HttpServletResponse httpResp = (HttpServletResponse)res;
+
+ Matcher matcher = GRID_NAME_PATTERN.matcher(httpReq.getRequestURI());
+
+ if (!matcher.matches()) {
+ Ignite dfltIgnite;
+
+ try {
+ dfltIgnite = Ignition.ignite();
+ }
+ catch (IgniteIllegalStateException e) {
+ dfltIgnite = null;
+ }
+
+ if (dfltIgnite != null) {
+ initAttributes(httpReq, dfltIgnite);
+
+ chain.doFilter(req, res);
+
+ return;
+ }
+
+ List<Ignite> ignites = Ignition.allGrids();
+
+ if (ignites.isEmpty()) {
+ req.getRequestDispatcher("/noIgnitesFound.jsp").forward(req, res);
+
+ return;
+ }
+
+ String igniteName = ignites.get(0).name();
+
+ if (igniteName == null || igniteName.length() == 0) {
+ initAttributes(httpReq, ignites.get(0));
+
+ chain.doFilter(req, res);
+
+ return;
+ }
+
+ StringBuilder redirectUrl = new StringBuilder();
+
+ redirectUrl.append(httpReq.getContextPath());
+ redirectUrl.append("/g_").append(IgniteNameRepository.instance().getOrRegisterShortName(igniteName));
+ redirectUrl.append(httpReq.getRequestURI());
+
+ if (httpReq.getQueryString() != null)
+ redirectUrl.append('?').append(httpReq.getQueryString());
+
+ httpResp.sendRedirect(redirectUrl.toString());
+
+ return;
+ }
+
+ String shortName = matcher.group(1);
+
+ String igniteName = IgniteNameRepository.instance().igniteName(shortName);
+
+ Ignite ignite = null;
+
+ if (igniteName != null) {
+ try {
+ ignite = Ignition.ignite(igniteName);
+ }
+ catch (IgniteIllegalStateException e) {
+ // No-op.
+ }
+ }
+
+ if (ignite == null) {
+ req.getRequestDispatcher("/igniteNotFound.jsp").forward(req, res);
+
+ return;
+ }
+
+ initAttributes(httpReq, ignite);
+
+ String uri = matcher.group(2);
+
+ httpReq.getRequestDispatcher(uri == null ? "/" : uri).forward(req, res);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void destroy() {
+ // No-op.
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/c7a8427d/modules/webVisor/src/main/java/org/apache/ignite/webVisor/VisorServer.java
----------------------------------------------------------------------
diff --git a/modules/webVisor/src/main/java/org/apache/ignite/webVisor/VisorServer.java b/modules/webVisor/src/main/java/org/apache/ignite/webVisor/VisorServer.java
new file mode 100644
index 0000000..f404352
--- /dev/null
+++ b/modules/webVisor/src/main/java/org/apache/ignite/webVisor/VisorServer.java
@@ -0,0 +1,181 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.webVisor;
+
+import org.apache.ignite.*;
+import org.apache.ignite.internal.util.*;
+import org.apache.ignite.internal.util.typedef.internal.*;
+import org.eclipse.jetty.server.*;
+import org.eclipse.jetty.util.log.*;
+import org.eclipse.jetty.util.resource.*;
+import org.eclipse.jetty.webapp.*;
+import org.jetbrains.annotations.*;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+/**
+ *
+ */
+public class VisorServer {
+ /** */
+ private static VisorServer instance;
+
+ /** */
+ private Server srv;
+
+ /** */
+ private int port = -1;
+
+ /** */
+ private final WebVisorPluginConfiguration cfg;
+
+ /**
+ * @param cfg Config.
+ */
+ private VisorServer(WebVisorPluginConfiguration cfg) {
+ this.cfg = cfg;
+ }
+
+ /**
+ * @param cfg Config.
+ * @param log Logger.
+ */
+ public synchronized static VisorServer getOrStart(@NotNull WebVisorPluginConfiguration cfg,
+ @Nullable IgniteLogger log) {
+ if (instance == null) {
+ instance = new VisorServer(cfg);
+
+ instance.startup(log);
+ }
+
+ return instance;
+ }
+
+ /**
+ *
+ */
+ public boolean isStarted() {
+ return srv != null && srv.isStarted();
+ }
+
+ /**
+ *
+ */
+ public void startup(@Nullable IgniteLogger log) {
+ try {
+ Properties p = new Properties();
+
+ p.setProperty("org.eclipse.jetty.LEVEL", "WARN");
+ p.setProperty("org.eclipse.jetty.util.log.LEVEL", "OFF");
+ p.setProperty("org.eclipse.jetty.util.component.LEVEL", "OFF");
+
+ StdErrLog.setProperties(p);
+
+ URL webXmlRes = VisorServer.class.getClassLoader().getResource("webapp/WEB-INF/web.xml");
+
+ String webXmlStr = webXmlRes.toString();
+
+ int port;
+
+ for (port = cfg.getFirstPort(); port < cfg.getFirstPort() + cfg.getPortRangeSize(); port++) {
+ Server srv = new Server(port);
+
+ WebAppContext webAppCtx = new WebAppContext();
+
+ webAppCtx.setContextPath("/");
+
+ if (webXmlStr.startsWith("file:/")) {
+ // Run from IDEA.
+ File webApp = new File(webXmlRes.getFile()).getParentFile().getParentFile();
+ File classes = webApp.getParentFile();
+ File target = classes.getParentFile();
+ File moduleRoot = target.getParentFile();
+
+ webAppCtx.setResourceBase(moduleRoot.getAbsolutePath() + "/src/main/webapp");
+
+ Configuration.ClassList classlist = Configuration.ClassList.setServerDefault(srv);
+ classlist.addBefore(
+ "org.eclipse.jetty.webapp.JettyWebXmlConfiguration",
+ "org.eclipse.jetty.annotations.AnnotationConfiguration" );
+
+ // Set the ContainerIncludeJarPattern so that jetty examines these
+ // container-path jars for tlds, web-fragments etc.
+ // If you omit the jar that contains the jstl .tlds, the jsp engine will
+ // scan for them instead.
+ webAppCtx.setAttribute(
+ "org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",
+ ".*/[^/]*servlet-api-[^/]*\\.jar$|.*/javax.servlet.jsp.jstl-.*\\.jar$|.*/[^/]*taglibs.*\\.jar$" );
+ }
+ else {
+ // Run from JAR
+ URL webAppUrl = new URL(webXmlStr.substring(0, webXmlStr.length() - "WEB-INF/web.xml".length()));
+
+ webAppCtx.setBaseResource(Resource.newResource(webAppUrl));
+ }
+
+ webAppCtx.setAttribute("debugUtil", DebugUtil.getInstance());
+
+ srv.setHandler(webAppCtx);
+
+ try {
+ srv.start();
+
+ this.srv = srv;
+
+ break;
+ }
+ catch (BindException ignored) {
+ // No-op.
+ }
+ }
+
+ if (srv == null) {
+ U.error(log, "Failed to start web server all ports are busy [firstPort=" + cfg.getFirstPort()
+ + ", portsCount=" + cfg.getPortRangeSize() + "]");
+ }
+ else {
+ this.port = port;
+
+ if (log != null)
+ log.info("Visor server started: http://localhost:" + port);
+ }
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ *
+ */
+ public void stop() throws Exception {
+ if (srv != null)
+ srv.stop();
+ }
+
+ /**
+ *
+ */
+ public int getPort() {
+ assert isStarted();
+
+ return port;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/c7a8427d/modules/webVisor/src/main/java/org/apache/ignite/webVisor/WebVisorPlugin.java
----------------------------------------------------------------------
diff --git a/modules/webVisor/src/main/java/org/apache/ignite/webVisor/WebVisorPlugin.java b/modules/webVisor/src/main/java/org/apache/ignite/webVisor/WebVisorPlugin.java
new file mode 100644
index 0000000..daad599
--- /dev/null
+++ b/modules/webVisor/src/main/java/org/apache/ignite/webVisor/WebVisorPlugin.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.webVisor;
+
+import org.apache.ignite.plugin.*;
+
+/**
+ *
+ */
+public class WebVisorPlugin implements IgnitePlugin {
+ // No-op.
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/c7a8427d/modules/webVisor/src/main/java/org/apache/ignite/webVisor/WebVisorPluginConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/webVisor/src/main/java/org/apache/ignite/webVisor/WebVisorPluginConfiguration.java b/modules/webVisor/src/main/java/org/apache/ignite/webVisor/WebVisorPluginConfiguration.java
new file mode 100644
index 0000000..9bc339f
--- /dev/null
+++ b/modules/webVisor/src/main/java/org/apache/ignite/webVisor/WebVisorPluginConfiguration.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.webVisor;
+
+import org.apache.ignite.plugin.*;
+
+/**
+ *
+ */
+public class WebVisorPluginConfiguration implements PluginConfiguration {
+ /** */
+ private int firstPort = 8100;
+
+ /** */
+ private int portRangeSize = 10;
+
+ /**
+ *
+ */
+ public int getFirstPort() {
+ return firstPort;
+ }
+
+ /**
+ * @param firstPort First port.
+ */
+ public void setFirstPort(int firstPort) {
+ this.firstPort = firstPort;
+ }
+
+ /**
+ *
+ */
+ public int getPortRangeSize() {
+ return portRangeSize;
+ }
+
+ /**
+ * @param portRangeSize Port range size.
+ */
+ public void setPortRangeSize(int portRangeSize) {
+ this.portRangeSize = portRangeSize;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/c7a8427d/modules/webVisor/src/main/java/org/apache/ignite/webVisor/WebVisorPluginProvider.java
----------------------------------------------------------------------
diff --git a/modules/webVisor/src/main/java/org/apache/ignite/webVisor/WebVisorPluginProvider.java b/modules/webVisor/src/main/java/org/apache/ignite/webVisor/WebVisorPluginProvider.java
new file mode 100644
index 0000000..b51fdee
--- /dev/null
+++ b/modules/webVisor/src/main/java/org/apache/ignite/webVisor/WebVisorPluginProvider.java
@@ -0,0 +1,137 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.webVisor;
+
+import org.apache.ignite.*;
+import org.apache.ignite.cluster.*;
+import org.apache.ignite.configuration.*;
+import org.apache.ignite.internal.*;
+import org.apache.ignite.plugin.*;
+import org.jetbrains.annotations.*;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ *
+ */
+public class WebVisorPluginProvider implements PluginProvider<WebVisorPluginConfiguration> {
+ /** */
+ private final WebVisorPlugin plugin = new WebVisorPlugin();
+
+ /** */
+ private WebVisorPluginConfiguration cfg;
+
+ /** */
+ private VisorServer srv;
+
+ /** */
+ private GridKernalContext igniteCtx;
+
+ /** {@inheritDoc} */
+ @Override public String name() {
+ return "web-visor";
+ }
+
+ /** {@inheritDoc} */
+ @Override public String version() {
+ return "1.0.0";
+ }
+
+ /** {@inheritDoc} */
+ @Override public String copyright() {
+ return null;
+ }
+
+ /** {@inheritDoc} */
+ @Override public WebVisorPlugin plugin() {
+ return plugin;
+ }
+
+ /** {@inheritDoc} */
+ @Nullable @Override public <T> T createComponent(PluginContext ctx, Class<T> cls) {
+ return null;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void initExtensions(PluginContext ctx, ExtensionRegistry registry) {
+ IgniteConfiguration igniteCfg = ctx.igniteConfiguration();
+
+ if (igniteCfg.getPluginConfigurations() != null) {
+ for (PluginConfiguration pluginCfg : igniteCfg.getPluginConfigurations()) {
+ if (pluginCfg instanceof WebVisorPluginConfiguration) {
+ cfg = (WebVisorPluginConfiguration)pluginCfg;
+
+ break;
+ }
+ }
+ }
+
+ if (cfg == null)
+ cfg = new WebVisorPluginConfiguration();
+
+ srv = VisorServer.getOrStart(cfg, ctx.log(VisorServer.class));
+
+ igniteCtx = ((IgniteKernal)ctx.grid()).context();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void start(PluginContext ctx) throws IgniteCheckedException {
+ if (srv.isStarted()) {
+ igniteCtx.addNodeAttribute(WebVisorUtils.WEB_VISOR_NODE_PORT, srv.getPort());
+
+ String igniteName = ctx.grid().name();
+
+ if (igniteName != null && !igniteName.isEmpty()) {
+ String shortName = IgniteNameRepository.instance().getOrRegisterShortName(igniteName);
+
+ igniteCtx.addNodeAttribute(WebVisorUtils.WEB_VISOR_NODE_URI, "/g_" + shortName);
+ }
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public void stop(boolean cancel) throws IgniteCheckedException {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onIgniteStart() throws IgniteCheckedException {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onIgniteStop(boolean cancel) {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Nullable @Override public Serializable provideDiscoveryData(UUID nodeId) {
+ return null;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void receiveDiscoveryData(UUID nodeId, Serializable data) {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public void validateNewNode(ClusterNode node) throws PluginValidationException {
+ // No-op.
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/c7a8427d/modules/webVisor/src/main/java/org/apache/ignite/webVisor/WebVisorUtils.java
----------------------------------------------------------------------
diff --git a/modules/webVisor/src/main/java/org/apache/ignite/webVisor/WebVisorUtils.java b/modules/webVisor/src/main/java/org/apache/ignite/webVisor/WebVisorUtils.java
new file mode 100644
index 0000000..91a3361
--- /dev/null
+++ b/modules/webVisor/src/main/java/org/apache/ignite/webVisor/WebVisorUtils.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.webVisor;
+
+import org.apache.ignite.cluster.*;
+import org.apache.ignite.internal.util.typedef.*;
+
+/**
+ *
+ */
+public class WebVisorUtils {
+ /** */
+ public static final String WEB_VISOR_NODE_PORT = "web.visor.node.port";
+
+ /** */
+ public static final String WEB_VISOR_NODE_URI = "web.visor.node.uri";
+
+
+ /**
+ * @param node Node.
+ */
+ public static String hostname(ClusterNode node) {
+ for (String hostName : node.hostNames()) {
+ if (!F.isEmpty(hostName))
+ return hostName;
+ }
+
+ for (String addr : node.addresses()) {
+ if (!F.isEmpty(addr))
+ return addr;
+ }
+
+ return "unknown";
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/c7a8427d/modules/webVisor/src/main/java/org/apache/ignite/webVisor/render/AbstractPageBean.java
----------------------------------------------------------------------
diff --git a/modules/webVisor/src/main/java/org/apache/ignite/webVisor/render/AbstractPageBean.java b/modules/webVisor/src/main/java/org/apache/ignite/webVisor/render/AbstractPageBean.java
new file mode 100644
index 0000000..6e3207c
--- /dev/null
+++ b/modules/webVisor/src/main/java/org/apache/ignite/webVisor/render/AbstractPageBean.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.webVisor.render;
+
+import org.apache.ignite.*;
+import org.apache.ignite.cluster.*;
+import org.jetbrains.annotations.*;
+
+import javax.servlet.http.*;
+
+/**
+ *
+ */
+public class AbstractPageBean {
+ /** */
+ protected final HttpServletRequest req;
+
+ /** */
+ protected final Ignite ignite;
+
+ /**
+ * @param req Request.
+ */
+ public AbstractPageBean(HttpServletRequest req) {
+ this.req = req;
+
+ req.setAttribute("p", this);
+
+ ignite = (Ignite)req.getAttribute("g");
+ }
+
+ /**
+ *
+ */
+ @NotNull public Ignite getIgnite() {
+ return ignite;
+ }
+
+ /**
+ *
+ */
+ @NotNull public ClusterNode getLocalNode() {
+ return ignite.cluster().localNode();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/c7a8427d/modules/webVisor/src/main/java/org/apache/ignite/webVisor/render/ClusterPage.java
----------------------------------------------------------------------
diff --git a/modules/webVisor/src/main/java/org/apache/ignite/webVisor/render/ClusterPage.java b/modules/webVisor/src/main/java/org/apache/ignite/webVisor/render/ClusterPage.java
new file mode 100644
index 0000000..d955dc2
--- /dev/null
+++ b/modules/webVisor/src/main/java/org/apache/ignite/webVisor/render/ClusterPage.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.webVisor.render;
+
+import org.apache.ignite.cluster.*;
+import org.jetbrains.annotations.*;
+
+import javax.servlet.http.*;
+import java.util.*;
+
+/**
+ *
+ */
+public class ClusterPage extends AbstractPageBean {
+ /** */
+ private final List<ClusterNode> nodes;
+
+ /** */
+ private boolean showClients = true;
+
+ /**
+ * @param req Request.
+ */
+ public ClusterPage(@NotNull HttpServletRequest req) {
+ super(req);
+
+ nodes = new ArrayList<>();
+
+ if ("true".equals(req.getParameter("filter")))
+ showClients = req.getParameter("showClients") != null;
+
+ for (ClusterNode node : getIgnite().cluster().nodes()) {
+ if (showClients || !node.isClient())
+ nodes.add(node);
+ }
+
+ Collections.sort(nodes, new Comparator<ClusterNode>() {
+ @Override public int compare(ClusterNode o1, ClusterNode o2) {
+ int res = Long.compare(o1.order(), o2.order());
+
+ if (res != 0)
+ return res;
+
+ return o1.id().compareTo(o2.id());
+ }
+ });
+ }
+
+ /**
+ *
+ */
+ @NotNull public List<ClusterNode> getNodes() {
+ return nodes;
+ }
+
+ /**
+ *
+ */
+ public boolean isShowClients() {
+ return showClients;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/c7a8427d/modules/webVisor/src/main/java/org/apache/ignite/webVisor/render/NodeInfoPage.java
----------------------------------------------------------------------
diff --git a/modules/webVisor/src/main/java/org/apache/ignite/webVisor/render/NodeInfoPage.java b/modules/webVisor/src/main/java/org/apache/ignite/webVisor/render/NodeInfoPage.java
new file mode 100644
index 0000000..fce0f28
--- /dev/null
+++ b/modules/webVisor/src/main/java/org/apache/ignite/webVisor/render/NodeInfoPage.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.webVisor.render;
+
+import org.jetbrains.annotations.*;
+
+import javax.servlet.http.*;
+
+/**
+ *
+ */
+public class NodeInfoPage extends AbstractPageBean {
+ /**
+ * @param req Request.
+ */
+ public NodeInfoPage(@NotNull HttpServletRequest req) {
+ super(req);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/c7a8427d/modules/webVisor/src/main/java/org/apache/ignite/webVisor/render/WU.java
----------------------------------------------------------------------
diff --git a/modules/webVisor/src/main/java/org/apache/ignite/webVisor/render/WU.java b/modules/webVisor/src/main/java/org/apache/ignite/webVisor/render/WU.java
new file mode 100644
index 0000000..6d097c1
--- /dev/null
+++ b/modules/webVisor/src/main/java/org/apache/ignite/webVisor/render/WU.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.webVisor.render;
+
+import org.apache.ignite.*;
+import org.apache.ignite.cluster.*;
+import org.apache.ignite.spi.discovery.tcp.internal.*;
+import org.apache.ignite.webVisor.*;
+import org.jetbrains.annotations.*;
+
+/**
+ *
+ */
+public class WU {
+ /** */
+ private final Ignite g;
+
+ /**
+ * @param g G.
+ */
+ public WU(Ignite g) {
+ this.g = g;
+ }
+
+ /**
+ * @param node Node.
+ */
+ public String nodeAddr(ClusterNode node) {
+ String host = WebVisorUtils.hostname(node);
+
+ if (!node.isClient() && node instanceof TcpDiscoveryNode)
+ return host + ':' + ((TcpDiscoveryNode)node).discoveryPort();
+
+ return host;
+ }
+
+ /**
+ * @param node Node.
+ */
+ @Nullable public String visorUrl(ClusterNode node) {
+ Integer port = node.attribute(WebVisorUtils.WEB_VISOR_NODE_PORT);
+
+ if (port == null)
+ return null;
+
+ String uri = node.attribute(WebVisorUtils.WEB_VISOR_NODE_URI);
+
+ return "http://" + WebVisorUtils.hostname(node) + ':' + port + (uri == null ? "" : uri);
+ }
+
+ /**
+ *
+ */
+ public ClusterNode localNode() {
+ return g.cluster().localNode();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/c7a8427d/modules/webVisor/src/main/resources/META-INF/services/org.apache.ignite.plugin.PluginProvider
----------------------------------------------------------------------
diff --git a/modules/webVisor/src/main/resources/META-INF/services/org.apache.ignite.plugin.PluginProvider b/modules/webVisor/src/main/resources/META-INF/services/org.apache.ignite.plugin.PluginProvider
new file mode 100644
index 0000000..4834987
--- /dev/null
+++ b/modules/webVisor/src/main/resources/META-INF/services/org.apache.ignite.plugin.PluginProvider
@@ -0,0 +1 @@
+org.apache.ignite.webVisor.WebVisorPluginProvider
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/c7a8427d/modules/webVisor/src/main/webapp/WEB-INF/sitemesh3.xml
----------------------------------------------------------------------
diff --git a/modules/webVisor/src/main/webapp/WEB-INF/sitemesh3.xml b/modules/webVisor/src/main/webapp/WEB-INF/sitemesh3.xml
new file mode 100644
index 0000000..6e432b1
--- /dev/null
+++ b/modules/webVisor/src/main/webapp/WEB-INF/sitemesh3.xml
@@ -0,0 +1,3 @@
+<sitemesh>
+ <mapping path="/*" decorator="/decorator.jsp"/>
+</sitemesh>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/c7a8427d/modules/webVisor/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/modules/webVisor/src/main/webapp/WEB-INF/web.xml b/modules/webVisor/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..6fc8fb4
--- /dev/null
+++ b/modules/webVisor/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<web-app version="2.4"
+ xmlns="http://java.sun.com/xml/ns/j2ee">
+ <welcome-file-list>
+ <welcome-file>nodeInfo.jsp</welcome-file>
+ </welcome-file-list>
+
+ <filter>
+ <filter-name>sitemesh</filter-name>
+ <filter-class>org.sitemesh.config.ConfigurableSiteMeshFilter</filter-class>
+ </filter>
+
+ <filter>
+ <filter-name>nodeSwitch</filter-name>
+ <filter-class>org.apache.ignite.webVisor.NodeSwitchFilter</filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>sitemesh</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <filter-mapping>
+ <filter-name>nodeSwitch</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+</web-app>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/c7a8427d/modules/webVisor/src/main/webapp/caches.jsp
----------------------------------------------------------------------
diff --git a/modules/webVisor/src/main/webapp/caches.jsp b/modules/webVisor/src/main/webapp/caches.jsp
new file mode 100644
index 0000000..f493f7b
--- /dev/null
+++ b/modules/webVisor/src/main/webapp/caches.jsp
@@ -0,0 +1,15 @@
+<%--@elvariable id="g" type="org.apache.ignite.Ignite"--%>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <title>Caches</title>
+</head>
+<body>
+
+<h2>Caches</h2>
+
+In development
+
+</body>
+</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/c7a8427d/modules/webVisor/src/main/webapp/cluster.jsp
----------------------------------------------------------------------
diff --git a/modules/webVisor/src/main/webapp/cluster.jsp b/modules/webVisor/src/main/webapp/cluster.jsp
new file mode 100644
index 0000000..9aa895b
--- /dev/null
+++ b/modules/webVisor/src/main/webapp/cluster.jsp
@@ -0,0 +1,52 @@
+<%--@elvariable id="g" type="org.apache.ignite.Ignite"--%>
+<%--@elvariable id="wu" type="org.apache.ignite.webVisor.render.WU"--%>
+<%@ page import="org.apache.ignite.webVisor.render.*" %>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+<!DOCTYPE html>
+<html lang="en">
+<% ClusterPage p = new ClusterPage(request); %>
+<%--@elvariable id="p" type="org.apache.ignite.webVisor.render.ClusterPage"--%>
+<head>
+ <title>${wu.nodeAddr(p.localNode)}: Cluster</title>
+
+ <link rel="stylesheet" href="css/cluster.css" type="text/css">
+</head>
+<body>
+
+<h2>Nodes in the cluster</h2>
+
+<div class="row">
+ <div class="col-md-6">
+ <c:forEach items="${p.nodes}" var="node">
+ <%--@elvariable id="node" type="org.apache.ignite.spi.discovery.tcp.internal.TcpDiscoveryNode"--%>
+ <div class="cluster-node">
+ <span class="glyphicon ${node.client ? 'glyphicon-phone' : 'glyphicon-hdd'}"
+ aria-hidden="true"
+ title="${node.client ? 'Client node' : 'Server node'}"></span>
+
+ <strong>${wu.nodeAddr(node)}</strong> <br>
+ <small><span class="uuid">${node.id()}</span></small>
+ </div>
+ </c:forEach>
+ </div>
+
+ <div class="col-md-2">
+
+ </div>
+
+ <div class="col-md-4">
+ <h4>Filters</h4>
+
+ <form role="form" action="cluster.jsp">
+ <input type="hidden" name="filter" value="true">
+
+ <div class="checkbox">
+ <label><input type="checkbox" name="showClients" <%= p.isShowClients() ? "checked=checked" : "" %> onchange="submit()">Show clients</label>
+ </div>
+ </form>
+ </div>
+</div>
+
+
+</body>
+</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/c7a8427d/modules/webVisor/src/main/webapp/css/cluster.css
----------------------------------------------------------------------
diff --git a/modules/webVisor/src/main/webapp/css/cluster.css b/modules/webVisor/src/main/webapp/css/cluster.css
new file mode 100644
index 0000000..1efecfe
--- /dev/null
+++ b/modules/webVisor/src/main/webapp/css/cluster.css
@@ -0,0 +1,10 @@
+.cluster-node {
+ padding: 3px;
+ margin-top: 20px;
+
+ border-radius: 4px;
+}
+
+.cluster-node .uuid {
+ color: gray;
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/c7a8427d/modules/webVisor/src/main/webapp/css/main.css
----------------------------------------------------------------------
diff --git a/modules/webVisor/src/main/webapp/css/main.css b/modules/webVisor/src/main/webapp/css/main.css
new file mode 100644
index 0000000..2b2482c
--- /dev/null
+++ b/modules/webVisor/src/main/webapp/css/main.css
@@ -0,0 +1,3 @@
+.value {
+ font-weight: bold;
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/c7a8427d/modules/webVisor/src/main/webapp/decorator.jsp
----------------------------------------------------------------------
diff --git a/modules/webVisor/src/main/webapp/decorator.jsp b/modules/webVisor/src/main/webapp/decorator.jsp
new file mode 100644
index 0000000..a5b1f8e
--- /dev/null
+++ b/modules/webVisor/src/main/webapp/decorator.jsp
@@ -0,0 +1,59 @@
+<%--@elvariable id="g" type="org.apache.ignite.Ignite"--%>
+<%--@elvariable id="wu" type="org.apache.ignite.webVisor.render.WU"--%>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
+ <title><sitemesh:write property='title'/></title>
+
+ <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
+
+ <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
+ <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
+ <!--[if lt IE 9]>
+ <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
+ <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
+ <![endif]-->
+
+ <link rel="stylesheet" href="css/main.css" type="text/css">
+
+ <sitemesh:write property='head'/>
+</head>
+<body>
+<nav class="navbar navbar-default">
+ <div class="container">
+ <div class="navbar-header">
+ <a class="navbar-brand" href="${pageContext.request.contextPath}/">Ignite</a>
+ </div>
+ <div>
+ <ul class="nav navbar-nav">
+ <li><a href="nodeInfo.jsp">Node</a></li>
+ <li><a href="cluster.jsp">Cluster</a></li>
+ <li><a href="caches.jsp">Caches</a></li>
+ </ul>
+ <ul class="nav navbar-nav navbar-right">
+ <li style="color: gray">
+ <small>Local node: ${wu.nodeAddr(wu.localNode())}</small>
+
+ <c:if test="${g.name() != null}">
+ <br> <small>Name: ${g.name()}</small>
+ </c:if>
+ </li>
+ </ul>
+ </div>
+ </div>
+</nav>
+
+<div class="container">
+ <sitemesh:write property='body'/>
+</div>
+
+<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
+<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
+<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
+</body>
+</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/c7a8427d/modules/webVisor/src/main/webapp/igniteNotFound.jsp
----------------------------------------------------------------------
diff --git a/modules/webVisor/src/main/webapp/igniteNotFound.jsp b/modules/webVisor/src/main/webapp/igniteNotFound.jsp
new file mode 100644
index 0000000..8e6b6f6
--- /dev/null
+++ b/modules/webVisor/src/main/webapp/igniteNotFound.jsp
@@ -0,0 +1,14 @@
+<%--@elvariable id="g" type="org.apache.ignite.Ignite"--%>
+<%--@elvariable id="wu" type="org.apache.ignite.webVisor.render.WU"--%>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <title>Ignite not found</title>
+</head>
+<body>
+
+Ignite not found
+
+</body>
+</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/c7a8427d/modules/webVisor/src/main/webapp/moreThenOneIgnite.jsp
----------------------------------------------------------------------
diff --git a/modules/webVisor/src/main/webapp/moreThenOneIgnite.jsp b/modules/webVisor/src/main/webapp/moreThenOneIgnite.jsp
new file mode 100644
index 0000000..0c3693f
--- /dev/null
+++ b/modules/webVisor/src/main/webapp/moreThenOneIgnite.jsp
@@ -0,0 +1,14 @@
+<%--@elvariable id="g" type="org.apache.ignite.Ignite"--%>
+<%--@elvariable id="wu" type="org.apache.ignite.webVisor.render.WU"--%>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <title>Error</title>
+</head>
+<body>
+
+More then one Ignite found with id8=${igniteId8}
+
+</body>
+</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/c7a8427d/modules/webVisor/src/main/webapp/noIgnitesFound.jsp
----------------------------------------------------------------------
diff --git a/modules/webVisor/src/main/webapp/noIgnitesFound.jsp b/modules/webVisor/src/main/webapp/noIgnitesFound.jsp
new file mode 100644
index 0000000..176d253
--- /dev/null
+++ b/modules/webVisor/src/main/webapp/noIgnitesFound.jsp
@@ -0,0 +1,14 @@
+<%--@elvariable id="g" type="org.apache.ignite.Ignite"--%>
+<%--@elvariable id="wu" type="org.apache.ignite.webVisor.render.WU"--%>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <title>Ignite no ignites run in JVM</title>
+</head>
+<body>
+
+Ignite no ignites run in JVM
+
+</body>
+</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/c7a8427d/modules/webVisor/src/main/webapp/nodeInfo.jsp
----------------------------------------------------------------------
diff --git a/modules/webVisor/src/main/webapp/nodeInfo.jsp b/modules/webVisor/src/main/webapp/nodeInfo.jsp
new file mode 100644
index 0000000..89e1d7f
--- /dev/null
+++ b/modules/webVisor/src/main/webapp/nodeInfo.jsp
@@ -0,0 +1,19 @@
+<%--@elvariable id="g" type="org.apache.ignite.Ignite"--%>
+<%--@elvariable id="wu" type="org.apache.ignite.webVisor.render.WU"--%>
+<%@ page import="org.apache.ignite.webVisor.render.*" %>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+<!DOCTYPE html>
+<html lang="en">
+<% NodeInfoPage p = new NodeInfoPage(request); %>
+<%--@elvariable id="p" type="org.apache.ignite.webVisor.render.NodeInfoPage"--%>
+<head>
+ <title>${wu.nodeAddr(p.localNode)}: Cluster</title>
+
+ <%--<link rel="stylesheet" href="css/cluster.css" type="text/css">--%>
+</head>
+<body>
+
+In development
+
+</body>
+</html>
\ No newline at end of file