001: /* Copyright 2001 The JA-SIG Collaborative. All rights reserved.
002: * See license distributed with this file and
003: * available online at http://www.uportal.org/license.html
004: */
005:
006: package org.jasig.portal.utils;
007:
008: import java.io.BufferedReader;
009: import java.io.IOException;
010: import java.io.InputStreamReader;
011: import java.io.OutputStreamWriter;
012: import java.net.HttpURLConnection;
013: import java.net.URL;
014: import java.util.Enumeration;
015:
016: import javax.servlet.http.HttpServletRequest;
017: import javax.servlet.http.HttpServletResponse;
018:
019: import org.jasig.portal.PortalException;
020: import org.jasig.portal.PortalSessionManager;
021: import org.jasig.portal.UPFileSpec;
022: import org.jasig.portal.UserInstance;
023: import org.apache.commons.logging.Log;
024: import org.apache.commons.logging.LogFactory;
025:
026: /**
027: * The URLUtil class offers static helper methods for manipulating the
028: * request parameters and URLs of both HTTP GET and HTTP POST requests
029: * and performing redirections based on the new parameters and URLs.
030: * and request parameters.
031: *
032: * @author Andreas Christoforides, achristoforides@unicon.net
033: * @author Nick Bolton, nbolton@unicon.net
034: * @version $Revision: 35492 $
035: */
036:
037: public class URLUtil {
038:
039: private static final Log log = LogFactory.getLog(URLUtil.class);
040:
041: public static final int REDIRECT_URL_LIMIT = 512;
042:
043: public static final String HTTP_GET_REQUEST = "GET";
044: public static final String HTTP_POST_REQUEST = "POST";
045:
046: /**
047: * Performs a redirect for both HTTP GET and HTTP POST requests
048: * based on the the specified target channel and parameters to be ignored.
049: *
050: * @param req An HttpServletRequest object.
051: * @param res An HttpServletResponse object.
052: * @param targetNodeId The target node Id of a channel.
053: * @param ignoreParams An array of String objects containing
054: * the parameters to be ignored.
055: */
056: public static void redirect(HttpServletRequest req,
057: HttpServletResponse res, String targetNodeId,
058: boolean asRoot, String[] ignoreParams, String charset)
059: throws PortalException {
060: String extras = new UPFileSpec(req).getUPFileExtras();
061: UPFileSpec uPFileSpec = buildUPFileSpec(targetNodeId, extras,
062: asRoot);
063:
064: // only handles get methods at this time
065: redirectGet(req, res, uPFileSpec, ignoreParams);
066:
067: // Determine if this is an HTTP GET or POST request
068: /*
069: if (httpMethod.equalsIgnoreCase(HTTP_GET_REQUEST)) {
070: redirectGet(req, res, uPFileSpec, ignoreParams);
071: } else if (httpMethod.equalsIgnoreCase(HTTP_POST_REQUEST)) {
072: redirectPost(req, res, uPFileSpec, ignoreParams, charset);
073: }
074: */
075: }
076:
077: /**
078: * Uses an HttpServletRequest object and a String array that
079: * contains the names of parameters to be ignored to construct
080: * a filtered name-value pair string.
081: *
082: * @param req A HttpServletRequest object.
083: * @param ignoreParams An array of String objects representing
084: * the parameters to be ignored.
085: *
086: * @return A String of name-value pairs representing a query string. .
087: */
088: private static String buildRequestParams(HttpServletRequest req,
089: String[] ignoreParams) {
090: String parameterName = null;
091: String[] parameterValues = null;
092:
093: StringBuffer sb = new StringBuffer(REDIRECT_URL_LIMIT);
094:
095: // Get all parameters
096: Enumeration requestParameterNames = req.getParameterNames();
097:
098: // Walk through all parameter names
099: while (requestParameterNames.hasMoreElements()) {
100: // Get parameter name
101: parameterName = (String) requestParameterNames
102: .nextElement();
103:
104: // Exclude the parameter that are in the ignoreParams array
105: // and only include parameters If they came from
106: if (!parameterExistsIn(parameterName, ignoreParams)) {
107: // Get all values of parameter in case it is a
108: // multi-value parameter
109: parameterValues = req.getParameterValues(parameterName);
110:
111: // Add parameter name-value pairs
112: for (int index = 0; index < parameterValues.length; index++) {
113: sb.append(parameterName);
114: sb.append("=");
115: sb.append(parameterValues[index]);
116: sb.append("&");
117: }
118: }
119: }
120:
121: // Truncate the extra '&' from the end if one exists
122: if (sb.length() != 0 && sb.charAt(sb.length() - 1) == '&') {
123: sb.setLength(sb.length() - 1);
124: }
125:
126: return sb.toString();
127: }
128:
129: /**
130: * Determines if the specified parameter exists within
131: * the specified String array.
132: *
133: * @param param The parameter name to search for in the array of parameters.
134: * @param params The array of parameters to search in.
135: *
136: * @return Returns true if the parameter name is found, false otherwise.
137: */
138: private static boolean parameterExistsIn(String param,
139: String[] params) {
140: boolean found = false;
141:
142: for (int index = 0; index < params.length; index++) {
143: if (param.equals(params[index])) {
144: found = true;
145: }
146: }
147:
148: return found;
149: }
150:
151: /**
152: * Constructs a generic UPFileSpec object using the specified
153: * target node id.
154: *
155: * @param targetNodeId The target node id to be used in the
156: * UPFileSpec object.
157: *
158: * @return A generic UPFileSpec object.
159: */
160: private static UPFileSpec buildUPFileSpec(String targetNodeId,
161: String extras, boolean asRoot) throws PortalException {
162: UPFileSpec up = null;
163:
164: if (asRoot) {
165: up = new UPFileSpec(
166: PortalSessionManager.IDEMPOTENT_URL_TAG,
167: UPFileSpec.RENDER_METHOD, targetNodeId, null,
168: extras);
169: } else {
170: up = new UPFileSpec(
171: PortalSessionManager.IDEMPOTENT_URL_TAG,
172: UPFileSpec.RENDER_METHOD,
173: UserInstance.USER_LAYOUT_ROOT_NODE, targetNodeId,
174: extras);
175: }
176:
177: return up;
178: }
179:
180: /**
181: * Performs a HTTP GET redirect using the specified UPFileSpec
182: * and parameters to be ignored.
183: *
184: * @param req An HttpServletRequest object.
185: * @param res An HttpServletResponse object.
186: * @param up the uPortal file spec.
187: * @param ignoreParams An array of String objects containing
188: * the parameters to be ignored.
189: */
190: public static void redirectGet(HttpServletRequest req,
191: HttpServletResponse res, UPFileSpec up,
192: String[] ignoreParams) throws PortalException {
193:
194: StringBuffer sb = new StringBuffer(REDIRECT_URL_LIMIT);
195:
196: try {
197: sb.append(up.getUPFile());
198: String qs = req.getQueryString();
199: if (qs != null && !"".equals(qs)) {
200: sb.append('?').append(
201: buildRequestParams(req, ignoreParams));
202: }
203: if (log.isDebugEnabled())
204: log.debug("URLUtil::redirectGet() "
205: + "Redirecting to framework: " + sb.toString());
206: res.sendRedirect(res.encodeRedirectURL(sb.toString()));
207: } catch (IOException ioe) {
208: log.error("URLUtil::redirectGet() "
209: + "Failed redirecting to framework: "
210: + sb.toString(), ioe);
211: throw new PortalException(ioe);
212: }
213: }
214:
215: private static void buildHeader(HttpServletRequest req,
216: HttpURLConnection uconn) {
217: String name;
218: String value;
219: String currentValue;
220: Enumeration fields = req.getHeaderNames();
221: while (fields.hasMoreElements()) {
222: name = (String) fields.nextElement();
223: value = req.getHeader(name);
224: currentValue = uconn.getRequestProperty(name);
225: if (currentValue != null && !"".equals(currentValue)) {
226: value = currentValue + ',' + value;
227: }
228: uconn.setRequestProperty(name, value);
229: }
230: }
231:
232: /**
233: * Performs a HTTP POST redirect using the specified
234: * UPFileSpec and parameters to be ignored.
235: *
236: * @param req An HttpServletRequest object.
237: * @param res An HttpServletResponse object.
238: * @param up the uPortal file spec.
239: * @param ignoreParams An array of String objects containing
240: * the parameters to be ignored.
241: */
242: public static void redirectPost(HttpServletRequest req,
243: HttpServletResponse res, UPFileSpec up,
244: String[] ignoreParams, String charset)
245: throws PortalException {
246:
247: String parameters = buildRequestParams(req, ignoreParams);
248: StringBuffer urlStr = new StringBuffer(REDIRECT_URL_LIMIT);
249: String this Uri = req.getRequestURI();
250:
251: urlStr.append("http://").append(req.getServerName());
252: urlStr.append(":").append(req.getServerPort());
253:
254: int pos = this Uri.indexOf("tag");
255: if (pos >= 0) {
256: urlStr.append(this Uri.substring(0, pos));
257: urlStr.append(up.getUPFile());
258: } else {
259: log.error("URLUtil::redirectPost() "
260: + "Invalid url, no tag found: " + this Uri);
261: throw new PortalException("Invalid URL, no tag found: "
262: + this Uri);
263: }
264:
265: if (log.isDebugEnabled())
266: log.debug("URLUtil::redirectPost() "
267: + "Redirecting to framework: " + urlStr.toString());
268: OutputStreamWriter wr = null;
269: BufferedReader br = null;
270: HttpURLConnection conn = null;
271:
272: try {
273: URL url = new URL(urlStr.toString());
274: conn = (HttpURLConnection) url.openConnection();
275:
276: conn.setDoOutput(true);
277: conn.setDoInput(true);
278:
279: // forward the headers
280: buildHeader(req, conn);
281:
282: // post the parameters
283: wr = new OutputStreamWriter(conn.getOutputStream(), charset);
284: wr.write(parameters);
285: wr.flush();
286:
287: // now let's get the results
288: conn.connect(); // throws IOException
289: br = new BufferedReader(new InputStreamReader(conn
290: .getInputStream(), charset));
291: StringBuffer results = new StringBuffer(512);
292: String oneline;
293: while ((oneline = br.readLine()) != null) {
294: results.append(oneline).append('\n');
295: }
296:
297: // send the results back to the original requestor
298: res.getWriter().print(results.toString());
299: } catch (IOException ioe) {
300: log.error(ioe, ioe);
301: throw new PortalException(ioe);
302: } finally {
303: try {
304: if (br != null)
305: br.close();
306: if (wr != null)
307: wr.close();
308: if (conn != null)
309: conn.disconnect();
310: } catch (IOException exception) {
311: log
312: .error("URLUtil:redirectPost()::Unable to close Resources "
313: + exception);
314: }
315: }
316: }
317: }
|