001: /* ResourceCaches.java
002:
003: {{IS_NOTE
004: Purpose:
005:
006: Description:
007:
008: History:
009: Tue Aug 30 18:31:05 2005, Created by tomyeh
010: }}IS_NOTE
011:
012: Copyright (C) 2005 Potix Corporation. All Rights Reserved.
013:
014: {{IS_RIGHT
015: This program is distributed under GPL Version 2.0 in the hope that
016: it will be useful, but WITHOUT ANY WARRANTY.
017: }}IS_RIGHT
018: */
019: package org.zkoss.web.util.resource;
020:
021: import java.io.File;
022: import java.io.InputStream;
023: import java.io.FileInputStream;
024: import java.io.InputStreamReader;
025: import java.net.URL;
026:
027: import javax.servlet.ServletContext;
028:
029: import org.zkoss.lang.D;
030: import org.zkoss.lang.Exceptions;
031: import org.zkoss.lang.SystemException;
032: import org.zkoss.util.resource.ResourceCache;
033: import org.zkoss.util.logging.Log;
034: import org.zkoss.io.Files;
035:
036: import org.zkoss.web.servlet.Servlets;
037:
038: /**
039: * Utilities to load (and parse) the servlet resource.
040: *
041: * <p>Usage 1:
042: * <ol>
043: * <li>Use {@link #getContent} to load the resource into a String-type content.
044: * </ol>
045: *
046: * <p>Usage 2:
047: * <ol>
048: * <li>Implements a loader by extending from {@link ResourceLoader}.</li>
049: * <li>Creates a resource cache ({@link ResourceCache})
050: * by use of the loader in the previous step.</li>
051: * <li>Invoke {@link #get} to load the resource.</li>
052: * </ol>
053: *
054: * <p>Usage 2 has better performance because you need to parse the content
055: * only once. Usage 1 is simple if you don't pase it into any intermediate
056: * format.
057: *
058: * @author tomyeh
059: */
060: public class ResourceCaches {
061: private static final Log log = Log.lookup(ResourceCaches.class);
062:
063: /** Loads, parses and returns the resource of the specified URI,
064: * or null if not found. The parser is defined by the loader defined
065: * in {@link ResourceCache}.
066: *
067: * <p>If you don't need to parse the content, you might use
068: * {@link #getContent}
069: *
070: * @param cache the resource cache.
071: * Note: its loader must extend from {@link ResourceLoader}.
072: * @param path the URI path
073: * @param extra the extra parameter that will be passed to
074: * {@link ResourceLoader#parse(String,File,Object)} and
075: * {@link ResourceLoader#parse(String,URL,Object)}
076: */
077: public static final Object get(ResourceCache cache,
078: ServletContext ctx, String path, Object extra) {
079: //20050905: Tom Yeh
080: //We don't need to handle the default name if user specifies only a dir
081: //because it is handled by the container directlys
082: //And, web developer has to specify <welcome-file> in web.xml
083: // if (D.ON && log.finerable()) log.finer("Servlet path: "+path);
084: URL url = null;
085: if (path == null || path.length() == 0)
086: path = "/";
087: else if (path.charAt(0) != '/') {
088: if (path.indexOf("://") > 0) {
089: try {
090: url = new URL(path);
091: } catch (java.net.MalformedURLException ex) {
092: throw new SystemException(ex);
093: }
094: } else
095: path = '/' + path;
096: }
097:
098: if (url == null) {
099: if (path.startsWith("/~")) {
100: final ServletContext ctx0 = ctx;
101: final String path0 = path;
102: final int j = path.indexOf('/', 2);
103: final String ctxpath;
104: if (j >= 0) {
105: ctxpath = "/" + path.substring(2, j);
106: path = path.substring(j);
107: } else {
108: ctxpath = "/" + path.substring(2);
109: path = "/";
110: }
111:
112: final ExtendletContext extctx = Servlets
113: .getExtendletContext(ctx, ctxpath.substring(1));
114: if (extctx != null) {
115: url = extctx.getResource(path);
116: // if (log.debugable()) log.debug("Resolving "+path0+" to "+url);
117: if (url == null)
118: return null;
119: return cache
120: .get(new ResourceInfo(path, url, extra));
121: }
122:
123: ctx = ctx.getContext(ctxpath);
124: if (ctx == null) { //failed
125: // if (D.ON && log.debugable()) log.debug("Context not found: "+ctxpath);
126: ctx = ctx0;
127: path = path0;//restore
128: }
129: }
130:
131: final String flnm = ctx.getRealPath(path);
132: if (flnm != null) {
133: final File file = new File(flnm);
134: if (file.exists())
135: return cache
136: .get(new ResourceInfo(path, file, extra));
137: }
138: }
139:
140: //try url because some server uses JAR format
141: try {
142: if (url == null)
143: url = ctx.getResource(path);
144: if (url != null)
145: return cache.get(new ResourceInfo(path, url, extra));
146: } catch (Throwable ex) {
147: log.warning("Unable to load " + path + "\n"
148: + Exceptions.getMessage(ex));
149: }
150: return null;
151: }
152:
153: //-- direct content without parser. --//
154: private static final String ATTR_PAGE_CACHE = "org.zkoss.web.util.resource.PageCache";
155:
156: /** Returns the content of the specified path, or null if not found.
157: *
158: * <p> The content is returned directly as a string without any parsing.
159: *
160: * <p>Note: the encoding is assumed to be "UTF-8".
161: *
162: * @param path the URI path
163: */
164: public static final String getContent(ServletContext ctx,
165: String path) {
166: return (String) get(getCache(ctx), ctx, path, null);
167: }
168:
169: private static final ResourceCache getCache(ServletContext ctx) {
170: ResourceCache cache = (ResourceCache) ctx
171: .getAttribute(ATTR_PAGE_CACHE);
172: if (cache == null) {
173: synchronized (ResourceCaches.class) {
174: cache = (ResourceCache) ctx
175: .getAttribute(ATTR_PAGE_CACHE);
176: if (cache == null) {
177: cache = new ResourceCache(new ContentLoader(ctx),
178: 29);
179: cache.setMaxSize(1024);
180: cache.setLifetime(60 * 60 * 1000); //1hr
181: ctx.setAttribute(ATTR_PAGE_CACHE, cache);
182: }
183: }
184: }
185: return cache;
186: }
187:
188: private static class ContentLoader extends ResourceLoader {
189: private final ServletContext _ctx;
190:
191: private ContentLoader(ServletContext ctx) {
192: _ctx = ctx;
193: }
194:
195: //-- super --//
196: protected Object parse(String path, File file, Object extra)
197: throws Exception {
198: return readAll(new FileInputStream(file));
199: }
200:
201: protected Object parse(String path, URL url, Object extra)
202: throws Exception {
203: return readAll(url.openStream());
204: }
205:
206: private String readAll(InputStream is) throws Exception {
207: if (is == null)
208: return null;
209: return Files.readAll(new InputStreamReader(is, "UTF-8"))
210: .toString();
211: }
212: }
213: }
|