You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ag...@apache.org on 2017/02/13 12:31:41 UTC
[08/12] ignite git commit: IGNITE-4687 Added pool to process REST
request in Web Agent.
IGNITE-4687 Added pool to process REST request in Web Agent.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/262a3410
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/262a3410
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/262a3410
Branch: refs/heads/ignite-4003
Commit: 262a3410802de790b75de9b94fea9599b30171bd
Parents: 0ace63c
Author: Andrey Novikov <an...@gridgain.com>
Authored: Mon Feb 13 17:35:29 2017 +0700
Committer: Andrey Novikov <an...@gridgain.com>
Committed: Mon Feb 13 17:35:29 2017 +0700
----------------------------------------------------------------------
.../ignite/console/agent/AgentLauncher.java | 203 ++++++------
.../apache/ignite/console/agent/AgentUtils.java | 80 +++++
.../console/agent/handlers/AbstractHandler.java | 110 -------
.../agent/handlers/AbstractListener.java | 104 ++++++
.../console/agent/handlers/DatabaseHandler.java | 298 -----------------
.../agent/handlers/DatabaseListener.java | 316 +++++++++++++++++++
.../console/agent/handlers/RestHandler.java | 276 ----------------
.../console/agent/handlers/RestListener.java | 280 ++++++++++++++++
8 files changed, 880 insertions(+), 787 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/262a3410/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/AgentLauncher.java
----------------------------------------------------------------------
diff --git a/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/AgentLauncher.java b/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/AgentLauncher.java
index 049791f..a3d609f 100644
--- a/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/AgentLauncher.java
+++ b/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/AgentLauncher.java
@@ -41,8 +41,8 @@ import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
-import org.apache.ignite.console.agent.handlers.DatabaseHandler;
-import org.apache.ignite.console.agent.handlers.RestHandler;
+import org.apache.ignite.console.agent.handlers.DatabaseListener;
+import org.apache.ignite.console.agent.handlers.RestListener;
import org.apache.ignite.internal.util.typedef.X;
import org.apache.log4j.Logger;
import org.json.JSONException;
@@ -278,141 +278,138 @@ public class AgentLauncher {
cfg.tokens(Arrays.asList(tokens.trim().split(",")));
}
- final RestHandler restHnd = new RestHandler(cfg);
+ URI uri = URI.create(cfg.serverUri());
- try {
- restHnd.start();
+ // Create proxy authenticator using passed properties.
+ switch (uri.getScheme()) {
+ case "http":
+ case "https":
+ final String username = System.getProperty(uri.getScheme() + ".proxyUsername");
+ final char[] pwd = System.getProperty(uri.getScheme() + ".proxyPassword", "").toCharArray();
- URI uri = URI.create(cfg.serverUri());
+ Authenticator.setDefault(new Authenticator() {
+ @Override protected PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication(username, pwd);
+ }
+ });
- // Create proxy authenticator using passed properties.
- switch (uri.getScheme()) {
- case "http":
- case "https":
- final String username = System.getProperty(uri.getScheme() + ".proxyUsername");
- final char[] pwd = System.getProperty(uri.getScheme() + ".proxyPassword", "").toCharArray();
+ break;
- Authenticator.setDefault(new Authenticator() {
- @Override protected PasswordAuthentication getPasswordAuthentication() {
- return new PasswordAuthentication(username, pwd);
- }
- });
-
- break;
+ default:
+ // No-op.
+ }
- default:
- // No-op.
- }
+ IO.Options opts = new IO.Options();
- IO.Options opts = new IO.Options();
+ opts.path = "/agents";
- opts.path = "/agents";
+ // Workaround for use self-signed certificate
+ if (Boolean.getBoolean("trust.all")) {
+ SSLContext ctx = SSLContext.getInstance("TLS");
- // Workaround for use self-signed certificate
- if (Boolean.getBoolean("trust.all")) {
- SSLContext ctx = SSLContext.getInstance("TLS");
+ // Create an SSLContext that uses our TrustManager
+ ctx.init(null, getTrustManagers(), null);
- // Create an SSLContext that uses our TrustManager
- ctx.init(null, getTrustManagers(), null);
+ opts.sslContext = ctx;
+ }
- opts.sslContext = ctx;
- }
+ final Socket client = IO.socket(uri, opts);
- final Socket client = IO.socket(uri, opts);
+ final RestListener restHnd = new RestListener(cfg);
- try {
- Emitter.Listener onConnecting = new Emitter.Listener() {
- @Override public void call(Object... args) {
- log.info("Connecting to: " + cfg.serverUri());
- }
- };
+ final DatabaseListener dbHnd = new DatabaseListener(cfg);
- Emitter.Listener onConnect = new Emitter.Listener() {
- @Override public void call(Object... args) {
- log.info("Connection established.");
+ try {
+ Emitter.Listener onConnecting = new Emitter.Listener() {
+ @Override public void call(Object... args) {
+ log.info("Connecting to: " + cfg.serverUri());
+ }
+ };
- JSONObject authMsg = new JSONObject();
+ Emitter.Listener onConnect = new Emitter.Listener() {
+ @Override public void call(Object... args) {
+ log.info("Connection established.");
- try {
- authMsg.put("tokens", cfg.tokens());
+ JSONObject authMsg = new JSONObject();
- String clsName = AgentLauncher.class.getSimpleName() + ".class";
+ try {
+ authMsg.put("tokens", cfg.tokens());
- String clsPath = AgentLauncher.class.getResource(clsName).toString();
+ String clsName = AgentLauncher.class.getSimpleName() + ".class";
- if (clsPath.startsWith("jar")) {
- String manifestPath = clsPath.substring(0, clsPath.lastIndexOf('!') + 1) +
- "/META-INF/MANIFEST.MF";
+ String clsPath = AgentLauncher.class.getResource(clsName).toString();
- Manifest manifest = new Manifest(new URL(manifestPath).openStream());
+ if (clsPath.startsWith("jar")) {
+ String manifestPath = clsPath.substring(0, clsPath.lastIndexOf('!') + 1) +
+ "/META-INF/MANIFEST.MF";
- Attributes attr = manifest.getMainAttributes();
+ Manifest manifest = new Manifest(new URL(manifestPath).openStream());
- authMsg.put("ver", attr.getValue("Implementation-Version"));
- authMsg.put("bt", attr.getValue("Build-Time"));
- }
+ Attributes attr = manifest.getMainAttributes();
- client.emit("agent:auth", authMsg, new Ack() {
- @Override public void call(Object... args) {
- // Authentication failed if response contains args.
- if (args != null && args.length > 0) {
- onDisconnect.call(args);
+ authMsg.put("ver", attr.getValue("Implementation-Version"));
+ authMsg.put("bt", attr.getValue("Build-Time"));
+ }
- System.exit(1);
- }
+ client.emit("agent:auth", authMsg, new Ack() {
+ @Override public void call(Object... args) {
+ // Authentication failed if response contains args.
+ if (args != null && args.length > 0) {
+ onDisconnect.call(args);
- log.info("Authentication success.");
+ System.exit(1);
}
- });
- }
- catch (JSONException | IOException e) {
- log.error("Failed to construct authentication message", e);
- client.close();
- }
+ log.info("Authentication success.");
+ }
+ });
}
- };
-
- DatabaseHandler dbHnd = new DatabaseHandler(cfg);
-
- final CountDownLatch latch = new CountDownLatch(1);
-
- client
- .on(EVENT_CONNECTING, onConnecting)
- .on(EVENT_CONNECT, onConnect)
- .on(EVENT_CONNECT_ERROR, onError)
- .on(EVENT_RECONNECTING, onConnecting)
- .on(EVENT_NODE_REST, restHnd)
- .on(EVENT_SCHEMA_IMPORT_DRIVERS, dbHnd.availableDriversListener())
- .on(EVENT_SCHEMA_IMPORT_SCHEMAS, dbHnd.schemasListener())
- .on(EVENT_SCHEMA_IMPORT_METADATA, dbHnd.metadataListener())
- .on(EVENT_ERROR, onError)
- .on(EVENT_DISCONNECT, onDisconnect)
- .on(EVENT_AGENT_WARNING, new Emitter.Listener() {
- @Override public void call(Object... args) {
- log.warn(args[0]);
- }
- })
- .on(EVENT_AGENT_CLOSE, new Emitter.Listener() {
- @Override public void call(Object... args) {
- onDisconnect.call(args);
+ catch (JSONException | IOException e) {
+ log.error("Failed to construct authentication message", e);
+
+ client.close();
+ }
+ }
+ };
+
+ final CountDownLatch latch = new CountDownLatch(1);
+
+ client
+ .on(EVENT_CONNECTING, onConnecting)
+ .on(EVENT_CONNECT, onConnect)
+ .on(EVENT_CONNECT_ERROR, onError)
+ .on(EVENT_RECONNECTING, onConnecting)
+ .on(EVENT_NODE_REST, restHnd)
+ .on(EVENT_SCHEMA_IMPORT_DRIVERS, dbHnd.availableDriversListener())
+ .on(EVENT_SCHEMA_IMPORT_SCHEMAS, dbHnd.schemasListener())
+ .on(EVENT_SCHEMA_IMPORT_METADATA, dbHnd.metadataListener())
+ .on(EVENT_ERROR, onError)
+ .on(EVENT_DISCONNECT, onDisconnect)
+ .on(EVENT_AGENT_WARNING, new Emitter.Listener() {
+ @Override public void call(Object... args) {
+ log.warn(args[0]);
+ }
+ })
+ .on(EVENT_AGENT_CLOSE, new Emitter.Listener() {
+ @Override public void call(Object... args) {
+ onDisconnect.call(args);
- client.off();
+ client.off();
- latch.countDown();
- }
- });
+ latch.countDown();
+ }
+ });
- client.connect();
+ client.connect();
- latch.await();
- }
- finally {
- client.close();
- }
+ latch.await();
}
finally {
+ client.close();
+
restHnd.stop();
+
+ dbHnd.stop();
}
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/262a3410/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/AgentUtils.java
----------------------------------------------------------------------
diff --git a/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/AgentUtils.java b/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/AgentUtils.java
index 50a849a..cb22651 100644
--- a/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/AgentUtils.java
+++ b/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/AgentUtils.java
@@ -17,11 +17,19 @@
package org.apache.ignite.console.agent;
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.jsonorg.JsonOrgModule;
+import io.socket.client.Ack;
import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.ProtectionDomain;
+import java.util.Arrays;
import org.apache.log4j.Logger;
+import org.json.JSONArray;
+import org.json.JSONObject;
/**
* Utility methods.
@@ -30,6 +38,28 @@ public class AgentUtils {
/** */
private static final Logger log = Logger.getLogger(AgentUtils.class.getName());
+ /** JSON object mapper. */
+ private static final ObjectMapper mapper = new ObjectMapper();
+
+ /** */
+ private static final Ack NOOP_CB = new Ack() {
+ @Override public void call(Object... args) {
+ if (args != null && args.length > 0 && args[0] instanceof Throwable)
+ log.error("Failed to execute request on agent.", (Throwable) args[0]);
+ else
+ log.info("Request on agent successfully executed " + Arrays.toString(args));
+ }
+ };
+
+ static {
+ JsonOrgModule module = new JsonOrgModule();
+
+ mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
+ mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
+
+ mapper.registerModule(module);
+ }
+
/**
* Default constructor.
*/
@@ -108,4 +138,54 @@ public class AgentUtils {
return null;
}
+
+ /**
+ * Get callback from handler arguments.
+ *
+ * @param args Arguments.
+ * @return Callback or noop callback.
+ */
+ public static Ack safeCallback(Object[] args) {
+ boolean hasCb = args != null && args.length > 0 && args[args.length - 1] instanceof Ack;
+
+ return hasCb ? (Ack)args[args.length - 1] : NOOP_CB;
+ }
+
+ /**
+ * Remove callback from handler arguments.
+ *
+ * @param args Arguments.
+ * @return Arguments without callback.
+ */
+ public static Object[] removeCallback(Object[] args) {
+ boolean hasCb = args != null && args.length > 0 && args[args.length - 1] instanceof Ack;
+
+ return hasCb ? Arrays.copyOf(args, args.length - 1) : args;
+ }
+
+ /**
+ * Map java object to JSON object.
+ *
+ * @param obj Java object.
+ * @return {@link JSONObject} or {@link JSONArray}.
+ * @throws IllegalArgumentException If conversion fails due to incompatible type.
+ */
+ public static Object toJSON(Object obj) {
+ if (obj instanceof Iterable)
+ return mapper.convertValue(obj, JSONArray.class);
+
+ return mapper.convertValue(obj, JSONObject.class);
+ }
+
+ /**
+ * Map JSON object to java object.
+ *
+ * @param obj {@link JSONObject} or {@link JSONArray}.
+ * @param toValType Expected value type.
+ * @return Mapped object type of {@link T}.
+ * @throws IllegalArgumentException If conversion fails due to incompatible type.
+ */
+ public static <T> T fromJSON(Object obj, Class<T> toValType) throws IllegalArgumentException {
+ return mapper.convertValue(obj, toValType);
+ }
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/262a3410/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/AbstractHandler.java
----------------------------------------------------------------------
diff --git a/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/AbstractHandler.java b/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/AbstractHandler.java
deleted file mode 100644
index 7e4e320..0000000
--- a/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/AbstractHandler.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * 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.console.agent.handlers;
-
-import com.fasterxml.jackson.annotation.JsonAutoDetect;
-import com.fasterxml.jackson.annotation.PropertyAccessor;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.datatype.jsonorg.JsonOrgModule;
-import io.socket.client.Ack;
-import io.socket.emitter.Emitter;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Map;
-import org.json.JSONArray;
-import org.json.JSONObject;
-
-/**
- * Base class for web socket handlers.
- */
-abstract class AbstractHandler implements Emitter.Listener {
- /** JSON object mapper. */
- private static final ObjectMapper mapper = new ObjectMapper();
-
- static {
- JsonOrgModule module = new JsonOrgModule();
-
- mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
- mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
-
- mapper.registerModule(module);
- }
-
- /**
- * @param obj Object.
- * @return {@link JSONObject} or {@link JSONArray}.
- */
- private Object toJSON(Object obj) {
- if (obj instanceof Iterable)
- return mapper.convertValue(obj, JSONArray.class);
-
- return mapper.convertValue(obj, JSONObject.class);
- }
-
- /** {@inheritDoc} */
- @SuppressWarnings("unchecked")
- @Override public final void call(Object... args) {
- Ack cb = null;
-
- try {
- if (args == null || args.length == 0)
- throw new IllegalArgumentException("Missing arguments.");
-
- if (args.length > 2)
- throw new IllegalArgumentException("Wrong arguments count, must be <= 2: " + Arrays.toString(args));
-
- JSONObject lsnrArgs = null;
-
- if (args.length == 1) {
- if (args[0] instanceof JSONObject)
- lsnrArgs = (JSONObject)args[0];
- else if (args[0] instanceof Ack)
- cb = (Ack)args[0];
- else
- throw new IllegalArgumentException("Wrong type of argument, must be JSONObject or Ack: " + args[0]);
- }
- else {
- if (args[0] != null && !(args[0] instanceof JSONObject))
- throw new IllegalArgumentException("Wrong type of argument, must be JSONObject: " + args[0]);
-
- if (!(args[1] instanceof Ack))
- throw new IllegalArgumentException("Wrong type of argument, must be Ack: " + args[1]);
-
- lsnrArgs = (JSONObject)args[0];
-
- cb = (Ack)args[1];
- }
-
- Object res = execute(lsnrArgs == null ? Collections.emptyMap() : mapper.convertValue(lsnrArgs, Map.class));
-
- if (cb != null)
- cb.call(null, toJSON(res));
- }
- catch (Exception e) {
- if (cb != null)
- cb.call(e, null);
- }
- }
-
- /**
- * Execute command with specified arguments.
- *
- * @param args Map with method args.
- */
- public abstract Object execute(Map<String, Object> args) throws Exception;
-}
http://git-wip-us.apache.org/repos/asf/ignite/blob/262a3410/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/AbstractListener.java
----------------------------------------------------------------------
diff --git a/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/AbstractListener.java b/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/AbstractListener.java
new file mode 100644
index 0000000..987dac9
--- /dev/null
+++ b/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/AbstractListener.java
@@ -0,0 +1,104 @@
+/*
+ * 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.console.agent.handlers;
+
+import io.socket.client.Ack;
+import io.socket.emitter.Emitter;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import org.apache.log4j.Logger;
+
+import static org.apache.ignite.console.agent.AgentUtils.removeCallback;
+import static org.apache.ignite.console.agent.AgentUtils.fromJSON;
+import static org.apache.ignite.console.agent.AgentUtils.safeCallback;
+import static org.apache.ignite.console.agent.AgentUtils.toJSON;
+
+/**
+ * Base class for web socket handlers.
+ */
+abstract class AbstractListener implements Emitter.Listener {
+ /** */
+ private ExecutorService pool;
+
+ /** */
+ final Logger log = Logger.getLogger(this.getClass().getName());
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ @Override public final void call(Object... args) {
+ final Ack cb = safeCallback(args);
+
+ args = removeCallback(args);
+
+ try {
+ final Map<String, Object> params;
+
+ if (args == null || args.length == 0)
+ params = Collections.emptyMap();
+ else if (args.length == 1)
+ params = fromJSON(args[0], Map.class);
+ else
+ throw new IllegalArgumentException("Wrong arguments count, must be <= 1: " + Arrays.toString(args));
+
+ if (pool == null)
+ pool = newThreadPool();
+
+ pool.submit(new Runnable() {
+ @Override public void run() {
+ try {
+ Object res = execute(params);
+
+ cb.call(null, toJSON(res));
+ } catch (Exception e) {
+ cb.call(e, null);
+ }
+ }
+ });
+ }
+ catch (Exception e) {
+ cb.call(e, null);
+ }
+ }
+
+ /**
+ * Stop handler.
+ */
+ public void stop() {
+ if (pool != null)
+ pool.shutdownNow();
+ }
+
+ /**
+ * Creates a thread pool that can schedule commands to run after a given delay, or to execute periodically.
+ *
+ * @return Newly created thread pool.
+ */
+ protected ExecutorService newThreadPool() {
+ return Executors.newSingleThreadExecutor();
+ }
+
+ /**
+ * Execute command with specified arguments.
+ *
+ * @param args Map with method args.
+ */
+ public abstract Object execute(Map<String, Object> args) throws Exception;
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/262a3410/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/DatabaseHandler.java
----------------------------------------------------------------------
diff --git a/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/DatabaseHandler.java b/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/DatabaseHandler.java
deleted file mode 100644
index 02146d9..0000000
--- a/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/DatabaseHandler.java
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * 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.console.agent.handlers;
-
-import io.socket.emitter.Emitter;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.net.URL;
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import org.apache.ignite.console.agent.AgentConfiguration;
-import org.apache.ignite.console.demo.AgentMetadataDemo;
-import org.apache.ignite.schema.parser.DbMetadataReader;
-import org.apache.ignite.schema.parser.DbTable;
-import org.apache.log4j.Logger;
-
-import static org.apache.ignite.console.agent.AgentUtils.resolvePath;
-
-/**
- * API to extract database metadata.
- */
-public class DatabaseHandler {
- /** */
- private static final Logger log = Logger.getLogger(DatabaseHandler.class.getName());
-
- /** */
- private final File driversFolder;
-
- /**
- * @param cfg Config.
- */
- public DatabaseHandler(AgentConfiguration cfg) {
- driversFolder = resolvePath(cfg.driversFolder() == null ? "jdbc-drivers" : cfg.driversFolder());
- }
-
- /**
- * @param jdbcDriverJarPath JDBC driver JAR path.
- * @param jdbcDriverCls JDBC driver class.
- * @param jdbcUrl JDBC URL.
- * @param jdbcInfo Properties to connect to database.
- * @return Connection to database.
- * @throws SQLException
- */
- private Connection connect(String jdbcDriverJarPath, String jdbcDriverCls, String jdbcUrl,
- Properties jdbcInfo) throws SQLException {
- if (AgentMetadataDemo.isTestDriveUrl(jdbcUrl))
- return AgentMetadataDemo.testDrive();
-
- if (!new File(jdbcDriverJarPath).isAbsolute() && driversFolder != null)
- jdbcDriverJarPath = new File(driversFolder, jdbcDriverJarPath).getPath();
-
- return DbMetadataReader.getInstance().connect(jdbcDriverJarPath, jdbcDriverCls, jdbcUrl, jdbcInfo);
- }
-
- /**
- * @param jdbcDriverJarPath JDBC driver JAR path.
- * @param jdbcDriverCls JDBC driver class.
- * @param jdbcUrl JDBC URL.
- * @param jdbcInfo Properties to connect to database.
- * @return Collection of schema names.
- * @throws SQLException
- */
- protected Collection<String> schemas(String jdbcDriverJarPath, String jdbcDriverCls, String jdbcUrl,
- Properties jdbcInfo) throws SQLException {
- if (log.isDebugEnabled())
- log.debug("Start collecting database schemas [drvJar=" + jdbcDriverJarPath +
- ", drvCls=" + jdbcDriverCls + ", jdbcUrl=" + jdbcUrl + "]");
-
- try (Connection conn = connect(jdbcDriverJarPath, jdbcDriverCls, jdbcUrl, jdbcInfo)) {
- Collection<String> schemas = DbMetadataReader.getInstance().schemas(conn);
-
- if (log.isDebugEnabled())
- log.debug("Finished collection of schemas [jdbcUrl=" + jdbcUrl + ", count=" + schemas.size() + "]");
-
- return schemas;
- }
- catch (Throwable e) {
- log.error("Failed to collect schemas", e);
-
- throw new SQLException("Failed to collect schemas", e);
- }
- }
-
- /**
- * Listener for schema names.
- *
- * @return Collection of schema names.
- */
- public Emitter.Listener schemasListener() {
- return new AbstractHandler() {
- @Override public Object execute(Map<String, Object> args) throws Exception {
- String driverPath = null;
-
- if (args.containsKey("driverPath"))
- driverPath = args.get("driverPath").toString();
-
- if (!args.containsKey("driverClass"))
- throw new IllegalArgumentException("Missing driverClass in arguments: " + args);
-
- String driverCls = args.get("driverClass").toString();
-
- if (!args.containsKey("url"))
- throw new IllegalArgumentException("Missing url in arguments: " + args);
-
- String url = args.get("url").toString();
-
- if (!args.containsKey("info"))
- throw new IllegalArgumentException("Missing info in arguments: " + args);
-
- Properties info = new Properties();
-
- info.putAll((Map)args.get("info"));
-
- return schemas(driverPath, driverCls, url, info);
- }
- };
- }
-
- /**
- * @param jdbcDriverJarPath JDBC driver JAR path.
- * @param jdbcDriverCls JDBC driver class.
- * @param jdbcUrl JDBC URL.
- * @param jdbcInfo Properties to connect to database.
- * @param schemas List of schema names to process.
- * @param tblsOnly If {@code true} then only tables will be processed otherwise views also will be processed.
- * @return Collection of tables.
- */
- protected Collection<DbTable> metadata(String jdbcDriverJarPath, String jdbcDriverCls, String jdbcUrl,
- Properties jdbcInfo, List<String> schemas, boolean tblsOnly) throws SQLException {
- if (log.isDebugEnabled())
- log.debug("Start collecting database metadata [drvJar=" + jdbcDriverJarPath +
- ", drvCls=" + jdbcDriverCls + ", jdbcUrl=" + jdbcUrl + "]");
-
- try (Connection conn = connect(jdbcDriverJarPath, jdbcDriverCls, jdbcUrl, jdbcInfo)) {
- Collection<DbTable> metadata = DbMetadataReader.getInstance().metadata(conn, schemas, tblsOnly);
-
- if (log.isDebugEnabled())
- log.debug("Finished collection of metadata [jdbcUrl=" + jdbcUrl + ", count=" + metadata.size() + "]");
-
- return metadata;
- }
- catch (Throwable e) {
- log.error("Failed to collect metadata", e);
-
- throw new SQLException("Failed to collect metadata", e);
- }
- }
-
- /**
- * Listener for tables.
- *
- * @return Collection of tables.
- */
- public Emitter.Listener metadataListener() {
- return new AbstractHandler() {
- @SuppressWarnings("unchecked")
- @Override public Object execute(Map<String, Object> args) throws Exception {
- String driverPath = null;
-
- if (args.containsKey("driverPath"))
- driverPath = args.get("driverPath").toString();
-
- if (!args.containsKey("driverClass"))
- throw new IllegalArgumentException("Missing driverClass in arguments: " + args);
-
- String driverCls = args.get("driverClass").toString();
-
- if (!args.containsKey("url"))
- throw new IllegalArgumentException("Missing url in arguments: " + args);
-
- String url = args.get("url").toString();
-
- if (!args.containsKey("info"))
- throw new IllegalArgumentException("Missing info in arguments: " + args);
-
- Properties info = new Properties();
-
- info.putAll((Map)args.get("info"));
-
- if (!args.containsKey("schemas"))
- throw new IllegalArgumentException("Missing schemas in arguments: " + args);
-
- List<String> schemas = (List<String>)args.get("schemas");
-
- if (!args.containsKey("tablesOnly"))
- throw new IllegalArgumentException("Missing tablesOnly in arguments: " + args);
-
- boolean tblsOnly = (boolean)args.get("tablesOnly");
-
- return metadata(driverPath, driverCls, url, info, schemas, tblsOnly);
- }
- };
- }
-
- /**
- * Listener for drivers.
- *
- * @return Drivers in drivers folder
- * @see AgentConfiguration#driversFolder
- */
- public Emitter.Listener availableDriversListener() {
- return new AbstractHandler() {
- @Override public Object execute(Map<String, Object> args) throws Exception {
- if (driversFolder == null) {
- log.info("JDBC drivers folder not specified, returning empty list");
-
- return Collections.emptyList();
- }
-
- if (log.isDebugEnabled())
- log.debug("Collecting JDBC drivers in folder: " + driversFolder.getPath());
-
- File[] list = driversFolder.listFiles(new FilenameFilter() {
- @Override public boolean accept(File dir, String name) {
- return name.endsWith(".jar");
- }
- });
-
- if (list == null) {
- log.info("JDBC drivers folder has no files, returning empty list");
-
- return Collections.emptyList();
- }
-
- List<JdbcDriver> res = new ArrayList<>();
-
- for (File file : list) {
- try {
- boolean win = System.getProperty("os.name").contains("win");
-
- URL url = new URL("jar", null,
- "file:" + (win ? "/" : "") + file.getPath() + "!/META-INF/services/java.sql.Driver");
-
- try (BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()))) {
- String jdbcDriverCls = reader.readLine();
-
- res.add(new JdbcDriver(file.getName(), jdbcDriverCls));
-
- if (log.isDebugEnabled())
- log.debug("Found: [driver=" + file + ", class=" + jdbcDriverCls + "]");
- }
- }
- catch (IOException e) {
- res.add(new JdbcDriver(file.getName(), null));
-
- log.info("Found: [driver=" + file + "]");
- log.info("Failed to detect driver class: " + e.getMessage());
- }
- }
-
- return res;
- }
- };
- }
-
- /**
- * Wrapper class for later to be transformed to JSON and send to Web Console.
- */
- private static class JdbcDriver {
- /** */
- public final String jdbcDriverJar;
- /** */
- public final String jdbcDriverCls;
-
- /**
- * @param jdbcDriverJar File name of driver jar file.
- * @param jdbcDriverCls Optional JDBC driver class.
- */
- public JdbcDriver(String jdbcDriverJar, String jdbcDriverCls) {
- this.jdbcDriverJar = jdbcDriverJar;
- this.jdbcDriverCls = jdbcDriverCls;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/ignite/blob/262a3410/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/DatabaseListener.java
----------------------------------------------------------------------
diff --git a/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/DatabaseListener.java b/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/DatabaseListener.java
new file mode 100644
index 0000000..4577228
--- /dev/null
+++ b/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/DatabaseListener.java
@@ -0,0 +1,316 @@
+/*
+ * 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.console.agent.handlers;
+
+import io.socket.emitter.Emitter;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import org.apache.ignite.console.agent.AgentConfiguration;
+import org.apache.ignite.console.demo.AgentMetadataDemo;
+import org.apache.ignite.schema.parser.DbMetadataReader;
+import org.apache.ignite.schema.parser.DbTable;
+import org.apache.log4j.Logger;
+
+import static org.apache.ignite.console.agent.AgentUtils.resolvePath;
+
+/**
+ * API to extract database metadata.
+ */
+public class DatabaseListener {
+ /** */
+ private static final Logger log = Logger.getLogger(DatabaseListener.class.getName());
+
+ /** */
+ private final File driversFolder;
+
+ /** */
+ private final AbstractListener schemasLsnr = new AbstractListener() {
+ @Override public Object execute(Map<String, Object> args) throws Exception {
+ String driverPath = null;
+
+ if (args.containsKey("driverPath"))
+ driverPath = args.get("driverPath").toString();
+
+ if (!args.containsKey("driverClass"))
+ throw new IllegalArgumentException("Missing driverClass in arguments: " + args);
+
+ String driverCls = args.get("driverClass").toString();
+
+ if (!args.containsKey("url"))
+ throw new IllegalArgumentException("Missing url in arguments: " + args);
+
+ String url = args.get("url").toString();
+
+ if (!args.containsKey("info"))
+ throw new IllegalArgumentException("Missing info in arguments: " + args);
+
+ Properties info = new Properties();
+
+ info.putAll((Map)args.get("info"));
+
+ return schemas(driverPath, driverCls, url, info);
+ }
+ };
+
+ private final AbstractListener metadataLsnr = new AbstractListener() {
+ @SuppressWarnings("unchecked")
+ @Override public Object execute(Map<String, Object> args) throws Exception {
+ String driverPath = null;
+
+ if (args.containsKey("driverPath"))
+ driverPath = args.get("driverPath").toString();
+
+ if (!args.containsKey("driverClass"))
+ throw new IllegalArgumentException("Missing driverClass in arguments: " + args);
+
+ String driverCls = args.get("driverClass").toString();
+
+ if (!args.containsKey("url"))
+ throw new IllegalArgumentException("Missing url in arguments: " + args);
+
+ String url = args.get("url").toString();
+
+ if (!args.containsKey("info"))
+ throw new IllegalArgumentException("Missing info in arguments: " + args);
+
+ Properties info = new Properties();
+
+ info.putAll((Map)args.get("info"));
+
+ if (!args.containsKey("schemas"))
+ throw new IllegalArgumentException("Missing schemas in arguments: " + args);
+
+ List<String> schemas = (List<String>)args.get("schemas");
+
+ if (!args.containsKey("tablesOnly"))
+ throw new IllegalArgumentException("Missing tablesOnly in arguments: " + args);
+
+ boolean tblsOnly = (boolean)args.get("tablesOnly");
+
+ return metadata(driverPath, driverCls, url, info, schemas, tblsOnly);
+ }
+ };
+
+ private final AbstractListener availableDriversLsnr = new AbstractListener() {
+ @Override public Object execute(Map<String, Object> args) throws Exception {
+ if (driversFolder == null) {
+ log.info("JDBC drivers folder not specified, returning empty list");
+
+ return Collections.emptyList();
+ }
+
+ if (log.isDebugEnabled())
+ log.debug("Collecting JDBC drivers in folder: " + driversFolder.getPath());
+
+ File[] list = driversFolder.listFiles(new FilenameFilter() {
+ @Override public boolean accept(File dir, String name) {
+ return name.endsWith(".jar");
+ }
+ });
+
+ if (list == null) {
+ log.info("JDBC drivers folder has no files, returning empty list");
+
+ return Collections.emptyList();
+ }
+
+ List<JdbcDriver> res = new ArrayList<>();
+
+ for (File file : list) {
+ try {
+ boolean win = System.getProperty("os.name").contains("win");
+
+ URL url = new URL("jar", null,
+ "file:" + (win ? "/" : "") + file.getPath() + "!/META-INF/services/java.sql.Driver");
+
+ try (BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()))) {
+ String jdbcDriverCls = reader.readLine();
+
+ res.add(new JdbcDriver(file.getName(), jdbcDriverCls));
+
+ if (log.isDebugEnabled())
+ log.debug("Found: [driver=" + file + ", class=" + jdbcDriverCls + "]");
+ }
+ }
+ catch (IOException e) {
+ res.add(new JdbcDriver(file.getName(), null));
+
+ log.info("Found: [driver=" + file + "]");
+ log.info("Failed to detect driver class: " + e.getMessage());
+ }
+ }
+
+ return res;
+ }
+ };
+
+ /**
+ * @param cfg Config.
+ */
+ public DatabaseListener(AgentConfiguration cfg) {
+ driversFolder = resolvePath(cfg.driversFolder() == null ? "jdbc-drivers" : cfg.driversFolder());
+ }
+
+ /**
+ * @param jdbcDriverJarPath JDBC driver JAR path.
+ * @param jdbcDriverCls JDBC driver class.
+ * @param jdbcUrl JDBC URL.
+ * @param jdbcInfo Properties to connect to database.
+ * @return Connection to database.
+ * @throws SQLException
+ */
+ private Connection connect(String jdbcDriverJarPath, String jdbcDriverCls, String jdbcUrl,
+ Properties jdbcInfo) throws SQLException {
+ if (AgentMetadataDemo.isTestDriveUrl(jdbcUrl))
+ return AgentMetadataDemo.testDrive();
+
+ if (!new File(jdbcDriverJarPath).isAbsolute() && driversFolder != null)
+ jdbcDriverJarPath = new File(driversFolder, jdbcDriverJarPath).getPath();
+
+ return DbMetadataReader.getInstance().connect(jdbcDriverJarPath, jdbcDriverCls, jdbcUrl, jdbcInfo);
+ }
+
+ /**
+ * @param jdbcDriverJarPath JDBC driver JAR path.
+ * @param jdbcDriverCls JDBC driver class.
+ * @param jdbcUrl JDBC URL.
+ * @param jdbcInfo Properties to connect to database.
+ * @return Collection of schema names.
+ * @throws SQLException
+ */
+ protected Collection<String> schemas(String jdbcDriverJarPath, String jdbcDriverCls, String jdbcUrl,
+ Properties jdbcInfo) throws SQLException {
+ if (log.isDebugEnabled())
+ log.debug("Start collecting database schemas [drvJar=" + jdbcDriverJarPath +
+ ", drvCls=" + jdbcDriverCls + ", jdbcUrl=" + jdbcUrl + "]");
+
+ try (Connection conn = connect(jdbcDriverJarPath, jdbcDriverCls, jdbcUrl, jdbcInfo)) {
+ Collection<String> schemas = DbMetadataReader.getInstance().schemas(conn);
+
+ if (log.isDebugEnabled())
+ log.debug("Finished collection of schemas [jdbcUrl=" + jdbcUrl + ", count=" + schemas.size() + "]");
+
+ return schemas;
+ }
+ catch (Throwable e) {
+ log.error("Failed to collect schemas", e);
+
+ throw new SQLException("Failed to collect schemas", e);
+ }
+ }
+
+ /**
+ * Listener for drivers.
+ *
+ * @return Drivers in drivers folder
+ * @see AgentConfiguration#driversFolder
+ */
+ public Emitter.Listener availableDriversListener() {
+ return availableDriversLsnr;
+ }
+
+ /**
+ * Listener for schema names.
+ *
+ * @return Collection of schema names.
+ */
+ public Emitter.Listener schemasListener() {
+ return schemasLsnr;
+ }
+
+ /**
+ * @param jdbcDriverJarPath JDBC driver JAR path.
+ * @param jdbcDriverCls JDBC driver class.
+ * @param jdbcUrl JDBC URL.
+ * @param jdbcInfo Properties to connect to database.
+ * @param schemas List of schema names to process.
+ * @param tblsOnly If {@code true} then only tables will be processed otherwise views also will be processed.
+ * @return Collection of tables.
+ */
+ protected Collection<DbTable> metadata(String jdbcDriverJarPath, String jdbcDriverCls, String jdbcUrl,
+ Properties jdbcInfo, List<String> schemas, boolean tblsOnly) throws SQLException {
+ if (log.isDebugEnabled())
+ log.debug("Start collecting database metadata [drvJar=" + jdbcDriverJarPath +
+ ", drvCls=" + jdbcDriverCls + ", jdbcUrl=" + jdbcUrl + "]");
+
+ try (Connection conn = connect(jdbcDriverJarPath, jdbcDriverCls, jdbcUrl, jdbcInfo)) {
+ Collection<DbTable> metadata = DbMetadataReader.getInstance().metadata(conn, schemas, tblsOnly);
+
+ if (log.isDebugEnabled())
+ log.debug("Finished collection of metadata [jdbcUrl=" + jdbcUrl + ", count=" + metadata.size() + "]");
+
+ return metadata;
+ }
+ catch (Throwable e) {
+ log.error("Failed to collect metadata", e);
+
+ throw new SQLException("Failed to collect metadata", e);
+ }
+ }
+
+ /**
+ * Listener for tables.
+ *
+ * @return Collection of tables.
+ */
+ public Emitter.Listener metadataListener() {
+ return metadataLsnr;
+ }
+
+ /**
+ * Stop handler.
+ */
+ public void stop() {
+ availableDriversLsnr.stop();
+
+ schemasLsnr.stop();
+
+ metadataLsnr.stop();
+ }
+
+ /**
+ * Wrapper class for later to be transformed to JSON and send to Web Console.
+ */
+ private static class JdbcDriver {
+ /** */
+ public final String jdbcDriverJar;
+ /** */
+ public final String jdbcDriverCls;
+
+ /**
+ * @param jdbcDriverJar File name of driver jar file.
+ * @param jdbcDriverCls Optional JDBC driver class.
+ */
+ public JdbcDriver(String jdbcDriverJar, String jdbcDriverCls) {
+ this.jdbcDriverJar = jdbcDriverJar;
+ this.jdbcDriverCls = jdbcDriverCls;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/262a3410/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/RestHandler.java
----------------------------------------------------------------------
diff --git a/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/RestHandler.java b/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/RestHandler.java
deleted file mode 100644
index 1b4b565..0000000
--- a/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/RestHandler.java
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * 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.console.agent.handlers;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.net.ConnectException;
-import java.net.URISyntaxException;
-import java.nio.charset.Charset;
-import java.util.List;
-import java.util.Map;
-import org.apache.commons.codec.Charsets;
-import org.apache.http.Header;
-import org.apache.http.NameValuePair;
-import org.apache.http.client.entity.UrlEncodedFormEntity;
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.client.methods.HttpRequestBase;
-import org.apache.http.client.utils.URIBuilder;
-import org.apache.http.entity.StringEntity;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClientBuilder;
-import org.apache.ignite.console.agent.AgentConfiguration;
-import org.apache.ignite.console.demo.AgentClusterDemo;
-import org.apache.log4j.Logger;
-
-import static org.apache.ignite.console.agent.AgentConfiguration.DFLT_NODE_PORT;
-
-/**
- * API to translate REST requests to Ignite cluster.
- */
-public class RestHandler extends AbstractHandler {
- /** */
- private static final Logger log = Logger.getLogger(RestHandler.class.getName());
-
- /** */
- private final AgentConfiguration cfg;
-
- /** */
- private CloseableHttpClient httpClient;
-
- /**
- * @param cfg Config.
- */
- public RestHandler(AgentConfiguration cfg) {
- this.cfg = cfg;
- }
-
- /**
- * Start HTTP client for communication with node via REST.
- */
- public void start() {
- httpClient = HttpClientBuilder.create().build();
- }
-
- /**
- * Stop HTTP client.
- */
- public void stop() {
- if (httpClient != null) {
- try {
- httpClient.close();
- }
- catch (IOException ignore) {
- // No-op.
- }
- }
- }
-
- /** {@inheritDoc} */
- @SuppressWarnings("unchecked")
- @Override public Object execute(Map<String, Object> args) throws Exception {
- if (log.isDebugEnabled())
- log.debug("Start parse REST command args: " + args);
-
- String uri = null;
-
- if (args.containsKey("uri"))
- uri = args.get("uri").toString();
-
- Map<String, Object> params = null;
-
- if (args.containsKey("params"))
- params = (Map<String, Object>)args.get("params");
-
- if (!args.containsKey("demo"))
- throw new IllegalArgumentException("Missing demo flag in arguments: " + args);
-
- boolean demo = (boolean)args.get("demo");
-
- if (!args.containsKey("method"))
- throw new IllegalArgumentException("Missing method in arguments: " + args);
-
- String mtd = args.get("method").toString();
-
- Map<String, Object> headers = null;
-
- if (args.containsKey("headers"))
- headers = (Map<String, Object>)args.get("headers");
-
- String body = null;
-
- if (args.containsKey("body"))
- body = args.get("body").toString();
-
- return executeRest(uri, params, demo, mtd, headers, body);
- }
-
- /**
- * @param uri Url.
- * @param params Params.
- * @param demo Use demo node.
- * @param mtd Method.
- * @param headers Headers.
- * @param body Body.
- */
- protected RestResult executeRest(String uri, Map<String, Object> params, boolean demo,
- String mtd, Map<String, Object> headers, String body) throws IOException, URISyntaxException {
- if (log.isDebugEnabled())
- log.debug("Start execute REST command [method=" + mtd + ", uri=/" + (uri == null ? "" : uri) +
- ", parameters=" + params + "]");
-
- final URIBuilder builder;
-
- if (demo) {
- // try start demo if needed.
- AgentClusterDemo.testDrive(cfg);
-
- // null if demo node not started yet.
- if (cfg.demoNodeUri() == null)
- return RestResult.fail("Demo node is not started yet.", 404);
-
- builder = new URIBuilder(cfg.demoNodeUri());
- }
- else
- builder = new URIBuilder(cfg.nodeUri());
-
- if (builder.getPort() == -1)
- builder.setPort(DFLT_NODE_PORT);
-
- if (uri != null) {
- if (!uri.startsWith("/") && !cfg.nodeUri().endsWith("/"))
- uri = '/' + uri;
-
- builder.setPath(uri);
- }
-
- if (params != null) {
- for (Map.Entry<String, Object> entry : params.entrySet()) {
- if (entry.getValue() != null)
- builder.addParameter(entry.getKey(), entry.getValue().toString());
- }
- }
-
- HttpRequestBase httpReq = null;
-
- try {
- if ("GET".equalsIgnoreCase(mtd))
- httpReq = new HttpGet(builder.build());
- else if ("POST".equalsIgnoreCase(mtd)) {
- HttpPost post;
-
- if (body == null) {
- List<NameValuePair> nvps = builder.getQueryParams();
-
- builder.clearParameters();
-
- post = new HttpPost(builder.build());
-
- if (!nvps.isEmpty())
- post.setEntity(new UrlEncodedFormEntity(nvps));
- }
- else {
- post = new HttpPost(builder.build());
-
- post.setEntity(new StringEntity(body));
- }
-
- httpReq = post;
- }
- else
- throw new IOException("Unknown HTTP-method: " + mtd);
-
- if (headers != null) {
- for (Map.Entry<String, Object> entry : headers.entrySet())
- httpReq.addHeader(entry.getKey(), entry.getValue() == null ? null : entry.getValue().toString());
- }
-
- try (CloseableHttpResponse resp = httpClient.execute(httpReq)) {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
-
- resp.getEntity().writeTo(out);
-
- Charset charset = Charsets.UTF_8;
-
- Header encodingHdr = resp.getEntity().getContentEncoding();
-
- if (encodingHdr != null) {
- String encoding = encodingHdr.getValue();
-
- charset = Charsets.toCharset(encoding);
- }
-
- return RestResult.success(resp.getStatusLine().getStatusCode(), new String(out.toByteArray(), charset));
- }
- catch (ConnectException e) {
- log.info("Failed connect to node and execute REST command [uri=" + builder.build() + "]");
-
- return RestResult.fail("Failed connect to node and execute REST command.", 404);
- }
- }
- finally {
- if (httpReq != null)
- httpReq.reset();
- }
- }
-
- /**
- * Request result.
- */
- public static class RestResult {
- /** The field contains description of error if server could not handle the request. */
- public final String error;
-
- /** REST http code. */
- public final int code;
-
- /** The field contains result of command. */
- public final String data;
-
- /**
- * @param error The field contains description of error if server could not handle the request.
- * @param resCode REST http code.
- * @param res The field contains result of command.
- */
- private RestResult(String error, int resCode, String res) {
- this.error = error;
- this.code = resCode;
- this.data = res;
- }
-
- /**
- * @param error The field contains description of error if server could not handle the request.
- * @param restCode REST http code.
- * @return Request result.
- */
- public static RestResult fail(String error, int restCode) {
- return new RestResult(error, restCode, null);
- }
-
- /**
- * @param code REST http code.
- * @param data The field contains result of command.
- * @return Request result.
- */
- public static RestResult success(int code, String data) {
- return new RestResult(null, code, data);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/ignite/blob/262a3410/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/RestListener.java
----------------------------------------------------------------------
diff --git a/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/RestListener.java b/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/RestListener.java
new file mode 100644
index 0000000..1e86549
--- /dev/null
+++ b/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/RestListener.java
@@ -0,0 +1,280 @@
+/*
+ * 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.console.agent.handlers;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.net.ConnectException;
+import java.net.URISyntaxException;
+import java.nio.charset.Charset;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import org.apache.commons.codec.Charsets;
+import org.apache.http.Header;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpRequestBase;
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.ignite.console.agent.AgentConfiguration;
+import org.apache.ignite.console.demo.AgentClusterDemo;
+import org.apache.log4j.Logger;
+
+import static org.apache.ignite.console.agent.AgentConfiguration.DFLT_NODE_PORT;
+
+/**
+ * API to translate REST requests to Ignite cluster.
+ */
+public class RestListener extends AbstractListener {
+ /** */
+ private static final Logger log = Logger.getLogger(RestListener.class.getName());
+
+ /** */
+ private final AgentConfiguration cfg;
+
+ /** */
+ private CloseableHttpClient httpClient;
+
+ /**
+ * @param cfg Config.
+ */
+ public RestListener(AgentConfiguration cfg) {
+ super();
+
+ this.cfg = cfg;
+
+ httpClient = HttpClientBuilder.create().build();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void stop() {
+ super.stop();
+
+ if (httpClient != null) {
+ try {
+ httpClient.close();
+ }
+ catch (IOException ignore) {
+ // No-op.
+ }
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override protected ExecutorService newThreadPool() {
+ return Executors.newCachedThreadPool();
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ @Override public Object execute(Map<String, Object> args) throws Exception {
+ if (log.isDebugEnabled())
+ log.debug("Start parse REST command args: " + args);
+
+ String uri = null;
+
+ if (args.containsKey("uri"))
+ uri = args.get("uri").toString();
+
+ Map<String, Object> params = null;
+
+ if (args.containsKey("params"))
+ params = (Map<String, Object>)args.get("params");
+
+ if (!args.containsKey("demo"))
+ throw new IllegalArgumentException("Missing demo flag in arguments: " + args);
+
+ boolean demo = (boolean)args.get("demo");
+
+ if (!args.containsKey("method"))
+ throw new IllegalArgumentException("Missing method in arguments: " + args);
+
+ String mtd = args.get("method").toString();
+
+ Map<String, Object> headers = null;
+
+ if (args.containsKey("headers"))
+ headers = (Map<String, Object>)args.get("headers");
+
+ String body = null;
+
+ if (args.containsKey("body"))
+ body = args.get("body").toString();
+
+ return executeRest(uri, params, demo, mtd, headers, body);
+ }
+
+ /**
+ * @param uri Url.
+ * @param params Params.
+ * @param demo Use demo node.
+ * @param mtd Method.
+ * @param headers Headers.
+ * @param body Body.
+ */
+ protected RestResult executeRest(String uri, Map<String, Object> params, boolean demo,
+ String mtd, Map<String, Object> headers, String body) throws IOException, URISyntaxException {
+ if (log.isDebugEnabled())
+ log.debug("Start execute REST command [method=" + mtd + ", uri=/" + (uri == null ? "" : uri) +
+ ", parameters=" + params + "]");
+
+ final URIBuilder builder;
+
+ if (demo) {
+ // try start demo if needed.
+ AgentClusterDemo.testDrive(cfg);
+
+ // null if demo node not started yet.
+ if (cfg.demoNodeUri() == null)
+ return RestResult.fail("Demo node is not started yet.", 404);
+
+ builder = new URIBuilder(cfg.demoNodeUri());
+ }
+ else
+ builder = new URIBuilder(cfg.nodeUri());
+
+ if (builder.getPort() == -1)
+ builder.setPort(DFLT_NODE_PORT);
+
+ if (uri != null) {
+ if (!uri.startsWith("/") && !cfg.nodeUri().endsWith("/"))
+ uri = '/' + uri;
+
+ builder.setPath(uri);
+ }
+
+ if (params != null) {
+ for (Map.Entry<String, Object> entry : params.entrySet()) {
+ if (entry.getValue() != null)
+ builder.addParameter(entry.getKey(), entry.getValue().toString());
+ }
+ }
+
+ HttpRequestBase httpReq = null;
+
+ try {
+ if ("GET".equalsIgnoreCase(mtd))
+ httpReq = new HttpGet(builder.build());
+ else if ("POST".equalsIgnoreCase(mtd)) {
+ HttpPost post;
+
+ if (body == null) {
+ List<NameValuePair> nvps = builder.getQueryParams();
+
+ builder.clearParameters();
+
+ post = new HttpPost(builder.build());
+
+ if (!nvps.isEmpty())
+ post.setEntity(new UrlEncodedFormEntity(nvps));
+ }
+ else {
+ post = new HttpPost(builder.build());
+
+ post.setEntity(new StringEntity(body));
+ }
+
+ httpReq = post;
+ }
+ else
+ throw new IOException("Unknown HTTP-method: " + mtd);
+
+ if (headers != null) {
+ for (Map.Entry<String, Object> entry : headers.entrySet())
+ httpReq.addHeader(entry.getKey(), entry.getValue() == null ? null : entry.getValue().toString());
+ }
+
+ try (CloseableHttpResponse resp = httpClient.execute(httpReq)) {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+ resp.getEntity().writeTo(out);
+
+ Charset charset = Charsets.UTF_8;
+
+ Header encodingHdr = resp.getEntity().getContentEncoding();
+
+ if (encodingHdr != null) {
+ String encoding = encodingHdr.getValue();
+
+ charset = Charsets.toCharset(encoding);
+ }
+
+ return RestResult.success(resp.getStatusLine().getStatusCode(), new String(out.toByteArray(), charset));
+ }
+ catch (ConnectException e) {
+ log.info("Failed connect to node and execute REST command [uri=" + builder.build() + "]");
+
+ return RestResult.fail("Failed connect to node and execute REST command.", 404);
+ }
+ }
+ finally {
+ if (httpReq != null)
+ httpReq.reset();
+ }
+ }
+
+ /**
+ * Request result.
+ */
+ public static class RestResult {
+ /** The field contains description of error if server could not handle the request. */
+ public final String error;
+
+ /** REST http code. */
+ public final int code;
+
+ /** The field contains result of command. */
+ public final String data;
+
+ /**
+ * @param error The field contains description of error if server could not handle the request.
+ * @param resCode REST http code.
+ * @param res The field contains result of command.
+ */
+ private RestResult(String error, int resCode, String res) {
+ this.error = error;
+ this.code = resCode;
+ this.data = res;
+ }
+
+ /**
+ * @param error The field contains description of error if server could not handle the request.
+ * @param restCode REST http code.
+ * @return Request result.
+ */
+ public static RestResult fail(String error, int restCode) {
+ return new RestResult(error, restCode, null);
+ }
+
+ /**
+ * @param code REST http code.
+ * @param data The field contains result of command.
+ * @return Request result.
+ */
+ public static RestResult success(int code, String data) {
+ return new RestResult(null, code, data);
+ }
+ }
+}