001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.activemq.maven;
018
019import org.apache.activemq.broker.BrokerFactory;
020import org.apache.activemq.broker.BrokerService;
021import org.apache.maven.plugin.MojoExecutionException;
022
023/**
024 * Singleton facade between Maven and one ActiveMQ broker.
025 */
026public class Broker {
027
028    private static BrokerService broker;
029
030    private static boolean[] shutdown;
031
032    private static Thread shutdownThread;
033
034    public static void start(boolean fork, String configUri) throws MojoExecutionException {
035
036        if (broker != null) {
037            throw new MojoExecutionException("A local broker is already running");
038        }
039
040        try {
041            broker = BrokerFactory.createBroker(configUri);
042            if (fork) {
043                new Thread(new Runnable() {
044                    @Override
045                    public void run() {
046                        try {
047                            broker.start();
048                            waitForShutdown();
049                        } catch (Exception e) {
050                            e.printStackTrace();
051                        }
052                    }
053                }).start();
054            } else {
055                broker.start();
056                waitForShutdown();
057            }
058        } catch (Exception e) {
059            throw new MojoExecutionException("Failed to start the ActiveMQ Broker", e);
060        }
061    }
062
063    public static void stop() throws MojoExecutionException {
064
065        if (broker == null) {
066            throw new MojoExecutionException("The local broker is not running");
067        }
068
069        try {
070            broker.stop();
071            broker.waitUntilStopped();
072            broker = null;
073
074            Runtime.getRuntime().removeShutdownHook(shutdownThread);
075
076            // Terminate the shutdown hook thread
077            synchronized (shutdown) {
078                shutdown[0] = true;
079                shutdown.notify();
080            }
081        } catch (Exception e) {
082            throw new MojoExecutionException("Failed to stop the ActiveMQ Broker", e);
083        }
084    }
085
086    /**
087     * Wait for a shutdown invocation elsewhere
088     *
089     * @throws Exception
090     */
091    protected static void waitForShutdown() throws Exception {
092        shutdown = new boolean[] { false };
093
094        shutdownThread = new Thread() {
095            @Override
096            public void run() {
097                synchronized (shutdown) {
098                    shutdown[0] = true;
099                    shutdown.notify();
100                }
101            }
102        };
103
104        Runtime.getRuntime().addShutdownHook(shutdownThread);
105
106        // Wait for any shutdown event
107        synchronized (shutdown) {
108            while (!shutdown[0]) {
109                try {
110                    shutdown.wait();
111                } catch (InterruptedException e) {
112                }
113            }
114        }
115
116        // Stop broker
117        if (broker != null) {
118            broker.stop();
119        }
120    }
121
122    /**
123     * Return the broker service created.
124     */
125    public static BrokerService getBroker() {
126        return broker;
127    }
128
129    /**
130     * Override the default creation of the broker service.  Primarily added for testing purposes.
131     *
132     * @param broker
133     */
134    public static void setBroker(BrokerService broker) {
135        Broker.broker = broker;
136    }
137}