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.core.io;
018:
019: import java.io.File;
020: import java.io.IOException;
021: import java.io.InputStream;
022: import java.net.MalformedURLException;
023: import java.net.URI;
024: import java.net.URL;
025: import java.net.URLConnection;
026:
027: import org.springframework.util.Assert;
028: import org.springframework.util.ResourceUtils;
029: import org.springframework.util.StringUtils;
030:
031: /**
032: * {@link Resource} implementation for <code>java.net.URL</code> locators.
033: * Obviously supports resolution as URL, and also as File in case of
034: * the "file:" protocol.
035: *
036: * @author Juergen Hoeller
037: * @since 28.12.2003
038: * @see java.net.URL
039: */
040: public class UrlResource extends AbstractResource {
041:
042: /**
043: * Original URL, used for actual access.
044: */
045: private final URL url;
046:
047: /**
048: * Cleaned URL (with normalized path), used for comparisons.
049: */
050: private final URL cleanedUrl;
051:
052: /**
053: * Original URI, if available; used for URI and File access.
054: */
055: private final URI uri;
056:
057: /**
058: * Create a new UrlResource.
059: * @param url a URL
060: */
061: public UrlResource(URL url) {
062: Assert.notNull(url, "URL must not be null");
063: this .url = url;
064: this .cleanedUrl = getCleanedUrl(this .url, url.toString());
065: this .uri = null;
066: }
067:
068: /**
069: * Create a new UrlResource.
070: * @param uri a URI
071: * @throws MalformedURLException if the given URL path is not valid
072: */
073: public UrlResource(URI uri) throws MalformedURLException {
074: Assert.notNull(uri, "URI must not be null");
075: this .url = uri.toURL();
076: this .cleanedUrl = getCleanedUrl(this .url, uri.toString());
077: this .uri = uri;
078: }
079:
080: /**
081: * Create a new UrlResource.
082: * @param path a URL path
083: * @throws MalformedURLException if the given URL path is not valid
084: */
085: public UrlResource(String path) throws MalformedURLException {
086: Assert.notNull(path, "Path must not be null");
087: this .url = new URL(path);
088: this .cleanedUrl = getCleanedUrl(this .url, path);
089: this .uri = null;
090: }
091:
092: /**
093: * Determine a cleaned URL for the given original URL.
094: * @param originalUrl the original URL
095: * @param originalPath the original URL path
096: * @return the cleaned URL
097: * @see org.springframework.util.StringUtils#cleanPath
098: */
099: private URL getCleanedUrl(URL originalUrl, String originalPath) {
100: try {
101: return new URL(StringUtils.cleanPath(originalPath));
102: } catch (MalformedURLException ex) {
103: // Cleaned URL path cannot be converted to URL
104: // -> take original URL.
105: return originalUrl;
106: }
107: }
108:
109: /**
110: * This implementation opens an InputStream for the given URL.
111: * It sets the "UseCaches" flag to <code>false</code>,
112: * mainly to avoid jar file locking on Windows.
113: * @see java.net.URL#openConnection()
114: * @see java.net.URLConnection#setUseCaches(boolean)
115: * @see java.net.URLConnection#getInputStream()
116: */
117: public InputStream getInputStream() throws IOException {
118: URLConnection con = this .url.openConnection();
119: con.setUseCaches(false);
120: return con.getInputStream();
121: }
122:
123: /**
124: * This implementation returns the underlying URL reference.
125: */
126: public URL getURL() throws IOException {
127: return this .url;
128: }
129:
130: /**
131: * This implementation returns the underlying URI directly,
132: * if possible.
133: */
134: public URI getURI() throws IOException {
135: if (this .uri != null) {
136: return this .uri;
137: } else {
138: return super .getURI();
139: }
140: }
141:
142: /**
143: * This implementation returns a File reference for the underlying URL/URI,
144: * provided that it refers to a file in the file system.
145: * @see org.springframework.util.ResourceUtils#getFile(java.net.URL, String)
146: */
147: public File getFile() throws IOException {
148: if (this .uri != null) {
149: return ResourceUtils.getFile(this .uri, getDescription());
150: } else {
151: return ResourceUtils.getFile(this .url, getDescription());
152: }
153: }
154:
155: /**
156: * This implementation creates a UrlResource, applying the given path
157: * relative to the path of the underlying URL of this resource descriptor.
158: * @see java.net.URL#URL(java.net.URL, String)
159: */
160: public Resource createRelative(String relativePath)
161: throws MalformedURLException {
162: if (relativePath.startsWith("/")) {
163: relativePath = relativePath.substring(1);
164: }
165: return new UrlResource(new URL(this .url, relativePath));
166: }
167:
168: /**
169: * This implementation returns the name of the file that this URL refers to.
170: * @see java.net.URL#getFile()
171: * @see java.io.File#getName()
172: */
173: public String getFilename() {
174: return new File(this .url.getFile()).getName();
175: }
176:
177: /**
178: * This implementation returns a description that includes the URL.
179: */
180: public String getDescription() {
181: return "URL [" + this .url + "]";
182: }
183:
184: /**
185: * This implementation compares the underlying URL references.
186: */
187: public boolean equals(Object obj) {
188: return (obj == this || (obj instanceof UrlResource && this .cleanedUrl
189: .equals(((UrlResource) obj).cleanedUrl)));
190: }
191:
192: /**
193: * This implementation returns the hash code of the underlying URL reference.
194: */
195: public int hashCode() {
196: return this.cleanedUrl.hashCode();
197: }
198:
199: }
|