View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.shiro.lang.util;
20  
21  import java.io.File;
22  import java.io.InputStream;
23  
24  /**
25   * A {@code ByteSource} wraps a byte array and provides additional encoding operations.  Most users will find the
26   * {@link Util} inner class sufficient to construct ByteSource instances.
27   *
28   * @since 1.0
29   */
30  public interface ByteSource {
31  
32      /**
33       * Returns the wrapped byte array.
34       *
35       * @return the wrapped byte array.
36       */
37      byte[] getBytes();
38  
39      /**
40       * Returns the <a href="http://en.wikipedia.org/wiki/Hexadecimal">Hex</a>-formatted String representation of the
41       * underlying wrapped byte array.
42       *
43       * @return the <a href="http://en.wikipedia.org/wiki/Hexadecimal">Hex</a>-formatted String representation of the
44       * underlying wrapped byte array.
45       */
46      String toHex();
47  
48      /**
49       * Returns the <a href="http://en.wikipedia.org/wiki/Base64">Base 64</a>-formatted String representation of the
50       * underlying wrapped byte array.
51       *
52       * @return the <a href="http://en.wikipedia.org/wiki/Base64">Base 64</a>-formatted String representation of the
53       * underlying wrapped byte array.
54       */
55      String toBase64();
56  
57      /**
58       * Returns {@code true} if the underlying wrapped byte array is null or empty (zero length), {@code false}
59       * otherwise.
60       *
61       * @return {@code true} if the underlying wrapped byte array is null or empty (zero length), {@code false}
62       * otherwise.
63       * @since 1.2
64       */
65      boolean isEmpty();
66  
67      /**
68       * Utility class that can construct ByteSource instances.  This is slightly nicer than needing to know the
69       * {@code ByteSource} implementation class to use.
70       *
71       * @since 1.2
72       */
73      final class Util {
74  
75          private Util() {
76          }
77  
78          /**
79           * Returns a new {@code ByteSource} instance representing the specified byte array.
80           *
81           * @param bytes the bytes to represent as a {@code ByteSource} instance.
82           * @return a new {@code ByteSource} instance representing the specified byte array.
83           */
84          public static ByteSource bytes(byte[] bytes) {
85              return new SimpleByteSource(bytes);
86          }
87  
88          /**
89           * Returns a new {@code ByteSource} instance representing the specified character array's bytes.  The byte
90           * array is obtained assuming {@code UTF-8} encoding.
91           *
92           * @param chars the character array to represent as a {@code ByteSource} instance.
93           * @return a new {@code ByteSource} instance representing the specified character array's bytes.
94           */
95          public static ByteSource bytes(char[] chars) {
96              return new SimpleByteSource(chars);
97          }
98  
99          /**
100          * Returns a new {@code ByteSource} instance representing the specified string's bytes.  The byte
101          * array is obtained assuming {@code UTF-8} encoding.
102          *
103          * @param string the string to represent as a {@code ByteSource} instance.
104          * @return a new {@code ByteSource} instance representing the specified string's bytes.
105          */
106         public static ByteSource bytes(String string) {
107             return new SimpleByteSource(string);
108         }
109 
110         /**
111          * Returns a new {@code ByteSource} instance representing the specified ByteSource.
112          *
113          * @param source the ByteSource to represent as a new {@code ByteSource} instance.
114          * @return a new {@code ByteSource} instance representing the specified ByteSource.
115          */
116         public static ByteSource bytes(ByteSource source) {
117             return new SimpleByteSource(source);
118         }
119 
120         /**
121          * Returns a new {@code ByteSource} instance representing the specified File's bytes.
122          *
123          * @param file the file to represent as a {@code ByteSource} instance.
124          * @return a new {@code ByteSource} instance representing the specified File's bytes.
125          */
126         public static ByteSource bytes(File file) {
127             return new SimpleByteSource(file);
128         }
129 
130         /**
131          * Returns a new {@code ByteSource} instance representing the specified InputStream's bytes.
132          *
133          * @param stream the InputStream to represent as a {@code ByteSource} instance.
134          * @return a new {@code ByteSource} instance representing the specified InputStream's bytes.
135          */
136         public static ByteSource bytes(InputStream stream) {
137             return new SimpleByteSource(stream);
138         }
139 
140         /**
141          * Returns {@code true} if the specified object can be easily represented as a {@code ByteSource} using
142          * the {@link ByteSource.Util}'s default heuristics, {@code false} otherwise.
143          * <p/>
144          * This implementation merely returns {@link SimpleByteSource}
145          * .{@link SimpleByteSource#isCompatible(Object) isCompatible(source)}.
146          *
147          * @param source the object to test to see if it can be easily converted to ByteSource instances using default
148          *               heuristics.
149          * @return {@code true} if the specified object can be easily represented as a {@code ByteSource} using
150          * the {@link ByteSource.Util}'s default heuristics, {@code false} otherwise.
151          */
152         public static boolean isCompatible(Object source) {
153             return SimpleByteSource.isCompatible(source);
154         }
155 
156         /**
157          * Returns a {@code ByteSource} instance representing the specified byte source argument.  If the argument
158          * <em>cannot</em> be easily converted to bytes (as is indicated by the {@link #isCompatible(Object)} JavaDoc),
159          * this method will throw an {@link IllegalArgumentException}.
160          *
161          * @param source the byte-backed instance that should be represented as a {@code ByteSource} instance.
162          * @return a {@code ByteSource} instance representing the specified byte source argument.
163          * @throws IllegalArgumentException if the argument <em>cannot</em> be easily converted to bytes
164          *                                  (as indicated by the {@link #isCompatible(Object)} JavaDoc)
165          */
166         public static ByteSource bytes(Object source) throws IllegalArgumentException {
167             if (source == null) {
168                 return null;
169             }
170             if (!isCompatible(source)) {
171                 String msg = "Unable to heuristically acquire bytes for object of type ["
172                         + source.getClass().getName() + "].  If this type is indeed a byte-backed data type, you might "
173                         + "want to write your own ByteSource implementation to extract its bytes explicitly.";
174                 throw new IllegalArgumentException(msg);
175             }
176             if (source instanceof byte[]) {
177                 return bytes((byte[]) source);
178             } else if (source instanceof ByteSource) {
179                 return (ByteSource) source;
180             } else if (source instanceof char[]) {
181                 return bytes((char[]) source);
182             } else if (source instanceof String) {
183                 return bytes((String) source);
184             } else if (source instanceof File) {
185                 return bytes((File) source);
186             } else if (source instanceof InputStream) {
187                 return bytes((InputStream) source);
188             } else {
189                 throw new IllegalStateException("Encountered unexpected byte source.  This is a bug - please notify "
190                         + "the Shiro developer list asap (the isCompatible implementation does not reflect this "
191                         + "method's implementation).");
192             }
193         }
194     }
195 }