View Javadoc
1   package org.codehaus.mojo.gwt.shell;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.maven.artifact.Artifact;
23  import org.apache.maven.plugin.MojoExecutionException;
24  import org.apache.maven.plugin.MojoFailureException;
25  import org.apache.maven.plugins.annotations.Parameter;
26  import org.codehaus.mojo.gwt.AbstractGwtModuleMojo;
27  import org.codehaus.plexus.util.StringUtils;
28  import org.codehaus.plexus.util.cli.CommandLineUtils;
29  
30  import java.io.File;
31  import java.util.ArrayList;
32  import java.util.Arrays;
33  import java.util.Collection;
34  import java.util.List;
35  
36  /**
37   * Support running GWT SDK Tools as forked JVM with classpath set according to project source/resource directories and
38   * dependencies.
39   * 
40   * @author ccollins
41   * @author cooper
42   * @author willpugh
43   * @version $Id$
44   */
45  public abstract class AbstractGwtShellMojo
46      extends AbstractGwtModuleMojo
47  {
48      /**
49       * Location on filesystem where GWT will write generated content for review (-gen option to GWT Compiler).
50       * <p>
51       * Can be set from command line using '-Dgwt.gen=...'
52       */
53      @Parameter(defaultValue = "${project.build.directory}/.generated", property = "gwt.gen")
54      private File gen;
55  
56      /**
57       * Whether to add -gen parameter to the compiler command line
58       * <p>
59       * Can be set from command line using '-Dgwt.genParam=false'. Defaults to 'true' for backwards compatibility.
60       *
61       * @since 2.5.0-rc1
62       */
63      @Parameter(defaultValue = "true", property = "gwt.genParam")
64      private boolean genParam;
65  
66      /**
67       * GWT logging level (-logLevel ERROR, WARN, INFO, TRACE, DEBUG, SPAM, or ALL).
68       * <p>
69       * Can be set from command line using '-Dgwt.logLevel=...'
70       */
71      @Parameter(defaultValue = "INFO", property = "gwt.logLevel")
72      private String logLevel;
73  
74      /**
75       * GWT JavaScript compiler output style (-style OBF[USCATED], PRETTY, or DETAILED).
76       * <p>
77       * Can be set from command line using '-Dgwt.style=...'
78       */
79      @Parameter(property = "gwt.style")
80      protected String style;
81  
82      /**
83       * The directory into which deployable but not servable output files will be written (defaults to 'WEB-INF/deploy' under the webappDirectory directory/jar, and may be the same as the extra directory/jar)
84       *
85       * @since 2.3.0-1
86       */
87      @Parameter
88      private File deploy;
89  
90      /**
91       * Extra JVM arguments that are passed to the GWT-Maven generated scripts (for compiler, shell, etc - typically use
92       * -Xmx512m here, or -XstartOnFirstThread, etc).
93       * <p>
94       * Can be set from command line using '-Dgwt.extraJvmArgs=...', defaults to setting max Heap size to be large enough
95       * for most GWT use cases.
96       * </p>
97       */
98      @Parameter(property = "gwt.extraJvmArgs", defaultValue="-Xmx512m")
99      private String extraJvmArgs;
100 
101     /**
102      * Option to specify the jvm (or path to the java executable) to use with the forking scripts. For the default, the
103      * jvm will be the same as the one used to run Maven.
104      *
105      * @since 1.1
106      */
107     @Parameter(property = "gwt.jvm")
108     private String jvm;
109 
110     /**
111      * Forked process execution timeOut. Usefull to avoid maven to hang in continuous integration server.
112      */
113     @Parameter
114     private int timeOut;
115 
116     /**
117      *
118      * Artifacts to be included as source-jars in GWTCompiler Classpath. Removes the restriction that source code must
119      * be bundled inside of the final JAR when dealing with external utility libraries not designed exclusivelly for
120      * GWT. The plugin will download the source.jar if necessary.
121      *
122      * This option is a workaround to avoid packaging sources inside the same JAR when splitting and application into
123      * modules. A smaller JAR can then be used on server classpath and distributed without sources (that may not be
124      * desirable).
125      *
126      * @deprecated add a {@code <classifier>sources</classifier>} dependency instead
127      */
128     @Deprecated
129     @Parameter
130     private String[] compileSourcesArtifacts;
131 
132     /**
133      * Whether to use the persistent unit cache or not.
134      * <p>
135      * Can be set from command line using '-Dgwt.persistentunitcache=...'
136      *
137      * @since 2.5.0-rc1
138      */
139     @Parameter(property = "gwt.persistentunitcache")
140     private Boolean persistentunitcache;
141 
142     /**
143      * The directory where the persistent unit cache will be created if enabled.
144      * <p>
145      * Can be set from command line using '-Dgwt.persistentunitcachedir=...'
146      *
147      * @since 2.5.0-rc1
148      */
149     @Parameter(property = "gwt.persistentunitcachedir")
150     private File persistentunitcachedir;
151 
152     // methods
153 
154     /**
155      * {@inheritDoc}
156      *
157      * @see org.apache.maven.plugin.Mojo#execute()
158      */
159     public final void execute()
160         throws MojoExecutionException, MojoFailureException
161     {
162         doExecute();
163     }
164 
165     public abstract void doExecute()
166         throws MojoExecutionException, MojoFailureException;
167 
168     protected String getExtraJvmArgs()
169     {
170         return extraJvmArgs;
171     }
172 
173     protected String getLogLevel()
174     {
175         return this.logLevel;
176     }
177 
178     protected String getStyle()
179     {
180         return this.style;
181     }
182 
183 
184     protected String getJvm()
185     {
186         return jvm;
187     }
188 
189     /**
190      * hook to post-process the dependency-based classpath
191      */
192     protected void postProcessClassPath( Collection<File> classpath )
193     {
194         // Nothing to do in most case
195     }
196 
197     private List<String> getJvmArgs()
198     {
199         List<String> extra = new ArrayList<String>();
200         String userExtraJvmArgs = getExtraJvmArgs();
201         if ( userExtraJvmArgs != null )
202         {
203             try
204             {
205                 // cleanup new lines bc removeDuplicateWhitespace leaves the first isWhitespace character found
206                 userExtraJvmArgs = userExtraJvmArgs.replace('\n', ' ').replace('\r', ' ');
207                 return new ArrayList<String>(Arrays.asList( CommandLineUtils.translateCommandline( StringUtils.removeDuplicateWhitespace( userExtraJvmArgs ) ) ) );
208             }
209             catch ( Exception e )
210             {
211                 throw new RuntimeException( e );
212             }
213         }
214         return extra;
215     }
216 
217     /**
218      * @param timeOut the timeOut to set
219      */
220     public void setTimeOut( int timeOut )
221     {
222         this.timeOut = timeOut;
223     }
224 
225     protected JavaCommand createJavaCommand() {
226         return new JavaCommand()
227             .setLog( getLog() )
228             .setJvm( getJvm() )
229             .setJvmArgs( getJvmArgs() )
230             .setTimeOut( timeOut )
231             .addClassPathProcessors( new ClassPathProcessor()
232             {
233                 @Override
234                 public void postProcessClassPath( List<File> files )
235                 {
236                     AbstractGwtShellMojo.this.postProcessClassPath( files );
237                 }
238             } );
239     }
240     /**
241      * Add sources.jar artifacts for project dependencies listed as compileSourcesArtifacts. This is a GWT hack to avoid
242      * packaging java source files into JAR when sharing code between server and client. Typically, some domain model
243      * classes or business rules may be packaged as a separate Maven module. With GWT packaging this requires to
244      * distribute such classes with code, that may not be desirable.
245      * <p>
246      * The hack can also be used to include utility code from external librariries that may not have been designed for
247      * GWT.
248      */
249     protected void addCompileSourceArtifacts(JavaCommand cmd)
250             throws MojoExecutionException
251     {
252         if ( compileSourcesArtifacts == null )
253         {
254             return;
255         }
256         for ( String include : compileSourcesArtifacts )
257         {
258             List<String> parts = new ArrayList<String>();
259             parts.addAll( Arrays.asList(include.split(":")) );
260             if ( parts.size() == 2 )
261             {
262                 // type is optional as it will mostly be "jar"
263                 parts.add( "jar" );
264             }
265             String dependencyId = StringUtils.join( parts.iterator(), ":" );
266             boolean found = false;
267 
268             for ( Artifact artifact : getProjectArtifacts() )
269             {
270                 getLog().debug( "compare " + dependencyId + " with " + artifact.getDependencyConflictId() );
271                 if ( artifact.getDependencyConflictId().equals( dependencyId ) )
272                 {
273                     getLog().debug( "Add " + dependencyId + " sources.jar artifact to compile classpath" );
274                     Artifact sources =
275                             resolve( artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion(),
276                                     "jar", "sources" );
277                     cmd.addToClasspath( sources.getFile() );
278                     found = true;
279                     break;
280                 }
281             }
282             if ( !found )
283                 getLog().warn(
284                         "Declared compileSourcesArtifact was not found in project dependencies " + dependencyId );
285         }
286     }
287 
288     protected void addArgumentDeploy(JavaCommand cmd) {
289         if ( deploy != null )
290         {
291             cmd.arg( "-deploy" ).arg( String.valueOf( deploy ) );
292         }
293     }
294 
295     protected void addArgumentGen( JavaCommand cmd )
296     {
297         if ( this.genParam )
298         {
299             if ( !this.gen.exists() )
300             {
301                 this.gen.mkdirs();
302             }
303             cmd.arg( "-gen", this.gen.getAbsolutePath() );
304         }
305     }
306 
307     protected void addPersistentUnitCache(JavaCommand cmd) {
308         if ( persistentunitcache != null )
309         {
310             cmd.systemProperty( "gwt.persistentunitcache", String.valueOf( persistentunitcache.booleanValue() ) );
311         }
312         if ( persistentunitcachedir != null )
313         {
314             cmd.systemProperty( "gwt.persistentunitcachedir", persistentunitcachedir.getAbsolutePath() );
315         }
316     }
317 
318 }