001/* 002 * Copyright (C) 2007 The Guava 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 * http://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 com.google.common.io; 018 019import static com.google.common.base.Preconditions.checkArgument; 020import static com.google.common.base.Preconditions.checkNotNull; 021 022import com.google.common.annotations.Beta; 023import com.google.common.base.Charsets; 024import com.google.common.base.Objects; 025import com.google.common.collect.Lists; 026 027import java.io.IOException; 028import java.io.InputStream; 029import java.io.InputStreamReader; 030import java.io.OutputStream; 031import java.net.URL; 032import java.nio.charset.Charset; 033import java.util.List; 034 035/** 036 * Provides utility methods for working with resources in the classpath. 037 * Note that even though these methods use {@link URL} parameters, they 038 * are usually not appropriate for HTTP or other non-classpath resources. 039 * 040 * <p>All method parameters must be non-null unless documented otherwise. 041 * 042 * @author Chris Nokleberg 043 * @author Ben Yu 044 * @author Colin Decker 045 * @since 1.0 046 */ 047@Beta 048public final class Resources { 049 private Resources() {} 050 051 /** 052 * Returns a factory that will supply instances of {@link InputStream} that 053 * read from the given URL. 054 * 055 * @param url the URL to read from 056 * @return the factory 057 * @deprecated Use {@link #asByteSource(URL)} instead. This method is 058 * scheduled for removal in Guava 18.0. 059 */ 060 @Deprecated 061 public static InputSupplier<InputStream> newInputStreamSupplier(URL url) { 062 return ByteStreams.asInputSupplier(asByteSource(url)); 063 } 064 065 /** 066 * Returns a {@link ByteSource} that reads from the given URL. 067 * 068 * @since 14.0 069 */ 070 public static ByteSource asByteSource(URL url) { 071 return new UrlByteSource(url); 072 } 073 074 /** 075 * A byte source that reads from a URL using {@link URL#openStream()}. 076 */ 077 private static final class UrlByteSource extends ByteSource { 078 079 private final URL url; 080 081 private UrlByteSource(URL url) { 082 this.url = checkNotNull(url); 083 } 084 085 @Override 086 public InputStream openStream() throws IOException { 087 return url.openStream(); 088 } 089 090 @Override 091 public String toString() { 092 return "Resources.asByteSource(" + url + ")"; 093 } 094 } 095 096 /** 097 * Returns a factory that will supply instances of 098 * {@link InputStreamReader} that read a URL using the given character set. 099 * 100 * @param url the URL to read from 101 * @param charset the charset used to decode the input stream; see {@link 102 * Charsets} for helpful predefined constants 103 * @return the factory 104 * @deprecated Use {@link #asCharSource(URL, Charset)} instead. This method 105 * is scheduled for removal in Guava 18.0. 106 */ 107 @Deprecated 108 public static InputSupplier<InputStreamReader> newReaderSupplier( 109 URL url, Charset charset) { 110 return CharStreams.asInputSupplier(asCharSource(url, charset)); 111 } 112 113 /** 114 * Returns a {@link CharSource} that reads from the given URL using the given 115 * character set. 116 * 117 * @since 14.0 118 */ 119 public static CharSource asCharSource(URL url, Charset charset) { 120 return asByteSource(url).asCharSource(charset); 121 } 122 123 /** 124 * Reads all bytes from a URL into a byte array. 125 * 126 * @param url the URL to read from 127 * @return a byte array containing all the bytes from the URL 128 * @throws IOException if an I/O error occurs 129 */ 130 public static byte[] toByteArray(URL url) throws IOException { 131 return asByteSource(url).read(); 132 } 133 134 /** 135 * Reads all characters from a URL into a {@link String}, using the given 136 * character set. 137 * 138 * @param url the URL to read from 139 * @param charset the charset used to decode the input stream; see {@link 140 * Charsets} for helpful predefined constants 141 * @return a string containing all the characters from the URL 142 * @throws IOException if an I/O error occurs. 143 */ 144 public static String toString(URL url, Charset charset) throws IOException { 145 return asCharSource(url, charset).read(); 146 } 147 148 /** 149 * Streams lines from a URL, stopping when our callback returns false, or we 150 * have read all of the lines. 151 * 152 * @param url the URL to read from 153 * @param charset the charset used to decode the input stream; see {@link 154 * Charsets} for helpful predefined constants 155 * @param callback the LineProcessor to use to handle the lines 156 * @return the output of processing the lines 157 * @throws IOException if an I/O error occurs 158 */ 159 public static <T> T readLines(URL url, Charset charset, 160 LineProcessor<T> callback) throws IOException { 161 return CharStreams.readLines(newReaderSupplier(url, charset), callback); 162 } 163 164 /** 165 * Reads all of the lines from a URL. The lines do not include 166 * line-termination characters, but do include other leading and trailing 167 * whitespace. 168 * 169 * <p>This method returns a mutable {@code List}. For an 170 * {@code ImmutableList}, use 171 * {@code Resources.asCharSource(url, charset).readLines()}. 172 * 173 * @param url the URL to read from 174 * @param charset the charset used to decode the input stream; see {@link 175 * Charsets} for helpful predefined constants 176 * @return a mutable {@link List} containing all the lines 177 * @throws IOException if an I/O error occurs 178 */ 179 public static List<String> readLines(URL url, Charset charset) 180 throws IOException { 181 // don't use asCharSource(url, charset).readLines() because that returns 182 // an immutable list, which would change the behavior of this method 183 return readLines(url, charset, new LineProcessor<List<String>>() { 184 final List<String> result = Lists.newArrayList(); 185 186 @Override 187 public boolean processLine(String line) { 188 result.add(line); 189 return true; 190 } 191 192 @Override 193 public List<String> getResult() { 194 return result; 195 } 196 }); 197 } 198 199 /** 200 * Copies all bytes from a URL to an output stream. 201 * 202 * @param from the URL to read from 203 * @param to the output stream 204 * @throws IOException if an I/O error occurs 205 */ 206 public static void copy(URL from, OutputStream to) throws IOException { 207 asByteSource(from).copyTo(to); 208 } 209 210 /** 211 * Returns a {@code URL} pointing to {@code resourceName} if the resource is 212 * found using the {@linkplain Thread#getContextClassLoader() context class 213 * loader}. In simple environments, the context class loader will find 214 * resources from the class path. In environments where different threads can 215 * have different class loaders, for example app servers, the context class 216 * loader will typically have been set to an appropriate loader for the 217 * current thread. 218 * 219 * <p>In the unusual case where the context class loader is null, the class 220 * loader that loaded this class ({@code Resources}) will be used instead. 221 * 222 * @throws IllegalArgumentException if the resource is not found 223 */ 224 public static URL getResource(String resourceName) { 225 ClassLoader loader = Objects.firstNonNull( 226 Thread.currentThread().getContextClassLoader(), 227 Resources.class.getClassLoader()); 228 URL url = loader.getResource(resourceName); 229 checkArgument(url != null, "resource %s not found.", resourceName); 230 return url; 231 } 232 233 /** 234 * Given a {@code resourceName} that is relative to {@code contextClass}, 235 * returns a {@code URL} pointing to the named resource. 236 * 237 * @throws IllegalArgumentException if the resource is not found 238 */ 239 public static URL getResource(Class<?> contextClass, String resourceName) { 240 URL url = contextClass.getResource(resourceName); 241 checkArgument(url != null, "resource %s relative to %s not found.", 242 resourceName, contextClass.getName()); 243 return url; 244 } 245}