001: /*
002: * Copyright 2002-2006 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.core.io;
018:
019: import java.io.File;
020: import java.io.FileNotFoundException;
021: import java.io.IOException;
022: import java.io.InputStream;
023: import java.net.URL;
024:
025: import org.springframework.util.Assert;
026: import org.springframework.util.ClassUtils;
027: import org.springframework.util.ObjectUtils;
028: import org.springframework.util.ResourceUtils;
029: import org.springframework.util.StringUtils;
030:
031: /**
032: * {@link Resource} implementation for class path resources.
033: * Uses either a given ClassLoader or a given Class for loading resources.
034: *
035: * <p>Supports resolution as <code>java.io.File</code> if the class path
036: * resource resides in the file system, but not for resources in a JAR.
037: * Always supports resolution as URL.
038: *
039: * @author Juergen Hoeller
040: * @since 28.12.2003
041: * @see java.lang.ClassLoader#getResourceAsStream(String)
042: * @see java.lang.Class#getResourceAsStream(String)
043: */
044: public class ClassPathResource extends AbstractResource {
045:
046: private final String path;
047:
048: private ClassLoader classLoader;
049:
050: private Class clazz;
051:
052: /**
053: * Create a new ClassPathResource for ClassLoader usage.
054: * A leading slash will be removed, as the ClassLoader
055: * resource access methods will not accept it.
056: * <p>The thread context class loader will be used for
057: * loading the resource.
058: * @param path the absolute path within the class path
059: * @see java.lang.ClassLoader#getResourceAsStream(String)
060: * @see org.springframework.util.ClassUtils#getDefaultClassLoader()
061: */
062: public ClassPathResource(String path) {
063: this (path, (ClassLoader) null);
064: }
065:
066: /**
067: * Create a new ClassPathResource for ClassLoader usage.
068: * A leading slash will be removed, as the ClassLoader
069: * resource access methods will not accept it.
070: * @param path the absolute path within the classpath
071: * @param classLoader the class loader to load the resource with,
072: * or <code>null</code> for the thread context class loader
073: * @see java.lang.ClassLoader#getResourceAsStream(String)
074: */
075: public ClassPathResource(String path, ClassLoader classLoader) {
076: Assert.notNull(path, "Path must not be null");
077: if (path.startsWith("/")) {
078: path = path.substring(1);
079: }
080: this .path = StringUtils.cleanPath(path);
081: this .classLoader = (classLoader != null ? classLoader
082: : ClassUtils.getDefaultClassLoader());
083: }
084:
085: /**
086: * Create a new ClassPathResource for Class usage.
087: * The path can be relative to the given class,
088: * or absolute within the classpath via a leading slash.
089: * @param path relative or absolute path within the class path
090: * @param clazz the class to load resources with
091: * @see java.lang.Class#getResourceAsStream
092: */
093: public ClassPathResource(String path, Class clazz) {
094: Assert.notNull(path, "Path must not be null");
095: this .path = StringUtils.cleanPath(path);
096: this .clazz = clazz;
097: }
098:
099: /**
100: * Create a new ClassPathResource with optional ClassLoader and Class.
101: * Only for internal usage.
102: * @param path relative or absolute path within the classpath
103: * @param classLoader the class loader to load the resource with, if any
104: * @param clazz the class to load resources with, if any
105: */
106: protected ClassPathResource(String path, ClassLoader classLoader,
107: Class clazz) {
108: this .path = path;
109: this .classLoader = classLoader;
110: this .clazz = clazz;
111: }
112:
113: /**
114: * Return the path for this resource.
115: */
116: public final String getPath() {
117: return this .path;
118: }
119:
120: /**
121: * This implementation opens an InputStream for the given class path resource.
122: * @see java.lang.ClassLoader#getResourceAsStream(String)
123: * @see java.lang.Class#getResourceAsStream(String)
124: */
125: public InputStream getInputStream() throws IOException {
126: InputStream is = null;
127: if (this .clazz != null) {
128: is = this .clazz.getResourceAsStream(this .path);
129: } else {
130: is = this .classLoader.getResourceAsStream(this .path);
131: }
132: if (is == null) {
133: throw new FileNotFoundException(getDescription()
134: + " cannot be opened because it does not exist");
135: }
136: return is;
137: }
138:
139: /**
140: * This implementation returns a URL for the underlying class path resource.
141: * @see java.lang.ClassLoader#getResource(String)
142: * @see java.lang.Class#getResource(String)
143: */
144: public URL getURL() throws IOException {
145: URL url = null;
146: if (this .clazz != null) {
147: url = this .clazz.getResource(this .path);
148: } else {
149: url = this .classLoader.getResource(this .path);
150: }
151: if (url == null) {
152: throw new FileNotFoundException(
153: getDescription()
154: + " cannot be resolved to URL because it does not exist");
155: }
156: return url;
157: }
158:
159: /**
160: * This implementation returns a File reference for the underlying class path
161: * resource, provided that it refers to a file in the file system.
162: * @see org.springframework.util.ResourceUtils#getFile(java.net.URL, String)
163: */
164: public File getFile() throws IOException {
165: return ResourceUtils.getFile(getURL(), getDescription());
166: }
167:
168: /**
169: * This implementation creates a ClassPathResource, applying the given path
170: * relative to the path of the underlying resource of this descriptor.
171: * @see org.springframework.util.StringUtils#applyRelativePath(String, String)
172: */
173: public Resource createRelative(String relativePath) {
174: String pathToUse = StringUtils.applyRelativePath(this .path,
175: relativePath);
176: return new ClassPathResource(pathToUse, this .classLoader,
177: this .clazz);
178: }
179:
180: /**
181: * This implementation returns the name of the file that this class path
182: * resource refers to.
183: * @see org.springframework.util.StringUtils#getFilename(String)
184: */
185: public String getFilename() {
186: return StringUtils.getFilename(this .path);
187: }
188:
189: /**
190: * This implementation returns a description that includes the class path location.
191: */
192: public String getDescription() {
193: return "class path resource [" + this .path + "]";
194: }
195:
196: /**
197: * This implementation compares the underlying class path locations.
198: */
199: public boolean equals(Object obj) {
200: if (obj == this ) {
201: return true;
202: }
203: if (obj instanceof ClassPathResource) {
204: ClassPathResource otherRes = (ClassPathResource) obj;
205: return (this .path.equals(otherRes.path)
206: && ObjectUtils.nullSafeEquals(this .classLoader,
207: otherRes.classLoader) && ObjectUtils
208: .nullSafeEquals(this .clazz, otherRes.clazz));
209: }
210: return false;
211: }
212:
213: /**
214: * This implementation returns the hash code of the underlying
215: * class path location.
216: */
217: public int hashCode() {
218: return this.path.hashCode();
219: }
220:
221: }
|