diff --git a/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/DefaultJnlpDependencyRequestBuilder.java b/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/DefaultJnlpDependencyRequestBuilder.java index a4a4fbe9..90406787 100644 --- a/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/DefaultJnlpDependencyRequestBuilder.java +++ b/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/DefaultJnlpDependencyRequestBuilder.java @@ -69,6 +69,14 @@ public void init( JnlpDependencyGlobalConfig globalConfig ) this.globalConfig = globalConfig; } + /** + * {@inheritDoc} + */ + public JnlpDependencyRequests createRequests() + { + return new JnlpDependencyRequests( globalConfig ); + } + /** * {@inheritDoc} */ diff --git a/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/DefaultJnlpDependencyRequestConsumer.java b/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/DefaultJnlpDependencyRequestConsumer.java index 4f7a43b6..e3772901 100644 --- a/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/DefaultJnlpDependencyRequestConsumer.java +++ b/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/DefaultJnlpDependencyRequestConsumer.java @@ -19,17 +19,18 @@ * under the License. */ -import org.apache.maven.artifact.Artifact; -import org.apache.maven.plugin.MojoExecutionException; import org.codehaus.mojo.webstart.dependency.task.JnlpDependencyTask; -import org.codehaus.mojo.webstart.dependency.task.JnlpDependencyTaskException; import org.codehaus.mojo.webstart.util.IOUtil; import org.codehaus.plexus.component.annotations.Component; import org.codehaus.plexus.component.annotations.Requirement; import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.logging.Logger; import java.io.File; import java.util.List; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; /** * Created on 1/4/14. @@ -46,157 +47,194 @@ public class DefaultJnlpDependencyRequestConsumer @Requirement private IOUtil ioUtil; - private int maxThreads; - - private boolean failFast; - /** * {@inheritDoc} */ - public void setMaxThreads( int maxThreads ) + public JnlpDependencyResults execute( JnlpDependencyRequestConsumerConfig config, JnlpDependencyRequests requests ) { - this.maxThreads = maxThreads; - } - /** - * {@inheritDoc} - */ - public void setFailFast( boolean failFast ) - { - this.failFast = failFast; + getLogger().info( "Process " + requests.getNbRequests() + " dependencies." ); + + RequestExecutor executor = new RequestExecutor( getLogger(), ioUtil, config ); + + executor.registerRequests( requests.getRequests() ); + + JnlpDependencyResults results = executor.terminatesAndWaits(); + + return results; } - /** - * {@inheritDoc} - */ - public JnlpDependencyResults execute( JnlpDependencyRequests requests ) + private static class RequestExecutor + extends ThreadPoolExecutor { - List dependencyRequests = requests.getRequests(); + private final JnlpDependencyRequestConsumerConfig config; + + private final Logger logger; - getLogger().info( "Process " + dependencyRequests.size() + " requests." ); + private final IOUtil ioUtil; - JnlpDependencyResults results = new JnlpDependencyResults(); + private final JnlpDependencyResults results; - for ( JnlpDependencyRequest request : dependencyRequests ) + public RequestExecutor( Logger logger, IOUtil ioUtil, JnlpDependencyRequestConsumerConfig config ) { - JnlpDependencyResult result = execute( request ); - results.registerResult( request, result ); - if ( failFast && result.isError() ) - { - getLogger().warn( "Fail fast after first dependency processing error." ); - break; - } + super( config.getMaxThreads(), config.getMaxThreads(), 1L, TimeUnit.SECONDS, + new LinkedBlockingQueue() ); + this.logger = logger; + this.ioUtil = ioUtil; + this.config = config; + this.results = new JnlpDependencyResults(); } - return results; - } - protected JnlpDependencyResult execute( JnlpDependencyRequest request ) - { - JnlpDependencyConfig config = request.getConfig(); + @Override + protected void afterExecute( Runnable r, Throwable t ) + { + super.afterExecute( r, t ); + RequestTask task = (RequestTask) r; - JnlpDependencyResult result = prepareResult( config ); + JnlpDependencyResult result = task.result; - File workingDirectory = config.getWorkingDirectory(); + results.registerResult( task.request, result ); - File workingFile = result.getOriginalfile(); + boolean withError = t != null; - JnlpDependencyTask[] tasks = request.getTasks(); + if ( withError ) + { + result.setError( t ); - for ( int i = 0, length = tasks.length; i < length; i++ ) - { + if ( config.isFailFast() ) + { + logger.warn( "Fail fast after first dependency processing error." ); - JnlpDependencyTask task = tasks[i]; + //TODO Stop the executor + shutdownNow(); + } + } + + + } + + /** + * Ask the thread to stop. + *

+ * It will finish all incoming files (but will not accept more files to + * parse) + *

+ * Note: The method does not return until all files are not consumed. + */ + public JnlpDependencyResults terminatesAndWaits() + { + // ask executor to terminate + shutdown(); - // copy previous file to a new task isolated directory - File newDirectory = new File( workingDirectory, i + "_" + task.getClass().getSimpleName() ); try { - ioUtil.copyFileToDirectoryIfNecessary( workingFile, newDirectory ); + // wait until all submited jobs are terminated + // i don't want timeout, i think 2 days is good :) + awaitTermination( 2 * 60 * 60 * 24, TimeUnit.SECONDS ); } - catch ( MojoExecutionException e ) + catch ( InterruptedException e ) { - result.setError( e ); - break; + logger.error( "Could not stop the executor after two days...", e ); } - workingFile = new File( newDirectory, workingFile.getName() ); - getLogger().debug( String.format( "[task %s] (%s): workingFile: %s", i, task, workingFile ) ); - try - { - workingFile = task.execute( config, workingFile ); - } - catch ( JnlpDependencyTaskException e ) + return results; + } + + public void registerRequests( List dependencyRequests ) + { + + for ( JnlpDependencyRequest dependencyRequest : dependencyRequests ) { - result.setError( e ); - break; + RequestTask newtask = new RequestTask( logger, ioUtil, dependencyRequest ); + + JnlpDependencyResult result = newtask.result; + if ( result.isUptodate() ) + { + if ( config.isVerbose() ) + { + logger.info( + "Skip up-to-date dependency: " + dependencyRequest.getConfig().getArtifact().getId() ); + } + results.registerResult( newtask.request, result ); + } + else + { + if ( config.isVerbose() ) + { + logger.info( "Process dependency: " + dependencyRequest.getConfig().getArtifact().getId() ); + } + execute( newtask ); + } } } + } - // copy to final destination - finalizeResult( config, workingFile, result ); + private static class RequestTask + implements Runnable + { - getLogger().info( "Dependency " + config.getArtifact().getId() + " treated." ); + private final Logger logger; - return result; - } + private final IOUtil ioUtil; - private JnlpDependencyResult prepareResult( JnlpDependencyConfig config ) - { + private final JnlpDependencyRequest request; - File workingDirectory = config.getWorkingDirectory(); + private JnlpDependencyResult result; - Artifact artifact = config.getArtifact(); + private RequestTask( Logger logger, IOUtil ioUtil, JnlpDependencyRequest request ) + { + this.logger = logger; + this.ioUtil = ioUtil; + this.request = request; + this.result = new JnlpDependencyResult( request ); + } - File incomingFile = artifact.getFile(); + /** + * {@inheritDoc} + */ + public void run() + { + JnlpDependencyConfig config = request.getConfig(); - String fileName = config.getDependencyFilenameStrategy().getDependencyFilename( artifact, false ); + File workingFile = request.getOriginalFile(); - File workingFile = new File( workingDirectory, fileName ); + try + { + // copy artifact file to original file + ioUtil.copyFile( config.getArtifact().getFile(), workingFile ); - JnlpDependencyResult result = new JnlpDependencyResult( artifact, workingFile ); + File workingDirectory = config.getWorkingDirectory(); - copyFile( incomingFile, workingFile, result ); - return result; - } + JnlpDependencyTask[] tasks = request.getTasks(); - private void finalizeResult( JnlpDependencyConfig config, File workingFile, JnlpDependencyResult result ) - { + for ( int i = 0, length = tasks.length; i < length; i++ ) + { - // copy to final destination + JnlpDependencyTask task = tasks[i]; - File finalDirectory = config.getFinalDirectory(); - String filename = config.getDependencyFilenameStrategy().getDependencyFilename( config.getArtifact(), - config.isOutputJarVersion() ); + // copy previous file to a new task isolated directory + File newDirectory = new File( workingDirectory, i + "_" + task.getClass().getSimpleName() ); + ioUtil.copyFileToDirectoryIfNecessary( workingFile, newDirectory ); - if ( config.isPack200() ) - { - filename += ".pack"; - } + workingFile = new File( newDirectory, workingFile.getName() ); - if ( config.isGzip() ) - { - filename += ".gz"; - } + logger.debug( String.format( "[task %s] (%s): workingFile: %s", i, task, workingFile ) ); - File finalFile = new File( finalDirectory, filename ); + workingFile = task.execute( config, workingFile ); + } - copyFile( workingFile, finalFile, result ); - result.setFinalFile( finalFile ); - } + // copy to final destination + ioUtil.copyFile( workingFile, request.getFinalFile() ); + } + catch ( Exception e ) + { + result.setError( e ); + } - private void copyFile( File source, File destination, JnlpDependencyResult result ) - { - getLogger().debug( "Copy " + source.getName() + " to " + destination ); - try - { - ioUtil.copyFile( source, destination ); - } - catch ( MojoExecutionException e ) - { - result.setError( e ); + logger.info( "Dependency " + config.getArtifact().getId() + " treated." ); } } } diff --git a/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/JnlpDependencyRequest.java b/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/JnlpDependencyRequest.java index 22c729d7..f1079e52 100644 --- a/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/JnlpDependencyRequest.java +++ b/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/JnlpDependencyRequest.java @@ -19,8 +19,11 @@ * under the License. */ +import org.apache.maven.artifact.Artifact; import org.codehaus.mojo.webstart.dependency.task.JnlpDependencyTask; +import java.io.File; + /** * Created on 1/4/14. * @@ -34,10 +37,25 @@ public class JnlpDependencyRequest private final JnlpDependencyTask[] tasks; + private final File originalFile; + + private final File finalFile; + + private final boolean uptodate; + public JnlpDependencyRequest( JnlpDependencyConfig config, JnlpDependencyTask... tasks ) { this.config = config; this.tasks = tasks; + + originalFile = buildOriginalFile(); + finalFile = buildFinalFile(); + + File incomingFile = getConfig().getArtifact().getFile(); + + long limitDate = incomingFile.lastModified(); + uptodate = originalFile.exists() && originalFile.lastModified() > limitDate && + finalFile.exists() && finalFile.lastModified() > limitDate; } public JnlpDependencyConfig getConfig() @@ -49,4 +67,50 @@ public JnlpDependencyTask[] getTasks() { return tasks; } + + public File getOriginalFile() + { + return originalFile; + } + + public boolean isUptodate() + { + return uptodate; + } + + public File getFinalFile() + { + return finalFile; + } + + private File buildOriginalFile() + { + + File workingDirectory = config.getWorkingDirectory(); + + Artifact artifact = config.getArtifact(); + + String fileName = config.getDependencyFilenameStrategy().getDependencyFilename( artifact, false ); + + return new File( workingDirectory, fileName ); + } + + private File buildFinalFile() + { + + File finalDirectory = config.getFinalDirectory(); + String filename = config.getDependencyFilenameStrategy().getDependencyFilename( config.getArtifact(), + config.isOutputJarVersion() ); + if ( config.isPack200() ) + { + filename += ".pack"; + } + + if ( config.isGzip() ) + { + filename += ".gz"; + } + + return new File( finalDirectory, filename ); + } } diff --git a/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/JnlpDependencyRequestBuilder.java b/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/JnlpDependencyRequestBuilder.java index 9ba7fdbb..362f159a 100644 --- a/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/JnlpDependencyRequestBuilder.java +++ b/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/JnlpDependencyRequestBuilder.java @@ -33,5 +33,7 @@ public interface JnlpDependencyRequestBuilder void init( JnlpDependencyGlobalConfig config ); + JnlpDependencyRequests createRequests(); + JnlpDependencyRequest createRequest( Artifact artifact, boolean outputJarVersion ); } diff --git a/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/JnlpDependencyRequestConsumer.java b/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/JnlpDependencyRequestConsumer.java index bbe45bac..637c5fac 100644 --- a/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/JnlpDependencyRequestConsumer.java +++ b/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/JnlpDependencyRequestConsumer.java @@ -30,9 +30,5 @@ public interface JnlpDependencyRequestConsumer String ROLE = JnlpDependencyRequestConsumer.class.getName(); - void setMaxThreads( int maxThreads ); - - void setFailFast( boolean failFast ); - - JnlpDependencyResults execute( JnlpDependencyRequests requests ); + JnlpDependencyResults execute( JnlpDependencyRequestConsumerConfig config, JnlpDependencyRequests requests ); } diff --git a/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/JnlpDependencyRequestConsumerConfig.java b/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/JnlpDependencyRequestConsumerConfig.java new file mode 100644 index 00000000..19d6cde1 --- /dev/null +++ b/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/JnlpDependencyRequestConsumerConfig.java @@ -0,0 +1,66 @@ +package org.codehaus.mojo.webstart.dependency; + +/* + * 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. + */ + +/** + * Created on 1/7/14. + * + * @author Tony Chemit + * @since 1.0-beta-5 + */ +public class JnlpDependencyRequestConsumerConfig +{ + + private boolean verbose; + + private int maxThreads; + + private boolean failFast; + + public int getMaxThreads() + { + return maxThreads; + } + + public void setMaxThreads( int maxThreads ) + { + this.maxThreads = maxThreads; + } + + public boolean isFailFast() + { + return failFast; + } + + public void setFailFast( boolean failFast ) + { + this.failFast = failFast; + } + + public boolean isVerbose() + { + return verbose; + } + + public void setVerbose( boolean verbose ) + { + this.verbose = verbose; + } +} diff --git a/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/JnlpDependencyRequests.java b/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/JnlpDependencyRequests.java index 63e0484d..071d3a61 100644 --- a/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/JnlpDependencyRequests.java +++ b/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/JnlpDependencyRequests.java @@ -32,29 +32,22 @@ public class JnlpDependencyRequests { - /** - * Max number of threads to use for parallelism execution. - */ - private int maxThreads = 20; - /** * Registred requests. */ private final List requests; - public JnlpDependencyRequests() - { - requests = new ArrayList(); - } + private final JnlpDependencyGlobalConfig config; - public int getMaxThreads() + public JnlpDependencyRequests( JnlpDependencyGlobalConfig config ) { - return maxThreads; + this.config = config; + requests = new ArrayList(); } - public void setMaxThreads( int maxThreads ) + public JnlpDependencyGlobalConfig getConfig() { - this.maxThreads = maxThreads; + return config; } public void addRequest( JnlpDependencyRequest request ) @@ -66,4 +59,9 @@ public List getRequests() { return Collections.unmodifiableList( requests ); } + + public int getNbRequests() + { + return requests.size(); + } } diff --git a/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/JnlpDependencyResult.java b/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/JnlpDependencyResult.java index 7c03f3ec..cb483bde 100644 --- a/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/JnlpDependencyResult.java +++ b/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/JnlpDependencyResult.java @@ -31,46 +31,42 @@ */ public class JnlpDependencyResult { - private final Artifact artifact; - private final File originalfile; + private final JnlpDependencyRequest request; - private File finalFile; + private Throwable error; - private Exception error; - - public JnlpDependencyResult( Artifact artifact, File originalFile ) + public JnlpDependencyResult( JnlpDependencyRequest request ) { - this.artifact = artifact; - this.originalfile = originalFile; + this.request = request; } public Artifact getArtifact() { - return artifact; + return request.getConfig().getArtifact(); } - public File getOriginalfile() + public File getOriginalFile() { - return originalfile; + return request.getOriginalFile(); } public File getFinalFile() { - return finalFile; + return request.getFinalFile(); } - public Exception getError() + public boolean isUptodate() { - return error; + return request.isUptodate(); } - public void setFinalFile( File finalFile ) + public Throwable getError() { - this.finalFile = finalFile; + return error; } - public void setError( Exception error ) + public void setError( Throwable error ) { this.error = error; } diff --git a/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/JnlpDependencyResults.java b/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/JnlpDependencyResults.java index 44e2fb3b..edc76e4a 100644 --- a/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/JnlpDependencyResults.java +++ b/webstart-maven-plugin/src/main/java/org/codehaus/mojo/webstart/dependency/JnlpDependencyResults.java @@ -81,4 +81,30 @@ public JnlpDependencyResult[] getResultsWithError() } return resultWithErrors.toArray( new JnlpDependencyResult[resultWithErrors.size()] ); } + + public int getNbRequestsProcessed() + { + int result = 0; + for ( JnlpDependencyRequest request : results.keySet() ) + { + if ( !request.isUptodate() ) + { + result++; + } + } + return result; + } + + public int getNbRequestsUptodate() + { + int result = 0; + for ( JnlpDependencyRequest request : results.keySet() ) + { + if ( request.isUptodate() ) + { + result++; + } + } + return result; + } }