001    /**
002     *  Licensed to the Apache Software Foundation (ASF) under one
003     *  or more contributor license agreements.  See the NOTICE file
004     *  distributed with this work for additional information
005     *  regarding copyright ownership.  The ASF licenses this file
006     *  to you under the Apache License, Version 2.0 (the
007     *  "License"); you may not use this file except in compliance
008     *  with the License.  You may obtain a copy of the License at
009     *
010     *    http://www.apache.org/licenses/LICENSE-2.0
011     *
012     *  Unless required by applicable law or agreed to in writing,
013     *  software distributed under the License is distributed on an
014     *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     *  KIND, either express or implied.  See the License for the
016     *  specific language governing permissions and limitations
017     *  under the License.
018     */
019    
020    package org.apache.geronimo.mavenplugins.geronimo.module;
021    
022    import java.io.IOException;
023    import java.util.List;
024    import java.util.ArrayList;
025    
026    import javax.enterprise.deploy.spi.DeploymentManager;
027    import javax.enterprise.deploy.spi.Target;
028    import javax.enterprise.deploy.spi.TargetModuleID;
029    import javax.enterprise.deploy.spi.status.ProgressObject;
030    import javax.enterprise.deploy.spi.status.ProgressListener;
031    import javax.enterprise.deploy.spi.status.ProgressEvent;
032    import javax.enterprise.deploy.spi.status.DeploymentStatus;
033    import javax.enterprise.deploy.spi.exceptions.DeploymentManagerCreationException;
034    import javax.enterprise.deploy.shared.factories.DeploymentFactoryManager;
035    
036    import org.apache.geronimo.deployment.plugin.factories.DeploymentFactoryImpl;
037    import org.apache.geronimo.mavenplugins.geronimo.ModuleConfig;
038    import org.apache.geronimo.mavenplugins.geronimo.reporting.ReportingMojoSupport;
039    
040    import org.codehaus.mojo.pluginsupport.util.ArtifactItem;
041    
042    import org.apache.maven.plugin.MojoExecutionException;
043    
044    /**
045     * Support for mojos that operate on modules.
046     *
047     * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
048     */
049    public abstract class ModuleMojoSupport
050        extends ReportingMojoSupport
051    {
052        private static final String URI_PREFIX = "deployer:geronimo:jmx";
053    
054        /**
055         * List of module artifact configurations.  Artifacts need to point to jar | war | ear | rar archive.
056         * Module artifact's configurations should match the moduleId specified in the plan, if plan exists.
057         *
058         * @parameter
059         */
060        protected ModuleConfig[] modules;
061    
062        /**
063         * Cached deployment manager.
064         */
065        private DeploymentManager deploymentManager;
066    
067        /**
068         * Whether to stop or proceed when errors and failures are encountered
069         *
070         * @parameter expression="${stopOnFailure}" default-value="false"
071         */
072        protected boolean stopOnFailure = false;
073    
074        /**
075         * Get a deployment manager; if the manager was previosuly initialized then that cached instance is used.
076         *
077         * @return  Deployment manager instance; never null
078         *
079         * @throws IOException
080         * @throws DeploymentManagerCreationException
081         */
082        protected DeploymentManager getDeploymentManager() throws IOException, DeploymentManagerCreationException {
083            if (deploymentManager == null) {
084                // Register the Geronimo factory
085                DeploymentFactoryManager manager = DeploymentFactoryManager.getInstance();
086                manager.registerDeploymentFactory(new DeploymentFactoryImpl());
087    
088                String uri = URI_PREFIX + "://" + hostname + ":" + port;
089    
090                DeploymentFactoryManager factoryManager = DeploymentFactoryManager.getInstance();
091                deploymentManager = factoryManager.getDeploymentManager(uri, username, password);
092            }
093    
094            return deploymentManager;
095        }
096    
097        /**
098         * Waits for the given progress to stop running.
099         *
100         * @param progress  The progress object to wait for.
101         * @return          The status of the deployment; never null
102         *
103         * @throws InterruptedException
104         */
105        protected DeploymentStatus waitFor(final ProgressObject progress) throws InterruptedException {
106            assert progress != null;
107    
108            //
109            // TODO: Add timeout?
110            //
111            
112            ProgressListener listener = new ProgressListener()
113            {
114                public void handleProgressEvent(final ProgressEvent event) {
115                    DeploymentStatus status = event.getDeploymentStatus();
116    
117                    if (!status.isRunning()) {
118                        synchronized (progress) {
119                            progress.notify();
120                        }
121                    }
122                }
123            };
124    
125            progress.addProgressListener(listener);
126    
127            synchronized (progress) {
128                while (progress.getDeploymentStatus().isRunning()) {
129                    progress.wait();
130                }
131            }
132    
133            return progress.getDeploymentStatus();
134        }
135    
136        /**
137         * Returns the Geronimo moduleId for the given artifact.
138         *
139         * @param item  The artifact item to get the moduleId for.
140         * @return      The moduleId of the given artifact item.
141         */
142        protected String getModuleId(final ArtifactItem item) {
143            assert item != null;
144    
145            return item.getGroupId() + "/" + item.getArtifactId() + "/" + item.getVersion() + "/" + item.getType();
146        }
147    
148        /**
149         * Given a list of modules, return a list of non-running ones.
150         *
151         * @param moduleIds  The list of modules to check
152         * @return          The list of modules that are not running
153         *
154         * @throws Exception
155         */
156        protected TargetModuleID[] getNonRunningModules(final TargetModuleID[] moduleIds) throws Exception {
157            assert moduleIds != null;
158    
159            List modulesList = new ArrayList();
160    
161            DeploymentManager manager = getDeploymentManager();
162    
163            Target[] targets = manager.getTargets();
164            TargetModuleID runningModuleIds[] = manager.getRunningModules(null, targets);
165    
166            for (int j = 0; j < moduleIds.length; j++) {
167                String moduleId = moduleIds[j].getModuleID();
168                log.debug("Checking if module is running: " + moduleId);
169    
170                boolean found = false;
171                for (int i = 0; i < runningModuleIds.length; i++) {
172                String runningModuleId = runningModuleIds[i].getModuleID();
173                    if (moduleId.equals(runningModuleId)) {
174                        log.debug("Module is running: " + moduleId);
175                        found = true;
176                        break;
177                    }
178                }
179    
180                if (!found) {
181                    log.debug("Module is not running: " + moduleId);
182                    modulesList.add(moduleIds[j]);
183                }
184            }
185            return (TargetModuleID[]) modulesList.toArray(new TargetModuleID[modulesList.size()]);
186        }
187    
188        /**
189         * Check if the given module is started.
190         *
191         * @param moduleId  The module ID to check
192         * @return          True if the module for this ID is started.
193         *
194         * @throws Exception
195         */
196        protected boolean isModuleStarted(final String moduleId) throws Exception {
197            assert moduleId != null;
198    
199            log.debug("Checking if module is started: " + moduleId);
200            
201            DeploymentManager manager = getDeploymentManager();
202    
203            Target[] targets = manager.getTargets();
204            TargetModuleID targetIds[] = manager.getRunningModules(null, targets);
205    
206            for (int i = 0; i < targetIds.length; i++) {
207                if (moduleId.equals(targetIds[i].getModuleID())) {
208                    return true;
209                }
210            }
211    
212            return false;
213        }
214    
215        protected TargetModuleID[] findModules(final String moduleId, final TargetModuleID targetIds[]) {
216            assert moduleId != null;
217            assert targetIds != null;
218    
219            List found = new ArrayList();
220    
221            log.debug("Scanning for modules that match: " + moduleId);
222            for (int i = 0; i < targetIds.length; i++) {
223                log.debug("Checking: " + targetIds[i].getModuleID());
224    
225                if (moduleId.equals(targetIds[i].getModuleID())) {
226                    found.add(targetIds[i]);
227                }
228            }
229    
230            return (TargetModuleID[]) found.toArray(new TargetModuleID[found.size()]);
231        }
232    
233        //
234        // TODO: Can probably wrap up some of this into findModules with a flag for running or non-running
235        //
236        
237        protected void startModule() throws Exception {
238            assert modules != null;
239    
240            for (int i=0; i<modules.length; i++) {
241                String moduleId = getModuleId(modules[i]);
242                
243                if (isModuleStarted(moduleId)) {
244                    log.warn("Module is already started: " + moduleId);
245                    continue;
246                    //throw new MojoExecutionException("Module is already started: " + moduleId);
247                }
248                
249                DeploymentManager manager = getDeploymentManager();
250                Target[] targets = manager.getTargets();
251                TargetModuleID[] targetIds = manager.getNonRunningModules(null, targets);
252    
253                TargetModuleID[] found = findModules(moduleId, targetIds);
254    
255                if (found.length == 0) {
256                    throw new MojoExecutionException("Module is not deployed: " + moduleId);
257                }
258    
259                log.info("Starting module: " + moduleId);
260                ProgressObject progress = manager.start(found);
261                
262                DeploymentStatus status = waitFor(progress);
263                if (status.isFailed()) {
264                    throw new MojoExecutionException("Failed to start module: " + moduleId);
265                }
266                
267                log.info("Started module(s):");
268                logModules(found, "    ");
269            }
270        }
271    
272        protected void stopModule() throws Exception {
273            assert modules != null;
274    
275            DeploymentManager manager = getDeploymentManager();
276            Target[] targets = manager.getTargets();
277            TargetModuleID[] targetIds = manager.getRunningModules(null, targets);
278    
279            for (int i=0; i<modules.length; i++) {
280               String moduleId = getModuleId(modules[i]);
281               if (!isModuleStarted(moduleId)) {
282                   log.info("Module is already stopped: " + moduleId);
283                   continue;
284                   //throw new MojoExecutionException("Module is not started: " + moduleId);
285               }
286    
287               TargetModuleID[] found = findModules(moduleId, targetIds);
288    
289               if (found.length == 0) {
290                   throw new MojoExecutionException("Module not deployed: " + moduleId);
291               }
292    
293               log.info("Stopping module: " + moduleId);
294               ProgressObject progress = manager.stop(found);
295    
296               DeploymentStatus status = waitFor(progress);
297               if (status.isFailed()) {
298                   throw new MojoExecutionException("Failed to stop module: " + moduleId);
299               }
300    
301               log.info("Stopped module(s):");
302               logModules(found, "    ");
303            }
304        }
305    
306        protected void undeployModule() throws Exception {
307            assert modules != null;
308    
309            stopModule();
310    
311            DeploymentManager manager = getDeploymentManager();
312            Target[] targets = manager.getTargets();
313            TargetModuleID[] targetIds = manager.getNonRunningModules(null, targets);
314    
315            for (int i=0; i<modules.length; i++) {
316              String moduleId = getModuleId(modules[i]);
317    
318              TargetModuleID[] found = findModules(moduleId, targetIds);
319    
320              if (found.length == 0) {
321                  log.info("Module is not deployed: " + moduleId);
322                  continue;
323                  //throw new Exception("Module is not deployed: " + moduleId);
324              }
325    
326              log.info("Undeploying module: " + moduleId);
327              ProgressObject progress = manager.undeploy(found);
328    
329              DeploymentStatus status = waitFor(progress);
330              if (status.isFailed()) {
331                  throw new MojoExecutionException("Failed to undeploy module: " + moduleId);
332              }
333    
334              log.info("Undeployed module(s):");
335              logModules(found, "    ");
336            }
337        }
338    
339        protected void logModules(final TargetModuleID[] targetIds) {
340            logModules(targetIds, "");
341        }
342    
343        protected void logModules(final TargetModuleID[] targetIds, final String pad) {
344            assert targetIds != null;
345            assert pad != null;
346    
347            for (int i=0; i<targetIds.length; i++) {
348                String url = targetIds[i].getWebURL();
349                log.info(pad + "[" + i + "] " + targetIds[i].getModuleID() + (url == null ? "" : ("; URL: " + url)));
350    
351                TargetModuleID[] children = targetIds[i].getChildTargetModuleID();
352                if (children != null) {
353                    logModules(children, pad + "    ");
354                }
355            }
356        }
357    }