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/09/13 12:54:34 UTC
svn commit: r1522863 [1/2] - in /ace/trunk:
org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/
org.apache.ace.agent/src/org/apache/ace/agent/
org.apache.ace.agent/src/org/apache/ace/agent/impl/
org.apache.ace.agent/test/org/apache/ace/agent/impl/
Author: jawi
Date: Fri Sep 13 10:54:34 2013
New Revision: 1522863
URL: http://svn.apache.org/r1522863
Log:
ACE-323 - smarter handling of installation failures:
- refactored the installation logic to be the same for installing
deployment packages as well as agent updates;
- introduced a generic interface for handling updates, this way
we can align the installation of agent updates and DPs;
- no longer leaking OSGi-specific exceptions upon failed
installations;
- refactored/simplified the download handling.
Added:
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/InstallationFailedException.java (with props)
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/UpdateHandler.java (with props)
Modified:
ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/AgentDeploymentTest.java
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/AgentUpdateHandler.java
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DeploymentHandler.java
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DownloadHandle.java
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DownloadHandler.java
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DownloadResult.java
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/Activator.java
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/AgentUpdateHandlerImpl.java
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DefaultController.java
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DeploymentHandlerImpl.java
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DownloadCallableImpl.java
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DownloadHandleImpl.java
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DownloadHandlerImpl.java
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DownloadResultImpl.java
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/InternalConstants.java
ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/UpdateHandlerBase.java
ace/trunk/org.apache.ace.agent/test/org/apache/ace/agent/impl/CustomControllerTest.java
ace/trunk/org.apache.ace.agent/test/org/apache/ace/agent/impl/DeploymentHandlerImplTest.java
ace/trunk/org.apache.ace.agent/test/org/apache/ace/agent/impl/DownloadHandlerTest.java
Modified: ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/AgentDeploymentTest.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/AgentDeploymentTest.java?rev=1522863&r1=1522862&r2=1522863&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/AgentDeploymentTest.java (original)
+++ ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/AgentDeploymentTest.java Fri Sep 13 10:54:34 2013
@@ -116,15 +116,15 @@ public class AgentDeploymentTest extends
m_packages.put(testPackage.getVersion().toString(), testPackage);
}
- public synchronized void setFailure(Failure failure) {
- m_failure = failure;
- }
-
public synchronized void reset() {
m_failure = null;
m_packages.clear();
}
+ public synchronized void setFailure(Failure failure) {
+ m_failure = failure;
+ }
+
@Override
protected synchronized void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String pathinfoTail = req.getPathInfo().replaceFirst("/" + m_agentId + "/versions/?", "");
@@ -199,16 +199,25 @@ public class AgentDeploymentTest extends
}
private static class TestEventListener implements EventListener {
- private final Map<String, List<Map<String, String>>> m_topics = new HashMap<String, List<Map<String, String>>>();
+ private static boolean matches(Map<String, String> source, Map<String, String> target) {
+ for (Map.Entry<String, String> sourceEntry : source.entrySet()) {
+ String sourceKey = sourceEntry.getKey();
+ String sourceValue = sourceEntry.getValue();
- public Map<String, List<Map<String, String>>> getTopics() {
- Map<String, List<Map<String, String>>> result;
- synchronized (m_topics) {
- result = new HashMap<String, List<Map<String, String>>>(m_topics);
+ if (!target.containsKey(sourceKey)) {
+ return false;
+ }
+ String targetValue = target.get(sourceKey);
+ if (!sourceValue.equals(targetValue)) {
+ return false;
+ }
}
- return result;
+
+ return true;
}
+ private final Map<String, List<Map<String, String>>> m_topics = new HashMap<String, List<Map<String, String>>>();
+
public boolean containsTopic(String topic) {
synchronized (m_topics) {
return m_topics.containsKey(topic);
@@ -230,6 +239,14 @@ public class AgentDeploymentTest extends
}
}
+ public Map<String, List<Map<String, String>>> getTopics() {
+ Map<String, List<Map<String, String>>> result;
+ synchronized (m_topics) {
+ result = new HashMap<String, List<Map<String, String>>>(m_topics);
+ }
+ return result;
+ }
+
@Override
public void handle(String topic, Map<String, String> payload) {
if (LOGLEVEL == Levels.DEBUG) {
@@ -245,23 +262,6 @@ public class AgentDeploymentTest extends
payloads.add(payload);
}
}
-
- private static boolean matches(Map<String, String> source, Map<String, String> target) {
- for (Map.Entry<String, String> sourceEntry : source.entrySet()) {
- String sourceKey = sourceEntry.getKey();
- String sourceValue = sourceEntry.getValue();
-
- if (!target.containsKey(sourceKey)) {
- return false;
- }
- String targetValue = target.get(sourceKey);
- if (!sourceValue.equals(targetValue)) {
- return false;
- }
- }
-
- return true;
- }
}
private static class TestPackage {
@@ -298,8 +298,8 @@ public class AgentDeploymentTest extends
}
}
- private static final String AGENT_DEPLOYMENT_COMPLETE = "agent/deployment/COMPLETE";
- private static final String AGENT_DEPLOYMENT_INSTALL = "agent/deployment/INSTALL";
+ private static final String AGENT_INSTALLATION_START = "agent/installation/START";
+ private static final String AGENT_INSTALLATION_COMPLETE = "agent/installation/COMPLETE";
private static final String AGENT_ID = "007";
private static final String TEST_BUNDLE_NAME_PREFIX = "test.bundle";
@@ -345,11 +345,11 @@ public class AgentDeploymentTest extends
// Check our event log, should contain all handled events...
Map<String, List<Map<String, String>>> topics = m_listener.getTopics();
- List<Map<String, String>> events = topics.get(AGENT_DEPLOYMENT_INSTALL);
+ List<Map<String, String>> events = topics.get(AGENT_INSTALLATION_START);
// should contain exactly three different elements...
assertEquals(events.toString(), 3, events.size());
- events = topics.get(AGENT_DEPLOYMENT_COMPLETE);
+ events = topics.get(AGENT_INSTALLATION_COMPLETE);
// should contain exactly three different elements...
assertEquals(events.toString(), 3, events.size());
}
@@ -476,6 +476,29 @@ public class AgentDeploymentTest extends
expectSuccessfulDeployment(m_package1, Failure.VERSIONS_RETRY_AFTER);
}
+ /**
+ * Tests the deployment of "streamed" deployment packages simulating an "unstable" connection.
+ */
+ public void testStreamingDeploymentWithUnstableConnection() throws Exception {
+ setupAgentForStreamingDeployment();
+
+ expectSuccessfulDeployment(m_package1, null);
+
+ expectFailedDeployment(m_package6, Failure.EMPTY_STREAM);
+ waitForInstalledVersion(V1_0_0);
+
+ expectFailedDeployment(m_package6, Failure.CORRUPT_STREAM);
+ waitForInstalledVersion(V1_0_0);
+
+ expectFailedDeployment(m_package6, Failure.ABORT_STREAM);
+ waitForInstalledVersion(V1_0_0);
+
+ expectFailedDeployment(m_package6, Failure.EMPTY_STREAM);
+ waitForInstalledVersion(V1_0_0);
+
+ expectFailedDeployment(m_package6, null);
+ }
+
@Override
protected void configureAdditionalServices() throws Exception {
TestBundle bundle1v1 = new TestBundle(TEST_BUNDLE_NAME_PREFIX.concat("1"), V1_0_0);
@@ -542,27 +565,27 @@ public class AgentDeploymentTest extends
return props;
}
- private void expectSuccessfulDeployment(TestPackage dpackage, Failure failure) throws Exception {
- deployPackage(dpackage, failure);
-
- waitForEventReceived(AGENT_DEPLOYMENT_INSTALL);
- waitForEventReceived(AGENT_DEPLOYMENT_COMPLETE, "successful", "true");
-
- waitForInstalledVersion(dpackage.getVersion());
+ private void deployPackage(TestPackage dpackage, Failure failure) {
+ synchronized (m_servlet) {
+ m_servlet.setFailure(failure);
+ m_servlet.addPackage(dpackage);
+ }
}
private void expectFailedDeployment(TestPackage dpackage, Failure failure) throws Exception {
deployPackage(dpackage, failure);
- waitForEventReceived(AGENT_DEPLOYMENT_INSTALL);
- waitForEventReceived(AGENT_DEPLOYMENT_COMPLETE, "successful", "false");
+ waitForEventReceived(AGENT_INSTALLATION_START);
+ waitForEventReceived(AGENT_INSTALLATION_COMPLETE, "successful", "false");
}
- private void deployPackage(TestPackage dpackage, Failure failure) {
- synchronized (m_servlet) {
- m_servlet.setFailure(failure);
- m_servlet.addPackage(dpackage);
- }
+ private void expectSuccessfulDeployment(TestPackage dpackage, Failure failure) throws Exception {
+ deployPackage(dpackage, failure);
+
+ waitForEventReceived(AGENT_INSTALLATION_START);
+ waitForEventReceived(AGENT_INSTALLATION_COMPLETE, "successful", "true");
+
+ waitForInstalledVersion(dpackage.getVersion());
}
private void setupAgentForNonStreamingDeployment() throws Exception {
Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/AgentUpdateHandler.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/AgentUpdateHandler.java?rev=1522863&r1=1522862&r2=1522863&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/AgentUpdateHandler.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/AgentUpdateHandler.java Fri Sep 13 10:54:34 2013
@@ -18,32 +18,9 @@
*/
package org.apache.ace.agent;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.SortedSet;
-
-import org.osgi.framework.Version;
-
/**
* Agent context delegate interface that is responsible for managing agent updates.
*/
-public interface AgentUpdateHandler {
-
- /** Returns the locally installed version of the agent. */
- Version getInstalledVersion();
-
- /** Returns the versions available on the server. */
- SortedSet<Version> getAvailableVersions() throws RetryAfterException, IOException;
-
- /** Returns an input stream for the update of the agent. */
- InputStream getInputStream(Version version) throws RetryAfterException, IOException;
-
- /** Returns a download handle to download the update of the agent. */
- DownloadHandle getDownloadHandle(Version version) throws RetryAfterException, IOException;
-
- /** Returns the size of the update of the agent. */
- long getSize(Version version) throws RetryAfterException, IOException;
-
- /** Installs the update of the agent. */
- void install(InputStream stream) throws IOException;
+public interface AgentUpdateHandler extends UpdateHandler {
+ // No additional methods
}
Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DeploymentHandler.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DeploymentHandler.java?rev=1522863&r1=1522862&r2=1522863&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DeploymentHandler.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DeploymentHandler.java Fri Sep 13 10:54:34 2013
@@ -18,71 +18,9 @@
*/
package org.apache.ace.agent;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.SortedSet;
-
-import org.osgi.framework.Version;
-import org.osgi.service.deploymentadmin.DeploymentException;
-
/**
* Agent context delegate interface that provides the deployment functions.
*/
-public interface DeploymentHandler {
-
- /**
- * Return the installed deployment package version for this agent.
- *
- * @return The installed version, {@link Version.emptyVersion} if no packages have been installed
- */
- Version getInstalledVersion();
-
- /**
- * Return the sorted set of available deployment package versions as reported by the server.
- *
- * @return The sorted set of versions, may be empty
- * @throws RetryAfterException If the server indicates it is too busy with a Retry-After header
- * @throws IOException If the connection to the server fails
- */
- SortedSet<Version> getAvailableVersions() throws RetryAfterException, IOException;
-
- /**
- * Return the estimated size for a deployment package as reported by the server.
- *
- * @param version The version of the package
- * @param fixPackage Request the server for a fix-package
- * @return The estimated size in bytes, <code>-1</code> indicates the size is unknown
- * @throws RetryAfterException If the server indicates it is too busy with a Retry-After header
- * @throws IOException If the connection to the server fails
- */
- long getPackageSize(Version version, boolean fixPackage) throws RetryAfterException, IOException;
-
- /**
- * Returns the {@link InputStream} for a deployment package.
- *
- * @param version The version of the deployment package
- * @param fixPackage Request the server for a fix-package
- * @return The input-stream for the deployment package
- * @throws RetryAfterException If the server indicates it is too busy with a Retry-After header
- * @throws IOException If the connection to the server fails
- */
- InputStream getInputStream(Version version, boolean fixPackage) throws RetryAfterException, IOException;
-
- /**
- * Return the {@link DownloadHandle} for a deployment package.
- *
- * @param version The version of the deployment package
- * @param fixPackage Request the server for a fix-package
- * @return The download handle
- */
- DownloadHandle getDownloadHandle(Version version, boolean fixPackage) throws RetryAfterException, IOException;
-
- /**
- * Install a deployment package from an input stream.
- *
- * @param inputStream The inputStream, not <code>null</code>
- * @throws IOException If reading the input stream fails.
- */
- // TODO should we expose the foreign exception?
- void deployPackage(InputStream inputStream) throws DeploymentException, IOException;
+public interface DeploymentHandler extends UpdateHandler {
+ // No additional methods
}
Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DownloadHandle.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DownloadHandle.java?rev=1522863&r1=1522862&r2=1522863&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DownloadHandle.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DownloadHandle.java Fri Sep 13 10:54:34 2013
@@ -18,6 +18,8 @@
*/
package org.apache.ace.agent;
+import java.util.concurrent.TimeUnit;
+
/**
* A {@link DownloadHandle} provides control over an asynchronous download and access to the resulting file when the it
* is completed. <br/>
@@ -30,76 +32,50 @@ package org.apache.ace.agent;
* <ul>
*/
public interface DownloadHandle {
-
- /**
- * Size of the buffer used while downloading the content stream.
- */
- int DEFAULT_READBUFFER_SIZE = 1024;
-
/**
- * Callback interface; when registered the progress method will be invoked while downloading the content stream for
- * every {@link READBUFFER_SIZE} bytes.
+ * Callback interface; when registered the completed method will be invoked when the download terminates for any
+ * reason.
*/
- interface ProgressListener {
+ interface DownloadProgressListener {
/**
* Called while downloading the content stream.
*
- * @param contentLength The total length of the content or -1 if unknown.
- * @param progress The number of bytes that has been received so far.
+ * @param bytesRead
+ * The number of bytes that has been received so far;
+ * @param totalBytes
+ * The total length of the content or -1 if unknown.
*/
- void progress(long contentLength, long progress);
- }
+ void progress(long bytesRead, long totalBytes);
- /**
- * Callback interface; when registered the completed method will be invoked when the download terminates for any
- * reason.
- *
- */
- interface ResultListener {
/**
* Called when a download terminates.
*
- * @param result The result of the download.
+ * @param result
+ * The result of the download.
*/
void completed(DownloadResult result);
}
/**
- * Registers the progress listener.
- *
- * @param listener The progress listener.
- * @return this
- */
- DownloadHandle setProgressListener(ProgressListener listener);
-
- /**
- * Registers the completion listener.
- *
- * @param listener The completion listener.
- * @return this
+ * Starts the download, reporting the result and progress to the supplied listeners.
*/
- DownloadHandle setCompletionListener(ResultListener listener);
+ void start(DownloadProgressListener listener);
/**
- * Starts the download.
+ * Convenience method to start the download and block until it is finished.
*
- * @return this
+ * @param timeout
+ * the timeout to wait for a result;
+ * @param unit
+ * the unit of the timeout to wait for a result.
+ * @return the download result, never <code>null</code>.
*/
- DownloadHandle start();
+ DownloadResult startAndAwaitResult(long timeout, TimeUnit unit) throws InterruptedException;
/**
* Pauses the download.
- *
- * @return this
- */
- DownloadHandle stop();
-
- /**
- * Retrieves the download result. Will wait for completion before returning.
- *
- * @return The result of the download
*/
- DownloadResult result();
+ void stop();
/**
* Releases any resources that may be held by the handle.
Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DownloadHandler.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DownloadHandler.java?rev=1522863&r1=1522862&r2=1522863&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DownloadHandler.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DownloadHandler.java Fri Sep 13 10:54:34 2013
@@ -34,5 +34,6 @@ public interface DownloadHandler {
DownloadHandle getHandle(URL url);
// TODO named handlers (resume over urls)
+ @Deprecated
DownloadHandle getHandle(URL url, int readBufferSize);
}
Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DownloadResult.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DownloadResult.java?rev=1522863&r1=1522862&r2=1522863&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DownloadResult.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/DownloadResult.java Fri Sep 13 10:54:34 2013
@@ -20,8 +20,6 @@ package org.apache.ace.agent;
import java.io.IOException;
import java.io.InputStream;
-import java.util.List;
-import java.util.Map;
/**
* Represents the result of a download task.
@@ -44,12 +42,10 @@ public interface DownloadResult {
InputStream getInputStream() throws IOException;
/**
- * @return
+ * @return the result code
*/
int getCode();
- Map<String, List<String>> getHeaders();
-
/**
* Return the cause of an unsuccessful download.
*
Added: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/InstallationFailedException.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/InstallationFailedException.java?rev=1522863&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/InstallationFailedException.java (added)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/InstallationFailedException.java Fri Sep 13 10:54:34 2013
@@ -0,0 +1,42 @@
+/*
+ * 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.agent;
+
+/**
+ * Generic exception that is thrown when an installation of an update failed.
+ *
+ * @see UpdateHandler#install(java.io.InputStream)
+ */
+public class InstallationFailedException extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Creates a new {@link InstallationFailedException} instance.
+ */
+ public InstallationFailedException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Creates a new {@link InstallationFailedException} instance.
+ */
+ public InstallationFailedException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+}
Propchange: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/InstallationFailedException.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/UpdateHandler.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/UpdateHandler.java?rev=1522863&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/UpdateHandler.java (added)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/UpdateHandler.java Fri Sep 13 10:54:34 2013
@@ -0,0 +1,125 @@
+/*
+ * 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.agent;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.SortedSet;
+
+import org.osgi.framework.Version;
+
+/**
+ * Generic interface for installing updates.
+ */
+public interface UpdateHandler {
+ /**
+ * @return a short descriptive name for this update handler, for example, "agent updater".
+ */
+ String getName();
+
+ /**
+ * Return the sorted set of available update-versions as reported by the server.
+ *
+ * @return a sorted set of versions, may be empty, but never be <code>null</code>.
+ * @throws RetryAfterException
+ * if the server indicates it is too busy, and this call should be retried on a later moment;
+ * @throws IOException
+ * in case the connection to the server failed.
+ */
+ SortedSet<Version> getAvailableVersions() throws RetryAfterException, IOException;
+
+ /**
+ * Return the {@link DownloadHandle} for an update.
+ *
+ * @param version
+ * the version of the update to get a download handle for, cannot be <code>null</code>;
+ * @param fixPackage
+ * <code>true</code> if a download handler for a fix-package should be requested, <code>false</code>
+ * otherwise.
+ * @return a download handle for the requested update, never <code>null</code>.
+ * @throws RetryAfterException
+ * if the server indicates it is too busy, and this call should be retried on a later moment.
+ */
+ DownloadHandle getDownloadHandle(Version version, boolean fixPackage) throws RetryAfterException;
+
+ /**
+ * Returns the highest available update-version as reported by the server.
+ *
+ * @return the highest available version, never <code>null</code>, can be {@link Version#emptyVersion} in case no
+ * version is available.
+ * @throws RetryAfterException
+ * if the server indicates it is too busy, and this call should be retried on a later moment;
+ * @throws IOException
+ * in case the connection to the server failed.
+ */
+ Version getHighestAvailableVersion() throws RetryAfterException, IOException;
+
+ /**
+ * Returns the {@link InputStream} for an update.
+ *
+ * @param version
+ * the version of the update to get an input-stream for, cannot be <code>null</code>;
+ * @param fixPackage
+ * <code>true</code> if an input-stream for a fix-package should be requested, <code>false</code>
+ * otherwise.
+ * @return the input-stream for the update, never <code>null</code>.
+ * @throws RetryAfterException
+ * if the server indicates it is too busy, and this call should be retried on a later moment;
+ * @throws IOException
+ * in case the connection to the server failed.
+ */
+ InputStream getInputStream(Version version, boolean fixPackage) throws RetryAfterException, IOException;
+
+ /**
+ * Return version of the current installed update for this agent.
+ *
+ * @return the installed version, {@link Version.emptyVersion} if no packages have been installed, never
+ * <code>null</code>.
+ */
+ Version getInstalledVersion();
+
+ /**
+ * Return the estimated size for an update as reported by the server.
+ *
+ * @param version
+ * the version of the update to get a size estimation for, cannot be <code>null</code>;
+ * @param fixPackage
+ * <code>true</code> if a size estimation for a fix-package should be requested, <code>false</code>
+ * otherwise.
+ * @return the estimated size in bytes, <code>-1</code> indicates the size is unknown.
+ * @throws RetryAfterException
+ * if the server indicates it is too busy, and this call should be retried on a later moment;
+ * @throws IOException
+ * in case the connection to the server failed.
+ */
+ long getSize(Version version, boolean fixPackage) throws RetryAfterException, IOException;
+
+ /**
+ * Install an update from an input stream.
+ *
+ * @param inputStream
+ * the inputStream, can not be <code>null</code>.
+ * @throws InstallationFailedException
+ * in case the installation failed;
+ * @throws IOException
+ * if reading from the given input stream fails.
+ */
+ void install(InputStream inputStream) throws InstallationFailedException, IOException;
+
+}
Propchange: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/UpdateHandler.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/Activator.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/Activator.java?rev=1522863&r1=1522862&r2=1522863&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/Activator.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/Activator.java Fri Sep 13 10:54:34 2013
@@ -18,6 +18,7 @@
*/
package org.apache.ace.agent.impl;
+import java.io.File;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
@@ -105,13 +106,15 @@ public class Activator implements Bundle
* Called by our {@link DependencyTrackerImpl} when all dependencies are satisfied.
*/
public void componentStarted(BundleContext context) throws Exception {
- m_agentContext = new AgentContextImpl(context.getDataFile(""));
+ final File bundleDataArea = context.getDataFile("");
+
+ m_agentContext = new AgentContextImpl(bundleDataArea);
m_agentContext.setHandler(LoggingHandler.class, new LoggingHandlerImpl());
m_agentContext.setHandler(ConfigurationHandler.class, new ConfigurationHandlerImpl());
m_agentContext.setHandler(EventsHandler.class, new EventsHandlerImpl(context));
m_agentContext.setHandler(ScheduledExecutorService.class, m_executorService);
- m_agentContext.setHandler(DownloadHandler.class, new DownloadHandlerImpl());
+ m_agentContext.setHandler(DownloadHandler.class, new DownloadHandlerImpl(bundleDataArea));
m_agentContext.setHandler(DeploymentHandler.class, new DeploymentHandlerImpl(context, m_packageAdmin));
m_agentContext.setHandler(AgentUpdateHandler.class, new AgentUpdateHandlerImpl(context));
m_agentContext.setHandler(FeedbackHandler.class, new FeedbackHandlerImpl());
Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/AgentUpdateHandlerImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/AgentUpdateHandlerImpl.java?rev=1522863&r1=1522862&r2=1522863&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/AgentUpdateHandlerImpl.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/AgentUpdateHandlerImpl.java Fri Sep 13 10:54:34 2013
@@ -18,7 +18,9 @@
*/
package org.apache.ace.agent.impl;
-import static org.apache.ace.agent.impl.ConnectionUtil.*;
+import static org.apache.ace.agent.impl.ConnectionUtil.closeSilently;
+import static org.apache.ace.agent.impl.ConnectionUtil.copy;
+
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -66,29 +68,34 @@ public class AgentUpdateHandlerImpl exte
}
@Override
- public DownloadHandle getDownloadHandle(Version version) throws RetryAfterException, IOException {
+ public DownloadHandle getDownloadHandle(Version version, boolean fixPackage) throws RetryAfterException {
return getDownloadHandle(getEndpoint(getServerURL(), getIdentification(), version));
}
@Override
- public InputStream getInputStream(Version version) throws RetryAfterException, IOException {
+ public InputStream getInputStream(Version version, boolean fixPackage) throws RetryAfterException, IOException {
return getInputStream(getEndpoint(getServerURL(), getIdentification(), version));
}
-
+
@Override
public Version getInstalledVersion() {
return m_bundleContext.getBundle().getVersion();
}
@Override
- public long getSize(Version version) throws RetryAfterException, IOException {
+ public String getName() {
+ return "agent";
+ }
+
+ @Override
+ public long getSize(Version version, boolean fixPackage) throws RetryAfterException, IOException {
return getPackageSize(getEndpoint(getServerURL(), getIdentification(), version));
}
@Override
public void install(InputStream stream) throws IOException {
try {
- InputStream currentBundleVersion = getInputStream(m_bundleContext.getBundle().getVersion());
+ InputStream currentBundleVersion = getInputStream(m_bundleContext.getBundle().getVersion(), false /* fixPackage */);
Bundle bundle = m_bundleContext.installBundle("agent-updater", generateBundle());
bundle.start();
ServiceTracker st = new ServiceTracker(m_bundleContext, m_bundleContext.createFilter("(" + Constants.OBJECTCLASS + "=org.apache.ace.agent.updater.Activator)"), null);
@@ -136,15 +143,17 @@ public class AgentUpdateHandlerImpl exte
/** Generates an input stream that contains a complete bundle containing our update code for the agent. */
private InputStream generateBundle() throws IOException {
+ final String activatorClass = "org/apache/ace/agent/updater/Activator.class";
+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream is = null;
JarOutputStream os = null;
try {
- is = getClass().getResourceAsStream("/org/apache/ace/agent/updater/Activator.class");
+ is = getClass().getResourceAsStream("/".concat(activatorClass));
os = new JarOutputStream(baos, createBundleManifest());
- os.putNextEntry(new JarEntry("org/apache/ace/agent/updater/Activator.class"));
+ os.putNextEntry(new JarEntry(activatorClass));
try {
copy(is, os);
Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DefaultController.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DefaultController.java?rev=1522863&r1=1522862&r2=1522863&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DefaultController.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DefaultController.java Fri Sep 13 10:54:34 2013
@@ -25,9 +25,7 @@ import static org.apache.ace.agent.Agent
import static org.apache.ace.agent.AgentConstants.CONFIG_CONTROLLER_SYNCDELAY;
import static org.apache.ace.agent.AgentConstants.CONFIG_CONTROLLER_SYNCINTERVAL;
import static org.apache.ace.agent.impl.ConnectionUtil.closeSilently;
-import static org.apache.ace.agent.impl.InternalConstants.AGENT_CONFIG_CHANGED;
-import static org.apache.ace.agent.impl.InternalConstants.AGENT_DEPLOYMENT_COMPLETE;
-import static org.apache.ace.agent.impl.InternalConstants.AGENT_DEPLOYMENT_INSTALL;
+import static org.apache.ace.agent.impl.InternalConstants.*;
import java.io.IOException;
import java.io.InputStream;
@@ -35,141 +33,126 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
-import java.util.SortedSet;
-import java.util.TreeSet;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
-import org.apache.ace.agent.AgentUpdateHandler;
-import org.apache.ace.agent.DeploymentHandler;
import org.apache.ace.agent.DownloadHandle;
+import org.apache.ace.agent.DownloadHandle.DownloadProgressListener;
import org.apache.ace.agent.DownloadResult;
import org.apache.ace.agent.DownloadState;
import org.apache.ace.agent.EventListener;
import org.apache.ace.agent.FeedbackChannel;
+import org.apache.ace.agent.InstallationFailedException;
import org.apache.ace.agent.RetryAfterException;
+import org.apache.ace.agent.UpdateHandler;
import org.osgi.framework.Version;
-import org.osgi.service.deploymentadmin.DeploymentException;
/**
* Default configurable controller
*/
public class DefaultController extends ComponentBase implements Runnable, EventListener {
-
/**
* UpdateInstaller that provides download deployment package install. The install is non-blocking. Upon download
* completion this installer will reschedule the controller.
*/
- static class DownloadUpdateInstaller extends UpdateInstaller implements DownloadHandle.ProgressListener, DownloadHandle.ResultListener {
- // active download state
+ static class DownloadUpdateInstaller extends UpdateInstaller {
private volatile DownloadHandle m_downloadHandle;
- private volatile DownloadResult m_downloadResult = null;
- private volatile Version m_downloadVersion;
- private volatile long m_downloadLength = 0;
- private volatile long m_downloadProgress = 0;
+ private volatile UpdateInfo m_updateInfo;
public DownloadUpdateInstaller(DefaultController controller) {
super(controller);
}
@Override
- public void completed(DownloadResult result) {
- int delay = 1; // seconds
- m_downloadResult = result;
- getController().logInfo("Deployment package download completed for version %s. Rescheduling the controller to run in %d seconds", m_downloadVersion, delay);
- getController().scheduleRun(delay);
- }
-
- @Override
- public void doInstallUpdate(Version fromVersion, Version toVersion, boolean fixPackage) throws RetryAfterException, DeploymentException, IOException {
- DeploymentHandler deploymentHandler = getController().getDeploymentHandler();
+ public void doInstallUpdate(final UpdateHandler delegate, final UpdateInfo updateInfo) throws RetryAfterException {
+ DefaultController controller = getController();
- if (m_downloadHandle != null && !m_downloadVersion.equals(toVersion)) {
- getController().logInfo("Cancelling deployment package download for %s because a newer version is available...", m_downloadVersion);
+ if (m_downloadHandle != null && m_updateInfo != null && !m_updateInfo.m_to.equals(updateInfo.m_to)) {
+ controller.logInfo("Cancelling download of %s update for %s because a newer version is available...", m_updateInfo.m_type, m_updateInfo.m_to);
m_downloadHandle.discard();
m_downloadHandle = null;
}
if (m_downloadHandle == null) {
- getController().logInfo("Starting deployment package download %s => %s...", fromVersion, toVersion);
-
- m_downloadVersion = toVersion;
-
- m_downloadHandle = deploymentHandler.getDownloadHandle(toVersion, fixPackage);
- m_downloadHandle.setProgressListener(this).setCompletionListener(this).start();
- return;
- }
-
- if (m_downloadResult == null) {
- getController().logInfo("Deployment package download for %s is in progress %d / %d", toVersion, m_downloadProgress, m_downloadLength);
- return;
- }
-
- DownloadState state = m_downloadResult.getState();
- if (DownloadState.FAILED == state) {
- getController().logWarning("Deployment package download for %s is FAILED. Restarting download...");
-
- m_downloadHandle.discard();
- m_downloadHandle = null;
-
- throw new IOException("Download failed for deployment update " + fromVersion + " => " + toVersion);
- }
- else if (DownloadState.STOPPED == state) {
- getController().logInfo("Deployment package download for %s is STOPPED. Trying to resume download...");
-
- m_downloadResult = null;
- m_downloadHandle.start();
- }
- else if (DownloadState.SUCCESSFUL == state) {
- getController().logInfo("Installing downloaded deployment update %s => %s...", fromVersion, toVersion);
-
- getController().sendDeploymentInstallEvent(fromVersion, toVersion, fixPackage);
-
- InputStream inputStream = null;
- boolean success = false;
+ controller.logInfo("Starting download of %s update, %s => %s...", updateInfo.m_type, updateInfo.m_from, updateInfo.m_to);
- try {
- inputStream = m_downloadResult.getInputStream();
-
- deploymentHandler.deployPackage(inputStream);
-
- success = true;
- }
- finally {
- m_downloadHandle.discard();
- m_downloadHandle = null;
+ m_updateInfo = updateInfo;
- closeSilently(inputStream);
+ m_downloadHandle = delegate.getDownloadHandle(updateInfo.m_to, updateInfo.m_fixPackage);
+ m_downloadHandle.start(new DownloadProgressListener() {
+ @Override
+ public void completed(DownloadResult result) {
+ DefaultController controller = getController();
+ DownloadState state = result.getState();
+
+ String type = updateInfo.m_type;
+ Version fromVersion = updateInfo.m_from;
+ Version toVersion = updateInfo.m_to;
+
+ if (DownloadState.FAILED == state) {
+ controller.logInfo("Download of %s update is FAILED. Restarting download...", type);
+
+ m_downloadHandle.discard();
+ m_downloadHandle = null;
+ }
+ else if (DownloadState.STOPPED == state) {
+ controller.logInfo("Download of %s update is STOPPED. Resuming download...", type);
+
+ m_downloadHandle.start(this);
+ }
+ else if (DownloadState.SUCCESSFUL == state) {
+ controller.logInfo("Installing %s update %s => %s...", type, fromVersion, toVersion);
+
+ boolean success = false;
+ Exception cause = null;
+
+ try {
+ startInstallation(updateInfo);
+
+ delegate.install(result.getInputStream());
+
+ success = true;
+ }
+ catch (Exception exception) {
+ cause = exception;
+ controller.logWarning("Installation of %s update failed!", exception, type);
+ }
+ finally {
+ m_downloadHandle.discard();
+ m_downloadHandle = null;
+
+ endInstallation(updateInfo, success, cause);
+ }
+ }
+ }
- getController().sendDeploymentCompletedEvent(fromVersion, toVersion, fixPackage, success);
- }
+ @Override
+ public void progress(long contentLength, long progress) {
+ if (updateInfo != null) {
+ getController().logInfo("Progress of %s update download: %d of %d bytes...", updateInfo.m_type, progress, contentLength);
+ }
+ }
+ });
}
}
@Override
public void doReset() {
if (m_downloadHandle != null) {
- getController().logInfo("Cancelling deployment package download for version %s because of reset...", m_downloadVersion);
+ getController().logInfo("Cancelling deployment package download for version %s because of reset...", m_updateInfo.m_to);
m_downloadHandle.discard();
}
clearDownloadState();
}
- @Override
- public void progress(long contentLength, long progress) {
- m_downloadLength = contentLength;
- m_downloadProgress = progress;
- }
-
private void clearDownloadState() {
if (m_downloadHandle != null) {
m_downloadHandle.discard();
}
m_downloadHandle = null;
- m_downloadResult = null;
- m_downloadVersion = null;
+ m_updateInfo = null;
}
}
@@ -182,27 +165,34 @@ public class DefaultController extends C
}
@Override
- public void doInstallUpdate(Version from, Version to, boolean fix) throws RetryAfterException, DeploymentException, IOException {
- getController().logInfo("Installing streaming deployment update %s => %s", from, to);
+ public void doInstallUpdate(UpdateHandler delegate, UpdateInfo updateInfo) throws RetryAfterException {
+ DefaultController controller = getController();
- getController().sendDeploymentInstallEvent(from, to, fix);
-
- DeploymentHandler deploymentHandler = getController().getDeploymentHandler();
+ controller.logInfo("Installing streaming %s update %s => %s", updateInfo.m_type, updateInfo.m_from, updateInfo.m_to);
InputStream inputStream = null;
- boolean success = false;
try {
- inputStream = deploymentHandler.getInputStream(to, fix);
+ inputStream = delegate.getInputStream(updateInfo.m_to, updateInfo.m_fixPackage);
+
+ startInstallation(updateInfo);
- deploymentHandler.deployPackage(inputStream);
+ delegate.install(inputStream);
- success = true;
+ endInstallation(updateInfo, true /* success */, null);
+ }
+ catch (RetryAfterException ex) {
+ // We aren't ready yet...
+ throw ex;
+ }
+ catch (InstallationFailedException ex) {
+ endInstallation(updateInfo, false /* success */, ex);
+ }
+ catch (IOException ex) {
+ endInstallation(updateInfo, false /* success */, ex);
}
finally {
closeSilently(inputStream);
-
- getController().sendDeploymentCompletedEvent(from, to, fix, success);
}
}
@@ -213,10 +203,27 @@ public class DefaultController extends C
}
/**
- * Base class for internal installer strategies. This implementation handles max update retry contraints and
+ * Small container for information about an update.
+ */
+ static class UpdateInfo {
+ final Version m_from;
+ final Version m_to;
+ final boolean m_fixPackage;
+ final String m_type;
+
+ public UpdateInfo(String type, Version from, Version to, boolean fixPackage) {
+ m_from = from;
+ m_to = to;
+ m_type = type;
+ m_fixPackage = fixPackage;
+ }
+ }
+
+ /**
+ * Base class for internal installer strategies. This implementation handles max update retry constraints and
* delegates the rest to concrete implementations.
*/
- abstract static class UpdateInstaller {
+ static abstract class UpdateInstaller {
private final DefaultController m_controller;
private Version m_lastVersionTried = null;
private boolean m_lastVersionSuccessful = true;
@@ -226,72 +233,140 @@ public class DefaultController extends C
m_controller = controller;
}
- public final boolean canInstallUpdate(Version fromVersion, Version toVersion, long maxRetries) {
- if (toVersion.compareTo(fromVersion) > 0) {
- // Possible newer version, lets check our administration whether we actually need to do something...
- if (m_lastVersionTried != null && toVersion.equals(m_lastVersionTried)) {
- if (m_failureCount >= maxRetries) {
- m_controller.logDebug("Ignoring update %s => %s because max retries (%d) reached!", fromVersion, toVersion, maxRetries);
- return false;
- }
- if (!m_lastVersionSuccessful) {
- m_controller.logDebug("Ignoring update %s => %s because it failed previously!", fromVersion, toVersion);
- return false;
- }
- }
+ /**
+ * Checks whether there's an update to install, and if so, uses the given delegate to actually install the
+ * update.
+ *
+ * @param delegate
+ * the update handle to use for installing the update;
+ * @param fixPackage
+ * <code>true</code> if the update should be downloaded as a "fix package", or <code>false</code> if
+ * it should be a "complete" update;
+ * @param maxRetries
+ * the maximum number of times an update should be retries.
+ * @throws RetryAfterException
+ * in case the server is too busy and we should defer our update to a later moment in time;
+ * @throws IOException
+ * in case of problems accessing the server.
+ */
+ public final void installUpdate(UpdateHandler delegate, boolean fixPackage, long maxRetries) throws RetryAfterException, IOException {
+ Version fromVersion = delegate.getInstalledVersion();
+ Version toVersion = delegate.getHighestAvailableVersion();
- m_controller.logDebug("Need to install update: newer deployment version available!");
- return true;
- }
- else {
- m_controller.logDebug("No need to install update: no newer deployment version available!");
- return false;
+ UpdateInfo updateInfo = new UpdateInfo(delegate.getName(), fromVersion, toVersion, fixPackage);
+
+ // Check whether we actually do need to do something...
+ if (!canInstallUpdate(updateInfo, maxRetries)) {
+ return;
}
- }
- public final void installUpdate(Version fromVersion, Version toVersion, boolean fixPackage) throws RetryAfterException {
if (m_lastVersionTried == null || !toVersion.equals(m_lastVersionTried)) {
m_lastVersionTried = toVersion;
m_lastVersionSuccessful = true;
m_failureCount = 0;
}
- try {
- doInstallUpdate(fromVersion, toVersion, fixPackage);
- // As we've just successfully installed this update, reset the failure counter...
- m_failureCount = 0;
- m_lastVersionSuccessful = true;
- }
- catch (RetryAfterException e) {
- // The server is busy. Re-throw so the controller can abort the sync and reschedule.
- throw (e);
- }
- catch (DeploymentException e) {
- getController().logWarning("Exception while deploying the package", e);
- e.printStackTrace();
- m_failureCount++;
- m_lastVersionSuccessful = false;
- }
- catch (IOException e) {
- getController().logWarning("Exception opening/streaming package inputstream", e);
- e.printStackTrace();
- m_failureCount++;
- }
+ doInstallUpdate(delegate, updateInfo);
}
+ /**
+ * Called when we should discard any pending installations.
+ */
public final void reset() {
m_lastVersionTried = null;
m_failureCount = 0;
doReset();
}
- protected abstract void doInstallUpdate(Version from, Version to, boolean fix) throws RetryAfterException, DeploymentException, IOException;
-
+ /**
+ * Called when an update is available and should be installed. Implementations should do the actual installation
+ * of the update using the given delegate.
+ *
+ * @param delegate
+ * the delegate to use for installing the update;
+ * @param updateInfo
+ * some information about the update.
+ * @throws RetryAfterException
+ * in case the server is too busy and we should defer our update to a later moment in time.
+ */
+ protected abstract void doInstallUpdate(UpdateHandler delegate, UpdateInfo updateInfo) throws RetryAfterException;
+
+ /**
+ * Called when we should discard any pending installations.
+ */
protected abstract void doReset();
+ /**
+ * Should be called to notify that an installation is ended, successfully or unsuccessfully.
+ *
+ * @param updateInfo
+ * the information about the update;
+ * @param success
+ * <code>true</code> if the installation was successful, <code>false</code> otherwise;
+ * @param cause
+ * the (optional) cause why the installation failed.
+ */
+ protected final void endInstallation(UpdateInfo updateInfo, boolean success, Exception cause) {
+ m_lastVersionSuccessful = success;
+ if (cause instanceof InstallationFailedException || cause instanceof IOException) {
+ m_failureCount++;
+ }
+ else {
+ m_failureCount = 0;
+ }
+ m_controller.sendDeploymentCompletedEvent(updateInfo, success);
+ }
+
protected final DefaultController getController() {
return m_controller;
}
+
+ /**
+ * Should be called to notify that an installation is started.
+ *
+ * @param updateInfo
+ * the information about the update.
+ */
+ protected final void startInstallation(UpdateInfo updateInfo) {
+ m_controller.sendDeploymentInstallEvent(updateInfo);
+ }
+
+ /**
+ * Determines whether, according to the given information about the possible update, we should actually perform
+ * an update or not.
+ *
+ * @param updateInfo
+ * the information about the possible update;
+ * @param maxRetries
+ * the maximum number of times an installation should be retried.
+ * @return <code>true</code> if there is a possible update to install, <code>false</code> otherwise.
+ */
+ private boolean canInstallUpdate(UpdateInfo updateInfo, long maxRetries) {
+ Version fromVersion = updateInfo.m_from;
+ Version toVersion = updateInfo.m_to;
+ String type = updateInfo.m_type;
+
+ if (toVersion.compareTo(fromVersion) > 0) {
+ // Possible newer version, lets check our administration whether we actually need to do something...
+ if (m_lastVersionTried != null && toVersion.equals(m_lastVersionTried)) {
+ if (m_failureCount >= maxRetries) {
+ m_controller.logDebug("Ignoring %s update %s => %s because max retries (%d) reached!", type, fromVersion, toVersion, maxRetries);
+ return false;
+ }
+ if (!m_lastVersionSuccessful) {
+ m_controller.logDebug("Ignoring %s update %s => %s because it failed previously!", type, fromVersion, toVersion);
+ return false;
+ }
+ }
+
+ m_controller.logDebug("Need to install update: newer %s version available!", type);
+ return true;
+ }
+ else {
+ m_controller.logDebug("No need to install update: no newer %s version available!", type);
+ return false;
+ }
+ }
}
private volatile ScheduledFuture<?> m_scheduledFuture;
@@ -433,25 +508,27 @@ public class DefaultController extends C
m_scheduledFuture = getExecutorService().schedule(this, seconds, TimeUnit.SECONDS);
}
- protected void sendDeploymentCompletedEvent(Version from, Version to, boolean fixPackage, boolean success) {
+ protected void sendDeploymentCompletedEvent(UpdateInfo updateInfo, boolean success) {
Map<String, String> eventProps = new HashMap<String, String>();
+ eventProps.put("type", updateInfo.m_type);
eventProps.put("name", getIdentificationHandler().getAgentId());
- eventProps.put("fromVersion", from.toString());
- eventProps.put("toVersion", to.toString());
- eventProps.put("fixPackage", Boolean.toString(fixPackage));
+ eventProps.put("fromVersion", updateInfo.m_from.toString());
+ eventProps.put("toVersion", updateInfo.m_to.toString());
+ eventProps.put("fixPackage", Boolean.toString(updateInfo.m_fixPackage));
eventProps.put("successful", Boolean.toString(success));
- getEventsHandler().postEvent(AGENT_DEPLOYMENT_COMPLETE, eventProps);
+ getEventsHandler().postEvent(AGENT_INSTALLATION_COMPLETE, eventProps);
}
- protected void sendDeploymentInstallEvent(Version from, Version to, boolean fixPackage) {
+ protected void sendDeploymentInstallEvent(UpdateInfo updateInfo) {
Map<String, String> eventProps = new HashMap<String, String>();
+ eventProps.put("type", updateInfo.m_type);
eventProps.put("name", getIdentificationHandler().getAgentId());
- eventProps.put("fromVersion", from.toString());
- eventProps.put("toVersion", to.toString());
- eventProps.put("fixPackage", Boolean.toString(fixPackage));
+ eventProps.put("fromVersion", updateInfo.m_from.toString());
+ eventProps.put("toVersion", updateInfo.m_to.toString());
+ eventProps.put("fixPackage", Boolean.toString(updateInfo.m_fixPackage));
- getEventsHandler().postEvent(AGENT_DEPLOYMENT_INSTALL, eventProps);
+ getEventsHandler().postEvent(AGENT_INSTALLATION_START, eventProps);
}
private FeedbackChannel getFeedbackChannel(String name) {
@@ -478,44 +555,9 @@ public class DefaultController extends C
return Collections.emptySet();
}
- private Version getHighestAvailableAgentVersion() throws RetryAfterException {
- SortedSet<Version> available = new TreeSet<Version>();
- try {
- available = getAgentUpdateHandler().getAvailableVersions();
- }
- catch (IOException e) {
- // Hopefully temporary problem due to remote IO or configuration. No cause to abort the sync so we just
- // log it as a warning.
- logWarning("Exception while retrieving agent versions", e);
- }
-
- return getHighestVersion(available);
- }
-
- private Version getHighestAvailableDeploymentVersion() throws RetryAfterException {
- SortedSet<Version> available = new TreeSet<Version>();
- try {
- available = getDeploymentHandler().getAvailableVersions();
- }
- catch (IOException e) {
- // Hopefully temporary problem due to remote IO or configuration. No cause to abort the sync so we just
- // log it as a warning.
- logWarning("Exception while retrieving deployment versions", e);
- }
-
- return getHighestVersion(available);
- }
-
- private Version getHighestVersion(SortedSet<Version> available) {
- Version highest = Version.emptyVersion;
- if (available != null && !available.isEmpty()) {
- highest = available.last();
- }
- return highest;
- }
-
- private UpdateInstaller getUpdateInstaller(boolean streaming) {
- if (streaming) {
+ private UpdateInstaller getUpdateInstaller() {
+ boolean updateUsingStreams = m_updateStreaming.get();
+ if (updateUsingStreams) {
if (m_updateInstaller == null) {
m_updateInstaller = new StreamingUpdateInstaller(this);
}
@@ -536,54 +578,24 @@ public class DefaultController extends C
return m_updateInstaller;
}
- private void runAgentUpdate() throws RetryAfterException {
+ private void runAgentUpdate() throws RetryAfterException, IOException {
logDebug("Checking for agent updates...");
- AgentUpdateHandler agentUpdateHandler = getAgentUpdateHandler();
-
- Version current = agentUpdateHandler.getInstalledVersion();
- Version highest = getHighestAvailableAgentVersion();
-
- if (highest.compareTo(current) < 1) {
- logDebug("No agent update available for version %s", current);
- return;
- }
-
- logInfo("Installing agent update %s => %s", current, highest);
+ long maxRetries = m_maxRetries.get();
+ boolean fixPackage = m_fixPackage.get();
- InputStream inputStream = null;
- try {
- inputStream = agentUpdateHandler.getInputStream(highest);
- agentUpdateHandler.install(inputStream);
- }
- catch (IOException e) {
- // Hopefully temporary problem due to remote IO or configuration. No cause to abort the sync so we
- // just log it as a warning.
- // FIXME Does not cover failed updates and should handle retries
- logWarning("Exception while installing agent update %s", e, highest);
- }
- finally {
- closeSilently(inputStream);
- }
+ UpdateInstaller updateInstaller = getUpdateInstaller();
+ updateInstaller.installUpdate(getAgentUpdateHandler(), fixPackage, maxRetries);
}
- private void runDeploymentUpdate() throws RetryAfterException {
+ private void runDeploymentUpdate() throws RetryAfterException, IOException {
logDebug("Checking for deployment updates...");
- DeploymentHandler deploymentHandler = getDeploymentHandler();
-
- Version current = deploymentHandler.getInstalledVersion();
- Version highest = getHighestAvailableDeploymentVersion();
-
long maxRetries = m_maxRetries.get();
- boolean updateUsingStreams = m_updateStreaming.get();
-
- UpdateInstaller updateInstaller = getUpdateInstaller(updateUsingStreams);
- if (updateInstaller.canInstallUpdate(current, highest, maxRetries)) {
- boolean fixPackage = m_fixPackage.get();
+ boolean fixPackage = m_fixPackage.get();
- updateInstaller.installUpdate(current, highest, fixPackage);
- }
+ UpdateInstaller updateInstaller = getUpdateInstaller();
+ updateInstaller.installUpdate(getDeploymentHandler(), fixPackage, maxRetries);
}
private void runFeedback() throws RetryAfterException {
Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DeploymentHandlerImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DeploymentHandlerImpl.java?rev=1522863&r1=1522862&r2=1522863&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DeploymentHandlerImpl.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DeploymentHandlerImpl.java Fri Sep 13 10:54:34 2013
@@ -31,6 +31,7 @@ import java.util.SortedSet;
import org.apache.ace.agent.DeploymentHandler;
import org.apache.ace.agent.DownloadHandle;
+import org.apache.ace.agent.InstallationFailedException;
import org.apache.ace.agent.RetryAfterException;
import org.apache.felix.deploymentadmin.DeploymentAdminImpl;
import org.osgi.framework.BundleContext;
@@ -46,7 +47,68 @@ import org.osgi.service.packageadmin.Pac
public class DeploymentHandlerImpl extends UpdateHandlerBase implements DeploymentHandler {
+ /**
+ * Internal EventAdmin that delegates to actual InternalEvents. Used to inject into the DeploymentAdmin only.
+ */
+ final class EventAdminBridge implements EventAdmin {
+ @Override
+ public void postEvent(Event event) {
+ getEventsHandler().postEvent(event.getTopic(), getPayload(event));
+ }
+
+ @Override
+ public void sendEvent(Event event) {
+ getEventsHandler().postEvent(event.getTopic(), getPayload(event));
+ }
+
+ private Map<String, String> getPayload(Event event) {
+ Map<String, String> payload = new HashMap<String, String>();
+ for (String propertyName : event.getPropertyNames()) {
+ payload.put(propertyName, event.getProperty(propertyName).toString());
+ }
+ return payload;
+ }
+ }
+ /**
+ * Internal LogService that wraps delegates to actual InternalLogger. Used to inject into the DeploymentAdmin only.
+ */
+ final class LogServiceBridge implements LogService {
+ @Override
+ public void log(int level, String message) {
+ log(level, message, null);
+ }
+
+ @Override
+ public void log(int level, String message, Throwable exception) {
+ switch (level) {
+ case LogService.LOG_WARNING:
+ logWarning(message, exception);
+ break;
+ case LogService.LOG_INFO:
+ logInfo(message, exception);
+ break;
+ case LogService.LOG_DEBUG:
+ logDebug(message, exception);
+ break;
+ default:
+ logError(message, exception);
+ break;
+ }
+ }
+
+ @Override
+ public void log(ServiceReference sr, int level, String message) {
+ log(level, message, null);
+ }
+
+ @Override
+ public void log(ServiceReference sr, int level, String message, Throwable exception) {
+ log(level, message, exception);
+ }
+ }
+
private final DeploymentAdmin m_deploymentAdmin;
+
private final boolean m_ownDeploymentAdmin;
public DeploymentHandlerImpl(BundleContext bundleContext, PackageAdmin packageAdmin) {
@@ -66,20 +128,21 @@ public class DeploymentHandlerImpl exten
}
@Override
- protected void onStart() throws Exception {
- if (m_ownDeploymentAdmin) {
- invokeMethod(m_deploymentAdmin, "start", new Class<?>[] {}, new Object[] {});
- }
+ public SortedSet<Version> getAvailableVersions() throws RetryAfterException, IOException {
+ return getAvailableVersions(getEndpoint(getServerURL(), getIdentification()));
}
@Override
- protected void onStop() throws Exception {
- if (m_ownDeploymentAdmin) {
- invokeMethod(m_deploymentAdmin, "stop", new Class<?>[] {}, new Object[] {});
- }
+ public DownloadHandle getDownloadHandle(Version version, boolean fixPackage) throws RetryAfterException {
+ return getDownloadHandle(getPackageURL(version, fixPackage));
}
@Override
+ public InputStream getInputStream(Version version, boolean fixPackage) throws RetryAfterException, IOException {
+ return getInputStream(getPackageURL(version, fixPackage));
+ };
+
+ @Override
public Version getInstalledVersion() {
Version highestVersion = Version.emptyVersion;
String identification = getIdentification();
@@ -94,35 +157,40 @@ public class DeploymentHandlerImpl exten
}
}
return highestVersion;
- }
+ };
@Override
- public void deployPackage(InputStream inputStream) throws DeploymentException {
- m_deploymentAdmin.installDeploymentPackage(inputStream);
- }
+ public String getName() {
+ return "deployment";
+ };
@Override
- public long getPackageSize(Version version, boolean fixPackage) throws RetryAfterException, IOException {
+ public long getSize(Version version, boolean fixPackage) throws RetryAfterException, IOException {
return getPackageSize(getPackageURL(version, fixPackage));
- };
+ }
@Override
- public InputStream getInputStream(Version version, boolean fixPackage) throws RetryAfterException, IOException {
- return getInputStream(getPackageURL(version, fixPackage));
- };
+ public void install(InputStream inputStream) throws InstallationFailedException, IOException {
+ try {
+ m_deploymentAdmin.installDeploymentPackage(inputStream);
+ }
+ catch (DeploymentException exception) {
+ throw new InstallationFailedException("Installation of deployment package failed!", exception);
+ }
+ }
@Override
- public DownloadHandle getDownloadHandle(Version version, boolean fixPackage) throws RetryAfterException, IOException {
- return getDownloadHandle(getPackageURL(version, fixPackage));
- };
+ protected void onStart() throws Exception {
+ if (m_ownDeploymentAdmin) {
+ invokeMethod(m_deploymentAdmin, "start", new Class<?>[] {}, new Object[] {});
+ }
+ }
@Override
- public SortedSet<Version> getAvailableVersions() throws RetryAfterException, IOException {
- return getAvailableVersions(getEndpoint(getServerURL(), getIdentification()));
- };
-
- private URL getPackageURL(Version version, boolean fixPackage) throws RetryAfterException, IOException {
- return getEndpoint(getServerURL(), getIdentification(), fixPackage ? getInstalledVersion() : Version.emptyVersion, version);
+ protected void onStop() throws Exception {
+ if (m_ownDeploymentAdmin) {
+ invokeMethod(m_deploymentAdmin, "stop", new Class<?>[] {}, new Object[] {});
+ }
}
private URL getEndpoint(URL serverURL, String identification) {
@@ -148,64 +216,7 @@ public class DeploymentHandlerImpl exten
}
}
- /**
- * Internal EventAdmin that delegates to actual InternalEvents. Used to inject into the DeploymentAdmin only.
- */
- final class EventAdminBridge implements EventAdmin {
- @Override
- public void postEvent(Event event) {
- getEventsHandler().postEvent(event.getTopic(), getPayload(event));
- }
-
- @Override
- public void sendEvent(Event event) {
- getEventsHandler().postEvent(event.getTopic(), getPayload(event));
- }
-
- private Map<String, String> getPayload(Event event) {
- Map<String, String> payload = new HashMap<String, String>();
- for (String propertyName : event.getPropertyNames()) {
- payload.put(propertyName, event.getProperty(propertyName).toString());
- }
- return payload;
- }
- }
-
- /**
- * Internal LogService that wraps delegates to actual InternalLogger. Used to inject into the DeploymentAdmin only.
- */
- final class LogServiceBridge implements LogService {
- @Override
- public void log(int level, String message) {
- log(level, message, null);
- }
-
- @Override
- public void log(int level, String message, Throwable exception) {
- switch (level) {
- case LogService.LOG_WARNING:
- logWarning(message, exception);
- break;
- case LogService.LOG_INFO:
- logInfo(message, exception);
- break;
- case LogService.LOG_DEBUG:
- logDebug(message, exception);
- break;
- default:
- logError(message, exception);
- break;
- }
- }
-
- @Override
- public void log(ServiceReference sr, int level, String message) {
- log(level, message, null);
- }
-
- @Override
- public void log(ServiceReference sr, int level, String message, Throwable exception) {
- log(level, message, exception);
- }
+ private URL getPackageURL(Version version, boolean fixPackage) throws RetryAfterException {
+ return getEndpoint(getServerURL(), getIdentification(), fixPackage ? getInstalledVersion() : Version.emptyVersion, version);
}
}
Modified: ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DownloadCallableImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DownloadCallableImpl.java?rev=1522863&r1=1522862&r2=1522863&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DownloadCallableImpl.java (original)
+++ ace/trunk/org.apache.ace.agent/src/org/apache/ace/agent/impl/DownloadCallableImpl.java Fri Sep 13 10:54:34 2013
@@ -18,7 +18,9 @@
*/
package org.apache.ace.agent.impl;
-import java.io.BufferedInputStream;
+import static org.apache.ace.agent.impl.ConnectionUtil.close;
+import static org.apache.ace.agent.impl.ConnectionUtil.closeSilently;
+
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
@@ -26,169 +28,133 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
-import java.net.URL;
-import java.util.List;
-import java.util.Map;
import java.util.concurrent.Callable;
-class DownloadCallableImpl implements Callable<Void> {
+import org.apache.ace.agent.DownloadHandle.DownloadProgressListener;
+import org.apache.ace.agent.DownloadState;
- // test support
- static final int FAIL_OPENCONNECTION = 1;
- static final int FAIL_OPENINPUTSTREAM = 2;
- static final int FAIL_OPENOUTPUTSTREAM = 3;
- static final int FAIL_AFTERFIRSTWRITE = 4;
+/**
+ * Responsible for actually downloading content from a download handle.
+ */
+final class DownloadCallableImpl implements Callable<Void> {
+ private static final int SC_OK = 200;
+ private static final int SC_PARTIAL_CONTENT = 206;
private final DownloadHandleImpl m_handle;
- private final URL m_source;
+ private final DownloadProgressListener m_listener;
private final File m_target;
private final int m_readBufferSize;
- private final int m_failAtPosition;
-
- private volatile boolean m_abort = false;
- DownloadCallableImpl(DownloadHandleImpl handle, URL source, File target, int readBufferSize, int failAtPosition) {
+ DownloadCallableImpl(DownloadHandleImpl handle, DownloadProgressListener listener, File target, int readBufferSize) {
m_handle = handle;
- m_source = source;
+ m_listener = listener;
m_target = target;
m_readBufferSize = readBufferSize;
- m_failAtPosition = failAtPosition;
}
@Override
public Void call() throws Exception {
- return download();
- }
-
- /**
- * Abort the download. Used instead of a cancel on the future so normal completion can take place.
- */
- void abort() {
- m_abort = true;
- }
-
- @SuppressWarnings("resource")
- private Void download() {
-
int statusCode = 0;
- Map<String, List<String>> headerFields = null;
-
- BufferedInputStream inputStream = null;
- BufferedOutputStream outputStream = null;
HttpURLConnection httpUrlConnection = null;
- try {
+ try {
boolean partialContent = false;
boolean appendTarget = false;
- if (m_failAtPosition == FAIL_OPENCONNECTION)
- throw new IOException("Failed on openConnection on request");
- httpUrlConnection = (HttpURLConnection) m_source.openConnection();
+ httpUrlConnection = m_handle.openConnection();
long targetSize = m_target.length();
if (targetSize > 0) {
- String rangeHeader = "bytes=" + targetSize + "-";
+ String rangeHeader = String.format("bytes=%d-", targetSize);
+
m_handle.logDebug("Requesting Range %s", rangeHeader);
+
httpUrlConnection.setRequestProperty("Range", rangeHeader);
}
statusCode = httpUrlConnection.getResponseCode();
- headerFields = httpUrlConnection.getHeaderFields();
- if (statusCode == 200) {
+ if (statusCode == SC_OK) {
partialContent = false;
}
- else if (statusCode == 206) {
+ else if (statusCode == SC_PARTIAL_CONTENT) {
partialContent = true;
}
else {
+ // TODO handle retry-after?!
throw new IOException("Unable to handle server response code " + statusCode);
}
- if (m_failAtPosition == FAIL_OPENINPUTSTREAM)
- throw new IOException("Failed on openConnection on request");
- inputStream = new BufferedInputStream(httpUrlConnection.getInputStream());
-
- long contentLength = httpUrlConnection.getContentLength();
+ long totalBytes = httpUrlConnection.getContentLength();
if (partialContent) {
String contentRange = httpUrlConnection.getHeaderField("Content-Range");
if (contentRange == null) {
throw new IOException("Server returned no Content-Range for partial content");
}
if (!contentRange.startsWith("bytes ")) {
- throw new IOException("Server returned non byes Content-Range " + contentRange);
+ throw new IOException("Server returned non bytes Content-Range " + contentRange);
}
+
String tmp = contentRange;
tmp = tmp.replace("byes ", "");
String[] parts = tmp.split("/");
String start = parts[0].split("-")[0];
String end = parts[0].split("-")[1];
- System.out.println("size:" + parts[1]);
- System.out.println("from:" + start);
- System.out.println("too:" + end);
- if (parts[1].equals("*"))
- contentLength = -1;
- else
- contentLength = Long.parseLong(parts[1]);
+ m_handle.logDebug("Size: %d, range from %d to %d.", parts[1], start, end);
+
+ if ("*".equals(parts[1])) {
+ totalBytes = -1;
+ }
+ else {
+ totalBytes = Long.parseLong(parts[1]);
+ }
}
- long progress = 0l;
+ long bytesRead = 0l;
if (partialContent) {
- progress = targetSize;
+ bytesRead = targetSize;
appendTarget = true;
}
- if (m_failAtPosition == FAIL_OPENOUTPUTSTREAM)
- throw new IOException("Failed on outputStream");
- outputStream = new BufferedOutputStream(new FileOutputStream(m_target, appendTarget));
+ InputStream inputStream = httpUrlConnection.getInputStream();
+ OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(m_target, appendTarget));
byte buffer[] = new byte[m_readBufferSize];
- int read = -1;
- while (!m_abort && (read = inputStream.read(buffer)) >= 0) {
+ int read;
- outputStream.write(buffer, 0, read);
- progress += read;
- m_handle.progressCallback(statusCode, headerFields, contentLength, progress);
-
- if (m_failAtPosition == FAIL_AFTERFIRSTWRITE)
- throw new IOException("Failed after first write");
+ try {
+ while (!Thread.currentThread().isInterrupted() && (read = inputStream.read(buffer)) >= 0) {
+ outputStream.write(buffer, 0, read);
+ bytesRead += read;
- if (Thread.currentThread().isInterrupted())
- m_abort = true;
+ m_listener.progress(bytesRead, totalBytes);
+ }
}
-
- if (m_abort) {
- m_handle.logDebug("Download stopped: %s" + m_source.toExternalForm());
- m_handle.stoppedCallback(statusCode, headerFields, null);
+ finally {
+ closeSilently(outputStream);
+ closeSilently(inputStream);
}
- else {
- m_handle.logDebug("Download completed: %s", m_source.toExternalForm());
- m_handle.successfulCallback(statusCode, headerFields);
+
+ boolean stoppedEarly = (totalBytes > 0L && bytesRead < totalBytes);
+ if (stoppedEarly) {
+ m_handle.logDebug("Download stopped early: %d of %d bytes downloaded...", bytesRead, totalBytes);
+
+ m_listener.completed(new DownloadResultImpl(DownloadState.STOPPED, (File) null, statusCode));
+ } else {
+ m_handle.logDebug("Download completed: %d bytes downloaded...", totalBytes);
+
+ m_listener.completed(new DownloadResultImpl(DownloadState.SUCCESSFUL, m_target, statusCode));
}
}
catch (Exception e) {
- m_handle.failedCallback(statusCode, headerFields, e);
+ m_handle.logWarning("Download failed!", e);
+
+ m_listener.completed(new DownloadResultImpl(DownloadState.FAILED, e, statusCode));
+ }
+ finally {
+ close(httpUrlConnection);
}
- cleanupQuietly(httpUrlConnection, inputStream, outputStream);
- return null;
- }
- private static void cleanupQuietly(HttpURLConnection httpUrlConnection, InputStream inputStream, OutputStream outputStream) {
- if (httpUrlConnection != null)
- httpUrlConnection.disconnect();
- if (inputStream != null)
- try {
- inputStream.close();
- }
- catch (IOException e) {
- // ignore
- }
- if (outputStream != null)
- try {
- outputStream.close();
- }
- catch (IOException e) {
- // ignore
- }
+ return null;
}
}