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 */ 019package org.apache.shiro.util; 020 021import java.io.File; 022import 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 */ 030public 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}