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: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.server.webapp;
031:
032: import com.caucho.config.ConfigException;
033: import com.caucho.config.types.PathBuilder;
034: import com.caucho.server.dispatch.UrlMap;
035: import com.caucho.util.L10N;
036: import com.caucho.vfs.Path;
037:
038: import javax.annotation.PostConstruct;
039: import java.util.ArrayList;
040: import java.util.logging.Level;
041: import java.util.logging.Logger;
042: import java.util.regex.Matcher;
043: import java.util.regex.Pattern;
044:
045: /**
046: * Configuration for a rewrite-real-path
047: */
048: public class RewriteRealPath {
049: static final L10N L = new L10N(RewriteRealPath.class);
050: static final Logger log = Logger.getLogger(RewriteRealPath.class
051: .getName());
052:
053: private Path _appDir;
054:
055: private final ArrayList<Program> _programList = new ArrayList<Program>();
056:
057: // path mapping (old path-mapping)
058: private UrlMap<String> _pathMapping;
059:
060: public RewriteRealPath(Path appDir) {
061: _appDir = appDir;
062: }
063:
064: /**
065: * Adds a rewrite
066: */
067: public void addRewrite(Rewrite rewrite) {
068: _programList.add(rewrite);
069: }
070:
071: /**
072: * Adds a real-path.
073: */
074: public void addRealPath(RealPath realPath) {
075: _programList.add(realPath);
076: }
077:
078: /**
079: * Adds a path pattern.
080: */
081: public void addPathPattern(String urlPattern, String realPath) {
082: if (_pathMapping == null)
083: _pathMapping = new UrlMap<String>();
084:
085: _pathMapping.addMap(urlPattern, realPath);
086: }
087:
088: /**
089: * Adds a path pattern.
090: */
091: public void addPathRegexp(String urlRegexp, String realPath) {
092: if (_pathMapping == null)
093: _pathMapping = new UrlMap<String>();
094:
095: _pathMapping.addRegexp(urlRegexp, realPath);
096: }
097:
098: /**
099: * Maps the path.
100: */
101: public String mapToRealPath(String uri) {
102: for (int i = 0; i < _programList.size(); i++) {
103: Program program = _programList.get(i);
104:
105: uri = program.rewrite(uri);
106:
107: String realPath = program.toRealPath(uri);
108:
109: if (realPath != null)
110: return _appDir.lookup(realPath).getNativePath();
111: }
112:
113: return pathMappingToRealPath(uri);
114: }
115:
116: /**
117: * Compatibility mapping to real path.
118: */
119: private String pathMappingToRealPath(String uri) {
120: if (_pathMapping == null)
121: return _appDir.lookup("./" + uri).getNativePath();
122:
123: ArrayList<String> regexpVars = new ArrayList<String>();
124:
125: String map = _pathMapping.map(uri, regexpVars);
126:
127: Path path;
128: if (map == null)
129: path = _appDir.lookup("./" + uri);
130: else {
131: try {
132: path = PathBuilder.lookupPath(map, regexpVars);
133: } catch (Exception e) {
134: log.log(Level.WARNING, e.toString(), e);
135:
136: path = _appDir.lookup(map);
137: }
138:
139: String match = (String) regexpVars.get(0);
140: String tail = uri.substring(match.length());
141:
142: // hacks to get the trailing '/' correct
143: if (uri.endsWith("/") && !tail.endsWith("/"))
144: tail = tail + '/';
145:
146: if (tail.startsWith("/"))
147: tail = '.' + tail;
148:
149: if (!tail.equals(""))
150: path = path.lookup(tail);
151: }
152:
153: String nativePath = path.getNativePath();
154:
155: // server/108j expects case insensitive
156: /*
157: if (CaseInsensitive.isCaseInsensitive())
158: return nativePath.toLowerCase();
159: else
160: return nativePath;
161: */
162:
163: return nativePath;
164: }
165:
166: static class Program {
167: public String rewrite(String uri) {
168: return uri;
169: }
170:
171: public String toRealPath(String uri) {
172: return null;
173: }
174: }
175:
176: public static class Rewrite extends Program {
177: private Pattern _regexp;
178: private String _replacement;
179:
180: /**
181: * Sets the regular expression.
182: */
183: public void setRegexp(String regexp) {
184: _regexp = Pattern.compile(regexp);
185: }
186:
187: /**
188: * Sets the target.
189: */
190: public void setReplacement(String replacement) {
191: _replacement = replacement;
192: }
193:
194: /**
195: * Init
196: */
197: @PostConstruct
198: public void init() throws ConfigException {
199: if (_regexp == null)
200: throw new ConfigException(L
201: .l("rewrite needs 'regexp' attribute."));
202: if (_replacement == null)
203: throw new ConfigException(L
204: .l("rewrite needs 'replacement' attribute."));
205: }
206:
207: public String rewrite(String uri) {
208: Matcher matcher = _regexp.matcher(uri);
209:
210: if (matcher.find()) {
211: matcher.reset();
212: return matcher.replaceAll(_replacement);
213: } else
214: return uri;
215: }
216: }
217:
218: public static class RealPath extends Program {
219: private Pattern _regexp;
220: private String _target;
221:
222: /**
223: * Sets the regular expression.
224: */
225: public void setRegexp(String regexp) {
226: _regexp = Pattern.compile(regexp);
227: }
228:
229: /**
230: * Sets the target.
231: */
232: public void setTarget(String target) {
233: StringBuilder sb = new StringBuilder();
234:
235: int length = target.length();
236: for (int i = 0; i < length; i++) {
237: char ch = target.charAt(i);
238: char ch1;
239:
240: if (ch == '\\'
241: && i + 1 < length
242: && !('0' <= (ch1 = target.charAt(i + 1)) && ch1 <= '9')) {
243: sb.append("\\\\");
244: } else
245: sb.append(ch);
246: }
247:
248: _target = sb.toString();
249: }
250:
251: /**
252: * Init
253: */
254: @PostConstruct
255: public void init() throws ConfigException {
256: if (_regexp == null)
257: throw new ConfigException(L
258: .l("real-path needs 'regexp' attribute."));
259: if (_target == null)
260: throw new ConfigException(L
261: .l("real-path needs 'target' attribute."));
262: }
263:
264: public String toRealPath(String uri) {
265: Matcher matcher = _regexp.matcher(uri);
266:
267: if (matcher.find()) {
268: matcher.reset();
269:
270: return matcher.replaceAll(_target);
271: } else
272: return null;
273: }
274: }
275: }
|