001: /*
002: * IndexedContent.java December 2002
003: *
004: * Copyright (C) 2002, 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.net.Path;
024: import java.io.FileInputStream;
025: import java.io.IOException;
026: import java.io.InputStream;
027: import java.util.Locale;
028: import java.io.File;
029:
030: /**
031: * The <code>IndexedContent</code> is used to provide any specific
032: * meta data for any file based <code>Content</code>s. This provides
033: * methods that allow the <code>Content</code> to be indexed by the
034: * <code>Context</code> object, this allows the server to build meta
035: * information on a resource without having to refer to a centralized
036: * table that matches the resource with its meta information.
037: * <p>
038: * Such approaches are used with servers like Apache that can have
039: * information stored in a file to describe the Language, Type etc.
040: * of a resource. This however uses a scheme that discovers the meta
041: * information of the <code>Content</code> by parsing the request URI.
042: * The <code>File</code>s that are indexed can have locale extensions
043: * to that the <code>Content</code>s can be discriminated upon based
044: * on preferred Language.
045: *
046: * @author Niall Gallagher
047: */
048: abstract class IndexedContent implements Content {
049:
050: /**
051: * This represents a cache of the buffered contents.
052: */
053: protected volatile String cache;
054:
055: /**
056: * This is the HTTP URI that references this content.
057: */
058: protected String target;
059:
060: /**
061: * This is the index that contains all the meta data.
062: */
063: protected Index index;
064:
065: /**
066: * Creates a default indexed object that is indexed based on
067: * the path name that it is given. The <code>Context</code> is
068: * used to parse the path and set the meta data. The meta data
069: * of the <code>Content</code> is set based on a set of rules
070: * specified by the <code>Context</code>. The path is broken
071: * into its separate components like its name, type, path etc.
072: * This will create the <code>Content</code> relative to the
073: * specified directory. i.e. the <code>Content</code> is
074: * created from a file that is rooted at the base directory.
075: *
076: * @param context the context that this resource is relative to
077: * @param target this is the HTTP request URI this represents
078: */
079: protected IndexedContent(Context context, String target) {
080: this .index = context.getIndex(target);
081: this .target = target;
082: }
083:
084: /**
085: * This allows the name for this object to be acquired. The
086: * name usually refers to the last entry in the path. So if
087: * the index target path was "/usr/bin/" the name is "bin".
088: *
089: * @return this returns the name of this index target
090: */
091: public String getName() {
092: return index.getName();
093: }
094:
095: /**
096: * This allows the MIME type of this <code>Index</code> to
097: * be acquired. The MIME type of a file is retrieved by the
098: * <code>Context.getContentType</code> method for a specific
099: * request URI. This should have a value and perhaps some
100: * parameters like the charset, "text/html; charset=UTF-8".
101: *
102: * @return the MIME type this object has been set to
103: */
104: public String getContentType() {
105: return index.getContentType();
106: }
107:
108: /**
109: * This gets the locale for this index object the locale is
110: * set to the <code>Locale.getDefault</code> if there is no
111: * locale information available for the index target. This
112: * will provide the <code>Context.getLocale</code> object.
113: *
114: * @return this returns the locale for this index target
115: */
116: public Locale getLocale() {
117: return index.getLocale();
118: }
119:
120: /**
121: * This is used to get the path that this object refers to.
122: * This should be the fully qualified normalized path. This
123: * refers to the OS system specific path that this represents.
124: *
125: * @return this returns the OS specific path for the target
126: */
127: public String getRealPath() {
128: return index.getRealPath();
129: }
130:
131: /**
132: * This is used to acquire the normalized URI style path for
133: * the index target. This allows the path to be used within
134: * the <code>Mapper</code> and other such objects that need
135: * a normalized URI style path to resolve resources.
136: *
137: * @return this returns the normalized path for the target
138: */
139: public String getRequestPath() {
140: return index.getRequestPath();
141: }
142:
143: /**
144: * This is used to acquire the <code>File</code> directory
145: * for the index target. This is typically rooted at a
146: * base path, for instance the <code>Context</code> root
147: * is typically used. This allows resources within the
148: * same directory to be acquired easily.
149: *
150: * @return this returns the OS file for the directory
151: */
152: public File getDirectory() {
153: return index.getDirectory();
154: }
155:
156: /**
157: * This is used to acquire the <code>File</code> reference
158: * for the index target. This is typically rooted at a
159: * base path, for instance the <code>Context</code> root
160: * is typically used. This allows the file to be opened,
161: * deleted, or read should the need arise in a service.
162: *
163: * @return this returns the OS file for the resource
164: */
165: public File getFile() {
166: return index.getFile();
167: }
168:
169: /**
170: * This is used to acquire the <code>Path</code> object that
171: * exposes various parts of the URI path. This can be used
172: * to extract the individual path segments as strings as
173: * well as the file extension and various other details.
174: *
175: * @return this returns a path object with various details
176: */
177: public Path getPath() {
178: return index.getPath();
179: }
180:
181: /**
182: * This is a simple convienience method that enables subclasses
183: * to retrieve the <code>FileInputStream</code> for the file.
184: *
185: * @return this returns the <code>FileInputStream</code> that
186: * represents the targeted file
187: *
188: * @throws IOException thrown if the file does not exist
189: */
190: protected InputStream getInputStream() throws IOException {
191: return new FileInputStream(getFile());
192: }
193:
194: /**
195: * This method is used to convert the contents of this object to
196: * a UTF-8 string. This is primarily used as a means to provide
197: * the text for the <code>toString</code> method in a thread
198: * safe manner by creating a privately scoped buffer object.
199: *
200: * @return this returns a UTF-8 representation of the contents
201: */
202: protected String getContent() {
203: return new ContentBuffer(this ).toString();
204: }
205:
206: /**
207: * This returns the date of the last modification of the file.
208: * This date is returned as the long, this is the number of
209: * milliseconds since January 1 1970. This is equivelant to
210: * using the <code>File.lastModified</code> method.
211: *
212: * @return the date of the last modification of the file
213: */
214: protected long getLastModified() {
215: return getFile().lastModified();
216: }
217:
218: /**
219: * This method is used to retrieve the length of the file that
220: * this <code>Content</code> represents. The size of the file
221: * is assumed not to be larger than the maximum integer value,
222: * if it is possible for the length to exceed this length the
223: * <code>File.length</code> method should be used.
224: *
225: * @return this returns the length of the file as an integer
226: */
227: protected int getLength() {
228: return (int) getFile().length();
229: }
230:
231: /**
232: * This acquires the contents of the file as a UTF-8 encoded
233: * string. This will also ensure that the contents of the file
234: * are cached as a string, thus avoiding the need to reconvert
235: * the contents into a UTF-8 string on each use of this.
236: *
237: * @return this returns a UTF-8 encoding of the file contents
238: */
239: public String toString() {
240: if (cache == null) {
241: cache = getContent();
242: }
243: return cache;
244: }
245: }
|