001 /*
002 * Apache License
003 * Version 2.0, January 2004
004 * http://www.apache.org/licenses/
005 *
006 * Copyright 1996-2008 by Sven Homburg
007 *
008 * Licensed under the Apache License, Version 2.0 (the "License");
009 * you may not use this file except in compliance with the License.
010 * You may obtain a copy of the License at
011 *
012 * http://www.apache.org/licenses/LICENSE-2.0
013 */
014
015 package org.chenillekit.core.resources;
016
017 import java.io.File;
018 import java.io.IOException;
019 import java.io.InputStream;
020 import java.net.MalformedURLException;
021 import java.net.URI;
022 import java.net.URISyntaxException;
023 import java.net.URL;
024 import java.util.Locale;
025
026 import org.apache.tapestry5.ioc.Resource;
027 import org.apache.tapestry5.ioc.internal.util.LocalizedNameGenerator;
028
029 /**
030 * A resource stored with in any location (local, remote or jar archive).
031 *
032 * @version $Id: URIResource.java 594 2009-12-05 15:17:26Z mlusetti $
033 */
034 public class URIResource implements Resource
035 {
036 private URI uri;
037
038 public URIResource(String uri)
039 {
040 try
041 {
042 this.uri = new URI(uri);
043 }
044 catch (URISyntaxException e)
045 {
046 throw new RuntimeException(e);
047 }
048 }
049
050 public URIResource(URI uri) throws MalformedURLException
051 {
052 this.uri = uri;
053 }
054
055 public URIResource(File file) throws MalformedURLException
056 {
057 this(file.toURI());
058 }
059
060 public URIResource(URL url) throws URISyntaxException, MalformedURLException
061 {
062 this(url.toURI());
063 }
064
065 protected Resource newResource(String uri)
066 {
067 return new URIResource(uri);
068 }
069
070 /**
071 * Returns true if the resource exists; if a stream to the content of the file may be openned.
072 *
073 * @return true if the resource exists, false if it does not
074 */
075 public boolean exists()
076 {
077 InputStream is = null;
078
079 try
080 {
081 is = uri.toURL().openStream();
082 int i = is.read();
083 return true;
084 }
085 catch (Exception e)
086 {
087 return false;
088 }
089 finally
090 {
091 try
092 {
093 if (is != null)
094 is.close();
095 }
096 catch (Exception e)
097 {
098 // do nothing
099 }
100 }
101 }
102
103 /**
104 * Opens a stream to the content of the resource, or returns null if the resource does not exist.
105 *
106 * @return an open, buffered stream to the content, if available
107 */
108 public InputStream openStream() throws IOException
109 {
110 return uri.toURL().openStream();
111 }
112
113 /**
114 * Returns the URL for the resource, or null if it does not exist.
115 */
116 public URL toURL()
117 {
118 try
119 {
120 if (exists())
121 return uri.toURL();
122 }
123 catch (Exception e)
124 {
125 // do nothing
126 }
127
128 return null;
129 }
130
131 /**
132 * Returns a localized version of the resource. May return null if no such resource exists.
133 */
134 public Resource forLocale(Locale locale)
135 {
136 for (String path : new LocalizedNameGenerator(this.uri.toString(), locale))
137 {
138 Resource potential = createResource(path);
139
140 if (potential.exists()) return potential;
141 }
142
143 return null;
144 }
145
146 /**
147 * Creates a new resource, unless the path matches the current Resource's path (in which case, this resource is
148 * returned).
149 */
150 private Resource createResource(String path)
151 {
152 if (this.uri.toString().equals(path)) return this;
153
154 return newResource(path);
155 }
156
157 /**
158 * Returns a Resource based on a relative path, relative to the folder containing the resource. Understands the "."
159 * (current folder) and ".." (parent folder) conventions, and treats multiple sequential slashes as a single slash.
160 */
161 public Resource forFile(String relativePath)
162 {
163 return createResource(relativePath);
164 }
165
166 /**
167 * Returns a new Resource with the extension changed (or, if the resource does not have an extension, the extension
168 * is added). The new Resource may not exist (that is, {@link #toURL()} may return null.
169 *
170 * @param extension to apply to the resource, such as "html" or "properties"
171 *
172 * @return the new resource
173 */
174 public Resource withExtension(String extension)
175 {
176 throw new RuntimeException("not implemented yet!");
177 }
178
179 /**
180 * Returns the portion of the path up to the last forward slash; this is the directory or folder portion of the
181 * Resource.
182 */
183 public String getFolder()
184 {
185 String folderName = "";
186 String completePath = toURL().getPath();
187
188 if (completePath != null)
189 {
190 int lastSlash = completePath.lastIndexOf('/');
191 if (lastSlash > 0)
192 folderName = completePath.substring(0, lastSlash);
193 }
194
195 return folderName;
196 }
197
198 /**
199 * Returns the file portion of the Resource path, everything that follows the final forward slash.
200 */
201 public String getFile()
202 {
203 String fileName = "";
204 String completePath = toURL().getPath();
205
206 if (completePath != null)
207 {
208 if (completePath.lastIndexOf('/') > 0)
209 fileName = completePath.substring(completePath.lastIndexOf('/') + 1);
210 else
211 fileName = completePath;
212 }
213
214 return fileName;
215 }
216
217 /**
218 * Return the path (the combination of folder and file).
219 */
220 public String getPath()
221 {
222 return toURL().toExternalForm();
223 }
224
225 @Override
226 public boolean equals(Object obj)
227 {
228 if (obj == null) return false;
229
230 if (obj == this) return true;
231
232 if (obj.getClass() != getClass()) return false;
233
234 URIResource other = (URIResource) obj;
235
236 return other.getPath().equals(getPath());
237 }
238
239 @Override
240 public int hashCode()
241 {
242 return 227 ^ getPath().hashCode();
243 }
244
245 @Override
246 public String toString()
247 {
248 return String.format("uri:%s", uri.toString());
249 }
250 }