You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ace.apache.org by ja...@apache.org on 2013/10/24 11:16:58 UTC
svn commit: r1535322 - in /ace/trunk/org.apache.ace.deployment:
src/org/apache/ace/deployment/servlet/
test/org/apache/ace/deployment/servlet/
Author: jawi
Date: Thu Oct 24 09:16:58 2013
New Revision: 1535322
URL: http://svn.apache.org/r1535322
Log:
ACE-330 - limit DP-versions for a target:
- some fixes found by monkey testing the earlier fix;
- basically the requested from-version needs to be verified
if it is still present before streaming back a DP;
- took the liberty of cleaning up the code a bit for sake
of readability;
- updated the unit tests to cover the new situation.
Added:
ace/trunk/org.apache.ace.deployment/src/org/apache/ace/deployment/servlet/DefaultDeploymentProcessor.java (with props)
Modified:
ace/trunk/org.apache.ace.deployment/src/org/apache/ace/deployment/servlet/DeploymentServlet.java
ace/trunk/org.apache.ace.deployment/test/org/apache/ace/deployment/servlet/DeploymentServletTest.java
Added: ace/trunk/org.apache.ace.deployment/src/org/apache/ace/deployment/servlet/DefaultDeploymentProcessor.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.deployment/src/org/apache/ace/deployment/servlet/DefaultDeploymentProcessor.java?rev=1535322&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.deployment/src/org/apache/ace/deployment/servlet/DefaultDeploymentProcessor.java (added)
+++ ace/trunk/org.apache.ace.deployment/src/org/apache/ace/deployment/servlet/DefaultDeploymentProcessor.java Thu Oct 24 09:16:58 2013
@@ -0,0 +1,62 @@
+/*
+ * 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.ace.deployment.servlet;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.ace.deployment.processor.DeploymentProcessor;
+
+/**
+ * Provides a default deployment processor that simply streams all content from the deployment package back to the
+ * client.
+ */
+public class DefaultDeploymentProcessor implements DeploymentProcessor {
+
+ @Override
+ public void process(InputStream inputStream, HttpServletRequest request, HttpServletResponse response) throws IOException {
+ OutputStream output = response.getOutputStream();
+
+ try {
+ byte[] buffer = new byte[1024 * 32];
+ for (int bytesRead = inputStream.read(buffer); bytesRead != -1; bytesRead = inputStream.read(buffer)) {
+ output.write(buffer, 0, bytesRead);
+ }
+ }
+ finally {
+ closeSilently(output);
+ }
+ }
+
+ private void closeSilently(Closeable output) {
+ try {
+ if (output != null) {
+ output.close();
+ }
+ }
+ catch (IOException e) {
+ // Ignore; nothing we can do about this...
+ }
+ }
+}
Propchange: ace/trunk/org.apache.ace.deployment/src/org/apache/ace/deployment/servlet/DefaultDeploymentProcessor.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: ace/trunk/org.apache.ace.deployment/src/org/apache/ace/deployment/servlet/DeploymentServlet.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.deployment/src/org/apache/ace/deployment/servlet/DeploymentServlet.java?rev=1535322&r1=1535321&r2=1535322&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.deployment/src/org/apache/ace/deployment/servlet/DeploymentServlet.java (original)
+++ ace/trunk/org.apache.ace.deployment/src/org/apache/ace/deployment/servlet/DeploymentServlet.java Thu Oct 24 09:16:58 2013
@@ -79,6 +79,46 @@ public class DeploymentServlet extends H
private volatile boolean m_useAuth = false;
+ public void addProcessor(ServiceReference ref, DeploymentProcessor processor) {
+ String key = (String) ref.getProperty(PROCESSOR);
+ if (key != null) {
+ m_processors.putIfAbsent(key, processor);
+ }
+ else {
+ m_log.log(LogService.LOG_WARNING, "Deployment processor ignored, required service property '" + PROCESSOR + "' is missing.");
+ }
+ }
+
+ @Override
+ public String getServletInfo() {
+ return "Ace Deployment Servlet Endpoint";
+ }
+
+ public void removeProcessor(ServiceReference ref, DeploymentProcessor processor) {
+ String key = (String) ref.getProperty(PROCESSOR);
+ // we do not log this here again, we already did so in 'addProcessor'
+ if (key != null) {
+ m_processors.remove(key);
+ }
+ }
+
+ @Override
+ public void updated(Dictionary settings) throws ConfigurationException {
+ if (settings != null) {
+ String useAuthString = (String) settings.get(KEY_USE_AUTHENTICATION);
+ if (useAuthString == null
+ || !("true".equalsIgnoreCase(useAuthString) || "false".equalsIgnoreCase(useAuthString))) {
+ throw new ConfigurationException(KEY_USE_AUTHENTICATION, "Missing or invalid value!");
+ }
+ boolean useAuth = Boolean.parseBoolean(useAuthString);
+
+ m_useAuth = useAuth;
+ }
+ else {
+ m_useAuth = false;
+ }
+ }
+
/**
* Responds to GET requests sent to this endpoint, the response depends on the requested path: <li>
* http://host/endpoint/targetid/versions/ returns a list of versions available for the specified target <li>
@@ -128,31 +168,11 @@ public class DeploymentServlet extends H
String targetID = pathElements[1];
String version = pathElements[3];
- String current = request.getParameter(CURRENT);
-
- List<ArtifactData> artifacts;
- if (current != null) {
- artifacts = m_provider.getBundleData(targetID, current, version);
- } else {
- artifacts = m_provider.getBundleData(targetID, version);
- }
-
- long dpSize = 0L;
- for (ArtifactData artifactData : artifacts) {
- long size = artifactData.getSize();
- if (size > 0L) {
- dpSize += size;
- }
- else {
- dpSize = -1L;
- break; // cannot determine the DP size...
- }
- }
-
response.setContentType(DP_MIMETYPE);
+ long dpSize = estimateDeploymentPackageSize(request, targetID, version);
if (dpSize > 0) {
- response.addHeader(HEADER_DPSIZE, Long.toString((long) (DPSIZE_FACTOR * dpSize)));
+ response.addHeader(HEADER_DPSIZE, Long.toString(dpSize));
}
}
}
@@ -209,39 +229,85 @@ public class DeploymentServlet extends H
return true;
}
+ private long estimateDeploymentPackageSize(HttpServletRequest request, String targetID, String version) throws IOException, OverloadedException, AceRestException {
+ List<String> versions = getVersions(targetID);
+ String current = request.getParameter(CURRENT);
+
+ List<ArtifactData> artifacts;
+ if (current != null && versions.contains(current)) {
+ artifacts = m_provider.getBundleData(targetID, current, version);
+ }
+ else {
+ artifacts = m_provider.getBundleData(targetID, version);
+ }
+
+ long dpSize = 0L;
+ for (ArtifactData artifactData : artifacts) {
+ long size = artifactData.getSize();
+ if (size > 0L) {
+ dpSize += size;
+ }
+ else {
+ // cannot determine the DP size...
+ return -1L;
+ }
+ }
+ return (long) (DPSIZE_FACTOR * dpSize);
+ }
+
+ private InputStream getDeploymentPackageStream(String targetID, String version, HttpServletRequest request, List<String> versions) throws IOException {
+ String current = request.getParameter(CURRENT);
+
+ // Determine whether we should return a fix-package, or a complete deployment package. Keep in consideration
+ // that due to ACE-330, the given current-version can already be purged from the repository...
+ if (current != null && versions.contains(current)) {
+ m_log.log(LogService.LOG_DEBUG, "Generating deployment fix-package for " + current + " => " + version);
+
+ return m_streamGenerator.getDeploymentPackage(targetID, current, version);
+ }
+
+ m_log.log(LogService.LOG_DEBUG, "Generating deployment package for " + version);
+
+ return m_streamGenerator.getDeploymentPackage(targetID, version);
+ }
+
/**
- * Serve the case where requested path is like: http://host/endpoint/targetid/versions/ returns a list of versions
- * available for the specified target
- *
- * @param targetID
- * the target ID for which to return all available versions;
- * @param response
- * response object.
+ * @return the requested {@link DeploymentProcessor}, or <code>null</code> in case none is requested.
+ * @throws AceRestException
+ * in case a non-existing deployment processor was requested.
*/
- private void handleVersionsRequest(String targetID, HttpServletResponse response) throws OverloadedException, AceRestException {
- ServletOutputStream output = null;
+ private DeploymentProcessor getDeploymentProcessor(HttpServletRequest request) throws AceRestException {
+ String processor = request.getParameter(PROCESSOR);
+ if (processor != null) {
+ DeploymentProcessor deploymentProcessor = m_processors.get(processor);
+ if (deploymentProcessor == null) {
+ throw new AceRestException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Could not find a deployment processor called: " + processor);
+ }
- List<String> versions = getVersions(targetID);
+ m_log.log(LogService.LOG_DEBUG, "Using deployment processor " + processor);
- response.setContentType(TEXT_MIMETYPE);
+ return deploymentProcessor;
+ }
+
+ m_log.log(LogService.LOG_DEBUG, "Using default deployment processor...");
+
+ return new DefaultDeploymentProcessor();
+ }
+
+ private List<String> getVersions(String targetID) throws OverloadedException, AceRestException {
try {
- output = response.getOutputStream();
- for (String version : versions) {
- output.print(version);
- output.print("\n");
- }
+ return m_provider.getVersions(targetID);
}
- catch (IOException e) {
- throw new AceRestException(HttpServletResponse.SC_BAD_REQUEST, "Request URI is invalid");
+ catch (IllegalArgumentException iae) {
+ throw new AceRestException(HttpServletResponse.SC_NOT_FOUND, "Unknown target (" + targetID + ")");
}
- finally {
- tryClose(output);
+ catch (IOException ioe) {
+ m_log.log(LogService.LOG_WARNING, "Error getting available versions.", ioe);
+ throw new AceRestException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Error getting available versions.");
}
}
private void handlePackageDelivery(String targetID, String version, HttpServletRequest request, HttpServletResponse response) throws OverloadedException, AceRestException {
- ServletOutputStream output = null;
-
List<String> versions = getVersions(targetID);
if (!versions.contains(version)) {
throw new AceRestException(HttpServletResponse.SC_NOT_FOUND, "Unknown version (" + version + ")");
@@ -252,33 +318,15 @@ public class DeploymentServlet extends H
response = new ContentRangeResponseWrapper(request, response);
response.setContentType(DP_MIMETYPE);
- String current = request.getParameter(CURRENT);
- String processor = request.getParameter(PROCESSOR);
+ // determine the deployment processor early, as to avoid having to create a complete deployment package in
+ // case of a missing/incorrect requested processor...
+ DeploymentProcessor deploymentProcessor = getDeploymentProcessor(request);
- InputStream inputStream;
- if (current != null) {
- inputStream = m_streamGenerator.getDeploymentPackage(targetID, current, version);
- }
- else {
- inputStream = m_streamGenerator.getDeploymentPackage(targetID, version);
- }
+ // get the input stream to the deployment package...
+ InputStream inputStream = getDeploymentPackageStream(targetID, version, request, versions);
- if (processor != null) {
- DeploymentProcessor deploymentProcessor = m_processors.get(processor);
- if (deploymentProcessor != null) {
- deploymentProcessor.process(inputStream, request, response);
- return;
- }
- else {
- throw new AceRestException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Could not find a deployment processor called: " + processor);
- }
- }
-
- output = response.getOutputStream();
- byte[] buffer = new byte[1024 * 32];
- for (int bytesRead = inputStream.read(buffer); bytesRead != -1; bytesRead = inputStream.read(buffer)) {
- output.write(buffer, 0, bytesRead);
- }
+ // process and send back the results to the client...
+ deploymentProcessor.process(inputStream, request, response);
}
catch (IllegalArgumentException e) {
throw (AceRestException) new AceRestException(HttpServletResponse.SC_BAD_REQUEST, "Request URI is invalid").initCause(e);
@@ -286,21 +334,35 @@ public class DeploymentServlet extends H
catch (IOException e) {
throw (AceRestException) new AceRestException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Could not deliver package").initCause(e);
}
- finally {
- tryClose(output);
- }
}
- private List<String> getVersions(String targetID) throws OverloadedException, AceRestException {
+ /**
+ * Serve the case where requested path is like: http://host/endpoint/targetid/versions/ returns a list of versions
+ * available for the specified target
+ *
+ * @param targetID
+ * the target ID for which to return all available versions;
+ * @param response
+ * response object.
+ */
+ private void handleVersionsRequest(String targetID, HttpServletResponse response) throws OverloadedException, AceRestException {
+ ServletOutputStream output = null;
+
+ List<String> versions = getVersions(targetID);
+
+ response.setContentType(TEXT_MIMETYPE);
try {
- return m_provider.getVersions(targetID);
+ output = response.getOutputStream();
+ for (String version : versions) {
+ output.print(version);
+ output.print("\n");
+ }
}
- catch (IllegalArgumentException iae) {
- throw new AceRestException(HttpServletResponse.SC_NOT_FOUND, "Unknown target (" + targetID + ")");
+ catch (IOException e) {
+ throw new AceRestException(HttpServletResponse.SC_BAD_REQUEST, "Request URI is invalid");
}
- catch (IOException ioe) {
- m_log.log(LogService.LOG_WARNING, "Error getting available versions.", ioe);
- throw new AceRestException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Error getting available versions.");
+ finally {
+ tryClose(output);
}
}
@@ -311,8 +373,7 @@ public class DeploymentServlet extends H
}
}
catch (IOException e) {
- m_log.log(LogService.LOG_WARNING, "Exception trying to close stream after request. ", e);
- throw new RuntimeException(e);
+ m_log.log(LogService.LOG_WARNING, "Exception trying to close stream after request.", e);
}
}
@@ -339,44 +400,4 @@ public class DeploymentServlet extends H
}
return elements;
}
-
- @Override
- public String getServletInfo() {
- return "Ace Deployment Servlet Endpoint";
- }
-
- @Override
- public void updated(Dictionary settings) throws ConfigurationException {
- if (settings != null) {
- String useAuthString = (String) settings.get(KEY_USE_AUTHENTICATION);
- if (useAuthString == null
- || !("true".equalsIgnoreCase(useAuthString) || "false".equalsIgnoreCase(useAuthString))) {
- throw new ConfigurationException(KEY_USE_AUTHENTICATION, "Missing or invalid value!");
- }
- boolean useAuth = Boolean.parseBoolean(useAuthString);
-
- m_useAuth = useAuth;
- }
- else {
- m_useAuth = false;
- }
- }
-
- public void addProcessor(ServiceReference ref, DeploymentProcessor processor) {
- String key = (String) ref.getProperty(PROCESSOR);
- if (key == null) {
- m_log.log(LogService.LOG_WARNING, "Deployment processor ignored, required service property '" + PROCESSOR + "' is missing.");
- return;
- }
- m_processors.putIfAbsent(key, processor);
- }
-
- public void removeProcessor(ServiceReference ref, DeploymentProcessor processor) {
- String key = (String) ref.getProperty(PROCESSOR);
- if (key == null) {
- // we do not log this here again, we already did so in 'addProcessor'
- return;
- }
- m_processors.remove(key);
- }
}
Modified: ace/trunk/org.apache.ace.deployment/test/org/apache/ace/deployment/servlet/DeploymentServletTest.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.deployment/test/org/apache/ace/deployment/servlet/DeploymentServletTest.java?rev=1535322&r1=1535321&r2=1535322&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.deployment/test/org/apache/ace/deployment/servlet/DeploymentServletTest.java (original)
+++ ace/trunk/org.apache.ace.deployment/test/org/apache/ace/deployment/servlet/DeploymentServletTest.java Thu Oct 24 09:16:58 2013
@@ -24,6 +24,9 @@ import static org.apache.ace.test.utils.
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -53,7 +56,7 @@ public class DeploymentServletTest {
private DeploymentServlet m_servlet;
private long m_artifactSize;
-
+
// request state
private HttpServletRequest m_request;
private String m_requestCurrentParameter;
@@ -106,7 +109,9 @@ public class DeploymentServletTest {
}
@Test(groups = { UNIT })
- public void getFixPackageForExistingTarget() throws Exception {
+ public void getFixPackageForExistingTargetWithNonExistingFromVersion() throws Exception {
+ // try to request a version range with a non-existing from-version, should cause a complete (non-fix) package to
+ // be returned...
m_requestPathInfo = "/existing/versions/2.0.0";
m_requestCurrentParameter = "1.0.0";
m_servlet.doGet(m_request, m_response);
@@ -114,7 +119,20 @@ public class DeploymentServletTest {
assertResponseOutputSize(100);
assertGeneratorTargetId("existing");
assertGeneratorToVersion("2.0.0");
- assertGeneratorFromVersion("1.0.0");
+ assertGeneratorFromVersion(null);
+ }
+
+ @Test(groups = { UNIT })
+ public void getFixPackageForExistingTargetWithExistingFromVersion() throws Exception {
+ // try to request a version range with an existing from-version, should cause a fix package to be returned...
+ m_requestPathInfo = "/existing/versions/2.0.0";
+ m_requestCurrentParameter = "2.0.0";
+ m_servlet.doGet(m_request, m_response);
+ assertResponseCode(HttpServletResponse.SC_OK);
+ assertResponseOutputSize(100);
+ assertGeneratorTargetId("existing");
+ assertGeneratorToVersion("2.0.0");
+ assertGeneratorFromVersion("2.0.0");
}
@Test
@@ -253,7 +271,7 @@ public class DeploymentServletTest {
m_requestPathInfo = "/existing/versions";
m_servlet.doGet(m_request, m_response);
assertResponseCode(HttpServletResponse.SC_OK);
- assert "2.0.0\n".equals(m_responseOutputStream.toString()) : "Expected to get version 2.0.0 in the response";
+ assertEquals(m_responseOutputStream.toString(), "2.0.0\n", "Expected to get version 2.0.0 in the response");
}
@Test
@@ -408,31 +426,31 @@ public class DeploymentServletTest {
}
private void assertGeneratorFromVersion(String version) {
- assert m_generatorFromVersion.equals(version) : "Wrong version.";
+ assertEquals(m_generatorFromVersion, version, "Wrong from-version");
}
private void assertGeneratorTargetId(String id) {
- assert m_generatorId.equals(id) : "Wrong target ID.";
+ assertEquals(m_generatorId, id, "Wrong target ID");
}
private void assertGeneratorToVersion(String version) {
- assert m_generatorToVersion.equals(version) : "Wrong version.";
+ assertEquals(m_generatorToVersion, version, "Wrong to-version");
}
private void assertResponseCode(int value) throws Exception {
- assert m_responseStatus == value : "We should have got response code " + value + " but got " + m_responseStatus;
+ assertEquals(m_responseStatus, value, "Incorrect response code from server");
}
private void assertResponseHeaderNotPresent(String name) throws Exception {
- assert !m_responseHeaders.containsKey(name) : "Expected response " + name + " header to NOT be set";
+ assertFalse(m_responseHeaders.containsKey(name), "Expected response " + name + " header to NOT be set");
}
private void assertResponseHeaderValue(String name, String value) throws Exception {
- assert m_responseHeaders.containsKey(name) : "Expected response " + name + " header to be set";
- assert m_responseHeaders.get(name).equals(value) : "Expected " + name + " header with value '" + value + "' and got '" + m_responseHeaders.get(name) + "'";
+ assertTrue(m_responseHeaders.containsKey(name), "Expected response " + name + " header to be set");
+ assertEquals(m_responseHeaders.get(name), value, "Unexpected response header");
}
private void assertResponseOutputSize(long size) throws Exception {
- assert m_responseOutputStream.size() == size : "We should have got a (dummy) deployment package of " + size + " bytes but got " + m_responseOutputStream.size();
+ assertEquals(m_responseOutputStream.size(), size, "We should have got a (dummy) deployment package of");
}
}