/*
* CollectionWizardServlet.java
*
* Version: $Revision: 4309 $
*
* Date: $Date: 2009-09-30 19:20:07 +0000 (Wed, 30 Sep 2009) $
*
* Copyright (c) 2002-2005, Hewlett-Packard Company and Massachusetts
* Institute of Technology. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the Hewlett-Packard Company nor the name of the
* Massachusetts Institute of Technology nor the names of their
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
package org.dspace.app.webui.servlet.admin;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.dspace.app.util.AuthorizeUtil;
import org.dspace.app.webui.servlet.DSpaceServlet;
import org.dspace.app.webui.util.FileUploadRequest;
import org.dspace.app.webui.util.JSPManager;
import org.dspace.app.webui.util.UIUtil;
import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.AuthorizeManager;
import org.dspace.content.Bitstream;
import org.dspace.content.BitstreamFormat;
import org.dspace.content.Collection;
import org.dspace.content.Community;
import org.dspace.content.FormatIdentifier;
import org.dspace.content.Item;
import org.dspace.content.MetadataField;
import org.dspace.content.MetadataSchema;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.core.LogManager;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
/**
* Collection creation wizard UI
*
* @author Robert Tansley
* @version $Revision: 4309 $
*/
public class CollectionWizardServlet extends DSpaceServlet
{
/** Initial questions page */
public final static int INITIAL_QUESTIONS = 1;
/** Basic information page */
public final static int BASIC_INFO = 2;
/** Permissions pages */
public final static int PERMISSIONS = 3;
/** Default item page */
public final static int DEFAULT_ITEM = 4;
/** Summary page */
public final static int SUMMARY = 5;
/** Permissions page for who gets read permissions on new items */
public final static int PERM_READ = 10;
/** Permissions page for submitters */
public final static int PERM_SUBMIT = 11;
/** Permissions page for workflow step 1 */
public final static int PERM_WF1 = 12;
/** Permissions page for workflow step 2 */
public final static int PERM_WF2 = 13;
/** Permissions page for workflow step 3 */
public final static int PERM_WF3 = 14;
/** Permissions page for collection administrators */
public final static int PERM_ADMIN = 15;
/** Logger */
private static Logger log = Logger.getLogger(CollectionWizardServlet.class);
protected void doDSGet(Context context, HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException,
SQLException, AuthorizeException
{
/*
* For GET, all we should really get is a community_id parameter (DB ID
* of community to add collection to). doDSPost handles this
*/
doDSPost(context, request, response);
}
protected void doDSPost(Context context, HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException,
SQLException, AuthorizeException
{
/*
* For POST, we expect from the form:
*
* community_id DB ID if it was a 'create a new collection' button press
*
* OR
*
* collection_id DB ID of collection we're dealing with stage Stage
* we're at (from constants above)
*/
// First, see if we have a multipart request
// (the 'basic info' page which might include uploading a logo)
String contentType = request.getContentType();
if ((contentType != null)
&& (contentType.indexOf("multipart/form-data") != -1))
{
// This is a multipart request, so it's a file upload
processBasicInfo(context, request, response);
return;
}
int communityID = UIUtil.getIntParameter(request, "community_id");
if (communityID > -1)
{
// We have a community ID, "create new collection" button pressed
Community c = Community.find(context, communityID);
if (c == null)
{
log.warn(LogManager.getHeader(context, "integrity_error",
UIUtil.getRequestLogInfo(request)));
JSPManager.showIntegrityError(request, response);
return;
}
// Create the collection
Collection newCollection = c.createCollection();
request.setAttribute("collection", newCollection);
if (AuthorizeManager.isAdmin(context))
{
// set a variable to show all buttons
request.setAttribute("sysadmin_button", new Boolean(true));
}
try
{
AuthorizeUtil.authorizeManageAdminGroup(context, newCollection);
request.setAttribute("admin_create_button", new Boolean(true));
}
catch (AuthorizeException authex) {
request.setAttribute("admin_create_button", new Boolean(false));
}
try
{
AuthorizeUtil.authorizeManageSubmittersGroup(context, newCollection);
request.setAttribute("submitters_button", new Boolean(true));
}
catch (AuthorizeException authex) {
request.setAttribute("submitters_button", new Boolean(false));
}
try
{
AuthorizeUtil.authorizeManageWorkflowsGroup(context, newCollection);
request.setAttribute("workflows_button", new Boolean(true));
}
catch (AuthorizeException authex) {
request.setAttribute("workflows_button", new Boolean(false));
}
try
{
AuthorizeUtil.authorizeManageTemplateItem(context, newCollection);
request.setAttribute("template_button", new Boolean(true));
}
catch (AuthorizeException authex) {
request.setAttribute("template_button", new Boolean(false));
}
JSPManager.showJSP(request, response,
"/dspace-admin/wizard-questions.jsp");
context.complete();
}
else
{
// Collection already created, dealing with one of the wizard pages
int collectionID = UIUtil.getIntParameter(request, "collection_id");
int stage = UIUtil.getIntParameter(request, "stage");
// Get the collection
Collection collection = Collection.find(context, collectionID);
// Put it in request attributes, as most JSPs will need it
request.setAttribute("collection", collection);
if (collection == null)
{
log.warn(LogManager.getHeader(context, "integrity_error",
UIUtil.getRequestLogInfo(request)));
JSPManager.showIntegrityError(request, response);
return;
}
// All pages will need this attribute
request.setAttribute("collection.id", String.valueOf(collection
.getID()));
switch (stage)
{
case INITIAL_QUESTIONS:
processInitialQuestions(context, request, response, collection);
break;
case PERMISSIONS:
processPermissions(context, request, response, collection);
break;
case DEFAULT_ITEM:
processDefaultItem(context, request, response, collection);
break;
default:
log.warn(LogManager.getHeader(context, "integrity_error",
UIUtil.getRequestLogInfo(request)));
JSPManager.showIntegrityError(request, response);
}
}
}
/**
* Process input from initial questions page
*
* @param context
* DSpace context
* @param request
* HTTP request
* @param response
* HTTP response
* @param collection
* Collection we're editing
*/
private void processInitialQuestions(Context context,
HttpServletRequest request, HttpServletResponse response,
Collection collection) throws SQLException, ServletException,
IOException, AuthorizeException
{
Group anonymousGroup = Group.find(context, 0);
// "Public read" checkbox. Only need to do anything
// if it's not checked (only system admin can uncheck this!).
if (!UIUtil.getBoolParameter(request, "public_read")
&& AuthorizeManager.isAdmin(context))
{
// Remove anonymous default policies for new items
AuthorizeManager.removePoliciesActionFilter(context, collection,
Constants.DEFAULT_ITEM_READ);
AuthorizeManager.removePoliciesActionFilter(context, collection,
Constants.DEFAULT_BITSTREAM_READ);
}
// Some people authorised to submit
if (UIUtil.getBoolParameter(request, "submitters"))
{
// Create submitters group
Group g = collection.createSubmitters();
}
// Check for the workflow steps
for (int i = 1; i <= 3; i++)
{
if (UIUtil.getBoolParameter(request, "workflow" + i))
{
// should have workflow step i
Group g = collection.createWorkflowGroup(i);
}
}
// Check for collection administrators
if (UIUtil.getBoolParameter(request, "admins"))
{
// Create administrators group
Group g = collection.createAdministrators();
}
// Default item stuff?
if (UIUtil.getBoolParameter(request, "default.item"))
{
collection.createTemplateItem();
}
// Need to set a name so that the indexer won't throw an exception
collection.setMetadata("name", "");
collection.update();
// Now display "basic info" screen
JSPManager.showJSP(request, response,
"/dspace-admin/wizard-basicinfo.jsp");
context.complete();
}
/**
* Process input from one of the permissions pages
*
* @param context
* DSpace context
* @param request
* HTTP request
* @param response
* HTTP response
* @param collection
* Collection we're editing
*/
private void processPermissions(Context context,
HttpServletRequest request, HttpServletResponse response,
Collection collection) throws SQLException, ServletException,
IOException, AuthorizeException
{
// Which permission are we dealing with?
int permission = UIUtil.getIntParameter(request, "permission");
// First, we deal with the special case of the MIT group...
if (UIUtil.getBoolParameter(request, "mitgroup"))
{
Group mitGroup = Group.findByName(context, "MIT Users");
int action;
if (permission == PERM_READ)
{
// assign default item and bitstream read to mitGroup
AuthorizeManager.addPolicy(context, collection,
Constants.DEFAULT_ITEM_READ, mitGroup);
AuthorizeManager.addPolicy(context, collection,
Constants.DEFAULT_BITSTREAM_READ, mitGroup);
}
else
{
// Must be submit
AuthorizeManager.addPolicy(context, collection, Constants.ADD,
mitGroup);
}
}
//We need to add the selected people to the group.
// First, get the relevant group
Group g = null;
switch (permission)
{
case PERM_READ:
// Actually need to create a group for this.
g = Group.create(context);
// Name it according to our conventions
g
.setName("COLLECTION_" + collection.getID()
+ "_DEFAULT_ITEM_READ");
// Give it the needed permission
AuthorizeManager.addPolicy(context, collection,
Constants.DEFAULT_ITEM_READ, g);
AuthorizeManager.addPolicy(context, collection,
Constants.DEFAULT_BITSTREAM_READ, g);
break;
case PERM_SUBMIT:
g = collection.getSubmitters();
break;
case PERM_WF1:
g = collection.getWorkflowGroup(1);
break;
case PERM_WF2:
g = collection.getWorkflowGroup(2);
break;
case PERM_WF3:
g = collection.getWorkflowGroup(3);
break;
case PERM_ADMIN:
g = collection.getAdministrators();
break;
}
// Add people and groups from the form to the group
int[] eperson_ids = UIUtil.getIntParameters(request, "eperson_id");
int[] group_ids = UIUtil.getIntParameters(request, "group_ids");
if (eperson_ids != null)
{
for (int i = 0; i < eperson_ids.length; i++)
{
EPerson eperson = EPerson.find(context, eperson_ids[i]);
if (eperson != null)
{
g.addMember(eperson);
}
}
}
if (group_ids != null)
{
for (int i = 0; i < group_ids.length; i++)
{
Group group = Group.find(context, group_ids[i]);
if (group != null)
{
g.addMember(group);
}
}
}
// Update group
g.update();
showNextPage(context, request, response, collection, permission);
context.complete();
}
/**
* process input from basic info page
*
* @param context
* @param request
* @param response
* @param collection
* @throws SQLException
* @throws ServletException
* @throws IOException
* @throws AuthorizeException
*/
private void processBasicInfo(Context context, HttpServletRequest request,
HttpServletResponse response) throws SQLException,
ServletException, IOException, AuthorizeException
{
// Wrap multipart request to get the submission info
FileUploadRequest wrapper = new FileUploadRequest(request);
Collection collection = Collection.find(context, UIUtil
.getIntParameter(wrapper, "collection_id"));
if (collection == null)
{
log.warn(LogManager.getHeader(context, "integrity_error", UIUtil
.getRequestLogInfo(wrapper)));
JSPManager.showIntegrityError(request, response);
return;
}
// Get metadata
collection.setMetadata("name", wrapper.getParameter("name"));
collection.setMetadata("short_description", wrapper
.getParameter("short_description"));
collection.setMetadata("introductory_text", wrapper
.getParameter("introductory_text"));
collection.setMetadata("copyright_text", wrapper
.getParameter("copyright_text"));
collection.setMetadata("side_bar_text", wrapper
.getParameter("side_bar_text"));
collection.setMetadata("provenance_description", wrapper
.getParameter("provenance_description"));
// Need to be more careful about license -- make sure it's null if
// nothing was entered
String license = wrapper.getParameter("license");
if ((license != null) || "".equals(license))
{
collection.setLicense(license);
}
File temp = wrapper.getFile("file");
if (temp != null)
{
// Read the temp file as logo
InputStream is = new BufferedInputStream(new FileInputStream(temp));
Bitstream logoBS = collection.setLogo(is);
// Strip all but the last filename. It would be nice
// to know which OS the file came from.
String noPath = wrapper.getFilesystemName("file");
while (noPath.indexOf('/') > -1)
{
noPath = noPath.substring(noPath.indexOf('/') + 1);
}
while (noPath.indexOf('\\') > -1)
{
noPath = noPath.substring(noPath.indexOf('\\') + 1);
}
logoBS.setName(noPath);
logoBS.setSource(wrapper.getFilesystemName("file"));
// Identify the format
BitstreamFormat bf = FormatIdentifier.guessFormat(context, logoBS);
logoBS.setFormat(bf);
AuthorizeManager.addPolicy(context, logoBS, Constants.WRITE, context
.getCurrentUser());
logoBS.update();
// Remove temp file
temp.delete();
}
collection.update();
// Now work out what next page is
showNextPage(context, request, response, collection, BASIC_INFO);
context.complete();
}
/**
* Process input from default item page
*
* @param context
* DSpace context
* @param request
* HTTP request
* @param response
* HTTP response
* @param collection
* Collection we're editing
*/
private void processDefaultItem(Context context,
HttpServletRequest request, HttpServletResponse response,
Collection collection) throws SQLException, ServletException,
IOException, AuthorizeException
{
Item item = collection.getTemplateItem();
for (int i = 0; i < 10; i++)
{
int dcTypeID = UIUtil.getIntParameter(request, "dctype_" + i);
String value = request.getParameter("value_" + i);
String lang = request.getParameter("lang_" + i);
if ((dcTypeID != -1) && (value != null) && !value.equals(""))
{
MetadataField field = MetadataField.find(context,dcTypeID);
MetadataSchema schema = MetadataSchema.find(context,field.getSchemaID());
item.addMetadata(schema.getName(),field.getElement(), field.getQualifier(), lang, value);
}
}
item.update();
// Now work out what next page is
showNextPage(context, request, response, collection, DEFAULT_ITEM);
context.complete();
}
/**
* Work out which page to show next, and show it
*
* @param context
* @param request
* @param response
* @param collection
* @param stage
* the stage the user just finished, or if PERMISSIONS, the
* particular permissions page
* @throws SQLException
* @throws ServletException
* @throws IOException
* @throws AuthorizeException
*/
private void showNextPage(Context context, HttpServletRequest request,
HttpServletResponse response, Collection collection, int stage)
throws SQLException, ServletException, IOException,
AuthorizeException
{
// Put collection in request attributes, as most JSPs will need it
request.setAttribute("collection", collection);
// FIXME: Not a nice hack -- do we show the MIT users checkbox?
if (Group.findByName(context, "MIT Users") != null)
{
request.setAttribute("mitgroup", new Boolean(true));
}
log.debug(LogManager.getHeader(context, "nextpage", "stage=" + stage));
switch (stage)
{
case BASIC_INFO:
// Next page is 'permission to read' page iff ITEM_DEFAULT_READ
// for anonymous group is NOT there
List anonReadPols = AuthorizeManager.getPoliciesActionFilter(
context, collection, Constants.DEFAULT_ITEM_READ);
// At this stage, if there's any ITEM_DEFAULT_READ, it can only
// be an anonymous one.
if (anonReadPols.size() == 0)
{
request.setAttribute("permission", new Integer(PERM_READ));
JSPManager.showJSP(request, response,
"/dspace-admin/wizard-permissions.jsp");
break;
}
case PERM_READ:
// Next page is 'permission to submit' iff there's a submit group
// defined
if (collection.getSubmitters() != null)
{
request.setAttribute("permission", new Integer(PERM_SUBMIT));
JSPManager.showJSP(request, response,
"/dspace-admin/wizard-permissions.jsp");
break;
}
case PERM_SUBMIT:
// Next page is 'workflow step 1' iff there's a wf step 1 group
// defined
if (collection.getWorkflowGroup(1) != null)
{
request.setAttribute("permission", new Integer(PERM_WF1));
JSPManager.showJSP(request, response,
"/dspace-admin/wizard-permissions.jsp");
break;
}
case PERM_WF1:
// Next page is 'workflow step 2' iff there's a wf step 2 group
// defined
if (collection.getWorkflowGroup(2) != null)
{
request.setAttribute("permission", new Integer(PERM_WF2));
JSPManager.showJSP(request, response,
"/dspace-admin/wizard-permissions.jsp");
break;
}
case PERM_WF2:
// Next page is 'workflow step 3' iff there's a wf step 2 group
// defined
if (collection.getWorkflowGroup(3) != null)
{
request.setAttribute("permission", new Integer(PERM_WF3));
JSPManager.showJSP(request, response,
"/dspace-admin/wizard-permissions.jsp");
break;
}
case PERM_WF3:
// Next page is 'collection administrator' iff there's a collection
// administrator group
if (collection.getAdministrators() != null)
{
request.setAttribute("permission", new Integer(PERM_ADMIN));
JSPManager.showJSP(request, response,
"/dspace-admin/wizard-permissions.jsp");
break;
}
case PERM_ADMIN:
// Next page is 'default item' iff there's a default item
if (collection.getTemplateItem() != null)
{
MetadataField[] types = MetadataField.findAll(context);
request.setAttribute("dctypes", types);
JSPManager.showJSP(request, response,
"/dspace-admin/wizard-default-item.jsp");
break;
}
case DEFAULT_ITEM:
// Next page is 'summary page (the last page)
// sort of a hack to pass the community ID to the edit collection
// page,
// which needs it in other contexts
if (collection != null)
{
Community[] communities = collection.getCommunities();
request.setAttribute("community", communities[0]);
EditCommunitiesServlet.storeAuthorizeAttributeCollectionEdit(context, request, collection);
}
JSPManager.showJSP(request, response, "/tools/edit-collection.jsp");
break;
}
}
}