2011/08/05 - Jakarta Cactus has been retired.

For more information, please explore the Attic.

View Javadoc

1   /* 
2    * ========================================================================
3    * 
4    * Licensed to the Apache Software Foundation (ASF) under one or more
5    * contributor license agreements.  See the NOTICE file distributed with
6    * this work for additional information regarding copyright ownership.
7    * The ASF licenses this file to You under the Apache License, Version 2.0
8    * (the "License"); you may not use this file except in compliance with
9    * the License.  You may obtain a copy of the License at
10   * 
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   * 
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   * 
19   * ========================================================================
20   */
21  package org.apache.cactus.eclipse.runner.containers.ant;
22  
23  import java.io.File;
24  import java.lang.reflect.InvocationTargetException;
25  import java.net.MalformedURLException;
26  import java.net.URL;
27  import java.util.Hashtable;
28  import java.util.Vector;
29  
30  import org.apache.cactus.eclipse.runner.containers.IContainerManager;
31  import org.apache.cactus.eclipse.runner.containers.IContainerProvider;
32  import org.apache.cactus.eclipse.runner.ui.CactusMessages;
33  import org.apache.cactus.eclipse.runner.ui.CactusPlugin;
34  import org.apache.cactus.eclipse.webapp.internal.WarBuilder;
35  import org.eclipse.core.boot.BootLoader;
36  import org.eclipse.core.runtime.CoreException;
37  import org.eclipse.core.runtime.IProgressMonitor;
38  import org.eclipse.core.runtime.NullProgressMonitor;
39  import org.eclipse.core.runtime.Path;
40  import org.eclipse.debug.core.DebugPlugin;
41  import org.eclipse.debug.core.ILaunchConfigurationType;
42  import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
43  import org.eclipse.debug.core.ILaunchManager;
44  import org.eclipse.jdt.core.IJavaProject;
45  import org.eclipse.jdt.core.JavaModelException;
46  import org.eclipse.jface.dialogs.ProgressMonitorDialog;
47  import org.eclipse.jface.operation.IRunnableWithProgress;
48  import org.eclipse.swt.widgets.Shell;
49  import org.eclipse.ui.externaltools.internal.model.IExternalToolConstants;
50  
51  /**
52   * Implementation of IContainerManager based on Ant.
53   * 
54   * @version $Id: AntContainerManager.java 238816 2004-02-29 16:36:46Z vmassol $
55   */
56  public class AntContainerManager implements IContainerManager
57  {
58      /**
59       * The progress monitor associated with the current action. 
60       */
61      private IProgressMonitor currentPM;
62  
63      /**
64       * True if the provider has successfully been deployed. 
65       */
66      private boolean stateProviderDeployed = false;
67  
68      /**
69       * True if the war has successfully been created. 
70       */
71      private boolean stateWarCreated = false;
72  
73      /**
74       * True if the container has been prepared. 
75       */
76      private boolean prepared = false;
77  
78      /**
79       * Provider currently used 
80       */
81      private AntContainerProvider provider;
82  
83      /**
84       * Table containing all the information needed
85       * (key = target mask & value = container home directory)
86       * to call the scripts
87       */
88      private Hashtable containerHomes;
89  
90      /**
91       * Ant arguments common to all container providers 
92       */
93      private Vector antArguments = new Vector();
94  
95      /**
96       * Path to the Ant build file for the manager
97       */
98      private String buildFilePath;
99  
100     /**
101      * Context path for the container provider
102      */
103     private String contextURLPath;
104 
105     /**
106      * Reference to the War file so that we can delete it on tearDown()
107      */
108     private File war;
109 
110     /**
111      * Constructor.
112      * 
113      * @param theBuildFilePath path to the Ant build file for this manager
114      * @param thePort the port that will be used when setting up the containers
115      * @param theTargetDir temporary directory to use for
116      *     containers configuration
117      * @param theHomes ContainerHome array for container config
118      * @param theContextURLPath context path of the container provider
119      * @throws CoreException if an argument is invalid 
120      */
121     public AntContainerManager(String theBuildFilePath, int thePort,
122         String theTargetDir, Hashtable theHomes, String theContextURLPath)
123         throws CoreException
124     {
125         this.buildFilePath = theBuildFilePath;
126         init(thePort, theTargetDir, theHomes, theContextURLPath);
127     }
128 
129     /**
130      * Initializer.
131      * 
132      * @param thePort the port that will be used when setting up the containers
133      * @param theTargetDir temporary directory to use for
134      *     containers configuration
135      * @param theHomes ContainerHome array for container config
136      * @param theContextURLPath context path of the container provider 
137      * @throws CoreException if an argument is invalid
138      */
139     public void init(int thePort, String theTargetDir, Hashtable theHomes,
140         String theContextURLPath) throws CoreException
141     {
142         if (thePort <= 0)
143         {
144             throw CactusPlugin.createCoreException(
145                 "CactusLaunch.message.invalidproperty.port",
146                 null);
147         }
148         if (theTargetDir.equalsIgnoreCase(""))
149         {
150             throw CactusPlugin.createCoreException(
151                 "CactusLaunch.message.invalidproperty.tempdir",
152                 null);
153         }
154         if (theHomes.size() == 0)
155         {
156             throw CactusPlugin.createCoreException(
157                 "CactusLaunch.message.invalidproperty.containers",
158                 null);
159         }
160         if (theContextURLPath.equalsIgnoreCase(""))
161         {
162             throw CactusPlugin.createCoreException(
163                 "CactusLaunch.message.invalidproperty.contextpath",
164                 null);
165         }
166         this.contextURLPath = theContextURLPath;
167         this.containerHomes = theHomes;
168         antArguments.add("-Dcactus.port=" + thePort);
169         antArguments.add("-Dcactus.target.dir=" + theTargetDir);
170         // Avoid Ant console popups on win32 platforms
171         if (BootLoader.getOS().equals(BootLoader.OS_WIN32))
172         {
173             antArguments.add("-Dcactus.jvm=javaw");
174         }
175         this.provider = (AntContainerProvider) getContainerProviders()[0];
176     }
177 
178     /**
179      * @return an array of provider containers supported by the manager
180      */
181     private IContainerProvider[] getContainerProviders()
182     {
183         String[] ids =
184             (String[]) containerHomes.keySet().toArray(
185                 new String[containerHomes.size()]);
186         IContainerProvider[] providers = new IContainerProvider[ids.length];
187         for (int i = 0; i < providers.length; i++)
188         {
189             providers[i] =
190                 new AntContainerProvider(
191                     this,
192                     ids[i],
193                     (String) containerHomes.get(ids[i]));
194         }
195         return providers;
196     }
197 
198     /**
199      * @param theTarget the Ant target to be called
200      * @param theProviderArguments the Ant arguments specific for
201      *     the container provider
202      * @return a launch configuration copy for Ant build
203      * @throws CoreException if the launch configuration cannot be created
204      */
205     public ILaunchConfigurationWorkingCopy createAntLaunchConfiguration(
206         String[] theProviderArguments, String theTarget) throws CoreException
207     {
208         CactusPlugin thePlugin = CactusPlugin.getDefault();
209         URL buildFileURL = thePlugin.find(new Path(buildFilePath));
210         if (buildFileURL == null)
211         {
212             throw CactusPlugin.createCoreException(
213                 "CactusLaunch.message.prepare.error.plugin.file",
214                 " : " + buildFilePath,
215                 null);
216         }
217         File buildFileLocation = new File(buildFileURL.getPath());
218 
219         ILaunchManager launchManager =
220             DebugPlugin.getDefault().getLaunchManager();
221         ILaunchConfigurationType antType =
222             launchManager.getLaunchConfigurationType(
223                 IExternalToolConstants.ID_PROGRAM_LAUNCH_CONFIGURATION_TYPE); //ID_ANT_LAUNCH_CONFIGURATION_TYPE
224                 
225         String name = "Cactus container start-up";
226         String uniqueName =
227             launchManager.generateUniqueLaunchConfigurationNameFrom(name);
228         ILaunchConfigurationWorkingCopy antConfig =
229             antType.newInstance(null, uniqueName);
230 
231         antConfig.setAttribute(
232             IExternalToolConstants.ATTR_LOCATION,
233             buildFileLocation.getAbsolutePath());
234         antConfig.setAttribute(
235             IExternalToolConstants.ATTR_TOOL_ARGUMENTS,
236             getString(getAllAntArguments(theProviderArguments)));
237         /*antConfig.setAttribute(
238             IExternalToolConstants.ATTR_ANT_TARGETS,
239             theTarget);
240         antConfig.setAttribute(
241             IExternalToolConstants.ATTR_RUN_IN_BACKGROUND,
242             false);*/
243         return antConfig;
244     }
245 
246     /**
247      * @param theStringArray an array of String
248      * @return the concatenation of the String elements 
249      */
250     private String getString(String[] theStringArray)
251     {
252         String result = "";
253         for (int i = 0; i < theStringArray.length; i++)
254         {
255             result += theStringArray[i] + " ";
256         }
257         return result;
258     }
259 
260     /**
261      * @param theProviderArguments the container provider specific arguments
262      * @return an array of arguments for the container build
263      */
264     private String[] getAllAntArguments(String[] theProviderArguments)
265     {
266         String[] managerArguments =
267             (String[]) antArguments.toArray(new String[antArguments.size()]);
268         String[] allArguments =
269             new String[theProviderArguments.length + managerArguments.length];
270         System.arraycopy(
271             theProviderArguments,
272             0,
273             allArguments,
274             0,
275             theProviderArguments.length);
276         System.arraycopy(
277             managerArguments,
278             0,
279             allArguments,
280             theProviderArguments.length,
281             managerArguments.length);
282         return allArguments;
283     }
284 
285     /**
286      * @see IContainerManager#prepare(org.eclipse.jdt.core.IJavaProject)
287      */
288     public void prepare(final IJavaProject theJavaProject)
289     {
290         this.prepared = false;
291         CactusPlugin.log("Preparing cactus tests");
292         new Thread(new Runnable()
293         {
294             public void run()
295             {
296                 try
297                 {
298                     prepareCactusTests(
299                         theJavaProject,
300                         new NullProgressMonitor(),
301                         provider);
302                 }
303                 catch (CoreException e)
304                 {
305                     CactusPlugin.displayErrorMessage(
306                         CactusMessages.getString(
307                             "CactusLaunch.message.prepare.error"),
308                         e.getMessage(),
309                         null);
310                     cancelPreparation(provider);
311                     return;
312                 }
313             }
314         }).start();
315         while (!prepared)
316         {
317             try
318             {
319                 Thread.sleep(100);
320             }
321             catch (InterruptedException e)
322             {
323                 CactusPlugin.log(e);
324             }
325         }
326     }
327 
328     /**
329      * Creates the war file, deploys and launches the container.
330      * 
331      * @param theJavaProject the Java file
332      * @param thePM the progress monitor to report to
333      * @param theProvider the provider to prepare
334      * @throws CoreException if anything goes wrong during preparation
335      */
336     private void prepareCactusTests(IJavaProject theJavaProject,
337         IProgressMonitor thePM, IContainerProvider theProvider)
338         throws CoreException
339     {
340         this.currentPM = thePM;
341         thePM.beginTask(
342             CactusMessages.getString("CactusLaunch.message.prepare"),
343             10);
344         try
345         {
346             URL warURL = createWar(theJavaProject, thePM);
347             this.stateWarCreated = true;
348             theProvider.deploy(this.contextURLPath, warURL, null, thePM);
349             this.stateProviderDeployed = true;
350             theProvider.start(null, thePM);
351         }
352         catch (MalformedURLException e)
353         {
354             CactusPlugin.log(e);
355             throw CactusPlugin.createCoreException(
356                 "CactusLaunch.message.war.malformed",
357                 e);
358         }
359         thePM.done();
360     }
361 
362     /**
363      * @param theJavaProject the project to build the war from
364      * @param thePM monitor that tracks the progression
365      * @return the URL to the war file
366      * @throws JavaModelException if we cannot create the war
367      * @throws CoreException if we cannot create the war
368      * @throws MalformedURLException if we cannot create the war
369      */
370     private URL createWar(IJavaProject theJavaProject, IProgressMonitor thePM)
371         throws JavaModelException, CoreException, MalformedURLException
372     {
373         WarBuilder newWar = new WarBuilder(theJavaProject);
374         this.war = newWar.createWar(thePM);
375         return war.toURL();
376     }
377 
378     /**
379      * Launches a new progress dialog for preparation cancellation.
380      * 
381      * @param theProvider the provider which preparation to cancel
382      */
383     private void cancelPreparation(final IContainerProvider theProvider)
384     {
385         ProgressMonitorDialog dialog = new ProgressMonitorDialog(getShell());
386         IRunnableWithProgress tearDownRunnable = new IRunnableWithProgress()
387         {
388             public void run(IProgressMonitor thePM) throws InterruptedException
389             {
390                 try
391                 {
392                     teardownCactusTests(thePM, theProvider);
393                 }
394                 catch (CoreException e)
395                 {
396                     throw new InterruptedException(e.getMessage());
397                 }
398             }
399         };
400         try
401         {
402             dialog.run(true, true, tearDownRunnable);
403         }
404         catch (InvocationTargetException tearDownE)
405         {
406             CactusPlugin.displayErrorMessage(
407                 CactusMessages.getString("CactusLaunch.message.teardown.error"),
408                 tearDownE.getTargetException().getMessage(),
409                 null);
410         }
411         catch (InterruptedException tearDownE)
412         {
413             CactusPlugin.displayErrorMessage(
414                 CactusMessages.getString("CactusLaunch.message.teardown.error"),
415                 tearDownE.getMessage(),
416                 null);
417         }
418     }
419 
420     /**
421      * Tears down the Cactus tests
422      */
423     public void tearDown()
424     {
425         CactusPlugin.log("Tearing down cactus tests");
426         try
427         {
428             teardownCactusTests(new NullProgressMonitor(), provider);
429         }
430         catch (CoreException e)
431         {
432             CactusPlugin.displayErrorMessage(
433                 CactusMessages.getString("CactusLaunch.message.teardown.error"),
434                 e.getMessage(),
435                 null);
436             cancelPreparation(provider);
437         }
438     }
439 
440     /**
441      * Stops the container and undeploys (cleans) it.
442      * @param thePM a progress monitor that reflects progress made while tearing
443      * down the container setup
444      * @param theProvider the provider of the container to stop and undeploy
445      * @throws CoreException if an error occurs when tearing down
446      */
447     private void teardownCactusTests(IProgressMonitor thePM,
448         IContainerProvider theProvider) throws CoreException
449     {
450         thePM.beginTask(
451             CactusMessages.getString("CactusLaunch.message.teardown"),
452             100);
453         theProvider.stop(null, thePM);
454         if (stateProviderDeployed)
455         {
456             theProvider.undeploy(null, null, thePM);
457         }
458         if (stateWarCreated)
459         {
460             this.war.delete();
461         }
462         thePM.done();
463     }
464 
465     /**
466      * Convenience method to get the active Shell.
467      * @return the active shell 
468      */
469     protected Shell getShell()
470     {
471         return CactusPlugin.getActiveWorkbenchShell();
472     }
473 
474     /**
475      * @param theRunner the Eclipse runner to call when tests are done
476      */
477     public void setEclipseRunner(EclipseRunTests theRunner)
478     {
479         provider.setEclipseRunner(theRunner);
480     }
481 
482     /**
483      * Sets the prepared flag.
484      */
485     public void preparationDone()
486     {
487         this.prepared = true;
488     }
489 
490 }