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'