001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.mail;
018
019import java.io.BufferedInputStream;
020import java.io.BufferedOutputStream;
021import java.io.ByteArrayInputStream;
022import java.io.ByteArrayOutputStream;
023import java.io.IOException;
024import java.io.InputStream;
025import java.io.OutputStream;
026import java.io.UnsupportedEncodingException;
027import java.nio.charset.StandardCharsets;
028
029import javax.activation.DataSource;
030
031/**
032 * A typed DataSource for InputStream, byte array, and String.
033 * <p>
034 * From version 1.3.1, it is possible to set a name for this DataSource, and it is recommended to do so.
035 * </p>
036 *
037 * @since 1.0
038 * @deprecated since 1.4, use {@link javax.mail.util.ByteArrayDataSource} or {@link javax.mail.util.SharedByteArrayInputStream}.
039 */
040@Deprecated
041public class ByteArrayDataSource implements DataSource {
042
043    /** Default content type. */
044    private static final String CONTENT_TYPE = "application/octet-stream";
045
046    /** Define the buffer size. */
047    public static final int BUFFER_SIZE = 512;
048
049    /** Stream containing the Data. */
050    private ByteArrayOutputStream outputStream;
051
052    /** The Content-contentType. */
053    private final String contentType;
054
055    /**
056     * The name associated with this data source. By default, the name is an empty string, similar to javax.mail.util.ByteArrayDataSource.
057     *
058     * @since 1.3.1
059     */
060    private String name = "";
061
062    /**
063     * Constructs a new instance from a byte array.
064     *
065     * @param data        A byte[].
066     * @param contentType A String.
067     * @throws IOException IOException
068     * @since 1.0
069     */
070    public ByteArrayDataSource(final byte[] data, final String contentType) throws IOException {
071        this.contentType = contentType;
072        try (ByteArrayInputStream bis = new ByteArrayInputStream(data)) {
073            read(bis);
074        }
075    }
076
077    /**
078     * Constructs a new instance from an input stream.
079     *
080     * @param inputStream An InputStream.
081     * @param contentType A String.
082     * @throws IOException IOException
083     * @since 1.0
084     */
085    public ByteArrayDataSource(final InputStream inputStream, final String contentType) throws IOException {
086        this.contentType = contentType;
087        this.read(inputStream);
088    }
089
090    /**
091     * Constructs a new instance from a String. N.B. assumes the data string can be converted using the charset iso-8859-1.
092     *
093     * @param data        A String.
094     * @param contentType A String.
095     * @throws IOException IOException
096     * @since 1.0
097     */
098    public ByteArrayDataSource(final String data, final String contentType) throws IOException {
099        this.contentType = contentType;
100        this.outputStream = new ByteArrayOutputStream();
101        try {
102            // Assumption that the string contains only ASCII characters!
103            // Else just pass in a charset into this constructor and use it in getBytes().
104            outputStream.write(data.getBytes(StandardCharsets.ISO_8859_1));
105            outputStream.flush();
106            outputStream.close();
107        } catch (final UnsupportedEncodingException e) {
108            throw new IOException("The Character Encoding is not supported.");
109        } finally {
110            outputStream.close();
111        }
112    }
113
114    /**
115     * Gets the content contentType.
116     *
117     * @return A String.
118     * @since 1.0
119     */
120    @Override
121    public String getContentType() {
122        return contentType == null ? CONTENT_TYPE : contentType;
123    }
124
125    /**
126     * Gets the input stream.
127     *
128     * @return An InputStream.
129     * @throws IOException IOException
130     * @since 1.0
131     */
132    @Override
133    public InputStream getInputStream() throws IOException {
134        if (outputStream == null) {
135            throw new IOException("no data");
136        }
137        return new ByteArrayInputStream(outputStream.toByteArray());
138    }
139
140    /**
141     * Gets the name.
142     *
143     * @return A String.
144     * @since 1.0
145     */
146    @Override
147    public String getName() {
148        return name;
149    }
150
151    /**
152     * Gets the OutputStream to write to.
153     *
154     * @return An OutputStream
155     * @since 1.0
156     */
157    @Override
158    public OutputStream getOutputStream() {
159        outputStream = new ByteArrayOutputStream();
160        return outputStream;
161    }
162
163    /**
164     * Reads the given input stream into this data source.
165     *
166     * @param inputStream An InputStream.
167     * @throws IOException IOException
168     */
169    private void read(final InputStream inputStream) throws IOException {
170        BufferedInputStream bis = null;
171        BufferedOutputStream osWriter = null;
172        try {
173            int length = 0;
174            final byte[] buffer = new byte[ByteArrayDataSource.BUFFER_SIZE];
175
176            bis = new BufferedInputStream(inputStream);
177            outputStream = new ByteArrayOutputStream();
178            osWriter = new BufferedOutputStream(outputStream);
179
180            // Write the InputData to OutputStream
181            while ((length = bis.read(buffer)) != -1) {
182                osWriter.write(buffer, 0, length);
183            }
184            osWriter.flush();
185            osWriter.close();
186        } finally {
187            if (bis != null) {
188                bis.close();
189            }
190            if (outputStream != null) {
191                outputStream.close();
192            }
193            if (osWriter != null) {
194                osWriter.close();
195            }
196        }
197    }
198
199    /**
200     * Sets the name for this DataSource.
201     *
202     * @param name The name.
203     * @since 1.3.1
204     */
205    public void setName(final String name) {
206        this.name = name;
207    }
208}