Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Simplified the I/O handling of Gradle tasks.

  • Loading branch information...
commit 6477d49b0a257cfcbe504c4f1a801c883f4e9ccd 1 parent af6b39b
@kelemen authored
View
121 src/org/netbeans/gradle/project/output/InputOutputManager.java
@@ -1,15 +1,22 @@
package org.netbeans.gradle.project.output;
import java.io.Closeable;
+import java.io.IOException;
+import java.io.Reader;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import org.openide.windows.IOProvider;
import org.openide.windows.InputOutput;
+import org.openide.windows.OutputWriter;
public final class InputOutputManager {
+ private static final Logger LOGGER = Logger.getLogger(InputOutputManager.class.getName());
+
private static final Lock MAIN_LOCK = new ReentrantLock();
private static final Map<String, Integer> USE_COUNTS = new HashMap<String, Integer>();
@@ -70,11 +77,16 @@ private static void decUseCount(String name) {
}
}
- public static class IORef implements Closeable {
+ public static final class IORef implements Closeable {
private final String name;
private final InputOutput io;
private final AtomicBoolean closed;
+ private final Lock ioLock;
+ private volatile OutputWriter out;
+ private volatile OutputWriter err;
+ private volatile Reader in;
+
private IORef(String name, InputOutput io) {
if (name == null) throw new NullPointerException("name");
if (io == null) throw new NullPointerException("io");
@@ -82,16 +94,121 @@ private IORef(String name, InputOutput io) {
this.name = name;
this.io = io;
this.closed = new AtomicBoolean(false);
+
+ this.ioLock = new ReentrantLock();
+ this.out = null;
+ this.err = null;
+ this.in = null;
+ }
+
+ private void checkNotClosed() {
+ if (closed.get()) {
+ throw new IllegalStateException();
+ }
}
public InputOutput getIo() {
return io;
}
+ public OutputWriter getOutRef() {
+ checkNotClosed();
+ OutputWriter result = out;
+ if (result == null) {
+ ioLock.lock();
+ try {
+ result = out;
+ if (result == null) {
+ result = io.getOut();
+ out = result;
+ }
+ } finally {
+ ioLock.unlock();
+ }
+ }
+ return result;
+ }
+
+ public OutputWriter getErrRef() {
+ checkNotClosed();
+ OutputWriter result = err;
+ if (result == null) {
+ ioLock.lock();
+ try {
+ result = err;
+ if (result == null) {
+ result = io.getErr();
+ err = result;
+ }
+ } finally {
+ ioLock.unlock();
+ }
+ }
+ return result;
+ }
+
+ public Reader getInRef() {
+ checkNotClosed();
+ Reader result = in;
+ if (result == null) {
+ ioLock.lock();
+ try {
+ result = in;
+ if (result == null) {
+ result = io.getIn();
+ in = result;
+ }
+ } finally {
+ ioLock.unlock();
+ }
+ }
+ return result;
+ }
+
+ private static void closeAll(Closeable... resources) throws IOException {
+ Throwable toThrow = null;
+ for (Closeable resource: resources) {
+ try {
+ if (resource != null) {
+ resource.close();
+ }
+ } catch (Throwable ex) {
+ if (toThrow == null) {
+ toThrow = ex;
+ }
+ else {
+ LOGGER.log(Level.INFO, "Suppressing exception", ex);
+ }
+ }
+ }
+
+ if (toThrow != null) {
+ if (toThrow instanceof IOException) {
+ throw (IOException)toThrow;
+ }
+ else if (toThrow instanceof Error) {
+ throw (Error)toThrow;
+ }
+ else if (toThrow instanceof RuntimeException) {
+ throw (RuntimeException)toThrow;
+ }
+ else {
+ throw new RuntimeException(toThrow);
+ }
+ }
+ }
+
@Override
- public void close() {
+ public void close() throws IOException {
if (closed.compareAndSet(false, true)) {
decUseCount(name);
+
+ ioLock.lock();
+ try {
+ closeAll(in, out, err);
+ } finally {
+ ioLock.unlock();
+ }
}
}
}
View
75 src/org/netbeans/gradle/project/tasks/GradleTasks.java
@@ -168,9 +168,7 @@ private static OutputRef configureOutput(
NbGradleProject project,
GradleTaskDef taskDef,
BuildLauncher buildLauncher,
- Reader buildIn,
- OutputWriter buildOutput,
- OutputWriter buildErrOutput) {
+ IORef buildIo) {
List<SmartOutputHandler.Consumer> consumers = new LinkedList<SmartOutputHandler.Consumer>();
consumers.add(new StackTraceConsumer(project));
@@ -186,17 +184,17 @@ private static OutputRef configureOutput(
errorConsumers.add(new FileLineConsumer());
Writer forwardedStdOut = new LineOutputWriter(new SmartOutputHandler(
- buildOutput,
+ buildIo.getOutRef(),
Arrays.asList(taskDef.getStdOutListener()),
outputConsumers));
Writer forwardedStdErr = new LineOutputWriter(new SmartOutputHandler(
- buildErrOutput,
+ buildIo.getErrRef(),
Arrays.asList(taskDef.getStdErrListener()),
errorConsumers));
buildLauncher.setStandardOutput(new WriterOutputStream(forwardedStdOut));
buildLauncher.setStandardError(new WriterOutputStream(forwardedStdErr));
- buildLauncher.setStandardInput(new ReaderInputStream(buildIn));
+ buildLauncher.setStandardInput(new ReaderInputStream(buildIo.getInRef()));
return new OutputRef(forwardedStdOut, forwardedStdErr);
}
@@ -237,49 +235,44 @@ private static void doGradleTasksWithProgress(
taskDef.isReuseOutput(),
taskDef.isCleanOutput());
try {
- OutputWriter buildOutput = ioRef.getIo().getOut();
try {
- OutputWriter buildErrOutput = ioRef.getIo().getErr();
+ OutputWriter buildOutput = ioRef.getOutRef();
+ if (GlobalGradleSettings.getAlwaysClearOutput().getValue()
+ || taskDef.isCleanOutput()) {
+ buildOutput.reset();
+ // There is no need to reset buildErrOutput,
+ // at least this is what NetBeans tells you in its
+ // logs if you do.
+ }
+ printCommand(buildOutput, command, taskDef);
+
+ OutputRef outputRef = configureOutput(project, taskDef, buildLauncher, ioRef);
try {
- if (GlobalGradleSettings.getAlwaysClearOutput().getValue()
- || taskDef.isCleanOutput()) {
- buildOutput.reset();
- // There is no need to reset buildErrOutput,
- // at least this is what NetBeans tells you in its
- // logs if you do.
- }
-
- printCommand(buildOutput, command, taskDef);
-
- OutputRef outputRef = configureOutput(
- project, taskDef, buildLauncher, ioRef.getIo().getIn(), buildOutput, buildErrOutput);
- try {
- ioRef.getIo().select();
- buildLauncher.run();
- } finally {
- // This close method will only forward the last lines
- // if they were not terminated with a line separator.
- outputRef.close();
- }
- } catch (Throwable ex) {
- LOGGER.log(
- ex instanceof Exception ? Level.INFO : Level.SEVERE,
- "Gradle build failure: " + command,
- ex);
-
- String buildFailureMessage = NbStrings.getBuildFailure(command);
- buildErrOutput.println();
- buildErrOutput.println(buildFailureMessage);
- project.displayError(buildFailureMessage, ex, false);
+ ioRef.getIo().select();
+ buildLauncher.run();
} finally {
- buildErrOutput.close();
+ // This close method will only forward the last lines
+ // if they were not terminated with a line separator.
+ outputRef.close();
}
- } finally {
- buildOutput.close();
+ } catch (Throwable ex) {
+ LOGGER.log(
+ ex instanceof Exception ? Level.INFO : Level.SEVERE,
+ "Gradle build failure: " + command,
+ ex);
+
+ String buildFailureMessage = NbStrings.getBuildFailure(command);
+
+ OutputWriter buildErrOutput = ioRef.getErrRef();
+ buildErrOutput.println();
+ buildErrOutput.println(buildFailureMessage);
+ project.displayError(buildFailureMessage, ex, false);
}
} finally {
ioRef.close();
}
+ } catch (IOException ex) {
+ LOGGER.log(Level.WARNING, "Unexpected I/O exception.", ex);
} finally {
if (initScript != null) {
initScript.delete();
Please sign in to comment.
Something went wrong with that request. Please try again.