-
Notifications
You must be signed in to change notification settings - Fork 395
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add processExecutors for the new Builder version lib
- Loading branch information
Showing
4 changed files
with
285 additions
and
13 deletions.
There are no files selected for viewing
191 changes: 191 additions & 0 deletions
191
src/main/java/com/jayway/maven/plugins/android/DefaultJavaProcessExecutor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,191 @@ | ||
/* | ||
* Copyright (C) 2014 The Android Open Source Project | ||
* | ||
* Licensed 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. | ||
*/ | ||
package com.jayway.maven.plugins.android; | ||
|
||
import com.android.annotations.NonNull; | ||
import com.android.ide.common.process.JavaProcessExecutor; | ||
import com.android.ide.common.process.JavaProcessInfo; | ||
import com.android.ide.common.process.ProcessException; | ||
import com.android.ide.common.process.ProcessOutput; | ||
import com.android.ide.common.process.ProcessOutputHandler; | ||
import com.android.ide.common.process.ProcessResult; | ||
import com.android.utils.ILogger; | ||
import com.google.common.base.Joiner; | ||
import com.google.common.collect.Lists; | ||
import com.google.common.io.ByteStreams; | ||
import com.google.common.io.Closeables; | ||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.io.OutputStream; | ||
import java.util.List; | ||
import java.util.Map; | ||
/** | ||
* Simple implementation of ProcessExecutor, using the standard Java Process(Builder) API. | ||
*/ | ||
public class DefaultJavaProcessExecutor implements JavaProcessExecutor | ||
{ | ||
private final ILogger mLogger; | ||
public DefaultJavaProcessExecutor( ILogger logger ) | ||
{ | ||
mLogger = logger; | ||
} | ||
@NonNull | ||
@Override | ||
public ProcessResult execute( | ||
@NonNull JavaProcessInfo processInfo, | ||
@NonNull ProcessOutputHandler processOutputHandler ) | ||
{ | ||
List<String> command = Lists.newArrayList(); | ||
command.add( processInfo.getExecutable() ); | ||
command.addAll( processInfo.getArgs() ); | ||
String commandString = Joiner.on( ' ' ).join( command ); | ||
mLogger.info( "command: " + commandString ); | ||
try | ||
{ | ||
// launch the command line process | ||
ProcessBuilder processBuilder = new ProcessBuilder( command ); | ||
Map<String, Object> envVariableMap = processInfo.getEnvironment(); | ||
if ( !envVariableMap.isEmpty() ) | ||
{ | ||
Map<String, String> env = processBuilder.environment(); | ||
for ( Map.Entry<String, Object> entry : envVariableMap.entrySet() ) | ||
{ | ||
env.put( entry.getKey(), entry.getValue().toString() ); | ||
} | ||
} | ||
// start the process | ||
Process process = processBuilder.start(); | ||
// and grab the output, and the exit code | ||
ProcessOutput output = processOutputHandler.createOutput(); | ||
int exitCode = grabProcessOutput( process, output ); | ||
processOutputHandler.handleOutput( output ); | ||
return new ProcessResultImplCopy( commandString, exitCode ); | ||
} | ||
catch ( IOException e ) | ||
{ | ||
return new ProcessResultImplCopy( commandString, e ); | ||
} | ||
catch ( InterruptedException e ) | ||
{ | ||
// Restore the interrupted status | ||
Thread.currentThread().interrupt(); | ||
return new ProcessResultImplCopy( commandString, e ); | ||
} | ||
catch ( ProcessException e ) | ||
{ | ||
return new ProcessResultImplCopy( commandString, e ); | ||
} | ||
} | ||
/** | ||
* Get the stderr/stdout outputs of a process and return when the process is done. | ||
* Both <b>must</b> be read or the process will block on windows. | ||
* | ||
* @param process The process to get the output from. | ||
* @param output The processOutput containing where to send the output. | ||
* Note that on Windows capturing the output is not optional. If output is null | ||
* the stdout/stderr will be captured and discarded. | ||
* @return the process return code. | ||
* @throws InterruptedException if {@link Process#waitFor()} was interrupted. | ||
*/ | ||
private static int grabProcessOutput( | ||
@NonNull final Process process, | ||
@NonNull final ProcessOutput output ) throws InterruptedException | ||
{ | ||
Thread threadErr = new Thread( "stderr" ) | ||
{ | ||
@Override | ||
public void run() | ||
{ | ||
InputStream stderr = process.getErrorStream(); | ||
OutputStream stream = output.getErrorOutput(); | ||
try | ||
{ | ||
ByteStreams.copy( stderr, stream ); | ||
stream.flush(); | ||
} | ||
catch ( IOException e ) | ||
{ | ||
// ignore? | ||
} | ||
finally | ||
{ | ||
try | ||
{ | ||
Closeables.close( stderr, true /* swallowIOException */ ); | ||
} | ||
catch ( IOException e ) | ||
{ | ||
// cannot happen | ||
} | ||
try | ||
{ | ||
Closeables.close( stream, true /* swallowIOException */ ); | ||
} | ||
catch ( IOException e ) | ||
{ | ||
// cannot happen | ||
} | ||
} | ||
} | ||
}; | ||
Thread threadOut = new Thread( "stdout" ) | ||
{ | ||
@Override | ||
public void run() | ||
{ | ||
InputStream stdout = process.getInputStream(); | ||
OutputStream stream = output.getStandardOutput(); | ||
try | ||
{ | ||
ByteStreams.copy( stdout, stream ); | ||
stream.flush(); | ||
} | ||
catch ( IOException e ) | ||
{ | ||
// ignore? | ||
} | ||
finally | ||
{ | ||
try | ||
{ | ||
Closeables.close( stdout, true /* swallowIOException */ ); | ||
} | ||
catch ( IOException e ) | ||
{ | ||
// cannot happen | ||
} | ||
try | ||
{ | ||
Closeables.close( stream, true /* swallowIOException */ ); | ||
} | ||
catch ( IOException e ) | ||
{ | ||
// cannot happen | ||
} | ||
} | ||
} | ||
}; | ||
threadErr.start(); | ||
threadOut.start(); | ||
// it looks like on windows process#waitFor() can return | ||
// before the thread have filled the arrays, so we wait for both threads and the | ||
// process itself. | ||
threadErr.join(); | ||
threadOut.join(); | ||
// get the return code from the process | ||
return process.waitFor(); | ||
} | ||
} |
67 changes: 67 additions & 0 deletions
67
src/main/java/com/jayway/maven/plugins/android/ProcessResultImplCopy.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
/* | ||
* Copyright (C) 2014 The Android Open Source Project | ||
* | ||
* Licensed 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. | ||
*/ | ||
package com.jayway.maven.plugins.android; | ||
|
||
import com.android.ide.common.process.ProcessException; | ||
import com.android.ide.common.process.ProcessResult; | ||
|
||
/** | ||
* Internal implementation of ProcessResult used by DefaultProcessExecutor. | ||
*/ | ||
class ProcessResultImplCopy implements ProcessResult | ||
{ | ||
private final String mCommand; | ||
private final int mExitValue; | ||
private final Exception mFailure; | ||
ProcessResultImplCopy( String command, int exitValue ) | ||
{ | ||
this( command, exitValue, null ); | ||
} | ||
ProcessResultImplCopy( String command, Exception failure ) | ||
{ | ||
this( command, -1, failure ); | ||
} | ||
ProcessResultImplCopy( String command, int exitValue, Exception failure ) | ||
{ | ||
mCommand = command; | ||
mExitValue = exitValue; | ||
mFailure = failure; | ||
} | ||
@Override | ||
public ProcessResult assertNormalExitValue() throws ProcessException | ||
{ | ||
if ( mExitValue != 0 ) | ||
{ | ||
throw new ProcessException( | ||
String.format( "Return code %d for process '%s'", mExitValue, mCommand ) ); | ||
} | ||
return this; | ||
} | ||
@Override | ||
public int getExitValue() | ||
{ | ||
return mExitValue; | ||
} | ||
@Override | ||
public ProcessResult rethrowFailure() throws ProcessException | ||
{ | ||
if ( mFailure != null ) | ||
{ | ||
throw new ProcessException( "", mFailure ); | ||
} | ||
return this; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters