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/16 13:31:02 UTC

svn commit: r1532731 - /ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/CustomAgentControllerTest.java

Author: jawi
Date: Wed Oct 16 11:31:02 2013
New Revision: 1532731

URL: http://svn.apache.org/r1532731
Log:
ACE-419: Some additional documentation added.

Modified:
    ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/CustomAgentControllerTest.java

Modified: ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/CustomAgentControllerTest.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/CustomAgentControllerTest.java?rev=1532731&r1=1532730&r2=1532731&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/CustomAgentControllerTest.java (original)
+++ ace/trunk/org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/CustomAgentControllerTest.java Wed Oct 16 11:31:02 2013
@@ -26,7 +26,6 @@ import java.io.PrintWriter;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
-import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 
@@ -39,6 +38,7 @@ import org.apache.ace.agent.AgentConstan
 import org.apache.ace.agent.AgentControl;
 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.FeedbackChannel;
 import org.apache.ace.agent.FeedbackHandler;
@@ -51,7 +51,10 @@ import org.osgi.framework.Version;
 import org.osgi.service.http.HttpService;
 
 /**
- * Tests that we can create an agent with a completely custom controller.
+ * Tests that we can create an agent with a completely custom controller, see {@link CustomController} for more
+ * information about the actual implementation.
+ * 
+ * @see CustomController
  */
 public class CustomAgentControllerTest extends BaseAgentTest {
     /**
@@ -109,20 +112,28 @@ public class CustomAgentControllerTest e
     /**
      * The actual custom controller as {@link Runnable} task, that simply loops and executes its tasks until notified to
      * stop.
+     * 
+     * @see #run()
      */
-    class CustomController implements Runnable, DownloadHandle.DownloadProgressListener {
-        private final CountDownLatch m_latch;
+    class CustomController implements Runnable {
         private volatile boolean m_stop = false;
 
-        public CustomController(CountDownLatch latch) {
-            m_latch = latch;
-        }
-
-        @Override
-        public void progress(long bytesRead, long totalBytes) {
-            System.out.printf("Download progress: %d of %d bytes read...%n", bytesRead, totalBytes);
-        }
-
+        /**
+         * Main loop, will sleep for a little and once every 500 ms will do the following:
+         * <ol>
+         * <li>Synchronize all agent feedback with the server (see {@link #sendFeedbackToServer()});</li>
+         * <li>Check for agent updates (see {@link #checkForUpdate(UpdateType)});</li>
+         * <li>Check for deployment updates (see {@link #checkForUpdate(UpdateType)}).</li>
+         * </ol>
+         * <p>
+         * Note that this implementation does very little error checking and is rather stubborn when it comes across
+         * failures: it simply keeps retrying, which, for this use case, is acceptable.
+         * </p>
+         * 
+         * @see #stop()
+         * @see #checkForUpdate(UpdateType)
+         * @see #sendFeedbackToServer()
+         */
         @Override
         public void run() {
             while (!m_stop) {
@@ -134,74 +145,97 @@ public class CustomAgentControllerTest e
                     break;
                 }
 
-                try {
-                    // Send our feedback...
-                    sendFeedbackToServer();
-                }
-                catch (Exception exception) {
-                    System.out.printf("Feedback synchronization failed with %s.%n", exception.getMessage());
-                    exception.printStackTrace(System.out);
+                if (m_stop) {
+                    // Check once more whether we're not stopped while sleeping...
+                    break;
                 }
 
-                try {
-                    // Check for agent updates...
-                    checkForUpdate(UpdateType.AGENT);
-                }
-                catch (Exception exception) {
-                    System.out.printf("Agent update failed with %s.%n", exception.getMessage());
-                    exception.printStackTrace(System.out);
-                }
+                sendFeedbackToServer();
 
-                try {
-                    // Check for deployment updates...
-                    checkForUpdate(UpdateType.DEPLOYMENT);
-                }
-                catch (Exception exception) {
-                    System.out.printf("Deployment update failed with %s.%n", exception.getMessage());
-                    exception.printStackTrace(System.out);
-                }
+                checkForUpdate(UpdateType.AGENT);
+
+                checkForUpdate(UpdateType.DEPLOYMENT);
             }
         }
 
+        /**
+         * Stops the main loop and allows the {@link #run()} loop to terminate (after it has done all of its work).
+         */
         public void stop() {
             m_stop = true;
         }
 
-        private void checkForUpdate(UpdateType updateType) throws Exception {
-            UpdateHandler updateHandler = getUpdateHandler(updateType);
-
-            Version installed = updateHandler.getInstalledVersion();
-            Version available = updateHandler.getHighestAvailableVersion();
-            if (installed != null && installed.compareTo(available) < 0) {
-                // Update available, update the agent...
-                if (!m_agentUser.downloadAvailableUpdate(updateType, getAgentId(), installed, available)) {
-                    // No, we may not download this update now...
-                    return;
-                }
-
-                System.out.printf("Downloading %s update (from v%s to v%s)...%n", updateType, installed, available);
+        /**
+         * Does the actual check for either the agent or deployment updates, and if available:
+         * <ol>
+         * <li>asks the "user" whether it should download this update, and if so;</li>
+         * <li>downloads the update to a temporary location;</li>
+         * <li>if the download is complete, it asks the "user" whether it should proceed with installing it, and if so;</li>
+         * <li>installs the agent/deployment update.</li>
+         * </ol>
+         * <p>
+         * In case an exception occurs during this check, it is logged and the method returns (early). No exceptions are
+         * propagated. In production code, a little more sophisticated error checking should be performed.
+         * </p>
+         * 
+         * @param updateType
+         *            the type of update we're performing, cannot be <code>null</code>.
+         */
+        private void checkForUpdate(UpdateType updateType) {
+            try {
+                UpdateHandler updateHandler = getUpdateHandler(updateType);
 
-                DownloadHandle downloadHandle = updateHandler.getDownloadHandle(available, false /* fixPackage */);
+                Version installed = updateHandler.getInstalledVersion();
+                Version available = updateHandler.getHighestAvailableVersion();
+                if (installed != null && installed.compareTo(available) < 0) {
+                    // Update available, ask the user whether we should download it...
+                    if (!m_agentUser.downloadAvailableUpdate(updateType, getAgentId(), installed, available)) {
+                        // No, we may not download this update now...
+                        return;
+                    }
 
-                Future<DownloadResult> future = downloadHandle.start(this);
-                // Block until the download is complete...
-                DownloadResult result = future.get();
+                    System.out.printf("Downloading %s update (from v%s to v%s)...%n", updateType, installed, available);
 
-                if (m_agentUser.installAvailableUpdate(updateType, getAgentId(), installed, available)) {
-                    System.out.printf("Installing %s update (from v%s to v%s)...%n", updateType, installed, available);
+                    DownloadHandle downloadHandle = updateHandler.getDownloadHandle(available, false /* fixPackage */);
 
-                    // We've confirmation that we can install this update...
-                    updateHandler.install(result.getInputStream());
+                    Future<DownloadResult> future = downloadHandle.start(new DownloadProgressListener() {
+                        @Override
+                        public void progress(long bytesRead, long totalBytes) {
+                            System.out.printf("Download progress: %d of %d bytes read...%n", bytesRead, totalBytes);
+                        }
+                    });
+                    // Block until the download is complete...
+                    DownloadResult result = future.get();
+
+                    // Download is complete, ask the user once more if we're allowed to install the update...
+                    if (m_agentUser.installAvailableUpdate(updateType, getAgentId(), installed, available)) {
+                        System.out.printf("Installing %s update (from v%s to v%s)...%n", updateType, installed, available);
 
-                    m_latch.countDown();
+                        // We've confirmation that we can install this update...
+                        updateHandler.install(result.getInputStream());
+                    }
                 }
             }
+            catch (Exception exception) {
+                System.out.printf("%s update failed with %s.%n", updateType, exception.getMessage());
+                exception.printStackTrace(System.out);
+            }
         }
 
+        /**
+         * @return the identification of the current agent, as returned by the agent's API.
+         */
         private String getAgentId() {
             return m_control.getAgentId();
         }
 
+        /**
+         * Returns the update handler for the given {@link UpdateType}.
+         * 
+         * @param updateType
+         *            the type of update we want an update handler for, cannot be <code>null</code>.
+         * @return an {@link UpdateHandler} instance, never <code>null</code>.
+         */
         private UpdateHandler getUpdateHandler(UpdateType updateType) {
             UpdateHandler updateHandler;
             if (UpdateType.AGENT == updateType) {
@@ -213,28 +247,44 @@ public class CustomAgentControllerTest e
             return updateHandler;
         }
 
-        private void sendFeedbackToServer() throws IOException {
-            FeedbackHandler feedbackHandler = m_control.getFeedbackHandler();
-            Set<String> channelNames = feedbackHandler.getChannelNames();
-            for (String channelName : channelNames) {
-                FeedbackChannel channel = feedbackHandler.getChannel(channelName);
-
-                System.out.printf("Synchronizing feedback of %s with server...%n", channelName);
+        /**
+         * Synchronizes the agent's feedback with the server by retrieving all feedback channels and sending their
+         * feedback to the server in turn.
+         * <p>
+         * In case an exception occurs during this check, it is logged and the method returns (early). No exceptions are
+         * propagated. In production code, a little more sophisticated error checking should be performed.
+         * </p>
+         */
+        private void sendFeedbackToServer() {
+            try {
+                FeedbackHandler feedbackHandler = m_control.getFeedbackHandler();
+                Set<String> channelNames = feedbackHandler.getChannelNames();
+                for (String channelName : channelNames) {
+                    FeedbackChannel channel = feedbackHandler.getChannel(channelName);
 
-                channel.sendFeedback();
+                    System.out.printf("Synchronizing feedback of %s with server...%n", channelName);
 
-                m_latch.countDown();
+                    channel.sendFeedback();
+                }
+            }
+            catch (Exception exception) {
+                System.out.printf("Feedback synchronization failed with %s.%n", exception.getMessage());
+                exception.printStackTrace(System.out);
             }
         }
     }
 
-    static class TestDeploymentServlet extends HttpServlet {
+    /**
+     * Stub servlet that acts as an ACE server for our agent. Does only the bare minimum with respect to a complete
+     * server.
+     */
+    static class StubDeploymentServlet extends HttpServlet {
         private static final long serialVersionUID = 1L;
 
         private final Map<String, TestPackage> m_packages = new HashMap<String, TestPackage>();
         private final String m_agentId;
 
-        public TestDeploymentServlet(String agentId, TestPackage... testPackages) {
+        public StubDeploymentServlet(String agentId, TestPackage... testPackages) {
             m_agentId = agentId;
 
             for (TestPackage testPackage : testPackages) {
@@ -356,25 +406,26 @@ public class CustomAgentControllerTest e
     /**
      * Tests that we can provide a custom controller implementation based on the following use-case:
      * <p>
-     * ...
+     * The agent should check for updates, and if found, ask the user whether it should proceed to download this update.
+     * If confirmed, the download of the update is started, and when complete, the user is asked once more whether to
+     * proceed with the installation of the update.
      * </p>
+     * 
+     * @see CustomController
      */
     public void testCustomController() throws Exception {
-        CountDownLatch latch = new CountDownLatch(3);
-
-        CustomController controller = new CustomController(latch);
+        CustomController controller = new CustomController();
 
         Thread thread = new Thread(controller);
         thread.start();
 
-        boolean success = latch.await(30, TimeUnit.SECONDS);
-
-        waitForInstalledVersion(V1_0_0);
-
-        controller.stop();
-        thread.join();
-
-        assertTrue("Use case not completed!", success);
+        try {
+            waitForInstalledVersion(V1_0_0);
+        }
+        finally {
+            controller.stop();
+            thread.join();
+        }
     }
 
     @Override
@@ -384,7 +435,7 @@ public class CustomAgentControllerTest e
         TestBundle bundle1v1 = new TestBundle(TEST_BUNDLE_NAME_PREFIX.concat("1"), V1_0_0);
         TestPackage package1 = new TestPackage(AGENT_ID, V1_0_0, bundle1v1);
 
-        TestDeploymentServlet servlet = new TestDeploymentServlet(AGENT_ID, package1);
+        StubDeploymentServlet servlet = new StubDeploymentServlet(AGENT_ID, package1);
 
         String url = String.format("http://localhost:%d/", TestConstants.PORT);
         NetUtils.waitForURL(url, 404, 10000);