Home | History | Annotate | Download | only in io
      1 /*
      2  * Copyright (C) 2007 The Guava Authors
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.google.common.io;
     18 
     19 import static com.google.common.base.Preconditions.checkArgument;
     20 import static com.google.common.base.Preconditions.checkNotNull;
     21 
     22 import com.google.common.annotations.Beta;
     23 import com.google.common.base.Charsets;
     24 import com.google.common.base.MoreObjects;
     25 import com.google.common.collect.Lists;
     26 
     27 import java.io.IOException;
     28 import java.io.InputStream;
     29 import java.io.OutputStream;
     30 import java.net.URL;
     31 import java.nio.charset.Charset;
     32 import java.util.List;
     33 
     34 /**
     35  * Provides utility methods for working with resources in the classpath.
     36  * Note that even though these methods use {@link URL} parameters, they
     37  * are usually not appropriate for HTTP or other non-classpath resources.
     38  *
     39  * <p>All method parameters must be non-null unless documented otherwise.
     40  *
     41  * @author Chris Nokleberg
     42  * @author Ben Yu
     43  * @author Colin Decker
     44  * @since 1.0
     45  */
     46 @Beta
     47 public final class Resources {
     48   private Resources() {}
     49 
     50   /**
     51    * Returns a {@link ByteSource} that reads from the given URL.
     52    *
     53    * @since 14.0
     54    */
     55   public static ByteSource asByteSource(URL url) {
     56     return new UrlByteSource(url);
     57   }
     58 
     59   /**
     60    * A byte source that reads from a URL using {@link URL#openStream()}.
     61    */
     62   private static final class UrlByteSource extends ByteSource {
     63 
     64     private final URL url;
     65 
     66     private UrlByteSource(URL url) {
     67       this.url = checkNotNull(url);
     68     }
     69 
     70     @Override
     71     public InputStream openStream() throws IOException {
     72       return url.openStream();
     73     }
     74 
     75     @Override
     76     public String toString() {
     77       return "Resources.asByteSource(" + url + ")";
     78     }
     79   }
     80 
     81   /**
     82    * Returns a {@link CharSource} that reads from the given URL using the given
     83    * character set.
     84    *
     85    * @since 14.0
     86    */
     87   public static CharSource asCharSource(URL url, Charset charset) {
     88     return asByteSource(url).asCharSource(charset);
     89   }
     90 
     91   /**
     92    * Reads all bytes from a URL into a byte array.
     93    *
     94    * @param url the URL to read from
     95    * @return a byte array containing all the bytes from the URL
     96    * @throws IOException if an I/O error occurs
     97    */
     98   public static byte[] toByteArray(URL url) throws IOException {
     99     return asByteSource(url).read();
    100   }
    101 
    102   /**
    103    * Reads all characters from a URL into a {@link String}, using the given
    104    * character set.
    105    *
    106    * @param url the URL to read from
    107    * @param charset the charset used to decode the input stream; see {@link
    108    *     Charsets} for helpful predefined constants
    109    * @return a string containing all the characters from the URL
    110    * @throws IOException if an I/O error occurs.
    111    */
    112   public static String toString(URL url, Charset charset) throws IOException {
    113     return asCharSource(url, charset).read();
    114   }
    115 
    116   /**
    117    * Streams lines from a URL, stopping when our callback returns false, or we
    118    * have read all of the lines.
    119    *
    120    * @param url the URL to read from
    121    * @param charset the charset used to decode the input stream; see {@link
    122    *     Charsets} for helpful predefined constants
    123    * @param callback the LineProcessor to use to handle the lines
    124    * @return the output of processing the lines
    125    * @throws IOException if an I/O error occurs
    126    */
    127   public static <T> T readLines(URL url, Charset charset,
    128       LineProcessor<T> callback) throws IOException {
    129     return asCharSource(url, charset).readLines(callback);
    130   }
    131 
    132   /**
    133    * Reads all of the lines from a URL. The lines do not include
    134    * line-termination characters, but do include other leading and trailing
    135    * whitespace.
    136    *
    137    * <p>This method returns a mutable {@code List}. For an
    138    * {@code ImmutableList}, use
    139    * {@code Resources.asCharSource(url, charset).readLines()}.
    140    *
    141    * @param url the URL to read from
    142    * @param charset the charset used to decode the input stream; see {@link
    143    *     Charsets} for helpful predefined constants
    144    * @return a mutable {@link List} containing all the lines
    145    * @throws IOException if an I/O error occurs
    146    */
    147   public static List<String> readLines(URL url, Charset charset)
    148       throws IOException {
    149     // don't use asCharSource(url, charset).readLines() because that returns
    150     // an immutable list, which would change the behavior of this method
    151     return readLines(url, charset, new LineProcessor<List<String>>() {
    152       final List<String> result = Lists.newArrayList();
    153 
    154       @Override
    155       public boolean processLine(String line) {
    156         result.add(line);
    157         return true;
    158       }
    159 
    160       @Override
    161       public List<String> getResult() {
    162         return result;
    163       }
    164     });
    165   }
    166 
    167   /**
    168    * Copies all bytes from a URL to an output stream.
    169    *
    170    * @param from the URL to read from
    171    * @param to the output stream
    172    * @throws IOException if an I/O error occurs
    173    */
    174   public static void copy(URL from, OutputStream to) throws IOException {
    175     asByteSource(from).copyTo(to);
    176   }
    177 
    178   /**
    179    * Returns a {@code URL} pointing to {@code resourceName} if the resource is
    180    * found using the {@linkplain Thread#getContextClassLoader() context class
    181    * loader}. In simple environments, the context class loader will find
    182    * resources from the class path. In environments where different threads can
    183    * have different class loaders, for example app servers, the context class
    184    * loader will typically have been set to an appropriate loader for the
    185    * current thread.
    186    *
    187    * <p>In the unusual case where the context class loader is null, the class
    188    * loader that loaded this class ({@code Resources}) will be used instead.
    189    *
    190    * @throws IllegalArgumentException if the resource is not found
    191    */
    192   public static URL getResource(String resourceName) {
    193     ClassLoader loader = MoreObjects.firstNonNull(
    194         Thread.currentThread().getContextClassLoader(),
    195         Resources.class.getClassLoader());
    196     URL url = loader.getResource(resourceName);
    197     checkArgument(url != null, "resource %s not found.", resourceName);
    198     return url;
    199   }
    200 
    201   /**
    202    * Given a {@code resourceName} that is relative to {@code contextClass},
    203    * returns a {@code URL} pointing to the named resource.
    204    *
    205    * @throws IllegalArgumentException if the resource is not found
    206    */
    207   public static URL getResource(Class<?> contextClass, String resourceName) {
    208     URL url = contextClass.getResource(resourceName);
    209     checkArgument(url != null, "resource %s relative to %s not found.",
    210         resourceName, contextClass.getName());
    211     return url;
    212   }
    213 }
    214