001/*
002 * Copyright 2002-2018 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.lang.Nullable;
025import org.springframework.util.Assert;
026
027/**
028 * {@link Resource} implementation for a given byte array.
029 * <p>Creates a {@link ByteArrayInputStream} for the given byte array.
030 *
031 * <p>Useful for loading content from any given byte array,
032 * without having to resort to a single-use {@link InputStreamResource}.
033 * Particularly useful for creating mail attachments from local content,
034 * where JavaMail needs to be able to read the stream multiple times.
035 *
036 * @author Juergen Hoeller
037 * @author Sam Brannen
038 * @since 1.2.3
039 * @see java.io.ByteArrayInputStream
040 * @see InputStreamResource
041 * @see org.springframework.mail.javamail.MimeMessageHelper#addAttachment(String, InputStreamSource)
042 */
043public class ByteArrayResource extends AbstractResource {
044
045        private final byte[] byteArray;
046
047        private final String description;
048
049
050        /**
051         * Create a new {@code ByteArrayResource}.
052         * @param byteArray the byte array to wrap
053         */
054        public ByteArrayResource(byte[] byteArray) {
055                this(byteArray, "resource loaded from byte array");
056        }
057
058        /**
059         * Create a new {@code ByteArrayResource} with a description.
060         * @param byteArray the byte array to wrap
061         * @param description where the byte array comes from
062         */
063        public ByteArrayResource(byte[] byteArray, @Nullable String description) {
064                Assert.notNull(byteArray, "Byte array must not be null");
065                this.byteArray = byteArray;
066                this.description = (description != null ? description : "");
067        }
068
069
070        /**
071         * Return the underlying byte array.
072         */
073        public final byte[] getByteArray() {
074                return this.byteArray;
075        }
076
077        /**
078         * This implementation always returns {@code true}.
079         */
080        @Override
081        public boolean exists() {
082                return true;
083        }
084
085        /**
086         * This implementation returns the length of the underlying byte array.
087         */
088        @Override
089        public long contentLength() {
090                return this.byteArray.length;
091        }
092
093        /**
094         * This implementation returns a ByteArrayInputStream for the
095         * underlying byte array.
096         * @see java.io.ByteArrayInputStream
097         */
098        @Override
099        public InputStream getInputStream() throws IOException {
100                return new ByteArrayInputStream(this.byteArray);
101        }
102
103        /**
104         * This implementation returns a description that includes the passed-in
105         * {@code description}, if any.
106         */
107        @Override
108        public String getDescription() {
109                return "Byte array resource [" + this.description + "]";
110        }
111
112
113        /**
114         * This implementation compares the underlying byte array.
115         * @see java.util.Arrays#equals(byte[], byte[])
116         */
117        @Override
118        public boolean equals(@Nullable Object other) {
119                return (this == other || (other instanceof ByteArrayResource &&
120                                Arrays.equals(((ByteArrayResource) other).byteArray, this.byteArray)));
121        }
122
123        /**
124         * This implementation returns the hash code based on the
125         * underlying byte array.
126         */
127        @Override
128        public int hashCode() {
129                return (byte[].class.hashCode() * 29 * this.byteArray.length);
130        }
131
132}