001: /*
002: * LayoutTag.java
003: *
004: * Version: $Revision: 2250 $
005: *
006: * Date: $Date: 2007-10-11 10:55:37 -0500 (Thu, 11 Oct 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.jsptag;
041:
042: import java.io.IOException;
043: import java.util.ArrayList;
044: import java.util.List;
045:
046: import javax.servlet.RequestDispatcher;
047: import javax.servlet.ServletConfig;
048: import javax.servlet.ServletException;
049: import javax.servlet.ServletRequest;
050: import javax.servlet.ServletResponse;
051: import javax.servlet.http.HttpServletResponse;
052: import javax.servlet.jsp.JspException;
053: import javax.servlet.jsp.jstl.fmt.LocaleSupport;
054: import javax.servlet.jsp.tagext.TagSupport;
055:
056: import org.apache.log4j.Logger;
057: import org.dspace.content.Collection;
058: import org.dspace.content.Community;
059: import org.dspace.core.ConfigurationManager;
060: import org.dspace.app.webui.servlet.FeedServlet;
061:
062: /**
063: * Tag for HTML page layout ("skin").
064: * <P>
065: * This tag <em>sets</em> request attributes that should be used by the header
066: * and footer to render the page appropriately:
067: * <P>
068: * <ul>
069: * <li><code>dspace.layout.title</code> - title of page</li>
070: * <li><code>dspace.layout.locbar</code> - value will Boolean true or false
071: * </li>
072: * <li><code>dspace.layout.parenttitles</code> - a <code>List</code> of
073: * <code>String</code>s corresponding with titles to put in the location bar.
074: * Only set if <code>dspace.layout.locbar</code> is true</li>
075: * <li><code>dspace.layout.parentlinks</code> - a <code>List</code> of
076: * <code>String</code>s corresponding with links to put in the location bar.
077: * Empty strings mean no link. Will only be set if
078: * <code>dspace.layout.locbar</code> is true.</li>
079: * <li><code>dspace.layout.navbar</code> - value will be "off", or the
080: * navigation bar to include, e.g. "/layout/navbar_default.jsp"</li>
081: * <li><code>dspace.layout.sidebar</code> - contents of the sidebar</li>
082: * <li><code>dspace.current.user</code> - the EPerson currently logged in, or
083: * <code>null</code> if anonymous access</li>
084: * <li><code>dspace.layout.feeddata</code> - <code>String</code>. "NONE"
085: * means no feed from this page; otherwise the Handle of object (community or
086: * collection) the feed is from</li>
087: * <li><code>dspace.layout.linkparts</code> - <code>String[]</code>. A
088: * cycling sequence of: 2nd part of MIME type (e.g. <code>rdf+rss</code>);
089: * title of feed; path component to go after /feed/ for the actual feed URL
090: * (e.g. <code>rss_1.0</code>). Hence, this array will have 3<i>n</i>
091: * elements where <i>n</i> is the number of feeds.</li>
092: * </ul>
093: * <p>
094: *
095: * * Additionally the following parameter may be set elsewhere in a Servlet.
096: * <p>
097: * <ul>
098: * <li><code>dspace.layout.head</code> - extra data to include verbatim in
099: * the <head> element of the page</li>
100: * </ul>
101: *
102: * Furthermore it sets the content type of the response to text/html using UTF-8
103: * to ensure this will be returned in the HTTP header.
104: * </p>
105: *
106: * @author Robert Tansley
107: * @version $Revision: 2250 $
108: */
109: public class LayoutTag extends TagSupport {
110: /** log4j logger */
111: private static Logger log = Logger.getLogger(LayoutTag.class);
112:
113: /** layout style name */
114: private String style;
115:
116: /** title */
117: private String title;
118:
119: /** title key (from message dictionary) */
120: private String titleKey;
121:
122: /** Navigation bar type, null means none */
123: private String navbar;
124:
125: /** Location bar type */
126: private String locbar;
127:
128: /** Name of "parent" page */
129: private String parentTitle;
130:
131: /** Name of "parent" page key (from message dictionary) */
132: private String parentTitleKey;
133:
134: /** Link to "parent" page */
135: private String parentLink;
136:
137: /** Contents of side bar */
138: private String sidebar;
139:
140: /** Whether to add headers to prevent browsers caching the page */
141: private String noCache;
142:
143: /** Syndication feed "autodiscovery" link data */
144: private String feedData;
145:
146: public LayoutTag() {
147: super ();
148: }
149:
150: public int doStartTag() throws JspException {
151: ServletRequest request = pageContext.getRequest();
152:
153: // header file
154: String header = "/layout/header-default.jsp";
155:
156: // Choose default style unless one is specified
157: if (style != null) {
158: header = "/layout/header-" + style.toLowerCase() + ".jsp";
159: }
160:
161: // Sort out location bar
162: if (locbar == null) {
163: locbar = "auto";
164: }
165:
166: // These lists will contain titles and links to put in the location
167: // bar
168: List parents = new ArrayList();
169: List parentLinks = new ArrayList();
170:
171: if (locbar.equalsIgnoreCase("off")) {
172: // No location bar
173: request.setAttribute("dspace.layout.locbar", new Boolean(
174: false));
175: } else {
176: // We'll always add "DSpace Home" to the a location bar
177: parents
178: .add(ConfigurationManager
179: .getProperty("dspace.name"));
180:
181: if (locbar.equalsIgnoreCase("nolink")) {
182: parentLinks.add("");
183: } else {
184: parentLinks.add("/");
185: }
186:
187: // Add other relevant components to the location bar
188: if (locbar.equalsIgnoreCase("link")) {
189: // "link" mode - next thing in location bar is taken from
190: // parameters of tag, with a link
191: if (parentTitle != null) {
192: parents.add(parentTitle);
193: parentLinks.add(parentLink);
194: } else if (parentTitleKey != null) {
195: parents.add(LocaleSupport.getLocalizedMessage(
196: pageContext, parentTitleKey));
197: parentLinks.add(parentLink);
198: }
199:
200: } else if (locbar.equalsIgnoreCase("commLink")) {
201: // "commLink" mode - show all parent communities
202: Community[] comms = (Community[]) request
203: .getAttribute("dspace.communities");
204:
205: if (comms != null) {
206: for (int i = 0; i < comms.length; i++) {
207: parents.add(comms[i].getMetadata("name"));
208: parentLinks.add("/handle/"
209: + comms[i].getHandle());
210: }
211: }
212: } else if (locbar.equalsIgnoreCase("nolink")) {
213: // "nolink" mode - next thing in location bar is taken from
214: // parameters of tag, with no link
215: if (parentTitle != null) {
216: parents.add(parentTitle);
217: parentLinks.add("");
218: }
219: } else {
220: // Grab parents from the URL - these should have been picked up
221: // by the HandleServlet
222: Collection col = (Collection) request
223: .getAttribute("dspace.collection");
224: Community[] comms = (Community[]) request
225: .getAttribute("dspace.communities");
226:
227: if (comms != null) {
228: for (int i = 0; i < comms.length; i++) {
229: parents.add(comms[i].getMetadata("name"));
230: parentLinks.add("/handle/"
231: + comms[i].getHandle());
232: }
233:
234: if (col != null) {
235: parents.add(col.getMetadata("name"));
236: parentLinks.add("/handle/" + col.getHandle());
237: }
238: }
239: }
240:
241: request.setAttribute("dspace.layout.locbar", new Boolean(
242: true));
243: }
244:
245: request.setAttribute("dspace.layout.parenttitles", parents);
246: request.setAttribute("dspace.layout.parentlinks", parentLinks);
247:
248: // Navigation bar: "default" is default :)
249: if (navbar == null) {
250: navbar = "default";
251: }
252:
253: if (navbar.equals("off")) {
254: request.setAttribute("dspace.layout.navbar", "off");
255: } else {
256: request.setAttribute("dspace.layout.navbar",
257: "/layout/navbar-" + navbar + ".jsp");
258: }
259:
260: // Set title
261: if (title != null) {
262: request.setAttribute("dspace.layout.title", title);
263: } else if (titleKey != null) {
264: request.setAttribute("dspace.layout.title", LocaleSupport
265: .getLocalizedMessage(pageContext, titleKey));
266: } else {
267: request.setAttribute("dspace.layout.title", "NO TITLE");
268: }
269:
270: // Set feedData if present
271: if (feedData != null && !"NONE".equals(feedData)) {
272: // set the links' reference - community or collection
273: boolean commLinks = feedData.startsWith("comm:");
274: boolean collLinks = feedData.startsWith("coll:");
275: if (commLinks) {
276: Community com = (Community) request
277: .getAttribute("dspace.community");
278: request.setAttribute("dspace.layout.feedref", com
279: .getHandle());
280: } else if (collLinks) {
281: Collection col = (Collection) request
282: .getAttribute("dspace.collection");
283: request.setAttribute("dspace.layout.feedref", col
284: .getHandle());
285: } else //feed is across all of DSpace and not Community/Collection specific
286: {
287: request.setAttribute("dspace.layout.feedref",
288: FeedServlet.SITE_FEED_KEY);
289: }
290:
291: // build a list of link attributes for each link format
292: String[] formats = feedData.substring(
293: feedData.indexOf(":") + 1).split(",");
294: List linkParts = new ArrayList();
295: // each link has a mime-type, title, and format (used in href URL)
296: for (int i = 0; i < formats.length; i++) {
297: if ("rss_1.0".equals(formats[i])) {
298: linkParts.add("rdf+xml");
299: } else {
300: linkParts.add("rss+xml");
301: }
302:
303: if (commLinks) {
304: linkParts.add("Items in Community");
305: } else if (collLinks) {
306: linkParts.add("Items in Collection");
307: } else {
308: linkParts.add("Items in "
309: + ConfigurationManager
310: .getProperty("dspace.name"));
311: }
312:
313: linkParts.add(formats[i]);
314: }
315: request.setAttribute("dspace.layout.linkparts", linkParts);
316: } else {
317: request.setAttribute("dspace.layout.feedref", "NONE");
318: }
319:
320: // Now include the header
321: try {
322: HttpServletResponse response = (HttpServletResponse) pageContext
323: .getResponse();
324:
325: // Set headers to prevent browser caching, if appropriate
326: if ((noCache != null) && noCache.equalsIgnoreCase("true")) {
327: response.addDateHeader("expires", 1);
328: response.addHeader("Pragma", "no-cache");
329: response.addHeader("Cache-control", "no-store");
330: }
331:
332: // Ensure the HTTP header will declare that UTF-8 is used
333: // in the response.
334: response.setContentType("text/html; charset=UTF-8");
335:
336: ServletConfig config = pageContext.getServletConfig();
337:
338: RequestDispatcher rd = config.getServletContext()
339: .getRequestDispatcher(header);
340:
341: rd.include(request, response);
342: } catch (IOException ioe) {
343: throw new JspException("Got IOException: " + ioe);
344: } catch (ServletException se) {
345: log.warn("Exception", se.getRootCause());
346: throw new JspException("Got ServletException: " + se);
347: }
348:
349: return EVAL_BODY_INCLUDE;
350: }
351:
352: public int doEndTag() throws JspException {
353: // Footer file to use
354: String footer = "/layout/footer-default.jsp";
355:
356: // Choose default flavour unless one is specified
357: if (style != null) {
358: footer = "/layout/footer-" + style.toLowerCase() + ".jsp";
359: }
360:
361: try {
362: // Ensure body is included before footer
363: pageContext.getOut().flush();
364:
365: // Context objects
366: ServletRequest request = pageContext.getRequest();
367: ServletResponse response = pageContext.getResponse();
368: ServletConfig config = pageContext.getServletConfig();
369:
370: if (sidebar != null) {
371: request.setAttribute("dspace.layout.sidebar", sidebar);
372: }
373:
374: RequestDispatcher rd = config.getServletContext()
375: .getRequestDispatcher(footer);
376:
377: rd.include(request, response);
378: } catch (ServletException se) {
379: throw new JspException("Got ServletException: " + se);
380: } catch (IOException ioe) {
381: throw new JspException("Got IOException: " + ioe);
382: }
383:
384: return EVAL_PAGE;
385: }
386:
387: /**
388: * Get the value of title.
389: *
390: * @return Value of title.
391: */
392: public String getTitle() {
393: return title;
394: }
395:
396: /**
397: * Set the value of title.
398: *
399: * @param v
400: * Value to assign to title.
401: */
402: public void setTitle(String v) {
403: this .title = v;
404: }
405:
406: /**
407: * @return Returns the titleKey.
408: */
409: public String getTitlekey() {
410: return titleKey;
411: }
412:
413: /**
414: * @param titleKey The titleKey to set.
415: */
416: public void setTitlekey(String titleKey) {
417: this .titleKey = titleKey;
418: }
419:
420: /**
421: * Get the value of navbar.
422: *
423: * @return Value of navbar.
424: */
425: public String getNavbar() {
426: return navbar;
427: }
428:
429: /**
430: * Set the value of navbar.
431: *
432: * @param v
433: * Value to assign to navbar.
434: */
435: public void setNavbar(String v) {
436: this .navbar = v;
437: }
438:
439: /**
440: * Get the value of locbar.
441: *
442: * @return Value of locbar.
443: */
444: public String getLocbar() {
445: return locbar;
446: }
447:
448: /**
449: * Set the value of locbar.
450: *
451: * @param v
452: * Value to assign to locbar.
453: */
454: public void setLocbar(String v) {
455: this .locbar = v;
456: }
457:
458: /**
459: * Get the value of parentTitle.
460: *
461: * @return Value of parentTitle.
462: */
463: public String getParenttitle() {
464: return parentTitle;
465: }
466:
467: /**
468: * Set the value of parent.
469: *
470: * @param v
471: * Value to assign to parent.
472: */
473: public void setParenttitle(String v) {
474: this .parentTitle = v;
475: }
476:
477: /**
478: * get parent title key (from message dictionary)
479: *
480: * @return Returns the parentTitleKey.
481: */
482: public String getParenttitlekey() {
483: return parentTitleKey;
484: }
485:
486: /**
487: * set parent title key (from message dictionary)
488: *
489: * @param parentTitleKey The parentTitleKey to set.
490: */
491: public void setParenttitlekey(String parentTitleKey) {
492: this .parentTitleKey = parentTitleKey;
493: }
494:
495: /**
496: * Get the value of parentlink.
497: *
498: * @return Value of parentlink.
499: */
500: public String getParentlink() {
501: return parentLink;
502: }
503:
504: /**
505: * Set the value of parentlink.
506: *
507: * @param v
508: * Value to assign to parentlink.
509: */
510: public void setParentlink(String v) {
511: this .parentLink = v;
512: }
513:
514: /**
515: * Get the value of style.
516: *
517: * @return Value of style.
518: */
519: public String getStyle() {
520: return style;
521: }
522:
523: /**
524: * Set the value of style.
525: *
526: * @param v
527: * Value to assign to style.
528: */
529: public void setStyle(String v) {
530: this .style = v;
531: }
532:
533: /**
534: * Get the value of sidebar.
535: *
536: * @return Value of sidebar.
537: */
538: public String getSidebar() {
539: return sidebar;
540: }
541:
542: /**
543: * Set the value of sidebar.
544: *
545: * @param v
546: * Value to assign to sidebar.
547: */
548: public void setSidebar(String v) {
549: this .sidebar = v;
550: }
551:
552: /**
553: * Get the value of sidebar.
554: *
555: * @return Value of sidebar.
556: */
557: public String getNocache() {
558: return noCache;
559: }
560:
561: /**
562: * Set the value of sidebar.
563: *
564: * @param v
565: * Value to assign to sidebar.
566: */
567: public void setNocache(String v) {
568: this .noCache = v;
569: }
570:
571: /**
572: * Get the value of feedData.
573: *
574: * @return Value of feedData.
575: */
576: public String getFeedData() {
577: return feedData;
578: }
579:
580: /**
581: * Set the value of feedData.
582: *
583: * @param v
584: * Value to assign to feedData.
585: */
586: public void setFeedData(String v) {
587: this .feedData = v;
588: }
589:
590: public void release() {
591: style = null;
592: title = null;
593: sidebar = null;
594: navbar = null;
595: locbar = null;
596: parentTitle = null;
597: parentLink = null;
598: noCache = null;
599: feedData = null;
600: }
601: }
|