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.BufferedReader;
28  import java.io.File;
29  import java.io.FileInputStream;
30  import java.io.FileNotFoundException;
31  import java.io.FileReader;
32  import java.io.FileWriter;
33  import java.io.IOException;
34  import java.io.InputStream;
35  import java.io.InputStreamReader;
36  import java.util.ArrayList;
37  import java.util.HashMap;
38  import java.util.List;
39  import java.util.Map;
40  import java.util.StringTokenizer;
41  
42  import org.codehaus.mojo.appassembler.daemon.DaemonGeneratorException;
43  import org.codehaus.mojo.appassembler.model.Daemon;
44  import org.codehaus.plexus.archiver.ArchiverException;
45  import org.codehaus.plexus.archiver.util.ArchiveEntryUtils;
46  import org.codehaus.plexus.logging.AbstractLogEnabled;
47  import org.codehaus.plexus.util.FileUtils;
48  import org.codehaus.plexus.util.IOUtil;
49  import org.codehaus.plexus.util.InterpolationFilterReader;
50  
51  /**
52   * @author <a href="mailto:trygve.laugstol@objectware.no">Trygve Laugst&oslash;l</a>
53   * @version $Id$
54   * @plexus.component
55   */
56  public class DefaultScriptGenerator
57      extends AbstractLogEnabled
58      implements ScriptGenerator
59  {
60  
61      private static final String DEFAULT_LICENSE_HEADER = "default-license-header.txt";
62  
63      private boolean isDefaultLicenseHeaderRequested( Daemon daemon )
64      {
65          if ( daemon.getLicenseHeaderFile() == null )
66          {
67              return true;
68          }
69  
70          if ( daemon.getLicenseHeaderFile().trim().length() > 0 )
71          {
72              return false;
73          }
74  
75          return false;
76      }
77  
78      private String getLicenseHeader( Platform platform, Daemon daemon )
79          throws DaemonGeneratorException
80      {
81          List<String> lines = null;
82          if ( isDefaultLicenseHeaderRequested( daemon ) )
83          {
84              getLogger().debug( "Using default licence file (" + DEFAULT_LICENSE_HEADER + ")." );
85              lines = readLicenseHeader();
86          }
87          else
88          {
89              getLogger().debug( "Using license file: " + daemon.getLicenseHeaderFile() );
90              lines = readLicenseHeaderFromFile( new File( daemon.getLicenseHeaderFile() ) );
91          }
92          StringBuffer resultLines = new StringBuffer();
93          for ( int i = 0; i < lines.size(); i++ )
94          {
95              String licenseLine = platform.getCommentPrefix() + lines.get( i );
96              resultLines.append( licenseLine.trim() + platform.getNewLine() );
97          }
98          return resultLines.toString();
99      }
100 
101     private List<String> readLicenseHeader()
102         throws DaemonGeneratorException
103     {
104         ArrayList<String> result = new ArrayList<String>();
105 
106         InputStream in = getClass().getResourceAsStream( DEFAULT_LICENSE_HEADER );
107 
108         InputStreamReader inr = new InputStreamReader( in );
109         try
110         {
111             BufferedReader bufRead = new BufferedReader( inr );
112             String str;
113             while ( ( str = bufRead.readLine() ) != null )
114             {
115                 result.add( str );
116             }
117             bufRead.close();
118         }
119         catch ( IOException e )
120         {
121             throw new DaemonGeneratorException(
122                                                 "Internal error: could not read license header template file (license-header.txt)" );
123         }
124         return result;
125     }
126 
127     private List<String> readLicenseHeaderFromFile( File licenseHeader )
128         throws DaemonGeneratorException
129     {
130         ArrayList<String> result = new ArrayList<String>();
131         try
132         {
133             BufferedReader in = new BufferedReader( new FileReader( licenseHeader ) );
134             String str;
135             while ( ( str = in.readLine() ) != null )
136             {
137                 result.add( str );
138             }
139             in.close();
140         }
141         catch ( IOException e )
142         {
143             throw new DaemonGeneratorException( "Internal error: could not read license header template file "
144                 + licenseHeader.getName() );
145         }
146         return result;
147     }
148 
149     // -----------------------------------------------------------------------
150     // ScriptGenerator Implementation
151     // -----------------------------------------------------------------------
152 
153     /*
154      * (non-Javadoc)
155      * @see org.codehaus.mojo.appassembler.daemon.script.ScriptGenerator#createBinScript(java.lang.String,
156      * org.codehaus.mojo.appassembler.model.Daemon, java.io.File, java.lang.String)
157      */
158     public void createBinScript( String platformName, Daemon daemon, File outputDirectory, String binFolder )
159         throws DaemonGeneratorException
160     {
161         Platform platform = Platform.getInstance( platformName );
162 
163         InputStream in = null;
164 
165         FileWriter out = null;
166         File binFile;
167 
168         try
169         {
170             in = getScriptTemplate( platformName, daemon );
171 
172             InputStreamReader reader = new InputStreamReader( getScriptTemplate( platformName, daemon ) );
173 
174             Map<Object, Object> context = new HashMap<Object, Object>();
175             context.put( "MAINCLASS", daemon.getMainClass() );
176             context.put( "CLASSPATH", platform.getClassPath( daemon ) );
177             context.put( "EXTRA_JVM_ARGUMENTS", platform.getExtraJvmArguments( daemon.getJvmSettings() ) );
178             context.put( "APP_NAME", daemon.getId() );
179             context.put( "ENV_SETUP", platform.getEnvSetup( daemon, binFolder ) );
180             context.put( "REPO", daemon.getRepositoryName() );
181             context.put( "LICENSE_HEADER", getLicenseHeader( platform, daemon ) );
182 
183             if ( daemon.getEndorsedDir() != null )
184             {
185                 context.put( "ENDORSED_DIR", daemon.getEndorsedDir() );
186             }
187             else
188             {
189                 context.put( "ENDORSED_DIR", "" );
190             }
191 
192             if ( platform.isShowConsoleWindow( daemon ) )
193             {
194                 context.put( "JAVA_BINARY", "java" );
195                 context.put( "UNIX_BACKGROUND", "" );
196             }
197             else
198             {
199                 context.put( "JAVA_BINARY", "start /min javaw" );
200                 context.put( "UNIX_BACKGROUND", " &" );
201             }
202 
203             String appArguments = platform.getAppArguments( daemon );
204             if ( appArguments != null )
205             {
206                 context.put( "APP_ARGUMENTS", appArguments + " " );
207             }
208             else
209             {
210                 context.put( "APP_ARGUMENTS", "" );
211             }
212 
213             String interpolationToken = platform.getInterpolationToken();
214             InterpolationFilterReader interpolationFilterReader =
215                 new InterpolationFilterReader( reader, context, interpolationToken, interpolationToken );
216 
217             // Set the name of the bin file
218             String programName = "";
219 
220             if ( daemon.getId() == null || daemon.getId().trim().equals( "" ) )
221             {
222                 // Get class name and use it as the filename
223                 StringTokenizer tokenizer = new StringTokenizer( daemon.getMainClass(), "." );
224                 while ( tokenizer.hasMoreElements() )
225                 {
226                     programName = tokenizer.nextToken();
227                 }
228 
229                 programName = programName.toLowerCase();
230             }
231             else
232             {
233                 programName = daemon.getId();
234             }
235 
236             File binDir = new File( outputDirectory, binFolder );
237             FileUtils.forceMkdir( binDir );
238             binFile = new File( binDir, programName + platform.getBinFileExtension() );
239             if ( Platform.UNIX_NAME.equals( platformName ) )
240             {
241                 // Only in case of an existing file it does make sense
242                 if ( binFile.exists() )
243                 {
244                     try
245                     {
246                         // in case it already exists, make it writable. Maybe deleting would be better?
247                         ArchiveEntryUtils.chmod( binFile, 0777, getLogger(), true );
248                     }
249                     catch ( ArchiverException ae )
250                     {
251                         throw new DaemonGeneratorException( "Failed to change permission for bin file.", ae );
252                     }
253                 }
254             }
255 
256             out = new FileWriter( binFile );
257             getLogger().debug( "Writing shell file for platform '" + platform.getName() + "' to '"
258                                    + binFile.getAbsolutePath() + "'." );
259 
260             IOUtil.copy( interpolationFilterReader, out );
261         }
262         catch ( FileNotFoundException e )
263         {
264             throw new DaemonGeneratorException( "Failed to get template for bin file.", e );
265         }
266         catch ( IOException e )
267         {
268             throw new DaemonGeneratorException( "Failed to write bin file.", e );
269         }
270         finally
271         {
272             IOUtil.close( out );
273             IOUtil.close( in );
274         }
275 
276         if ( Platform.UNIX_NAME.equals( platformName ) )
277         {
278             try
279             {
280                 // TODO: The permissions should be made configurable.
281                 ArchiveEntryUtils.chmod( binFile, 0755, getLogger(), true );
282             }
283             catch ( ArchiverException ae )
284             {
285                 throw new DaemonGeneratorException( "Failed to change permission for bin file.", ae );
286             }
287         }
288     }
289 
290     private InputStream getScriptTemplate( String platformName, Daemon daemon )
291         throws DaemonGeneratorException
292     {
293         InputStream is = null;
294 
295         try
296         {
297             String customTemplate = daemon.getWindowsScriptTemplate();
298             if ( Platform.UNIX_NAME.equals( platformName ) )
299             {
300                 customTemplate = daemon.getUnixScriptTemplate();
301             }
302 
303             if ( customTemplate != null )
304             {
305                 File customTemplateFile = new File( customTemplate );
306                 if ( customTemplateFile.exists() )
307                 {
308                     is = new FileInputStream( customTemplateFile );
309                 }
310                 else
311                 {
312                     is = getClass().getClassLoader().getResourceAsStream( customTemplate );
313                     if ( is == null )
314                     {
315                         throw new DaemonGeneratorException( "Unable to load external template resource: "
316                             + customTemplate );
317                     }
318                 }
319             }
320             else
321             {
322                 is = getClass().getResourceAsStream( platformName + "BinTemplate" );
323                 if ( is == null )
324                 {
325                     throw new DaemonGeneratorException( "Unable to load internal template resource: " + platformName
326                         + "BinTemplate" );
327                 }
328             }
329         }
330         catch ( FileNotFoundException e )
331         {
332             throw new DaemonGeneratorException( "Unable to load external template file", e );
333         }
334 
335         return is;
336 
337     }
338 }