001: /*
002: * UIUtil.java
003: *
004: * Version: $Revision: 2168 $
005: *
006: * Date: $Date: 2007-08-27 17:40:09 -0500 (Mon, 27 Aug 2007) $
007: *
008: * Copyright (c) 2002-2005, Hewlett-Packard Company and Massachusetts
009: * Institute of Technology. All rights reserved.
010: *
011: * Redistribution and use in source and binary forms, with or without
012: * modification, are permitted provided that the following conditions are
013: * met:
014: *
015: * - Redistributions of source code must retain the above copyright
016: * notice, this list of conditions and the following disclaimer.
017: *
018: * - Redistributions in binary form must reproduce the above copyright
019: * notice, this list of conditions and the following disclaimer in the
020: * documentation and/or other materials provided with the distribution.
021: *
022: * - Neither the name of the Hewlett-Packard Company nor the name of the
023: * Massachusetts Institute of Technology nor the names of their
024: * contributors may be used to endorse or promote products derived from
025: * this software without specific prior written permission.
026: *
027: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
028: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
029: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
030: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
031: * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
032: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
033: * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
034: * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
035: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
036: * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
037: * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
038: * DAMAGE.
039: */
040: package org.dspace.app.webui.util;
041:
042: import java.io.PrintWriter;
043: import java.io.StringWriter;
044: import java.sql.SQLException;
045: import java.util.Date;
046: import java.util.Enumeration;
047: import java.util.Locale;
048:
049: import javax.servlet.http.HttpServletRequest;
050: import javax.servlet.http.HttpSession;
051: import javax.servlet.jsp.jstl.core.Config;
052:
053: import org.apache.log4j.Logger;
054: import org.dspace.app.util.Util;
055: import org.dspace.authenticate.AuthenticationManager;
056: import org.dspace.content.Collection;
057: import org.dspace.content.Community;
058: import org.dspace.content.DCDate;
059: import org.dspace.core.ConfigurationManager;
060: import org.dspace.core.Constants;
061: import org.dspace.core.Context;
062: import org.dspace.core.Email;
063: import org.dspace.core.I18nUtil;
064: import org.dspace.eperson.EPerson;
065:
066: /**
067: * Miscellaneous UI utility methods
068: *
069: * @author Robert Tansley
070: * @version $Revision: 2168 $
071: */
072: public class UIUtil extends Util {
073: /** log4j category */
074: public static Logger log = Logger.getLogger(UIUtil.class);
075:
076: /**
077: * Obtain a new context object. If a context object has already been created
078: * for this HTTP request, it is re-used, otherwise it is created. If a user
079: * has authenticated with the system, the current user of the context is set
080: * appropriately.
081: *
082: * @param request
083: * the HTTP request
084: *
085: * @return a context object
086: */
087: public static Context obtainContext(HttpServletRequest request)
088: throws SQLException {
089:
090: //Set encoding to UTF-8, if not set yet
091: //This avoids problems of using the HttpServletRequest
092: //in the getSpecialGroups() for an AuthenticationMethod,
093: //which causes the HttpServletRequest to default to
094: //non-UTF-8 encoding.
095: try {
096: if (request.getCharacterEncoding() == null)
097: request
098: .setCharacterEncoding(Constants.DEFAULT_ENCODING);
099: } catch (Exception e) {
100: log.error("Unable to set encoding to UTF-8.", e);
101: }
102:
103: Context c = (Context) request.getAttribute("dspace.context");
104:
105: if (c == null) {
106: // No context for this request yet
107: c = new Context();
108: HttpSession session = request.getSession();
109:
110: // See if a user has authentication
111: Integer userID = (Integer) session
112: .getAttribute("dspace.current.user.id");
113:
114: if (userID != null) {
115: String remAddr = (String) session
116: .getAttribute("dspace.current.remote.addr");
117: if (remAddr != null
118: && remAddr.equals(request.getRemoteAddr())) {
119: EPerson e = EPerson.find(c, userID.intValue());
120:
121: Authenticate.loggedIn(c, request, e);
122: } else {
123: log.warn("POSSIBLE HIJACKED SESSION: request from "
124: + request.getRemoteAddr()
125: + " does not match original "
126: + "session address: " + remAddr
127: + ". Authentication rejected.");
128: }
129: }
130:
131: // Set any special groups - invoke the authentication mgr.
132: int[] groupIDs = AuthenticationManager.getSpecialGroups(c,
133: request);
134:
135: for (int i = 0; i < groupIDs.length; i++) {
136: c.setSpecialGroup(groupIDs[i]);
137: log.debug("Adding Special Group id="
138: + String.valueOf(groupIDs[i]));
139: }
140:
141: // Set the session ID and IP address
142: c.setExtraLogInfo("session_id="
143: + request.getSession().getId() + ":ip_addr="
144: + request.getRemoteAddr());
145:
146: // Store the context in the request
147: request.setAttribute("dspace.context", c);
148: }
149:
150: // Set the locale to be used
151: Locale sessionLocale = getSessionLocale(request);
152: Config.set(request.getSession(), Config.FMT_LOCALE,
153: sessionLocale);
154: c.setCurrentLocale(sessionLocale);
155:
156: return c;
157: }
158:
159: /**
160: * Get the current community location, that is, where the user "is". This
161: * returns <code>null</code> if there is no location, i.e. "all of DSpace"
162: * is the location.
163: *
164: * @param request
165: * current HTTP request
166: *
167: * @return the current community location, or null
168: */
169: public static Community getCommunityLocation(
170: HttpServletRequest request) {
171: return ((Community) request.getAttribute("dspace.community"));
172: }
173:
174: /**
175: * Get the current collection location, that is, where the user "is". This
176: * returns null if there is no collection location, i.e. the location is
177: * "all of DSpace" or a community.
178: *
179: * @param request
180: * current HTTP request
181: *
182: * @return the current collection location, or null
183: */
184: public static Collection getCollectionLocation(
185: HttpServletRequest request) {
186: return ((Collection) request.getAttribute("dspace.collection"));
187: }
188:
189: /**
190: * Put the original request URL into the request object as an attribute for
191: * later use. This is necessary because forwarding a request removes this
192: * information. The attribute is only written if it hasn't been before; thus
193: * it can be called after a forward safely.
194: *
195: * @param request
196: * the HTTP request
197: */
198: public static void storeOriginalURL(HttpServletRequest request) {
199: String orig = (String) request
200: .getAttribute("dspace.original.url");
201:
202: if (orig == null) {
203: String fullURL = request.getRequestURL().toString();
204:
205: if (request.getQueryString() != null) {
206: fullURL = fullURL + "?" + request.getQueryString();
207: }
208:
209: request.setAttribute("dspace.original.url", fullURL);
210: }
211: }
212:
213: /**
214: * Get the original request URL.
215: *
216: * @param request
217: * the HTTP request
218: *
219: * @return the original request URL
220: */
221: public static String getOriginalURL(HttpServletRequest request) {
222: // Make sure there's a URL in the attribute
223: storeOriginalURL(request);
224:
225: return ((String) request.getAttribute("dspace.original.url"));
226: }
227:
228: /**
229: * Write a human-readable version of a DCDate.
230: *
231: * @param d
232: * the date
233: * @param time
234: * if true, display the time with the date
235: * @param localTime
236: * if true, adjust for local timezone, otherwise GMT
237: * @param request
238: * the servlet request
239: *
240: * @return the date in a human-readable form.
241: */
242: public static String displayDate(DCDate d, boolean time,
243: boolean localTime, HttpServletRequest request) {
244: StringBuffer sb = new StringBuffer();
245: Locale locale = ((Context) request
246: .getAttribute("dspace.context")).getCurrentLocale();
247: if (locale == null)
248: locale = I18nUtil.DEFAULTLOCALE;
249:
250: if (d != null) {
251: int year;
252: int month;
253: int day;
254: int hour;
255: int minute;
256: int second;
257:
258: if (localTime) {
259: year = d.getYear();
260: month = d.getMonth();
261: day = d.getDay();
262: hour = d.getHour();
263: minute = d.getMinute();
264: second = d.getSecond();
265: } else {
266: year = d.getYearGMT();
267: month = d.getMonthGMT();
268: day = d.getDayGMT();
269: hour = d.getHourGMT();
270: minute = d.getMinuteGMT();
271: second = d.getSecondGMT();
272: }
273:
274: if (year > -1) {
275: if (month > -1) {
276: if (day > -1) {
277: sb.append(day + "-");
278: }
279: String monthName = DCDate.getMonthName(month,
280: getSessionLocale(request));
281: int monthLength = monthName.length();
282: monthLength = monthLength > 2 ? 3 : monthLength;
283: sb
284: .append(monthName.substring(0, monthLength)
285: + "-");
286: }
287:
288: sb.append(year + " ");
289: }
290:
291: if (time && (hour > -1)) {
292: String hr = String.valueOf(hour);
293:
294: while (hr.length() < 2) {
295: hr = "0" + hr;
296: }
297:
298: String mn = String.valueOf(minute);
299:
300: while (mn.length() < 2) {
301: mn = "0" + mn;
302: }
303:
304: String sc = String.valueOf(second);
305:
306: while (sc.length() < 2) {
307: sc = "0" + sc;
308: }
309:
310: sb.append(hr + ":" + mn + ":" + sc + " ");
311: }
312: } else {
313: sb.append("Unset");
314: }
315:
316: return (sb.toString());
317: }
318:
319: /**
320: * Return a string for logging, containing useful information about the
321: * current request - the URL, the method and parameters.
322: *
323: * @param request
324: * the request object.
325: * @return a multi-line string containing information about the request.
326: */
327: public static String getRequestLogInfo(HttpServletRequest request) {
328: String report;
329:
330: report = "-- URL Was: " + getOriginalURL(request) + "\n";
331: report = report + "-- Method: " + request.getMethod() + "\n";
332:
333: // First write the parameters we had
334: report = report + "-- Parameters were:\n";
335:
336: Enumeration e = request.getParameterNames();
337:
338: while (e.hasMoreElements()) {
339: String name = (String) e.nextElement();
340:
341: if (name.equals("login_password")) {
342: // We don't want to write a clear text password
343: // to the log, even if it's wrong!
344: report = report + "-- " + name + ": *not logged*\n";
345: } else {
346: report = report + "-- " + name + ": \""
347: + request.getParameter(name) + "\"\n";
348: }
349: }
350:
351: return report;
352: }
353:
354: /**
355: * Get the Locale for a session according to the user's language selection or language preferences.
356: * Order of selection
357: * - language selected via UI
358: * - language as set by application
359: * - language browser default
360: *
361: * @param request
362: * the request Object
363: * @return supportedLocale
364: * Locale supported by this DSpace Instance for this request
365: */
366: public static Locale getSessionLocale(HttpServletRequest request)
367:
368: {
369: String paramLocale = request.getParameter("locale");
370: Locale sessionLocale = null;
371: Locale supportedLocale = null;
372:
373: if (paramLocale != null && paramLocale != "") {
374: /* get session locale according to user selection */
375: sessionLocale = new Locale(paramLocale);
376: }
377:
378: if (sessionLocale == null) {
379: /* get session locale set by application */
380: HttpSession session = request.getSession();
381: sessionLocale = (Locale) Config.get(session,
382: Config.FMT_LOCALE);
383: }
384:
385: /*
386: * if session not set by selection or application then default browser
387: * locale
388: */
389: if (sessionLocale == null) {
390: sessionLocale = request.getLocale();
391: }
392:
393: if (sessionLocale == null) {
394: sessionLocale = I18nUtil.DEFAULTLOCALE;
395: }
396: supportedLocale = I18nUtil.getSupportedLocale(sessionLocale);
397:
398: return supportedLocale;
399: }
400:
401: /**
402: * Send an alert to the designated "alert recipient" - that is, when a
403: * database error or internal error occurs, this person is sent an e-mail
404: * with details.
405: * <P>
406: * The recipient is configured via the "alert.recipient" property in
407: * <code>dspace.cfg</code>. If this property is omitted, no alerts are
408: * sent.
409: * <P>
410: * This method "swallows" any exception that might occur - it will just be
411: * logged. This is because this method will usually be invoked as part of an
412: * error handling routine anyway.
413: *
414: * @param request
415: * the HTTP request leading to the error
416: * @param exception
417: * the exception causing the error, or null
418: */
419: public static void sendAlert(HttpServletRequest request,
420: Exception exception) {
421: String logInfo = UIUtil.getRequestLogInfo(request);
422: Context c = (Context) request.getAttribute("dspace.context");
423:
424: try {
425: String recipient = ConfigurationManager
426: .getProperty("alert.recipient");
427:
428: if (recipient != null) {
429: Email email = ConfigurationManager.getEmail(I18nUtil
430: .getEmailFilename(c.getCurrentLocale(),
431: "internal_error"));
432:
433: email.addRecipient(recipient);
434: email.addArgument(ConfigurationManager
435: .getProperty("dspace.url"));
436: email.addArgument(new Date());
437: email.addArgument(request.getSession().getId());
438: email.addArgument(logInfo);
439:
440: String stackTrace;
441:
442: if (exception != null) {
443: StringWriter sw = new StringWriter();
444: PrintWriter pw = new PrintWriter(sw);
445: exception.printStackTrace(pw);
446: pw.flush();
447: stackTrace = sw.toString();
448: } else {
449: stackTrace = "No exception";
450: }
451:
452: email.addArgument(stackTrace);
453: email.send();
454: }
455: } catch (Exception e) {
456: // Not much we can do here!
457: log.warn("Unable to send email alert", e);
458: }
459: }
460: }
|