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 version 2
011: * as published by the Free Software Foundation.
012: *
013: * Resin Open Source is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
016: * of NON-INFRINGEMENT. See the GNU General Public License for more
017: * details.
018: *
019: * You should have received a copy of the GNU General Public License
020: * along with Resin Open Source; if not, write to the
021: *
022: * Free Software Foundation, Inc.
023: * 59 Temple Place, Suite 330
024: * Boston, MA 02111-1307 USA
025: *
026: * @author Scott Ferguson
027: */
028:
029: package com.caucho.jsf.cfg;
030:
031: import java.io.IOException;
032: import java.util.*;
033: import java.util.regex.*;
034: import java.util.logging.*;
035:
036: import javax.el.*;
037:
038: import javax.faces.*;
039: import javax.faces.application.*;
040: import javax.faces.component.*;
041: import javax.faces.component.html.*;
042: import javax.faces.context.*;
043: import javax.faces.convert.*;
044: import javax.faces.el.*;
045: import javax.faces.event.*;
046: import javax.faces.validator.*;
047:
048: import javax.xml.bind.annotation.*;
049:
050: import com.caucho.config.*;
051: import com.caucho.util.*;
052:
053: public class NavigationRule implements Comparable<NavigationRule> {
054: private static final Logger log = Logger
055: .getLogger(NavigationRule.class.getName());
056:
057: private String _id;
058:
059: private String _fromViewId;
060: private Pattern _fromViewIdPattern;
061:
062: private int _cost;
063:
064: private ArrayList<NavigationCase> _caseList = new ArrayList<NavigationCase>();
065:
066: public void setId(String id) {
067: _id = id;
068: }
069:
070: public void setDescription(String description) {
071: }
072:
073: public void setDisplayName(String displayName) {
074: }
075:
076: public int getCost() {
077: return _cost;
078: }
079:
080: public int compareTo(NavigationRule rule) {
081: return rule.getCost() - _cost;
082: }
083:
084: public void setFromViewId(String viewId) {
085: _fromViewId = viewId;
086:
087: _cost = viewId.length();
088:
089: StringBuilder sb = new StringBuilder();
090:
091: for (int i = 0; i < viewId.length(); i++) {
092: char ch = viewId.charAt(i);
093:
094: switch (ch) {
095: case '*':
096: if (i < _cost)
097: _cost = i;
098:
099: sb.append(".*");
100: break;
101: case '.':
102: case '?':
103: case '+':
104: case '|':
105: case '[':
106: case ']':
107: case '$':
108: case '^':
109: case '\\':
110: case '(':
111: case ')':
112: sb.append("\\");
113: sb.append(ch);
114: break;
115: default:
116: sb.append(ch);
117: break;
118: }
119: }
120:
121: _fromViewIdPattern = Pattern.compile(sb.toString());
122: }
123:
124: public boolean isMatch(String url) {
125: return (_fromViewIdPattern == null || _fromViewIdPattern
126: .matcher(url).matches());
127: }
128:
129: public void addNavigationCase(NavigationCase navCase) {
130: _caseList.add(navCase);
131: }
132:
133: public boolean handleNavigation(FacesContext context,
134: String action, String outcome) {
135: NavigationCase navCase = findCase(action, outcome);
136:
137: if (navCase != null) {
138: if (log.isLoggable(Level.FINE))
139: log.fine("Jsf[" + context.getViewRoot().getViewId()
140: + "] navigation action:" + action + " outcome:"
141: + outcome + " matches " + navCase);
142:
143: navCase.handleNavigation(context);
144: return true;
145: }
146:
147: return false;
148: }
149:
150: private NavigationCase findCase(String action, String outcome) {
151: NavigationCase bestCase = null;
152: int bestCost = -1;
153:
154: for (int i = 0; i < _caseList.size(); i++) {
155: NavigationCase navCase = _caseList.get(i);
156:
157: int cost = 0;
158:
159: if (navCase.getFromAction() == null) {
160: } else if (action != null
161: && action.equals(navCase.getFromAction()))
162: cost |= 1;
163: else
164: continue;
165:
166: if (navCase.getFromOutcome() == null) {
167: } else if (outcome != null
168: && outcome.equals(navCase.getFromOutcome()))
169: cost |= 2;
170: else
171: continue;
172:
173: if (cost == 3)
174: return navCase;
175: else if (bestCost < cost) {
176: bestCost = cost;
177: bestCase = navCase;
178: }
179: }
180:
181: return bestCase;
182: }
183:
184: public String toString() {
185: return "NavigationRule[" + _fromViewIdPattern + "]";
186: }
187:
188: public static class NavigationCase {
189: private String _fromAction;
190: private String _fromOutcome;
191:
192: private String _toViewId;
193:
194: private boolean _isRedirect;
195:
196: public void setId(String id) {
197: }
198:
199: public void setDescription(String description) {
200: }
201:
202: public void setDisplayName(String displayName) {
203: }
204:
205: public void setFromAction(String expr) {
206: _fromAction = expr;
207: }
208:
209: public String getFromAction() {
210: return _fromAction;
211: }
212:
213: public void setFromOutcome(String expr) {
214: _fromOutcome = expr;
215: }
216:
217: public String getFromOutcome() {
218: return _fromOutcome;
219: }
220:
221: public void setToViewId(String viewId) {
222: _toViewId = viewId;
223: }
224:
225: public void setRedirect(Redirect redirect) {
226: _isRedirect = true;
227: }
228:
229: public void handleNavigation(FacesContext context) {
230: if (_isRedirect) {
231: try {
232: ExternalContext extContext = context
233: .getExternalContext();
234: ViewHandler viewHandler = context.getApplication()
235: .getViewHandler();
236:
237: String actionUrl = viewHandler.getActionURL(
238: context, _toViewId);
239:
240: extContext.redirect(extContext
241: .encodeActionURL(actionUrl));
242:
243: context.responseComplete();
244: } catch (IOException e) {
245: throw new RuntimeException(e);
246: }
247: } else {
248: UIViewRoot oldView = context.getViewRoot();
249:
250: ViewHandler view = context.getApplication()
251: .getViewHandler();
252:
253: UIViewRoot viewRoot = view.createView(context,
254: _toViewId);
255:
256: // XXX: is this in spec?
257: if (oldView != null)
258: viewRoot.setLocale(oldView.getLocale());
259:
260: context.setViewRoot(viewRoot);
261: }
262: }
263:
264: public String toString() {
265: if (_isRedirect)
266: return "NavCase[redirect," + _toViewId + "]";
267: else
268: return "NavCase[" + _toViewId + "]";
269: }
270: }
271:
272: public static class Redirect {
273: public void setId(String id) {
274: }
275: }
276: }
|