001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: * $Header:$
018: */
019: package org.apache.beehive.netui.tags.internal;
020:
021: import org.apache.beehive.netui.core.urls.URLType;
022: import org.apache.beehive.netui.pageflow.FlowController;
023: import org.apache.beehive.netui.pageflow.PageFlowConstants;
024: import org.apache.beehive.netui.pageflow.PageFlowUtils;
025: import org.apache.beehive.netui.pageflow.config.PageFlowActionMapping;
026: import org.apache.beehive.netui.pageflow.internal.InternalConstants;
027: import org.apache.beehive.netui.tags.rendering.TagRenderingBase;
028: import org.apache.struts.Globals;
029: import org.apache.struts.action.ActionMapping;
030: import org.apache.struts.config.ActionConfig;
031: import org.apache.struts.util.TokenProcessor;
032:
033: import javax.servlet.ServletContext;
034: import javax.servlet.http.HttpServletRequest;
035: import javax.servlet.http.HttpServletResponse;
036: import javax.servlet.http.HttpSession;
037: import javax.servlet.jsp.PageContext;
038: import java.net.URISyntaxException;
039: import java.util.Map;
040:
041: /**
042: * This is a utility class for the beehive tags with routines for helping with URL rewriting.
043: *
044: * <p> Includes methods to create a fully-rewritten url based on an initial url with query
045: * parameters and an anchor (location on page), checking if it needs to be secure and
046: * rewriting. There's also a method to check if a url is an action. </p>
047: */
048: public class PageFlowTagUtils {
049: /**
050: * Create a fully-rewritten url from an initial action url with query parameters
051: * and an anchor (location on page), checking if it needs to be secure then call
052: * the rewriter service using a type of {@link org.apache.beehive.netui.core.urls.URLType#ACTION}.
053: * @param pageContext the current PageContext.
054: * @param action the action url to rewrite.
055: * @param params the query parameters for this url.
056: * @param location the location (anchor or fragment) for this url.
057: * @return a uri that has been run through the URL rewriter service.
058: */
059: public static String rewriteActionURL(PageContext pageContext,
060: String action, Map params, String location)
061: throws URISyntaxException {
062: ServletContext servletContext = pageContext.getServletContext();
063: HttpServletRequest request = (HttpServletRequest) pageContext
064: .getRequest();
065: HttpServletResponse response = (HttpServletResponse) pageContext
066: .getResponse();
067: boolean forXML = TagRenderingBase.Factory.isXHTML(request);
068: if (action.length() > 0 && action.charAt(0) == '/')
069: action = action.substring(1);
070: return PageFlowUtils.getRewrittenActionURI(servletContext,
071: request, response, action, params, location, forXML);
072: }
073:
074: /**
075: * Create a fully-rewritten url from an initial href url with query parameters
076: * and an anchor (location on page), checking if it needs to be secure then call
077: * the rewriter service using a type of {@link org.apache.beehive.netui.core.urls.URLType#ACTION}.
078: * @param pageContext the current PageContext.
079: * @param url the href url to rewrite.
080: * @param params the query parameters for this url.
081: * @param location the location (anchor or fragment) for this url.
082: * @return a url that has been run through the URL rewriter service.
083: * @see PageFlowUtils#getRewrittenHrefURI(javax.servlet.ServletContext, javax.servlet.http.HttpServletRequest,
084: * javax.servlet.http.HttpServletResponse, String, java.util.Map, String, boolean)
085: */
086: public static String rewriteHrefURL(PageContext pageContext,
087: String url, Map params, String location)
088: throws URISyntaxException {
089: ServletContext servletContext = pageContext.getServletContext();
090: HttpServletRequest request = (HttpServletRequest) pageContext
091: .getRequest();
092: HttpServletResponse response = (HttpServletResponse) pageContext
093: .getResponse();
094: boolean forXML = TagRenderingBase.Factory.isXHTML(request);
095: return PageFlowUtils.getRewrittenHrefURI(servletContext,
096: request, response, url, params, location, forXML);
097: }
098:
099: /**
100: * Create a fully-rewritten url from an initial resource url with query parameters
101: * and an anchor (location on page), checking if it needs to be secure then call
102: * the rewriter service using a type of {@link org.apache.beehive.netui.core.urls.URLType#RESOURCE}.
103: * @param pageContext the current PageContext.
104: * @param url the resource url to rewrite.
105: * @param params the query parameters for this url.
106: * @param location the location (anchor or fragment) for this url.
107: * @return a url that has been run through the URL rewriter service.
108: * @see PageFlowUtils#getRewrittenResourceURI(javax.servlet.ServletContext, javax.servlet.http.HttpServletRequest,
109: * javax.servlet.http.HttpServletResponse, String, java.util.Map, String, boolean)
110: */
111: public static String rewriteResourceURL(PageContext pageContext,
112: String url, Map params, String location)
113: throws URISyntaxException {
114: ServletContext servletContext = pageContext.getServletContext();
115: HttpServletRequest request = (HttpServletRequest) pageContext
116: .getRequest();
117: HttpServletResponse response = (HttpServletResponse) pageContext
118: .getResponse();
119: boolean forXML = TagRenderingBase.Factory.isXHTML(request);
120: return PageFlowUtils.getRewrittenResourceURI(servletContext,
121: request, response, url, params, location, forXML);
122: }
123:
124: /**
125: * Determine whether a given URI is an Action.
126: * @param request the current HttpServletRequest.
127: * @param action the URI to check.
128: * @return <code>true</code> if the action is defined in the current page flow
129: * or in a shared flow. Otherwise, return <code>false</code>.
130: */
131: public static boolean isAction(HttpServletRequest request,
132: String action) {
133: FlowController flowController = PageFlowUtils
134: .getCurrentPageFlow(request);
135:
136: if (flowController != null) {
137: if (action.endsWith(PageFlowConstants.ACTION_EXTENSION)) {
138: action = action.substring(0, action.length()
139: - PageFlowConstants.ACTION_EXTENSION.length());
140: }
141:
142: if (getActionMapping(request, flowController, action) != null)
143: return true;
144: FlowController globalApp = PageFlowUtils.getSharedFlow(
145: InternalConstants.GLOBALAPP_CLASSNAME, request);
146: return getActionMapping(request, globalApp, action) != null;
147: }
148:
149: return true;
150: }
151:
152: /**
153: * Get or generate a token used to prevent double submits to an action. The token is stored in the session,
154: * and checked (and removed) when processing an action with the <code>preventDoubleSubmit</code> attribute
155: * set to <code>true</code>.
156: */
157: public static String getToken(HttpServletRequest request,
158: String action) {
159: FlowController flowController = PageFlowUtils
160: .getCurrentPageFlow(request);
161:
162: if (flowController != null) {
163: MappingAndController mac = getActionMapping(request,
164: flowController, action);
165: if (mac != null)
166: return getToken(request, mac.mapping);
167: }
168:
169: return null;
170: }
171:
172: /**
173: * Get or generate a token used to prevent double submits to an action. The token is stored in the session,
174: * and checked (and removed) when processing an action with the <code>preventDoubleSubmit</code> attribute
175: * set to <code>true</code>.
176: */
177: public static String getToken(HttpServletRequest request,
178: ActionMapping mapping) {
179: if (mapping instanceof PageFlowActionMapping
180: && ((PageFlowActionMapping) mapping)
181: .isPreventDoubleSubmit()) {
182: HttpSession session = request.getSession();
183: String token = (String) session
184: .getAttribute(Globals.TRANSACTION_TOKEN_KEY);
185: if (token != null)
186: return token;
187: token = TokenProcessor.getInstance().generateToken(request);
188: request.getSession().setAttribute(
189: Globals.TRANSACTION_TOKEN_KEY, token);
190: return token;
191: }
192:
193: return null;
194: }
195:
196: public static class MappingAndController {
197: public ActionMapping mapping;
198: public FlowController controller;
199: }
200:
201: public static MappingAndController getActionMapping(
202: HttpServletRequest request, FlowController flowController,
203: String action) {
204: ActionConfig mapping = null;
205: FlowController fc = null;
206:
207: if (flowController != null) {
208: //
209: // If there's a '.' delimiter, it's a shared flow action.
210: //
211: int dot = action.indexOf('.');
212:
213: if (dot == -1) {
214: //
215: // It's an action in the current page flow, or in the (deprecated) Global.app.
216: //
217: if (action.charAt(0) != '/')
218: action = '/' + action;
219: mapping = flowController.theModuleConfig()
220: .findActionConfig(action);
221: fc = flowController;
222:
223: //
224: // If we don't find it in the current page flow, look in Global.app.
225: //
226: if (mapping == null) {
227: FlowController globalApp = PageFlowUtils
228: .getSharedFlow(
229: InternalConstants.GLOBALAPP_CLASSNAME,
230: request);
231: if (globalApp != null) {
232: mapping = globalApp.theModuleConfig()
233: .findActionConfig(action);
234: fc = globalApp;
235: }
236: }
237: } else if (dot < action.length() - 1) {
238: //
239: // It's an action in a shared flow.
240: //
241: String sharedFlowName = action.substring(0, dot);
242: if (sharedFlowName.length() > 0
243: && sharedFlowName.charAt(0) == '/') {
244: sharedFlowName = sharedFlowName.substring(1);
245: }
246:
247: FlowController sharedFlow = (FlowController) PageFlowUtils
248: .getSharedFlows(request).get(sharedFlowName);
249:
250: if (sharedFlow != null) {
251: String actionPath = '/' + action.substring(dot + 1);
252: mapping = sharedFlow.theModuleConfig()
253: .findActionConfig(actionPath);
254: fc = sharedFlow;
255: }
256: }
257: }
258:
259: assert mapping == null || mapping instanceof ActionMapping : mapping
260: .getClass().getName();
261:
262: if (mapping != null) {
263: MappingAndController mac = new MappingAndController();
264: mac.mapping = (ActionMapping) mapping;
265: mac.controller = fc;
266: return mac;
267: }
268:
269: return null;
270: }
271: }
|