View Javadoc

1   /**
2    * The MIT License
3    * 
4    * Copyright 2006-2012 The Codehaus.
5    * 
6    * Permission is hereby granted, free of charge, to any person obtaining a copy of
7    * this software and associated documentation files (the "Software"), to deal in
8    * the Software without restriction, including without limitation the rights to
9    * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
10   * of the Software, and to permit persons to whom the Software is furnished to do
11   * so, subject to the following conditions:
12   * 
13   * The above copyright notice and this permission notice shall be included in all
14   * copies or substantial portions of the Software.
15   * 
16   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22   * SOFTWARE.
23   */
24  package org.codehaus.mojo.appassembler.daemon.script;
25  
26  import java.io.IOException;
27  import java.io.StringReader;
28  import java.io.StringWriter;
29  import java.util.ArrayList;
30  import java.util.HashMap;
31  import java.util.HashSet;
32  import java.util.Iterator;
33  import java.util.List;
34  import java.util.Map;
35  import java.util.Set;
36  
37  import org.codehaus.mojo.appassembler.daemon.DaemonGeneratorException;
38  import org.codehaus.mojo.appassembler.model.ClasspathElement;
39  import org.codehaus.mojo.appassembler.model.Daemon;
40  import org.codehaus.mojo.appassembler.model.Dependency;
41  import org.codehaus.mojo.appassembler.model.Directory;
42  import org.codehaus.mojo.appassembler.model.JvmSettings;
43  import org.codehaus.plexus.util.IOUtil;
44  import org.codehaus.plexus.util.InterpolationFilterReader;
45  import org.codehaus.plexus.util.StringUtils;
46  
47  /**
48   * @author <a href="mailto:trygve.laugstol@objectware.no">Trygve Laugst&oslash;l</a>
49   * @version $Id: Platform.java 16492 2012-04-29 18:26:21Z khmarbaise $
50   */
51  public class Platform
52  {
53      /**
54       * Unix as Platform name.
55       */
56      public static final String UNIX_NAME = "unix";
57  
58      /**
59       * Windows Platform name.
60       */
61      public static final String WINDOWS_NAME = "windows";
62  
63      private static final Map ALL_PLATFORMS;
64  
65      private static final String DEFAULT_UNIX_BIN_FILE_EXTENSION = "";
66  
67      private static final String DEFAULT_WINDOWS_BIN_FILE_EXTENSION = ".bat";
68  
69      private String binFileExtension;
70  
71      private String name;
72  
73      private boolean isWindows;
74  
75      // -----------------------------------------------------------------------
76      // Static
77      // -----------------------------------------------------------------------
78  
79      static
80      {
81          ALL_PLATFORMS = new HashMap ( );
82          addPlatform ( new Platform ( UNIX_NAME, false, DEFAULT_UNIX_BIN_FILE_EXTENSION ) );
83          addPlatform ( new Platform ( WINDOWS_NAME, true, DEFAULT_WINDOWS_BIN_FILE_EXTENSION ) );
84      }
85  
86      private static Platform addPlatform ( Platform platform )
87      {
88          ALL_PLATFORMS.put ( platform.name, platform );
89  
90          return platform;
91      }
92  
93      /**
94       * Get an instance of the named platform.
95       * 
96       * @param platformName
97       *            The name of the wished platform.
98       * @return Instance of the platform.
99       * @throws DaemonGeneratorException
100      *             in case of an wrong platformname.
101      */
102     public static Platform getInstance ( String platformName )
103             throws DaemonGeneratorException
104     {
105         Platform platform = ( Platform ) ALL_PLATFORMS.get ( platformName );
106 
107         if ( platform == null )
108         {
109             throw new DaemonGeneratorException ( "Unknown platform name '" + platformName + "'" );
110         }
111 
112         return platform;
113     }
114 
115     /**
116      * Get the names of all available platforms.
117      * 
118      * @return The names of the platform.
119      */
120     public static Set getAllPlatformNames ()
121     {
122         return ALL_PLATFORMS.keySet ( );
123     }
124 
125     /**
126      * Get all platforms.
127      * 
128      * @return All platforms.
129      */
130     public static Set getAllPlatforms ()
131     {
132         return new HashSet ( ALL_PLATFORMS.values ( ) );
133     }
134 
135     /**
136      * Redefine the list of platforms with the given one.
137      * 
138      * @param platformList
139      *            The new list of platforms.
140      * @return The redefined platforms set.
141      * @throws DaemonGeneratorException
142      *             in case of an error.
143      */
144     public static Set getPlatformSet ( List platformList )
145             throws DaemonGeneratorException
146     {
147         return getPlatformSet ( platformList, new HashSet ( ALL_PLATFORMS.values ( ) ) );
148     }
149 
150     /**
151      * Get back all platforms.
152      * 
153      * @param platformList
154      *            The list of platforms.
155      * @param allSet
156      *            The all set list.
157      * @return Get the platform sets.
158      * @throws DaemonGeneratorException
159      *             in case of an error.
160      */
161     public static Set getPlatformSet ( List platformList, Set allSet )
162             throws DaemonGeneratorException
163     {
164         if ( platformList == null )
165         {
166             return allSet;
167         }
168 
169         if ( platformList.size ( ) == 1 )
170         {
171             Object first = platformList.get ( 0 );
172 
173             if ( "all".equals ( first ) )
174             {
175                 return allSet;
176             }
177 
178             throw new DaemonGeneratorException (
179                     "The special platform 'all' can only be used if it is the only element in the platform list." );
180         }
181 
182         Set platformSet = new HashSet ( );
183 
184         for ( Iterator it = platformList.iterator ( ); it.hasNext ( ); )
185         {
186             String platformName = ( String ) it.next ( );
187 
188             if ( platformName.equals ( "all" ) )
189             {
190                 throw new DaemonGeneratorException (
191                         "The special platform 'all' can only be used if it is the only element in a platform list." );
192             }
193 
194             platformSet.add ( getInstance ( platformName ) );
195         }
196 
197         return platformSet;
198     }
199 
200     // -----------------------------------------------------------------------
201     //
202     // -----------------------------------------------------------------------
203 
204     private Platform ( String name, boolean isWindows, String binFileExtension )
205     {
206         this.name = name;
207 
208         this.isWindows = isWindows;
209 
210         this.binFileExtension = binFileExtension;
211     }
212 
213     // -----------------------------------------------------------------------
214     // The platform-specific bits
215     // -----------------------------------------------------------------------
216 
217     /**
218      * The interpolation token either for windows or unix.
219      * 
220      * @return The token which is used.
221      */
222     public String getInterpolationToken ()
223     {
224         return isWindows ? "#" : "@";
225     }
226 
227     /**
228      * @return The binary extension.
229      */
230     public String getBinFileExtension ()
231     {
232         return binFileExtension;
233     }
234 
235     /**
236      * @return BASEDIR representation for windows or unix.
237      */
238     public String getBasedir ()
239     {
240         return isWindows ? "\"%BASEDIR%\"" : "\"$BASEDIR\"";
241     }
242 
243     /**
244      * @return REPO representation for windows or unix.
245      */
246     public String getRepo ()
247     {
248         return isWindows ? "\"%REPO%\"" : "\"$REPO\"";
249     }
250 
251     /**
252      * @return The separator for windows or unix.
253      */
254     public String getSeparator ()
255     {
256         return isWindows ? "\\" : "/";
257     }
258 
259     /**
260      * @return The path separator for windows or unix.
261      */
262     public String getPathSeparator ()
263     {
264         return isWindows ? ";" : ":";
265     }
266 
267     /**
268      * @return Comment prefix for windows or unix.
269      */
270     public String getCommentPrefix ()
271     {
272         return isWindows ? "@REM " : "# ";
273     }
274 
275     public String getNewLine ()
276     {
277         return isWindows ? "\r\n" : "\n";
278     }
279 
280     // -----------------------------------------------------------------------
281     // This part depend on the platform-specific parts
282     // -----------------------------------------------------------------------
283 
284     /**
285      * Get the ClassPath based on the given Daemon.
286      * 
287      * @param daemon
288      *            The Daemon instance.
289      * @return The classpath as a string.
290      * @throws DaemonGeneratorException
291      *             in case of an error.
292      */
293     public String getClassPath ( Daemon daemon )
294             throws DaemonGeneratorException
295     {
296         List classpath = daemon.getAllClasspathElements ( );
297 
298         StringBuffer classpathBuffer = new StringBuffer ( );
299 
300         for ( Iterator it = classpath.iterator ( ); it.hasNext ( ); )
301         {
302             if ( classpathBuffer.length ( ) > 0 )
303             {
304                 classpathBuffer.append ( getPathSeparator ( ) );
305             }
306 
307             // -----------------------------------------------------------------------
308             //
309             // -----------------------------------------------------------------------
310 
311             Object object = it.next ( );
312 
313             if ( object instanceof Directory )
314             {
315                 Directory directory = ( Directory ) object;
316 
317                 if ( directory.getRelativePath ( ).charAt ( 0 ) != '/' )
318                 {
319                     classpathBuffer.append ( getBasedir ( ) ).append ( getSeparator ( ) );
320                 }
321             }
322             else if ( object instanceof Dependency )
323             {
324                 classpathBuffer.append ( getRepo ( ) ).append ( getSeparator ( ) );
325             }
326             else
327             {
328                 throw new DaemonGeneratorException ( "Unknown classpath element type: "
329                         + object.getClass ( ).getName ( ) );
330             }
331 
332             classpathBuffer.append ( StringUtils.replace ( ( ( ClasspathElement ) object ).getRelativePath ( ),
333                     "/", getSeparator ( ) ) );
334         }
335 
336         return classpathBuffer.toString ( );
337     }
338 
339     private String interpolateBaseDirAndRepo ( String content )
340     {
341         StringReader sr = new StringReader ( content );
342         StringWriter result = new StringWriter ( );
343 
344         Map context = new HashMap ( );
345 
346         context.put ( "BASEDIR", StringUtils.quoteAndEscape ( getBasedir ( ), '"' ) );
347         context.put ( "REPO", StringUtils.quoteAndEscape ( getRepo ( ), '"' ) );
348         InterpolationFilterReader interpolationFilterReader =
349                 new InterpolationFilterReader ( sr, context, "@", "@" );
350         try
351         {
352             IOUtil.copy ( interpolationFilterReader, result );
353         }
354         catch ( IOException e )
355         {
356             // shouldn't happen...
357         }
358         return result.toString ( );
359     }
360 
361     private List convertArguments ( List strings )
362     {
363         if ( strings == null )
364         {
365             return strings;
366         }
367 
368         ArrayList result = new ArrayList ( );
369         for ( Iterator iterator = strings.iterator ( ); iterator.hasNext ( ); )
370         {
371             String argument = ( String ) iterator.next ( );
372             result.add ( interpolateBaseDirAndRepo ( argument ) );
373         }
374 
375         return result;
376     }
377 
378     /**
379      * Get the extra JVMArguments.
380      * 
381      * @param jvmSettings
382      *            The JVM settings
383      * @return The created string which contains <code>-X</code> options for the JVM settings.
384      * @throws IOException
385      *             in case of an error.
386      */
387     public String getExtraJvmArguments ( JvmSettings jvmSettings ) throws IOException
388     {
389         if ( jvmSettings == null )
390         {
391             return "";
392         }
393 
394         String vmArgs = "";
395 
396         vmArgs = addJvmSetting ( "-Xms", jvmSettings.getInitialMemorySize ( ), vmArgs );
397         vmArgs = addJvmSetting ( "-Xmx", jvmSettings.getMaxMemorySize ( ), vmArgs );
398         vmArgs = addJvmSetting ( "-Xss", jvmSettings.getMaxStackSize ( ), vmArgs );
399 
400         vmArgs += arrayToString ( convertArguments ( jvmSettings.getExtraArguments ( ) ), "" );
401         vmArgs += arrayToString ( jvmSettings.getSystemProperties ( ), "-D" );
402 
403         return vmArgs.trim ( );
404     }
405 
406     private String arrayToString ( List strings, String separator )
407     {
408         String string = "";
409 
410         if ( strings != null )
411         {
412             Iterator it = strings.iterator ( );
413 
414             while ( it.hasNext ( ) )
415             {
416                 String s = ( String ) it.next ( );
417 
418                 if ( s.indexOf ( ' ' ) == -1 )
419                 {
420                     string += " " + separator + s;
421                 }
422                 else
423                 {
424                     string += " \"" + separator + s + "\"";
425                 }
426             }
427         }
428 
429         return string;
430     }
431 
432     /**
433      * Get the application arguments.
434      * 
435      * @param descriptor
436      *            Instance of the daemon descriptor.
437      * @return The list of application arguments.
438      */
439     public String getAppArguments ( Daemon descriptor )
440     {
441         List commandLineArguments = convertArguments ( descriptor.getCommandLineArguments ( ) );
442 
443         if ( commandLineArguments == null || commandLineArguments.size ( ) == 0 )
444         {
445             return null;
446         }
447 
448         if ( commandLineArguments.size ( ) == 1 )
449         {
450             return ( String ) commandLineArguments.get ( 0 );
451         }
452 
453         Iterator it = commandLineArguments.iterator ( );
454 
455         String appArguments = ( String ) it.next ( );
456 
457         while ( it.hasNext ( ) )
458         {
459             appArguments += " " + it.next ( );
460         }
461 
462         return appArguments;
463     }
464 
465     private String addJvmSetting ( String argType, String extraJvmArgument, String vmArgs )
466     {
467         if ( StringUtils.isEmpty ( extraJvmArgument ) )
468         {
469             return vmArgs;
470         }
471 
472         return vmArgs + " " + argType + extraJvmArgument;
473     }
474 
475     /**
476      * Get the environment setup file.
477      * 
478      * @param daemon
479      *            The instance of the Daemon for which this is beeing produced.
480      * @return The created string which contains the path to the setup file.
481      */
482     public String getEnvSetup ( Daemon daemon )
483     {
484         String envSetup = "";
485 
486         String envSetupFileName = daemon.getEnvironmentSetupFileName ( );
487 
488         if ( envSetupFileName != null )
489         {
490             if ( isWindows )
491             {
492                 String envScriptPath = "\"%BASEDIR%\\bin\\" + envSetupFileName + ".bat\"";
493 
494                 envSetup = "if exist " + envScriptPath + " call " + envScriptPath;
495             }
496             else
497             {
498                 String envScriptPath = "\"$BASEDIR\"/bin/" + envSetupFileName;
499                 envSetup = "[ -f " + envScriptPath + " ] && . " + envScriptPath;
500             }
501         }
502 
503         return envSetup;
504     }
505 
506     // -----------------------------------------------------------------------
507     // Object overrides
508     // -----------------------------------------------------------------------
509 
510     /*
511      * (non-Javadoc)
512      * @see java.lang.Object#equals(java.lang.Object)
513      */
514     public boolean equals ( Object o )
515     {
516         if ( this == o )
517         {
518             return true;
519         }
520 
521         if ( o == null || getClass ( ) != o.getClass ( ) )
522         {
523             return false;
524         }
525 
526         Platform platform = ( Platform ) o;
527 
528         return name.equals ( platform.name );
529     }
530 
531     /*
532      * (non-Javadoc)
533      * @see java.lang.Object#hashCode()
534      */
535     public int hashCode ()
536     {
537         return name.hashCode ( );
538     }
539 
540     /**
541      * The name of the platform.
542      * 
543      * @return The name of the platform.
544      */
545     public String getName ()
546     {
547         return name;
548     }
549 
550     /**
551      * ShowConsole window.
552      * 
553      * @param daemon
554      * @return true yes false otherwise.
555      */
556     public boolean isShowConsoleWindow ( Daemon daemon )
557     {
558         return daemon.isShowConsoleWindow ( ) && isWindows;
559     }
560 
561     // -----------------------------------------------------------------------
562     // Setters for the platform-specific bits
563     // -----------------------------------------------------------------------
564 
565     /**
566      * Set the bin file extension.
567      * 
568      * @param binFileExtension The extension of the binary file.
569      */
570     public void setBinFileExtension ( String binFileExtension )
571     {
572         // We can't have a null extension
573         if ( binFileExtension == null )
574         {
575             this.binFileExtension = "";
576         }
577         else
578         {
579             this.binFileExtension = binFileExtension;
580         }
581     }
582 }