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 }