001: /* *************************************************************************
002:
003: Millstone(TM)
004: Open Sourced User Interface Library for
005: Internet Development with Java
006:
007: Millstone is a registered trademark of IT Mill Ltd
008: Copyright (C) 2000-2005 IT Mill Ltd
009:
010: *************************************************************************
011:
012: This library is free software; you can redistribute it and/or
013: modify it under the terms of the GNU Lesser General Public
014: license version 2.1 as published by the Free Software Foundation.
015:
016: This library is distributed in the hope that it will be useful,
017: but WITHOUT ANY WARRANTY; without even the implied warranty of
018: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019: Lesser General Public License for more details.
020:
021: You should have received a copy of the GNU Lesser General Public
022: License along with this library; if not, write to the Free Software
023: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024:
025: *************************************************************************
026:
027: For more information, contact:
028:
029: IT Mill Ltd phone: +358 2 4802 7180
030: Ruukinkatu 2-4 fax: +358 2 4802 7181
031: 20540, Turku email: info@itmill.com
032: Finland company www: www.itmill.com
033:
034: Primary source for MillStone information and releases: www.millstone.org
035:
036: ********************************************************************** */
037:
038: package org.millstone.webadapter;
039:
040: import java.io.File;
041: import java.io.FileInputStream;
042: import java.io.FileNotFoundException;
043: import java.io.IOException;
044: import java.io.InputStream;
045: import java.util.Collection;
046: import java.util.Iterator;
047: import java.util.LinkedList;
048:
049: /**
050: * Theme source for reading themes from a directory on the Filesystem.
051: * @author IT Mill Ltd.
052: * @version 3.1.1
053: * @since 3.0
054: */
055: public class DirectoryThemeSource implements ThemeSource {
056:
057: private File path;
058: private Theme theme;
059: private WebAdapterServlet webAdapterServlet;
060:
061: /** Collection of subdirectory entries */
062: private Collection subdirs = new LinkedList();
063:
064: /** Creates a new instance of ThemeRepository by reading the themes
065: * from a local directory.
066: * @param path Path to the source directory .
067: * @param url External URL of the repository
068: * @throws FileNotFoundException if no theme files are found
069: */
070: public DirectoryThemeSource(File path,
071: WebAdapterServlet webAdapterServlet) throws ThemeException,
072: FileNotFoundException, IOException {
073:
074: this .path = path;
075: this .theme = null;
076: this .webAdapterServlet = webAdapterServlet;
077:
078: if (!this .path.isDirectory())
079: throw new java.io.FileNotFoundException(
080: "Theme path must be a directory ('" + this .path
081: + "')");
082:
083: // Load description file
084: File description = new File(path, Theme.DESCRIPTIONFILE);
085: if (description.exists()) {
086: try {
087: this .theme = new Theme(description);
088: } catch (Exception e) {
089: throw new ThemeException(
090: "ServletThemeSource: Failed to load '" + path
091: + "': " + e);
092: }
093:
094: // Debug info
095: if (webAdapterServlet.isDebugMode()) {
096: Log.info("Added DirectoryThemeSource: " + this .path);
097: }
098:
099: } else {
100: // There was no description file found.
101: // Handle subdirectories recursively
102: File[] files = this .path.listFiles();
103: for (int i = 0; i < files.length; i++) {
104: if (files[i].isDirectory()) {
105: this .subdirs.add(new DirectoryThemeSource(files[i],
106: webAdapterServlet));
107: } else if (files[i].getName().toLowerCase().endsWith(
108: ".jar")) {
109: this .subdirs.add(new JarThemeSource(files[i],
110: webAdapterServlet, ""));
111: }
112: }
113:
114: if (this .subdirs.isEmpty()) {
115: if (webAdapterServlet.isDebugMode()) {
116: Log
117: .debug("DirectoryThemeSource: Ignoring empty directory: "
118: + path);
119: }
120: }
121: }
122: }
123:
124: /**
125: * @see org.millstone.webadapter.ThemeSource#getXSLStreams(Theme, WebBrowser)
126: */
127: public Collection getXSLStreams(Theme theme, WebBrowser type)
128: throws ThemeException {
129: Collection xslFiles = new LinkedList();
130:
131: // If this directory contains a theme
132: // return XSL from this theme
133: if (this .theme != null) {
134:
135: if (webAdapterServlet.isDebugMode()) {
136: Log.info("DirectoryThemeSource: Loading XSL from: "
137: + theme);
138: }
139:
140: // Reload the description file
141: File description = new File(path, Theme.DESCRIPTIONFILE);
142: if (description.exists()) {
143: try {
144: this .theme = new Theme(description);
145: } catch (IOException e) {
146: throw new ThemeException(
147: "Failed to reload theme description" + e);
148: }
149: }
150:
151: Collection fileNames = theme.getFileNames(type);
152:
153: // Add all XSL file streams
154: for (Iterator i = fileNames.iterator(); i.hasNext();) {
155: File f = new File(this .path, (String) i.next());
156: try {
157: xslFiles.add(new XSLStream(f.getName(),
158: new FileInputStream(f)));
159: } catch (FileNotFoundException e) {
160: throw new ThemeException("XSL File not found: " + f);
161: }
162: }
163:
164: } else {
165:
166: // Handle subdirectories: return the first match
167: for (Iterator i = this .subdirs.iterator(); i.hasNext();) {
168: ThemeSource source = (ThemeSource) i.next();
169: if (source.getThemes().contains(theme))
170: xslFiles.addAll(source.getXSLStreams(theme, type));
171: }
172: }
173:
174: // Return the concatenated stream
175: return xslFiles;
176:
177: }
178:
179: /**
180: * @see org.millstone.webadapter.ThemeSource#getModificationTime()
181: */
182: public long getModificationTime() {
183:
184: long modTime = 0;
185:
186: // If this directory contains a theme
187: // return XSL from this theme
188: if (this .theme != null) {
189:
190: // Get modification time of the description file
191: modTime = new File(this .path, Theme.DESCRIPTIONFILE)
192: .lastModified();
193:
194: // Get modification time of the themes directory itself
195: if (this .path.lastModified() > modTime) {
196: modTime = this .path.lastModified();
197: }
198:
199: // Check modification time for all files
200: Collection fileNames = theme.getFileNames();
201: for (Iterator i = fileNames.iterator(); i.hasNext();) {
202: File f = new File(this .path, (String) i.next());
203: if (f.lastModified() > modTime) {
204: modTime = f.lastModified();
205: }
206: }
207: } else {
208: // Handle subdirectories
209: for (Iterator i = this .subdirs.iterator(); i.hasNext();) {
210: ThemeSource source = (ThemeSource) i.next();
211: long t = source.getModificationTime();
212: if (t > modTime)
213: modTime = t;
214: }
215: }
216:
217: return modTime;
218:
219: }
220:
221: /**
222: * @see org.millstone.webadapter.ThemeSource#getResource(String)
223: */
224: public InputStream getResource(String resourceId)
225: throws ThemeSource.ThemeException {
226:
227: // If this directory contains a theme
228: // return resource from this theme
229: if (this .theme != null) {
230:
231: try {
232: return new FileInputStream(new File(this .path,
233: resourceId));
234: } catch (FileNotFoundException e) {
235: throw new ThemeSource.ThemeException("Resource "
236: + resourceId + " not found.");
237: }
238:
239: } else {
240: int delim = resourceId.indexOf("/");
241: String subResourceName = "";
242: if (delim < resourceId.length() - 1)
243: subResourceName = resourceId.substring(delim + 1);
244: String subSourceName = resourceId.substring(0, delim);
245: for (Iterator i = this .subdirs.iterator(); i.hasNext();) {
246: ThemeSource source = (ThemeSource) i.next();
247: if (source.getName().equals(subSourceName)) {
248: return source.getResource(subResourceName);
249: }
250: }
251: }
252:
253: throw new ThemeSource.ThemeException("Resource " + resourceId
254: + " not found.");
255:
256: }
257:
258: /**
259: * @see org.millstone.webadapter.ThemeSource#getThemes()
260: */
261: public Collection getThemes() {
262: Collection themes = new LinkedList();
263: if (this .theme != null) {
264: themes.add(this .theme);
265: } else {
266: for (Iterator i = this .subdirs.iterator(); i.hasNext();) {
267: ThemeSource source = (ThemeSource) i.next();
268: themes.addAll(source.getThemes());
269: }
270:
271: }
272: return themes;
273: }
274:
275: /**
276: * @see org.millstone.webadapter.ThemeSource#getName()
277: */
278: public String getName() {
279: if (this .theme != null) {
280: return this .theme.getName();
281: } else {
282: return this .path.getName();
283: }
284: }
285:
286: /**
287: * @see org.millstone.webadapter.ThemeSource#getThemeByName(String)
288: */
289: public Theme getThemeByName(String name) {
290: Collection themes = this .getThemes();
291: for (Iterator i = themes.iterator(); i.hasNext();) {
292: Theme t = (Theme) i.next();
293: if (name != null && name.equals(t.getName()))
294: return t;
295: }
296: return null;
297: }
298:
299: }
|