001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: * Free SoftwareFoundation, Inc.
023: * 59 Temple Place, Suite 330
024: * Boston, MA 02111-1307 USA
025: *
026: * @author Scott Ferguson
027: */
028:
029: package com.caucho.jsp;
030:
031: import com.caucho.loader.DynamicClassLoader;
032: import com.caucho.log.Log;
033: import com.caucho.server.connection.CauchoRequest;
034: import com.caucho.server.util.CauchoSystem;
035: import com.caucho.server.webapp.WebApp;
036: import com.caucho.util.Alarm;
037: import com.caucho.util.L10N;
038: import com.caucho.util.LruCache;
039: import com.caucho.vfs.MergePath;
040: import com.caucho.vfs.Path;
041: import com.caucho.xsl.AbstractStylesheetFactory;
042: import com.caucho.xsl.CauchoStylesheet;
043: import com.caucho.xsl.StyleScript;
044: import com.caucho.xsl.StylesheetImpl;
045: import com.caucho.xsl.Xsl;
046:
047: import javax.servlet.ServletContext;
048: import javax.servlet.ServletException;
049: import javax.xml.transform.Templates;
050: import java.lang.ref.SoftReference;
051: import java.util.logging.Logger;
052:
053: class XslManager {
054: private static final Logger log = Log.open(XslManager.class);
055: static final L10N L = new L10N(XslManager.class);
056:
057: private WebApp _webApp;
058: private Path _workPath;
059: private LruCache<String, SoftReference<Templates>> _xslCache = new LruCache<String, SoftReference<Templates>>(
060: 256);
061: private boolean _strictXsl;
062: private long _lastUpdate;
063:
064: public XslManager(ServletContext context) {
065: _webApp = (WebApp) context;
066:
067: _workPath = CauchoSystem.getWorkPath();
068: }
069:
070: public void setStrictXsl(boolean strictXsl) {
071: _strictXsl = strictXsl;
072: }
073:
074: public String getServletInfo() {
075: return "Resin XTP";
076: }
077:
078: Templates get(String href, CauchoRequest req) throws Exception {
079: String servletPath = req.getPageServletPath();
080:
081: WebApp webApp = req.getWebApp();
082:
083: Path appDir = webApp.getAppDir();
084: Path pwd = appDir.lookupNative(webApp.getRealPath(servletPath));
085: pwd = pwd.getParent();
086:
087: String fullStyleSheet = pwd.toString() + "/" + href;
088:
089: Templates stylesheet = null;
090:
091: long now = Alarm.getCurrentTime();
092:
093: SoftReference<Templates> templateRef = _xslCache
094: .get(fullStyleSheet);
095:
096: if (templateRef != null)
097: stylesheet = templateRef.get();
098:
099: if (stylesheet instanceof StylesheetImpl
100: && !((StylesheetImpl) stylesheet).isModified())
101: return stylesheet;
102:
103: _lastUpdate = now;
104: stylesheet = getStylesheet(req, href);
105:
106: if (stylesheet == null)
107: throw new ServletException(L.l(
108: "can't find stylesheet `{0}'", href));
109:
110: _xslCache.put(fullStyleSheet, new SoftReference<Templates>(
111: stylesheet));
112:
113: return stylesheet;
114: }
115:
116: /**
117: * Returns the stylesheet given by the references.
118: */
119: Templates getStylesheet(CauchoRequest req, String href)
120: throws Exception {
121: String servletPath = req.getPageServletPath();
122:
123: WebApp webApp = req.getWebApp();
124: Path appDir = webApp.getAppDir();
125: Path pwd = appDir.lookupNative(webApp.getRealPath(servletPath));
126: pwd = pwd.getParent();
127:
128: DynamicClassLoader loader;
129: loader = (DynamicClassLoader) webApp.getClassLoader();
130:
131: MergePath stylePath = new MergePath();
132: stylePath.addMergePath(pwd);
133: stylePath.addMergePath(appDir);
134:
135: String resourcePath = loader.getResourcePathSpecificFirst();
136: stylePath.addClassPath(resourcePath);
137:
138: Path hrefPath = stylePath.lookup(href);
139:
140: if (hrefPath.canRead()) {
141: DynamicClassLoader owningLoader = getStylesheetLoader(href,
142: hrefPath);
143:
144: if (owningLoader != null) {
145: loader = owningLoader;
146:
147: stylePath = new MergePath();
148: stylePath.addMergePath(pwd);
149: stylePath.addMergePath(appDir);
150: resourcePath = loader.getResourcePathSpecificFirst();
151: stylePath.addClassPath(resourcePath);
152: }
153: }
154:
155: Thread thread = Thread.currentThread();
156: ClassLoader oldLoader = thread.getContextClassLoader();
157: try {
158: thread.setContextClassLoader(loader);
159:
160: CauchoStylesheet xsl;
161:
162: AbstractStylesheetFactory factory;
163:
164: if (_strictXsl)
165: factory = new Xsl();
166: else
167: factory = new StyleScript();
168:
169: factory.setStylePath(stylePath);
170: factory.setClassLoader(loader);
171: // factory.setWorkPath(_workPath);
172:
173: String className = "";
174:
175: if (pwd.lookup(href).canRead()) {
176: int p = req.getServletPath().lastIndexOf('/');
177: if (p >= 0)
178: className += req.getServletPath().substring(0, p);
179: }
180: /*
181: else if (href.startsWith("/"))
182: href = href.substring(1);
183: */
184:
185: className += "/" + href;
186:
187: factory.setClassName(className);
188:
189: // XXX: error here
190: return factory.newTemplates(href);
191: } finally {
192: thread.setContextClassLoader(oldLoader);
193: }
194: }
195:
196: private DynamicClassLoader getStylesheetLoader(String href,
197: Path sourcePath) {
198: DynamicClassLoader owningLoader = null;
199: ClassLoader loader = Thread.currentThread()
200: .getContextClassLoader();
201:
202: for (; loader != null; loader = loader.getParent()) {
203: if (!(loader instanceof DynamicClassLoader))
204: continue;
205:
206: DynamicClassLoader dynLoader = (DynamicClassLoader) loader;
207:
208: MergePath mp = new MergePath();
209: String resourcePath = dynLoader
210: .getResourcePathSpecificFirst();
211: mp.addClassPath(resourcePath);
212:
213: Path loaderPath = mp.lookup(href);
214:
215: if (loaderPath.getNativePath().equals(
216: sourcePath.getNativePath()))
217: owningLoader = dynLoader;
218: }
219:
220: return owningLoader;
221: }
222: }
|