/* * Copyright(c) 2002 Center for E-Commerce Infrastructure Development, The * University of Hong Kong (HKU). All Rights Reserved. * * This software is licensed under the Academic Free License Version 1.0 * * Academic Free License * Version 1.0 * * This Academic Free License applies to any software and associated * documentation (the "Software") whose owner (the "Licensor") has placed the * statement "Licensed under the Academic Free License Version 1.0" immediately * after the copyright notice that applies to the Software. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of the Software (1) to use, copy, modify, merge, publish, perform, * distribute, sublicense, and/or sell copies of the Software, and to permit * persons to whom the Software is furnished to do so, and (2) under patent * claims owned or controlled by the Licensor that are embodied in the Software * as furnished by the Licensor, to make, use, sell and offer for sale the * Software and derivative works thereof, subject to the following conditions: * * - Redistributions of the Software in source code form must retain all * copyright notices in the Software as furnished by the Licensor, this list * of conditions, and the following disclaimers. * - Redistributions of the Software in executable form must reproduce all * copyright notices in the Software as furnished by the Licensor, this list * of conditions, and the following disclaimers in the documentation and/or * other materials provided with the distribution. * - Neither the names of Licensor, nor the names of any contributors to the * Software, nor any of their trademarks or service marks, may be used to * endorse or promote products derived from this Software without express * prior written permission of the Licensor. * * DISCLAIMERS: LICENSOR WARRANTS THAT THE COPYRIGHT IN AND TO THE SOFTWARE IS * OWNED BY THE LICENSOR OR THAT THE SOFTWARE IS DISTRIBUTED BY LICENSOR UNDER * A VALID CURRENT LICENSE. EXCEPT AS EXPRESSLY STATED IN THE IMMEDIATELY * PRECEDING SENTENCE, THE SOFTWARE IS PROVIDED BY THE LICENSOR, CONTRIBUTORS * AND COPYRIGHT OWNERS "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE * LICENSOR, CONTRIBUTORS OR COPYRIGHT OWNERS BE LIABLE FOR ANY CLAIM, DAMAGES * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE. * * This license is Copyright (C) 2002 Lawrence E. Rosen. All rights reserved. * Permission is hereby granted to copy and distribute this license without * modification. This license may not be modified without the express written * permission of its copyright owner. */ /* ===== * * $Header: /home/cvsroot/ebxml-pkg/src/hk/hku/cecid/ebms/pkg/AttachmentDataSource.java,v 1.1 2005/07/28 09:36:24 dcmsze Exp $ * * Code authored by: * * cyng [2002-03-21] * * Code reviewed by: * * username [YYYY-MM-DD] * * Remarks: * * ===== */ package hk.hku.cecid.ebms.pkg; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import javax.activation.DataSource; import javax.mail.MessagingException; import javax.mail.internet.MimeUtility; /** * This is an implementation of <code>javax.activation.DataSource</code> * that encapsulates attachment data in a SOAP message. * * @author cyng * @version $Revision: 1.1 $ */ public class AttachmentDataSource implements DataSource { /** * Content type of the attachment. */ private String contentType; /** * Content-Transfer-Encoding of the attachment. */ private String encoding; /** * Name of the attachment. */ private String name; /** * Attachment data. */ private byte[] data; private long offset; private long length; private DataSource dataSource; /** * Constructs an <code>AttachmentDataSource</code> object from an array * of binary data. * * @param data Byte array containing data for the * <code>AttachmentDataSource</code> * @param contentType Content type of the data. */ public AttachmentDataSource(byte[] data, String contentType) { this(data, contentType, null); } /** * Constructs an <code>AttachmentDataSource</code> object from an array * of binary data, and assign a name to the data source. * * @param data Byte array containing data for the * <code>AttachmentDataSource</code> * @param contentType Content type of the data. * @param name Name assigned to the * <code>AttachmentDataSource</code> */ public AttachmentDataSource(byte[] data, String contentType, String name) { this(data, contentType, null, name); } /** * Constructs an <code>AttachmentDataSource</code> object from an array * of binary data, and assign a name to the data source. * * @param data Byte array containing data for the * <code>AttachmentDataSource</code> * @param contentType Content type of the data. * @param encoding Content-Transfer-Encoding of the data. * @param name Name assigned to the * <code>AttachmentDataSource</code> */ public AttachmentDataSource(byte[] data, String contentType, String encoding, String name) { this.contentType = contentType; this.encoding = encoding; if (name == null) { this.name = AttachmentDataSource.class.getName(); } else { this.name = name; } this.data = data; offset = 0; length = data.length; } /** * Constructs an <code>AttachmentDataSource</code> object from a file. * * @param fileName Name of the file to be loaded. * @param contentType Content type of the file. * @throws IOException */ public AttachmentDataSource(String fileName, String contentType) throws IOException { this(fileName, contentType, false); } /** * Constructs an <code>AttachmentDataSource</code> object from a file. * * @param fileName Name of the file to be loaded. * @param contentType Content type of the file. * @param loadToMem Load all data to memory upon creation * @throws IOException */ public AttachmentDataSource(String fileName, String contentType, boolean loadToMem) throws IOException { this(new File(fileName), contentType, loadToMem); } /** * Constructs an <code>AttachmentDataSource</code> object from a * <code>File</code> object. * * @param file <code>File</code> object containing information * on the file to be loaded. * @param contentType Content type of the file. * @throws IOException */ public AttachmentDataSource(File file, String contentType) throws IOException { this(file, contentType, false); } /** * Constructs an <code>AttachmentDataSource</code> object from a * <code>File</code> object. * * @param file <code>File</code> object containing information * on the file to be loaded. * @param contentType Content type of the file. * @param loadToMem Load all data to memory upon creation * @throws IOException */ public AttachmentDataSource(File file, String contentType, boolean loadToMem) throws IOException { this.contentType = contentType; this.encoding = null; if (loadToMem) { this.name = file.getName(); loadData(new FileInputStream(file)); } else { this.name = file.getCanonicalPath(); this.data = null; this.offset = 0; this.length = file.length(); } } /** * Constructs an <code>AttachmentDataSource</code> object from an * <code>InputStream</code>. * * @param in <code>InputStream</code> from which the data is * read and stored in the data source. * @param contentType Content type of the data. * @throws IOException */ public AttachmentDataSource(InputStream in, String contentType) throws IOException { this(in, contentType, null); } /** * Constructs an <code>AttachmentDataSource</code> object from an * <code>InputStream</code> with a given name. * * @param in <code>InputStream</code> from which the data * is read and stored in the data source. * @param contentType Content type of the data. * @param name Name assigned to the * <code>AttachmentDataSource</code>. * @throws IOException */ public AttachmentDataSource(InputStream in, String contentType, String name) throws IOException { this(in, contentType, null, name); } /** * Constructs an <code>AttachmentDataSource</code> object from an * <code>InputStream</code> with the specified Content-Transfer-Encoding * and name. * * @param in <code>InputStream</code> from which the data * is read and stored in the data source. * @param contentType Content type of the data. * @param encoding Content-Transfer-Encoding of the data. * @param name Name assigned to the * <code>AttachmentDataSource</code>. * @throws IOException */ public AttachmentDataSource(InputStream in, String contentType, String encoding, String name) throws IOException { this.contentType = contentType; this.encoding = encoding; if (name == null) { this.name = AttachmentDataSource.class.getName(); } else { this.name = name; } loadData(in); } /** * Constructs an <code>AttachmentDataSource</code> object using the data * of <code>length</code> in a file starting from <code>offset</code> * with the specified Content-Type. * * @param fileName Name of the file to be loaded. * @param offset Offset from the start of the file. * @param length Length of data to be read. * @param contentType Content type of the data. */ public AttachmentDataSource(String fileName, long offset, long length, String contentType) throws IOException { this(fileName, offset, length, contentType, false); } /** * Constructs an <code>AttachmentDataSource</code> object using the data * of <code>length</code> in a file starting from <code>offset</code> * with the specified Content-Type. * * @param fileName Name of the file to be loaded. * @param offset Offset from the start of the file. * @param length Length of data to be read. * @param contentType Content type of the data. * @param loadToMem Load all data to memory upon creation */ public AttachmentDataSource(String fileName, long offset, long length, String contentType, boolean loadToMem) throws IOException { this(fileName, offset, length, contentType, null, loadToMem); } /** * Constructs an <code>AttachmentDataSource</code> object using the data * of <code>length</code> in a file starting from <code>offset</code>. * with the specified Content-Type and Content-Transfer-Encoding. * * @param fileName Name of the file to be loaded. * @param offset Offset from the start of the file. * @param length Length of data to be read. * @param contentType Content type of the data. * @param encoding Content-Transfer-Encoding of the data. */ public AttachmentDataSource(String fileName, long offset, long length, String contentType, String encoding) throws IOException { this(fileName, offset, length, contentType, encoding, false); } /** * Constructs an <code>AttachmentDataSource</code> object using the data * of <code>length</code> in a file starting from <code>offset</code>. * with the specified Content-Type and Content-Transfer-Encoding. * * @param fileName Name of the file to be loaded. * @param offset Offset from the start of the file. * @param length Length of data to be read. * @param contentType Content type of the data. * @param encoding Content-Transfer-Encoding of the data. * @param loadToMem Load all data to memory upon creation */ public AttachmentDataSource(String fileName, long offset, long length, String contentType, String encoding, boolean loadToMem) throws IOException { if (loadToMem) { final File file = new File(name); if (file.length() < (offset + length)) { throw new IOException("Premature end-of-file: file name=" + name + " | file length=" + file.length() + " | offset=" + offset + " | length to be read=" + length); } final FileInputStream fis = new FileInputStream(name); final InputStream is = new PartialInputStream(fis, offset, length); loadData(is); } else { this.name = fileName; this.data = null; this.offset = offset; this.length = length; } this.contentType = contentType; this.encoding = encoding; } public AttachmentDataSource(DataSource dataSource, long offset, long length, String contentType, String encoding, boolean loadToMem) throws IOException { if (loadToMem) { InputStream fis = dataSource.getInputStream(); final InputStream is = new PartialInputStream(fis, offset, length); loadData(is); this.contentType = contentType; this.encoding = encoding; } else { this.dataSource = dataSource; this.contentType = contentType; this.encoding = encoding; this.data = null; this.offset = offset; this.length = length; } } private void loadData(InputStream is) throws IOException { try { final byte[] buffer = new byte[4096]; final ByteArrayOutputStream out = new ByteArrayOutputStream(); for (int c=is.read(buffer) ; c!=-1 ; c=is.read(buffer)) out.write(buffer, 0, c); this.data = out.toByteArray(); this.offset = 0; this.length = data.length; out.close(); } catch (IOException e) { throw e; } finally { if (is != null) { is.close(); } } } /** * Gets the content type of data stored in this * <code>AttachmentDataSource</code>. * * @return Content type of data stored in data source. */ public String getContentType() { return contentType; } /** * Gets <code>InputStream</code> from which data in the * <code>AttachmentDataSource</code> can be read. * * @return An <code>InputStream</code>. * @throws IOException */ public InputStream getInputStream() throws IOException { final InputStream is; if (data != null) { is = new ByteArrayInputStream(data); } else { InputStream fis = null; if (dataSource != null) { fis = dataSource.getInputStream(); } else { final File file = new File(name); if (file.length() < (offset + length)) { throw new IOException("Premature end-of-file: file name=" + name + " | file length=" + file.length() + " | offset=" + offset + " | length to be read=" + length); } fis = new FileInputStream(name); } is = new PartialInputStream(fis, offset, length); } if (encoding == null) { return is; } else { try { return MimeUtility.decode(is, encoding); } catch (MessagingException e) { throw new IOException(e.getMessage()); } } } /** * Gets the name of the <code>AttachmentDataSource</code>. * * @return Name of data source. */ public String getName() { return name; } /** * Sets the name of the <code>AttachmentDataSource</code>. * * @param name Name of data source. */ public void setName(String name) { this.name = name; } /** * This method should never be called. It implements the * <code>getOutputStream()</code> method of the * <code>javax.activation.DataSource</code> interface and * <code>IOException</code> will be thrown as the result of invocation. * * @return This method always result in <code>IOException</code>; it never * returns normally. * @throws IOException */ public OutputStream getOutputStream() throws IOException { throw new IOException("Program bug! " + AttachmentDataSource.class. getName() + ".getOutputStream() should not be invoked!"); } /** * Gets a byte array of data in this data source. * * @return A byte array of data. */ public byte[] getByteArray() throws IOException { if (data != null) { return data; } else { final ByteArrayOutputStream out = new ByteArrayOutputStream(); InputStream fis = null; try { if (dataSource != null) { fis = dataSource.getInputStream(); } else { fis = new FileInputStream(name); } final PartialInputStream in = new PartialInputStream (fis, offset, length); final byte[] buffer = new byte[4096]; for (int c=in.read(buffer) ; c!=-1 ; c=in.read(buffer)) out.write(buffer, 0, c); return out.toByteArray(); } catch (IOException e) { throw e; } finally { if (fis != null) { try { out.close(); fis.close(); } catch (IOException e) { throw e; } } } } } /** * Gets the length of data in this data source * * @return length of data */ public long getLength() { if (data != null) { return data.length; } else { return length; } } }