Package org.apache.ace.agent.itest

Source Code of org.apache.ace.agent.itest.CustomStandaloneAgentControllerTest

/*
* 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.itest;

import java.util.Set;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

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;
import org.apache.ace.agent.UpdateHandler;
import org.osgi.framework.Version;

/**
* Tests that we can create an agent with a completely custom controller, see {@link CustomStandaloneController} for
* more information about the actual implementation.
*
* @see CustomStandaloneController
*/
public class CustomStandaloneAgentControllerTest extends BaseAgentControllerTest {

    /**
     * The actual custom controller as {@link Runnable} task, that simply loops and executes its tasks until notified to
     * stop.
     *
     * @see #run()
     */
    class CustomStandaloneController implements Runnable {
        /**
         * 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() {
            System.out.println("Custom standalone controller running...");

            while (!Thread.interrupted()) {
                try {
                    TimeUnit.MILLISECONDS.sleep(500);
                }
                catch (InterruptedException exception) {
                    // We're requested to stop...
                    Thread.currentThread().interrupt();
                    break;
                }

                sendFeedbackToServer();

                checkForUpdate(UpdateType.AGENT);

                checkForUpdate(UpdateType.DEPLOYMENT);
            }

            System.out.println("Custom standalone controller stopped...");
        }

        /**
         * 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);

                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;
                    }

                    System.out.printf("Downloading %s update (from v%s to v%s)...%n", updateType, installed, available);

                    DownloadHandle downloadHandle = updateHandler.getDownloadHandle(available, false /* fixPackage */);

                    Future<DownloadResult> future = downloadHandle.start(new DownloadProgressListener() {
                        @Override
                        public void progress(long bytesRead) {
                            System.out.printf("Download progress: %d bytes read...%n", bytesRead);
                        }
                    });
                    // 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);

                        // We've confirmation that we can install this update...
                        updateHandler.install(result.getInputStream());
                    }

                    // Throw away downloaded packages...
                    downloadHandle.discard();
                }
            }
            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_agentControl.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) {
                updateHandler = m_agentControl.getAgentUpdateHandler();
            }
            else {
                updateHandler = m_agentControl.getDeploymentHandler();
            }
            return updateHandler;
        }

        /**
         * 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_agentControl.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);

                    channel.sendFeedback();
                }
            }
            catch (Exception exception) {
                System.out.printf("Feedback synchronization failed with %s.%n", exception.getMessage());
                exception.printStackTrace(System.out);
            }
        }
    }

    /**
     * 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 CustomStandaloneController
     */
    public void testCustomStandaloneController() throws Exception {
        // Tests that we're able to install DPs using only the AgentControl interface...
        CustomStandaloneController controller = new CustomStandaloneController();

        Thread thread = new Thread(controller);
        thread.start();

        try {
            waitForInstalledVersion(m_agentControl.getDeploymentHandler(), m_dpVersion);
        }
        finally {
            thread.interrupt();
            thread.join();
        }
    }

    /**
     * Creates a new {@link CustomStandaloneAgentControllerTest} instance.
     */
    public CustomStandaloneAgentControllerTest() {
        super(Object.class.getName(), "2", "0.0.2");
    }

    @Override
    protected void configureProvisionedServices() throws Exception {
        super.configureProvisionedServices();

        m_bundleContext.registerService(AgentUser.class.getName(), new AcknowledgingAgentUser(), null);
    }
}
TOP

Related Classes of org.apache.ace.agent.itest.CustomStandaloneAgentControllerTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.