
org.apache.servicecomb.foundation.vertx.stream.PumpFromPart Maven / Gradle / Ivy
/*
* 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.
*/
package org.apache.servicecomb.foundation.vertx.stream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.CompletableFuture;
import jakarta.servlet.http.Part;
import org.apache.commons.io.IOUtils;
import org.apache.servicecomb.foundation.vertx.http.DownloadUtils;
import org.apache.servicecomb.foundation.vertx.http.ReadStreamPart;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.vertx.core.Context;
import io.vertx.core.Handler;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.streams.ReadStream;
import io.vertx.core.streams.WriteStream;
public class PumpFromPart {
private static final Logger LOGGER = LoggerFactory.getLogger(PumpFromPart.class);
private final Context context;
private final Part part;
public PumpFromPart(Context context, Part part) {
this.context = context;
this.part = part;
}
private CompletableFuture> prepareReadStream() {
CompletableFuture> future = new CompletableFuture<>();
if (ReadStreamPart.class.isInstance(part)) {
future.complete(((ReadStreamPart) part).getReadStream());
return future;
}
try {
InputStream inputStream = part.getInputStream();
InputStreamToReadStream inputStreamToReadStream = new InputStreamToReadStream(context, inputStream, true);
inputStreamToReadStream.pause();
future.complete(inputStreamToReadStream);
} catch (IOException e) {
future.completeExceptionally(e);
}
return future;
}
public CompletableFuture toWriteStream(WriteStream writeStream, Handler throwableHandler) {
return prepareReadStream()
.thenCompose(readStream -> new PumpCommon().pump(context, readStream, writeStream, throwableHandler))
.whenComplete((v, e) -> {
if (e != null) {
LOGGER.error("to write stream failed.", e);
}
DownloadUtils.clearPartResource(part);
// PumpImpl will add drainHandler to writeStream,
// in order to support write multiple files to same writeStream,
// need reset after one stream is successful.
writeStream.drainHandler(null);
});
}
public CompletableFuture toOutputStream(OutputStream outputStream, boolean autoCloseOutputStream) {
if (context == null) {
return toOutputStreamSync(outputStream, autoCloseOutputStream);
}
return toOutputStreamAsync(outputStream, autoCloseOutputStream);
}
private CompletableFuture toOutputStreamAsync(OutputStream outputStream, boolean autoCloseOutputStream) {
OutputStreamToWriteStream outputStreamToWriteStream = new OutputStreamToWriteStream(context, outputStream,
autoCloseOutputStream);
return toWriteStream(outputStreamToWriteStream, null);
}
// DO NOT use a mocked sync context to unify the pump logic
// otherwise when pump big stream, will cause stack overflow
private CompletableFuture toOutputStreamSync(OutputStream outputStream, boolean autoCloseOutputStream) {
CompletableFuture future = new CompletableFuture<>();
future.whenComplete((v, e) -> DownloadUtils.clearPartResource(part));
try (InputStream inputStream = part.getInputStream()) {
IOUtils.copyLarge(inputStream, outputStream);
} catch (Throwable e) {
future.completeExceptionally(e);
}
if (autoCloseOutputStream) {
try {
outputStream.close();
} catch (Throwable e) {
future.completeExceptionally(e);
}
}
future.complete(null);
return future;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy