diff --git a/.idea/modules.xml b/.idea/modules.xml index afc29009fe5..2ab1229cbf5 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -17,6 +17,7 @@ + diff --git a/.idea/modules/plugin-transport-wares.iml b/.idea/modules/plugin-transport-wares.iml new file mode 100644 index 00000000000..a86286863a4 --- /dev/null +++ b/.idea/modules/plugin-transport-wares.iml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/common/logging/jdk/JdkESLogger.java b/modules/elasticsearch/src/main/java/org/elasticsearch/common/logging/jdk/JdkESLogger.java index 40aa4d32b21..092ad365b66 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/common/logging/jdk/JdkESLogger.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/common/logging/jdk/JdkESLogger.java @@ -31,9 +31,12 @@ public class JdkESLogger extends AbstractESLogger { private final Logger logger; - public JdkESLogger(String prefix, Logger logger) { + private final String name; + + public JdkESLogger(String prefix, String name, Logger logger) { super(prefix); this.logger = logger; + this.name = name; } @Override public String getName() { @@ -61,42 +64,42 @@ public class JdkESLogger extends AbstractESLogger { } @Override protected void internalTrace(String msg) { - logger.log(Level.FINEST, msg); + logger.logp(Level.FINEST, name, null, msg); } @Override protected void internalTrace(String msg, Throwable cause) { - logger.log(Level.FINEST, msg, cause); + logger.logp(Level.FINEST, name, null, msg, cause); } @Override protected void internalDebug(String msg) { - logger.log(Level.FINE, msg); + logger.logp(Level.FINE, name, null, msg); } @Override protected void internalDebug(String msg, Throwable cause) { - logger.log(Level.FINE, msg, cause); + logger.logp(Level.FINE, name, null, msg, cause); } @Override protected void internalInfo(String msg) { - logger.log(Level.INFO, msg); + logger.logp(Level.INFO, name, null, msg); } @Override protected void internalInfo(String msg, Throwable cause) { - logger.log(Level.INFO, msg, cause); + logger.logp(Level.INFO, name, null, msg, cause); } @Override protected void internalWarn(String msg) { - logger.log(Level.WARNING, msg); + logger.logp(Level.WARNING, name, null, msg); } @Override protected void internalWarn(String msg, Throwable cause) { - logger.log(Level.WARNING, msg, cause); + logger.logp(Level.WARNING, name, null, msg, cause); } @Override protected void internalError(String msg) { - logger.log(Level.SEVERE, msg); + logger.logp(Level.SEVERE, name, null, msg); } @Override protected void internalError(String msg, Throwable cause) { - logger.log(Level.SEVERE, msg, cause); + logger.logp(Level.SEVERE, name, null, msg, cause); } } diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/common/logging/jdk/JdkESLoggerFactory.java b/modules/elasticsearch/src/main/java/org/elasticsearch/common/logging/jdk/JdkESLoggerFactory.java index cbb8cb7ece1..c6b092de7aa 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/common/logging/jdk/JdkESLoggerFactory.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/common/logging/jdk/JdkESLoggerFactory.java @@ -29,6 +29,6 @@ public class JdkESLoggerFactory extends ESLoggerFactory { @Override public ESLogger newInstance(String prefix, String name) { final java.util.logging.Logger logger = java.util.logging.Logger.getLogger(name); - return new JdkESLogger(prefix, logger); + return new JdkESLogger(prefix, name, logger); } } diff --git a/plugins/transport/memcached/src/main/java/org/elasticsearch/memcached/MemcachedRestRequest.java b/plugins/transport/memcached/src/main/java/org/elasticsearch/memcached/MemcachedRestRequest.java index b24cb604bde..b1e362af5cc 100644 --- a/plugins/transport/memcached/src/main/java/org/elasticsearch/memcached/MemcachedRestRequest.java +++ b/plugins/transport/memcached/src/main/java/org/elasticsearch/memcached/MemcachedRestRequest.java @@ -20,13 +20,11 @@ package org.elasticsearch.memcached; import org.elasticsearch.common.Unicode; -import org.elasticsearch.common.collect.ImmutableSet; import org.elasticsearch.rest.support.AbstractRestRequest; import org.elasticsearch.rest.support.RestUtils; import java.util.HashMap; import java.util.Map; -import java.util.Set; /** * @author kimchy (shay.banon) @@ -137,18 +135,10 @@ public class MemcachedRestRequest extends AbstractRestRequest { return Unicode.fromBytes(data); } - @Override public Set headerNames() { - return ImmutableSet.of(); - } - @Override public String header(String name) { return null; } - @Override public String cookie() { - return null; - } - @Override public boolean hasParam(String key) { return params.containsKey(key); } diff --git a/plugins/transport/thrift/src/main/java/org/elasticsearch/thrift/ThriftRestRequest.java b/plugins/transport/thrift/src/main/java/org/elasticsearch/thrift/ThriftRestRequest.java index 2ccc9c5baf3..827120aa807 100644 --- a/plugins/transport/thrift/src/main/java/org/elasticsearch/thrift/ThriftRestRequest.java +++ b/plugins/transport/thrift/src/main/java/org/elasticsearch/thrift/ThriftRestRequest.java @@ -21,13 +21,11 @@ package org.elasticsearch.thrift; import org.elasticsearch.common.Bytes; import org.elasticsearch.common.Unicode; -import org.elasticsearch.common.collect.ImmutableSet; import org.elasticsearch.rest.support.AbstractRestRequest; import org.elasticsearch.rest.support.RestUtils; import java.util.HashMap; import java.util.Map; -import java.util.Set; /** * @author kimchy (shay.banon) @@ -115,13 +113,6 @@ public class ThriftRestRequest extends AbstractRestRequest implements org.elasti return Unicode.fromBytes(contentByteArray(), contentByteArrayOffset(), contentLength()); } - @Override public Set headerNames() { - if (request.getHeaders() == null) { - return ImmutableSet.of(); - } - return request.getHeaders().keySet(); - } - @Override public String header(String name) { if (request.getHeaders() == null) { return null; @@ -129,10 +120,6 @@ public class ThriftRestRequest extends AbstractRestRequest implements org.elasti return request.getHeaders().get(name); } - @Override public String cookie() { - return null; - } - @Override public boolean hasParam(String key) { return params.containsKey(key); } diff --git a/plugins/transport/wares/build.gradle b/plugins/transport/wares/build.gradle new file mode 100644 index 00000000000..36040e0385f --- /dev/null +++ b/plugins/transport/wares/build.gradle @@ -0,0 +1,127 @@ +dependsOn(':elasticsearch') + +apply plugin: 'java' +apply plugin: 'maven' + +archivesBaseName = "elasticsearch-transport-wares" + +explodedDistDir = new File(distsDir, 'exploded') + +configurations.compile.transitive = true +configurations.testCompile.transitive = true + +// no need to use the resource dir +sourceSets.main.resources.srcDirs 'src/main/java' +sourceSets.test.resources.srcDirs 'src/test/java' + +jar { +// from sourceSets.main.allJava + manifest { + attributes("Implementation-Title": "ElasticSearch", "Implementation-Version": rootProject.version, "Implementation-Date": buildTimeStr) + } +} + +configurations { + dists + distLib { + visible = false + transitive = false + } +} + +dependencies { + compile project(':elasticsearch') + compile 'javax.servlet:servlet-api:2.5' +} + +task explodedDist(dependsOn: [jar], description: 'Builds the plugin zip file') << { + [explodedDistDir]*.mkdirs() + + copy { + from configurations.distLib + into explodedDistDir + } + + // remove elasticsearch files (compile above adds the elasticsearch one) + ant.delete { fileset(dir: explodedDistDir, includes: "elasticsearch-*.jar") } + + copy { + from libsDir + into explodedDistDir + } + + ant.delete { fileset(dir: explodedDistDir, includes: "elasticsearch-*-javadoc.jar") } + ant.delete { fileset(dir: explodedDistDir, includes: "elasticsearch-*-sources.jar") } +} + +task zip(type: Zip, dependsOn: ['explodedDist']) { + from(explodedDistDir) { + } +} + +task release(dependsOn: [zip]) << { + ant.delete(dir: explodedDistDir) + copy { + from distsDir + into(new File(rootProject.distsDir, "plugins")) + } +} + +configurations { + deployerJars + tools +} + +dependencies { + deployerJars "org.apache.maven.wagon:wagon-http:1.0-beta-2" + tools "com.google.code:jarjar:1.0" +} + +task sourcesJar(type: Jar, dependsOn: classes) { + classifier = 'sources' + from sourceSets.main.allSource +} + +task javadocJar(type: Jar, dependsOn: javadoc) { + classifier = 'javadoc' + from javadoc.destinationDir +} + +artifacts { + archives sourcesJar + archives javadocJar +} + +uploadArchives { + repositories.mavenDeployer { + configuration = configurations.deployerJars + repository(url: rootProject.mavenRepoUrl) { + authentication(userName: rootProject.mavenRepoUser, password: rootProject.mavenRepoPass) + } + snapshotRepository(url: rootProject.mavenSnapshotRepoUrl) { + authentication(userName: rootProject.mavenRepoUser, password: rootProject.mavenRepoPass) + } + + pom.project { + inceptionYear '2009' + name 'elasticsearch-plugins-transport-wares' + description 'War Plugin for ElasticSearch' + licenses { + license { + name 'The Apache Software License, Version 2.0' + url 'http://www.apache.org/licenses/LICENSE-2.0.txt' + distribution 'repo' + } + } + scm { + connection 'git://github.com/elasticsearch/elasticsearch.git' + developerConnection 'git@github.com:elasticsearch/elasticsearch.git' + url 'http://github.com/elasticsearch/elasticsearch' + } + } + + pom.whenConfigured {pom -> + pom.dependencies = pom.dependencies.findAll {dep -> dep.scope != 'test' } // removes the test scoped ones + } + } +} \ No newline at end of file diff --git a/plugins/transport/wares/src/main/java/org/elasticsearch/wares/NodeServlet.java b/plugins/transport/wares/src/main/java/org/elasticsearch/wares/NodeServlet.java new file mode 100644 index 00000000000..cc6f1037c53 --- /dev/null +++ b/plugins/transport/wares/src/main/java/org/elasticsearch/wares/NodeServlet.java @@ -0,0 +1,158 @@ +/* + * Licensed to Elastic Search and Shay Banon under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. Elastic Search 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.elasticsearch.wares; + +import org.elasticsearch.common.settings.ImmutableSettings; +import org.elasticsearch.node.Node; +import org.elasticsearch.node.NodeBuilder; +import org.elasticsearch.node.internal.InternalNode; +import org.elasticsearch.rest.RestChannel; +import org.elasticsearch.rest.RestController; +import org.elasticsearch.rest.RestRequest; +import org.elasticsearch.rest.RestResponse; + +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStream; +import java.util.concurrent.CountDownLatch; + +/** + * A servlet that can be used to dispatch requests to elasticsearch. A {@link Node} will be started, reading + * config from either /WEB-INF/elasticsearch.json or /WEB-INF/elasticsearch.yml but, by defualt, + * with its internal HTTP interface disabled. + * + *

The node is registered as a servlet context attribute under elasticsearchNode so its easily + * accessible from other web resources if needed. + */ +public class NodeServlet extends HttpServlet { + + public static String NODE_KEY = "elasticsearchNode"; + + private Node node; + + private RestController restController; + + @Override public void init() throws ServletException { + getServletContext().log("Initializing elasticsearch Node '" + getServletName() + "'"); + ImmutableSettings.Builder settings = ImmutableSettings.settingsBuilder(); + + InputStream resourceAsStream = getServletContext().getResourceAsStream("/WEB-INF/elasticsearch.json"); + if (resourceAsStream != null) { + settings.loadFromStream("/WEB-INF/elasticsearch.json", resourceAsStream); + try { + resourceAsStream.close(); + } catch (IOException e) { + // ignore + } + } + + resourceAsStream = getServletContext().getResourceAsStream("/WEB-INF/elasticsearch.yml"); + if (resourceAsStream != null) { + settings.loadFromStream("/WEB-INF/elasticsearch.yml", resourceAsStream); + try { + resourceAsStream.close(); + } catch (IOException e) { + // ignore + } + } + if (settings.get("http.enabled") == null) { + settings.put("http.enabled", false); + } + + node = NodeBuilder.nodeBuilder().settings(settings).node(); + restController = ((InternalNode) node).injector().getInstance(RestController.class); + getServletContext().setAttribute(NODE_KEY, node); + } + + @Override public void destroy() { + if (node != null) { + getServletContext().removeAttribute(NODE_KEY); + node.close(); + } + } + + @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + ServletRestRequest request = new ServletRestRequest(req); + ServletRestChannel channel = new ServletRestChannel(request, resp); + try { + if (!restController.dispatchRequest(request, channel)) { + throw new ServletException("No mapping found for [" + request.uri() + "]"); + } + channel.latch.await(); + } catch (ServletException e) { + throw e; + } catch (Exception e) { + throw new IOException("failed to dispatch request", e); + } + if (channel.sendFailure != null) { + throw channel.sendFailure; + } + } + + static class ServletRestChannel implements RestChannel { + + final RestRequest restRequest; + + final HttpServletResponse resp; + + final CountDownLatch latch; + + IOException sendFailure; + + ServletRestChannel(RestRequest restRequest, HttpServletResponse resp) { + this.restRequest = restRequest; + this.resp = resp; + this.latch = new CountDownLatch(1); + } + + @Override public void sendResponse(RestResponse response) { + resp.setContentType(response.contentType()); + resp.addHeader("Access-Control-Allow-Origin", "*"); + if (restRequest.method() == RestRequest.Method.OPTIONS) { + // also add more access control parameters + resp.addHeader("Access-Control-Max-Age", "1728000"); + resp.addHeader("Access-Control-Allow-Methods", "PUT, DELETE"); + resp.addHeader("Access-Control-Allow-Headers", "X-Requested-With"); + } + try { + int contentLength = response.contentLength() + response.prefixContentLength() + response.suffixContentLength(); + resp.setContentLength(contentLength); + + ServletOutputStream out = resp.getOutputStream(); + if (response.prefixContent() != null) { + out.write(response.prefixContent(), 0, response.prefixContentLength()); + } + out.write(response.content(), 0, response.contentLength()); + if (response.suffixContent() != null) { + out.write(response.suffixContent(), 0, response.suffixContentLength()); + } + out.close(); + } catch (IOException e) { + sendFailure = e; + } finally { + latch.countDown(); + } + } + } +} \ No newline at end of file diff --git a/plugins/transport/wares/src/main/java/org/elasticsearch/wares/ServletRestRequest.java b/plugins/transport/wares/src/main/java/org/elasticsearch/wares/ServletRestRequest.java new file mode 100644 index 00000000000..e204ccb4c51 --- /dev/null +++ b/plugins/transport/wares/src/main/java/org/elasticsearch/wares/ServletRestRequest.java @@ -0,0 +1,113 @@ +/* + * Licensed to Elastic Search and Shay Banon under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. Elastic Search 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.elasticsearch.wares; + +import org.elasticsearch.common.Unicode; +import org.elasticsearch.common.io.Streams; +import org.elasticsearch.rest.support.AbstractRestRequest; +import org.elasticsearch.rest.support.RestUtils; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +public class ServletRestRequest extends AbstractRestRequest implements org.elasticsearch.rest.RestRequest { + + private final HttpServletRequest servletRequest; + + private final Method method; + + private final Map params; + + private final byte[] content; + + public ServletRestRequest(HttpServletRequest servletRequest) throws IOException { + this.servletRequest = servletRequest; + this.method = Method.valueOf(servletRequest.getMethod()); + this.params = new HashMap(); + + if (servletRequest.getQueryString() != null) { + RestUtils.decodeQueryString(servletRequest.getQueryString(), 0, params); + } + + content = Streams.copyToByteArray(servletRequest.getInputStream()); + } + + @Override public Method method() { + return this.method; + } + + @Override public String uri() { + return servletRequest.getRequestURI().substring(servletRequest.getContextPath().length()); + } + + @Override public String rawPath() { + return servletRequest.getRequestURI().substring(servletRequest.getContextPath().length()); + } + + @Override public boolean hasContent() { + return content.length > 0; + } + + @Override public boolean contentUnsafe() { + return false; + } + + @Override public byte[] contentByteArray() { + return content; + } + + @Override public int contentByteArrayOffset() { + return 0; + } + + @Override public int contentLength() { + return content.length; + } + + @Override public String contentAsString() { + return Unicode.fromBytes(contentByteArray(), contentByteArrayOffset(), contentLength()); + } + + @Override public String header(String name) { + return servletRequest.getHeader(name); + } + + @Override public Map params() { + return params; + } + + @Override public boolean hasParam(String key) { + return params.containsKey(key); + } + + @Override public String param(String key) { + return params.get(key); + } + + @Override public String param(String key, String defaultValue) { + String value = params.get(key); + if (value == null) { + return defaultValue; + } + return value; + } +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 40f0e20e208..beab68705c2 100644 --- a/settings.gradle +++ b/settings.gradle @@ -19,6 +19,7 @@ include 'plugins-lang-python' include 'plugins-transport-memcached' include 'plugins-transport-thrift' +include 'plugins-transport-wares' include 'plugins-river-twitter' include 'plugins-river-wikipedia'