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.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      public static final class Util {
74  
75          /**
76           * Returns a new {@code ByteSource} instance representing the specified byte array.
77           *
78           * @param bytes the bytes to represent as a {@code ByteSource} instance.
79           * @return a new {@code ByteSource} instance representing the specified byte array.
80           */
81          public static ByteSource bytes(byte[] bytes) {
82              return new SimpleByteSource(bytes);
83          }
84  
85          /**
86           * Returns a new {@code ByteSource} instance representing the specified character array's bytes.  The byte
87           * array is obtained assuming {@code UTF-8} encoding.
88           *
89           * @param chars the character array to represent as a {@code ByteSource} instance.
90           * @return a new {@code ByteSource} instance representing the specified character array's bytes.
91           */
92          public static ByteSource bytes(char[] chars) {
93              return new SimpleByteSource(chars);
94          }
95  
96          /**
97           * Returns a new {@code ByteSource} instance representing the specified string's bytes.  The byte
98           * array is obtained assuming {@code UTF-8} encoding.
99           *
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../../../../org/apache/shiro/util/ByteSource.html#ByteSource">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 }