001/*
002 * Copyright 2002-2017 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.core.io;
018
019import java.io.ByteArrayInputStream;
020import java.io.IOException;
021import java.io.InputStream;
022import java.util.Arrays;
023
024import org.springframework.util.Assert;
025
026/**
027 * {@link Resource} implementation for a given byte array.
028 * <p>Creates a {@link ByteArrayInputStream} for the given byte array.
029 *
030 * <p>Useful for loading content from any given byte array,
031 * without having to resort to a single-use {@link InputStreamResource}.
032 * Particularly useful for creating mail attachments from local content,
033 * where JavaMail needs to be able to read the stream multiple times.
034 *
035 * @author Juergen Hoeller
036 * @author Sam Brannen
037 * @since 1.2.3
038 * @see java.io.ByteArrayInputStream
039 * @see InputStreamResource
040 * @see org.springframework.mail.javamail.MimeMessageHelper#addAttachment(String, InputStreamSource)
041 */
042public class ByteArrayResource extends AbstractResource {
043
044        private final byte[] byteArray;
045
046        private final String description;
047
048
049        /**
050         * Create a new {@code ByteArrayResource}.
051         * @param byteArray the byte array to wrap
052         */
053        public ByteArrayResource(byte[] byteArray) {
054                this(byteArray, "resource loaded from byte array");
055        }
056
057        /**
058         * Create a new {@code ByteArrayResource} with a description.
059         * @param byteArray the byte array to wrap
060         * @param description where the byte array comes from
061         */
062        public ByteArrayResource(byte[] byteArray, String description) {
063                Assert.notNull(byteArray, "Byte array must not be null");
064                this.byteArray = byteArray;
065                this.description = (description != null ? description : "");
066        }
067
068
069        /**
070         * Return the underlying byte array.
071         */
072        public final byte[] getByteArray() {
073                return this.byteArray;
074        }
075
076        /**
077         * This implementation always returns {@code true}.
078         */
079        @Override
080        public boolean exists() {
081                return true;
082        }
083
084        /**
085         * This implementation returns the length of the underlying byte array.
086         */
087        @Override
088        public long contentLength() {
089                return this.byteArray.length;
090        }
091
092        /**
093         * This implementation returns a ByteArrayInputStream for the
094         * underlying byte array.
095         * @see java.io.ByteArrayInputStream
096         */
097        @Override
098        public InputStream getInputStream() throws IOException {
099                return new ByteArrayInputStream(this.byteArray);
100        }
101
102        /**
103         * This implementation returns a description that includes the passed-in
104         * {@code description}, if any.
105         */
106        @Override
107        public String getDescription() {
108                return "Byte array resource [" + this.description + "]";
109        }
110
111
112        /**
113         * This implementation compares the underlying byte array.
114         * @see java.util.Arrays#equals(byte[], byte[])
115         */
116        @Override
117        public boolean equals(Object obj) {
118                return (obj == this ||
119                        (obj instanceof ByteArrayResource && Arrays.equals(((ByteArrayResource) obj).byteArray, this.byteArray)));
120        }
121
122        /**
123         * This implementation returns the hash code based on the
124         * underlying byte array.
125         */
126        @Override
127        public int hashCode() {
128                return (byte[].class.hashCode() * 29 * this.byteArray.length);
129        }
130
131}