001: /*
002: * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
003: * PROPRIETARY/CONFIDENTIAL. Use of this product is subject to license terms.
004: */
005: package com.sun.portal.providers.error;
006:
007: import com.sun.portal.desktop.TypedException;
008: import com.sun.portal.desktop.context.DesktopAppContext;
009: import com.sun.portal.desktop.context.DesktopContext;
010: import com.sun.portal.providers.util.ProviderProperties;
011: import com.sun.portal.providers.Provider;
012: import com.sun.portal.providers.ProviderException;
013: import com.sun.portal.providers.UnknownEditTypeException;
014: import com.sun.portal.log.common.PortalLogger;
015: import com.sun.portal.util.ResourceLoader;
016:
017: import java.io.IOException;
018: import java.io.OutputStreamWriter;
019: import java.io.PrintWriter;
020: import java.io.StringWriter;
021: import java.io.Writer;
022: import java.net.MalformedURLException;
023: import java.net.URL;
024: import java.net.URLEncoder;
025: import java.util.HashMap;
026: import java.util.Hashtable;
027: import java.util.Locale;
028: import java.util.Map;
029: import java.util.Properties;
030: import java.util.logging.Level;
031: import java.util.logging.LogRecord;
032: import java.util.logging.Logger;
033: import javax.servlet.http.HttpServletRequest;
034: import javax.servlet.http.HttpServletResponse;
035:
036: /**
037: * Error Provider
038: */
039: public class ErrorProvider implements ProviderProperties, Provider {
040: protected static Map templates = null;
041: private static Logger logger = PortalLogger
042: .getLogger(ErrorProvider.class);
043:
044: static {
045: templates = new HashMap();
046: templates.put(TypedException.NON_EDITABLE_TYPE,
047: "noneditablechannel.template");
048: templates.put(TypedException.NO_PRIVILEGE_TYPE,
049: "noprivilege.template");
050: templates.put(TypedException.UNKNOWN_CHANNEL_TYPE,
051: "unknownchannel.template");
052: templates.put(TypedException.SESSION_TYPE, "session.template");
053: templates.put(TypedException.SESSION_TIMED_OUT,
054: "session.template");
055: }
056:
057: public ErrorProvider() {
058: }
059:
060: public void init(String name, HttpServletRequest req)
061: throws ProviderException {
062: }
063:
064: private String getAbsURL(HttpServletRequest req,
065: DesktopAppContext dac, String u)
066: throws MalformedURLException {
067: if (!u.regionMatches(true, 0, "http://", 0, 7)
068: && !u.regionMatches(true, 0, "https://", 0, 7)) {
069: StringBuffer ru = dac.getRequestServer(req);
070: URL requestURL = new URL(ru.toString());
071:
072: String scheme = requestURL.getProtocol();
073:
074: StringBuffer absURL = new StringBuffer(scheme);
075: absURL.append("://");
076: absURL.append(requestURL.getHost());
077: absURL.append(":");
078:
079: int port = requestURL.getPort();
080: // default port schemes need to fill in port
081: if (scheme.equals("http") && port <= 0) {
082: port = 80;
083: } else if (scheme.equals("https") && port <= 0) {
084: port = 443;
085: }
086:
087: absURL.append(port).append(u);
088: return absURL.toString();
089: } else {
090: return u;
091: }
092: }
093:
094: private String getNoSessionURL(HttpServletRequest req,
095: DesktopAppContext dac) {
096: String noSessionURL = dac.getNoSessionURL();
097: if (noSessionURL == null) {
098: if (logger.isLoggable(Level.WARNING)) {
099: logger.log(Level.WARNING, "PSDT_CSPPE0006");
100: }
101: noSessionURL = "/amserver/login";
102: }
103: StringBuffer redirectURL = new StringBuffer(noSessionURL);
104:
105: // Attach return URL as query string
106: String returnParam = dac.getSessionReturnURLParamName();
107: if (returnParam != null && returnParam.length() > 0) {
108: try {
109: StringBuffer returnURL = new StringBuffer(getAbsURL(
110: req, dac, req.getRequestURI()));
111: String qs = req.getQueryString();
112: if (qs != null) {
113: returnURL.append("?").append(qs);
114: }
115:
116: redirectURL.append(noSessionURL.indexOf('?') < 0 ? "?"
117: : "&");
118: redirectURL.append(returnParam).append("=").append(
119: URLEncoder.encode(returnURL.toString()));
120: } catch (MalformedURLException e) {
121: if (logger.isLoggable(Level.WARNING)) {
122: logger.log(Level.WARNING, "PSDT_CSPPE0006",
123: new Object[] { e.getLocalizedMessage() });
124: }
125: }
126: }
127:
128: return redirectURL.toString();
129: }
130:
131: public StringBuffer getContent(HttpServletRequest req,
132: HttpServletResponse res) throws ProviderException {
133: StringBuffer ob = null;
134:
135: // NOTE : Currently we are using non-standard interfaces viz DesktopContext
136: // and DesktopAppContext. What this means is that the current error
137: // provider is NOT swappable with any other one because the non-standard
138: // (or private) interfaces are not exposed.
139: //
140: // Read the values from the desktop servlet
141: //
142: Throwable e = (Throwable) req.getAttribute(getName()
143: + ".exception");
144: if (e instanceof TypedException) {
145: // Allow customization of ErrorProvider, no-op if redirectURL is not set
146: String redirectURL = getRedirectURL(req, (TypedException) e);
147: redirect(req, redirectURL);
148: }
149:
150: DesktopContext dc = (DesktopContext) req.getAttribute(getName()
151: + ".desktopContext");
152: DesktopAppContext dac = (DesktopAppContext) req
153: .getAttribute(getName() + ".desktopAppContext");
154: String app = getName();
155: String provider = "error";
156: String requestType = req.getParameter("requestType");
157:
158: // DesktopContext is available
159: if (dc != null) {
160: String locale = dc.getLocaleString();
161: String staticContent = dc.getStaticContentPath();
162: Hashtable tags = new Hashtable();
163:
164: tags.put(LOCALE_STRING, locale);
165: tags.put(STATIC_CONTENT, staticContent);
166: String logoutUrl = dc.getLogoutURL();
167: if (logoutUrl != null) {
168: tags.put(LOGOUT_URL, logoutUrl);
169: }
170:
171: // For "session timed out" and "invalid session" exceptions, use banner_nocontext.template.
172: if ((e instanceof TypedException)
173: && TypedException.SESSION_TIMED_OUT
174: .equals(((TypedException) e).getType())
175: || TypedException.SESSION_TYPE
176: .equals(((TypedException) e).getType())) {
177: tags.put(BANNER, dc.getTemplate(app, provider,
178: BANNER_TEMPLATE_NOCONTEXT, tags));
179: } else {
180: tags.put(BANNER, dc.getTemplate(app, provider,
181: BANNER_TEMPLATE, tags));
182: }
183:
184: tags.put(BULLET_COLOR, dc.getTemplate(app, provider,
185: BULLET_COLOR_JS, tags));
186: StringWriter swriter = new StringWriter(160);
187: PrintWriter buf = new PrintWriter(swriter, true);
188: if (e != null) {
189: e.printStackTrace(buf);
190: buf.flush();
191: }
192: tags.put(STACK_TRACE, swriter.toString());
193:
194: ob = dc.getTemplate(app, provider, getTemplateName(e,
195: requestType), tags);
196: }
197: // DesktopAppContext is available but not DesktopContext, work with default Desktop
198: else if (dac != null) {
199: if (logger.isLoggable(Level.INFO)) {
200: LogRecord record = new LogRecord(Level.INFO,
201: "PSDT_CSPPE0001");
202: record.setLoggerName(logger.getName());
203: record.setParameters(new Object[] { getTemplateName(e,
204: requestType) });
205: record.setThrown(e);
206: logger.log(record);
207: }
208: String type = dac.getDefaultDesktopType();
209: String locale = Locale.getDefault().toString();
210: String clientPath = dac.getClientPath(dac
211: .getDefaultClientType());
212:
213: Hashtable tags = new Hashtable();
214: tags.put(NO_SESSION_URL, getNoSessionURL(req, dac));
215:
216: String logoutUrl = dac.getLogoutURL();
217: if (logoutUrl != null) {
218: tags.put(LOGOUT_URL, logoutUrl);
219: }
220:
221: tags.put(BANNER, dac.getTemplate(type, locale, app,
222: provider, clientPath, BANNER_TEMPLATE_NOCONTEXT,
223: tags, dac.getTemplateBaseDir(), null));
224: tags.put(BULLET_COLOR, dac.getTemplate(type, locale, app,
225: provider, clientPath, BULLET_COLOR_JS, tags, dac
226: .getTemplateBaseDir(), null));
227:
228: StringWriter swriter = new StringWriter(160);
229: PrintWriter buf = new PrintWriter(swriter, true);
230: if (e != null) {
231: e.printStackTrace(buf);
232: buf.flush();
233: }
234: tags.put(STACK_TRACE, swriter.toString());
235:
236: ob = dac.getTemplate(type, locale, app, provider,
237: clientPath, getTemplateName(e, requestType), tags,
238: dac.getTemplateBaseDir(), null);
239: }
240: // Neither is available, send back 500 (Internal Server Error)
241: else {
242: try {
243: if (logger.isLoggable(Level.SEVERE)) {
244: LogRecord record = new LogRecord(Level.SEVERE,
245: "PSDT_CSPPE0002");
246: record.setLoggerName(logger.getName());
247: record
248: .setParameters(new Object[] { getTemplateName(
249: e, requestType) });
250: record.setThrown(e);
251: logger.log(record);
252: }
253: res
254: .sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
255: } catch (IOException ioe) {
256: throw new ProviderException("ErrorProvider:getContent",
257: ioe);
258: }
259: }
260:
261: return ob;
262: }
263:
264: protected void redirect(HttpServletRequest req, String redirectURL) {
265: // if redirect url is set, just redirect nothing more to do
266: if (redirectURL != null && !redirectURL.trim().equals("")) {
267: DesktopContext dc = (DesktopContext) req
268: .getAttribute(getName() + ".desktopContext");
269: DesktopAppContext appContext = (DesktopAppContext) req
270: .getAttribute(getName() + ".desktopAppContext");
271: HttpServletResponse res = (HttpServletResponse) req
272: .getAttribute(getName() + ".response");
273: Writer out;
274:
275: if (!req.getMethod().equalsIgnoreCase("head")) {
276: String clientType = appContext.getClientType(req);
277: String clientPath = appContext
278: .getClientPath(clientType);
279: StringBuffer redirect;
280: if (clientType != null) {
281: String contentType = appContext
282: .getContentType(clientType);
283: String charset;
284: if (dc != null) {
285: charset = dc.getCharset();
286: } else {
287: Locale locale = Locale.getDefault();
288: charset = appContext.getCharset(clientType,
289: locale);
290: }
291:
292: String type = appContext.getDefaultDesktopType();
293: if (dc != null) {
294: redirectURL = dc.encodeURL(redirectURL);
295: type = dc.getDesktopType();
296: }
297: Hashtable tags = new Hashtable();
298: tags.put("url", redirectURL);
299:
300: redirect = appContext.getTemplate(type, Locale
301: .getDefault().toString(), null, null,
302: clientPath, "redirect.template", tags,
303: appContext.getTemplateBaseDir());
304:
305: logger.log(Level.FINEST, "PSDT_CSPPE0003",
306: new Object[] { redirectURL, redirect });
307: try {
308: out = ErrorProvider.getWriter(res, contentType,
309: charset);
310: if (redirect != null) {
311: out.write(redirect.toString());
312: } else {
313: // log error, but fail gracefully because the spec says "should"
314: logger.log(Level.INFO, "PSDT_CSPPE0004");
315: }
316: } catch (IOException ioe) {
317: logger
318: .log(Level.WARNING, "PSDT_CSPPE0005",
319: ioe);
320: }
321: }
322: }
323:
324: res.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
325: res.setHeader("Location", redirectURL);
326: }
327: }
328:
329: private static Writer getWriter(HttpServletResponse res,
330: String contentType, String charset) throws IOException {
331: if (contentType != null) {
332: if (charset != null) {
333: res
334: .setContentType(contentType + "; charset="
335: + charset);
336: } else {
337: res.setContentType(contentType);
338: }
339: }
340:
341: return new OutputStreamWriter(res.getOutputStream(), charset);
342: }
343:
344: protected String getRedirectURL(HttpServletRequest req,
345: TypedException te) {
346: String redirectURL = null;
347: String propertiesFile = (String) req.getAttribute(getName()
348: + ".propertiesFile");
349:
350: if (propertiesFile != null && !propertiesFile.trim().equals("")) {
351: ResourceLoader resourceLoader = ResourceLoader
352: .getInstance(System.getProperties());
353: Properties properties = new Properties();
354: try {
355: properties.load(resourceLoader
356: .getResourceAsStream(propertiesFile));
357: } catch (Exception e) {
358: // use the error template, hence do nothing here.
359: }
360:
361: redirectURL = properties.getProperty(te.getType());
362: }
363:
364: return redirectURL;
365: }
366:
367: protected String getTemplateName(Throwable e, String requestType) {
368: String template = null;
369: String exceptionType;
370:
371: if (e instanceof TypedException) {
372: exceptionType = ((TypedException) e).getType();
373: template = (String) templates.get(exceptionType);
374: }
375:
376: if (template == null) {
377: // default template
378: template = ERROR_TEMPLATE;
379: }
380:
381: if (requestType != null && requestType.equalsIgnoreCase("ajax")) {
382: template += ".js";
383: }
384:
385: return template;
386: }
387:
388: public StringBuffer getContent(Map m) throws ProviderException {
389: return null;
390: }
391:
392: public StringBuffer getEdit(HttpServletRequest request,
393: HttpServletResponse response) throws ProviderException {
394: return null;
395: }
396:
397: public StringBuffer getEdit(Map m) throws ProviderException {
398: return null;
399: }
400:
401: public int getEditType() throws UnknownEditTypeException {
402: return 0;
403: }
404:
405: public URL processEdit(Map m) throws ProviderException {
406: return null;
407: }
408:
409: public URL processEdit(HttpServletRequest request,
410: HttpServletResponse response) throws ProviderException {
411: return null;
412: }
413:
414: public boolean isEditable() throws ProviderException {
415: return true;
416: }
417:
418: public boolean isPresentable() {
419: return true;
420: }
421:
422: public boolean isPresentable(HttpServletRequest req) {
423: return true;
424: }
425:
426: public String getTitle() throws ProviderException {
427: return null;
428: }
429:
430: public String getName() {
431: return "Error";
432: }
433:
434: public String getDescription() throws ProviderException {
435: return null;
436: }
437:
438: public URL getHelp(HttpServletRequest req) throws ProviderException {
439: return null;
440: }
441:
442: public long getRefreshTime() throws ProviderException {
443: return 0;
444: }
445:
446: public int getWidth() throws ProviderException {
447: return 0;
448: }
449: }
|