org.gradle.launcher.daemon.client.InputForwarder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gradle-api Show documentation
Show all versions of gradle-api Show documentation
Gradle 6.9.1 API redistribution.
/*
* Copyright 2011 the original author or authors.
*
* 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 org.gradle.launcher.daemon.client;
import org.gradle.internal.UncheckedException;
import org.gradle.internal.concurrent.ExecutorFactory;
import org.gradle.internal.concurrent.Stoppable;
import org.gradle.internal.concurrent.StoppableExecutor;
import org.gradle.internal.io.TextStream;
import org.gradle.util.DisconnectableInputStream;
import org.gradle.internal.io.LineBufferingOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.channels.AsynchronousCloseException;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* Asynchronously consumes from an input stream for a time,
* forwarding a line of input at a time to a specified action.
*
* Note that calling stop() will NOT close the source input stream.
*/
public class InputForwarder implements Stoppable {
private final InputStream input;
private final TextStream handler;
private final ExecutorFactory executorFactory;
private final int bufferSize;
private StoppableExecutor forwardingExecuter;
private DisconnectableInputStream disconnectableInput;
private LineBufferingOutputStream outputBuffer;
private final Lock lifecycleLock = new ReentrantLock();
private boolean started;
private boolean stopped;
public InputForwarder(InputStream input, TextStream handler, ExecutorFactory executerFactory, int bufferSize) {
this.input = input;
this.handler = handler;
this.executorFactory = executerFactory;
this.bufferSize = bufferSize;
}
public InputForwarder start() {
lifecycleLock.lock();
try {
if (started) {
throw new IllegalStateException("input forwarder has already been started");
}
disconnectableInput = new DisconnectableInputStream(input, bufferSize);
outputBuffer = new LineBufferingOutputStream(handler, bufferSize);
forwardingExecuter = executorFactory.create("forward input");
forwardingExecuter.execute(new Runnable() {
public void run() {
byte[] buffer = new byte[bufferSize];
int readCount;
Throwable readFailure = null;
try {
while (true) {
try {
readCount = disconnectableInput.read(buffer, 0, bufferSize);
if (readCount < 0) {
break;
}
} catch (AsynchronousCloseException e) {
break;
} catch (IOException e) {
readFailure = e;
break;
}
outputBuffer.write(buffer, 0, readCount);
}
outputBuffer.flush(); // will flush any unterminated lines out synchronously
} catch(IOException e) {
// should not happen
throw UncheckedException.throwAsUncheckedException(e);
} finally {
handler.endOfStream(readFailure);
}
}
});
started = true;
} finally {
lifecycleLock.unlock();
}
return this;
}
public void stop() {
lifecycleLock.lock();
try {
if (!stopped) {
try {
disconnectableInput.close();
} catch (IOException e) {
throw UncheckedException.throwAsUncheckedException(e);
}
forwardingExecuter.stop();
stopped = true;
}
} finally {
lifecycleLock.unlock();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy