Browse the collection by Title, - Author, or Date.
- <%-- HACK:
+<%-- HACK: |
+ + | + +
<%= copyright %>
@@ -155,7 +197,6 @@ } %> <%= sidebar %> - diff --git a/dspace/jsp/mydspace/subscriptions.jsp b/dspace/jsp/mydspace/subscriptions.jsp new file mode 100644 index 0000000000..3ba846f27a --- /dev/null +++ b/dspace/jsp/mydspace/subscriptions.jsp @@ -0,0 +1,138 @@ +<%-- + - subscription.jsp + - + - Version: $Revision$ + - + - Date: $Date$ + - + - Copyright (c) 2001, 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. + --%> + +<%-- + - Show a user's subscriptions and allow them to be modified + - + - Attributes: + - subscriptions - Collection[] - collections user is subscribed to + - communities - Community[] - communities that subscribed collections + - are in - i.e. subscriptions[0] is in communities[0]. + - updated - Boolean - if true, subscriptions have just been updated + --%> + +<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> + +<%@ page import="org.dspace.content.Community" %> +<%@ page import="org.dspace.content.Collection" %> + +<% + Collection[] subscriptions = + (Collection[]) request.getAttribute("subscriptions"); + Community[] communities = + (Community[]) request.getAttribute("communities"); + boolean updated = + ((Boolean) request.getAttribute("updated")).booleanValue(); +%> + +Your subscriptions have been updated.
+<% + } + + if (subscriptions.length > 0) + { +%> +Below are the collections you are subscribed to. You will be sent an + e-mail each day detailing new items that have become available in these + collection. On days that no new items have appeared, no e-mail will be + sent.
+ +You are not currently subscribed to any collections.
+<% + } +%> + + + +true
, write a message indicating that
+ * updated subscriptions have been stored
+ */
+ private void showSubscriptions(Context context,
+ HttpServletRequest request,
+ HttpServletResponse response,
+ boolean updated)
+ throws ServletException, IOException, SQLException
+ {
+ // Subscribed collections
+ Collection[] subs = Subscribe.getSubscriptions(context,
+ context.getCurrentUser());
+
+ // Get corresponding communities to make the link
+ Community[] communities = new Community[subs.length];
+ for (int i = 0; i < subs.length; i++)
+ {
+ Community[] theseComms = subs[i].getCommunities();
+ // FIXME: Assume first community is container - maybe something
+ // more context sensitive?
+ communities[i] = theseComms[0];
+ }
+
+ request.setAttribute("subscriptions", subs);
+ request.setAttribute("communities", communities);
+ request.setAttribute("updated", new Boolean(updated));
+
+ JSPManager.showJSP(request, response, "/mydspace/subscriptions.jsp");
+ }
+}
diff --git a/dspace/src/org/dspace/app/webui/servlet/X509CertificateServlet.java b/dspace/src/org/dspace/app/webui/servlet/X509CertificateServlet.java
index bc09b6fa2c..8dd6af34c1 100644
--- a/dspace/src/org/dspace/app/webui/servlet/X509CertificateServlet.java
+++ b/dspace/src/org/dspace/app/webui/servlet/X509CertificateServlet.java
@@ -129,7 +129,7 @@ public class X509CertificateServlet extends DSpaceServlet
EPerson eperson = X509Manager.getUser(context, certs[0]);
// Do we have an e-person?
- if (eperson != null && eperson.getActive())
+ if (eperson != null && eperson.canLogIn())
{
// Everything OK - log them in.
Authenticate.loggedIn(context, request, eperson);
diff --git a/dspace/src/org/dspace/app/webui/servlet/admin/EditEPersonServlet.java b/dspace/src/org/dspace/app/webui/servlet/admin/EditEPersonServlet.java
index dd041e6bfd..72f35139fd 100644
--- a/dspace/src/org/dspace/app/webui/servlet/admin/EditEPersonServlet.java
+++ b/dspace/src/org/dspace/app/webui/servlet/admin/EditEPersonServlet.java
@@ -108,7 +108,7 @@ public class EditEPersonServlet extends DSpaceServlet
? null
: request.getParameter("phone"));
- e.setActive(request.getParameter("active") != null &&
+ e.setCanLogIn(request.getParameter("active") != null &&
request.getParameter("active").equals("true"));
e.setRequireCertificate(
diff --git a/dspace/src/org/dspace/eperson/EPerson.java b/dspace/src/org/dspace/eperson/EPerson.java
index 68be47231c..1c65871547 100644
--- a/dspace/src/org/dspace/eperson/EPerson.java
+++ b/dspace/src/org/dspace/eperson/EPerson.java
@@ -394,23 +394,23 @@ public class EPerson implements DSpaceObject
/**
- * Set active/inactive
+ * Indicate whether the user can log in
*
- * @param isactive boolean yes/no
+ * @param login boolean yes/no
*/
- public void setActive(boolean isactive)
+ public void setCanLogIn(boolean login)
{
- myRow.setColumn("active", isactive);
+ myRow.setColumn("can_log_in", login);
}
/**
- * Get active/inactive
+ * Can the user log in?
*
- * @return isactive boolean, yes/no
+ * @return boolean, yes/no
*/
- public boolean getActive()
+ public boolean canLogIn()
{
- return myRow.getBooleanColumn("active");
+ return myRow.getBooleanColumn("can_log_in");
}
@@ -436,6 +436,27 @@ public class EPerson implements DSpaceObject
}
+ /**
+ * Indicate whether the user self-registered
+ *
+ * @param sr boolean yes/no
+ */
+ public void setSelfRegistered(boolean sr)
+ {
+ myRow.setColumn("self_registered", sr);
+ }
+
+ /**
+ * Can the user log in?
+ *
+ * @return boolean, yes/no
+ */
+ public boolean setSelfRegistered()
+ {
+ return myRow.getBooleanColumn("self_registered");
+ }
+
+
/**
* Get the value of a metadata field
*
diff --git a/dspace/src/org/dspace/eperson/Subscribe.java b/dspace/src/org/dspace/eperson/Subscribe.java
new file mode 100644
index 0000000000..872f8d049e
--- /dev/null
+++ b/dspace/src/org/dspace/eperson/Subscribe.java
@@ -0,0 +1,411 @@
+/*
+ * Subscribe.java
+ *
+ * Version: $Revision$
+ *
+ * Date: $Date$
+ *
+ * Copyright (c) 2001, 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.eperson;
+
+import java.io.IOException;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import javax.mail.MessagingException;
+
+import org.apache.log4j.Logger;
+
+import org.dspace.storage.rdbms.DatabaseManager;
+import org.dspace.storage.rdbms.TableRow;
+import org.dspace.storage.rdbms.TableRowIterator;
+import org.dspace.authorize.AuthorizeException;
+import org.dspace.authorize.AuthorizeManager;
+import org.dspace.content.Collection;
+import org.dspace.content.DCDate;
+import org.dspace.content.DCValue;
+import org.dspace.content.Item;
+import org.dspace.core.ConfigurationManager;
+import org.dspace.core.Context;
+import org.dspace.core.Email;
+import org.dspace.core.LogManager;
+import org.dspace.handle.HandleManager;
+import org.dspace.search.Harvest;
+import org.dspace.search.HarvestedItemInfo;
+
+
+/**
+ * Class defining methods for sending new item e-mail alerts to users
+ *
+ * @author Robert Tansley
+ * @version $Revision$
+ */
+public class Subscribe
+{
+ /** log4j logger */
+ private static Logger log = Logger.getLogger(Group.class);
+
+ /**
+ * Subscribe an e-person to a collection. An e-mail will be sent every day
+ * a new item appears in the collection.
+ *
+ * @param context DSpace context
+ * @param eperson EPerson to subscribe
+ * @param collection Collection to subscribe to
+ */
+ public static void subscribe(Context context, EPerson eperson,
+ Collection collection)
+ throws SQLException, AuthorizeException
+ {
+ // Check authorisation. Must be administrator, or the eperson.
+ if (AuthorizeManager.isAdmin(context) ||
+ (context.getCurrentUser() != null &&
+ context.getCurrentUser().getID() == eperson.getID()))
+ {
+ // already subscribed?
+ TableRowIterator r = DatabaseManager.query(context,
+ "SELECT * FROM subscription WHERE eperson_id=" +
+ eperson.getID() + " AND collection_id=" +
+ collection.getID());
+
+ if (!r.hasNext())
+ {
+ // Not subscribed, so add them
+ TableRow row = DatabaseManager.create(context, "subscription");
+ row.setColumn("eperson_id", eperson.getID());
+ row.setColumn("collection_id", collection.getID());
+ DatabaseManager.update(context, row);
+
+ log.info(LogManager.getHeader(context,
+ "subscribe",
+ "eperson_id=" + eperson.getID() + ",collection_id="
+ + collection.getID()));
+ }
+ }
+ else
+ {
+ throw new AuthorizeException(
+ "Only admin or e-person themselves can subscribe");
+ }
+ }
+
+
+ /**
+ * Unsubscribe an e-person to a collection. Passing in null
+ * for the collection unsubscribes the e-person from all collections they
+ * are subscribed to.
+ *
+ * @param context DSpace context
+ * @param eperson EPerson to unsubscribe
+ * @param collection Collection to unsubscribe from
+ */
+ public static void unsubscribe(Context context, EPerson eperson,
+ Collection collection)
+ throws SQLException, AuthorizeException
+ {
+ // Check authorisation. Must be administrator, or the eperson.
+ if (AuthorizeManager.isAdmin(context) ||
+ (context.getCurrentUser() != null &&
+ context.getCurrentUser().getID() == eperson.getID()))
+ {
+ if (collection == null)
+ {
+ // Unsubscribe from all
+ DatabaseManager.updateQuery(context,
+ "DELETE FROM subscription WHERE eperson_id=" +
+ eperson.getID());
+ }
+ else
+ {
+ DatabaseManager.updateQuery(context,
+ "DELETE FROM subscription WHERE eperson_id=" +
+ eperson.getID() + " AND collection_id=" +
+ collection.getID());
+
+ log.info(LogManager.getHeader(context,
+ "unsubscribe",
+ "eperson_id=" + eperson.getID() + ",collection_id="
+ + collection.getID()));
+ }
+ }
+ else
+ {
+ throw new AuthorizeException(
+ "Only admin or e-person themselves can unsubscribe");
+ }
+ }
+
+
+ /**
+ * Find out which collections an e-person is subscribed to
+ *
+ * @param context DSpace context
+ * @param eperson EPerson
+ * @return array of collections e-person is subscribed to
+ */
+ public static Collection[] getSubscriptions(Context context,
+ EPerson eperson)
+ throws SQLException
+ {
+ TableRowIterator tri = DatabaseManager.query(context,
+ "SELECT collection_id FROM subscription WHERE eperson_id=" +
+ eperson.getID());
+
+ List collections = new ArrayList();
+
+ while (tri.hasNext())
+ {
+ TableRow row = tri.next();
+
+ collections.add(Collection.find(context,
+ row.getIntColumn("collection_id")));
+ }
+
+ Collection[] collArray = new Collection[collections.size()];
+ return (Collection[]) collections.toArray(collArray);
+ }
+
+
+ /**
+ * Is that e-person subscribed to that collection?
+ *
+ * @param context DSpace context
+ * @param eperson find out if this e-person is subscribed
+ * @param collection find out if subscribed to this collection
+ * @return true
if they are subscribed
+ */
+ public static boolean isSubscribed(Context context, EPerson eperson,
+ Collection collection)
+ throws SQLException
+ {
+ TableRowIterator tri = DatabaseManager.query(
+ context,
+ "SELECT * FROM subscription WHERE eperson_id=" + eperson.getID() +
+ " AND collection_id=" + collection.getID());
+
+ return tri.hasNext();
+ }
+
+
+ /**
+ * Process subscriptions. This must be invoked only once a day.
+ * Messages are only sent out when a collection has actually received
+ * new items, so that people's mailboxes are not clogged with many "no
+ * new items" mails.+ * Yesterday's newly available items are included. If this is run + * at for example midday, any items that have been made available during + * the current day will not be included, but will be included in the next + * day's run.
+ * For example, if today's date is 2002-10-10 (in UTC) items made available + * during 2002-10-09 (UTC) will be included. + * + * @param context DSpace context object + */ + public static void processDaily(Context context) + throws SQLException, MessagingException, IOException + { + // Grab the subscriptions + TableRowIterator tri = DatabaseManager.query(context, + "SELECT * FROM subscription ORDER BY eperson_id"); + + EPerson currentEPerson = null; + List collections = null; // List of Collections + + // Go through the list collating subscriptions for each e-person + while (tri.hasNext()) + { + TableRow row = tri.next(); + + // Does this row relate to the same e-person as the last? + if (currentEPerson == null || + row.getIntColumn("eperson_id") != currentEPerson.getID()) + { + // New e-person. Send mail for previous e-person + if (currentEPerson != null) + { + sendEmail(context, currentEPerson, collections); + } + + currentEPerson = EPerson.find(context, + row.getIntColumn("eperson_id")); + collections = new ArrayList(); + + } + + collections.add( + Collection.find(context, + row.getIntColumn("collection_id"))); + } + + // Process the last person + if (currentEPerson != null) + { + sendEmail(context, currentEPerson, collections); + } + } + + + /** + * Sends an email to the given e-person with details of new items in the + * given collections, items that appeared yesterday. No e-mail is sent if + * there aren't any new items in any of the collections. + * + * @param context DSpace context object + * @param eperson eperson to send to + * @param collections List of collection IDs (Integers) + */ + public static void sendEmail(Context context, + EPerson eperson, List collections) + throws IOException, MessagingException, SQLException + { + // Get the start and end dates for yesterday + Date thisTimeYesterday = new Date( + System.currentTimeMillis() - (24 * 60 * 60 * 1000)); + + DCDate dcDateYesterday = new DCDate(thisTimeYesterday); + + // this time yesterday in ISO 8601, stripping the time + String isoDateYesterday = + dcDateYesterday.toString().substring(0, 10); + + String startDate = isoDateYesterday; + String endDate = isoDateYesterday + "T23:59:59Z"; + + + // FIXME: text of email should be more configurable from an + // i18n viewpoint + StringBuffer emailText = new StringBuffer(); + boolean isFirst = true; + + for (int i = 0; i < collections.size(); i++) + { + Collection c = (Collection) collections.get(i); + + List itemInfos = Harvest.harvest(context, + c, + startDate, + endDate, + true, // Need item objects + false); // But not containers + + // Only add to buffer if there are new items + if (itemInfos.size() > 0) + { + if (!isFirst) + { + emailText.append( + "\n---------------------------------------\n"); + } + else + { + isFirst = false; + } + + emailText.append("New items in collection ") + .append(c.getMetadata("name")) + .append(": ") + .append(itemInfos.size()) + .append("\n\n"); + + for (int j = 0; j < itemInfos.size(); j++) + { + HarvestedItemInfo hii = + (HarvestedItemInfo) itemInfos.get(j); + + DCValue[] titles = hii.item.getDC("title", null, Item.ANY); + emailText.append(" Title: "); + + if (titles.length > 0) + { + emailText.append(titles[0].value); + } + else + { + emailText.append("Untitled"); + } + + + DCValue[] authors = hii.item.getDC("contributor", Item.ANY, + Item.ANY); + + if (authors.length > 0) + { + emailText.append("\n Authors: ") + .append(authors[0].value); + for (int k = 1; k < authors.length; k++) + { + emailText.append("\n ") + .append(authors[k].value); + } + } + + emailText.append("\n ID: ") + .append(HandleManager.getCanonicalForm(hii.handle)) + .append("\n\n"); + } + } + } + + + // Send an e-mail if there were any new items + if (emailText.length() > 0) + { + Email email = ConfigurationManager.getEmail("subscription"); + + email.addArgument(emailText.toString()); + email.send(); + + log.info(LogManager.getHeader(context, + "sent_subscription", + "eperson_id=" + eperson.getID())); + } + } + + + /** + * Method for invoking subscriptions via the command line + * + * @param argv command-line arguments, none used yet + */ + public static void main(String[] argv) + throws Exception + { + Context context = new Context(); + processDaily(context); + // Nothing is actually written + context.abort(); + } +} diff --git a/dspace/src/org/dspace/eperson/test/EPersonTest.java b/dspace/src/org/dspace/eperson/test/EPersonTest.java index f2b2981ec4..8eef45bfd3 100644 --- a/dspace/src/org/dspace/eperson/test/EPersonTest.java +++ b/dspace/src/org/dspace/eperson/test/EPersonTest.java @@ -81,7 +81,7 @@ public class EPersonTest extends TestCase e1.setFirstName("Bob"); e1.setLastName("Brannigan"); e1.setPassword("password"); - e1.setActive(true); + e1.setCanLogIn(true); e1.setRequireCertificate(false); e1.update(); diff --git a/dspace/src/org/dspace/history/HistoryManager.java b/dspace/src/org/dspace/history/HistoryManager.java index 67416c3356..bf40616c14 100644 --- a/dspace/src/org/dspace/history/HistoryManager.java +++ b/dspace/src/org/dspace/history/HistoryManager.java @@ -806,7 +806,7 @@ public class HistoryManager eperson.getLastName()); model.add(res, model.createProperty(getPropertyId(shortname, "active")), - eperson.getActive()); + eperson.canLogIn()); model.add(res, model.createProperty(getPropertyId(shortname, "require_certificate")), eperson.getRequireCertificate());