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