/*******************************************************************************
* Copyright (c) 2007, 2014 compeople AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* compeople AG - initial API and implementation
*******************************************************************************/
package org.eclipse.riena.communication.core.attachment;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import org.eclipse.core.runtime.Assert;
import org.eclipse.riena.core.util.Nop;
/**
* This class contains data constructed from a File object or a URL. If this
* object is then passed as parameter in your webservice call, the contained
* data is passed as SOAP attachment. This is helpful for large and binary data
* transport
*/
public class Attachment {
protected enum Type {
FILE, URL, INPUTSTREAM
}
private static final int READ_BLOCK_SIZE = 10000;
// make all fields that are not in AttachmentSerialized transient, so
// hessian does not try to transfer them
// type how the attachment was constructed, is either FILE, URL or
// INPUTSTREAM
private transient Type type;
// contains the file object from which the Attachment was constructed
private transient File file;
// contains the url object from which the Attachment was constructed
// private transient URL url;
// contains the datasource with the data
private transient IDataSource dataSource;
// byte array for data when using a binary protocol i.e. hessian
// this array is not explicitly set but rather "magically" filled by hessian
// upon deserialization
private ByteArrayDataSource internalDataSource = null;
// private constructor used by hessian
private Attachment() {
super();
}
/**
* @param file
* create attachment from file content
* @pre file!=null
* @pre file.exist==true
* @throws java.io.FileNotFoundException
*/
public Attachment(final File file) throws IOException {
this();
type = Type.FILE;
this.file = file;
this.dataSource = new FileDataSource(file);
this.dataSource.checkValid();
}
/**
* @param url
* create attachment from url content
*/
public Attachment(final URL url) throws IOException {
this();
type = Type.URL;
// this.url = url;
this.dataSource = new HttpURLDataSource(url);
this.dataSource.checkValid();
}
/**
* @param dataHandler
*/
public Attachment(final InputStream inputStream) throws IOException {
this();
type = Type.INPUTSTREAM;
this.dataSource = new InputStreamDataSource(inputStream);
this.dataSource.checkValid();
}
protected Attachment(final ByteArrayDataSource dataSource) {
this();
type = Type.INPUTSTREAM;
this.dataSource = dataSource;
}
/**
* @return InputStream
* @throws IOException
*/
public InputStream readAsStream() throws IOException {
return dataSource.getInputStream();
}
/**
* Gets the attachment as file. File is created with this request. Caller
* must delete file after use.
*
* @param fullFilePath
* (full file path from where the attachemnt should be opened,
* includes the filename)
* @return read the content of the attachment as file object (requires temp
* storage)
* @throws IOException
*/
public File readAsFile(final String fullFilePath) throws IOException {
final InputStream input = readAsStream();
if (input == null) {
throw new IOException("no inputstream to save as file"); //$NON-NLS-1$
}
final FileOutputStream output = new FileOutputStream(fullFilePath);
try {
final byte[] b = new byte[READ_BLOCK_SIZE];
int length = 0;
while ((length = input.read(b)) == READ_BLOCK_SIZE) {
output.write(b, 0, length);
}
if (length > 0) {
output.write(b, 0, length);
}
final File returnFile = new File(fullFilePath);
return returnFile;
} finally {
output.close();
}
}
/**
* @return the construction type of the attachment
*/
protected Type getType() {
return type;
}
/**
* @return File object that was used when creating the attachment
* @pre getType()==Type.FILE;
*/
protected File getInternalFile() {
Assert.isTrue(getType() == Type.FILE, "invalid type when getting File object"); //$NON-NLS-1$
return file;
}
/**
* this method is called by hessian before an object is serialized. It
* stores that blob in a different unrelated object and returns it as the
* new attachment object. We need to make sure that the private fields of
* AttachmentSerialized are also available in Attachment as they are
* magically filled when deserializing.
*
* @return Object
*/
public Object writeReplace() {
try {
if (type == Type.INPUTSTREAM) {
try {
final InputStream input = dataSource.getInputStream();
if (input != null && input.markSupported()) {
input.reset();
}
} catch (final IOException e) {
Nop.reason("do nothing"); //$NON-NLS-1$
}
}
} catch (final Throwable e) {
return new AttachmentSerialized(dataSource);
}
return new AttachmentSerialized(dataSource);
}
/**
* this method is called by hessian after an object was fully deserialized
* we use it to create the dataHandler Object from the internal byte array
*
* @return Object
*/
public Object readResolve() {
dataSource = internalDataSource;
type = Type.INPUTSTREAM;
internalDataSource = null;
return this;
}
}