소스 검색

remove obsolete classes

tags/2.0.1
Jonathan Cobb 4 년 전
부모
커밋
745b18232a
15개의 변경된 파일0개의 추가작업 그리고 616개의 파일을 삭제
  1. +0
    -46
      wizard-server/src/main/java/org/cobbzilla/wizard/filters/EntityFilter.java
  2. +0
    -63
      wizard-server/src/main/java/org/cobbzilla/wizard/filters/EntityTypeHeaderFilter.java
  3. +0
    -51
      wizard-server/src/main/java/org/cobbzilla/wizard/filters/MultiEntityFilter.java
  4. +0
    -24
      wizard-server/src/main/java/org/cobbzilla/wizard/resources/ByteStreamingOutput.java
  5. +0
    -21
      wizard-server/src/main/java/org/cobbzilla/wizard/resources/FileStreamingOutput.java
  6. +0
    -4
      wizard-server/src/main/java/org/cobbzilla/wizard/resources/FileUploadContext.java
  7. +0
    -115
      wizard-server/src/main/java/org/cobbzilla/wizard/resources/FileUploadResource.java
  8. +0
    -11
      wizard-server/src/main/java/org/cobbzilla/wizard/resources/PdfUploadResource.java
  9. +0
    -85
      wizard-server/src/main/java/org/cobbzilla/wizard/resources/SendableCsv.java
  10. +0
    -31
      wizard-server/src/main/java/org/cobbzilla/wizard/resources/SendableResource.java
  11. +0
    -9
      wizard-server/src/main/java/org/cobbzilla/wizard/server/config/HasAssetStorageConfiguration.java
  12. +0
    -87
      wizard-server/src/main/java/org/cobbzilla/wizard/util/CsvStreamingOutput.java
  13. +0
    -21
      wizard-server/src/main/java/org/cobbzilla/wizard/util/FileStreamingOutput.java
  14. +0
    -28
      wizard-server/src/main/java/org/cobbzilla/wizard/util/ProxyStreamingOutput.java
  15. +0
    -20
      wizard-server/src/main/java/org/cobbzilla/wizard/util/StreamStreamingOutput.java

+ 0
- 46
wizard-server/src/main/java/org/cobbzilla/wizard/filters/EntityFilter.java 파일 보기

@@ -1,46 +0,0 @@
package org.cobbzilla.wizard.filters;

import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import java.io.IOException;
import java.lang.reflect.Type;

import static org.cobbzilla.util.reflect.ReflectionUtil.forName;
import static org.cobbzilla.util.reflect.ReflectionUtil.getFirstTypeParam;

@Slf4j
public abstract class EntityFilter<T> implements ContainerResponseFilter {

@Getter(lazy=true) private final Class<T> matchEntityClass = getFirstTypeParam(getClass());

@Override public void filter(ContainerRequestContext request, ContainerResponseContext response) throws IOException {

final Type entityType = response.getEntityType();
if (entityType == null) return;

final Class<?> responseClass;
final String responseClassName;
try {
responseClassName = entityType.toString().split(" ")[1];
responseClass = forName(responseClassName);
} catch (Exception e) {
log.warn("filter: error with '" + entityType + "': " + e);
return;
}

if (shouldFilter(request, response, responseClassName, responseClass)) {
filter(request, response, responseClassName, responseClass);
}
}

protected boolean shouldFilter(ContainerRequestContext request, ContainerResponseContext response, String responseClassName, Class<?> responseClass) {
return getMatchEntityClass().isAssignableFrom(responseClass);
}

protected void filter(ContainerRequestContext request, ContainerResponseContext response, String responseClassName, Class<?> responseClass) {}

}

+ 0
- 63
wizard-server/src/main/java/org/cobbzilla/wizard/filters/EntityTypeHeaderFilter.java 파일 보기

@@ -1,63 +0,0 @@
package org.cobbzilla.wizard.filters;

import lombok.extern.slf4j.Slf4j;
import org.cobbzilla.wizard.dao.SearchResults;
import org.cobbzilla.wizard.model.Identifiable;

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;

import static org.cobbzilla.util.daemon.ZillaRuntime.empty;

@Slf4j
public class EntityTypeHeaderFilter extends EntityFilter<Object> {

protected String getTypeHeaderName() { return Identifiable.ENTITY_TYPE_HEADER_NAME; }

@Override public void filter(ContainerRequestContext request,
ContainerResponseContext response,
String responseClassName,
Class<?> responseClass) {

final boolean isSearchResults = SearchResults.class.isAssignableFrom(responseClass);
final boolean isCollection = Collection.class.isAssignableFrom(responseClass);
final boolean isMap = Map.class.isAssignableFrom(responseClass);
final boolean isArray = responseClass.isArray();
String elementClassName;
if (isSearchResults) {
final SearchResults searchResults = (SearchResults) response.getEntity();
response.getHeaders().add(getTypeHeaderName(),
SearchResults.class.getName() + (searchResults.hasResults() ? "<" + getCollectionElementClass(searchResults.getResults()) + ">" : ""));

} else if (isCollection) {
response.getHeaders().add(getTypeHeaderName(), getCollectionElementClass((Collection) response.getEntity())+"[]");

} else if (isArray) {
final Object[] a = (Object[]) response.getEntity();
try {
elementClassName = empty(a) ? "" : a[0].getClass().getName();
} catch (Exception e) {
elementClassName = "";
}
response.getHeaders().add(getTypeHeaderName(), elementClassName + "[]");

} else if (isMap) {
response.getHeaders().add(getTypeHeaderName(), LinkedHashMap.class.getName());
} else {
response.getHeaders().add(getTypeHeaderName(), responseClassName);
}
return;
}

protected String getCollectionElementClass(Collection c) {
try {
return empty(c) ? "" : c.iterator().next().getClass().getName();
} catch (Exception ignored) {
return "";
}
}

}

+ 0
- 51
wizard-server/src/main/java/org/cobbzilla/wizard/filters/MultiEntityFilter.java 파일 보기

@@ -1,51 +0,0 @@
package org.cobbzilla.wizard.filters;

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import java.util.Collection;
import java.util.Iterator;

import static org.cobbzilla.util.reflect.ReflectionUtil.arrayClass;

public abstract class MultiEntityFilter<T, A extends ApiAccount, P extends ApiProfile> extends EntityFilter<T> {

protected abstract A getAccount(ContainerRequestContext request);
protected abstract P getActiveProfile(ContainerRequestContext request, A account);
protected abstract T filterEntity(T thing, A account, P profile);

@Override protected boolean shouldFilter(ContainerRequestContext request, ContainerResponseContext response,
String responseClassName, Class<?> responseClass) {
return super.shouldFilter(request, response, responseClassName, responseClass)
|| (responseClass.isArray() && arrayClass(getMatchEntityClass()).isAssignableFrom(responseClass) && ((Object[]) response.getEntity()).length > 0)
|| (Collection.class.isAssignableFrom(responseClass) && firstElementIsAssignableFrom(response));
}

private boolean firstElementIsAssignableFrom(ContainerResponseContext response) {
final Iterator iter = ((Collection) response.getEntity()).iterator();
return iter.hasNext() && getMatchEntityClass().isAssignableFrom(iter.next().getClass());
}

@Override protected void filter(ContainerRequestContext request, ContainerResponseContext response, String responseClassName, Class<?> responseClass) {
final A account = getAccount(request);
final P profile = getActiveProfile(request, account);
if (disableFilteringFor(account, profile)) return;
filterByProfile(responseClass, response, account, profile);
}

protected boolean disableFilteringFor(A account, P profile) { return false; }

protected ContainerResponseContext filterByProfile(Class<?> responseClass, ContainerResponseContext response, A account, P profile) {
final Object entity = response.getEntity();
if (responseClass.isArray()) {
for (T thing : (T[]) entity) filterEntity(thing, account, profile);

} else if (Collection.class.isAssignableFrom(responseClass)) {
for (T thing : ((Collection<T>) entity)) filterEntity(thing, account, profile);

} else {
filterEntity(((T) entity), account, profile);
}
return response;
}

}

+ 0
- 24
wizard-server/src/main/java/org/cobbzilla/wizard/resources/ByteStreamingOutput.java 파일 보기

@@ -1,24 +0,0 @@
package org.cobbzilla.wizard.resources;

import lombok.AllArgsConstructor;
import lombok.Getter;
import org.cobbzilla.util.io.StreamUtil;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.StreamingOutput;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

@AllArgsConstructor
public class ByteStreamingOutput implements StreamingOutput {

@Getter private final byte[] data;

@Override public void write(OutputStream out) throws IOException, WebApplicationException {
try (InputStream in = new ByteArrayInputStream(data)) {
StreamUtil.copyLarge(in, out);
}
}
}

+ 0
- 21
wizard-server/src/main/java/org/cobbzilla/wizard/resources/FileStreamingOutput.java 파일 보기

@@ -1,21 +0,0 @@
package org.cobbzilla.wizard.resources;

import lombok.AllArgsConstructor;
import lombok.Getter;
import org.cobbzilla.util.io.StreamUtil;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.StreamingOutput;
import java.io.*;

@AllArgsConstructor
public class FileStreamingOutput implements StreamingOutput {

@Getter private final File file;

@Override public void write(OutputStream out) throws IOException, WebApplicationException {
try (InputStream in = new FileInputStream(file)) {
StreamUtil.copyLarge(in, out);
}
}
}

+ 0
- 4
wizard-server/src/main/java/org/cobbzilla/wizard/resources/FileUploadContext.java 파일 보기

@@ -1,4 +0,0 @@
package org.cobbzilla.wizard.resources;

public interface FileUploadContext {
}

+ 0
- 115
wizard-server/src/main/java/org/cobbzilla/wizard/resources/FileUploadResource.java 파일 보기

@@ -1,115 +0,0 @@
package org.cobbzilla.wizard.resources;

import org.cobbzilla.wizard.asset.AssetStorageService;
import org.cobbzilla.wizard.asset.AssetStream;
import org.cobbzilla.wizard.model.AssetStorageInfo;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.glassfish.jersey.server.ContainerRequest;

import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import java.io.InputStream;
import java.util.Collection;
import java.util.Optional;
import java.util.regex.Pattern;

import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static javax.ws.rs.core.MediaType.MULTIPART_FORM_DATA;
import static org.cobbzilla.util.daemon.ZillaRuntime.die;
import static org.cobbzilla.util.daemon.ZillaRuntime.empty;
import static org.cobbzilla.util.http.HttpContentTypes.contentType;
import static org.cobbzilla.wizard.resources.ResourceUtil.*;

public abstract class FileUploadResource<FI extends AssetStorageInfo> {

protected abstract boolean validateUpload(ContainerRequest context);
protected abstract boolean validateDownload(ContainerRequest context, String uuid);
protected abstract boolean validateDelete(ContainerRequest context, String uuid);

/**
* Subclasses should override this method, or subclass a from a more specific class like PdfUploadResource
* @return Regular expression representing the allowed file extensions
*/
protected abstract Pattern getAllowedFileExtensions();

protected abstract AssetStorageService getStorage();

protected abstract FI createFileInfo(FormDataContentDisposition fileDetail);
protected abstract Collection<FI> findFileInfos();
protected abstract FI findFileInfo(String uuid);
protected abstract void deleteFileInfo(FI fileInfo);

@GET
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
public Response findDocuments(@Context ContainerRequest context) {
if (!validateDownload(context, null)) return forbidden();
return ok(findFileInfos());
}

@POST
@Consumes(MULTIPART_FORM_DATA)
@Produces(APPLICATION_JSON)
public Response uploadDocument(@Context ContainerRequest context,
@FormDataParam("file") InputStream fileStream,
@FormDataParam("file") FormDataContentDisposition fileDetail) {

if (!validateUpload(context)) return forbidden();

final Optional<String> error = validateFile(fileStream, fileDetail);
if (error.isPresent()) return invalid(error.get());

final FI fileInfo = createFileInfo(fileDetail);
getStorage().store(fileStream, fileDetail.getFileName(), fileInfo.getAsset());
return ok(fileInfo);
}

@GET @Path("/{uuid}")
@Consumes(APPLICATION_JSON)
@Produces("*/*")
public Response downloadDocument(@Context ContainerRequest context,
@PathParam("uuid") String uuid) {

if (!validateDownload(context, uuid)) return forbidden();

final FI fileInfo = findFileInfo(uuid);
if (fileInfo == null) return notFound(uuid);

final AssetStream assetStream = getStorage().load(fileInfo.getAsset());
if (empty(assetStream)) return notFound();

return stream(contentType(assetStream.getFormatName()), assetStream.getStream());
}

@DELETE @Path("/{uuid}")
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
public Response deleteDocument(@Context ContainerRequest context,
@PathParam("uuid") String uuid) {

if (!validateDelete(context, uuid)) return forbidden();

final FI fileInfo = findFileInfo(uuid);
if (fileInfo == null) return notFound(uuid);

if (getStorage().exists(fileInfo.getAsset())) {
if (!getStorage().delete(fileInfo.getAsset())) return die("deleteDocument: could not delete: " + fileInfo.getAsset());
}
deleteFileInfo(fileInfo);

return ok(fileInfo);
}

private Optional<String> validateFile(InputStream fileStream, FormDataContentDisposition fileDetail) {
if (fileStream == null) return Optional.of("err.fileStream.empty");
if (fileDetail == null) return Optional.of("err.fileDetail.empty");
if (empty(fileDetail.getFileName())) return Optional.of("err.fileName.empty");
if (!getAllowedFileExtensions().matcher(fileDetail.getFileName()).matches()) {
return Optional.of("err.fileFormat.invalid");
}

return Optional.empty();
}
}

+ 0
- 11
wizard-server/src/main/java/org/cobbzilla/wizard/resources/PdfUploadResource.java 파일 보기

@@ -1,11 +0,0 @@
package org.cobbzilla.wizard.resources;

import org.cobbzilla.wizard.model.AssetStorageInfo;

import java.util.regex.Pattern;

public abstract class PdfUploadResource<FI extends AssetStorageInfo> extends FileUploadResource<FI> {

@Override protected Pattern getAllowedFileExtensions() { return Pattern.compile(".*\\.pdf"); }

}

+ 0
- 85
wizard-server/src/main/java/org/cobbzilla/wizard/resources/SendableCsv.java 파일 보기

@@ -1,85 +0,0 @@
package org.cobbzilla.wizard.resources;

import com.github.jknack.handlebars.Handlebars;
import org.cobbzilla.util.collection.NameAndValue;
import org.cobbzilla.util.http.HttpContentTypes;
import org.cobbzilla.wizard.model.search.ResultPage;
import org.cobbzilla.wizard.model.search.SqlViewField;
import org.cobbzilla.wizard.util.CsvStreamingOutput;

import java.util.Collection;
import java.util.List;

public class SendableCsv extends SendableResource {

public SendableCsv(String name, Collection rows, String[] fields) {
this(name, rows, fields, null, null);
}

public SendableCsv(String name, Collection rows, String[] fields, String[] header) {
this(name, rows, fields, header, null);
}

public SendableCsv(String name, Collection rows, String[] fields, String[] header, Handlebars handlebars) {
super(new CsvStreamingOutput(rows, fields, header, handlebars));
setName(name);
}

@Override public String getContentType() { return HttpContentTypes.TEXT_CSV; }
@Override public Boolean getForceDownload() { return true; }

public static SendableCsv searchToCSV(ResultPage search, String name, List results, SqlViewField[] searchFields, Handlebars handlebars) {
final String[] fields;
final String[] header;
if (search.hasFieldMappings()) {
final NameAndValue[] fieldMappings = search.getFieldMappings();
fields = new String[fieldMappings.length];
header = new String[fieldMappings.length];
for (int i=0; i<fieldMappings.length; i++) {
final String value = fieldMappings[i].getValue();
boolean found = false;
for (SqlViewField searchField : searchFields) {
if (value.equals(searchField.getName())
|| (value.contains(".") && value.substring(0, value.indexOf(".")).equals(searchField.getName()))) {
if (value.contains(".")) {
fields[i] = fieldGetter(searchField) + "." + value.substring(value.indexOf('.') + 1);
} else {
fields[i] = fieldGetter(searchField);
}
found = true;
break;
}
}
if (!found) fields[i] = value;
header[i] = fieldMappings[i].getName();
}
} else if (search.getHasFields()) {
fields = search.getFields();
header = new String[fields.length];
for (int i=0; i<fields.length; i++) {
for (SqlViewField searchField : searchFields) {
if (fields[i].equals(searchField.getName())) {
fields[i] = fieldGetter(searchField);
header[i] = searchField.getName();
break;
}
}
}
} else {
header = new String[searchFields.length];
fields = new String[searchFields.length];
for (int i=0; i<searchFields.length; i++) {
fields[i] = fieldGetter(searchFields[i]);
header[i] = searchFields[i].getName();
}
}
return new SendableCsv(name, results, fields, header, handlebars);
}

public static String fieldGetter(SqlViewField field) {
return field.getType() != null
? field.hasEntity() ? "related."+ field.getEntity()+"."+ field.getEntityProperty() : field.getEntityProperty()
: field.getEntityProperty();
}

}

+ 0
- 31
wizard-server/src/main/java/org/cobbzilla/wizard/resources/SendableResource.java 파일 보기

@@ -1,31 +0,0 @@
package org.cobbzilla.wizard.resources;

import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.cobbzilla.util.collection.ArrayUtil;
import org.cobbzilla.util.collection.NameAndValue;

import javax.ws.rs.core.StreamingOutput;

import static org.cobbzilla.util.http.HttpStatusCodes.OK;

@Accessors(chain=true)
public class SendableResource {

public SendableResource (StreamingOutput out) { setOut(out); }

@Getter @Setter private int status = OK;
@Getter @Setter private String statusReason;
@Getter @Setter private NameAndValue[] headers;
@Getter @Setter private StreamingOutput out;
@Getter @Setter private String name;
@Getter @Setter private String contentType;
@Getter @Setter private Long contentLength;
@Getter @Setter private Boolean forceDownload;

public SendableResource addHeader (String name, String value) {
headers = ArrayUtil.append(headers, new NameAndValue(name, value));
return this;
}
}

+ 0
- 9
wizard-server/src/main/java/org/cobbzilla/wizard/server/config/HasAssetStorageConfiguration.java 파일 보기

@@ -1,9 +0,0 @@
package org.cobbzilla.wizard.server.config;

import org.cobbzilla.wizard.asset.AssetStorageService;

public interface HasAssetStorageConfiguration {

AssetStorageService getAssetStorageService();

}

+ 0
- 87
wizard-server/src/main/java/org/cobbzilla/wizard/util/CsvStreamingOutput.java 파일 보기

@@ -1,87 +0,0 @@
package org.cobbzilla.wizard.util;

import com.github.jknack.handlebars.Handlebars;
import com.opencsv.CSVWriter;
import lombok.Cleanup;
import lombok.extern.slf4j.Slf4j;
import org.cobbzilla.util.handlebars.HandlebarsUtil;
import org.cobbzilla.util.reflect.ReflectionUtil;
import org.cobbzilla.wizard.model.HasRelatedEntities;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.StreamingOutput;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.*;

import static org.cobbzilla.util.daemon.ZillaRuntime.die;
import static org.cobbzilla.util.daemon.ZillaRuntime.empty;
import static org.cobbzilla.util.reflect.ReflectionUtil.toMap;

@Slf4j
public class CsvStreamingOutput implements StreamingOutput {

private final String[] fields;
private final Collection rows;
private String[] header;
private Handlebars handlebars;

public CsvStreamingOutput(Collection rows, String[] fields, String[] header, Handlebars handlebars) {
this.rows = rows;
this.fields = fields;
this.header = header;
this.handlebars = handlebars;
}

public CsvStreamingOutput(Collection rows, String[] fields, String[] header) {
this(rows, fields, header, null);
}

public CsvStreamingOutput(Collection rows, String[] fields) {
this(rows, fields, null);
}

@Override public void write(OutputStream out) throws IOException, WebApplicationException {

if (empty(fields)) die("write: no fields specified");

@Cleanup final CSVWriter writer = new CSVWriter(new OutputStreamWriter(out));

final List<Map<String, Object>> data = new ArrayList<>();
final boolean defaultHeaders = empty(header);
final Set<String> columns = defaultHeaders ? new HashSet<>() : null;
for (Object row : rows) {
final Map<String, Object> map = new HashMap<>();
for (String field : fields) {
if (field.startsWith("'") && field.endsWith("'")) {
map.put(field, field.substring(1, field.length()-1));

} else if (handlebars != null && field.contains("[[") && field.contains("]]")) {
final Map<String, Object> ctx = toMap(row);
if (row instanceof HasRelatedEntities) ctx.putAll(((HasRelatedEntities) row).getRelated());
map.put(field, HandlebarsUtil.apply(handlebars, field, ctx, '[', ']'));

} else {
map.put(field, ReflectionUtil.get(row, field, null));
}
}
data.add(map);
if (defaultHeaders) columns.addAll(map.keySet());
}

if (defaultHeaders) header = columns.toArray(new String[columns.size()]);
writer.writeNext(header); // header row

for (Map<String, Object> row : data) {
final String[] line = new String[fields.length];
for (int i = 0; i < line.length; i++) {
final String field = fields[i];
final Object value = row.get(field);
line[i] = value == null ? "" : String.valueOf(value);
}
writer.writeNext(line, false);
}
}

}

+ 0
- 21
wizard-server/src/main/java/org/cobbzilla/wizard/util/FileStreamingOutput.java 파일 보기

@@ -1,21 +0,0 @@
package org.cobbzilla.wizard.util;

import lombok.AllArgsConstructor;
import org.cobbzilla.util.io.StreamUtil;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.StreamingOutput;
import java.io.*;

@AllArgsConstructor
public class FileStreamingOutput implements StreamingOutput {

private File cache;

@Override
public void write(OutputStream out) throws IOException, WebApplicationException {
try (InputStream in = new FileInputStream(cache)) {
StreamUtil.copyLarge(in, out);
}
}
}

+ 0
- 28
wizard-server/src/main/java/org/cobbzilla/wizard/util/ProxyStreamingOutput.java 파일 보기

@@ -1,28 +0,0 @@
package org.cobbzilla.wizard.util;

import lombok.AllArgsConstructor;
import lombok.Getter;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.impl.client.CloseableHttpClient;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.StreamingOutput;
import java.io.IOException;
import java.io.OutputStream;

@AllArgsConstructor
class ProxyStreamingOutput implements StreamingOutput {

@Getter private final HttpResponse response;
@Getter private final CloseableHttpClient httpClient;

@Override public void write(OutputStream output) throws IOException, WebApplicationException {
try {
IOUtils.copy(response.getEntity().getContent(), output);
} finally {
httpClient.close();
}
}

}

+ 0
- 20
wizard-server/src/main/java/org/cobbzilla/wizard/util/StreamStreamingOutput.java 파일 보기

@@ -1,20 +0,0 @@
package org.cobbzilla.wizard.util;

import lombok.AllArgsConstructor;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.StreamingOutput;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import static org.cobbzilla.util.io.StreamUtil.copyLarge;

@AllArgsConstructor
public class StreamStreamingOutput implements StreamingOutput {

private InputStream in;

@Override public void write(OutputStream out) throws IOException, WebApplicationException { copyLarge(in, out); }

}

불러오는 중...
취소
저장