001: /*
002: * EditCommunitiesServlet.java
003: *
004: * Version: $Revision: 1719 $
005: *
006: * Date: $Date: 2006-12-28 07:12:43 -0600 (Thu, 28 Dec 2006) $
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.servlet.admin;
041:
042: import java.io.BufferedInputStream;
043: import java.io.File;
044: import java.io.FileInputStream;
045: import java.io.IOException;
046: import java.io.InputStream;
047: import java.sql.SQLException;
048:
049: import javax.servlet.ServletException;
050: import javax.servlet.http.HttpServletRequest;
051: import javax.servlet.http.HttpServletResponse;
052:
053: import org.apache.log4j.Logger;
054: import org.dspace.app.webui.servlet.DSpaceServlet;
055: import org.dspace.app.webui.util.FileUploadRequest;
056: import org.dspace.app.webui.util.JSPManager;
057: import org.dspace.app.webui.util.UIUtil;
058: import org.dspace.authorize.AuthorizeException;
059: import org.dspace.authorize.AuthorizeManager;
060: import org.dspace.content.Bitstream;
061: import org.dspace.content.BitstreamFormat;
062: import org.dspace.content.Collection;
063: import org.dspace.content.Community;
064: import org.dspace.content.FormatIdentifier;
065: import org.dspace.content.Item;
066: import org.dspace.core.Constants;
067: import org.dspace.core.Context;
068: import org.dspace.core.LogManager;
069: import org.dspace.eperson.Group;
070:
071: /**
072: * Servlet for editing communities and collections, including deletion,
073: * creation, and metadata editing
074: *
075: * @author Robert Tansley
076: * @version $Revision: 1719 $
077: */
078: public class EditCommunitiesServlet extends DSpaceServlet {
079: /** User wants to edit a community */
080: public static final int START_EDIT_COMMUNITY = 1;
081:
082: /** User wants to delete a community */
083: public static final int START_DELETE_COMMUNITY = 2;
084:
085: /** User wants to create a community */
086: public static final int START_CREATE_COMMUNITY = 3;
087:
088: /** User wants to edit a collection */
089: public static final int START_EDIT_COLLECTION = 4;
090:
091: /** User wants to delete a collection */
092: public static final int START_DELETE_COLLECTION = 5;
093:
094: /** User wants to create a collection */
095: public static final int START_CREATE_COLLECTION = 6;
096:
097: /** User commited community edit or creation */
098: public static final int CONFIRM_EDIT_COMMUNITY = 7;
099:
100: /** User confirmed community deletion */
101: public static final int CONFIRM_DELETE_COMMUNITY = 8;
102:
103: /** User commited collection edit or creation */
104: public static final int CONFIRM_EDIT_COLLECTION = 9;
105:
106: /** User wants to delete a collection */
107: public static final int CONFIRM_DELETE_COLLECTION = 10;
108:
109: /** Logger */
110: private static Logger log = Logger
111: .getLogger(EditCommunitiesServlet.class);
112:
113: protected void doDSGet(Context context, HttpServletRequest request,
114: HttpServletResponse response) throws ServletException,
115: IOException, SQLException, AuthorizeException {
116: // GET just displays the list of communities and collections
117: showControls(context, request, response);
118: }
119:
120: protected void doDSPost(Context context,
121: HttpServletRequest request, HttpServletResponse response)
122: throws ServletException, IOException, SQLException,
123: AuthorizeException {
124: // First, see if we have a multipart request (uploading a logo)
125: String contentType = request.getContentType();
126:
127: if ((contentType != null)
128: && (contentType.indexOf("multipart/form-data") != -1)) {
129: // This is a multipart request, so it's a file upload
130: processUploadLogo(context, request, response);
131:
132: return;
133: }
134:
135: /*
136: * Respond to submitted forms. Each form includes an "action" parameter
137: * indicating what needs to be done (from the constants above.)
138: */
139: int action = UIUtil.getIntParameter(request, "action");
140:
141: /*
142: * Most of the forms supply one or more of these values. Since we just
143: * get null if we try and find something with ID -1, we'll just try and
144: * find both here to save hassle later on
145: */
146: Community community = Community.find(context, UIUtil
147: .getIntParameter(request, "community_id"));
148: Community parentCommunity = Community.find(context, UIUtil
149: .getIntParameter(request, "parent_community_id"));
150: Collection collection = Collection.find(context, UIUtil
151: .getIntParameter(request, "collection_id"));
152:
153: // Just about every JSP will need the values we received
154: request.setAttribute("community", community);
155: request.setAttribute("parent", parentCommunity);
156: request.setAttribute("collection", collection);
157:
158: /*
159: * First we check for a "cancel" button - if it's been pressed, we
160: * simply return to the main control page
161: */
162: if (request.getParameter("submit_cancel") != null) {
163: showControls(context, request, response);
164:
165: return;
166: }
167:
168: if (AuthorizeManager.isAdmin(context)) {
169: // set a variable to show all buttons
170: request.setAttribute("admin_button", new Boolean(true));
171: }
172:
173: // Now proceed according to "action" parameter
174: switch (action) {
175: case START_EDIT_COMMUNITY:
176:
177: // Display the relevant "edit community" page
178: JSPManager.showJSP(request, response,
179: "/tools/edit-community.jsp");
180:
181: break;
182:
183: case START_DELETE_COMMUNITY:
184:
185: // Show "confirm delete" page
186: JSPManager.showJSP(request, response,
187: "/tools/confirm-delete-community.jsp");
188:
189: break;
190:
191: case START_CREATE_COMMUNITY:
192:
193: // Display edit community page with empty fields + create button
194: JSPManager.showJSP(request, response,
195: "/tools/edit-community.jsp");
196:
197: break;
198:
199: case START_EDIT_COLLECTION:
200:
201: // Display the relevant "edit collection" page
202: JSPManager.showJSP(request, response,
203: "/tools/edit-collection.jsp");
204:
205: break;
206:
207: case START_DELETE_COLLECTION:
208:
209: // Show "confirm delete" page
210: JSPManager.showJSP(request, response,
211: "/tools/confirm-delete-collection.jsp");
212:
213: break;
214:
215: case START_CREATE_COLLECTION:
216:
217: // Forward to collection creation wizard
218: response.sendRedirect(response.encodeRedirectURL(request
219: .getContextPath()
220: + "/tools/collection-wizard?community_id="
221: + community.getID()));
222:
223: break;
224:
225: case CONFIRM_EDIT_COMMUNITY:
226:
227: // Edit or creation of a community confirmed
228: processConfirmEditCommunity(context, request, response,
229: community);
230:
231: break;
232:
233: case CONFIRM_DELETE_COMMUNITY:
234:
235: // remember the parent community, if any
236: Community parent = community.getParentCommunity();
237:
238: // Delete the community
239: community.delete();
240:
241: // if community was top-level, redirect to community-list page
242: if (parent == null) {
243: response.sendRedirect(response
244: .encodeRedirectURL(request.getContextPath()
245: + "/community-list"));
246: } else
247: // redirect to parent community page
248: {
249: response.sendRedirect(response
250: .encodeRedirectURL(request.getContextPath()
251: + "/handle/" + parent.getHandle()));
252: }
253:
254: // Show main control page
255: //showControls(context, request, response);
256: // Commit changes to DB
257: context.complete();
258:
259: break;
260:
261: case CONFIRM_EDIT_COLLECTION:
262:
263: // Edit or creation of a collection confirmed
264: processConfirmEditCollection(context, request, response,
265: community, collection);
266:
267: break;
268:
269: case CONFIRM_DELETE_COLLECTION:
270:
271: // Delete the collection
272: community.removeCollection(collection);
273:
274: // Show main control page
275: showControls(context, request, response);
276:
277: // Commit changes to DB
278: context.complete();
279:
280: break;
281:
282: default:
283:
284: // Erm... weird action value received.
285: log.warn(LogManager.getHeader(context, "integrity_error",
286: UIUtil.getRequestLogInfo(request)));
287: JSPManager.showIntegrityError(request, response);
288: }
289: }
290:
291: /**
292: * Show community home page with admin controls
293: *
294: * @param context
295: * Current DSpace context
296: * @param request
297: * Current HTTP request
298: * @param response
299: * Current HTTP response
300: */
301: private void showControls(Context context,
302: HttpServletRequest request, HttpServletResponse response)
303: throws ServletException, IOException, SQLException,
304: AuthorizeException {
305: // new approach - eliminate the 'list-communities' page in favor of the
306: // community home page, enhanced with admin controls. If no community,
307: // or no parent community, just fall back to the community-list page
308: Community community = (Community) request
309: .getAttribute("community");
310:
311: if (community != null) {
312: response.sendRedirect(response.encodeRedirectURL(request
313: .getContextPath()
314: + "/handle/" + community.getHandle()));
315: } else {
316: // see if a parent community was specified
317: Community parent = (Community) request
318: .getAttribute("parent");
319:
320: if (parent != null) {
321: response.sendRedirect(response
322: .encodeRedirectURL(request.getContextPath()
323: + "/handle/" + parent.getHandle()));
324: } else {
325: // fall back on community-list page
326: response.sendRedirect(response
327: .encodeRedirectURL(request.getContextPath()
328: + "/community-list"));
329: }
330: }
331: }
332:
333: /**
334: * Create/update community metadata from a posted form
335: *
336: * @param context
337: * DSpace context
338: * @param request
339: * the HTTP request containing posted info
340: * @param response
341: * the HTTP response
342: * @param community
343: * the community to update (or null for creation)
344: */
345: private void processConfirmEditCommunity(Context context,
346: HttpServletRequest request, HttpServletResponse response,
347: Community community) throws ServletException, IOException,
348: SQLException, AuthorizeException {
349: if (request.getParameter("create").equals("true")) {
350: // if there is a parent community id specified, create community
351: // as its child; otherwise, create it as a top-level community
352: int parentCommunityID = UIUtil.getIntParameter(request,
353: "parent_community_id");
354:
355: if (parentCommunityID != -1) {
356: Community parent = Community.find(context,
357: parentCommunityID);
358:
359: if (parent != null) {
360: community = parent.createSubcommunity();
361: }
362: } else {
363: community = Community.create(null, context);
364: }
365:
366: // Set attribute
367: request.setAttribute("community", community);
368: }
369:
370: community.setMetadata("name", request.getParameter("name"));
371: community.setMetadata("short_description", request
372: .getParameter("short_description"));
373:
374: String intro = request.getParameter("introductory_text");
375:
376: if (intro.equals("")) {
377: intro = null;
378: }
379:
380: String copy = request.getParameter("copyright_text");
381:
382: if (copy.equals("")) {
383: copy = null;
384: }
385:
386: String side = request.getParameter("side_bar_text");
387:
388: if (side.equals("")) {
389: side = null;
390: }
391:
392: community.setMetadata("introductory_text", intro);
393: community.setMetadata("copyright_text", copy);
394: community.setMetadata("side_bar_text", side);
395: community.update();
396:
397: // Which button was pressed?
398: String button = UIUtil.getSubmitButton(request, "submit");
399:
400: if (button.equals("submit_set_logo")) {
401: // Change the logo - delete any that might be there first
402: community.setLogo(null);
403: community.update();
404:
405: // Display "upload logo" page. Necessary attributes already set by
406: // doDSPost()
407: JSPManager.showJSP(request, response,
408: "/dspace-admin/upload-logo.jsp");
409: } else if (button.equals("submit_delete_logo")) {
410: // Simply delete logo
411: community.setLogo(null);
412: community.update();
413:
414: // Show edit page again - attributes set in doDSPost()
415: JSPManager.showJSP(request, response,
416: "/tools/edit-community.jsp");
417: } else if (button.equals("submit_authorization_edit")) {
418: // Forward to policy edit page
419: response
420: .sendRedirect(response.encodeRedirectURL(request
421: .getContextPath()
422: + "/dspace-admin/authorize?community_id="
423: + community.getID()
424: + "&submit_community_select=1"));
425: } else {
426: // Button at bottom clicked - show main control page
427: showControls(context, request, response);
428: }
429:
430: // Commit changes to DB
431: context.complete();
432: }
433:
434: /**
435: * Create/update collection metadata from a posted form
436: *
437: * @param context
438: * DSpace context
439: * @param request
440: * the HTTP request containing posted info
441: * @param response
442: * the HTTP response
443: * @param community
444: * the community the collection is in
445: * @param collection
446: * the collection to update (or null for creation)
447: */
448: private void processConfirmEditCollection(Context context,
449: HttpServletRequest request, HttpServletResponse response,
450: Community community, Collection collection)
451: throws ServletException, IOException, SQLException,
452: AuthorizeException {
453: if (request.getParameter("create").equals("true")) {
454: // We need to create a new community
455: collection = community.createCollection();
456: request.setAttribute("collection", collection);
457: }
458:
459: // Update the basic metadata
460: collection.setMetadata("name", request.getParameter("name"));
461: collection.setMetadata("short_description", request
462: .getParameter("short_description"));
463:
464: String intro = request.getParameter("introductory_text");
465:
466: if (intro.equals("")) {
467: intro = null;
468: }
469:
470: String copy = request.getParameter("copyright_text");
471:
472: if (copy.equals("")) {
473: copy = null;
474: }
475:
476: String side = request.getParameter("side_bar_text");
477:
478: if (side.equals("")) {
479: side = null;
480: }
481:
482: String license = request.getParameter("license");
483:
484: if (license.equals("")) {
485: license = null;
486: }
487:
488: String provenance = request
489: .getParameter("provenance_description");
490:
491: if (provenance.equals("")) {
492: provenance = null;
493: }
494:
495: collection.setMetadata("introductory_text", intro);
496: collection.setMetadata("copyright_text", copy);
497: collection.setMetadata("side_bar_text", side);
498: collection.setMetadata("license", license);
499: collection.setMetadata("provenance_description", provenance);
500:
501: // Which button was pressed?
502: String button = UIUtil.getSubmitButton(request, "submit");
503:
504: if (button.equals("submit_set_logo")) {
505: // Change the logo - delete any that might be there first
506: collection.setLogo(null);
507:
508: // Display "upload logo" page. Necessary attributes already set by
509: // doDSPost()
510: JSPManager.showJSP(request, response,
511: "/dspace-admin/upload-logo.jsp");
512: } else if (button.equals("submit_delete_logo")) {
513: // Simply delete logo
514: collection.setLogo(null);
515:
516: // Show edit page again - attributes set in doDSPost()
517: JSPManager.showJSP(request, response,
518: "/tools/edit-collection.jsp");
519: } else if (button.startsWith("submit_wf_create_")) {
520: int step = Integer.parseInt(button.substring(17));
521:
522: // Create new group
523: Group newGroup = collection.createWorkflowGroup(step);
524: collection.update();
525:
526: // Forward to group edit page
527: response
528: .sendRedirect(response.encodeRedirectURL(request
529: .getContextPath()
530: + "/tools/group-edit?group_id="
531: + newGroup.getID()));
532: } else if (button.equals("submit_admins_create")) {
533: // Create new group
534: Group newGroup = collection.createAdministrators();
535:
536: // Forward to group edit page
537: response
538: .sendRedirect(response.encodeRedirectURL(request
539: .getContextPath()
540: + "/tools/group-edit?group_id="
541: + newGroup.getID()));
542: } else if (button.equals("submit_submitters_create")) {
543: // Create new group
544: Group newGroup = collection.createSubmitters();
545:
546: // Forward to group edit page
547: response
548: .sendRedirect(response.encodeRedirectURL(request
549: .getContextPath()
550: + "/tools/group-edit?group_id="
551: + newGroup.getID()));
552: } else if (button.equals("submit_authorization_edit")) {
553: // Forward to policy edit page
554: response.sendRedirect(response.encodeRedirectURL(request
555: .getContextPath()
556: + "/dspace-admin/authorize?collection_id="
557: + collection.getID()
558: + "&submit_collection_select=1"));
559: } else if (button.startsWith("submit_wf_edit_")) {
560: int step = Integer.parseInt(button.substring(15));
561:
562: // Edit workflow group
563: Group g = collection.getWorkflowGroup(step);
564: response.sendRedirect(response.encodeRedirectURL(request
565: .getContextPath()
566: + "/tools/group-edit?group_id=" + g.getID()));
567: } else if (button.equals("submit_submitters_edit")) {
568: // Edit submitters group
569: Group g = collection.getSubmitters();
570: response.sendRedirect(response.encodeRedirectURL(request
571: .getContextPath()
572: + "/tools/group-edit?group_id=" + g.getID()));
573: } else if (button.equals("submit_admins_edit")) {
574: // Edit 'collection administrators' group
575: Group g = collection.getAdministrators();
576: response.sendRedirect(response.encodeRedirectURL(request
577: .getContextPath()
578: + "/tools/group-edit?group_id=" + g.getID()));
579: } else if (button.startsWith("submit_wf_delete_")) {
580: // Delete workflow group
581: int step = Integer.parseInt(button.substring(17));
582:
583: Group g = collection.getWorkflowGroup(step);
584: collection.setWorkflowGroup(step, null);
585:
586: // Have to update to avoid ref. integrity error
587: collection.update();
588: g.delete();
589:
590: // Show edit page again - attributes set in doDSPost()
591: JSPManager.showJSP(request, response,
592: "/tools/edit-collection.jsp");
593: } else if (button.equals("submit_create_template")) {
594: // Create a template item
595: collection.createTemplateItem();
596:
597: // Forward to edit page for new template item
598: Item i = collection.getTemplateItem();
599: i.setOwningCollection(collection);
600:
601: // have to update to avoid ref. integrity error
602: i.update();
603: collection.update();
604: context.complete();
605: response.sendRedirect(response.encodeRedirectURL(request
606: .getContextPath()
607: + "/tools/edit-item?item_id=" + i.getID()));
608:
609: return;
610: } else if (button.equals("submit_edit_template")) {
611: // Forward to edit page for template item
612: Item i = collection.getTemplateItem();
613: response.sendRedirect(response.encodeRedirectURL(request
614: .getContextPath()
615: + "/tools/edit-item?item_id=" + i.getID()));
616: } else if (button.equals("submit_delete_template")) {
617: collection.removeTemplateItem();
618:
619: // Show edit page again - attributes set in doDSPost()
620: JSPManager.showJSP(request, response,
621: "/tools/edit-collection.jsp");
622: } else {
623: // Plain old "create/update" button pressed - go back to main page
624: showControls(context, request, response);
625: }
626:
627: // Commit changes to DB
628: collection.update();
629: context.complete();
630: }
631:
632: /**
633: * Process the input from the upload logo page
634: *
635: * @param context
636: * current DSpace context
637: * @param request
638: * current servlet request object
639: * @param response
640: * current servlet response object
641: */
642: private void processUploadLogo(Context context,
643: HttpServletRequest request, HttpServletResponse response)
644: throws ServletException, IOException, SQLException,
645: AuthorizeException {
646: // Wrap multipart request to get the submission info
647: FileUploadRequest wrapper = new FileUploadRequest(request);
648:
649: Community community = Community.find(context, UIUtil
650: .getIntParameter(wrapper, "community_id"));
651: Collection collection = Collection.find(context, UIUtil
652: .getIntParameter(wrapper, "collection_id"));
653:
654: File temp = wrapper.getFile("file");
655:
656: // Read the temp file as logo
657: InputStream is = new BufferedInputStream(new FileInputStream(
658: temp));
659: Bitstream logoBS;
660:
661: if (collection == null) {
662: logoBS = community.setLogo(is);
663: } else {
664: logoBS = collection.setLogo(is);
665: }
666:
667: // Strip all but the last filename. It would be nice
668: // to know which OS the file came from.
669: String noPath = wrapper.getFilesystemName("file");
670:
671: while (noPath.indexOf('/') > -1) {
672: noPath = noPath.substring(noPath.indexOf('/') + 1);
673: }
674:
675: while (noPath.indexOf('\\') > -1) {
676: noPath = noPath.substring(noPath.indexOf('\\') + 1);
677: }
678:
679: logoBS.setName(noPath);
680: logoBS.setSource(wrapper.getFilesystemName("file"));
681:
682: // Identify the format
683: BitstreamFormat bf = FormatIdentifier.guessFormat(context,
684: logoBS);
685: logoBS.setFormat(bf);
686: AuthorizeManager.addPolicy(context, logoBS, Constants.WRITE,
687: context.getCurrentUser());
688: logoBS.update();
689:
690: if (AuthorizeManager.isAdmin(context)) {
691: // set a variable to show all buttons
692: request.setAttribute("admin_button", new Boolean(true));
693: }
694:
695: if (collection == null) {
696: community.update();
697:
698: // Show community edit page
699: request.setAttribute("community", community);
700: JSPManager.showJSP(request, response,
701: "/tools/edit-community.jsp");
702: } else {
703: collection.update();
704:
705: // Show collection edit page
706: request.setAttribute("collection", collection);
707: request.setAttribute("community", community);
708: JSPManager.showJSP(request, response,
709: "/tools/edit-collection.jsp");
710: }
711:
712: // Remove temp file
713: temp.delete();
714:
715: // Update DB
716: context.complete();
717: }
718: }
|