Skip to content
Permalink
Browse files
[CXF-5489] Add transferTo(file) functionality
Modified patch from Henry Clout applied

git-svn-id: https://svn.apache.org/repos/asf/cxf/trunk@1561791 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
dkulp committed Jan 27, 2014
1 parent de76767 commit 6a9eec6adec3bd08dac318ad51df10959e919bac
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 17 deletions.
@@ -20,12 +20,14 @@
package org.apache.cxf.attachment;


import java.io.File;
import java.io.IOException;
import java.io.InputStream;

import org.apache.cxf.helpers.IOUtils;
import org.apache.cxf.io.Transferable;

public class DelegatingInputStream extends InputStream {
public class DelegatingInputStream extends InputStream implements Transferable {
private InputStream is;
private AttachmentDeserializer deserializer;
private boolean isClosed;
@@ -52,6 +54,13 @@ public void close() throws IOException {
isClosed = true;
}

public void transferTo(File destinationFile) throws IOException {
if (isClosed) {
throw new IOException("Stream is closed");
}
IOUtils.transferTo(is, destinationFile);
}

public boolean isClosed() {
return isClosed;
}
@@ -21,6 +21,8 @@

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -31,6 +33,7 @@
import java.nio.charset.Charset;

import org.apache.cxf.io.CopyingOutputStream;
import org.apache.cxf.io.Transferable;

public final class IOUtils {
public static final Charset UTF8_CHARSET = Charset.forName("utf-8");
@@ -174,6 +177,24 @@ public static void copy(final Reader input, final Writer output,
n = input.read(buffer);
}
}

public static void transferTo(InputStream inputStream, File destinationFile) throws IOException {
if (Transferable.class.isAssignableFrom(inputStream.getClass())) {
((Transferable)inputStream).transferTo(destinationFile);
} else {
FileOutputStream fout = new FileOutputStream(destinationFile);
try {
copyAndCloseInput(inputStream, fout);
} finally {
try {
fout.close();
} catch (IOException ex) {
//ignore
}
}
}
}


public static String toString(final InputStream input) throws IOException {
return toString(input, DEFAULT_BUFFER_SIZE);
@@ -21,6 +21,13 @@

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

import org.apache.cxf.io.Transferable;

/**
* Subclass of ByteArrayOutputStream that allows creation of a
@@ -43,12 +50,30 @@ public LoadingByteArrayOutputStream(int i) {
super(i);
}

public ByteArrayInputStream createInputStream() {
return new ByteArrayInputStream(buf, 0, count) {
public String toString() {
return IOUtils.newStringFromBytes(buf, 0, count);
private static class LoadedByteArrayInputStream extends ByteArrayInputStream implements Transferable {
public LoadedByteArrayInputStream(byte[] buf, int length) {
super(buf, 0, length);
}
public String toString() {
return IOUtils.newStringFromBytes(buf, 0, count);
}

@Override
public void transferTo(File file) throws IOException {
FileOutputStream fout = new FileOutputStream(file);
FileChannel channel = fout.getChannel();
ByteBuffer bb = ByteBuffer.wrap(buf, 0, count);
while (bb.hasRemaining()) {
channel.write(bb);
}
};
channel.close();
fout.close();
}

}

public ByteArrayInputStream createInputStream() {
return new LoadedByteArrayInputStream(buf, count);
}

public void setSize(int i) {
@@ -527,16 +527,7 @@ public InputStream getInputStream() throws IOException {
}
} else {
try {
InputStream fileInputStream = new FileInputStream(tempFile) {
boolean closed;
public void close() throws IOException {
if (!closed) {
super.close();
maybeDeleteTempFile(this);
}
closed = true;
}
};
InputStream fileInputStream = new TransferableFileInputStream(tempFile);
streamList.add(fileInputStream);
if (cipherTransformation != null) {
fileInputStream = new CipherInputStream(fileInputStream, ciphers.getDecryptor()) {
@@ -662,4 +653,35 @@ public void close() throws IOException {
return in;
}

private class TransferableFileInputStream extends FileInputStream implements Transferable {
private boolean closed;
private File sourceFile;

TransferableFileInputStream(File sourceFile) throws FileNotFoundException {
super(sourceFile);
this.sourceFile = sourceFile;
}

public void close() throws IOException {
if (!closed) {
super.close();
maybeDeleteTempFile(this);
}
closed = true;
}

@Override
public void transferTo(File destinationFile) throws IOException {
if (closed) {
throw new IOException("Stream closed");
}
//We've cached the file so try renaming.
boolean transfered = sourceFile.renameTo(destinationFile);
if (!transfered) {
// Data is in memory, or we failed to rename the file, try copying
// the stream instead.
IOUtils.transferTo(getInputStream(), destinationFile);
}
}
}
}
@@ -0,0 +1,33 @@
/**
* 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.cxf.io;

import java.io.File;
import java.io.IOException;

/**
* Implementing classes support transfer of their data to a file. This
* is typically implemented as a stream copy, or a file move.
*
*/
public interface Transferable {

void transferTo(File file) throws IOException;

}
@@ -18,6 +18,8 @@
*/
package org.apache.cxf.jaxrs.ext.multipart;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.util.Iterator;
@@ -31,6 +33,8 @@
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.Providers;

import org.apache.cxf.helpers.IOUtils;
import org.apache.cxf.io.Transferable;
import org.apache.cxf.jaxrs.impl.MetadataMap;
import org.apache.cxf.jaxrs.utils.JAXRSUtils;

@@ -42,7 +46,7 @@
* See the {@link AttachmentBuilder} for a convenient
* way to create attachments for use with {@link org.apache.cxf.jaxrs.client.WebClient}.
*/
public class Attachment {
public class Attachment implements Transferable {

private DataHandler handler;
private MultivaluedMap<String, String> headers =
@@ -163,6 +167,10 @@ public MultivaluedMap<String, String> getHeaders() {
return new MetadataMap<String, String>(headers, false, true);
}

public void transferTo(File destinationFile) throws IOException {
IOUtils.transferTo(handler.getInputStream(), destinationFile);
}

@Override
public int hashCode() {
return headers.hashCode();

0 comments on commit 6a9eec6

Please sign in to comment.