KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > dspace > app > webui > servlet > HandleServlet


1 /*
2  * HandleServlet.java
3  *
4  * Version: $Revision: 1.23 $
5  *
6  * Date: $Date: 2006/09/27 17:48:22 $
7  *
8  * Copyright (c) 2002-2005, Hewlett-Packard Company and Massachusetts
9  * Institute of Technology. All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions are
13  * met:
14  *
15  * - Redistributions of source code must retain the above copyright
16  * notice, this list of conditions and the following disclaimer.
17  *
18  * - Redistributions in binary form must reproduce the above copyright
19  * notice, this list of conditions and the following disclaimer in the
20  * documentation and/or other materials provided with the distribution.
21  *
22  * - Neither the name of the Hewlett-Packard Company nor the name of the
23  * Massachusetts Institute of Technology nor the names of their
24  * contributors may be used to endorse or promote products derived from
25  * this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
32  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
33  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
34  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
35  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
36  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
37  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
38  * DAMAGE.
39  */

40 package org.dspace.app.webui.servlet;
41
42 import java.io.IOException JavaDoc;
43 import java.net.URLEncoder JavaDoc;
44 import java.sql.SQLException JavaDoc;
45 import java.util.List JavaDoc;
46
47 import javax.servlet.ServletException JavaDoc;
48 import javax.servlet.http.HttpServletRequest JavaDoc;
49 import javax.servlet.http.HttpServletResponse JavaDoc;
50
51 import org.apache.log4j.Logger;
52 import org.dspace.app.webui.util.Authenticate;
53 import org.dspace.app.webui.util.JSPManager;
54 import org.dspace.app.webui.util.UIUtil;
55 import org.dspace.authorize.AuthorizeException;
56 import org.dspace.authorize.AuthorizeManager;
57 import org.dspace.browse.Browse;
58 import org.dspace.browse.BrowseScope;
59 import org.dspace.content.Collection;
60 import org.dspace.content.Community;
61 import org.dspace.content.DCValue;
62 import org.dspace.content.DSpaceObject;
63 import org.dspace.content.Item;
64 import org.dspace.core.Constants;
65 import org.dspace.core.Context;
66 import org.dspace.core.LogManager;
67 import org.dspace.eperson.EPerson;
68 import org.dspace.eperson.Group;
69 import org.dspace.eperson.Subscribe;
70 import org.dspace.handle.HandleManager;
71
72 /**
73  * Servlet for handling requests within a community or collection. The Handle is
74  * extracted from the URL, e.g: <code>/community/1721.1/1234</code>. If there
75  * is anything after the Handle, the request is forwarded to the appropriate
76  * servlet. For example:
77  * <P>
78  * <code>/community/1721.1/1234/simple-search</code>
79  * <P>
80  * would be forwarded to <code>/simple-search</code>. If there is nothing
81  * after the Handle, the community or collection home page is shown.
82  *
83  * @author Robert Tansley
84  * @version $Revision: 1.23 $
85  */

86 public class HandleServlet extends DSpaceServlet
87 {
88     /** log4j category */
89     private static Logger log = Logger.getLogger(DSpaceServlet.class);
90
91     protected void doDSGet(Context context, HttpServletRequest JavaDoc request,
92             HttpServletResponse JavaDoc response) throws ServletException JavaDoc, IOException JavaDoc,
93             SQLException JavaDoc, AuthorizeException
94     {
95         String JavaDoc handle = null;
96         String JavaDoc extraPathInfo = null;
97         DSpaceObject dso = null;
98
99         // Original path info, of the form "1721.x/1234"
100
// or "1721.x/1234/extra/stuff"
101
String JavaDoc path = request.getPathInfo();
102
103         if (path != null)
104         {
105             // substring(1) is to remove initial '/'
106
path = path.substring(1);
107
108             try
109             {
110                 // Extract the Handle
111
int firstSlash = path.indexOf('/');
112                 int secondSlash = path.indexOf('/', firstSlash + 1);
113
114                 if (secondSlash != -1)
115                 {
116                     // We have extra path info
117
handle = path.substring(0, secondSlash);
118                     extraPathInfo = path.substring(secondSlash);
119                 }
120                 else
121                 {
122                     // The path is just the Handle
123
handle = path;
124                 }
125             }
126             catch (NumberFormatException JavaDoc nfe)
127             {
128                 // Leave handle as null
129
}
130         }
131
132         // Find out what the handle relates to
133
if (handle != null)
134         {
135             dso = HandleManager.resolveToObject(context, handle);
136         }
137
138         if (dso == null)
139         {
140             log.info(LogManager
141                     .getHeader(context, "invalid_id", "path=" + path));
142             JSPManager.showInvalidIDError(request, response, path, -1);
143
144             return;
145         }
146
147         // OK, we have a valid Handle. What is it?
148
if (dso.getType() == Constants.ITEM)
149         {
150             Item item = (Item) dso;
151             
152             response.setDateHeader("Last-Modified", item
153                     .getLastModified().getTime());
154             
155             // Check for if-modified-since header
156
long modSince = request.getDateHeader("If-Modified-Since");
157
158             if (modSince != -1 && item.getLastModified().getTime() < modSince)
159             {
160                 // Item has not been modified since requested date,
161
// hence bitstream has not; return 304
162
response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
163             }
164             else
165             {
166                 // Display the item page
167
displayItem(context, request, response, item, handle);
168             }
169         }
170         else if (dso.getType() == Constants.COLLECTION)
171         {
172             Collection c = (Collection) dso;
173
174             // Store collection location in request
175
request.setAttribute("dspace.collection", c);
176
177             /*
178              * Find the "parent" community the collection, mainly for
179              * "breadcrumbs" FIXME: At the moment, just grab the first community
180              * the collection is in. This should probably be more context
181              * sensitive when we have multiple inclusion.
182              */

183             Community[] parents = c.getCommunities();
184             request.setAttribute("dspace.community", parents[0]);
185
186             /*
187              * Find all the "parent" communities for the collection for
188              * "breadcrumbs"
189              */

190             request.setAttribute("dspace.communities", getParents(parents[0],
191                     true));
192
193             // home page, or forward to another page?
194
if ((extraPathInfo == null) || (extraPathInfo.equals("/")))
195             {
196                 collectionHome(context, request, response, parents[0], c);
197             }
198             else
199             {
200                 // Forward to another servlet
201
request.getRequestDispatcher(extraPathInfo).forward(request,
202                         response);
203             }
204         }
205         else if (dso.getType() == Constants.COMMUNITY)
206         {
207             Community c = (Community) dso;
208
209             // Store collection location in request
210
request.setAttribute("dspace.community", c);
211
212             /*
213              * Find all the "parent" communities for the community
214              */

215             request.setAttribute("dspace.communities", getParents(c, false));
216
217             // home page, or forward to another page?
218
if ((extraPathInfo == null) || (extraPathInfo.equals("/")))
219             {
220                 communityHome(context, request, response, c);
221             }
222             else
223             {
224                 // Forward to another servlet
225
request.getRequestDispatcher(extraPathInfo).forward(request,
226                         response);
227             }
228         }
229         else
230         {
231             // Shouldn't happen. Log and treat as invalid ID
232
log.info(LogManager.getHeader(context,
233                     "Handle not an item, collection or community", "handle="
234                             + handle));
235             JSPManager.showInvalidIDError(request, response, path, -1);
236
237             return;
238         }
239     }
240
241     /**
242      * Show an item page
243      *
244      * @param context
245      * Context object
246      * @param request
247      * the HTTP request
248      * @param response
249      * the HTTP response
250      * @param item
251      * the item
252      * @param handle
253      * the item's handle
254      */

255     private void displayItem(Context context, HttpServletRequest JavaDoc request,
256             HttpServletResponse JavaDoc response, Item item, String JavaDoc handle)
257             throws ServletException JavaDoc, IOException JavaDoc, SQLException JavaDoc,
258             AuthorizeException
259     {
260         // Tombstone?
261
if (item.isWithdrawn())
262         {
263             JSPManager.showJSP(request, response, "/tombstone.jsp");
264
265             return;
266         }
267
268         // Ensure the user has authorisation
269
AuthorizeManager.authorizeAction(context, item, Constants.READ);
270
271         log
272                 .info(LogManager.getHeader(context, "view_item", "handle="
273                         + handle));
274
275         // show edit link
276
if (item.canEdit())
277         {
278             // set a variable to create an edit button
279
request.setAttribute("admin_button", new Boolean JavaDoc(true));
280         }
281
282         // Get the collections
283
Collection[] collections = item.getCollections();
284
285         // For the breadcrumbs, get the first collection and the first community
286
// that is in. FIXME: Not multiple-inclusion friendly--should be
287
// smarter, context-sensitive
288
request.setAttribute("dspace.collection", item.getOwningCollection());
289
290         Community[] comms = item.getOwningCollection().getCommunities();
291         request.setAttribute("dspace.community", comms[0]);
292
293         /*
294          * Find all the "parent" communities for the collection
295          */

296         request.setAttribute("dspace.communities", getParents(comms[0], true));
297
298         // Full or simple display?
299
boolean displayAll = false;
300         String JavaDoc modeParam = request.getParameter("mode");
301
302         if ((modeParam != null) && modeParam.equalsIgnoreCase("full"))
303         {
304             displayAll = true;
305         }
306
307         // Set attributes and display
308
request.setAttribute("display.all", new Boolean JavaDoc(displayAll));
309         request.setAttribute("item", item);
310         request.setAttribute("collections", collections);
311         JSPManager.showJSP(request, response, "/display-item.jsp");
312     }
313
314     /**
315      * Show a community home page, or deal with button press on home page
316      *
317      * @param context
318      * Context object
319      * @param request
320      * the HTTP request
321      * @param response
322      * the HTTP response
323      * @param community
324      * the community
325      */

326     private void communityHome(Context context, HttpServletRequest JavaDoc request,
327             HttpServletResponse JavaDoc response, Community community)
328             throws ServletException JavaDoc, IOException JavaDoc, SQLException JavaDoc
329     {
330         // Handle click on a browse or search button
331
if (!handleButton(request, response, community.getHandle()))
332         {
333             // No button pressed, display community home page
334
log.info(LogManager.getHeader(context, "view_community",
335                     "community_id=" + community.getID()));
336
337             // Get the collections within the community
338
Collection[] collections = community.getCollections();
339
340             // get any subcommunities of the community
341
Community[] subcommunities = community.getSubcommunities();
342
343             // Find the 5 last submitted items
344
BrowseScope scope = new BrowseScope(context);
345             scope.setScope(community);
346             scope.setTotal(5);
347
348             List JavaDoc items = Browse.getLastSubmitted(scope);
349
350             // Get titles and URLs to item pages
351
String JavaDoc[] itemTitles = getItemTitles(items);
352             String JavaDoc[] itemLinks = getItemURLs(context, items);
353
354             // is the user a COMMUNITY_EDITOR?
355
if (community.canEditBoolean())
356             {
357                 // set a variable to create an edit button
358
request.setAttribute("editor_button", new Boolean JavaDoc(true));
359             }
360
361             // can they add to this community?
362
if (AuthorizeManager.authorizeActionBoolean(context, community,
363                     Constants.ADD))
364             {
365                 // set a variable to create an edit button
366
request.setAttribute("add_button", new Boolean JavaDoc(true));
367             }
368
369             // can they remove from this community?
370
if (AuthorizeManager.authorizeActionBoolean(context, community,
371                     Constants.REMOVE))
372             {
373                 // set a variable to create an edit button
374
request.setAttribute("remove_button", new Boolean JavaDoc(true));
375             }
376
377             // Forward to community home page
378
request.setAttribute("last.submitted.titles", itemTitles);
379             request.setAttribute("last.submitted.urls", itemLinks);
380             request.setAttribute("community", community);
381             request.setAttribute("collections", collections);
382             request.setAttribute("subcommunities", subcommunities);
383             JSPManager.showJSP(request, response, "/community-home.jsp");
384         }
385     }
386
387     /**
388      * Show a collection home page, or deal with button press on home page
389      *
390      * @param context
391      * Context object
392      * @param request
393      * the HTTP request
394      * @param response
395      * the HTTP response
396      * @param community
397      * the community
398      * @param collection
399      * the collection
400      */

401     private void collectionHome(Context context, HttpServletRequest JavaDoc request,
402             HttpServletResponse JavaDoc response, Community community,
403             Collection collection) throws ServletException JavaDoc, IOException JavaDoc,
404             SQLException JavaDoc, AuthorizeException
405     {
406         // Handle click on a browse or search button
407
if (!handleButton(request, response, collection.getHandle()))
408         {
409             // Will need to know whether to commit to DB
410
boolean updated = false;
411
412             // No search or browse button pressed, check for
413
if (request.getParameter("submit_subscribe") != null)
414             {
415                 // Subscribe button pressed.
416
// Only registered can subscribe, so redirect unless logged in.
417
if (context.getCurrentUser() == null &&
418                     !Authenticate
419                             .startAuthentication(context, request, response))
420
421                     return;
422                 else
423                 {
424                     Subscribe.subscribe(context, context.getCurrentUser(),
425                             collection);
426                     updated = true;
427                 }
428             }
429             else if (request.getParameter("submit_unsubscribe") != null)
430             {
431                 Subscribe.unsubscribe(context, context.getCurrentUser(),
432                         collection);
433                 updated = true;
434             }
435
436             // display collection home page
437
log.info(LogManager.getHeader(context, "view_collection",
438                     "collection_id=" + collection.getID()));
439
440             // Find the 5 last submitted items
441
BrowseScope scope = new BrowseScope(context);
442             scope.setScope(collection);
443             scope.setTotal(5);
444
445             List JavaDoc items = Browse.getLastSubmitted(scope);
446
447             // Get titles and URLs to item pages
448
String JavaDoc[] itemTitles = getItemTitles(items);
449             String JavaDoc[] itemLinks = getItemURLs(context, items);
450
451             // Is the user logged in/subscribed?
452
EPerson e = context.getCurrentUser();
453             boolean subscribed = false;
454
455             if (e != null)
456             {
457                 subscribed = Subscribe.isSubscribed(context, e, collection);
458
459                 // is the user a COLLECTION_EDITOR?
460
if (collection.canEditBoolean())
461                 {
462                     // set a variable to create an edit button
463
request.setAttribute("editor_button", new Boolean JavaDoc(true));
464                 }
465
466                 // can they admin this collection?
467
if (AuthorizeManager.authorizeActionBoolean(context,
468                         collection, Constants.COLLECTION_ADMIN))
469                 {
470                     request.setAttribute("admin_button", new Boolean JavaDoc(true));
471
472                     // give them a button to manage submitter list
473
// what group is the submitter?
474
Group group = collection.getSubmitters();
475
476                     if (group != null)
477                     {
478                         request.setAttribute("submitters", group);
479                     }
480                 }
481
482                 // can they submit to this collection?
483
if (AuthorizeManager.authorizeActionBoolean(context,
484                         collection, Constants.ADD))
485                 {
486                     request
487                             .setAttribute("can_submit_button",
488                                     new Boolean JavaDoc(true));
489
490                 }
491                 else
492                 {
493                     request.setAttribute("can_submit_button",
494                             new Boolean JavaDoc(false));
495                 }
496             }
497
498             // Forward to collection home page
499
request.setAttribute("last.submitted.titles", itemTitles);
500             request.setAttribute("last.submitted.urls", itemLinks);
501             request.setAttribute("collection", collection);
502             request.setAttribute("community", community);
503             request.setAttribute("logged.in", new Boolean JavaDoc(e != null));
504             request.setAttribute("subscribed", new Boolean JavaDoc(subscribed));
505             JSPManager.showJSP(request, response, "/collection-home.jsp");
506
507             if (updated)
508             {
509                 context.complete();
510             }
511         }
512     }
513
514     /**
515      * Check to see if a browse or search button has been pressed on a community
516      * or collection home page. If so, redirect to the appropriate URL.
517      *
518      * @param request
519      * HTTP request
520      * @param response
521      * HTTP response
522      * @param handle
523      * Handle of the community/collection home page
524      *
525      * @return true if a browse/search button was pressed and the user was
526      * redirected
527      */

528     private boolean handleButton(HttpServletRequest JavaDoc request,
529             HttpServletResponse JavaDoc response, String JavaDoc handle) throws IOException JavaDoc
530     {
531         String JavaDoc button = UIUtil.getSubmitButton(request, "");
532         String JavaDoc location = request.getParameter("location");
533         String JavaDoc prefix = "/";
534         String JavaDoc url = null;
535
536         if (location == null)
537         {
538             return false;
539         }
540
541         /*
542          * Work out the "prefix" to which to redirect If "/", scope is all of
543          * DSpace, so prefix is "/" If prefix is a handle, scope is a community
544          * or collection, so "/handle/1721.x/xxxx/" is the prefix.
545          */

546         if (!location.equals("/"))
547         {
548             prefix = "/handle/" + location + "/";
549         }
550
551         if (button.equals("submit_titles"))
552         {
553             // Redirect to browse by title
554
url = request.getContextPath() + prefix + "browse-title";
555         }
556         else if (button.equals("submit_authors"))
557         {
558             // Redirect to browse authors
559
url = request.getContextPath() + prefix + "browse-author";
560         }
561         else if (button.equals("submit_subjects"))
562         {
563             // Redirect to browse by date
564
url = request.getContextPath() + prefix + "browse-subject";
565         }
566         else if (button.equals("submit_dates"))
567         {
568             // Redirect to browse by date
569
url = request.getContextPath() + prefix + "browse-date";
570         }
571         else if (button.equals("submit_search")
572                 || (request.getParameter("query") != null))
573         {
574             /*
575              * Have to check for search button and query - in some browsers,
576              * typing a query into the box and hitting return doesn't produce a
577              * submit button parameter. Redirect to appropriate search page
578              */

579             url = request.getContextPath()
580                     + prefix
581                     + "simple-search?query="
582                     + URLEncoder.encode(request.getParameter("query"),
583                             Constants.DEFAULT_ENCODING);
584         }
585
586         // If a button was pressed, redirect to appropriate page
587
if (url != null)
588         {
589             response.sendRedirect(response.encodeRedirectURL(url));
590
591             return true;
592         }
593
594         return false;
595     }
596
597     /**
598      * Utility method to obtain the titles for the Items in the given list.
599      *
600      * @param List
601      * of Items
602      * @return array of corresponding titles
603      */

604     private String JavaDoc[] getItemTitles(List JavaDoc items)
605     {
606         String JavaDoc[] titles = new String JavaDoc[items.size()];
607
608         for (int i = 0; i < items.size(); i++)
609         {
610             Item item = (Item) items.get(i);
611
612             // FIXME: Should probably check for preferred language?
613
DCValue[] titlesForThis = item.getDC("title", null, Item.ANY);
614
615             // Just use the first title, if any
616
if (titlesForThis.length == 0)
617             {
618                 // No title at all!
619
titles[i] = null;
620             }
621             else
622             {
623                 // Use first title
624
titles[i] = titlesForThis[0].value;
625             }
626         }
627
628         return titles;
629     }
630
631     /**
632      * Utility method obtain URLs for the most recent items
633      *
634      * @param context
635      * DSpace context
636      * @param items
637      * the items to get URLs for
638      * @return an array of URLs (in Strings) corresponding to those items
639      */

640     private String JavaDoc[] getItemURLs(Context context, List JavaDoc items)
641             throws SQLException JavaDoc
642     {
643         String JavaDoc[] urls = new String JavaDoc[items.size()];
644
645         for (int i = 0; i < items.size(); i++)
646         {
647             Item item = (Item) items.get(i);
648             urls[i] = "/handle/" + item.getHandle();
649         }
650
651         return urls;
652     }
653
654     /**
655      * Utility method to produce a list of parent communities for a given
656      * community, ending with the passed community, if include is true. If
657      * commmunity is top-level, the array will be empty, or contain only the
658      * passed community, if include is true. The array is ordered highest level
659      * to lowest
660      */

661     private Community[] getParents(Community c, boolean include)
662             throws SQLException JavaDoc
663     {
664         // Find all the "parent" communities for the community
665
Community[] parents = c.getAllParents();
666
667         // put into an array in reverse order
668
int revLength = include ? (parents.length + 1) : parents.length;
669         Community[] reversedParents = new Community[revLength];
670         int index = parents.length - 1;
671
672         for (int i = 0; i < parents.length; i++)
673         {
674             reversedParents[i] = parents[index - i];
675         }
676
677         if (include)
678         {
679             reversedParents[revLength - 1] = c;
680         }
681
682         return reversedParents;
683     }
684 }
685
Popular Tags