1bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor/* 21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2007 The Guava Authors 3bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 4bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Licensed under the Apache License, Version 2.0 (the "License"); 5bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * you may not use this file except in compliance with the License. 6bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * You may obtain a copy of the License at 7bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 8bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * http://www.apache.org/licenses/LICENSE-2.0 9bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 10bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Unless required by applicable law or agreed to in writing, software 11bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * distributed under the License is distributed on an "AS IS" BASIS, 12bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * See the License for the specific language governing permissions and 14bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * limitations under the License. 15bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 16bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 17bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorpackage com.google.common.io; 18bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 19bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport static com.google.common.base.Preconditions.checkArgument; 20bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport static com.google.common.base.Preconditions.checkNotNull; 21bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.Beta; 237dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.base.Charsets; 243ecfa412eddc4b084663f38d562537b86b9734d5Paul Duffinimport com.google.common.base.MoreObjects; 250888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport com.google.common.collect.Lists; 261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 27bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.io.IOException; 28bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.io.InputStream; 29bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.io.OutputStream; 30bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.net.URL; 31bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.nio.charset.Charset; 32bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorimport java.util.List; 33bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 34bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor/** 35bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Provides utility methods for working with resources in the classpath. 361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Note that even though these methods use {@link URL} parameters, they 37bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * are usually not appropriate for HTTP or other non-classpath resources. 38bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 39bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * <p>All method parameters must be non-null unless documented otherwise. 40bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 41bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @author Chris Nokleberg 42bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @author Ben Yu 437dd252788645e940eada959bdde927426e2531c9Paul Duffin * @author Colin Decker 441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 1.0 45bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@Beta 47bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnorpublic final class Resources { 481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private Resources() {} 49bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 50bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 517dd252788645e940eada959bdde927426e2531c9Paul Duffin * Returns a {@link ByteSource} that reads from the given URL. 527dd252788645e940eada959bdde927426e2531c9Paul Duffin * 537dd252788645e940eada959bdde927426e2531c9Paul Duffin * @since 14.0 547dd252788645e940eada959bdde927426e2531c9Paul Duffin */ 557dd252788645e940eada959bdde927426e2531c9Paul Duffin public static ByteSource asByteSource(URL url) { 567dd252788645e940eada959bdde927426e2531c9Paul Duffin return new UrlByteSource(url); 577dd252788645e940eada959bdde927426e2531c9Paul Duffin } 587dd252788645e940eada959bdde927426e2531c9Paul Duffin 597dd252788645e940eada959bdde927426e2531c9Paul Duffin /** 607dd252788645e940eada959bdde927426e2531c9Paul Duffin * A byte source that reads from a URL using {@link URL#openStream()}. 617dd252788645e940eada959bdde927426e2531c9Paul Duffin */ 627dd252788645e940eada959bdde927426e2531c9Paul Duffin private static final class UrlByteSource extends ByteSource { 637dd252788645e940eada959bdde927426e2531c9Paul Duffin 647dd252788645e940eada959bdde927426e2531c9Paul Duffin private final URL url; 657dd252788645e940eada959bdde927426e2531c9Paul Duffin 667dd252788645e940eada959bdde927426e2531c9Paul Duffin private UrlByteSource(URL url) { 677dd252788645e940eada959bdde927426e2531c9Paul Duffin this.url = checkNotNull(url); 687dd252788645e940eada959bdde927426e2531c9Paul Duffin } 697dd252788645e940eada959bdde927426e2531c9Paul Duffin 707dd252788645e940eada959bdde927426e2531c9Paul Duffin @Override 717dd252788645e940eada959bdde927426e2531c9Paul Duffin public InputStream openStream() throws IOException { 727dd252788645e940eada959bdde927426e2531c9Paul Duffin return url.openStream(); 737dd252788645e940eada959bdde927426e2531c9Paul Duffin } 747dd252788645e940eada959bdde927426e2531c9Paul Duffin 757dd252788645e940eada959bdde927426e2531c9Paul Duffin @Override 767dd252788645e940eada959bdde927426e2531c9Paul Duffin public String toString() { 770888a09821a98ac0680fad765217302858e70fa4Paul Duffin return "Resources.asByteSource(" + url + ")"; 787dd252788645e940eada959bdde927426e2531c9Paul Duffin } 79bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 80bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 81bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 820888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Returns a {@link CharSource} that reads from the given URL using the given 830888a09821a98ac0680fad765217302858e70fa4Paul Duffin * character set. 847dd252788645e940eada959bdde927426e2531c9Paul Duffin * 857dd252788645e940eada959bdde927426e2531c9Paul Duffin * @since 14.0 867dd252788645e940eada959bdde927426e2531c9Paul Duffin */ 877dd252788645e940eada959bdde927426e2531c9Paul Duffin public static CharSource asCharSource(URL url, Charset charset) { 887dd252788645e940eada959bdde927426e2531c9Paul Duffin return asByteSource(url).asCharSource(charset); 89bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 90bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 91bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 92bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Reads all bytes from a URL into a byte array. 93bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 94bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param url the URL to read from 95bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @return a byte array containing all the bytes from the URL 96bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @throws IOException if an I/O error occurs 97bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 98bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public static byte[] toByteArray(URL url) throws IOException { 997dd252788645e940eada959bdde927426e2531c9Paul Duffin return asByteSource(url).read(); 100bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 101bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 102bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 103bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Reads all characters from a URL into a {@link String}, using the given 104bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * character set. 105bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 106bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param url the URL to read from 1077dd252788645e940eada959bdde927426e2531c9Paul Duffin * @param charset the charset used to decode the input stream; see {@link 1087dd252788645e940eada959bdde927426e2531c9Paul Duffin * Charsets} for helpful predefined constants 109bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @return a string containing all the characters from the URL 110bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @throws IOException if an I/O error occurs. 111bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 112bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public static String toString(URL url, Charset charset) throws IOException { 1137dd252788645e940eada959bdde927426e2531c9Paul Duffin return asCharSource(url, charset).read(); 114bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 115bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 116bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 117bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Streams lines from a URL, stopping when our callback returns false, or we 118bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * have read all of the lines. 119bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 120bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param url the URL to read from 1217dd252788645e940eada959bdde927426e2531c9Paul Duffin * @param charset the charset used to decode the input stream; see {@link 1227dd252788645e940eada959bdde927426e2531c9Paul Duffin * Charsets} for helpful predefined constants 123bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param callback the LineProcessor to use to handle the lines 124bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @return the output of processing the lines 125bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @throws IOException if an I/O error occurs 126bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 1270888a09821a98ac0680fad765217302858e70fa4Paul Duffin public static <T> T readLines(URL url, Charset charset, 1280888a09821a98ac0680fad765217302858e70fa4Paul Duffin LineProcessor<T> callback) throws IOException { 1293ecfa412eddc4b084663f38d562537b86b9734d5Paul Duffin return asCharSource(url, charset).readLines(callback); 130bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 131bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 132bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 133bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Reads all of the lines from a URL. The lines do not include 134bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * line-termination characters, but do include other leading and trailing 135bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * whitespace. 136bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 1370888a09821a98ac0680fad765217302858e70fa4Paul Duffin * <p>This method returns a mutable {@code List}. For an 1380888a09821a98ac0680fad765217302858e70fa4Paul Duffin * {@code ImmutableList}, use 1390888a09821a98ac0680fad765217302858e70fa4Paul Duffin * {@code Resources.asCharSource(url, charset).readLines()}. 1400888a09821a98ac0680fad765217302858e70fa4Paul Duffin * 141bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param url the URL to read from 1427dd252788645e940eada959bdde927426e2531c9Paul Duffin * @param charset the charset used to decode the input stream; see {@link 1437dd252788645e940eada959bdde927426e2531c9Paul Duffin * Charsets} for helpful predefined constants 144bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @return a mutable {@link List} containing all the lines 145bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @throws IOException if an I/O error occurs 146bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 1470888a09821a98ac0680fad765217302858e70fa4Paul Duffin public static List<String> readLines(URL url, Charset charset) 1480888a09821a98ac0680fad765217302858e70fa4Paul Duffin throws IOException { 1490888a09821a98ac0680fad765217302858e70fa4Paul Duffin // don't use asCharSource(url, charset).readLines() because that returns 1500888a09821a98ac0680fad765217302858e70fa4Paul Duffin // an immutable list, which would change the behavior of this method 1510888a09821a98ac0680fad765217302858e70fa4Paul Duffin return readLines(url, charset, new LineProcessor<List<String>>() { 1520888a09821a98ac0680fad765217302858e70fa4Paul Duffin final List<String> result = Lists.newArrayList(); 1530888a09821a98ac0680fad765217302858e70fa4Paul Duffin 1540888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override 1550888a09821a98ac0680fad765217302858e70fa4Paul Duffin public boolean processLine(String line) { 1560888a09821a98ac0680fad765217302858e70fa4Paul Duffin result.add(line); 1570888a09821a98ac0680fad765217302858e70fa4Paul Duffin return true; 1580888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1590888a09821a98ac0680fad765217302858e70fa4Paul Duffin 1600888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override 1610888a09821a98ac0680fad765217302858e70fa4Paul Duffin public List<String> getResult() { 1620888a09821a98ac0680fad765217302858e70fa4Paul Duffin return result; 1630888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 1640888a09821a98ac0680fad765217302858e70fa4Paul Duffin }); 165bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 166bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 167bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 168bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Copies all bytes from a URL to an output stream. 169bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 170bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param from the URL to read from 171bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @param to the output stream 172bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @throws IOException if an I/O error occurs 173bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 174bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public static void copy(URL from, OutputStream to) throws IOException { 1757dd252788645e940eada959bdde927426e2531c9Paul Duffin asByteSource(from).copyTo(to); 176bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 1770888a09821a98ac0680fad765217302858e70fa4Paul Duffin 178bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 179bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * Returns a {@code URL} pointing to {@code resourceName} if the resource is 1800888a09821a98ac0680fad765217302858e70fa4Paul Duffin * found using the {@linkplain Thread#getContextClassLoader() context class 1810888a09821a98ac0680fad765217302858e70fa4Paul Duffin * loader}. In simple environments, the context class loader will find 1820888a09821a98ac0680fad765217302858e70fa4Paul Duffin * resources from the class path. In environments where different threads can 1830888a09821a98ac0680fad765217302858e70fa4Paul Duffin * have different class loaders, for example app servers, the context class 1840888a09821a98ac0680fad765217302858e70fa4Paul Duffin * loader will typically have been set to an appropriate loader for the 1850888a09821a98ac0680fad765217302858e70fa4Paul Duffin * current thread. 1860888a09821a98ac0680fad765217302858e70fa4Paul Duffin * 1870888a09821a98ac0680fad765217302858e70fa4Paul Duffin * <p>In the unusual case where the context class loader is null, the class 1880888a09821a98ac0680fad765217302858e70fa4Paul Duffin * loader that loaded this class ({@code Resources}) will be used instead. 189bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 1900888a09821a98ac0680fad765217302858e70fa4Paul Duffin * @throws IllegalArgumentException if the resource is not found 191bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 192bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public static URL getResource(String resourceName) { 1933ecfa412eddc4b084663f38d562537b86b9734d5Paul Duffin ClassLoader loader = MoreObjects.firstNonNull( 1940888a09821a98ac0680fad765217302858e70fa4Paul Duffin Thread.currentThread().getContextClassLoader(), 1950888a09821a98ac0680fad765217302858e70fa4Paul Duffin Resources.class.getClassLoader()); 1960888a09821a98ac0680fad765217302858e70fa4Paul Duffin URL url = loader.getResource(resourceName); 197bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor checkArgument(url != null, "resource %s not found.", resourceName); 198bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return url; 199bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 200bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor 201bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor /** 2020888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Given a {@code resourceName} that is relative to {@code contextClass}, 2030888a09821a98ac0680fad765217302858e70fa4Paul Duffin * returns a {@code URL} pointing to the named resource. 204bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * 2050888a09821a98ac0680fad765217302858e70fa4Paul Duffin * @throws IllegalArgumentException if the resource is not found 206bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor */ 207bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor public static URL getResource(Class<?> contextClass, String resourceName) { 208bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor URL url = contextClass.getResource(resourceName); 2090888a09821a98ac0680fad765217302858e70fa4Paul Duffin checkArgument(url != null, "resource %s relative to %s not found.", 2100888a09821a98ac0680fad765217302858e70fa4Paul Duffin resourceName, contextClass.getName()); 211bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor return url; 212bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor } 213bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor} 214