001: /*
002: * Copyright 2002-2007 the original author or 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:
017: package org.springframework.util;
018:
019: import java.io.File;
020: import java.io.FileNotFoundException;
021: import java.net.MalformedURLException;
022: import java.net.URL;
023: import java.net.URLDecoder;
024:
025: /**
026: * Utility methods for resolving resource locations to files in the
027: * file system. Mainly for internal use within the framework.
028: *
029: * <p>Consider using Spring's Resource abstraction in the core package
030: * for handling all kinds of file resources in a uniform manner.
031: * {@link org.springframework.core.io.ResourceLoader}'s <code>getResource</code>
032: * method can resolve any location to a {@link org.springframework.core.io.Resource}
033: * object, which in turn allows to obtain a <code>java.io.File</code> in the
034: * file system through its <code>getFile()</code> method.
035: *
036: * <p>The main reason for these utility methods for resource location handling
037: * is to support {@link Log4jConfigurer}, which must be able to resolve
038: * resource locations <i>before the logging system has been initialized</i>.
039: * Spring' Resource abstraction in the core package, on the other hand,
040: * already expects the logging system to be available.
041: *
042: * @author Juergen Hoeller
043: * @since 1.1.5
044: * @see org.springframework.core.io.Resource
045: * @see org.springframework.core.io.ClassPathResource
046: * @see org.springframework.core.io.FileSystemResource
047: * @see org.springframework.core.io.UrlResource
048: * @see org.springframework.core.io.ResourceLoader
049: */
050: public abstract class ResourceUtils {
051:
052: /** Pseudo URL prefix for loading from the class path: "classpath:" */
053: public static final String CLASSPATH_URL_PREFIX = "classpath:";
054:
055: /** URL prefix for loading from the file system: "file:" */
056: public static final String FILE_URL_PREFIX = "file:";
057:
058: /** URL protocol for a file in the file system: "file" */
059: public static final String URL_PROTOCOL_FILE = "file";
060:
061: /** URL protocol for an entry from a jar file: "jar" */
062: public static final String URL_PROTOCOL_JAR = "jar";
063:
064: /** URL protocol for an entry from a zip file: "zip" */
065: public static final String URL_PROTOCOL_ZIP = "zip";
066:
067: /** URL protocol for an entry from a WebSphere jar file: "wsjar" */
068: public static final String URL_PROTOCOL_WSJAR = "wsjar";
069:
070: /** Separator between JAR URL and file path within the JAR */
071: public static final String JAR_URL_SEPARATOR = "!/";
072:
073: /**
074: * Return whether the given resource location is a URL:
075: * either a special "classpath" pseudo URL or a standard URL.
076: * @param resourceLocation the location String to check
077: * @return whether the location qualifies as a URL
078: * @see #CLASSPATH_URL_PREFIX
079: * @see java.net.URL
080: */
081: public static boolean isUrl(String resourceLocation) {
082: if (resourceLocation == null) {
083: return false;
084: }
085: if (resourceLocation.startsWith(CLASSPATH_URL_PREFIX)) {
086: return true;
087: }
088: try {
089: new URL(resourceLocation);
090: return true;
091: } catch (MalformedURLException ex) {
092: return false;
093: }
094: }
095:
096: /**
097: * Resolve the given resource location to a <code>java.net.URL</code>.
098: * <p>Does not check whether the URL actually exists; simply returns
099: * the URL that the given location would correspond to.
100: * @param resourceLocation the resource location to resolve: either a
101: * "classpath:" pseudo URL, a "file:" URL, or a plain file path
102: * @return a corresponding URL object
103: * @throws FileNotFoundException if the resource cannot be resolved to a URL
104: */
105: public static URL getURL(String resourceLocation)
106: throws FileNotFoundException {
107: Assert.notNull(resourceLocation,
108: "Resource location must not be null");
109: if (resourceLocation.startsWith(CLASSPATH_URL_PREFIX)) {
110: String path = resourceLocation
111: .substring(CLASSPATH_URL_PREFIX.length());
112: URL url = ClassUtils.getDefaultClassLoader().getResource(
113: path);
114: if (url == null) {
115: String description = "class path resource [" + path
116: + "]";
117: throw new FileNotFoundException(
118: description
119: + " cannot be resolved to URL because it does not exist");
120: }
121: return url;
122: }
123: try {
124: // try URL
125: return new URL(resourceLocation);
126: } catch (MalformedURLException ex) {
127: // no URL -> treat as file path
128: try {
129: return new URL(FILE_URL_PREFIX + resourceLocation);
130: } catch (MalformedURLException ex2) {
131: throw new FileNotFoundException(
132: "Resource location ["
133: + resourceLocation
134: + "] is neither a URL not a well-formed file path");
135: }
136: }
137: }
138:
139: /**
140: * Resolve the given resource location to a <code>java.io.File</code>,
141: * i.e. to a file in the file system.
142: * <p>Does not check whether the fil actually exists; simply returns
143: * the File that the given location would correspond to.
144: * @param resourceLocation the resource location to resolve: either a
145: * "classpath:" pseudo URL, a "file:" URL, or a plain file path
146: * @return a corresponding File object
147: * @throws FileNotFoundException if the resource cannot be resolved to
148: * a file in the file system
149: */
150: public static File getFile(String resourceLocation)
151: throws FileNotFoundException {
152: Assert.notNull(resourceLocation,
153: "Resource location must not be null");
154: if (resourceLocation.startsWith(CLASSPATH_URL_PREFIX)) {
155: String path = resourceLocation
156: .substring(CLASSPATH_URL_PREFIX.length());
157: String description = "class path resource [" + path + "]";
158: URL url = ClassUtils.getDefaultClassLoader().getResource(
159: path);
160: if (url == null) {
161: throw new FileNotFoundException(
162: description
163: + " cannot be resolved to absolute file path "
164: + "because it does not reside in the file system");
165: }
166: return getFile(url, description);
167: }
168: try {
169: // try URL
170: return getFile(new URL(resourceLocation));
171: } catch (MalformedURLException ex) {
172: // no URL -> treat as file path
173: return new File(resourceLocation);
174: }
175: }
176:
177: /**
178: * Resolve the given resource URL to a <code>java.io.File</code>,
179: * i.e. to a file in the file system.
180: * @param resourceUrl the resource URL to resolve
181: * @return a corresponding File object
182: * @throws FileNotFoundException if the URL cannot be resolved to
183: * a file in the file system
184: */
185: public static File getFile(URL resourceUrl)
186: throws FileNotFoundException {
187: return getFile(resourceUrl, "URL");
188: }
189:
190: /**
191: * Resolve the given resource URL to a <code>java.io.File</code>,
192: * i.e. to a file in the file system.
193: * @param resourceUrl the resource URL to resolve
194: * @param description a description of the original resource that
195: * the URL was created for (for example, a class path location)
196: * @return a corresponding File object
197: * @throws FileNotFoundException if the URL cannot be resolved to
198: * a file in the file system
199: */
200: public static File getFile(URL resourceUrl, String description)
201: throws FileNotFoundException {
202: Assert.notNull(resourceUrl, "Resource URL must not be null");
203: if (!URL_PROTOCOL_FILE.equals(resourceUrl.getProtocol())) {
204: throw new FileNotFoundException(description
205: + " cannot be resolved to absolute file path "
206: + "because it does not reside in the file system: "
207: + resourceUrl);
208: }
209: return new File(URLDecoder.decode(resourceUrl.getFile()));
210: }
211:
212: /**
213: * Determine whether the given URL points to a resource in a jar file,
214: * that is, has protocol "jar", "zip" or "wsjar".
215: * <p>"zip" and "wsjar" are used by BEA WebLogic Server and IBM WebSphere,
216: * respectively, but can be treated like jar files.
217: * @param url the URL to check
218: * @return whether the URL has been identified as a JAR URL
219: */
220: public static boolean isJarURL(URL url) {
221: String protocol = url.getProtocol();
222: return (URL_PROTOCOL_JAR.equals(protocol)
223: || URL_PROTOCOL_ZIP.equals(protocol) || URL_PROTOCOL_WSJAR
224: .equals(protocol));
225: }
226:
227: /**
228: * Extract the URL for the actual jar file from the given URL
229: * (which may point to a resource in a jar file or to a jar file itself).
230: * @param jarUrl the original URL
231: * @return the URL for the actual jar file
232: * @throws MalformedURLException if no valid jar file URL could be extracted
233: */
234: public static URL extractJarFileURL(URL jarUrl)
235: throws MalformedURLException {
236: String urlFile = jarUrl.getFile();
237: int separatorIndex = urlFile.indexOf(JAR_URL_SEPARATOR);
238: if (separatorIndex != -1) {
239: String jarFile = urlFile.substring(0, separatorIndex);
240: try {
241: return new URL(jarFile);
242: } catch (MalformedURLException ex) {
243: // Probably no protocol in original jar URL, like "jar:C:/mypath/myjar.jar".
244: // This usually indicates that the jar file resides in the file system.
245: if (!jarFile.startsWith("/")) {
246: jarFile = "/" + jarFile;
247: }
248: return new URL(FILE_URL_PREFIX + jarFile);
249: }
250: } else {
251: return jarUrl;
252: }
253: }
254:
255: }
|