Hi Gary,

I implemented a simple embargo as follows:

*. Setup the ingest workflow to specify an
    embargo period in the 'dc:date available'
    field.

*. Modify the dspace-api code so that
         AuthorizeManager::authorize()
   calls out to a checkEmbargo() method
   to verify that an object does not have
   an outstanding embargo.
   Currently hard-coded to only check the
   embargo for anonymous readers.
 
This seems to work in the test environment I have,
but we haven't rolled anything out for patron use.
I like the solution because:

*. It's implemented at the API level -
      not at the Manakin UI level
*. Does not require changes to the
     database schema
*. Simple implementation - just change one .java file
    and rebuild dspace-api.jar.
    Can be generalized to enforce the embargo
    for different groups of users/whatever.
    
Anyway - just FYI.  I was planning to send an e-mail
to the dev-list once I had the code out in use
on a real production server to see if there is
any interest in it, but that may not happen for
several months yet, so there's a listing of the
code I've been playing with below.

Good luck!
Reuben


$  hg diff -r  1 input-forms.xml
...
+       </field>
+       <field>
+        <dc-schema>dc</dc-schema>
+         <dc-element>date</dc-element>
+         <dc-qualifier>available</dc-qualifier>
+         <repeatable>false</repeatable>
+         <label>Embargo</label>
+         <input-type
value-pairs-name="etd_embargo">dropdown</input-type>
+         <hint>Thesis embargo must be justified by reason of pending
patent,
+                security restriction, or other similar constraint on
public access.
+            </hint>
+         <required></required>
+       </field>
+
+     </page>
+   </form>
...+<value-pairs value-pairs-name="etd_embargo"
dc-term="date.available">
+<pair>
+<displayed-value>Immediate access to full description and
thesis</displayed-value>
+<stored-value>NO_RESTRICTION</stored-value>
+</pair>
+<pair>
+<displayed-value>Access to full description and thesis in 6
months</displayed-value>
+<stored-value>MONTHS_WITHHELD:6</stored-value>
+</pair>
+<pair>
+<displayed-value>Access to full description and thesis in 1
+year</displayed-value>
+<stored-value>MONTHS_WITHHELD:12</stored-value>
+</pair>
+<pair>
+<displayed-value>Access to full description and thesis in 2
+years</displayed-value>
+<stored-value>MONTHS_WITHHELD:24</stored-value>
+</pair>
+</value-pairs>

-----------------------------------------
$ svn diff
===================================================================
---
dspace-api/src/main/java/org/dspace/authorize/AuthorizeManager.java     
(revision
2942)
+++
dspace-api/src/main/java/org/dspace/authorize/AuthorizeManager.java     (working
copy)
@@ -40,11 +40,19 @@
 package org.dspace.authorize;
 
 import java.sql.SQLException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.Iterator;
 import java.util.List;
 
+import org.apache.log4j.Logger;
+import org.dspace.content.Bitstream;
+import org.dspace.content.Bundle;
+import org.dspace.content.DCValue;
 import org.dspace.content.DSpaceObject;
+import org.dspace.content.Item;
 import org.dspace.core.Constants;
 import org.dspace.core.Context;
 import org.dspace.eperson.EPerson;
@@ -70,6 +78,7 @@
  */
 public class AuthorizeManager
 {
+    private static final Logger log =
Logger.getLogger(AuthorizeManager.class);
     /**
      * Utility method, checks that the current user of the given
context can
      * perform all of the specified actions on the given object. An
@@ -237,6 +246,99 @@
     }
 
     /**
+     * Return true if an embargo is in effect on the given thing.
+     * Application policy determines which users must respect an
embargo.
+     * Embargo is only checked for BitStream objects by crawling
+     * up to the Item level and checking for date.available
+     * metadata specifying MONTHS_WITHHELD:#
+     * TODO: make this method configurable via a config file
+     *        and plugin mechanism.
+     *
+     * @param thing to test for embargo
+     * @return true if an embargo needs enforced, false otherwise
+     */
+    public static boolean checkEmbargo ( DSpaceObject thing ) throws
SQLException {
+        if ( Constants.BITSTREAM != thing.getType () ) {
+            return false;
+        }
+        boolean b_embargo_metadata = false;
+        log.info( "checking embargo on bitstream id: " + thing.getID
() );
+
+        // Check for an embargo on the owning item - ugh!
+        for ( Bundle bundle : ((Bitstream) thing).getBundles () ) {
+            for ( Item item : bundle.getItems () ) {
+                for ( DCValue dc_embargo : item.getMetadata( "dc",
"date", "available", Item.ANY ) ) {
+                    b_embargo_metadata = true;
+                    if ( dc_embargo.value.startsWith(
"MONTHS_WITHHELD:" ) ) {
+                        DateFormat formatter = new
SimpleDateFormat("yyyy-MM-dd");
+                        Date       t_now = new Date ();
+                        int        i_months_withheld =
Integer.parseInt( dc_embargo.value.substring( "MONTHS_WITHHELD:".length
() ) );
+                        
+                        // Frick - figure out if embargo is still in
effect
+                        DCValue[] v_issued = item.getMetadata( "dc",
"date", "issued", Item.ANY );
+                        if ( v_issued.length < 1 ) {
+                            log.info( "embargo failed to find ISSUED
date for item: " + item.getID () );
+                        }
+                            
+                        for ( DCValue dc_issued : v_issued ) {
+                            String s_date = dc_issued.value;
+                            int    i_split = s_date.indexOf( "T" );
+                            if ( i_split > 0 ) {
+                                s_date = s_date.substring( 0, i_split
);
+                            }
+                            try {
+                                Date t_issued = formatter.parse(
s_date );
+                                // Just a loose estimate - 31
days/month
+                                Date t_embargo = new Date(
t_issued.getTime () +
+                                                           (long)
i_months_withheld*31*24*60*60*1000
+                                                       );
+                                if ( t_now.getTime () <
t_embargo.getTime () ) {
+                                    // embargo is still in effect!
+                                    //if (log.isDebugEnabled()) {
+                                    log.info( "Denying access due to
embargo to bistream with id: " + thing.getID () + " t_now: " + t_now +
", t_issued: " + t_issued + ", t_embargo: " + t_embargo  );
+                                    //}
+                                    return true;
+                                } else {
+                                    log.info( "Embargo expired on id:
" + thing.getID() + " t_now: " + t_now + ", t_issued: " + t_issued + ",
t_embargo: " + t_embargo );
+                                }
+                            } catch ( java.text.ParseException e ) {
+                                log.info( "Failed to parse
date.available embargo string: " + s_date );
+                            }
+                            break;  // Should be exactly 1 issue date
+                        } // endfor - dc:date.issued
+                        break; // break out of the date.available
loop!
+                    } else {
+                        log.info( "embargo cannot parse
data.available: " + dc_embargo.value );
+                    } // endif WITHHELD
+                } // endfor dc:date.available
+            } // endfor item
+        } // endofor bundle
+        
+        if ( ! b_embargo_metadata ) {
+            log.info( "embargo no metadata for item: " + thing.getID
() );
+        }
+        return false;
+    } 
+
+    /**
+     * Check whether an embargo should be enforced
+     * on the given object for the user with the given userid.
+     * TODO: make this method configurable via a config file
+     *        and plugin mechanism.
+     *
+     * @param context of login
+     * @param thing DSpaceObject
+     * @param i_userid of user trying to access thing, 0 == Anonymous
+     * @return true if an embargo needs enforced, false otherwise
+     */
+    public static boolean checkEmbargo ( Context context, DSpaceObject
thing, int i_userid ) throws SQLException {
+        if ( (0 == i_userid) ) {
+            return checkEmbargo( thing );
+        }
+        return false;
+    }
+
+    /**
      * Check to see if the given user can perform the given action on
the given
      * object. Always returns true if the ignore authorization flat is
set in
      * the current context.
@@ -266,6 +368,11 @@
             return false;
         }
 
+        
+        //if (log.isDebugEnabled()) {
+        log.info( "authorizing access to object id: " + o.getID () );
+        //}
+
         // is authorization disabled for this context?
         if (c.ignoreAuthorization())
         {
@@ -289,6 +396,11 @@
             }
         }
 
+        if ( checkEmbargo( c, o, userid ) ) {
+            return false;
+        }
+
+
         for (ResourcePolicy rp : getPoliciesActionFilter(c, o,
action))
         {
             // check policies for date validity

---------------

>>> Gary McGath <[EMAIL PROTECTED]> 6/30/2008 1:59 PM >>>
Gary McGath wrote:
> Sigh ... Implemnting embargo on the Manakin side of DSpace 1.5 is 
> proving to be the bane of my life. I appreciate the suggestions I've

> received, but most of them require waiting, and that isn't an
option.
> 
> Anyway, I've been trying to implement a variant of Embargo v2 
> (http://wiki.dspace.org/index.php/Embargo_on_Bitstream_v2_%28JSP%29),

> and making some progress. It comes down to a modification to 
> dspace-api/src/main/java/org/dspace/content/InstallItem.java , where
I 
> add the following code to installItem:

I've found the problem, or at least a major part of it. In the Wiki,
I'd 
provided Oracle code to set the primary key with a trigger, since the 
DEFAULT clause isn't legal under Oracle. But this was conflicting with

DSpace's wrapper classes, with the result that the primary key was 
apparently being set twice. This meant that the UPDATE statement 
generated by DatabaseManager.java used a primary key value that didn't

belong to the row it was trying to update.

I altered my database to remove the trigger, and now at least rows are

appearing in the UMRESTRICTED table which have actual data. I'm 
wondering if the DEFAULT clause should be there at all, even for 
Postgresql. I'm far from an SQL expert, so my conclusions should be 
treated with caution.

I've updated the wiki page 
(http://wiki.dspace.org/index.php/Embargo_on_Bitstream_v2_%28JSP%29#Create_Database_Tables)

to delete the offending trigger, so that now the Oracle code looks just

like the old SQL except for the absence of a DEFAULT clause.

If there are further issues with this, I'll post again to the list.


-- 
Gary McGath
Digital Library Software Engineer
Harvard University Library Office for Information Systems
http://hul.harvard.edu/~gary/index.html 


-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php 
_______________________________________________
DSpace-tech mailing list
[email protected] 
https://lists.sourceforge.net/lists/listinfo/dspace-tech

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
DSpace-tech mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/dspace-tech

Reply via email to