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 Sam
028: */
029:
030: package com.caucho.server.rewrite;
031:
032: import com.caucho.config.ConfigException;
033: import com.caucho.server.webapp.WebApp;
034: import com.caucho.util.L10N;
035: import com.caucho.util.*;
036: import com.caucho.make.*;
037: import com.caucho.vfs.*;
038:
039: import javax.annotation.PostConstruct;
040: import javax.servlet.FilterChain;
041: import javax.servlet.ServletException;
042: import javax.servlet.http.HttpServletResponse;
043: import java.util.ArrayList;
044: import java.util.logging.Logger;
045:
046: public class MatchRule extends AbstractRuleWithConditions implements
047: AlarmListener {
048: private static final L10N L = new L10N(MatchRule.class);
049:
050: private static final Logger log = Logger.getLogger(MatchRule.class
051: .getName());
052:
053: private DependencyContainer _depend = new DependencyContainer();
054:
055: private ArrayList<Rule> _ruleList = new ArrayList<Rule>();
056:
057: private FilterChainMapper _lastFilterChainMapper = new LastFilterChainMapper();
058: private Rule _firstRule;
059: private Rule _lastRule;
060:
061: private Alarm _alarm;
062:
063: protected MatchRule(RewriteDispatch rewriteDispatch) {
064: super (rewriteDispatch);
065:
066: super .setPassFilterChainMapper(new FirstFilterChainMapper());
067: }
068:
069: public String getTagName() {
070: return "match";
071: }
072:
073: public boolean isModified() {
074: return _depend.isModified();
075: }
076:
077: public void addDependency(PersistentDependency depend) {
078: _depend.add(depend);
079: }
080:
081: public void setPassFilterChainMapper(
082: FilterChainMapper nextFilterChainMapper) {
083: // overriden and set in constructor
084: }
085:
086: private void add(Rule rule) {
087: if (_firstRule == null)
088: _firstRule = rule;
089:
090: if (_lastRule != null) {
091: _lastRule.setPassFilterChainMapper(rule);
092: _lastRule.setFailFilterChainMapper(rule);
093: }
094:
095: rule.setPassFilterChainMapper(_lastFilterChainMapper);
096: rule.setFailFilterChainMapper(_lastFilterChainMapper);
097:
098: _lastRule = rule;
099:
100: _ruleList.add(rule);
101:
102: }
103:
104: /**
105: * Adds a dispatch.
106: */
107: public AcceptRule createDispatch() {
108: return new AcceptRule(getRewriteDispatch());
109: }
110:
111: public void addDispatch(AcceptRule dispatch) {
112: add(dispatch);
113: }
114:
115: /**
116: * Adds a forbidden.
117: */
118: public ErrorRule createForbidden() {
119: return new ErrorRule(getRewriteDispatch(),
120: HttpServletResponse.SC_FORBIDDEN);
121: }
122:
123: public void addForbidden(ErrorRule forbidden) {
124: add(forbidden);
125: }
126:
127: /**
128: * Adds a forward.
129: */
130: public ForwardRule createForward() {
131: return new ForwardRule(getRewriteDispatch());
132: }
133:
134: public void addForward(ForwardRule forward) {
135: add(forward);
136: }
137:
138: /**
139: * Adds a gone.
140: */
141: public ErrorRule createGone() {
142: return new ErrorRule(getRewriteDispatch(),
143: HttpServletResponse.SC_GONE);
144: }
145:
146: public void addGone(ErrorRule gone) {
147: add(gone);
148: }
149:
150: public ImportRule createImport() {
151: return new ImportRule(getRewriteDispatch());
152: }
153:
154: public void addImport(ImportRule importRule) {
155: add(importRule);
156: }
157:
158: /**
159: * Adds a load-balance
160: */
161: public LoadBalanceRule createLoadBalance() {
162: WebApp webApp = getRewriteDispatch().getWebApp();
163:
164: if (webApp == null)
165: throw new ConfigException(
166: L
167: .l("<load-balance> requires a web-app. Host-based <rewrite-dispatch> can not use <load-balance>."));
168:
169: return new LoadBalanceRule(getRewriteDispatch(), webApp);
170: }
171:
172: public void addLoadBalance(LoadBalanceRule loadBalance) {
173: add(loadBalance);
174: }
175:
176: /**
177: * Adds a proxy
178: */
179: public ProxyRule createProxy() {
180: WebApp webApp = getRewriteDispatch().getWebApp();
181:
182: if (webApp == null)
183: throw new ConfigException(
184: L
185: .l("<proxy> requires a web-app. Host-based <rewrite-dispatch> can not use <proxy>."));
186:
187: return new ProxyRule(getRewriteDispatch(), webApp);
188: }
189:
190: public void addProxy(ProxyRule proxy) {
191: add(proxy);
192: }
193:
194: public MatchRule createMatch() {
195: return new MatchRule(getRewriteDispatch());
196: }
197:
198: public void addMatch(MatchRule match) {
199: add(match);
200: }
201:
202: /**
203: * Adds a moved permanently (301)
204: */
205: public MovedRule createMovedPermanently() {
206: return new MovedRule(getRewriteDispatch(),
207: HttpServletResponse.SC_MOVED_PERMANENTLY);
208: }
209:
210: public void addMovedPermanently(MovedRule moved) {
211: add(moved);
212: }
213:
214: /**
215: * Adds a not-found.
216: */
217: public ErrorRule createNotFound() {
218: return new ErrorRule(getRewriteDispatch(),
219: HttpServletResponse.SC_NOT_FOUND);
220: }
221:
222: public void addNotFound(ErrorRule notFound) {
223: add(notFound);
224: }
225:
226: /**
227: * Adds a redirect.
228: */
229: public RedirectRule createRedirect() {
230: return new RedirectRule(getRewriteDispatch());
231: }
232:
233: public void addRedirect(RedirectRule redirect) {
234: add(redirect);
235: }
236:
237: /**
238: * Adds a rewrite
239: */
240: public RewriteRule createRewrite() {
241: return new RewriteRule(getRewriteDispatch());
242: }
243:
244: public void addRewrite(RewriteRule rewrite) {
245: add(rewrite);
246: }
247:
248: /**
249: * Adds a set
250: */
251: public SetRule createSet() {
252: return new SetRule(getRewriteDispatch());
253: }
254:
255: public void addSet(SetRule set) {
256: add(set);
257: }
258:
259: @Override
260: public void init() {
261: super .init();
262:
263: _ruleList.trimToSize();
264:
265: register();
266:
267: if (_depend.size() > 0) {
268: _alarm = new Alarm(this );
269:
270: handleAlarm(_alarm);
271: }
272: }
273:
274: public FilterChain dispatch(String uri, String queryString,
275: FilterChain accept, FilterChainMapper next)
276: throws ServletException {
277: return null;
278: }
279:
280: @Override
281: synchronized public void register() {
282: super .register();
283:
284: ArrayList<Rule> ruleList = new ArrayList<Rule>();
285:
286: if (_ruleList != null)
287: ruleList.addAll(_ruleList);
288:
289: for (Rule rule : ruleList) {
290: rule.register();
291: }
292: }
293:
294: @Override
295: synchronized public void unregister() {
296: ArrayList<Rule> ruleList = new ArrayList<Rule>();
297:
298: if (_ruleList != null)
299: ruleList.addAll(_ruleList);
300:
301: for (Rule rule : ruleList) {
302: rule.unregister();
303: }
304:
305: super .unregister();
306: }
307:
308: public void handleAlarm(Alarm alarm) {
309: if (_ruleList == null) {
310: } else if (_depend.isModified()) {
311: getRewriteDispatch().clearCache();
312: } else {
313: long time = _depend.getCheckInterval();
314: if (time >= 0 && time < 5000)
315: time = 5000;
316:
317: if (time > 0) {
318: alarm.queue(time);
319: }
320: }
321: }
322:
323: @Override
324: public void destroy() {
325: unregister();
326:
327: ArrayList<Rule> ruleList = new ArrayList<Rule>();
328:
329: if (_ruleList != null)
330: ruleList.addAll(_ruleList);
331:
332: _ruleList = null;
333:
334: for (Rule rule : ruleList) {
335: // XXX: s/b Config.destroy(rule);
336: rule.destroy();
337: }
338:
339: Alarm alarm = _alarm;
340: _alarm = null;
341:
342: if (alarm != null)
343: alarm.dequeue();
344:
345: super .destroy();
346: }
347:
348: private class FirstFilterChainMapper implements FilterChainMapper {
349: public FilterChain map(String uri, String queryString,
350: FilterChain accept) throws ServletException {
351: if (_firstRule != null)
352: return _firstRule.map(uri, queryString, accept);
353: else
354: return _lastFilterChainMapper.map(uri, queryString,
355: accept);
356: }
357: }
358:
359: private class LastFilterChainMapper implements FilterChainMapper {
360: public FilterChain map(String uri, String queryString,
361: FilterChain accept) throws ServletException {
362: FilterChainMapper failFilterChainMapper = getFailFilterChainMapper();
363:
364: if (failFilterChainMapper != null)
365: return failFilterChainMapper.map(uri, queryString,
366: accept);
367: else
368: return accept;
369: }
370: }
371: }
|