001 /* 002 * Copyright 2002-2004 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.ObjectUtils; 027 import org.springframework.util.ResourceUtils; 028 import org.springframework.util.StringUtils; 029 030 /** 031 * Resource implementation for class path resources. 032 * Uses either the thread context class loader, a given ClassLoader 033 * 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.Thread#getContextClassLoader 042 * @see java.lang.ClassLoader#getResourceAsStream 043 * @see java.lang.Class#getResourceAsStream 044 */ 045 public class ClassPathResource extends AbstractResource { 046 047 private final String path; 048 049 private ClassLoader classLoader; 050 051 private Class clazz; 052 053 /** 054 * Create a new ClassPathResource for ClassLoader usage. 055 * A leading slash will be removed, as the ClassLoader 056 * resource access methods will not accept it. 057 * <p>The thread context class loader will be used for 058 * loading the resource. 059 * @param path the absolute path within the class path 060 * @see java.lang.ClassLoader#getResourceAsStream 061 * @see java.lang.Thread#getContextClassLoader 062 */ 063 public ClassPathResource(String path) { 064 this(path, (ClassLoader) null); 065 } 066 067 /** 068 * Create a new ClassPathResource for ClassLoader usage. 069 * A leading slash will be removed, as the ClassLoader 070 * resource access methods will not accept it. 071 * @param path the absolute path within the classpath 072 * @param classLoader the class loader to load the resource with, 073 * or null for the thread context class loader 074 * @see java.lang.ClassLoader#getResourceAsStream 075 */ 076 public ClassPathResource(String path, ClassLoader classLoader) { 077 Assert.notNull(path, "path is required"); 078 if (path.startsWith("/")) { 079 path = path.substring(1); 080 } 081 this.path = path; 082 this.classLoader = classLoader; 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 is required"); 095 this.path = 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, Class clazz) { 107 Assert.notNull(path, "path is required"); 108 this.path = path; 109 this.classLoader = classLoader; 110 this.clazz = clazz; 111 } 112 113 public InputStream getInputStream() throws IOException { 114 InputStream is = null; 115 if (this.clazz != null) { 116 is = this.clazz.getResourceAsStream(this.path); 117 } 118 else { 119 ClassLoader cl = this.classLoader; 120 if (cl == null) { 121 // no class loader specified -> use thread context class loader 122 cl = Thread.currentThread().getContextClassLoader(); 123 } 124 is = cl.getResourceAsStream(this.path); 125 } 126 if (is == null) { 127 throw new FileNotFoundException( 128 getDescription() + " cannot be opened because it does not exist"); 129 } 130 return is; 131 } 132 133 public URL getURL() throws IOException { 134 URL url = null; 135 if (this.clazz != null) { 136 url = this.clazz.getResource(this.path); 137 } 138 else { 139 ClassLoader cl = this.classLoader; 140 if (cl == null) { 141 // no class loader specified -> use thread context class loader 142 cl = Thread.currentThread().getContextClassLoader(); 143 } 144 url = cl.getResource(this.path); 145 } 146 if (url == null) { 147 throw new FileNotFoundException( 148 getDescription() + " cannot be resolved to URL because it does not exist"); 149 } 150 return url; 151 } 152 153 public File getFile() throws IOException { 154 return ResourceUtils.getFile(getURL(), getDescription()); 155 } 156 157 public Resource createRelative(String relativePath) { 158 String pathToUse = StringUtils.applyRelativePath(this.path, relativePath); 159 return new ClassPathResource(pathToUse, this.classLoader, this.clazz); 160 } 161 162 public String getFilename() { Rate163 return StringUtils.getFilename(this.path); 164 } 165 166 public String getDescription() { 167 return "class path resource [" + this.path + "]"; 168 } 169 170 public boolean equals(Object obj) { 171 if (obj == this) { 172 return true; 173 } 174 if (obj instanceof ClassPathResource) { 175 ClassPathResource otherRes = (ClassPathResource) obj; 176 return (this.path.equals(otherRes.path) && ObjectUtils.nullSafeEquals(this.clazz, otherRes.clazz)); 177 } 178 return false; 179 } 180 181 public int hashCode() { 182 return this.path.hashCode(); 183 } 184 185 }