diff --git a/README.md b/README.md index 6366e91..6834133 100644 --- a/README.md +++ b/README.md @@ -4,26 +4,11 @@ Servlet Transport for Elasticsearch The wares transport plugin allows to use the REST interface over servlets. You don't really install this plugin, but instead use the jar file in addition to elasticsearch itself in your web app using the maven repo: -```xml - - org.elasticsearch - elasticsearch-transport-wares - 2.0.0.RC1 - -``` - -* For master elasticsearch versions, look at [master branch](https://github.com/elasticsearch/elasticsearch-transport-wares/tree/master). -* For 0.90.x elasticsearch versions, look at [es-0.90 branch](https://github.com/elasticsearch/elasticsearch-transport-wares/tree/es-0.90). - -| Wares Transport Plugin | elasticsearch | Release date | -|-----------------------------|-----------------------|:------------:| -| 2.0.0-SNAPSHOT | 1.0.0.RC1 -> master | XXXX-XX-XX | -| 2.0.0.RC1 | 1.0.0.RC1 -> master | 2014-10-15 | +## Version 2.7.1-SNAPSHOT for Elasticsearch: 1.7 -Please read documentation relative to the version you are using: +If you are looking for another version documentation, please refer to the +[compatibility matrix](http://github.com/elastic/elasticsearch-transport-wares). -* [2.0.0-SNAPSHOT](https://github.com/elasticsearch/elasticsearch-transport-wares/blob/master/README.md) -* [2.0.0.RC1](https://github.com/elasticsearch/elasticsearch-transport-wares/tree/v2.2.0.RC1/README.md) Tomcat configuration (CORS filter) ---------------------------------- @@ -41,6 +26,14 @@ The [Tomcat configuration](http://tomcat.apache.org/tomcat-7.0-doc/config/filter ``` +Node resource +------------- + +The node is registered as a servlet context attribute under `elasticsearchNode` so it is easily accessible from other web resources if needed. + +You can also preregister your own node using `elasticsearchNode` servlet context attribute. It will be used by the NodeServlet. + + License ------- diff --git a/dev-tools/build_release.py b/dev-tools/build_release.py index 27a4652..9271886 100755 --- a/dev-tools/build_release.py +++ b/dev-tools/build_release.py @@ -63,7 +63,7 @@ (see https://github.com/settings/applications#personal-access-tokens) - Optional: default to no authentication - SMTP_HOST - Optional: default to localhost - MAIL_SENDER - Optional: default to 'david@pilato.fr': must be authorized to send emails to elasticsearch mailing list - - MAIL_TO - Optional: default to 'elasticsearch@googlegroups.com' + - MAIL_TO - Optional: default to 'discuss+announcements@elastic.co' """ env = os.environ @@ -289,14 +289,27 @@ def find_release_version(src_branch): return match.group(1) raise RuntimeError('Could not find release version in branch %s' % src_branch) -# extract a value from pom.xml -def find_from_pom(tag): +# extract a value from pom.xml after a given line +def find_from_pom(tag, first_line=None): with open(POM_FILE, encoding='utf-8') as file: + previous_line_matched = False + if first_line is None: + previous_line_matched = True for line in file: - match = re.search(r'<%s>(.+)' % (tag, tag), line) - if match: - return match.group(1) - raise RuntimeError('Could not find <%s> in pom.xml file' % (tag)) + if previous_line_matched: + match = re.search(r'<%s>(.+)' % (tag, tag), line) + if match: + return match.group(1) + + if first_line is not None: + match = re.search(r'%s' % first_line, line) + if match: + previous_line_matched = True + + if first_line is not None: + raise RuntimeError('Could not find %s in pom.xml file after %s' % (tag, first_line)) + else: + raise RuntimeError('Could not find %s in pom.xml file' % tag) def get_artifacts(artifact_id, release): artifact_path = ROOT_DIR + 'target/releases/%s-%s.zip' % (artifact_id, release) @@ -380,13 +393,13 @@ def get_github_repository(reponame, else: g = github3.GitHub() - return g.repository("elasticsearch", reponame) + return g.repository("elastic", reponame) # Check if there are some remaining open issues and fails def check_opened_issues(version, repository, reponame): opened_issues = [i for i in repository.iter_issues(state='open', labels='%s' % version)] if len(opened_issues)>0: - raise NameError('Some issues [%s] are still opened. Check https://github.com/elasticsearch/%s/issues?labels=%s&state=open' + raise NameError('Some issues [%s] are still opened. Check https://github.com/elastic/%s/issues?labels=%s&state=open' % (len(opened_issues), reponame, version)) # List issues from github: can be done anonymously if you don't @@ -453,8 +466,7 @@ def prepare_email(artifact_id, release_version, repository, %(issues_new)s %(issues_doc)s -Issues, Pull requests, Feature requests are warmly welcome on %(artifact_id)s project repository: %(project_url)s -For questions or comments around this plugin, feel free to use elasticsearch mailing list: https://groups.google.com/forum/#!forum/elasticsearch +For questions or comments around this plugin, feel free to use elasticsearch mailing list: https://discuss.elastic.co/c/elasticsearch Enjoy, @@ -486,14 +498,12 @@ def prepare_email(artifact_id, release_version, repository, %(issues_new)s %(issues_doc)s -

Issues, Pull requests, Feature requests are warmly welcome on -%(artifact_id)s project repository!

For questions or comments around this plugin, feel free to use elasticsearch -mailing list!

+mailing list!

Enjoy,

-

- The Elasticsearch team

+

- The Elastic team

""" % {'release_version': release_version, 'artifact_id': artifact_id, @@ -522,7 +532,7 @@ def send_email(msg, dry_run=True, mail=True, sender=env.get('MAIL_SENDER'), - to=env.get('MAIL_TO', 'elasticsearch@googlegroups.com'), + to=env.get('MAIL_TO', 'discuss+announcements@elastic.co'), smtp_server=env.get('SMTP_SERVER', 'localhost')): msg['From'] = 'Elasticsearch Team <%s>' % sender msg['To'] = 'Elasticsearch Mailing List <%s>' % to @@ -611,7 +621,7 @@ def check_email_settings(): if mail: check_email_settings() print('An email to %s will be sent after the release' - % env.get('MAIL_TO', 'elasticsearch@googlegroups.com')) + % env.get('MAIL_TO', 'discuss+announcements@elastic.co')) input('Press Enter to continue...') check_github_credentials() @@ -626,7 +636,14 @@ def check_email_settings(): artifact_name = find_from_pom('name') artifact_description = find_from_pom('description') project_url = find_from_pom('url') - elasticsearch_version = find_from_pom('elasticsearch.version') + + try: + elasticsearch_version = find_from_pom('elasticsearch.version') + except RuntimeError: + # With projects using elasticsearch-parent project, we need to consider elasticsearch version + # to be after elasticsearch-parent + elasticsearch_version = find_from_pom('version', 'elasticsearch-parent') + print(' Artifact Id: [%s]' % artifact_id) print(' Release version: [%s]' % release_version) print(' Elasticsearch: [%s]' % elasticsearch_version) diff --git a/pom.xml b/pom.xml index c19d208..f9220cb 100644 --- a/pom.xml +++ b/pom.xml @@ -6,11 +6,11 @@ org.elasticsearch elasticsearch-transport-wares - 2.0.0-SNAPSHOT + 2.7.1-SNAPSHOT jar Elasticsearch Servlet Transport plugin The wares transport plugin allows to use the REST interface over servlets. - https://github.com/elasticsearch/elasticsearch-transport-wares/ + https://github.com/elastic/elasticsearch-transport-wares/ 2009 @@ -20,30 +20,28 @@ - scm:git:git@github.com:elasticsearch/elasticsearch-transport-wares.git - scm:git:git@github.com:elasticsearch/elasticsearch-transport-wares.git - - http://github.com/elasticsearch/elasticsearch-transport-wares + scm:git:git@github.com:elastic/elasticsearch-transport-wares.git + scm:git:git@github.com:elastic/elasticsearch-transport-wares.git + http://github.com/elastic/elasticsearch-transport-wares - org.sonatype.oss - oss-parent - 7 + org.elasticsearch + elasticsearch-parent + 1.7.0 - 1.0.0.RC1 + org.elasticsearch elasticsearch - ${elasticsearch.version} - compile + javax.servlet javax.servlet-api @@ -54,10 +52,7 @@ log4j log4j - 1.2.16 - runtime - @@ -65,38 +60,14 @@ org.apache.maven.plugins maven-compiler-plugin - 2.3.2 - - 1.6 - 1.6 - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.11 - - - **/*Tests.java - - org.apache.maven.plugins maven-source-plugin - 2.1.2 - - - attach-sources - - jar - - - + org.apache.maven.plugins maven-assembly-plugin - 2.3 false ${project.build.directory}/releases/ @@ -115,4 +86,12 @@ + + + + oss-snapshots + Sonatype OSS Snapshots + https://oss.sonatype.org/content/repositories/snapshots/ + + diff --git a/src/main/java/org/elasticsearch/wares/AbstractServletRestChannel.java b/src/main/java/org/elasticsearch/wares/AbstractServletRestChannel.java index 1b43100..f421764 100644 --- a/src/main/java/org/elasticsearch/wares/AbstractServletRestChannel.java +++ b/src/main/java/org/elasticsearch/wares/AbstractServletRestChannel.java @@ -31,12 +31,10 @@ * Base implementation of RestChannel responsible for mapping a * RestResponse to an HttpServletResponse. */ -abstract class AbstractServletRestChannel implements RestChannel { +abstract class AbstractServletRestChannel extends RestChannel { - final RestRequest restRequest; - - protected AbstractServletRestChannel(RestRequest restRequest) { - this.restRequest = restRequest; + protected AbstractServletRestChannel(RestRequest request, boolean detailedErrorsEnabled) { + super(request, detailedErrorsEnabled); } @Override @@ -44,29 +42,14 @@ public void sendResponse(RestResponse response) { HttpServletResponse resp = getServletResponse(); resp.setStatus(response.status().getStatus()); resp.setContentType(response.contentType()); - String opaque = restRequest.header("X-Opaque-Id"); + String opaque = request.header("X-Opaque-Id"); if (opaque != null) { resp.addHeader("X-Opaque-Id", opaque); } try { - int contentLength = response.contentLength(); - if (response.prefixContent() != null) { - contentLength += response.prefixContentLength(); - } - if (response.suffixContent() != null) { - contentLength += response.suffixContentLength(); - } - - resp.setContentLength(contentLength); - + resp.setContentLength(response.content().length()); 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()); - } + response.content().writeTo(out); out.close(); } catch (IOException e) { errorOccured(e); diff --git a/src/main/java/org/elasticsearch/wares/AsyncNodeServlet.java b/src/main/java/org/elasticsearch/wares/AsyncNodeServlet.java index 7a5ccf4..b777983 100644 --- a/src/main/java/org/elasticsearch/wares/AsyncNodeServlet.java +++ b/src/main/java/org/elasticsearch/wares/AsyncNodeServlet.java @@ -48,7 +48,8 @@ public void destroy() { protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { final AsyncContext asyncContext = req.startAsync(); ServletRestRequest request = new ServletRestRequest(req); - AsyncServletRestChannel channel = new AsyncServletRestChannel(request, asyncContext); + AsyncServletRestChannel channel = new AsyncServletRestChannel(request, asyncContext, + detailedErrorsEnabled); restController.dispatchRequest(request, channel); } @@ -56,8 +57,8 @@ static class AsyncServletRestChannel extends AbstractServletRestChannel { final AsyncContext asyncContext; - AsyncServletRestChannel(RestRequest restRequest, AsyncContext asyncContext) { - super(restRequest); + AsyncServletRestChannel(RestRequest restRequest, AsyncContext asyncContext, boolean detailedErrorsEnabled) { + super(restRequest, detailedErrorsEnabled); this.asyncContext = asyncContext; } diff --git a/src/main/java/org/elasticsearch/wares/NodeServlet.java b/src/main/java/org/elasticsearch/wares/NodeServlet.java index a1b4b66..5b51639 100644 --- a/src/main/java/org/elasticsearch/wares/NodeServlet.java +++ b/src/main/java/org/elasticsearch/wares/NodeServlet.java @@ -20,6 +20,7 @@ package org.elasticsearch.wares; import org.elasticsearch.common.settings.ImmutableSettings; +import org.elasticsearch.http.netty.NettyHttpServerTransport; import org.elasticsearch.node.Node; import org.elasticsearch.node.NodeBuilder; import org.elasticsearch.node.internal.InternalNode; @@ -53,54 +54,68 @@ public class NodeServlet extends HttpServlet { protected Node node; protected RestController restController; + + protected boolean detailedErrorsEnabled; @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 + final Object nodeAttribute = getServletContext().getAttribute(NODE_KEY); + if (nodeAttribute == null || !(nodeAttribute instanceof InternalNode)) { + if (nodeAttribute != null) { + getServletContext().log( + "Warning: overwriting attribute with key \"" + NODE_KEY + "\" and type \"" + + nodeAttribute.getClass().getName() + "\"."); } - } - - resourceAsStream = getServletContext().getResourceAsStream("/WEB-INF/elasticsearch.yml"); - if (resourceAsStream != null) { - settings.loadFromStream("/WEB-INF/elasticsearch.yml", resourceAsStream); - try { - resourceAsStream.close(); - } catch (IOException e) { - // ignore + 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 + } } - } - - Enumeration enumeration = getServletContext().getAttributeNames(); - - while (enumeration.hasMoreElements()) { - String key = enumeration.nextElement(); - - if (key.startsWith(NAME_PREFIX)) { - Object attribute = getServletContext().getAttribute(key); - - if (attribute != null) - attribute = attribute.toString(); - - settings.put(key.substring(NAME_PREFIX.length()), (String) attribute); + + resourceAsStream = getServletContext().getResourceAsStream("/WEB-INF/elasticsearch.yml"); + if (resourceAsStream != null) { + settings.loadFromStream("/WEB-INF/elasticsearch.yml", resourceAsStream); + try { + resourceAsStream.close(); + } catch (IOException e) { + // ignore + } } + + Enumeration enumeration = getServletContext().getAttributeNames(); + + while (enumeration.hasMoreElements()) { + String key = enumeration.nextElement(); + + if (key.startsWith(NAME_PREFIX)) { + Object attribute = getServletContext().getAttribute(key); + + if (attribute != null) + attribute = attribute.toString(); + + settings.put(key.substring(NAME_PREFIX.length()), (String) attribute); + } + } + + if (settings.get("http.enabled") == null) { + settings.put("http.enabled", false); + } + + node = NodeBuilder.nodeBuilder().settings(settings).node(); + getServletContext().setAttribute(NODE_KEY, node); + } else { + getServletContext().log("Using pre-initialized elasticsearch Node '" + getServletName() + "'"); + this.node = (InternalNode) nodeAttribute; } - - 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); + restController = ((InternalNode) node).injector().getInstance(RestController.class); + detailedErrorsEnabled = this.node.settings().getAsBoolean(NettyHttpServerTransport.SETTING_HTTP_DETAILED_ERRORS_ENABLED, true); } @Override @@ -114,7 +129,7 @@ public void destroy() { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletRestRequest request = new ServletRestRequest(req); - ServletRestChannel channel = new ServletRestChannel(request, resp); + ServletRestChannel channel = new ServletRestChannel(request, resp, this.detailedErrorsEnabled); try { restController.dispatchRequest(request, channel); channel.latch.await(); @@ -134,8 +149,8 @@ static class ServletRestChannel extends AbstractServletRestChannel { IOException sendFailure; - ServletRestChannel(RestRequest restRequest, HttpServletResponse resp) { - super(restRequest); + ServletRestChannel(RestRequest restRequest, HttpServletResponse resp, boolean detailedErrorsEnabled) { + super(restRequest, detailedErrorsEnabled); this.resp = resp; this.latch = new CountDownLatch(1); } diff --git a/src/main/java/org/elasticsearch/wares/ServletRestRequest.java b/src/main/java/org/elasticsearch/wares/ServletRestRequest.java index abd1248..40ac7ac 100644 --- a/src/main/java/org/elasticsearch/wares/ServletRestRequest.java +++ b/src/main/java/org/elasticsearch/wares/ServletRestRequest.java @@ -81,11 +81,6 @@ public boolean hasContent() { return content.length > 0; } - @Override - public boolean contentUnsafe() { - return false; - } - @Override public BytesReference content() { return new BytesArray(content);