001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019 package org.apache.shiro.util;
020
021 import java.io.File;
022 import java.io.InputStream;
023
024 /**
025 * A {@code ByteSource} wraps a byte array and provides additional encoding operations. Most users will find the
026 * {@link Util} inner class sufficient to construct ByteSource instances.
027 *
028 * @since 1.0
029 */
030 public interface ByteSource {
031
032 /**
033 * Returns the wrapped byte array.
034 *
035 * @return the wrapped byte array.
036 */
037 byte[] getBytes();
038
039 /**
040 * Returns the <a href="http://en.wikipedia.org/wiki/Hexadecimal">Hex</a>-formatted String representation of the
041 * underlying wrapped byte array.
042 *
043 * @return the <a href="http://en.wikipedia.org/wiki/Hexadecimal">Hex</a>-formatted String representation of the
044 * underlying wrapped byte array.
045 */
046 String toHex();
047
048 /**
049 * Returns the <a href="http://en.wikipedia.org/wiki/Base64">Base 64</a>-formatted String representation of the
050 * underlying wrapped byte array.
051 *
052 * @return the <a href="http://en.wikipedia.org/wiki/Base64">Base 64</a>-formatted String representation of the
053 * underlying wrapped byte array.
054 */
055 String toBase64();
056
057 /**
058 * Returns {@code true} if the underlying wrapped byte array is null or empty (zero length), {@code false}
059 * otherwise.
060 *
061 * @return {@code true} if the underlying wrapped byte array is null or empty (zero length), {@code false}
062 * otherwise.
063 * @since 1.2
064 */
065 boolean isEmpty();
066
067 /**
068 * Utility class that can construct ByteSource instances. This is slightly nicer than needing to know the
069 * {@code ByteSource} implementation class to use.
070 *
071 * @since 1.2
072 */
073 public static final class Util {
074
075 /**
076 * Returns a new {@code ByteSource} instance representing the specified byte array.
077 *
078 * @param bytes the bytes to represent as a {@code ByteSource} instance.
079 * @return a new {@code ByteSource} instance representing the specified byte array.
080 */
081 public static ByteSource bytes(byte[] bytes) {
082 return new SimpleByteSource(bytes);
083 }
084
085 /**
086 * Returns a new {@code ByteSource} instance representing the specified character array's bytes. The byte
087 * array is obtained assuming {@code UTF-8} encoding.
088 *
089 * @param chars the character array to represent as a {@code ByteSource} instance.
090 * @return a new {@code ByteSource} instance representing the specified character array's bytes.
091 */
092 public static ByteSource bytes(char[] chars) {
093 return new SimpleByteSource(chars);
094 }
095
096 /**
097 * Returns a new {@code ByteSource} instance representing the specified string's bytes. The byte
098 * array is obtained assuming {@code UTF-8} encoding.
099 *
100 * @param string the string to represent as a {@code ByteSource} instance.
101 * @return a new {@code ByteSource} instance representing the specified string's bytes.
102 */
103 public static ByteSource bytes(String string) {
104 return new SimpleByteSource(string);
105 }
106
107 /**
108 * Returns a new {@code ByteSource} instance representing the specified ByteSource.
109 *
110 * @param source the ByteSource to represent as a new {@code ByteSource} instance.
111 * @return a new {@code ByteSource} instance representing the specified ByteSource.
112 */
113 public static ByteSource bytes(ByteSource source) {
114 return new SimpleByteSource(source);
115 }
116
117 /**
118 * Returns a new {@code ByteSource} instance representing the specified File's bytes.
119 *
120 * @param file the file to represent as a {@code ByteSource} instance.
121 * @return a new {@code ByteSource} instance representing the specified File's bytes.
122 */
123 public static ByteSource bytes(File file) {
124 return new SimpleByteSource(file);
125 }
126
127 /**
128 * Returns a new {@code ByteSource} instance representing the specified InputStream's bytes.
129 *
130 * @param stream the InputStream to represent as a {@code ByteSource} instance.
131 * @return a new {@code ByteSource} instance representing the specified InputStream's bytes.
132 */
133 public static ByteSource bytes(InputStream stream) {
134 return new SimpleByteSource(stream);
135 }
136
137 /**
138 * Returns {@code true} if the specified object can be easily represented as a {@code ByteSource} using
139 * the {@link ByteSource.Util}'s default heuristics, {@code false} otherwise.
140 * <p/>
141 * This implementation merely returns {@link SimpleByteSource}.{@link SimpleByteSource#isCompatible(Object) isCompatible(source)}.
142 *
143 * @param source the object to test to see if it can be easily converted to ByteSource instances using default
144 * heuristics.
145 * @return {@code true} if the specified object can be easily represented as a {@code ByteSource} using
146 * the {@link ByteSource.Util}'s default heuristics, {@code false} otherwise.
147 */
148 public static boolean isCompatible(Object source) {
149 return SimpleByteSource.isCompatible(source);
150 }
151
152 /**
153 * Returns a {@code ByteSource} instance representing the specified byte source argument. If the argument
154 * <em>cannot</em> be easily converted to bytes (as is indicated by the {@link #isCompatible(Object)} JavaDoc),
155 * this method will throw an {@link IllegalArgumentException}.
156 *
157 * @param source the byte-backed instance that should be represented as a {@code ByteSource} instance.
158 * @return a {@code ByteSource} instance representing the specified byte source argument.
159 * @throws IllegalArgumentException if the argument <em>cannot</em> be easily converted to bytes
160 * (as indicated by the {@link #isCompatible(Object)} JavaDoc)
161 */
162 public static ByteSource bytes(Object source) throws IllegalArgumentException {
163 if (source == null) {
164 return null;
165 }
166 if (!isCompatible(source)) {
167 String msg = "Unable to heuristically acquire bytes for object of type [" +
168 source.getClass().getName() + "]. If this type is indeed a byte-backed data type, you might " +
169 "want to write your own ByteSource implementation to extract its bytes explicitly.";
170 throw new IllegalArgumentException(msg);
171 }
172 if (source instanceof byte[]) {
173 return bytes((byte[]) source);
174 } else if (source instanceof ByteSource) {
175 return (ByteSource) source;
176 } else if (source instanceof char[]) {
177 return bytes((char[]) source);
178 } else if (source instanceof String) {
179 return bytes((String) source);
180 } else if (source instanceof File) {
181 return bytes((File) source);
182 } else if (source instanceof InputStream) {
183 return bytes((InputStream) source);
184 } else {
185 throw new IllegalStateException("Encountered unexpected byte source. This is a bug - please notify " +
186 "the Shiro developer list asap (the isCompatible implementation does not reflect this " +
187 "method's implementation).");
188 }
189 }
190 }
191 }