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;
024
025import java.io.IOException;
026import java.io.InputStream;
027import java.io.InputStreamReader;
028import java.io.OutputStream;
029import java.net.URL;
030import java.nio.charset.Charset;
031import java.util.List;
032
033/**
034 * Provides utility methods for working with resources in the classpath.
035 * Note that even though these methods use {@link URL} parameters, they
036 * are usually not appropriate for HTTP or other non-classpath resources.
037 *
038 * <p>All method parameters must be non-null unless documented otherwise.
039 *
040 * @author Chris Nokleberg
041 * @author Ben Yu
042 * @since 1.0
043 */
044@Beta
045public final class Resources {
046  private Resources() {}
047
048  /**
049   * Returns a factory that will supply instances of {@link InputStream} that
050   * read from the given URL.
051   *
052   * @param url the URL to read from
053   * @return the factory
054   */
055  public static InputSupplier<InputStream> newInputStreamSupplier(
056      final URL url) {
057    checkNotNull(url);
058    return new InputSupplier<InputStream>() {
059      @Override
060      public InputStream getInput() throws IOException {
061        return url.openStream();
062      }
063    };
064  }
065
066  /**
067   * Returns a factory that will supply instances of
068   * {@link InputStreamReader} that read a URL using the given character set.
069   *
070   * @param url the URL to read from
071   * @param charset the charset used to decode the input stream; see {@link
072   *     Charsets} for helpful predefined constants
073   * @return the factory
074   */
075  public static InputSupplier<InputStreamReader> newReaderSupplier(
076      URL url, Charset charset) {
077    return CharStreams.newReaderSupplier(newInputStreamSupplier(url), charset);
078  }
079
080  /**
081   * Reads all bytes from a URL into a byte array.
082   *
083   * @param url the URL to read from
084   * @return a byte array containing all the bytes from the URL
085   * @throws IOException if an I/O error occurs
086   */
087  public static byte[] toByteArray(URL url) throws IOException {
088    return ByteStreams.toByteArray(newInputStreamSupplier(url));
089  }
090
091  /**
092   * Reads all characters from a URL into a {@link String}, using the given
093   * character set.
094   *
095   * @param url the URL to read from
096   * @param charset the charset used to decode the input stream; see {@link
097   *     Charsets} for helpful predefined constants
098   * @return a string containing all the characters from the URL
099   * @throws IOException if an I/O error occurs.
100   */
101  public static String toString(URL url, Charset charset) throws IOException {
102    return CharStreams.toString(newReaderSupplier(url, charset));
103  }
104
105  /**
106   * Streams lines from a URL, stopping when our callback returns false, or we
107   * have read all of the lines.
108   *
109   * @param url the URL to read from
110   * @param charset the charset used to decode the input stream; see {@link
111   *     Charsets} for helpful predefined constants
112   * @param callback the LineProcessor to use to handle the lines
113   * @return the output of processing the lines
114   * @throws IOException if an I/O error occurs
115   */
116  public static <T> T readLines(URL url, Charset charset,
117      LineProcessor<T> callback) throws IOException {
118    return CharStreams.readLines(newReaderSupplier(url, charset), callback);
119  }
120
121  /**
122   * Reads all of the lines from a URL. The lines do not include
123   * line-termination characters, but do include other leading and trailing
124   * whitespace.
125   *
126   * @param url the URL to read from
127   * @param charset the charset used to decode the input stream; see {@link
128   *     Charsets} for helpful predefined constants
129   * @return a mutable {@link List} containing all the lines
130   * @throws IOException if an I/O error occurs
131   */
132  public static List<String> readLines(URL url, Charset charset)
133      throws IOException {
134    return CharStreams.readLines(newReaderSupplier(url, charset));
135  }
136
137  /**
138   * Copies all bytes from a URL to an output stream.
139   *
140   * @param from the URL to read from
141   * @param to the output stream
142   * @throws IOException if an I/O error occurs
143   */
144  public static void copy(URL from, OutputStream to) throws IOException {
145    ByteStreams.copy(newInputStreamSupplier(from), to);
146  }
147  
148  /**
149   * Returns a {@code URL} pointing to {@code resourceName} if the resource is
150   * found in the class path. {@code Resources.class.getClassLoader()} is used
151   * to locate the resource.
152   * 
153   * @throws IllegalArgumentException if resource is not found
154   */
155  public static URL getResource(String resourceName) {
156    URL url = Resources.class.getClassLoader().getResource(resourceName);
157    checkArgument(url != null, "resource %s not found.", resourceName);
158    return url;
159  }
160
161  /**
162   * Returns a {@code URL} pointing to {@code resourceName} that is relative to
163   * {@code contextClass}, if the resource is found in the class path. 
164   * 
165   * @throws IllegalArgumentException if resource is not found
166   */
167  public static URL getResource(Class<?> contextClass, String resourceName) {
168    URL url = contextClass.getResource(resourceName);
169    checkArgument(url != null, "resource %s relative to %s not found.",
170        resourceName, contextClass.getName());
171    return url;
172  }
173}