All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.codehaus.mojo.gwt.shell.RunMojo Maven / Gradle / Ivy

There is a newer version: 2.10.0
Show newest version
package org.codehaus.mojo.gwt.shell;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Execute;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;
import org.codehaus.mojo.gwt.utils.GwtModuleReaderException;
import org.codehaus.plexus.archiver.ArchiverException;
import org.codehaus.plexus.archiver.UnArchiver;
import org.codehaus.plexus.archiver.manager.ArchiverManager;
import org.codehaus.plexus.archiver.manager.NoSuchArchiverException;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.DirectoryScanner;

/**
 * Runs the project in the GWT (Classic or Super) Dev Mode for development.
 *
 * @author ccollins
 * @author cooper
 * @version $Id$
 */
@Mojo(name = "run", requiresDirectInvocation = true, requiresDependencyResolution = ResolutionScope.TEST)
@Execute(phase = LifecyclePhase.PROCESS_CLASSES, goal = "war:exploded")
public class RunMojo
    extends AbstractGwtWebMojo
{
    /**
     * Location of the hosted-mode web application structure.
     */
    @Parameter(defaultValue = "${project.build.directory}/${project.build.finalName}")
    // Parameter shared with EclipseMojo
    private File hostedWebapp;

    /**
     * The MavenProject executed by the "compile" phase
     */
    @Parameter(defaultValue = "${executedProject}")
    private MavenProject executedProject;

    /**
     * URL that should be automatically opened in the GWT shell. For example com.myapp.gwt.Module/Module.html.
     * 

* When the host page is outside the module "public" folder (for example, at webapp root), the module MUST be * specified (using a single <module> in configuration or by setting -Dgwt.module=..) and the * runTarget parameter can only contain the host page URI. *

* When the GWT module host page is part of the module "public" folder, the runTarget MAY define the full GWT module * path (com.myapp.gwt.Module/Module.html) that will be automatically converted according to the * rename-to directive into renamed/Module.html. */ @Parameter(property = "runTarget", required = true) private String runTarget; /** * Forked process execution timeOut (in seconds). Primary used for integration-testing. */ @Parameter @SuppressWarnings("unused") private int runTimeOut; /** * Runs the embedded GWT server on the specified port. */ @Parameter(defaultValue = "8888", property = "gwt.port") private int port; /** * Runs the code server on the specified port. */ @Parameter(defaultValue = "9997", property = "gwt.codeServerPort") private int codeServerPort; /** * Location of the compiled classes. */ @Parameter(defaultValue = "${project.build.outputDirectory}", required = true, readonly = true) private File buildOutputDirectory; /** * Prevents the embedded GWT Tomcat server from running (even if a port is specified). *

* Can be set from command line using '-Dgwt.noserver=...' */ @Parameter(defaultValue = "false", property = "gwt.noserver") private boolean noServer; /** * Specifies a different embedded web server to run (must implement ServletContainerLauncher) */ @Parameter(property = "gwt.server") private String server; /** * List of System properties to pass when running the hosted mode. * * @since 1.2 */ @Parameter private Map systemProperties; /** * Copies the contents of warSourceDirectory to hostedWebapp. *

* Can be set from command line using '-Dgwt.copyWebapp=...' *

* * @since 2.1.0-1 */ @Parameter(defaultValue = "false", property = "gwt.copyWebapp") private boolean copyWebapp; /** * set the appengine sdk to use *

* Artifact will be downloaded with groupId : {@link #appEngineGroupId} * and artifactId {@link #appEngineArtifactId} *

* * @since 2.1.0-1 */ @Parameter(defaultValue = "1.3.8", property = "gwt.appEngineVersion") private String appEngineVersion; /** *

* List of {@link Pattern} jars to exclude from the classPath when running * dev mode *

* * @since 2.1.0-1 */ @Parameter private List runClasspathExcludes; /** *

* Location to find appengine sdk or to unzip downloaded one see {@link #appEngineVersion} *

* * @since 2.1.0-1 */ @Parameter(defaultValue = "${project.build.directory}/appengine-sdk/", property = "gwt.appEngineHome") private File appEngineHome; /** * groupId to download appengine sdk from maven repo * * @since 2.1.0-1 */ @Parameter(defaultValue = "com.google.appengine", property = "gwt.appEngineGroupId") private String appEngineGroupId; /** * groupId to download appengine sdk from maven repo * * @since 2.1.0-1 */ @Parameter(defaultValue = "appengine-java-sdk", property = "gwt.appEngineArtifactId") private String appEngineArtifactId; /** * To look up Archiver/UnArchiver implementations * @since 2.1.0-1 */ @Component protected ArchiverManager archiverManager; /** * Set GWT shell bindAddress. *

* Can be set from command line using '-Dgwt.bindAddress=...' * @since 2.1.0-1 */ @Parameter(property = "gwt.bindAddress") private String bindAddress; /** * EXPERIMENTAL: Cache results of generators with stable output. * * @since 2.6.0-rc1 */ @Parameter(defaultValue = "true", property = "gwt.cacheGeneratorResults") private boolean cacheGeneratorResults; /** * The compiler's working directory for internal use (must be writeable; defaults to a system temp dir) * * @since 2.6.0-rc1 */ @Parameter private File workDir; /** * Logs to a file in the given directory, as well as graphically * * @since 2.6.0-rc1 */ @Parameter private File logDir; /** * Specifies Java source level. *

* The default value depends on the JVM used to launch Maven. * * @since 2.6.0-rc1 */ @Parameter(defaultValue = "auto", property = "maven.compiler.source") private String sourceLevel; /** * Runs Super Dev Mode instead of classic Development Mode. * * @since 2.7.0-rc1 */ @Parameter(defaultValue = "true", property = "gwt.superDevMode") private boolean superDevMode; /** * Compiles faster by reusing data from the previous compile. * * @since 2.7.0-rc1 */ @Parameter(alias = "compilePerFile", defaultValue = "true", property = "gwt.compiler.incremental") private boolean incremental; /** * Generate exports for JsInterop purposes. * * @since 2.8.0-rc1 */ @Parameter(alias = "generateJsInteropExports", defaultValue = "false", property = "gwt.compiler.generateJsInteropExports") private boolean generateJsInteropExports; /** * EXPERIMENTAL: Emit extra information allow chrome dev tools to display Java identifiers in many places instead of JavaScript functions. *

* Value can be one of NONE, ONLY_METHOD_NAME, ABBREVIATED or FULL. * * @since 2.7.0-rc1 */ @Parameter(defaultValue = "NONE", property = "gwt.compiler.methodNameDisplayMode") private String methodNameDisplayMode; /** * @return the startup URL to open in hosted browser (gwt 1.6+) */ public String getStartupUrl() throws MojoExecutionException { if ( noServer ) { return runTarget; } int dash = runTarget.indexOf( '/' ); if ( dash > 0 ) { String prefix = runTarget.substring( 0, dash ); // runTarget includes the GWT module full path. // Lets retrieve the GWT module and apply the rename-to directive String[] modules = getModules(); for ( String module : modules ) { if ( prefix.equals( module ) ) { try { return readModule( module ).getPath() + '/' + runTarget.substring( dash + 1 ); } catch ( GwtModuleReaderException e ) { throw new MojoExecutionException( e.getMessage(), e ); } } } } return runTarget; } public void doExecute( ) throws MojoExecutionException, MojoFailureException { JavaCommand cmd = createJavaCommand() .setMainClass( "com.google.gwt.dev.DevMode" ); if ( gwtSdkFirstInClasspath ) { cmd.addToClasspath( getGwtUserJar() ) .addToClasspath( getGwtDevJar() ); } cmd.addToClasspath( getClasspath( Artifact.SCOPE_RUNTIME ) ); addCompileSourceArtifacts( cmd ); addArgumentDeploy(cmd); addArgumentGen( cmd ); addPersistentUnitCache(cmd); if ( !gwtSdkFirstInClasspath ) { cmd.addToClasspath( getGwtUserJar() ) .addToClasspath( getGwtDevJar() ); } cmd.arg( "-war", hostedWebapp.getAbsolutePath() ) .arg( "-logLevel", getLogLevel() ) .arg( "-port", Integer.toString( getPort() ) ) .arg( "-codeServerPort" , Integer.toString( codeServerPort )) .arg( "-startupUrl", getStartupUrl() ) .arg( noServer, "-nostartServer" ) .arg( !cacheGeneratorResults, "-XnocacheGeneratorResults" ) .arg( !superDevMode, "-nosuperDevMode" ) .arg( !incremental, "-noincremental" ) .arg( generateJsInteropExports, "-generateJsInteropExports" ) .arg( "-sourceLevel", sourceLevel ); if ( style != null && style.length() > 0 ) { cmd.arg( "-style", style ); } if ( methodNameDisplayMode != null && methodNameDisplayMode.length() > 0 && !methodNameDisplayMode.equals( "NONE" )) { cmd.arg( "-XmethodNameDisplayMode", methodNameDisplayMode ); } if ( workDir != null ) { cmd.arg( "-workDir", workDir.getAbsolutePath() ); } if ( logDir != null ) { cmd.arg( "-logdir", logDir.getAbsolutePath() ); } if ( server != null ) { cmd.arg( "-server", server ); } if ( systemProperties != null && !systemProperties.isEmpty() ) { for ( String key : systemProperties.keySet() ) { String value = systemProperties.get( key ); if ( value != null ) { getLog().debug( " " + key + "=" + value ); cmd.systemProperty( key, value ); } else { getLog().debug( "skip sysProps " + key + " with empty value" ); } } } if ( bindAddress != null && bindAddress.length() > 0 ) { cmd.arg( "-bindAddress" ).arg( bindAddress ); } if ( modulePathPrefix != null && !modulePathPrefix.isEmpty() ) { cmd.arg( "-modulePathPrefix" ).arg( modulePathPrefix ); } if ( !noServer ) { setupExplodedWar(); } else { getLog().info( "noServer is set! Skipping exploding war file..." ); } for ( String module : getModules() ) { cmd.arg( module ); } try { cmd.execute(); } catch ( JavaCommandException e ) { throw new MojoExecutionException( e.getMessage(), e ); } } @Override protected void postProcessClassPath( Collection classPath ) { boolean isAppEngine = "com.google.appengine.tools.development.gwt.AppEngineLauncher".equals( server ); List patternsToExclude = new ArrayList(); if ( runClasspathExcludes != null && !runClasspathExcludes.isEmpty() ) { for ( String runClasspathExclude : runClasspathExcludes ) { patternsToExclude.add( Pattern.compile( runClasspathExclude ) ); } } Iterator it = classPath.iterator(); while ( it.hasNext() ) { String name = it.next().getName(); if ( !patternsToExclude.isEmpty() ) { for ( Pattern pattern : patternsToExclude ) { if ( pattern.matcher( name ).find() ) { getLog().info( "remove jar " + name + " from system classpath" ); it.remove(); continue; } } } } // TODO refactor this a little if ( isAppEngine ) { File appEngineToolsApi = new File( appEngineHome, "/lib/appengine-tools-api.jar" ); File appEngineLocalRuntime = new File( appEngineHome, "/lib/impl/appengine-local-runtime.jar" ); File appEngineAgent = new File( appEngineHome, "/lib/agent/appengine-agent.jar" ); if ( appEngineHome.exists() && appEngineToolsApi.exists() && appEngineLocalRuntime.exists() && appEngineAgent.exists() ) { classPath.add( appEngineToolsApi ); classPath.add( appEngineLocalRuntime ); classPath.add( appEngineAgent ); } else { try { if ( !appEngineHome.exists() ) { appEngineHome.mkdirs(); // force addition of appengine SDK in a exploded SDK repository location Artifact appEngineSdk = resolve( appEngineGroupId, appEngineArtifactId, appEngineVersion, "zip", "" ); // sdk extraction UnArchiver unArchiver = archiverManager.getUnArchiver( appEngineSdk.getFile() ); unArchiver.setSourceFile( appEngineSdk.getFile() ); unArchiver.setDestDirectory( appEngineHome ); getLog().info( "extract appengine " + appEngineVersion + " sdk to " + appEngineHome.getPath() ); unArchiver.extract(); } else { getLog().info( "use existing appengine sdk from " + appEngineHome.getPath() ); } appEngineToolsApi = new File( appEngineHome, "appengine-java-sdk-" + appEngineVersion + "/lib/appengine-tools-api.jar" ); if ( !appEngineToolsApi.exists() ) { throw new RuntimeException( appEngineToolsApi.getPath() + " not exists" ); } classPath.add( appEngineToolsApi ); getLog().debug( "add " + appEngineToolsApi.getPath() + " to the classpath" ); appEngineLocalRuntime = new File( appEngineHome, "appengine-java-sdk-" + appEngineVersion + "/lib/impl/appengine-local-runtime.jar" ); if ( !appEngineLocalRuntime.exists() ) { throw new RuntimeException( appEngineLocalRuntime.getPath() + " not exists" ); } classPath.add( appEngineLocalRuntime ); getLog().debug( "add " + appEngineLocalRuntime.getPath() + " to the classpath" ); appEngineAgent = new File( appEngineHome, "appengine-java-sdk-" + appEngineVersion + "/lib/agent/appengine-agent.jar" ); classPath.add( appEngineAgent ); getLog().debug( "add " + appEngineAgent.getPath() + " to the classpath" ); } catch ( MojoExecutionException e ) { // FIXME add throws MojoExecutionException in postProcessClassPath throw new RuntimeException( e.getMessage(), e ); } catch ( ArchiverException e ) { // FIXME add throws MojoExecutionException in postProcessClassPath throw new RuntimeException( e.getMessage(), e ); } catch ( NoSuchArchiverException e ) { // FIXME add throws MojoExecutionException in postProcessClassPath throw new RuntimeException( e.getMessage(), e ); } } } } /** * Copied a directory structure with deafault exclusions (.svn, CVS, etc) * * @param sourceDir The source directory to copy, must not be null. * @param destDir The target directory to copy to, must not be null. * @throws java.io.IOException If the directory structure could not be copied. */ private void copyDirectoryStructureIfModified(File sourceDir, File destDir) throws IOException { DirectoryScanner scanner = new DirectoryScanner(); scanner.setBasedir( sourceDir ); scanner.addDefaultExcludes(); scanner.scan(); /* * NOTE: Make sure the destination directory is always there (even if empty) to support POM-less ITs. */ destDir.mkdirs(); String[] includedDirs = scanner.getIncludedDirectories(); for ( int i = 0; i < includedDirs.length; ++i ) { File clonedDir = new File( destDir, includedDirs[i] ); clonedDir.mkdirs(); } String[] includedFiles = scanner.getIncludedFiles(); for ( int i = 0; i < includedFiles.length; ++i ) { File sourceFile = new File(sourceDir, includedFiles[i]); File destFile = new File(destDir, includedFiles[i]); FileUtils.copyFileIfModified(sourceFile, destFile); } } private void setupExplodedWar() throws MojoExecutionException { getLog().info( "create exploded Jetty webapp in " + hostedWebapp ); if ( copyWebapp && !warSourceDirectory.getAbsolutePath().equals( hostedWebapp.getAbsolutePath() ) ) { try { // can't use FileUtils.copyDirectoryStructureIfModified because it does not // excludes the DEFAULTEXCLUDES copyDirectoryStructureIfModified(warSourceDirectory, hostedWebapp); } catch ( IOException e ) { throw new MojoExecutionException( "Failed to copy warSourceDirectory to " + hostedWebapp, e ); } } File classes = new File( hostedWebapp, "WEB-INF/classes" ); classes.mkdirs(); if ( !buildOutputDirectory.getAbsolutePath().equals( classes.getAbsolutePath() ) ) { getLog().warn( "Your POM does not match your " + "hosted webapp WEB-INF/classes folder for GWT Hosted browser to see your classes." ); try { FileUtils.copyDirectoryStructure( buildOutputDirectory, classes ); } catch ( IOException e ) { throw new MojoExecutionException( "Failed to copy classes to " + classes , e ); } } File lib = new File( hostedWebapp, "WEB-INF/lib" ); lib.mkdirs(); Collection artifacts = getProjectRuntimeArtifacts(); for ( Artifact artifact : artifacts ) { try { // Using m2eclipse with "resolve workspace dependencies" the artifact is the buildOutputDirectory if ( ! artifact.getFile().isDirectory() ) { FileUtils.copyFileToDirectory( artifact.getFile(), lib ); } } catch ( IOException e ) { throw new MojoExecutionException( "Failed to copy runtime dependency " + artifact, e ); } } } public int getPort() { return this.port; } /** * @param runTimeOut the runTimeOut to set */ public void setRunTimeOut( int runTimeOut ) { setTimeOut( runTimeOut ); } public void setExecutedProject( MavenProject executedProject ) { this.executedProject = executedProject; } @Override public MavenProject getProject() { return executedProject; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy