001: /*
002: * FileLocator.java February 2004
003: *
004: * Copyright (C) 2004, Niall Gallagher <niallg@users.sf.net>
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013: * GNU Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General
016: * Public License along with this library; if not, write to the
017: * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
018: * Boston, MA 02111-1307 USA
019: */
020:
021: package simple.http.serve;
022:
023: import simple.util.FileProperties;
024: import java.util.Properties;
025: import java.io.IOException;
026: import java.io.File;
027: import java.net.URL;
028:
029: /**
030: * The <code>FileLocator</code> provides an implementation of the
031: * <code>Locator</code> interface for locating files from a list of
032: * directories. This will use the list of directories to search for
033: * named files. The list of files is searched by increasing index so
034: * the first occurrence of a named file found in the search path will
035: * be used. This accepts the name of the file to be used, so for
036: * example if the file required was <code>example.xml</code> then
037: * the name alone should be supplied. If however path information
038: * is supplied it can be in a URI or platform specific format.
039: *
040: * @author Niall Gallagher
041: */
042: public class FileLocator implements Locator {
043:
044: /**
045: * This is the list of directories within the search path.
046: */
047: private File[] list;
048:
049: /**
050: * Constructor for the <code>FileLocator</code> object. This
051: * no argument constructor will contain an empty search path
052: * and as a result will only search for resources within the
053: * current working directory.
054: */
055: public FileLocator() {
056: this (new File[] {});
057: }
058:
059: /**
060: * Constructor for the <code>FileLocator</code> object. This
061: * constructor requires a single path for searching. The path
062: * is searched for the named resources and if found it is
063: * used, however if the resource is not found in the given
064: * path the current working directory is searched.
065: *
066: * @param path this is the path to search for the resources
067: */
068: public FileLocator(File path) {
069: this (new File[] { path });
070: }
071:
072: /**
073: * Constructor for the <code>FileLocator</code> object. This
074: * constructor requires a list of directories with which to
075: * search for resources. The resources are searched for in
076: * increasing index, so index zero is the first directory
077: * searched followed by index one and so on. This uses the
078: * current working directory if the search fails.
079: *
080: * @param list this is the list of files to search within
081: */
082: public FileLocator(File[] list) {
083: this .list = list;
084: }
085:
086: /**
087: * This is used to discover the location of a resource using
088: * the name of the resource. This will return the location of
089: * the resource in a system specific path format. This mirrors
090: * the <code>FileContext.getRealPath</code> method, however it
091: * should be supplied with only the name of the resource with
092: * no path information, which keeps any code interacting with
093: * this portable across systems using different path formats.
094: *
095: * @param name the name of the resource that is to be located
096: *
097: * @return the location of the resource in the system format
098: *
099: * @exception LocateException thrown if the named resource
100: * could not be found after exhausting all lookup means
101: */
102: public String getLocation(String name) throws LocateException {
103: String real = getRealPath(name);
104:
105: for (int i = 0; i < list.length; i++) {
106: try {
107: return getLocation(list[i], real);
108: } catch (LocateException e) {
109: continue;
110: }
111: }
112: return getLocation(new File("."), real);
113: }
114:
115: /**
116: * This is used to discover the location of a resource using
117: * the name of the resource. This will return the location of
118: * the resource in a system specific path format. This mirrors
119: * the <code>FileContext.getRealPath</code> method, however it
120: * should be supplied with only the name of the resource with
121: * no path information, which keeps any code interacting with
122: * this portable across systems using different path formats.
123: *
124: * @param base this is the directory to use for the search
125: * @param name the name of the resource that is to be located
126: *
127: * @return the location of the resource in the system format
128: *
129: * @exception LocateException thrown if the named resource
130: * could not be found after exhausting all lookup means
131: */
132: private String getLocation(File base, String name)
133: throws LocateException {
134: File file = new File(base, name);
135:
136: if (file.exists()) {
137: return file.getAbsolutePath();
138: }
139: throw new LocateException("File not found");
140: }
141:
142: /**
143: * This is used to produce a <code>File</code> object pointing
144: * to the location of the named resource. This method mirrors
145: * the <code>FileContext.getFile</code> method, however it
146: * should be supplied with only the name of the resource with
147: * no path information, which keeps any code interacting with
148: * this portable across systems using different path formats.
149: *
150: * @param name the name of the resource that is to be located
151: *
152: * @return a <code>File</code> referencing the named resource
153: *
154: * @exception LocateException thrown if the named resource
155: * could not be found after exhausting all lookup means
156: */
157: public File getFile(String name) throws LocateException {
158: return new File(getLocation(name));
159: }
160:
161: /**
162: * This is used to produce a <code>Properties</code> object
163: * that contains the contents of the named Java properties file.
164: * This mirrors the <code>FileContext.getProperties</code>
165: * method, however it should be supplied with only the name of
166: * the resource with no path information, which keeps any code
167: * interacting with this portable across different platforms.
168: *
169: * @param name the name of the resource that is to be located
170: *
171: * @return a <code>Properties</code> object for the resource
172: *
173: * @exception LocateException thrown if the named resource
174: * could not be found after exhausting all lookup means
175: */
176: public Properties getProperties(String name) throws LocateException {
177: try {
178: return new FileProperties(getFile(name));
179: } catch (IOException e) {
180: throw new LocateException("File not found");
181: }
182: }
183:
184: /**
185: * This is provided so that a <code>ClassLoader</code> can be
186: * used to load the named resource. This method enables the
187: * configuration information to be loaded from the specified
188: * class path, which enables the files to be stored within a
189: * JAR resource or at any desired location. This only needs
190: * the name of the resource, no path information is required,
191: * this keeps the code portable and simple.
192: *
193: * @param name the name of the resource that is to be located
194: *
195: * @return a <code>URL</code> referencing the named resource
196: *
197: * @exception LocateException thrown if the named resource
198: * could not be found after exhausting all lookup means
199: */
200: public URL getResource(String name) throws LocateException {
201: try {
202: return getResource(getFile(name));
203: } catch (Exception e) {
204: return getResource(name, getClassLoader());
205: }
206: }
207:
208: /**
209: * This is used so that a <code>ClassLoader</code> can be
210: * used to load the named resource. This method enables the
211: * configuration information to be loaded from the specified
212: * class path, which enables the files to be stored within a
213: * JAR resource or at any desired location. This only needs
214: * the name of the resource, no path information is required,
215: * this keeps the code portable and simple.
216: *
217: * @param name the name of the resource that is to be located
218: * @param loader the <code>ClassLoader</code> that is used
219: *
220: * @return a <code>URL</code> referencing the named resource
221: *
222: * @exception LocateException thrown if the named resource
223: * could not be found after exhausting all lookup means
224: */
225: private URL getResource(String name, ClassLoader loader)
226: throws LocateException {
227: URL target = loader.getResource(name);
228:
229: if (target == null) {
230: throw new LocateException("File not found");
231: }
232: return target;
233: }
234:
235: /**
236: * The method is used to convert a <code>File</code> object to
237: * a <code>URL</code> object. This is used for convinience so
238: * that if the <code>getResource(String)</code> method is used
239: * and the specified file can be located, the correct type can
240: * be returned, if there is a problem an exception is thrown.
241: *
242: * @param path this is the file to convert to a <code>URL</code>
243: *
244: * @return this returns a <code>URL<code> for the given file
245: *
246: * @exception IOException if there is a conversion problem
247: */
248: private URL getResource(File path) throws IOException {
249: return path.getCanonicalFile().toURL();
250: }
251:
252: /**
253: * This method is used to acquire a <code>ClassLoader</code>
254: * that can be used to, acquire the configuration from the
255: * specified class path. This uses the loader that was used
256: * to load this class, which ensures that it will contain
257: * the correct hierarchy of class loaders to traverse.
258: *
259: * @return this returns the <code>ClassLoader</code> to use
260: */
261: private ClassLoader getClassLoader() {
262: return FileLocator.class.getClassLoader();
263: }
264:
265: /**
266: * This method is used to convert a URI style path into a
267: * platform specific path. This is used to accommodate paths
268: * supplied instead of resource names. The URI path format
269: * is supported as it is platform independent and in general
270: * is the typical path format used in web based systems.
271: *
272: * @param path this is a URI path this is to be converted
273: */
274: private String getRealPath(String path) {
275: return path.replace('/', File.separatorChar);
276: }
277: }
|