001: /*
002: * Copyright 2000,2005 wingS development team.
003: *
004: * This file is part of wingS (http://wingsframework.org).
005: *
006: * wingS is free software; you can redistribute it and/or modify
007: * it under the terms of the GNU Lesser General Public License
008: * as published by the Free Software Foundation; either version 2.1
009: * of the License, or (at your option) any later version.
010: *
011: * Please see COPYING for the complete licence.
012: */
013: package org.wings.template;
014:
015: import org.apache.commons.logging.Log;
016: import org.apache.commons.logging.LogFactory;
017: import java.io.ByteArrayInputStream;
018: import java.io.File;
019: import java.io.FileInputStream;
020: import java.io.IOException;
021: import java.io.InputStream;
022: import java.net.URL;
023: import java.util.Hashtable;
024:
025: /**
026: * A <CODE>CachedFileDataSource</CODE> implements a DataSource
027: * for a file, but caches small ones.
028: *
029: * @author <A href="mailto:zeller@think.de">Henner Zeller</A>
030: */
031: public class CachedFileTemplateSource extends FileTemplateSource {
032: private final static Log log = LogFactory
033: .getLog(CachedFileTemplateSource.class);
034:
035: private final static class CacheEntry {
036: private byte[] filebuffer = null;
037: private long lastModified;
038: private File file;
039:
040: public CacheEntry(File f) throws IOException {
041: this .file = f;
042: lastModified = -1;
043: // we want to throw an IOException here if the file is not found
044: if (file != null) {
045: lastModified = file.lastModified();
046: refresh();
047: }
048: }
049:
050: public CacheEntry(URL url) throws IOException {
051: file = null;
052: lastModified = System.currentTimeMillis();
053: InputStream in = url.openStream();
054: /*
055: * unfortnunatly, we do not know the length of
056: * the data ..
057: */
058: int totLen = 0;
059: int copyLen = 0;
060: byte[] tempBuffer = new byte[1024];
061: do {
062: copyLen = in.read(tempBuffer);
063: if (copyLen > 0) {
064: byte[] newFileBuf = new byte[totLen + copyLen];
065: if (filebuffer != null)
066: System.arraycopy(filebuffer, 0, newFileBuf, 0,
067: totLen);
068: System.arraycopy(tempBuffer, 0, newFileBuf, totLen,
069: copyLen);
070: totLen += copyLen;
071: filebuffer = newFileBuf;
072: }
073: } while (copyLen >= 0);
074: in.close();
075: }
076:
077: public byte[] getBuffer() {
078: return filebuffer;
079: }
080:
081: /**
082: * returns the time, this file has been
083: * last modified. This checks the Timestamp of
084: * the file and initiates a reload to the cache
085: * if it changed.
086: */
087: public long lastModified() {
088: checkModified();
089: return lastModified;
090: }
091:
092: private void checkModified() {
093: if (file == null)
094: return;
095: long timestamp = file.lastModified();
096: if (lastModified != timestamp) {
097: lastModified = timestamp;
098: try {
099: refresh();
100: } catch (IOException e) {
101: /* ignore currently, file might have been deleted, but is
102: * still in cache.
103: */
104: if (log.isErrorEnabled()) {
105: log
106: .error(file.getAbsolutePath()
107: + " not found. Maybe it has been deleted from the filesystem.");
108: }
109: }
110: }
111: }
112:
113: private void refresh() throws IOException {
114: int len = (int) file.length();
115: filebuffer = new byte[len];
116: FileInputStream in = new FileInputStream(file);
117: int pos = 0;
118: while (pos < len) {
119: pos += in.read(filebuffer, pos, len - pos);
120: }
121: in.close();
122: }
123: }
124:
125: /*
126: * we should provide a way to expunge old
127: * entries here ...
128: */
129: private static Hashtable cache = new Hashtable();
130: private static final int CACHED_LIMIT = 1024;
131:
132: private transient CacheEntry entry;
133:
134: public CachedFileTemplateSource(File f) throws IOException {
135: super (f);
136:
137: entry = (CacheEntry) cache.get(f);
138: if (entry == null && f.length() <= CACHED_LIMIT) {
139: entry = new CacheEntry(f);
140: cache.put(f, entry);
141: }
142: }
143:
144: public CachedFileTemplateSource(URL url) throws IOException {
145: super (null); // we never read the file directly
146: entry = (CacheEntry) cache.get(url);
147: if (entry == null) {
148: entry = new CacheEntry(url);
149: cache.put(url, entry);
150: }
151: canonicalName = url.toString();
152: }
153:
154: /**
155: * Returns the time the content of this File
156: * was last modified.
157: * <p/>
158: * The return value is used to decide whether to reparse a
159: * Source or not. Reparsing is done if the value returned
160: * here differs from the value returned at the last processing
161: * time.
162: *
163: * @return long a modification time
164: */
165: public long lastModified() {
166: if (entry != null)
167: return entry.lastModified();
168: else
169: return super .lastModified();
170: }
171:
172: /**
173: * Gets an InputStream of the File.
174: */
175: public InputStream getInputStream() throws IOException {
176: if (entry != null)
177: return new ByteArrayInputStream(entry.getBuffer());
178: else
179: return super.getInputStream();
180: }
181: }
|