Compare commits

...

56 Commits

Author SHA1 Message Date
Hardy Pottinger
b5b1d429ae [maven-release-plugin] prepare release dspace-1.8.3 2013-07-25 08:40:24 -05:00
Tim Donohue
d1eee3c804 Merge pull request #263 from hardyoyo/DS-1603-backport_to_18
backporting patch to DS-1603 to dspace 1.8
2013-07-24 13:21:09 -07:00
Hardy Pottinger
bb46eb44f4 backporting patch to DS-1603 to dspace 1.8 2013-07-24 14:49:22 -05:00
Tim Donohue
27573deea0 More line ending normalization (related to DS-1587) 2013-07-24 19:35:56 +00:00
vagrant
24224dbd0e Line ending normalization (related to DS-1587) 2013-07-23 21:05:49 +00:00
Tim Donohue
42bb874a92 Fixing incorrect path (related to DS-1587) 2013-06-26 12:37:32 -05:00
Tim Donohue
7b9e0230a8 Still more line ending cleanup (related to DS-1587) 2013-06-26 09:49:33 -05:00
Tim Donohue
d3487915e8 Even more line ending cleanup (related to changes in DS-1587), argh. 2013-06-26 09:46:37 -05:00
Tim Donohue
3cb3054fd1 More line ending cleanup (related to changes in DS-1587) 2013-06-26 09:43:22 -05:00
Tim Donohue
5b5960e72a Fix line endings (related to changes in DS-1587) 2013-06-26 09:33:43 -05:00
Tim Donohue
1a01ab804b Merge pull request #243 from DSpace/DS-1587-1.8.x
DS-1587: Fix 1.8.x Branch for Git/GitHub
2013-06-26 07:28:29 -07:00
Tim Donohue
292ef8a639 Fix license headers in files which were missing them 2013-06-26 09:16:20 -05:00
Tim Donohue
e0fe7ebdac Cleanup POMs to work with GitHub and also merge in old "dspace-pom" functionality into dspace-parent POM 2013-06-26 09:14:47 -05:00
Tim Donohue
553b242cbd DS-1587 - Commit .gitignore and .gitattributes. Fix line endings in several POMs 2013-06-25 16:43:44 -05:00
Ivan Masár
f377bac528 DS-1581 Prevent double-up of restriction message 2013-06-20 09:31:04 +02:00
helix84
5816e75571 Merge pull request #107 from doctorlard/buildfix2_1_8_x
Keep empty directories so that Maven builds without errors.
2012-12-08 15:03:18 -08:00
Jonathan Harker
200757a8c1 Keep empty directories so that Maven builds without errors. 2012-10-20 03:25:12 +13:00
Tim Donohue
d23cb5969b Updating PDF manual in 1.8.x branch. This both updates the PDF manual for folks forking via this branch as well as the one linked off www.dspace.org (as the main website now points at the PDF manuals stored in corresponding GitHub branch). 2012-06-12 14:01:44 -05:00
Tim Donohue
3fdcb3bb3e [maven-release-plugin] prepare for next development iteration
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6956 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2012-02-24 16:27:02 +00:00
Tim Donohue
c7dcf15487 [maven-release-plugin] prepare release dspace-1.8.2
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6954 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2012-02-24 16:26:46 +00:00
Tim Donohue
cfacc241db Committing a slightly updated version of DSpace PDF Manual for 1.8.2
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6952 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2012-02-24 15:51:11 +00:00
Tim Donohue
3182d5b2cf Fix for DS-1122: When adding a Bitstream to a Bundle, the 'bitstream_order' is always set to the 'sequence_id' (applied to both 1.8.x branch and Trunk). Also fixes issues with AIPs being able to restore bitstream ordering.
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6948 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2012-02-20 22:00:19 +00:00
Kevin Van de Velde
e7369eff13 [DS-1129] Edit Harvesting Collection Content Source tab broken
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6945 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2012-02-18 10:50:14 +00:00
Kevin Van de Velde
2ec032bb0e [DS-918] Concurrent task claiming and editing of metadata possible for same item in submission workflow
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6944 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2012-02-18 10:26:42 +00:00
Kevin Van de Velde
a2381e00f7 [DS-1048] Superfluous warning in dspace.log
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6942 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2012-02-18 10:14:43 +00:00
Kevin Van de Velde
a42f5ede3f [DS-910] Encoding of discovery facet urls
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6941 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2012-02-18 09:38:15 +00:00
Tim Donohue
b25a877d14 Fix for DS-1120: AIP Backup & Restore : SITE AIP has a different checksum everytime when orphaned Collection/Community groups exist (applied to both 1.8.x branch and Trunk)
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6940 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2012-02-15 19:04:16 +00:00
Tim Donohue
4ccab20836 Backporting fix for DS-1108 to 1.8.x branch: AIP Backup & Restore doesn't restore a Bitstream's "Sequence ID"
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6938 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2012-02-15 17:54:27 +00:00
Tim Donohue
c1b4e3f04c Backporting fix for DS-1107 to 1.8.x branch: System-wide Curation Task UI is missing a "Task" label
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6937 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2012-02-15 17:49:48 +00:00
Scott Phillips
d792352696 DS-1124, increase the default upload maximum to 2GB
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6935 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2012-02-13 22:03:00 +00:00
Scott Phillips
c979086f51 DS-1012: updated the configuration parameters to use the modules syntax instead of the old style all in one.
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6914 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2011-12-20 17:30:02 +00:00
Robin Taylor
ac3fa09efa [maven-release-plugin] prepare for next development iteration
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6912 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2011-12-15 10:24:03 +00:00
Robin Taylor
20943b7192 [maven-release-plugin] prepare release dspace-1.8.1
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6910 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2011-12-15 10:23:26 +00:00
Robin Taylor
8eb972dd3e Correct SCM element in dspace-1.8.x/pom.xml
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6909 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2011-12-15 10:14:04 +00:00
Robin Taylor
44047a38e3 [maven-release-plugin] rollback the release of dspace-1.8.1
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6908 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2011-12-15 10:10:02 +00:00
Robin Taylor
2836e3c9a5 [maven-release-plugin] prepare release dspace-1.8.1
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6907 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2011-12-15 10:02:52 +00:00
Robin Taylor
3cce8ae734 [maven-release-plugin] rollback the release of dspace-1.8.1
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6906 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2011-12-15 09:51:02 +00:00
Robin Taylor
86496eb53c [maven-release-plugin] prepare release dspace-1.8.1
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6905 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2011-12-15 09:38:59 +00:00
Robin Taylor
5255f9f13d Add licence to StaticPage
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6904 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2011-12-15 09:20:03 +00:00
Peter Dietz
952cc523e7 DS-1076 Add a simple StaticPage.java and map requests to page/* to it. Overrides happen in XSL. Have a demo at page/about.
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6902 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2011-12-14 23:26:10 +00:00
Scott Phillips
97e769977d DS-1094: Fixed an NPE error while mapping errors, fixed a typo in unknown, and the authors column pull from creator or contributor.
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6899 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2011-12-12 19:42:49 +00:00
Peter Dietz
abd0262a9e DS-1090 Fix fetchURL method for CC License, so that it does not fail due to recent CC changes.
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6897 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2011-12-08 18:26:40 +00:00
Kevin Van de Velde
43f2c10746 [DS-899] Last modified timestamp doesn't trigger on bitstream delete bugfix
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6888 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2011-12-07 16:23:40 +00:00
Kevin Van de Velde
67b82c063f [DS-1064] Authentication error bugfix with external login in JSPUI
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6873 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2011-12-04 10:59:17 +00:00
Tim Donohue
ec3593b5c7 Fix for DS-1077: XMLUI & CLI always show a NullPointerException after running a Site-wide Curation Task. This patch ensures that the Curator is not too quick to call complete() on its Context object when running a Site-wide task. It also ensures the Curator doesn't continually create a new Context each time 'curationContext()' is called -- instead a newly created context is cached so that it can be used for the remainder of the task processing. This fix has been applied to trunk and 1.8.x branch.
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6871 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2011-12-02 17:53:03 +00:00
Scott Phillips
53079bceab DS-1055: Limit display of harvested bitstreams when using harvesting by reference. (Committed to branch and trunk)
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6865 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2011-11-28 20:17:43 +00:00
Scott Phillips
e369276e9f DS-1052: Items with null date.accessioned are perminantly sorted to the top of all date based searches. (committed to both trunk and branch)
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6864 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2011-11-28 20:06:09 +00:00
Scott Phillips
2bb7d1715d DS-1012: Lazy Shibboleth authentication.
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6861 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2011-11-28 20:03:02 +00:00
Scott Phillips
96b3992377 DS-1068: Removing a metadata field from an item does not update the browse sorting indexes. (committed to both trunk and branch)
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6860 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2011-11-28 20:01:44 +00:00
Scott Phillips
99c07e1400 DS-1062: Emails report new items twice, sometimes. (this change was committed to branch and trunk)
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6857 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2011-11-28 19:58:26 +00:00
Scott Phillips
69cdf807c6 DS-1065: Login CHooser will place plank div prior to login form (committed to both trunk and branch)
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6856 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2011-11-28 19:57:03 +00:00
Robin Taylor
641cf1030b [DS-1075] - Fix separator replacement in URIs
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6852 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2011-11-28 11:20:31 +00:00
Robin Taylor
967008c637 [DS-1074] - Fix DB connection leak in DAVServlet
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6850 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2011-11-28 10:24:29 +00:00
Andrea Schweer
de2a2c2f3a [DS-1070] DSpaceObjectManager unnecessarily keeps references to DSpace objects
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6846 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2011-11-21 04:44:31 +00:00
Robin Taylor
acd00a24f3 Updated 1_8_x branch to correct version and scm elements.
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6838 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2011-11-05 10:03:13 +00:00
Robin Taylor
c2292282f7 Creating a branch for 1.8.x bug-fix releases.
git-svn-id: http://scm.dspace.org/svn/repo/dspace/branches/dspace-1_8_x@6837 9c30dcfa-912a-0410-8fc2-9e0234be79fd
2011-11-04 14:35:31 +00:00
186 changed files with 23332 additions and 22225 deletions

14
.gitattributes vendored Normal file
View File

@@ -0,0 +1,14 @@
# Auto detect text files and perform LF normalization
* text=auto
# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain

23
.gitignore vendored Normal file
View File

@@ -0,0 +1,23 @@
## Ignore the MVN compiled output directories from version tracking
target/
## Ignore project files created by Eclipse
.settings/
.project
.classpath
## Ignore project files created by IntelliJ IDEA
*.iml
*.ipr
*.iws
.idea/
## Ignore project files created by NetBeans
nbproject/private/
build/
nbbuild/
dist/
nbdist/
nbactions.xml
nb-configuration.xml
META-INF/

5
LICENSE_HEADER Normal file
View File

@@ -0,0 +1,5 @@
The contents of this file are subject to the license and copyright
detailed in the LICENSE and NOTICE files at the root of the source
tree and available online at
http://www.dspace.org/license/

View File

@@ -13,20 +13,14 @@
<parent> <parent>
<groupId>org.dspace</groupId> <groupId>org.dspace</groupId>
<artifactId>dspace-parent</artifactId> <artifactId>dspace-parent</artifactId>
<version>3.0-SNAPSHOT</version> <version>1.8.3</version>
<relativePath>..</relativePath> <relativePath>..</relativePath>
</parent> </parent>
<!-- <properties>
The Subversion repository location is used by Continuum to update against <!-- This is the path to the root [dspace-src] directory. -->
when changes have occurred, this spawns a new build cycle and releases snapshots <root.basedir>${basedir}/..</root.basedir>
into the snapshot repository below. </properties>
-->
<scm>
<connection>scm:svn:http://scm.dspace.org/svn/repo/dspace/trunk/dspace</connection>
<developerConnection>scm:svn:https://scm.dspace.org/svn/repo/dspace/trunk/dspace</developerConnection>
<url>http://scm.dspace.org/svn/repo/dspace/trunk/dspace</url>
</scm>
<!-- <!--
Runtime and Compile Time dependencies for DSpace. Runtime and Compile Time dependencies for DSpace.
@@ -256,6 +250,11 @@
<artifactId>rome-modules</artifactId> <artifactId>rome-modules</artifactId>
<version>1.0</version> <version>1.0</version>
</dependency> </dependency>
</dependencies> <dependency>
<groupId>com.coverity.security</groupId>
<artifactId>coverity-escapers</artifactId>
<version>1.1.1</version>
</dependency>
</dependencies>
</project> </project>

View File

@@ -1,407 +1,407 @@
/** /**
* The contents of this file are subject to the license and copyright * The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source * detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at * tree and available online at
* *
* http://www.dspace.org/license/ * http://www.dspace.org/license/
*/ */
package org.dspace.app.bulkedit; package org.dspace.app.bulkedit;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.content.DCValue; import org.dspace.content.DCValue;
import org.dspace.content.Collection; import org.dspace.content.Collection;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
* Utility class to store changes to item that may occur during a batch edit. * Utility class to store changes to item that may occur during a batch edit.
* *
* @author Stuart Lewis * @author Stuart Lewis
*/ */
public class BulkEditChange public class BulkEditChange
{ {
/** The item these changes relate to */ /** The item these changes relate to */
private Item item; private Item item;
/** The List of hashtables with the new elements */ /** The List of hashtables with the new elements */
private List<DCValue> adds; private List<DCValue> adds;
/** The List of hashtables with the removed elements */ /** The List of hashtables with the removed elements */
private List<DCValue> removes; private List<DCValue> removes;
/** The List of hashtables with the unchanged elements */ /** The List of hashtables with the unchanged elements */
private List<DCValue> constant; private List<DCValue> constant;
/** The List of the complete set of new values (constant + adds) */ /** The List of the complete set of new values (constant + adds) */
private List<DCValue> complete; private List<DCValue> complete;
/** The list of old collections the item used to be mapped to */ /** The list of old collections the item used to be mapped to */
private List<Collection> oldMappedCollections; private List<Collection> oldMappedCollections;
/** The list of new collections the item has been mapped into */ /** The list of new collections the item has been mapped into */
private List<Collection> newMappedCollections; private List<Collection> newMappedCollections;
/** The old owning collection */ /** The old owning collection */
private Collection oldOwningCollection; private Collection oldOwningCollection;
/** The new owning collection */ /** The new owning collection */
private Collection newOwningCollection; private Collection newOwningCollection;
/** Is this a new item */ /** Is this a new item */
private boolean newItem; private boolean newItem;
/** Has this item been deleted? */ /** Has this item been deleted? */
private boolean deleted; private boolean deleted;
/** Has this item been withdrawn? */ /** Has this item been withdrawn? */
private boolean withdrawn; private boolean withdrawn;
/** Has this item been reinstated? */ /** Has this item been reinstated? */
private boolean reinstated; private boolean reinstated;
/** Have any changes actually been made? */ /** Have any changes actually been made? */
private boolean empty; private boolean empty;
/** /**
* Initialise a change holder for a new item * Initialise a change holder for a new item
*/ */
public BulkEditChange() public BulkEditChange()
{ {
// Set the item to be null // Set the item to be null
item = null; item = null;
newItem = true; newItem = true;
empty = true; empty = true;
oldOwningCollection = null; oldOwningCollection = null;
newOwningCollection = null; newOwningCollection = null;
// Initialise the arrays // Initialise the arrays
adds = new ArrayList<DCValue>(); adds = new ArrayList<DCValue>();
removes = new ArrayList<DCValue>(); removes = new ArrayList<DCValue>();
constant = new ArrayList<DCValue>(); constant = new ArrayList<DCValue>();
complete = new ArrayList<DCValue>(); complete = new ArrayList<DCValue>();
oldMappedCollections = new ArrayList<Collection>(); oldMappedCollections = new ArrayList<Collection>();
newMappedCollections = new ArrayList<Collection>(); newMappedCollections = new ArrayList<Collection>();
} }
/** /**
* Initialise a new change holder for an existing item * Initialise a new change holder for an existing item
* *
* @param i The Item to store * @param i The Item to store
*/ */
public BulkEditChange(Item i) public BulkEditChange(Item i)
{ {
// Store the item // Store the item
item = i; item = i;
newItem = false; newItem = false;
empty = true; empty = true;
// Initialise the arrays // Initialise the arrays
adds = new ArrayList<DCValue>(); adds = new ArrayList<DCValue>();
removes = new ArrayList<DCValue>(); removes = new ArrayList<DCValue>();
constant = new ArrayList<DCValue>(); constant = new ArrayList<DCValue>();
complete = new ArrayList<DCValue>(); complete = new ArrayList<DCValue>();
oldMappedCollections = new ArrayList<Collection>(); oldMappedCollections = new ArrayList<Collection>();
newMappedCollections = new ArrayList<Collection>(); newMappedCollections = new ArrayList<Collection>();
} }
/** /**
* Store the item - used when a new item is created * Store the item - used when a new item is created
* *
* @param i The item * @param i The item
*/ */
public void setItem(Item i) public void setItem(Item i)
{ {
// Store the item // Store the item
item = i; item = i;
} }
/** /**
* Add an added metadata value * Add an added metadata value
* *
* @param dcv The value to add * @param dcv The value to add
*/ */
public void registerAdd(DCValue dcv) public void registerAdd(DCValue dcv)
{ {
// Add the added value // Add the added value
adds.add(dcv); adds.add(dcv);
complete.add(dcv); complete.add(dcv);
empty = false; empty = false;
} }
/** /**
* Add a removed metadata value * Add a removed metadata value
* *
* @param dcv The value to remove * @param dcv The value to remove
*/ */
public void registerRemove(DCValue dcv) public void registerRemove(DCValue dcv)
{ {
// Add the removed value // Add the removed value
removes.add(dcv); removes.add(dcv);
empty = false; empty = false;
} }
/** /**
* Add an unchanged metadata value * Add an unchanged metadata value
* *
* @param dcv The value to keep unchanged * @param dcv The value to keep unchanged
*/ */
public void registerConstant(DCValue dcv) public void registerConstant(DCValue dcv)
{ {
// Add the removed value // Add the removed value
constant.add(dcv); constant.add(dcv);
complete.add(dcv); complete.add(dcv);
} }
/** /**
* Add a new mapped Collection * Add a new mapped Collection
* *
* @param c The new mapped Collection * @param c The new mapped Collection
*/ */
public void registerNewMappedCollection(Collection c) public void registerNewMappedCollection(Collection c)
{ {
// Add the new owning Collection // Add the new owning Collection
newMappedCollections.add(c); newMappedCollections.add(c);
empty = false; empty = false;
} }
/** /**
* Add an old mapped Collection * Add an old mapped Collection
* *
* @param c The old mapped Collection * @param c The old mapped Collection
*/ */
public void registerOldMappedCollection(Collection c) public void registerOldMappedCollection(Collection c)
{ {
// Add the old owning Collection (if it isn't there already, or is an old collection) // Add the old owning Collection (if it isn't there already, or is an old collection)
boolean found = false; boolean found = false;
if ((this.getOldOwningCollection() != null) && if ((this.getOldOwningCollection() != null) &&
(this.getOldOwningCollection().getHandle().equals(c.getHandle()))) (this.getOldOwningCollection().getHandle().equals(c.getHandle())))
{ {
found = true; found = true;
} }
for (Collection collection : oldMappedCollections) for (Collection collection : oldMappedCollections)
{ {
if (collection.getHandle().equals(c.getHandle())) if (collection.getHandle().equals(c.getHandle()))
{ {
found = true; found = true;
} }
} }
if (!found) if (!found)
{ {
oldMappedCollections.add(c); oldMappedCollections.add(c);
empty = false; empty = false;
} }
} }
/** /**
* Register a change to the owning collection * Register a change to the owning collection
* *
* @param oldC The old owning collection * @param oldC The old owning collection
* @param newC The new owning collection * @param newC The new owning collection
*/ */
public void changeOwningCollection(Collection oldC, Collection newC) public void changeOwningCollection(Collection oldC, Collection newC)
{ {
// Store the old owning collection // Store the old owning collection
oldOwningCollection = oldC; oldOwningCollection = oldC;
// Store the new owning collection // Store the new owning collection
newOwningCollection = newC; newOwningCollection = newC;
empty = false; empty = false;
} }
/** /**
* Set the owning collection of an item * Set the owning collection of an item
* *
* @param newC The new owning collection * @param newC The new owning collection
*/ */
public void setOwningCollection(Collection newC) public void setOwningCollection(Collection newC)
{ {
// Store the new owning collection // Store the new owning collection
newOwningCollection = newC; newOwningCollection = newC;
//empty = false; //empty = false;
} }
/** /**
* Get the DSpace Item that these changes are applicable to. * Get the DSpace Item that these changes are applicable to.
* *
* @return The item * @return The item
*/ */
public Item getItem() public Item getItem()
{ {
// Return the item // Return the item
return item; return item;
} }
/** /**
* Get the list of elements and their values that have been added. * Get the list of elements and their values that have been added.
* *
* @return the list of elements and their values that have been added. * @return the list of elements and their values that have been added.
*/ */
public List<DCValue> getAdds() public List<DCValue> getAdds()
{ {
// Return the array // Return the array
return adds; return adds;
} }
/** /**
* Get the list of elements and their values that have been removed. * Get the list of elements and their values that have been removed.
* *
* @return the list of elements and their values that have been removed. * @return the list of elements and their values that have been removed.
*/ */
public List<DCValue> getRemoves() public List<DCValue> getRemoves()
{ {
// Return the array // Return the array
return removes; return removes;
} }
/** /**
* Get the list of unchanged values * Get the list of unchanged values
* *
* @return the list of unchanged values * @return the list of unchanged values
*/ */
public List<DCValue> getConstant() public List<DCValue> getConstant()
{ {
// Return the array // Return the array
return constant; return constant;
} }
/** /**
* Get the list of all values * Get the list of all values
* *
* @return the list of all values * @return the list of all values
*/ */
public List<DCValue> getComplete() public List<DCValue> getComplete()
{ {
// Return the array // Return the array
return complete; return complete;
} }
/** /**
* Get the list of new mapped Collections * Get the list of new mapped Collections
* *
* @return the list of new mapped collections * @return the list of new mapped collections
*/ */
public List<Collection> getNewMappedCollections() public List<Collection> getNewMappedCollections()
{ {
// Return the array // Return the array
return newMappedCollections; return newMappedCollections;
} }
/** /**
* Get the list of old mapped Collections * Get the list of old mapped Collections
* *
* @return the list of old mapped collections * @return the list of old mapped collections
*/ */
public List<Collection> getOldMappedCollections() public List<Collection> getOldMappedCollections()
{ {
// Return the array // Return the array
return oldMappedCollections; return oldMappedCollections;
} }
/** /**
* Get the old owning collection * Get the old owning collection
* *
* @return the old owning collection * @return the old owning collection
*/ */
public Collection getOldOwningCollection() public Collection getOldOwningCollection()
{ {
// Return the old owning collection // Return the old owning collection
return oldOwningCollection; return oldOwningCollection;
} }
/** /**
* Get the new owning collection * Get the new owning collection
* *
* @return the new owning collection * @return the new owning collection
*/ */
public Collection getNewOwningCollection() public Collection getNewOwningCollection()
{ {
// Return the new owning collection // Return the new owning collection
return newOwningCollection; return newOwningCollection;
} }
/** /**
* Does this change object represent a new item? * Does this change object represent a new item?
* *
* @return Whether or not this is for a new item * @return Whether or not this is for a new item
*/ */
public boolean isNewItem() public boolean isNewItem()
{ {
// Return the new item status // Return the new item status
return newItem; return newItem;
} }
/** /**
* Does this change object represent a deleted item? * Does this change object represent a deleted item?
* *
* @return Whether or not this is for a deleted item * @return Whether or not this is for a deleted item
*/ */
public boolean isDeleted() public boolean isDeleted()
{ {
// Return the new item status // Return the new item status
return deleted; return deleted;
} }
/** /**
* Set that this item has been deleted * Set that this item has been deleted
*/ */
public void setDeleted() { public void setDeleted() {
// Store the setting // Store the setting
deleted = true; deleted = true;
empty = false; empty = false;
} }
/** /**
* Does this change object represent a withdrawn item? * Does this change object represent a withdrawn item?
* *
* @return Whether or not this is for a withdrawn item * @return Whether or not this is for a withdrawn item
*/ */
public boolean isWithdrawn() public boolean isWithdrawn()
{ {
// Return the new item status // Return the new item status
return withdrawn; return withdrawn;
} }
/** /**
* Set that this item has been withdrawn * Set that this item has been withdrawn
*/ */
public void setWithdrawn() { public void setWithdrawn() {
// Store the setting // Store the setting
withdrawn = true; withdrawn = true;
empty = false; empty = false;
} }
/** /**
* Does this change object represent a reinstated item? * Does this change object represent a reinstated item?
* *
* @return Whether or not this is for a reinstated item * @return Whether or not this is for a reinstated item
*/ */
public boolean isReinstated() public boolean isReinstated()
{ {
// Return the new item status // Return the new item status
return reinstated; return reinstated;
} }
/** /**
* Set that this item has been deleted * Set that this item has been deleted
*/ */
public void setReinstated() { public void setReinstated() {
// Store the setting // Store the setting
reinstated = true; reinstated = true;
empty = false; empty = false;
} }
/** /**
* Have any changes actually been recorded, or is this empty? * Have any changes actually been recorded, or is this empty?
* *
* @return Whether or not changes have been made * @return Whether or not changes have been made
*/ */
public boolean hasChanges() public boolean hasChanges()
{ {
return !empty; return !empty;
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,193 +1,193 @@
/** /**
* The contents of this file are subject to the license and copyright * The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source * detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at * tree and available online at
* *
* http://www.dspace.org/license/ * http://www.dspace.org/license/
*/ */
package org.dspace.app.bulkedit; package org.dspace.app.bulkedit;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
/** /**
* Utility class to store a line from a CSV file * Utility class to store a line from a CSV file
* *
* @author Stuart Lewis * @author Stuart Lewis
*/ */
public class DSpaceCSVLine implements Serializable public class DSpaceCSVLine implements Serializable
{ {
/** The item id of the item represented by this line. -1 is for a new item */ /** The item id of the item represented by this line. -1 is for a new item */
private int id; private int id;
/** The elements in this line in a hashtable, keyed by the metadata type */ /** The elements in this line in a hashtable, keyed by the metadata type */
private Map<String, ArrayList> items; private Map<String, ArrayList> items;
/** /**
* Create a new CSV line * Create a new CSV line
* *
* @param itemId The item ID of the line * @param itemId The item ID of the line
*/ */
public DSpaceCSVLine(int itemId) public DSpaceCSVLine(int itemId)
{ {
// Store the ID + separator, and initialise the hashtable // Store the ID + separator, and initialise the hashtable
this.id = itemId; this.id = itemId;
items = new HashMap<String, ArrayList>(); items = new HashMap<String, ArrayList>();
} }
/** /**
* Create a new CSV line for a new item * Create a new CSV line for a new item
*/ */
public DSpaceCSVLine() public DSpaceCSVLine()
{ {
// Set the ID to be -1, and initialise the hashtable // Set the ID to be -1, and initialise the hashtable
this.id = -1; this.id = -1;
this.items = new HashMap<String, ArrayList>(); this.items = new HashMap<String, ArrayList>();
} }
/** /**
* Get the item ID that this line represents * Get the item ID that this line represents
* *
* @return The item ID * @return The item ID
*/ */
public int getID() public int getID()
{ {
// Return the ID // Return the ID
return id; return id;
} }
/** /**
* Add a new metadata value to this line * Add a new metadata value to this line
* *
* @param key The metadata key (e.g. dc.contributor.author) * @param key The metadata key (e.g. dc.contributor.author)
* @param value The metadata value * @param value The metadata value
*/ */
public void add(String key, String value) public void add(String key, String value)
{ {
// Create the array list if we need to // Create the array list if we need to
if (items.get(key) == null) if (items.get(key) == null)
{ {
items.put(key, new ArrayList<String>()); items.put(key, new ArrayList<String>());
} }
// Store the item if it is not null // Store the item if it is not null
if (value != null) if (value != null)
{ {
items.get(key).add(value); items.get(key).add(value);
} }
} }
/** /**
* Get all the values that match the given metadata key. Will be null if none exist. * Get all the values that match the given metadata key. Will be null if none exist.
* *
* @param key The metadata key * @param key The metadata key
* @return All the elements that match * @return All the elements that match
*/ */
public List<String> get(String key) public List<String> get(String key)
{ {
// Return any relevant values // Return any relevant values
return items.get(key); return items.get(key);
} }
/** /**
* Get any action associated with this line * Get any action associated with this line
* *
* @return The action (may be blank, 'withdraw', 'reinstate' or 'delete') * @return The action (may be blank, 'withdraw', 'reinstate' or 'delete')
*/ */
public String getAction() public String getAction()
{ {
if (items.containsKey("action")) { if (items.containsKey("action")) {
ArrayList actions = items.get("action"); ArrayList actions = items.get("action");
if (actions.size() > 0) { if (actions.size() > 0) {
return ((String)actions.get(0)).trim(); return ((String)actions.get(0)).trim();
} }
} }
return ""; return "";
} }
/** /**
* Get all the metadata keys that are represented in this line * Get all the metadata keys that are represented in this line
* *
* @return An enumeration of all the keys * @return An enumeration of all the keys
*/ */
public Set<String> keys() public Set<String> keys()
{ {
// Return the keys // Return the keys
return items.keySet(); return items.keySet();
} }
/** /**
* Write this line out as a CSV formatted string, in the order given by the headings provided * Write this line out as a CSV formatted string, in the order given by the headings provided
* *
* @param headings The headings which define the order the elements must be presented in * @param headings The headings which define the order the elements must be presented in
* @return The CSV formatted String * @return The CSV formatted String
*/ */
protected String toCSV(List<String> headings) protected String toCSV(List<String> headings)
{ {
StringBuilder bits = new StringBuilder(); StringBuilder bits = new StringBuilder();
// Add the id // Add the id
bits.append("\"").append(id).append("\"").append(DSpaceCSV.fieldSeparator); bits.append("\"").append(id).append("\"").append(DSpaceCSV.fieldSeparator);
bits.append(valueToCSV(items.get("collection"))); bits.append(valueToCSV(items.get("collection")));
// Add the rest of the elements // Add the rest of the elements
for (String heading : headings) for (String heading : headings)
{ {
bits.append(DSpaceCSV.fieldSeparator); bits.append(DSpaceCSV.fieldSeparator);
List<String> values = items.get(heading); List<String> values = items.get(heading);
if (values != null && !"collection".equals(heading)) if (values != null && !"collection".equals(heading))
{ {
bits.append(valueToCSV(values)); bits.append(valueToCSV(values));
} }
} }
return bits.toString(); return bits.toString();
} }
/** /**
* Internal method to create a CSV formatted String joining a given set of elements * Internal method to create a CSV formatted String joining a given set of elements
* *
* @param values The values to create the string from * @param values The values to create the string from
* @return The line as a CSV formatted String * @return The line as a CSV formatted String
*/ */
protected String valueToCSV(List<String> values) protected String valueToCSV(List<String> values)
{ {
// Check there is some content // Check there is some content
if (values == null) if (values == null)
{ {
return ""; return "";
} }
// Get on with the work // Get on with the work
String s; String s;
if (values.size() == 1) if (values.size() == 1)
{ {
s = values.get(0); s = values.get(0);
} }
else else
{ {
// Concatenate any fields together // Concatenate any fields together
StringBuilder str = new StringBuilder(); StringBuilder str = new StringBuilder();
for (String value : values) for (String value : values)
{ {
if (str.length() > 0) if (str.length() > 0)
{ {
str.append(DSpaceCSV.valueSeparator); str.append(DSpaceCSV.valueSeparator);
} }
str.append(value); str.append(value);
} }
s = str.toString(); s = str.toString();
} }
// Replace internal quotes with two sets of quotes // Replace internal quotes with two sets of quotes
return "\"" + s.replaceAll("\"", "\"\"") + "\""; return "\"" + s.replaceAll("\"", "\"\"") + "\"";
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -836,6 +836,7 @@ public class BrowseDAOOracle implements BrowseDAO
{ {
queryBuf.append(" DESC "); queryBuf.append(" DESC ");
} }
queryBuf.append(" NULLS LAST ");
} }
} }

View File

@@ -844,6 +844,7 @@ public class BrowseDAOPostgres implements BrowseDAO
{ {
queryBuf.append(" DESC "); queryBuf.append(" DESC ");
} }
queryBuf.append(" NULLS LAST ");
} }
} }

View File

@@ -564,6 +564,9 @@ public class IndexBrowse
{ {
String nValue = OrderFormat.makeSortString(value.value, value.language, so.getType()); String nValue = OrderFormat.makeSortString(value.value, value.language, so.getType());
sortMap.put(key, nValue); sortMap.put(key, nValue);
} else {
// Add an empty entry to clear out any old values in the sort columns.
sortMap.put(key, null);
} }
} }

View File

@@ -449,11 +449,19 @@ public class Bundle extends DSpaceObject
// FIXME: multiple inclusion is affected by this... // FIXME: multiple inclusion is affected by this...
AuthorizeManager.inheritPolicies(ourContext, this, b); AuthorizeManager.inheritPolicies(ourContext, this, b);
//Determine the current highest bitstream order in our bundle2bitstream table
//This will always append a newly added bitstream as the last one
int bitstreamOrder = 0; //bitstream order starts at '0' index
TableRow tableRow = DatabaseManager.querySingle(ourContext, "SELECT MAX(bitstream_order) as max_value FROM bundle2bitstream WHERE bundle_id=?", getID());
if(tableRow != null){
bitstreamOrder = tableRow.getIntColumn("max_value") + 1;
}
// Add the mapping row to the database // Add the mapping row to the database
TableRow mappingRow = DatabaseManager.row("bundle2bitstream"); TableRow mappingRow = DatabaseManager.row("bundle2bitstream");
mappingRow.setColumn("bundle_id", getID()); mappingRow.setColumn("bundle_id", getID());
mappingRow.setColumn("bitstream_id", b.getID()); mappingRow.setColumn("bitstream_id", b.getID());
mappingRow.setColumn("bitstream_order", b.getSequenceID()); mappingRow.setColumn("bitstream_order", bitstreamOrder);
DatabaseManager.insert(ourContext, mappingRow); DatabaseManager.insert(ourContext, mappingRow);
} }
@@ -491,6 +499,14 @@ public class Bundle extends DSpaceObject
// Place the bitstream in the list of bitstreams in this bundle // Place the bitstream in the list of bitstreams in this bundle
bitstreams.add(bitstreamMap.get(bitstreamId)); bitstreams.add(bitstreamMap.get(bitstreamId));
}
//The order of the bitstreams has changed, ensure that we update the last modified of our item
Item owningItem = (Item) getParentObject();
if(owningItem != null)
{
owningItem.updateLastModified();
owningItem.update();
} }
} }
@@ -531,7 +547,16 @@ public class Bundle extends DSpaceObject
} }
ourContext.addEvent(new Event(Event.REMOVE, Constants.BUNDLE, getID(), Constants.BITSTREAM, b.getID(), String.valueOf(b.getSequenceID()))); ourContext.addEvent(new Event(Event.REMOVE, Constants.BUNDLE, getID(), Constants.BITSTREAM, b.getID(), String.valueOf(b.getSequenceID())));
//Ensure that the last modified from the item is triggered !
Item owningItem = (Item) getParentObject();
if(owningItem != null)
{
owningItem.updateLastModified();
owningItem.update();
}
// In the event that the bitstream to remove is actually // In the event that the bitstream to remove is actually
// the primary bitstream, be sure to unset the primary // the primary bitstream, be sure to unset the primary
// bitstream. // bitstream.

View File

@@ -123,10 +123,29 @@ public class InstallItem
handle = HandleManager.createHandle(c, item, suppliedHandle); handle = HandleManager.createHandle(c, item, suppliedHandle);
} }
//NOTE: this method specifically skips over "populateMetadata()" // Even though we are restoring an item it may not have a have the proper dates. So lets
// As this is a "restore" all the metadata should have already been restored // double check that it has a date accessioned and date issued, and if either of those dates
// are not set then set them to today.
//@TODO: Do we actually want a "Restored on ..." provenance message? Or perhaps kick off an event? DCDate now = DCDate.getCurrent();
// If the item dosn't have a date.accessioned create one.
DCValue[] dateAccessioned = item.getDC("date", "accessioned", Item.ANY);
if (dateAccessioned.length == 0)
{
item.addDC("date", "accessioned", null, now.toString());
}
// create issue date if not present
DCValue[] currentDateIssued = item.getDC("date", "issued", Item.ANY);
if (currentDateIssued.length == 0)
{
DCDate issued = new DCDate(now.getYear(),now.getMonth(),now.getDay(),-1,-1,-1);
item.addDC("date", "issued", null, issued.toString());
}
// Record that the item was restored
String provDescription = "Restored into DSpace on "+ now + " (GMT).";
item.addDC("description", "provenance", "en", provDescription);
return finishItem(c, item, is, null); return finishItem(c, item, is, null);
} }
@@ -153,7 +172,7 @@ public class InstallItem
} }
} }
// fill in metadata needed by new Item.
private static void populateMetadata(Context c, Item item, DCDate embargoLiftDate) private static void populateMetadata(Context c, Item item, DCDate embargoLiftDate)
throws SQLException, IOException, AuthorizeException throws SQLException, IOException, AuthorizeException
{ {

View File

@@ -306,6 +306,15 @@ public class Item extends DSpaceObject
return myDate; return myDate;
} }
/**
* Method that updates the last modified date of the item
* The modified boolean will be set to true and the actual date update will occur on item.update().
*/
void updateLastModified()
{
modified = true;
}
/** /**
* Set the "is_archived" flag. This is public and only * Set the "is_archived" flag. This is public and only
* <code>WorkflowItem.archive()</code> should set this. * <code>WorkflowItem.archive()</code> should set this.

View File

@@ -1,147 +1,147 @@
/** /**
* The contents of this file are subject to the license and copyright * The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source * detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at * tree and available online at
* *
* http://www.dspace.org/license/ * http://www.dspace.org/license/
*/ */
package org.dspace.content; package org.dspace.content;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Formatter; import java.util.Formatter;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeException;
import org.dspace.content.license.FormattableArgument; import org.dspace.content.license.FormattableArgument;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.eperson.EPerson; import org.dspace.eperson.EPerson;
/** /**
* Utility class to manage generation and storing of the license text that the * Utility class to manage generation and storing of the license text that the
* submitter has to grant/granted for archiving the item * submitter has to grant/granted for archiving the item
* *
* @author bollini * @author bollini
* *
*/ */
public class LicenseUtils public class LicenseUtils
{ {
/** /**
* Return the text of the license that the user has granted/must grant * Return the text of the license that the user has granted/must grant
* before for submit the item. The license text is build using the template * before for submit the item. The license text is build using the template
* defined for the collection if any or the wide site configuration. In the * defined for the collection if any or the wide site configuration. In the
* license text the following substitution can be used. {0} the eperson * license text the following substitution can be used. {0} the eperson
* firstname<br> * firstname<br>
* {1} the eperson lastname<br> * {1} the eperson lastname<br>
* {2} the eperson email<br> * {2} the eperson email<br>
* {3} the current date<br> * {3} the current date<br>
* {4} the collection object that will be formatted using the appropriate * {4} the collection object that will be formatted using the appropriate
* LicenseArgumentFormatter plugin (if defined)<br> * LicenseArgumentFormatter plugin (if defined)<br>
* {5} the item object that will be formatted using the appropriate * {5} the item object that will be formatted using the appropriate
* LicenseArgumentFormatter plugin (if defined)<br> * LicenseArgumentFormatter plugin (if defined)<br>
* {6} the eperson object that will be formatted using the appropriate * {6} the eperson object that will be formatted using the appropriate
* LicenseArgumentFormatter plugin (if defined)<br> * LicenseArgumentFormatter plugin (if defined)<br>
* {x} any addition argument supplied wrapped in the * {x} any addition argument supplied wrapped in the
* LicenseArgumentFormatter based on his type (map key) * LicenseArgumentFormatter based on his type (map key)
* *
* @see LicenseArgumentFormatter * @see LicenseArgumentFormatter
* @param locale * @param locale
* @param collection * @param collection
* @param item * @param item
* @param eperson * @param eperson
* @param additionalInfo * @param additionalInfo
* @return the license text obtained substituting the provided argument in * @return the license text obtained substituting the provided argument in
* the license template * the license template
*/ */
public static String getLicenseText(Locale locale, Collection collection, public static String getLicenseText(Locale locale, Collection collection,
Item item, EPerson eperson, Map<String, Object> additionalInfo) Item item, EPerson eperson, Map<String, Object> additionalInfo)
{ {
Formatter formatter = new Formatter(locale); Formatter formatter = new Formatter(locale);
// EPerson firstname, lastname, email and the current date // EPerson firstname, lastname, email and the current date
// will be available as separate arguments to make more simple produce // will be available as separate arguments to make more simple produce
// "tradition" text license // "tradition" text license
// collection, item and eperson object will be also available // collection, item and eperson object will be also available
int numArgs = 7 + (additionalInfo != null ? additionalInfo.size() : 0); int numArgs = 7 + (additionalInfo != null ? additionalInfo.size() : 0);
Object[] args = new Object[numArgs]; Object[] args = new Object[numArgs];
args[0] = eperson.getFirstName(); args[0] = eperson.getFirstName();
args[1] = eperson.getLastName(); args[1] = eperson.getLastName();
args[2] = eperson.getEmail(); args[2] = eperson.getEmail();
args[3] = new java.util.Date(); args[3] = new java.util.Date();
args[4] = new FormattableArgument("collection", collection); args[4] = new FormattableArgument("collection", collection);
args[5] = new FormattableArgument("item", item); args[5] = new FormattableArgument("item", item);
args[6] = new FormattableArgument("eperson", eperson); args[6] = new FormattableArgument("eperson", eperson);
if (additionalInfo != null) if (additionalInfo != null)
{ {
int i = 7; // Start is next index after previous args int i = 7; // Start is next index after previous args
for (Map.Entry<String, Object> info : additionalInfo.entrySet()) for (Map.Entry<String, Object> info : additionalInfo.entrySet())
{ {
args[i] = new FormattableArgument(info.getKey(), info.getValue()); args[i] = new FormattableArgument(info.getKey(), info.getValue());
i++; i++;
} }
} }
String licenseTemplate = collection.getLicense(); String licenseTemplate = collection.getLicense();
return formatter.format(licenseTemplate, args).toString(); return formatter.format(licenseTemplate, args).toString();
} }
/** /**
* Utility method if no additional arguments has need to be supplied to the * Utility method if no additional arguments has need to be supplied to the
* license template. (i.e. call the full getLicenseText supplying * license template. (i.e. call the full getLicenseText supplying
* <code>null</code> for the additionalInfo argument) * <code>null</code> for the additionalInfo argument)
* *
* @param locale * @param locale
* @param collection * @param collection
* @param item * @param item
* @param eperson * @param eperson
* @return * @return
*/ */
public static String getLicenseText(Locale locale, Collection collection, public static String getLicenseText(Locale locale, Collection collection,
Item item, EPerson eperson) Item item, EPerson eperson)
{ {
return getLicenseText(locale, collection, item, eperson, null); return getLicenseText(locale, collection, item, eperson, null);
} }
/** /**
* Store a copy of the license a user granted in the item. * Store a copy of the license a user granted in the item.
* *
* @param context * @param context
* the dspace context * the dspace context
* @param item * @param item
* the item object of the license * the item object of the license
* @param licenseText * @param licenseText
* the license the user granted * the license the user granted
* @throws SQLException * @throws SQLException
* @throws IOException * @throws IOException
* @throws AuthorizeException * @throws AuthorizeException
*/ */
public static void grantLicense(Context context, Item item, public static void grantLicense(Context context, Item item,
String licenseText) throws SQLException, IOException, String licenseText) throws SQLException, IOException,
AuthorizeException AuthorizeException
{ {
// Put together text to store // Put together text to store
// String licenseText = "License granted by " + eperson.getFullName() // String licenseText = "License granted by " + eperson.getFullName()
// + " (" + eperson.getEmail() + ") on " // + " (" + eperson.getEmail() + ") on "
// + DCDate.getCurrent().toString() + " (GMT):\n\n" + license; // + DCDate.getCurrent().toString() + " (GMT):\n\n" + license;
// Store text as a bitstream // Store text as a bitstream
byte[] licenseBytes = licenseText.getBytes(); byte[] licenseBytes = licenseText.getBytes();
ByteArrayInputStream bais = new ByteArrayInputStream(licenseBytes); ByteArrayInputStream bais = new ByteArrayInputStream(licenseBytes);
Bitstream b = item.createSingleBitstream(bais, "LICENSE"); Bitstream b = item.createSingleBitstream(bais, "LICENSE");
// Now set the format and name of the bitstream // Now set the format and name of the bitstream
b.setName("license.txt"); b.setName("license.txt");
b.setSource("Written by org.dspace.content.LicenseUtils"); b.setSource("Written by org.dspace.content.LicenseUtils");
// Find the License format // Find the License format
BitstreamFormat bf = BitstreamFormat.findByShortDescription(context, BitstreamFormat bf = BitstreamFormat.findByShortDescription(context,
"License"); "License");
b.setFormat(bf); b.setFormat(bf);
b.update(); b.update();
} }
} }

View File

@@ -1,174 +1,174 @@
/** /**
* The contents of this file are subject to the license and copyright * The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source * detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at * tree and available online at
* *
* http://www.dspace.org/license/ * http://www.dspace.org/license/
*/ */
package org.dspace.content.crosswalk; package org.dspace.content.crosswalk;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.sql.SQLException; import java.sql.SQLException;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.content.DSpaceObject; import org.dspace.content.DSpaceObject;
import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeException;
import org.jdom.Element; import org.jdom.Element;
import org.jdom.Namespace; import org.jdom.Namespace;
/** /**
* Crosswalk descriptive metadata to and from DIM (DSpace Intermediate * Crosswalk descriptive metadata to and from DIM (DSpace Intermediate
* Metadata) format, strictly for the purpose of including a precise and * Metadata) format, strictly for the purpose of including a precise and
* complete record of the DMD in an AIP. Although the DIM format was never * complete record of the DMD in an AIP. Although the DIM format was never
* intended to be used outside of DSpace, it is admirably suited to * intended to be used outside of DSpace, it is admirably suited to
* describing the exact state of the descriptive MD stored in the RDBMS. * describing the exact state of the descriptive MD stored in the RDBMS.
* All crosswalks to standard formats such as MODS and even DC are necessarily * All crosswalks to standard formats such as MODS and even DC are necessarily
* "lossy" and inexact. Since the purpose of an AIP is to preserve and restore * "lossy" and inexact. Since the purpose of an AIP is to preserve and restore
* the state of an object exactly, DIM is the preferred format for * the state of an object exactly, DIM is the preferred format for
* recording its descriptive MD. * recording its descriptive MD.
* <p> * <p>
* In order to allow external applications to make sense of DSpace AIPs for * In order to allow external applications to make sense of DSpace AIPs for
* preservation purposes, we recommend adding a parallel descriptive * preservation purposes, we recommend adding a parallel descriptive
* metadata section in one of the preferred standard formats such as MODS * metadata section in one of the preferred standard formats such as MODS
* as well as the DIM. * as well as the DIM.
* *
* @author Larry Stone * @author Larry Stone
* @version $Revision: 1.2 $ * @version $Revision: 1.2 $
*/ */
public class AIPDIMCrosswalk public class AIPDIMCrosswalk
implements DisseminationCrosswalk, IngestionCrosswalk implements DisseminationCrosswalk, IngestionCrosswalk
{ {
/** /**
* Get XML namespaces of the elements this crosswalk may return. * Get XML namespaces of the elements this crosswalk may return.
* Returns the XML namespaces (as JDOM objects) of the root element. * Returns the XML namespaces (as JDOM objects) of the root element.
* *
* @return array of namespaces, which may be empty. * @return array of namespaces, which may be empty.
*/ */
public Namespace[] getNamespaces() public Namespace[] getNamespaces()
{ {
Namespace result[] = new Namespace[1]; Namespace result[] = new Namespace[1];
result[0] = XSLTCrosswalk.DIM_NS; result[0] = XSLTCrosswalk.DIM_NS;
return result; return result;
} }
/** /**
* Get the XML Schema location(s) of the target metadata format. * Get the XML Schema location(s) of the target metadata format.
* Returns the string value of the <code>xsi:schemaLocation</code> * Returns the string value of the <code>xsi:schemaLocation</code>
* attribute that should be applied to the generated XML. * attribute that should be applied to the generated XML.
* <p> * <p>
* It may return the empty string if no schema is known, but crosswalk * It may return the empty string if no schema is known, but crosswalk
* authors are strongly encouraged to implement this call so their output * authors are strongly encouraged to implement this call so their output
* XML can be validated correctly. * XML can be validated correctly.
* @return SchemaLocation string, including URI namespace, followed by * @return SchemaLocation string, including URI namespace, followed by
* whitespace and URI of XML schema document, or empty string if unknown. * whitespace and URI of XML schema document, or empty string if unknown.
*/ */
public String getSchemaLocation() public String getSchemaLocation()
{ {
return ""; return "";
} }
/** /**
* Predicate: Can this disseminator crosswalk the given object. * Predicate: Can this disseminator crosswalk the given object.
* Needed by OAI-PMH server implementation. * Needed by OAI-PMH server implementation.
* *
* @param dso dspace object, e.g. an <code>Item</code>. * @param dso dspace object, e.g. an <code>Item</code>.
* @return true when disseminator is capable of producing metadata. * @return true when disseminator is capable of producing metadata.
*/ */
public boolean canDisseminate(DSpaceObject dso) public boolean canDisseminate(DSpaceObject dso)
{ {
return true; return true;
} }
/** /**
* Predicate: Does this disseminator prefer to return a list of Elements, * Predicate: Does this disseminator prefer to return a list of Elements,
* rather than a single root Element? * rather than a single root Element?
* <p> * <p>
* Some metadata formats have an XML schema without a root element, * Some metadata formats have an XML schema without a root element,
* for example, the Dublin Core and Qualified Dublin Core formats. * for example, the Dublin Core and Qualified Dublin Core formats.
* This would be <code>true</code> for a crosswalk into QDC, since * This would be <code>true</code> for a crosswalk into QDC, since
* it would "prefer" to return a list, since any root element it has * it would "prefer" to return a list, since any root element it has
* to produce would have to be part of a nonstandard schema. In * to produce would have to be part of a nonstandard schema. In
* most cases your implementation will want to return * most cases your implementation will want to return
* <code>false</code> * <code>false</code>
* *
* @return true when disseminator prefers you call disseminateList(). * @return true when disseminator prefers you call disseminateList().
*/ */
public boolean preferList() public boolean preferList()
{ {
return false; return false;
} }
/** /**
* Execute crosswalk, returning List of XML elements. * Execute crosswalk, returning List of XML elements.
* Returns a <code>List</code> of JDOM <code>Element</code> objects representing * Returns a <code>List</code> of JDOM <code>Element</code> objects representing
* the XML produced by the crosswalk. This is typically called when * the XML produced by the crosswalk. This is typically called when
* a list of fields is desired, e.g. for embedding in a METS document * a list of fields is desired, e.g. for embedding in a METS document
* <code>xmlData</code> field. * <code>xmlData</code> field.
* <p> * <p>
* When there are no results, an * When there are no results, an
* empty list is returned, but never <code>null</code>. * empty list is returned, but never <code>null</code>.
* *
* @param dso the DSpace Object whose metadata to export. * @param dso the DSpace Object whose metadata to export.
* @return results of crosswalk as list of XML elements. * @return results of crosswalk as list of XML elements.
* *
* @throws CrosswalkInternalException (<code>CrosswalkException</code>) failure of the crosswalk itself. * @throws CrosswalkInternalException (<code>CrosswalkException</code>) failure of the crosswalk itself.
* @throws CrosswalkObjectNotSupported (<code>CrosswalkException</code>) Cannot crosswalk this kind of DSpace object. * @throws CrosswalkObjectNotSupported (<code>CrosswalkException</code>) Cannot crosswalk this kind of DSpace object.
* @throws IOException I/O failure in services this calls * @throws IOException I/O failure in services this calls
* @throws SQLException Database failure in services this calls * @throws SQLException Database failure in services this calls
* @throws AuthorizeException current user not authorized for this operation. * @throws AuthorizeException current user not authorized for this operation.
*/ */
public List<Element> disseminateList(DSpaceObject dso) public List<Element> disseminateList(DSpaceObject dso)
throws CrosswalkException, IOException, SQLException, throws CrosswalkException, IOException, SQLException,
AuthorizeException AuthorizeException
{ {
Element dim = disseminateElement(dso); Element dim = disseminateElement(dso);
return dim.getChildren(); return dim.getChildren();
} }
/** /**
* Execute crosswalk, returning one XML root element as * Execute crosswalk, returning one XML root element as
* a JDOM <code>Element</code> object. * a JDOM <code>Element</code> object.
* This is typically the root element of a document. * This is typically the root element of a document.
* <p> * <p>
* *
* @param dso the DSpace Object whose metadata to export. * @param dso the DSpace Object whose metadata to export.
* @return root Element of the target metadata, never <code>null</code> * @return root Element of the target metadata, never <code>null</code>
* *
* @throws CrosswalkInternalException (<code>CrosswalkException</code>) failure of the crosswalk itself. * @throws CrosswalkInternalException (<code>CrosswalkException</code>) failure of the crosswalk itself.
* @throws CrosswalkObjectNotSupported (<code>CrosswalkException</code>) Cannot crosswalk this kind of DSpace object. * @throws CrosswalkObjectNotSupported (<code>CrosswalkException</code>) Cannot crosswalk this kind of DSpace object.
* @throws IOException I/O failure in services this calls * @throws IOException I/O failure in services this calls
* @throws SQLException Database failure in services this calls * @throws SQLException Database failure in services this calls
* @throws AuthorizeException current user not authorized for this operation. * @throws AuthorizeException current user not authorized for this operation.
*/ */
public Element disseminateElement(DSpaceObject dso) public Element disseminateElement(DSpaceObject dso)
throws CrosswalkException, IOException, SQLException, throws CrosswalkException, IOException, SQLException,
AuthorizeException AuthorizeException
{ {
return XSLTDisseminationCrosswalk.createDIM(dso); return XSLTDisseminationCrosswalk.createDIM(dso);
} }
/** /**
* Ingest a whole document. Build Document object around root element, * Ingest a whole document. Build Document object around root element,
* and feed that to the transformation, since it may get handled * and feed that to the transformation, since it may get handled
* differently than a List of metadata elements. * differently than a List of metadata elements.
*/ */
public void ingest(Context context, DSpaceObject dso, Element root) public void ingest(Context context, DSpaceObject dso, Element root)
throws CrosswalkException, IOException, SQLException, AuthorizeException throws CrosswalkException, IOException, SQLException, AuthorizeException
{ {
ingest(context, dso, root.getChildren()); ingest(context, dso, root.getChildren());
} }
/** /**
* Fields correspond directly to Item.addMetadata() calls so * Fields correspond directly to Item.addMetadata() calls so
* they are simply executed. * they are simply executed.
*/ */
public void ingest(Context context, DSpaceObject dso, List<Element> dimList) public void ingest(Context context, DSpaceObject dso, List<Element> dimList)
throws CrosswalkException, throws CrosswalkException,
IOException, SQLException, AuthorizeException IOException, SQLException, AuthorizeException
{ {
XSLTIngestionCrosswalk.ingestDIM(context, dso, dimList); XSLTIngestionCrosswalk.ingestDIM(context, dso, dimList);
} }
} }

View File

@@ -1,69 +1,69 @@
/** /**
* The contents of this file are subject to the license and copyright * The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source * detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at * tree and available online at
* *
* http://www.dspace.org/license/ * http://www.dspace.org/license/
*/ */
package org.dspace.content.crosswalk; package org.dspace.content.crosswalk;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.IOException; import java.io.IOException;
import java.sql.SQLException; import java.sql.SQLException;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeException;
import org.dspace.content.DSpaceObject; import org.dspace.content.DSpaceObject;
import org.dspace.content.Bitstream; import org.dspace.content.Bitstream;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.core.Constants; import org.dspace.core.Constants;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.core.Utils; import org.dspace.core.Utils;
import org.dspace.license.CreativeCommons; import org.dspace.license.CreativeCommons;
/** /**
* Export the item's Creative Commons license, RDF form. * Export the item's Creative Commons license, RDF form.
* *
* @author Larry Stone * @author Larry Stone
* @version $Revision: 1.0 $ * @version $Revision: 1.0 $
*/ */
public class CreativeCommonsRDFStreamDisseminationCrosswalk public class CreativeCommonsRDFStreamDisseminationCrosswalk
implements StreamDisseminationCrosswalk implements StreamDisseminationCrosswalk
{ {
/** log4j logger */ /** log4j logger */
private static Logger log = Logger.getLogger(CreativeCommonsRDFStreamDisseminationCrosswalk.class); private static Logger log = Logger.getLogger(CreativeCommonsRDFStreamDisseminationCrosswalk.class);
public boolean canDisseminate(Context context, DSpaceObject dso) public boolean canDisseminate(Context context, DSpaceObject dso)
{ {
try try
{ {
return dso.getType() == Constants.ITEM && return dso.getType() == Constants.ITEM &&
CreativeCommons.getLicenseRdfBitstream((Item)dso) != null; CreativeCommons.getLicenseRdfBitstream((Item)dso) != null;
} }
catch (Exception e) catch (Exception e)
{ {
log.error("Failed getting CC license", e); log.error("Failed getting CC license", e);
return false; return false;
} }
} }
public void disseminate(Context context, DSpaceObject dso, OutputStream out) public void disseminate(Context context, DSpaceObject dso, OutputStream out)
throws CrosswalkException, IOException, SQLException, AuthorizeException throws CrosswalkException, IOException, SQLException, AuthorizeException
{ {
if (dso.getType() == Constants.ITEM) if (dso.getType() == Constants.ITEM)
{ {
Bitstream cc = CreativeCommons.getLicenseRdfBitstream((Item)dso); Bitstream cc = CreativeCommons.getLicenseRdfBitstream((Item)dso);
if (cc != null) if (cc != null)
{ {
Utils.copy(cc.retrieve(), out); Utils.copy(cc.retrieve(), out);
out.close(); out.close();
} }
} }
} }
public String getMIMEType() public String getMIMEType()
{ {
return "text/xml"; return "text/xml";
} }
} }

View File

@@ -1,62 +1,62 @@
/** /**
* The contents of this file are subject to the license and copyright * The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source * detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at * tree and available online at
* *
* http://www.dspace.org/license/ * http://www.dspace.org/license/
*/ */
package org.dspace.content.crosswalk; package org.dspace.content.crosswalk;
import java.io.InputStream; import java.io.InputStream;
import java.io.IOException; import java.io.IOException;
import java.sql.SQLException; import java.sql.SQLException;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeException;
import org.dspace.content.DSpaceObject; import org.dspace.content.DSpaceObject;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.core.Constants; import org.dspace.core.Constants;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.license.CreativeCommons; import org.dspace.license.CreativeCommons;
/** /**
* Ingest a Creative Commons license, RDF form. * Ingest a Creative Commons license, RDF form.
* <p> * <p>
* Note that this is NOT needed when ingesting a DSpace AIP, since the * Note that this is NOT needed when ingesting a DSpace AIP, since the
* CC license is stored as a Bitstream (or two) in a dedicated Bundle; * CC license is stored as a Bitstream (or two) in a dedicated Bundle;
* the normal apparatus of ingestig the AIP will restore that Bitstream * the normal apparatus of ingestig the AIP will restore that Bitstream
* with its proper name and thus the presence of the CC license. * with its proper name and thus the presence of the CC license.
* <p> * <p>
* This crosswalk should only be used when ingesting other kinds of SIPs. * This crosswalk should only be used when ingesting other kinds of SIPs.
* *
* @author Larry Stone * @author Larry Stone
* @version $Revision: 1.0 $ * @version $Revision: 1.0 $
*/ */
public class CreativeCommonsRDFStreamIngestionCrosswalk public class CreativeCommonsRDFStreamIngestionCrosswalk
implements StreamIngestionCrosswalk implements StreamIngestionCrosswalk
{ {
/** log4j logger */ /** log4j logger */
private static Logger log = Logger.getLogger(CreativeCommonsRDFStreamIngestionCrosswalk.class); private static Logger log = Logger.getLogger(CreativeCommonsRDFStreamIngestionCrosswalk.class);
public void ingest(Context context, DSpaceObject dso, InputStream in, String MIMEType) public void ingest(Context context, DSpaceObject dso, InputStream in, String MIMEType)
throws CrosswalkException, IOException, SQLException, AuthorizeException throws CrosswalkException, IOException, SQLException, AuthorizeException
{ {
// If package includes a Creative Commons license, add that: // If package includes a Creative Commons license, add that:
if (dso.getType() == Constants.ITEM) if (dso.getType() == Constants.ITEM)
{ {
if (log.isDebugEnabled()) if (log.isDebugEnabled())
{ {
log.debug("Reading a Creative Commons license, MIMEtype=" + MIMEType); log.debug("Reading a Creative Commons license, MIMEtype=" + MIMEType);
} }
CreativeCommons.setLicense(context, (Item)dso, in, MIMEType); CreativeCommons.setLicense(context, (Item)dso, in, MIMEType);
} }
} }
public String getMIMEType() public String getMIMEType()
{ {
return "text/rdf"; return "text/rdf";
} }
} }

View File

@@ -1,69 +1,69 @@
/** /**
* The contents of this file are subject to the license and copyright * The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source * detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at * tree and available online at
* *
* http://www.dspace.org/license/ * http://www.dspace.org/license/
*/ */
package org.dspace.content.crosswalk; package org.dspace.content.crosswalk;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.IOException; import java.io.IOException;
import java.sql.SQLException; import java.sql.SQLException;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeException;
import org.dspace.content.DSpaceObject; import org.dspace.content.DSpaceObject;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.content.Bitstream; import org.dspace.content.Bitstream;
import org.dspace.core.Constants; import org.dspace.core.Constants;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.core.Utils; import org.dspace.core.Utils;
import org.dspace.license.CreativeCommons; import org.dspace.license.CreativeCommons;
/** /**
* Export the object's Creative Commons license, text form. * Export the object's Creative Commons license, text form.
* *
* @author Larry Stone * @author Larry Stone
* @version $Revision: 1.0 $ * @version $Revision: 1.0 $
*/ */
public class CreativeCommonsTextStreamDisseminationCrosswalk public class CreativeCommonsTextStreamDisseminationCrosswalk
implements StreamDisseminationCrosswalk implements StreamDisseminationCrosswalk
{ {
/** log4j logger */ /** log4j logger */
private static Logger log = Logger.getLogger(CreativeCommonsTextStreamDisseminationCrosswalk.class); private static Logger log = Logger.getLogger(CreativeCommonsTextStreamDisseminationCrosswalk.class);
public boolean canDisseminate(Context context, DSpaceObject dso) public boolean canDisseminate(Context context, DSpaceObject dso)
{ {
try try
{ {
return dso.getType() == Constants.ITEM && return dso.getType() == Constants.ITEM &&
CreativeCommons.getLicenseTextBitstream((Item)dso) != null; CreativeCommons.getLicenseTextBitstream((Item)dso) != null;
} }
catch (Exception e) catch (Exception e)
{ {
log.error("Failed getting CC license", e); log.error("Failed getting CC license", e);
return false; return false;
} }
} }
public void disseminate(Context context, DSpaceObject dso, OutputStream out) public void disseminate(Context context, DSpaceObject dso, OutputStream out)
throws CrosswalkException, IOException, SQLException, AuthorizeException throws CrosswalkException, IOException, SQLException, AuthorizeException
{ {
if (dso.getType() == Constants.ITEM) if (dso.getType() == Constants.ITEM)
{ {
Bitstream cc = CreativeCommons.getLicenseTextBitstream((Item)dso); Bitstream cc = CreativeCommons.getLicenseTextBitstream((Item)dso);
if (cc != null) if (cc != null)
{ {
Utils.copy(cc.retrieve(), out); Utils.copy(cc.retrieve(), out);
out.close(); out.close();
} }
} }
} }
public String getMIMEType() public String getMIMEType()
{ {
return "text/plain"; return "text/plain";
} }
} }

View File

@@ -1,21 +1,21 @@
/** /**
* The contents of this file are subject to the license and copyright * The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source * detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at * tree and available online at
* *
* http://www.dspace.org/license/ * http://www.dspace.org/license/
*/ */
package org.dspace.content.crosswalk; package org.dspace.content.crosswalk;
public interface IConverter public interface IConverter
{ {
/** /**
* Get an alternative format for the input string. Useful examples are * Get an alternative format for the input string. Useful examples are
* conversion from a metadata language value in ISO-639-3 to ISO-639-1, etc. * conversion from a metadata language value in ISO-639-3 to ISO-639-1, etc.
* *
* @param value * @param value
* the input string to convert * the input string to convert
* @return the converted string returned by the "conversion algorithm" * @return the converted string returned by the "conversion algorithm"
*/ */
public String makeConversion(String value); public String makeConversion(String value);
} }

View File

@@ -1,70 +1,70 @@
/** /**
* The contents of this file are subject to the license and copyright * The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source * detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at * tree and available online at
* *
* http://www.dspace.org/license/ * http://www.dspace.org/license/
*/ */
package org.dspace.content.crosswalk; package org.dspace.content.crosswalk;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.IOException; import java.io.IOException;
import java.sql.SQLException; import java.sql.SQLException;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeException;
import org.dspace.content.DSpaceObject; import org.dspace.content.DSpaceObject;
import org.dspace.content.Bitstream; import org.dspace.content.Bitstream;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.content.packager.PackageUtils; import org.dspace.content.packager.PackageUtils;
import org.dspace.core.Constants; import org.dspace.core.Constants;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.core.Utils; import org.dspace.core.Utils;
/** /**
* Export the object's DSpace deposit license. * Export the object's DSpace deposit license.
* *
* @author Larry Stone * @author Larry Stone
* @version $Revision: 1.0 $ * @version $Revision: 1.0 $
*/ */
public class LicenseStreamDisseminationCrosswalk public class LicenseStreamDisseminationCrosswalk
implements StreamDisseminationCrosswalk implements StreamDisseminationCrosswalk
{ {
/** log4j logger */ /** log4j logger */
private static Logger log = Logger.getLogger(LicenseStreamDisseminationCrosswalk.class); private static Logger log = Logger.getLogger(LicenseStreamDisseminationCrosswalk.class);
public boolean canDisseminate(Context context, DSpaceObject dso) public boolean canDisseminate(Context context, DSpaceObject dso)
{ {
try try
{ {
return dso.getType() == Constants.ITEM && return dso.getType() == Constants.ITEM &&
PackageUtils.findDepositLicense(context, (Item)dso) != null; PackageUtils.findDepositLicense(context, (Item)dso) != null;
} }
catch (Exception e) catch (Exception e)
{ {
log.error("Failed getting Deposit license", e); log.error("Failed getting Deposit license", e);
return false; return false;
} }
} }
public void disseminate(Context context, DSpaceObject dso, OutputStream out) public void disseminate(Context context, DSpaceObject dso, OutputStream out)
throws CrosswalkException, IOException, SQLException, AuthorizeException throws CrosswalkException, IOException, SQLException, AuthorizeException
{ {
if (dso.getType() == Constants.ITEM) if (dso.getType() == Constants.ITEM)
{ {
Bitstream licenseBs = PackageUtils.findDepositLicense(context, (Item)dso); Bitstream licenseBs = PackageUtils.findDepositLicense(context, (Item)dso);
if (licenseBs != null) if (licenseBs != null)
{ {
Utils.copy(licenseBs.retrieve(), out); Utils.copy(licenseBs.retrieve(), out);
out.close(); out.close();
} }
} }
} }
public String getMIMEType() public String getMIMEType()
{ {
return "text/plain"; return "text/plain";
} }
} }

View File

@@ -1,66 +1,66 @@
/** /**
* The contents of this file are subject to the license and copyright * The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source * detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at * tree and available online at
* *
* http://www.dspace.org/license/ * http://www.dspace.org/license/
*/ */
package org.dspace.content.crosswalk; package org.dspace.content.crosswalk;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.InputStream; import java.io.InputStream;
import java.io.IOException; import java.io.IOException;
import java.sql.SQLException; import java.sql.SQLException;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeException;
import org.dspace.content.DSpaceObject; import org.dspace.content.DSpaceObject;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.content.packager.PackageUtils; import org.dspace.content.packager.PackageUtils;
import org.dspace.core.Constants; import org.dspace.core.Constants;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.core.Utils; import org.dspace.core.Utils;
/** /**
* Accept a DSpace deposit license. * Accept a DSpace deposit license.
* <p> * <p>
* Note that this is NOT needed when ingesting a DSpace AIP, since the * Note that this is NOT needed when ingesting a DSpace AIP, since the
* deposit license is stored as a Bitstream (or two) in a dedicated Bundle; * deposit license is stored as a Bitstream (or two) in a dedicated Bundle;
* the normal apparatus of ingestig the AIP will restore that Bitstream * the normal apparatus of ingestig the AIP will restore that Bitstream
* with its proper name and thus the presence of the deposit license. * with its proper name and thus the presence of the deposit license.
* <p> * <p>
* This crosswalk should only be used when ingesting other kinds of SIPs. * This crosswalk should only be used when ingesting other kinds of SIPs.
* *
* @author Larry Stone * @author Larry Stone
* @version $Revision: 1.0 $ * @version $Revision: 1.0 $
*/ */
public class LicenseStreamIngestionCrosswalk public class LicenseStreamIngestionCrosswalk
implements StreamIngestionCrosswalk implements StreamIngestionCrosswalk
{ {
/** log4j logger */ /** log4j logger */
private static Logger log = Logger.getLogger(LicenseStreamIngestionCrosswalk.class); private static Logger log = Logger.getLogger(LicenseStreamIngestionCrosswalk.class);
public void ingest(Context context, DSpaceObject dso, InputStream in, String MIMEType) public void ingest(Context context, DSpaceObject dso, InputStream in, String MIMEType)
throws CrosswalkException, IOException, SQLException, AuthorizeException throws CrosswalkException, IOException, SQLException, AuthorizeException
{ {
// If package includes a Creative Commons license, add that: // If package includes a Creative Commons license, add that:
if (dso.getType() == Constants.ITEM) if (dso.getType() == Constants.ITEM)
{ {
if (log.isDebugEnabled()) if (log.isDebugEnabled())
{ {
log.debug("Reading a DSpace Deposit license, MIMEtype=" + MIMEType); log.debug("Reading a DSpace Deposit license, MIMEtype=" + MIMEType);
} }
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream();
Utils.copy(in, baos); Utils.copy(in, baos);
PackageUtils.addDepositLicense(context, baos.toString(), PackageUtils.addDepositLicense(context, baos.toString(),
(Item)dso, null); (Item)dso, null);
} }
} }
public String getMIMEType() public String getMIMEType()
{ {
return "text/plain"; return "text/plain";
} }
} }

View File

@@ -1,43 +1,43 @@
/** /**
* The contents of this file are subject to the license and copyright * The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source * detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at * tree and available online at
* *
* http://www.dspace.org/license/ * http://www.dspace.org/license/
*/ */
package org.dspace.content.crosswalk; package org.dspace.content.crosswalk;
import java.io.InputStream; import java.io.InputStream;
import java.io.IOException; import java.io.IOException;
import java.sql.SQLException; import java.sql.SQLException;
import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeException;
import org.dspace.content.DSpaceObject; import org.dspace.content.DSpaceObject;
import org.dspace.core.Context; import org.dspace.core.Context;
/** /**
* A crosswalk to ignore and dispose of the ingested material. * A crosswalk to ignore and dispose of the ingested material.
* <p> * <p>
* Specify this crosswalk in the mapping of e.g. METS metadata field * Specify this crosswalk in the mapping of e.g. METS metadata field
* types to crosswalks when you wish to ignore a redundant or unknown * types to crosswalks when you wish to ignore a redundant or unknown
* type of metadata. For example, when ingesting a DSpace AIP with an * type of metadata. For example, when ingesting a DSpace AIP with an
* AIP ingester, it is best to ignore the rightsMD fields since they * AIP ingester, it is best to ignore the rightsMD fields since they
* are already going to be ingested as member bitstreams anyway. * are already going to be ingested as member bitstreams anyway.
* *
* @author Larry Stone * @author Larry Stone
* @version $Revision: 1.0 $ * @version $Revision: 1.0 $
*/ */
public class NullStreamIngestionCrosswalk public class NullStreamIngestionCrosswalk
implements StreamIngestionCrosswalk implements StreamIngestionCrosswalk
{ {
public void ingest(Context context, DSpaceObject dso, InputStream in, String MIMEType) public void ingest(Context context, DSpaceObject dso, InputStream in, String MIMEType)
throws CrosswalkException, IOException, SQLException, AuthorizeException throws CrosswalkException, IOException, SQLException, AuthorizeException
{ {
in.close(); in.close();
} }
public String getMIMEType() public String getMIMEType()
{ {
return "text/plain"; return "text/plain";
} }
} }

View File

@@ -1,343 +1,343 @@
/** /**
* The contents of this file are subject to the license and copyright * The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source * detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at * tree and available online at
* *
* http://www.dspace.org/license/ * http://www.dspace.org/license/
*/ */
package org.dspace.content.crosswalk; package org.dspace.content.crosswalk;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.List; import java.util.List;
import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeException;
import org.dspace.content.DSpaceObject; import org.dspace.content.DSpaceObject;
import org.dspace.content.packager.PackageDisseminator; import org.dspace.content.packager.PackageDisseminator;
import org.dspace.content.packager.PackageException; import org.dspace.content.packager.PackageException;
import org.dspace.content.packager.PackageIngester; import org.dspace.content.packager.PackageIngester;
import org.dspace.content.packager.PackageParameters; import org.dspace.content.packager.PackageParameters;
import org.dspace.content.packager.RoleDisseminator; import org.dspace.content.packager.RoleDisseminator;
import org.dspace.core.ConfigurationManager; import org.dspace.core.ConfigurationManager;
import org.dspace.core.Constants; import org.dspace.core.Constants;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.core.PluginManager; import org.dspace.core.PluginManager;
import org.jdom.Document; import org.jdom.Document;
import org.jdom.Element; import org.jdom.Element;
import org.jdom.JDOMException; import org.jdom.JDOMException;
import org.jdom.Namespace; import org.jdom.Namespace;
import org.jdom.input.SAXBuilder; import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter; import org.jdom.output.XMLOutputter;
/** /**
* Role Crosswalk * Role Crosswalk
* <p> * <p>
* Translate between DSpace Group & EPeople definitions and a DSpace-specific * Translate between DSpace Group & EPeople definitions and a DSpace-specific
* XML export format (generated by the RoleDisseminator). This is primarily * XML export format (generated by the RoleDisseminator). This is primarily
* used for AIPs, but may be used by other Packagers as necessary. * used for AIPs, but may be used by other Packagers as necessary.
* <p> * <p>
* This crosswalk allows you to export DSpace Groups & EPeople to this XML * This crosswalk allows you to export DSpace Groups & EPeople to this XML
* structured format. It also allows you to import an XML file of this format * structured format. It also allows you to import an XML file of this format
* in order to restore DSpace Groups and EPeople defined within it. * in order to restore DSpace Groups and EPeople defined within it.
* <p> * <p>
* This is just wrappers; the real work is done in RoleDisseminator and * This is just wrappers; the real work is done in RoleDisseminator and
* RoleIngester. * RoleIngester.
* *
* @author mwood * @author mwood
* @author Tim Donohue * @author Tim Donohue
* @see org.dspace.content.packager.RoleDisseminator * @see org.dspace.content.packager.RoleDisseminator
* @see org.dspace.content.packager.RoleIngester * @see org.dspace.content.packager.RoleIngester
* @see AbstractPackagerWrappingCrosswalk * @see AbstractPackagerWrappingCrosswalk
* @see IngestionCrosswalk * @see IngestionCrosswalk
* @see DisseminationCrosswalk * @see DisseminationCrosswalk
*/ */
public class RoleCrosswalk public class RoleCrosswalk
extends AbstractPackagerWrappingCrosswalk extends AbstractPackagerWrappingCrosswalk
implements IngestionCrosswalk, DisseminationCrosswalk implements IngestionCrosswalk, DisseminationCrosswalk
{ {
// Plugin Name of DSPACE-ROLES packager to use for ingest/dissemination // Plugin Name of DSPACE-ROLES packager to use for ingest/dissemination
// (Whatever plugin is defined with this name in 'dspace.cfg' will be used by this Crosswalk) // (Whatever plugin is defined with this name in 'dspace.cfg' will be used by this Crosswalk)
private static final String ROLE_PACKAGER_PLUGIN = "DSPACE-ROLES"; private static final String ROLE_PACKAGER_PLUGIN = "DSPACE-ROLES";
// ---- Dissemination Methods ----------- // ---- Dissemination Methods -----------
/** /**
* Get XML namespaces of the elements this crosswalk may return. * Get XML namespaces of the elements this crosswalk may return.
* Returns the XML namespaces (as JDOM objects) of the root element. * Returns the XML namespaces (as JDOM objects) of the root element.
* *
* @return array of namespaces, which may be empty. * @return array of namespaces, which may be empty.
*/ */
@Override @Override
public Namespace[] getNamespaces() public Namespace[] getNamespaces()
{ {
Namespace result[] = new Namespace[1]; Namespace result[] = new Namespace[1];
result[0] = RoleDisseminator.DSROLES_NS; result[0] = RoleDisseminator.DSROLES_NS;
return result; return result;
} }
/** /**
* Get the XML Schema location(s) of the target metadata format. * Get the XML Schema location(s) of the target metadata format.
* Returns the string value of the <code>xsi:schemaLocation</code> * Returns the string value of the <code>xsi:schemaLocation</code>
* attribute that should be applied to the generated XML. * attribute that should be applied to the generated XML.
* <p> * <p>
* It may return the empty string if no schema is known, but crosswalk * It may return the empty string if no schema is known, but crosswalk
* authors are strongly encouraged to implement this call so their output * authors are strongly encouraged to implement this call so their output
* XML can be validated correctly. * XML can be validated correctly.
* @return SchemaLocation string, including URI namespace, followed by * @return SchemaLocation string, including URI namespace, followed by
* whitespace and URI of XML schema document, or empty string if unknown. * whitespace and URI of XML schema document, or empty string if unknown.
*/ */
@Override @Override
public String getSchemaLocation() public String getSchemaLocation()
{ {
return ""; return "";
} }
/** /**
* Predicate: Can this disseminator crosswalk the given object. * Predicate: Can this disseminator crosswalk the given object.
* *
* @param dso dspace object, e.g. an <code>Item</code>. * @param dso dspace object, e.g. an <code>Item</code>.
* @return true when disseminator is capable of producing metadata. * @return true when disseminator is capable of producing metadata.
*/ */
@Override @Override
public boolean canDisseminate(DSpaceObject dso) public boolean canDisseminate(DSpaceObject dso)
{ {
//We can only disseminate SITE, COMMUNITY or COLLECTION objects, //We can only disseminate SITE, COMMUNITY or COLLECTION objects,
//as Groups are only associated with those objects. //as Groups are only associated with those objects.
return (dso.getType() == Constants.SITE || return (dso.getType() == Constants.SITE ||
dso.getType() == Constants.COMMUNITY || dso.getType() == Constants.COMMUNITY ||
dso.getType() == Constants.COLLECTION); dso.getType() == Constants.COLLECTION);
} }
/** /**
* Predicate: Does this disseminator prefer to return a list of Elements, * Predicate: Does this disseminator prefer to return a list of Elements,
* rather than a single root Element? * rather than a single root Element?
* *
* @return true when disseminator prefers you call disseminateList(). * @return true when disseminator prefers you call disseminateList().
*/ */
@Override @Override
public boolean preferList() public boolean preferList()
{ {
//We prefer disseminators call 'disseminateElement()' instead of 'disseminateList()' //We prefer disseminators call 'disseminateElement()' instead of 'disseminateList()'
return false; return false;
} }
/** /**
* Execute crosswalk, returning List of XML elements. * Execute crosswalk, returning List of XML elements.
* Returns a <code>List</code> of JDOM <code>Element</code> objects representing * Returns a <code>List</code> of JDOM <code>Element</code> objects representing
* the XML produced by the crosswalk. This is typically called when * the XML produced by the crosswalk. This is typically called when
* a list of fields is desired, e.g. for embedding in a METS document * a list of fields is desired, e.g. for embedding in a METS document
* <code>xmlData</code> field. * <code>xmlData</code> field.
* <p> * <p>
* When there are no results, an * When there are no results, an
* empty list is returned, but never <code>null</code>. * empty list is returned, but never <code>null</code>.
* *
* @param dso the DSpace Object whose metadata to export. * @param dso the DSpace Object whose metadata to export.
* @return results of crosswalk as list of XML elements. * @return results of crosswalk as list of XML elements.
* *
* @throws CrosswalkInternalException (<code>CrosswalkException</code>) failure of the crosswalk itself. * @throws CrosswalkInternalException (<code>CrosswalkException</code>) failure of the crosswalk itself.
* @throws CrosswalkObjectNotSupported (<code>CrosswalkException</code>) Cannot crosswalk this kind of DSpace object. * @throws CrosswalkObjectNotSupported (<code>CrosswalkException</code>) Cannot crosswalk this kind of DSpace object.
* @throws IOException I/O failure in services this calls * @throws IOException I/O failure in services this calls
* @throws SQLException Database failure in services this calls * @throws SQLException Database failure in services this calls
* @throws AuthorizeException current user not authorized for this operation. * @throws AuthorizeException current user not authorized for this operation.
*/ */
@Override @Override
public List<Element> disseminateList(DSpaceObject dso) public List<Element> disseminateList(DSpaceObject dso)
throws CrosswalkException, IOException, SQLException, throws CrosswalkException, IOException, SQLException,
AuthorizeException AuthorizeException
{ {
Element dim = disseminateElement(dso); Element dim = disseminateElement(dso);
return dim.getChildren(); return dim.getChildren();
} }
/** /**
* Execute crosswalk, returning one XML root element as * Execute crosswalk, returning one XML root element as
* a JDOM <code>Element</code> object. * a JDOM <code>Element</code> object.
* This is typically the root element of a document. * This is typically the root element of a document.
* <p> * <p>
* *
* @param dso the DSpace Object whose metadata to export. * @param dso the DSpace Object whose metadata to export.
* @return root Element of the target metadata, never <code>null</code> * @return root Element of the target metadata, never <code>null</code>
* *
* @throws CrosswalkInternalException (<code>CrosswalkException</code>) failure of the crosswalk itself. * @throws CrosswalkInternalException (<code>CrosswalkException</code>) failure of the crosswalk itself.
* @throws CrosswalkObjectNotSupported (<code>CrosswalkException</code>) Cannot crosswalk this kind of DSpace object. * @throws CrosswalkObjectNotSupported (<code>CrosswalkException</code>) Cannot crosswalk this kind of DSpace object.
* @throws IOException I/O failure in services this calls * @throws IOException I/O failure in services this calls
* @throws SQLException Database failure in services this calls * @throws SQLException Database failure in services this calls
* @throws AuthorizeException current user not authorized for this operation. * @throws AuthorizeException current user not authorized for this operation.
*/ */
@Override @Override
public Element disseminateElement(DSpaceObject dso) public Element disseminateElement(DSpaceObject dso)
throws CrosswalkException, IOException, SQLException, throws CrosswalkException, IOException, SQLException,
AuthorizeException AuthorizeException
{ {
try try
{ {
PackageDisseminator dip = (PackageDisseminator) PackageDisseminator dip = (PackageDisseminator)
PluginManager.getNamedPlugin(PackageDisseminator.class, ROLE_PACKAGER_PLUGIN); PluginManager.getNamedPlugin(PackageDisseminator.class, ROLE_PACKAGER_PLUGIN);
if (dip == null) if (dip == null)
{ {
throw new CrosswalkInternalException("Cannot find a PackageDisseminator plugin named " + ROLE_PACKAGER_PLUGIN); throw new CrosswalkInternalException("Cannot find a PackageDisseminator plugin named " + ROLE_PACKAGER_PLUGIN);
} }
// Create a temporary file to disseminate into // Create a temporary file to disseminate into
String tempDirectory = ConfigurationManager.getProperty("upload.temp.dir"); String tempDirectory = ConfigurationManager.getProperty("upload.temp.dir");
File tempFile = File.createTempFile("RoleCrosswalkDisseminate" + dso.hashCode(), null, new File(tempDirectory)); File tempFile = File.createTempFile("RoleCrosswalkDisseminate" + dso.hashCode(), null, new File(tempDirectory));
tempFile.deleteOnExit(); tempFile.deleteOnExit();
// Initialize our packaging parameters // Initialize our packaging parameters
PackageParameters pparams; PackageParameters pparams;
if(this.getPackagingParameters()!=null) if(this.getPackagingParameters()!=null)
{ {
pparams = this.getPackagingParameters(); pparams = this.getPackagingParameters();
} }
else else
{ {
pparams = new PackageParameters(); pparams = new PackageParameters();
} }
//actually disseminate to our temp file. //actually disseminate to our temp file.
Context context = new Context(); Context context = new Context();
dip.disseminate(context, dso, pparams, tempFile); dip.disseminate(context, dso, pparams, tempFile);
context.complete(); context.complete();
// if we ended up with a Zero-length output file, // if we ended up with a Zero-length output file,
// this means dissemination was successful but had no results // this means dissemination was successful but had no results
if(tempFile.exists() && tempFile.length()==0) if(tempFile.exists() && tempFile.length()==0)
{ {
return null; return null;
} }
try try
{ {
//Try to parse our XML results (which were disseminated by the Packager) //Try to parse our XML results (which were disseminated by the Packager)
SAXBuilder builder = new SAXBuilder(); SAXBuilder builder = new SAXBuilder();
Document xmlDocument = builder.build(tempFile); Document xmlDocument = builder.build(tempFile);
//If XML parsed successfully, return root element of doc //If XML parsed successfully, return root element of doc
if(xmlDocument!=null && xmlDocument.hasRootElement()) if(xmlDocument!=null && xmlDocument.hasRootElement())
{ {
return xmlDocument.getRootElement(); return xmlDocument.getRootElement();
} }
else else
{ {
return null; return null;
} }
} }
catch (JDOMException je) catch (JDOMException je)
{ {
throw new MetadataValidationException("Error parsing Roles XML (see wrapped error message for more details) ",je); throw new MetadataValidationException("Error parsing Roles XML (see wrapped error message for more details) ",je);
} }
} }
catch (PackageException pe) catch (PackageException pe)
{ {
throw new CrosswalkInternalException("Failed to export Roles via packager (see wrapped error message for more details) ",pe); throw new CrosswalkInternalException("Failed to export Roles via packager (see wrapped error message for more details) ",pe);
} }
} }
// ---- Ingestion Methods ----------- // ---- Ingestion Methods -----------
/** /**
* Ingest a List of XML elements * Ingest a List of XML elements
* *
* @param context * @param context
* @param dso * @param dso
* @param metadata * @param metadata
* @throws CrosswalkException * @throws CrosswalkException
* @throws IOException * @throws IOException
* @throws SQLException * @throws SQLException
* @throws AuthorizeException * @throws AuthorizeException
*/ */
@Override @Override
public void ingest(Context context, DSpaceObject dso, List<Element> metadata) public void ingest(Context context, DSpaceObject dso, List<Element> metadata)
throws CrosswalkException, IOException, SQLException, AuthorizeException throws CrosswalkException, IOException, SQLException, AuthorizeException
{ {
if(!metadata.isEmpty()) if(!metadata.isEmpty())
{ {
ingest(context, dso, ((Element) metadata.get(0)).getParentElement()); ingest(context, dso, ((Element) metadata.get(0)).getParentElement());
} }
} }
/** /**
* Ingest a whole XML document, starting at specified root. * Ingest a whole XML document, starting at specified root.
* <P> * <P>
* This essentially just wraps a call to the configured Role PackageIngester. * This essentially just wraps a call to the configured Role PackageIngester.
* *
* @param context * @param context
* @param dso * @param dso
* @param root * @param root
* @throws CrosswalkException * @throws CrosswalkException
* @throws IOException * @throws IOException
* @throws SQLException * @throws SQLException
* @throws AuthorizeException * @throws AuthorizeException
*/ */
@Override @Override
public void ingest(Context context, DSpaceObject dso, Element root) public void ingest(Context context, DSpaceObject dso, Element root)
throws CrosswalkException, IOException, SQLException, AuthorizeException throws CrosswalkException, IOException, SQLException, AuthorizeException
{ {
if (dso.getType() != Constants.SITE && if (dso.getType() != Constants.SITE &&
dso.getType() != Constants.COMMUNITY && dso.getType() != Constants.COMMUNITY &&
dso.getType() != Constants.COLLECTION) dso.getType() != Constants.COLLECTION)
{ {
throw new CrosswalkObjectNotSupported("Role crosswalk only valid for Site, Community or Collection"); throw new CrosswalkObjectNotSupported("Role crosswalk only valid for Site, Community or Collection");
} }
//locate our "DSPACE-ROLES" PackageIngester plugin //locate our "DSPACE-ROLES" PackageIngester plugin
PackageIngester sip = (PackageIngester) PackageIngester sip = (PackageIngester)
PluginManager.getNamedPlugin(PackageIngester.class, ROLE_PACKAGER_PLUGIN); PluginManager.getNamedPlugin(PackageIngester.class, ROLE_PACKAGER_PLUGIN);
if (sip == null) if (sip == null)
{ {
throw new CrosswalkInternalException("Cannot find a PackageIngester plugin named " + ROLE_PACKAGER_PLUGIN); throw new CrosswalkInternalException("Cannot find a PackageIngester plugin named " + ROLE_PACKAGER_PLUGIN);
} }
// Initialize our packaging parameters // Initialize our packaging parameters
PackageParameters pparams; PackageParameters pparams;
if(this.getPackagingParameters()!=null) if(this.getPackagingParameters()!=null)
{ {
pparams = this.getPackagingParameters(); pparams = this.getPackagingParameters();
} }
else else
{ {
pparams = new PackageParameters(); pparams = new PackageParameters();
} }
// Initialize our license info // Initialize our license info
String license = null; String license = null;
if(this.getIngestionLicense()!=null) if(this.getIngestionLicense()!=null)
{ {
license = this.getIngestionLicense(); license = this.getIngestionLicense();
} }
// Create a temporary file to ingest from // Create a temporary file to ingest from
String tempDirectory = ConfigurationManager.getProperty("upload.temp.dir"); String tempDirectory = ConfigurationManager.getProperty("upload.temp.dir");
File tempFile = File.createTempFile("RoleCrosswalkIngest" + dso.hashCode(), null, new File(tempDirectory)); File tempFile = File.createTempFile("RoleCrosswalkIngest" + dso.hashCode(), null, new File(tempDirectory));
tempFile.deleteOnExit(); tempFile.deleteOnExit();
FileOutputStream fileOutStream = null; FileOutputStream fileOutStream = null;
try try
{ {
fileOutStream = new FileOutputStream(tempFile); fileOutStream = new FileOutputStream(tempFile);
XMLOutputter writer = new XMLOutputter(); XMLOutputter writer = new XMLOutputter();
writer.output(root, fileOutStream); writer.output(root, fileOutStream);
} }
finally finally
{ {
if (fileOutStream != null) if (fileOutStream != null)
{ {
fileOutStream.close(); fileOutStream.close();
} }
} }
//Actually call the ingester //Actually call the ingester
try try
{ {
sip.ingest(context, dso, tempFile, pparams, license); sip.ingest(context, dso, tempFile, pparams, license);
} }
catch (PackageException e) catch (PackageException e)
{ {
throw new CrosswalkInternalException(e); throw new CrosswalkInternalException(e);
} }
} }
} }

View File

@@ -1,51 +1,51 @@
/** /**
* The contents of this file are subject to the license and copyright * The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source * detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at * tree and available online at
* *
* http://www.dspace.org/license/ * http://www.dspace.org/license/
*/ */
package org.dspace.content.license; package org.dspace.content.license;
import java.util.Formattable; import java.util.Formattable;
import java.util.Formatter; import java.util.Formatter;
import org.dspace.core.PluginManager; import org.dspace.core.PluginManager;
/** /**
* Wrapper class to make formattable any argument used in the license template. * Wrapper class to make formattable any argument used in the license template.
* The formatter behavior is delegated to a specific class on "type" basis * The formatter behavior is delegated to a specific class on "type" basis
* using the PluginManager * using the PluginManager
* *
* @see Formattable * @see Formattable
* @see LicenseArgumentFormatter * @see LicenseArgumentFormatter
* @author bollini * @author bollini
* *
*/ */
public class FormattableArgument implements Formattable public class FormattableArgument implements Formattable
{ {
private String type; private String type;
private Object object; private Object object;
public FormattableArgument(String type, Object object) public FormattableArgument(String type, Object object)
{ {
this.type = type; this.type = type;
this.object = object; this.object = object;
} }
public void formatTo(Formatter formatter, int flags, int width, public void formatTo(Formatter formatter, int flags, int width,
int precision) int precision)
{ {
LicenseArgumentFormatter laf = (LicenseArgumentFormatter) PluginManager LicenseArgumentFormatter laf = (LicenseArgumentFormatter) PluginManager
.getNamedPlugin(LicenseArgumentFormatter.class, type); .getNamedPlugin(LicenseArgumentFormatter.class, type);
if (laf != null) if (laf != null)
{ {
laf.formatTo(formatter, flags, width, object, type); laf.formatTo(formatter, flags, width, object, type);
} }
else else
{ {
formatter.format(object.toString()); formatter.format(object.toString());
} }
} }
} }

View File

@@ -1,37 +1,37 @@
/** /**
* The contents of this file are subject to the license and copyright * The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source * detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at * tree and available online at
* *
* http://www.dspace.org/license/ * http://www.dspace.org/license/
*/ */
package org.dspace.content.license; package org.dspace.content.license;
import java.util.Formatter; import java.util.Formatter;
public interface LicenseArgumentFormatter public interface LicenseArgumentFormatter
{ {
/** /**
* Format the object following the <code>java.util.Formatter</code> rules. * Format the object following the <code>java.util.Formatter</code> rules.
* The object type is expected to be know to the implementer can is free to * The object type is expected to be know to the implementer can is free to
* assume safe to cast as appropriate. If a <code>null</code> object is * assume safe to cast as appropriate. If a <code>null</code> object is
* supplied is expected that the implementer will work as if a "sample data" * supplied is expected that the implementer will work as if a "sample data"
* was requested. * was requested.
* *
* @see Formatter * @see Formatter
* @param formatter * @param formatter
* the current formatter that need to process the object * the current formatter that need to process the object
* @param flags * @param flags
* the flags option for the formatter * the flags option for the formatter
* @param width * @param width
* the width option for the formatter * the width option for the formatter
* @param object * @param object
* the object to be formatted * the object to be formatted
* @param type * @param type
* the type of the object (this is an alias not the class name! - * the type of the object (this is an alias not the class name! -
* i.e. item, collection, eperson, etc.) * i.e. item, collection, eperson, etc.)
*/ */
void formatTo(Formatter formatter, int flags, int width, Object object, void formatTo(Formatter formatter, int flags, int width, Object object,
String type); String type);
} }

View File

@@ -1,45 +1,45 @@
/** /**
* The contents of this file are subject to the license and copyright * The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source * detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at * tree and available online at
* *
* http://www.dspace.org/license/ * http://www.dspace.org/license/
*/ */
package org.dspace.content.license; package org.dspace.content.license;
import java.util.Formatter; import java.util.Formatter;
import org.dspace.content.DSpaceObject; import org.dspace.content.DSpaceObject;
/** /**
* This is a simple implementation of the LicenseArgumentFormatter for a * This is a simple implementation of the LicenseArgumentFormatter for a
* DSpaceObject. The formatter options width/precision are not take in care. * DSpaceObject. The formatter options width/precision are not take in care.
* *
* @author bollini * @author bollini
* *
*/ */
public class SimpleDSpaceObjectLicenseFormatter implements public class SimpleDSpaceObjectLicenseFormatter implements
LicenseArgumentFormatter LicenseArgumentFormatter
{ {
public void formatTo(Formatter formatter, int flags, int width, public void formatTo(Formatter formatter, int flags, int width,
Object object, String type) Object object, String type)
{ {
if (object == null) if (object == null)
{ {
formatter.format("sample "+type); formatter.format("sample "+type);
} }
else else
{ {
DSpaceObject dso = (DSpaceObject) object; DSpaceObject dso = (DSpaceObject) object;
String name = dso.getName(); String name = dso.getName();
if (name != null) if (name != null)
{ {
formatter.format(name); formatter.format(name);
} }
else else
{ {
formatter.format(""); formatter.format("");
} }
} }
} }
} }

View File

@@ -792,6 +792,11 @@ public abstract class AbstractMETSIngester extends AbstractPackageIngester
Bitstream bitstream = bundle.createBitstream(fileStream); Bitstream bitstream = bundle.createBitstream(fileStream);
bitstream.setName(path); bitstream.setName(path);
// Set bitstream sequence id, if known
String seqID = mfile.getAttributeValue("SEQ");
if(seqID!=null && !seqID.isEmpty())
bitstream.setSequenceID(Integer.parseInt(seqID));
// crosswalk this bitstream's administrative metadata located in // crosswalk this bitstream's administrative metadata located in
// METS manifest (or referenced externally) // METS manifest (or referenced externally)
manifest.crosswalkBitstream(context, params, bitstream, mfileID, manifest.crosswalkBitstream(context, params, bitstream, mfileID,

View File

@@ -1,191 +1,191 @@
/** /**
* The contents of this file are subject to the license and copyright * The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source * detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at * tree and available online at
* *
* http://www.dspace.org/license/ * http://www.dspace.org/license/
*/ */
package org.dspace.content.packager; package org.dspace.content.packager;
import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Collection; import org.dspace.content.Collection;
import org.dspace.content.Community; import org.dspace.content.Community;
import org.dspace.content.DSpaceObject; import org.dspace.content.DSpaceObject;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.content.ItemIterator; import org.dspace.content.ItemIterator;
import org.dspace.content.crosswalk.CrosswalkException; import org.dspace.content.crosswalk.CrosswalkException;
import org.dspace.core.Constants; import org.dspace.core.Constants;
import org.dspace.core.Context; import org.dspace.core.Context;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
* An abstract implementation of a DSpace Package Disseminator, which * An abstract implementation of a DSpace Package Disseminator, which
* implements a few helper/utility methods that most (all?) PackageDisseminators * implements a few helper/utility methods that most (all?) PackageDisseminators
* may find useful. * may find useful.
* <P> * <P>
* First, implements recursive functionality in the disseminateAll() * First, implements recursive functionality in the disseminateAll()
* method of the PackageIngester interface. This method is setup to * method of the PackageIngester interface. This method is setup to
* recursively call disseminate() method. * recursively call disseminate() method.
* <P> * <P>
* All Package disseminators should either extend this abstract class * All Package disseminators should either extend this abstract class
* or implement <code>PackageDisseminator</code> to better suit their needs. * or implement <code>PackageDisseminator</code> to better suit their needs.
* *
* @author Tim Donohue * @author Tim Donohue
* @see PackageDisseminator * @see PackageDisseminator
*/ */
public abstract class AbstractPackageDisseminator public abstract class AbstractPackageDisseminator
implements PackageDisseminator implements PackageDisseminator
{ {
/** List of all successfully disseminated package files */ /** List of all successfully disseminated package files */
private List<File> packageFileList = new ArrayList<File>(); private List<File> packageFileList = new ArrayList<File>();
/** /**
* Recursively export one or more DSpace Objects as a series of packages. * Recursively export one or more DSpace Objects as a series of packages.
* This method will export the given DSpace Object as well as all referenced * This method will export the given DSpace Object as well as all referenced
* DSpaceObjects (e.g. child objects) into a series of packages. The * DSpaceObjects (e.g. child objects) into a series of packages. The
* initial object is exported to the location specified by the OutputStream. * initial object is exported to the location specified by the OutputStream.
* All other packages are exported to the same directory location. * All other packages are exported to the same directory location.
* <p> * <p>
* Package is any serialized representation of the item, at the discretion * Package is any serialized representation of the item, at the discretion
* of the implementing class. It does not have to include content bitstreams. * of the implementing class. It does not have to include content bitstreams.
* <br> * <br>
* Use the <code>params</code> parameter list to adjust the way the * Use the <code>params</code> parameter list to adjust the way the
* package is made, e.g. including a "<code>metadataOnly</code>" * package is made, e.g. including a "<code>metadataOnly</code>"
* parameter might make the package a bare manifest in XML * parameter might make the package a bare manifest in XML
* instead of a Zip file including manifest and contents. * instead of a Zip file including manifest and contents.
* <br> * <br>
* Throws an exception of the initial object is not acceptable or there is * Throws an exception of the initial object is not acceptable or there is
* a failure creating the package. * a failure creating the package.
* *
* @param context DSpace context. * @param context DSpace context.
* @param dso initial DSpace object * @param dso initial DSpace object
* @param params Properties-style list of options specific to this packager * @param params Properties-style list of options specific to this packager
* @param pkgFile File where initial package should be written. All other * @param pkgFile File where initial package should be written. All other
* packages will be written to the same directory as this File. * packages will be written to the same directory as this File.
* @throws PackageValidationException if package cannot be created or there is * @throws PackageValidationException if package cannot be created or there is
* a fatal error in creating it. * a fatal error in creating it.
*/ */
@Override @Override
public List<File> disseminateAll(Context context, DSpaceObject dso, public List<File> disseminateAll(Context context, DSpaceObject dso,
PackageParameters params, File pkgFile) PackageParameters params, File pkgFile)
throws PackageException, CrosswalkException, throws PackageException, CrosswalkException,
AuthorizeException, SQLException, IOException AuthorizeException, SQLException, IOException
{ {
//If unset, make sure the Parameters specifies this is a recursive dissemination //If unset, make sure the Parameters specifies this is a recursive dissemination
if(!params.recursiveModeEnabled()) if(!params.recursiveModeEnabled())
{ {
params.setRecursiveModeEnabled(true); params.setRecursiveModeEnabled(true);
} }
//try to disseminate the first object using provided PackageDisseminator //try to disseminate the first object using provided PackageDisseminator
disseminate(context, dso, params, pkgFile); disseminate(context, dso, params, pkgFile);
//check if package was disseminated //check if package was disseminated
if(pkgFile.exists()) if(pkgFile.exists())
{ {
//add to list of successfully disseminated packages //add to list of successfully disseminated packages
addToPackageList(pkgFile); addToPackageList(pkgFile);
//We can only recursively disseminate non-Items //We can only recursively disseminate non-Items
//(NOTE: Items have no children, as Bitstreams/Bundles are created from Item packages) //(NOTE: Items have no children, as Bitstreams/Bundles are created from Item packages)
if(dso.getType()!=Constants.ITEM) if(dso.getType()!=Constants.ITEM)
{ {
//Determine where first file package was disseminated to, as all //Determine where first file package was disseminated to, as all
//others will be written to same directory //others will be written to same directory
String pkgDirectory = pkgFile.getCanonicalFile().getParent(); String pkgDirectory = pkgFile.getCanonicalFile().getParent();
if(!pkgDirectory.endsWith(File.separator)) if(!pkgDirectory.endsWith(File.separator))
{ {
pkgDirectory += File.separator; pkgDirectory += File.separator;
} }
String fileExtension = PackageUtils.getFileExtension(pkgFile.getName()); String fileExtension = PackageUtils.getFileExtension(pkgFile.getName());
//recursively disseminate content, based on object type //recursively disseminate content, based on object type
switch (dso.getType()) switch (dso.getType())
{ {
case Constants.COLLECTION : case Constants.COLLECTION :
//Also find all Items in this Collection and disseminate //Also find all Items in this Collection and disseminate
Collection collection = (Collection) dso; Collection collection = (Collection) dso;
ItemIterator iterator = collection.getItems(); ItemIterator iterator = collection.getItems();
while(iterator.hasNext()) while(iterator.hasNext())
{ {
Item item = iterator.next(); Item item = iterator.next();
//disseminate all items (recursively!) //disseminate all items (recursively!)
String childFileName = pkgDirectory + PackageUtils.getPackageName(item, fileExtension); String childFileName = pkgDirectory + PackageUtils.getPackageName(item, fileExtension);
disseminateAll(context, item, params, new File(childFileName)); disseminateAll(context, item, params, new File(childFileName));
} }
break; break;
case Constants.COMMUNITY : case Constants.COMMUNITY :
//Also find all SubCommunities in this Community and disseminate //Also find all SubCommunities in this Community and disseminate
Community community = (Community) dso; Community community = (Community) dso;
Community[] subcommunities = community.getSubcommunities(); Community[] subcommunities = community.getSubcommunities();
for(int i=0; i<subcommunities.length; i++) for(int i=0; i<subcommunities.length; i++)
{ {
//disseminate all sub-communities (recursively!) //disseminate all sub-communities (recursively!)
String childFileName = pkgDirectory + PackageUtils.getPackageName(subcommunities[i], fileExtension); String childFileName = pkgDirectory + PackageUtils.getPackageName(subcommunities[i], fileExtension);
disseminateAll(context, subcommunities[i], params, new File(childFileName)); disseminateAll(context, subcommunities[i], params, new File(childFileName));
} }
//Also find all Collections in this Community and disseminate //Also find all Collections in this Community and disseminate
Collection[] collections = community.getCollections(); Collection[] collections = community.getCollections();
for(int i=0; i<collections.length; i++) for(int i=0; i<collections.length; i++)
{ {
//disseminate all collections (recursively!) //disseminate all collections (recursively!)
String childFileName = pkgDirectory + PackageUtils.getPackageName(collections[i], fileExtension); String childFileName = pkgDirectory + PackageUtils.getPackageName(collections[i], fileExtension);
disseminateAll(context, collections[i], params, new File(childFileName)); disseminateAll(context, collections[i], params, new File(childFileName));
} }
break; break;
case Constants.SITE : case Constants.SITE :
//Also find all top-level Communities and disseminate //Also find all top-level Communities and disseminate
Community[] topCommunities = Community.findAllTop(context); Community[] topCommunities = Community.findAllTop(context);
for(int i=0; i<topCommunities.length; i++) for(int i=0; i<topCommunities.length; i++)
{ {
//disseminate all top-level communities (recursively!) //disseminate all top-level communities (recursively!)
String childFileName = pkgDirectory + PackageUtils.getPackageName(topCommunities[i], fileExtension); String childFileName = pkgDirectory + PackageUtils.getPackageName(topCommunities[i], fileExtension);
disseminateAll(context, topCommunities[i], params, new File(childFileName)); disseminateAll(context, topCommunities[i], params, new File(childFileName));
} }
break; break;
}//end switch }//end switch
}//end if not an Item }//end if not an Item
}//end if pkgFile exists }//end if pkgFile exists
//return list of all successfully disseminated packages //return list of all successfully disseminated packages
return getPackageList(); return getPackageList();
} }
/** /**
* Add File to list of successfully disseminated package files * Add File to list of successfully disseminated package files
* @param file File * @param file File
*/ */
protected void addToPackageList(File f) protected void addToPackageList(File f)
{ {
//add to list of successfully disseminated packages //add to list of successfully disseminated packages
if(!packageFileList.contains(f)) if(!packageFileList.contains(f))
{ {
packageFileList.add(f); packageFileList.add(f);
} }
} }
/** /**
* Return List of all package Files which have been disseminated * Return List of all package Files which have been disseminated
* this instance of the Disseminator. * this instance of the Disseminator.
* <P> * <P>
* This list can be useful in reporting back to the user what content has * This list can be useful in reporting back to the user what content has
* been disseminated as packages. It's used by disseminateAll() to report * been disseminated as packages. It's used by disseminateAll() to report
* what packages were created. * what packages were created.
* *
* @return List of Files which correspond to the disseminated packages * @return List of Files which correspond to the disseminated packages
*/ */
protected List<File> getPackageList() protected List<File> getPackageList()
{ {
return packageFileList; return packageFileList;
} }
} }

View File

@@ -1,380 +1,380 @@
/** /**
* The contents of this file are subject to the license and copyright * The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source * detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at * tree and available online at
* *
* http://www.dspace.org/license/ * http://www.dspace.org/license/
*/ */
package org.dspace.content.packager; package org.dspace.content.packager;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Collection; import org.dspace.content.Collection;
import org.dspace.content.DSpaceObject; import org.dspace.content.DSpaceObject;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.content.crosswalk.CrosswalkException; import org.dspace.content.crosswalk.CrosswalkException;
import org.dspace.core.Constants; import org.dspace.core.Constants;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.core.LogManager; import org.dspace.core.LogManager;
/** /**
* An abstract implementation of a DSpace Package Ingester, which * An abstract implementation of a DSpace Package Ingester, which
* implements a few helper/utility methods that most (all?) PackageIngesters * implements a few helper/utility methods that most (all?) PackageIngesters
* may find useful. * may find useful.
* <P> * <P>
* First, implements recursive functionality in ingestAll() and replaceAll() * First, implements recursive functionality in ingestAll() and replaceAll()
* methods of the PackageIngester interface. These methods are setup to * methods of the PackageIngester interface. These methods are setup to
* recursively call ingest() and replace() respectively. * recursively call ingest() and replace() respectively.
* <P> * <P>
* Finally, it also implements several utility methods (createDSpaceObject(), * Finally, it also implements several utility methods (createDSpaceObject(),
* finishCreateItem(), updateDSpaceObject()) which subclasses may find useful. * finishCreateItem(), updateDSpaceObject()) which subclasses may find useful.
* This classes will allow subclasses to easily create/update objects without * This classes will allow subclasses to easily create/update objects without
* having to worry too much about normal DSpace submission workflows (which is * having to worry too much about normal DSpace submission workflows (which is
* taken care of in these utility methods). * taken care of in these utility methods).
* <P> * <P>
* All Package ingesters should either extend this abstract class * All Package ingesters should either extend this abstract class
* or implement <code>PackageIngester</code> to better suit their needs. * or implement <code>PackageIngester</code> to better suit their needs.
* *
* @author Tim Donohue * @author Tim Donohue
* @see PackageIngester * @see PackageIngester
*/ */
public abstract class AbstractPackageIngester public abstract class AbstractPackageIngester
implements PackageIngester implements PackageIngester
{ {
/** log4j category */ /** log4j category */
private static Logger log = Logger.getLogger(AbstractPackageIngester.class); private static Logger log = Logger.getLogger(AbstractPackageIngester.class);
/** /**
* References to other packages -- these are the next packages to ingest recursively * References to other packages -- these are the next packages to ingest recursively
* Key = DSpace Object just ingested, Value = List of all packages relating to a DSpaceObject * Key = DSpace Object just ingested, Value = List of all packages relating to a DSpaceObject
**/ **/
private Map<DSpaceObject,List<String>> packageReferences = new HashMap<DSpaceObject,List<String>>(); private Map<DSpaceObject,List<String>> packageReferences = new HashMap<DSpaceObject,List<String>>();
/** List of all successfully ingested/replaced DSpace objects */ /** List of all successfully ingested/replaced DSpace objects */
private List<DSpaceObject> dsoIngestedList = new ArrayList<DSpaceObject>(); private List<DSpaceObject> dsoIngestedList = new ArrayList<DSpaceObject>();
/** /**
* Recursively create one or more DSpace Objects out of the contents * Recursively create one or more DSpace Objects out of the contents
* of the ingested package (and all other referenced packages). * of the ingested package (and all other referenced packages).
* The initial object is created under the indicated parent. All other * The initial object is created under the indicated parent. All other
* objects are created based on their relationship to the initial object. * objects are created based on their relationship to the initial object.
* <p> * <p>
* For example, a scenario may be to create a Collection based on a * For example, a scenario may be to create a Collection based on a
* collection-level package, and also create an Item for every item-level * collection-level package, and also create an Item for every item-level
* package referenced by the collection-level package. * package referenced by the collection-level package.
* <p> * <p>
* The output of this method is one or more newly created <code>DspaceObject<code>s. * The output of this method is one or more newly created <code>DspaceObject<code>s.
* <p> * <p>
* The packager <em>may</em> choose not to implement <code>ingestAll</code>, * The packager <em>may</em> choose not to implement <code>ingestAll</code>,
* or simply forward the call to <code>ingest</code> if it is unable to support * or simply forward the call to <code>ingest</code> if it is unable to support
* recursive ingestion. * recursive ingestion.
* <p> * <p>
* The deposit license (Only significant for Item) is passed * The deposit license (Only significant for Item) is passed
* explicitly as a string since there is no place for it in many * explicitly as a string since there is no place for it in many
* package formats. It is optional and may be given as * package formats. It is optional and may be given as
* <code>null</code>. * <code>null</code>.
* *
* @param context DSpace context. * @param context DSpace context.
* @param parent parent under which to create the initial object * @param parent parent under which to create the initial object
* (may be null -- in which case ingester must determine parent from package * (may be null -- in which case ingester must determine parent from package
* or throw an error). * or throw an error).
* @param pkgFile The initial package file to ingest * @param pkgFile The initial package file to ingest
* @param params Properties-style list of options (interpreted by each packager). * @param params Properties-style list of options (interpreted by each packager).
* @param license may be null, which takes default license. * @param license may be null, which takes default license.
* @return List of DSpaceObjects created * @return List of DSpaceObjects created
* *
* @throws PackageValidationException if initial package (or any referenced package) * @throws PackageValidationException if initial package (or any referenced package)
* is unacceptable or there is a fatal error in creating a DSpaceObject * is unacceptable or there is a fatal error in creating a DSpaceObject
* @throws UnsupportedOperationException if this packager does not * @throws UnsupportedOperationException if this packager does not
* implement <code>ingestAll</code> * implement <code>ingestAll</code>
*/ */
@Override @Override
public List<DSpaceObject> ingestAll(Context context, DSpaceObject parent, File pkgFile, public List<DSpaceObject> ingestAll(Context context, DSpaceObject parent, File pkgFile,
PackageParameters params, String license) PackageParameters params, String license)
throws PackageException, UnsupportedOperationException, throws PackageException, UnsupportedOperationException,
CrosswalkException, AuthorizeException, CrosswalkException, AuthorizeException,
SQLException, IOException SQLException, IOException
{ {
//If unset, make sure the Parameters specifies this is a recursive ingest //If unset, make sure the Parameters specifies this is a recursive ingest
if(!params.recursiveModeEnabled()) if(!params.recursiveModeEnabled())
{ {
params.setRecursiveModeEnabled(true); params.setRecursiveModeEnabled(true);
} }
//Initial DSpace Object to ingest //Initial DSpace Object to ingest
DSpaceObject dso = null; DSpaceObject dso = null;
//try to ingest the first package //try to ingest the first package
try try
{ {
//actually ingest pkg using provided PackageIngester //actually ingest pkg using provided PackageIngester
dso = ingest(context, parent, pkgFile, params, license); dso = ingest(context, parent, pkgFile, params, license);
} }
catch(IllegalStateException ie) catch(IllegalStateException ie)
{ {
// NOTE: if we encounter an IllegalStateException, this means the // NOTE: if we encounter an IllegalStateException, this means the
// handle is already in use and this object already exists. // handle is already in use and this object already exists.
//if we are skipping over (i.e. keeping) existing objects //if we are skipping over (i.e. keeping) existing objects
if(params.keepExistingModeEnabled()) if(params.keepExistingModeEnabled())
{ {
log.warn(LogManager.getHeader(context, "skip_package_ingest", "Object already exists, package-skipped=" + pkgFile)); log.warn(LogManager.getHeader(context, "skip_package_ingest", "Object already exists, package-skipped=" + pkgFile));
} }
else // Pass this exception on -- which essentially causes a full rollback of all changes (this is the default) else // Pass this exception on -- which essentially causes a full rollback of all changes (this is the default)
{ {
throw ie; throw ie;
} }
} }
//as long as our first object was ingested successfully //as long as our first object was ingested successfully
if(dso!=null) if(dso!=null)
{ {
//add to list of successfully ingested objects //add to list of successfully ingested objects
addToIngestedList(dso); addToIngestedList(dso);
//We can only recursively ingest non-Items //We can only recursively ingest non-Items
//(NOTE: Items have no children, as Bitstreams/Bundles are created from Item packages) //(NOTE: Items have no children, as Bitstreams/Bundles are created from Item packages)
if(dso.getType()!=Constants.ITEM) if(dso.getType()!=Constants.ITEM)
{ {
//Check if we found child package references when ingesting this latest DSpaceObject //Check if we found child package references when ingesting this latest DSpaceObject
List<String> childPkgRefs = getPackageReferences(dso); List<String> childPkgRefs = getPackageReferences(dso);
//we can only recursively ingest child packages //we can only recursively ingest child packages
//if we have references to them //if we have references to them
if(childPkgRefs!=null && !childPkgRefs.isEmpty()) if(childPkgRefs!=null && !childPkgRefs.isEmpty())
{ {
//Recursively ingest each child package, using this current object as the parent DSpace Object //Recursively ingest each child package, using this current object as the parent DSpace Object
for(String childPkgRef : childPkgRefs) for(String childPkgRef : childPkgRefs)
{ {
// Remember where the additions start // Remember where the additions start
int oldSize = dsoIngestedList.size(); int oldSize = dsoIngestedList.size();
//Assume package reference is relative to current package location //Assume package reference is relative to current package location
File childPkg = new File(pkgFile.getAbsoluteFile().getParent(), childPkgRef); File childPkg = new File(pkgFile.getAbsoluteFile().getParent(), childPkgRef);
//fun, it's recursive! -- ingested referenced package as a child of current object //fun, it's recursive! -- ingested referenced package as a child of current object
ingestAll(context, dso, childPkg, params, license); ingestAll(context, dso, childPkg, params, license);
// A Collection can map to Items that it does not "own". // A Collection can map to Items that it does not "own".
// If a Collection package has an Item as a child, it // If a Collection package has an Item as a child, it
// should be mapped regardless of ownership. // should be mapped regardless of ownership.
// Note: Only perform this mapping if new items were ingested to this collection // Note: Only perform this mapping if new items were ingested to this collection
if (Constants.COLLECTION == dso.getType() && dsoIngestedList.size()>oldSize) if (Constants.COLLECTION == dso.getType() && dsoIngestedList.size()>oldSize)
{ {
// Since running 'ingestAll' on an item, will only ingest one Item at most, // Since running 'ingestAll' on an item, will only ingest one Item at most,
// Just make sure that item is mapped to this collection. // Just make sure that item is mapped to this collection.
Item childItem = (Item)dsoIngestedList.get(oldSize); Item childItem = (Item)dsoIngestedList.get(oldSize);
Collection collection = (Collection)dso; Collection collection = (Collection)dso;
if (!childItem.isIn(collection)) if (!childItem.isIn(collection))
{ {
collection.addItem(childItem); collection.addItem(childItem);
} }
} }
} }
}//end if child pkgs }//end if child pkgs
}//end if not an Item }//end if not an Item
}//end if DSpaceObject not null }//end if DSpaceObject not null
//Return list of all objects ingested //Return list of all objects ingested
return getIngestedList(); return getIngestedList();
} }
/** /**
* Recursively replace one or more DSpace Objects out of the contents * Recursively replace one or more DSpace Objects out of the contents
* of the ingested package (and all other referenced packages). * of the ingested package (and all other referenced packages).
* The initial object to replace is indicated by <code>dso</code>. All other * The initial object to replace is indicated by <code>dso</code>. All other
* objects are replaced based on information provided in the referenced packages. * objects are replaced based on information provided in the referenced packages.
* <p> * <p>
* For example, a scenario may be to replace a Collection based on a * For example, a scenario may be to replace a Collection based on a
* collection-level package, and also replace *every* Item in that collection * collection-level package, and also replace *every* Item in that collection
* based on the item-level packages referenced by the collection-level package. * based on the item-level packages referenced by the collection-level package.
* <p> * <p>
* Please note that since the <code>dso</code> input only specifies the * Please note that since the <code>dso</code> input only specifies the
* initial object to replace, any additional objects to replace must be * initial object to replace, any additional objects to replace must be
* determined based on the referenced packages (or initial package itself). * determined based on the referenced packages (or initial package itself).
* <p> * <p>
* The output of this method is one or more replaced <code>DspaceObject<code>s. * The output of this method is one or more replaced <code>DspaceObject<code>s.
* <p> * <p>
* The packager <em>may</em> choose not to implement <code>replaceAll</code>, * The packager <em>may</em> choose not to implement <code>replaceAll</code>,
* since it somewhat contradicts the archival nature of DSpace. It also * since it somewhat contradicts the archival nature of DSpace. It also
* may choose to forward the call to <code>replace</code> if it is unable to * may choose to forward the call to <code>replace</code> if it is unable to
* support recursive replacement. * support recursive replacement.
* *
* @param context DSpace context. * @param context DSpace context.
* @param dso initial existing DSpace Object to be replaced, may be null * @param dso initial existing DSpace Object to be replaced, may be null
* if object to replace can be determined from package * if object to replace can be determined from package
* @param pkgFile The package file to ingest. * @param pkgFile The package file to ingest.
* @param params Properties-style list of options specific to this packager * @param params Properties-style list of options specific to this packager
* @return List of DSpaceObjects replaced * @return List of DSpaceObjects replaced
* *
* @throws PackageValidationException if initial package (or any referenced package) * @throws PackageValidationException if initial package (or any referenced package)
* is unacceptable or there is a fatal error in creating a DSpaceObject * is unacceptable or there is a fatal error in creating a DSpaceObject
* @throws UnsupportedOperationException if this packager does not * @throws UnsupportedOperationException if this packager does not
* implement <code>replaceAll</code> * implement <code>replaceAll</code>
*/ */
@Override @Override
public List<DSpaceObject> replaceAll(Context context, DSpaceObject dso, public List<DSpaceObject> replaceAll(Context context, DSpaceObject dso,
File pkgFile, PackageParameters params) File pkgFile, PackageParameters params)
throws PackageException, UnsupportedOperationException, throws PackageException, UnsupportedOperationException,
CrosswalkException, AuthorizeException, CrosswalkException, AuthorizeException,
SQLException, IOException SQLException, IOException
{ {
//If unset, make sure the Parameters specifies this is a recursive replace //If unset, make sure the Parameters specifies this is a recursive replace
if(!params.recursiveModeEnabled()) if(!params.recursiveModeEnabled())
{ {
params.setRecursiveModeEnabled(true); params.setRecursiveModeEnabled(true);
} }
//actually ingest pkg using provided PackageIngester, and replace object //actually ingest pkg using provided PackageIngester, and replace object
//NOTE: 'dso' may be null! If it is null, the PackageIngester must determine //NOTE: 'dso' may be null! If it is null, the PackageIngester must determine
// the object to be replaced from the package itself. // the object to be replaced from the package itself.
DSpaceObject replacedDso = replace(context, dso, pkgFile, params); DSpaceObject replacedDso = replace(context, dso, pkgFile, params);
//as long as our object was replaced successfully //as long as our object was replaced successfully
if(replacedDso!=null) if(replacedDso!=null)
{ {
//add to list of successfully replaced objects //add to list of successfully replaced objects
addToIngestedList(replacedDso); addToIngestedList(replacedDso);
//We can only recursively replace non-Items //We can only recursively replace non-Items
//(NOTE: Items have no children, as Bitstreams/Bundles are created from Item packages) //(NOTE: Items have no children, as Bitstreams/Bundles are created from Item packages)
if(replacedDso.getType()!=Constants.ITEM) if(replacedDso.getType()!=Constants.ITEM)
{ {
//Check if we found child package references when replacing this latest DSpaceObject //Check if we found child package references when replacing this latest DSpaceObject
List<String> childPkgRefs = getPackageReferences(replacedDso); List<String> childPkgRefs = getPackageReferences(replacedDso);
//we can only recursively ingest child packages //we can only recursively ingest child packages
//if we have references to them //if we have references to them
if(childPkgRefs!=null && !childPkgRefs.isEmpty()) if(childPkgRefs!=null && !childPkgRefs.isEmpty())
{ {
//Recursively replace each child package //Recursively replace each child package
for(String childPkgRef : childPkgRefs) for(String childPkgRef : childPkgRefs)
{ {
// Remember where the additions start // Remember where the additions start
int oldSize = dsoIngestedList.size(); int oldSize = dsoIngestedList.size();
//Assume package reference is relative to current package location //Assume package reference is relative to current package location
File childPkg = new File(pkgFile.getAbsoluteFile().getParent(), childPkgRef); File childPkg = new File(pkgFile.getAbsoluteFile().getParent(), childPkgRef);
//fun, it's recursive! -- replaced referenced package as a child of current object //fun, it's recursive! -- replaced referenced package as a child of current object
// Pass object to replace as 'null', as we don't know which object to replace. // Pass object to replace as 'null', as we don't know which object to replace.
replaceAll(context, null, childPkg, params); replaceAll(context, null, childPkg, params);
// A Collection can map to Items that it does not "own". // A Collection can map to Items that it does not "own".
// If a Collection package has an Item as a child, it // If a Collection package has an Item as a child, it
// should be mapped regardless of ownership. // should be mapped regardless of ownership.
// If a Collection package has an Item as a child, it // If a Collection package has an Item as a child, it
// should be mapped regardless of ownership. // should be mapped regardless of ownership.
// Note: Only perform this mapping if new items were ingested to this collection // Note: Only perform this mapping if new items were ingested to this collection
if (Constants.COLLECTION == replacedDso.getType() && dsoIngestedList.size()>oldSize) if (Constants.COLLECTION == replacedDso.getType() && dsoIngestedList.size()>oldSize)
{ {
// Since running 'replaceAll' on an item, will only ingest one Item at most, // Since running 'replaceAll' on an item, will only ingest one Item at most,
// Just make sure that item is mapped to this collection. // Just make sure that item is mapped to this collection.
Item childItem = (Item)dsoIngestedList.get(oldSize); Item childItem = (Item)dsoIngestedList.get(oldSize);
Collection collection = (Collection)replacedDso; Collection collection = (Collection)replacedDso;
if (!childItem.isIn(collection)) if (!childItem.isIn(collection))
{ {
collection.addItem(childItem); collection.addItem(childItem);
} }
} }
} }
}//end if child pkgs }//end if child pkgs
}//end if not an Item }//end if not an Item
}//end if DSpaceObject not null }//end if DSpaceObject not null
//Return list of all objects replaced //Return list of all objects replaced
return getIngestedList(); return getIngestedList();
} }
/** /**
* During ingestion process, some submission information packages (SIPs) * During ingestion process, some submission information packages (SIPs)
* may reference other packages to be ingested (recursively). * may reference other packages to be ingested (recursively).
* <P> * <P>
* This method collects all references to other packages, so that we * This method collects all references to other packages, so that we
* can choose to recursively ingest them, as necessary, alongside the * can choose to recursively ingest them, as necessary, alongside the
* DSpaceObject created from the original SIP. * DSpaceObject created from the original SIP.
* <P> * <P>
* References are collected based on the DSpaceObject created from the SIP * References are collected based on the DSpaceObject created from the SIP
* (this way we keep the context of these references). * (this way we keep the context of these references).
* *
* @param dso DSpaceObject whose SIP referenced another package * @param dso DSpaceObject whose SIP referenced another package
* @param packageRef A reference to another package, which can be ingested after this one * @param packageRef A reference to another package, which can be ingested after this one
*/ */
public void addPackageReference(DSpaceObject dso, String packageRef) public void addPackageReference(DSpaceObject dso, String packageRef)
{ {
List<String> packageRefValues = null; List<String> packageRefValues = null;
// Check if we already have an entry for packages reference by this object // Check if we already have an entry for packages reference by this object
if(packageReferences.containsKey(dso)) if(packageReferences.containsKey(dso))
{ {
packageRefValues = packageReferences.get(dso); packageRefValues = packageReferences.get(dso);
} }
else else
{ {
//Create a new empty list of references //Create a new empty list of references
packageRefValues = new ArrayList<String>(); packageRefValues = new ArrayList<String>();
} }
//add this package reference to existing list and save //add this package reference to existing list and save
packageRefValues.add(packageRef); packageRefValues.add(packageRef);
packageReferences.put(dso, packageRefValues); packageReferences.put(dso, packageRefValues);
} }
/** /**
* Return a list of known SIP references from a newly created DSpaceObject. * Return a list of known SIP references from a newly created DSpaceObject.
* <P> * <P>
* These references should detail where another package exists which * These references should detail where another package exists which
* should be ingested alongside the current DSpaceObject. * should be ingested alongside the current DSpaceObject.
* <P> * <P>
* The <code>AbstractPackageIngester</code> or an equivalent SIP handler is expected * The <code>AbstractPackageIngester</code> or an equivalent SIP handler is expected
* to understand how to deal with these package references. * to understand how to deal with these package references.
* *
* @param dso DSpaceObject whose SIP referenced other SIPs * @param dso DSpaceObject whose SIP referenced other SIPs
* @return List of Strings which are the references to external submission ingestion packages * @return List of Strings which are the references to external submission ingestion packages
* (may be null if no SIPs were referenced) * (may be null if no SIPs were referenced)
*/ */
public List<String> getPackageReferences(DSpaceObject dso) public List<String> getPackageReferences(DSpaceObject dso)
{ {
return packageReferences.get(dso); return packageReferences.get(dso);
} }
/** /**
* Add DSpaceObject to list of successfully ingested/replaced objects * Add DSpaceObject to list of successfully ingested/replaced objects
* @param dso DSpaceObject * @param dso DSpaceObject
*/ */
protected void addToIngestedList(DSpaceObject dso) protected void addToIngestedList(DSpaceObject dso)
{ {
//add to list of successfully ingested objects //add to list of successfully ingested objects
if(!dsoIngestedList.contains(dso)) if(!dsoIngestedList.contains(dso))
{ {
dsoIngestedList.add(dso); dsoIngestedList.add(dso);
} }
} }
/** /**
* Return List of all DSpaceObjects which have been ingested/replaced by * Return List of all DSpaceObjects which have been ingested/replaced by
* this instance of the Ingester. * this instance of the Ingester.
* <P> * <P>
* This list can be useful in reporting back to the user what content has * This list can be useful in reporting back to the user what content has
* been added or replaced. It's used by ingestAll() and replaceAll() to * been added or replaced. It's used by ingestAll() and replaceAll() to
* return this list of everything that was ingested/replaced. * return this list of everything that was ingested/replaced.
* *
* @return List of DSpaceObjects which have been added/replaced * @return List of DSpaceObjects which have been added/replaced
*/ */
protected List<DSpaceObject> getIngestedList() protected List<DSpaceObject> getIngestedList()
{ {
return dsoIngestedList; return dsoIngestedList;
} }
} }

View File

@@ -1,406 +1,406 @@
/** /**
* The contents of this file are subject to the license and copyright * The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source * detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at * tree and available online at
* *
* http://www.dspace.org/license/ * http://www.dspace.org/license/
*/ */
package org.dspace.content.packager; package org.dspace.content.packager;
import java.io.IOException; import java.io.IOException;
import java.sql.SQLException; import java.sql.SQLException;
import org.jdom.Element; import org.jdom.Element;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Bitstream; import org.dspace.content.Bitstream;
import org.dspace.content.Collection; import org.dspace.content.Collection;
import org.dspace.content.DCValue; import org.dspace.content.DCValue;
import org.dspace.content.DSpaceObject; import org.dspace.content.DSpaceObject;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.content.MetadataField; import org.dspace.content.MetadataField;
import org.dspace.content.MetadataSchema; import org.dspace.content.MetadataSchema;
import org.dspace.content.NonUniqueMetadataException; import org.dspace.content.NonUniqueMetadataException;
import org.dspace.content.crosswalk.CrosswalkException; import org.dspace.content.crosswalk.CrosswalkException;
import org.dspace.content.crosswalk.MetadataValidationException; import org.dspace.content.crosswalk.MetadataValidationException;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.core.Constants; import org.dspace.core.Constants;
/** /**
* Subclass of the METS packager framework to ingest a DSpace * Subclass of the METS packager framework to ingest a DSpace
* Archival Information Package (AIP). The AIP is intended to be, foremost, * Archival Information Package (AIP). The AIP is intended to be, foremost,
* a _complete_ and _accurate_ representation of one object in the DSpace * a _complete_ and _accurate_ representation of one object in the DSpace
* object model. An AIP contains all of the information needed to restore * object model. An AIP contains all of the information needed to restore
* the object precisely in another DSpace archive instance. * the object precisely in another DSpace archive instance.
* <p> * <p>
* This ingester recognizes two distinct types of AIPs: "Manifest-Only" and "External". * This ingester recognizes two distinct types of AIPs: "Manifest-Only" and "External".
* The Manifest-Only AIP, which is selected by specifying a PackageParameters * The Manifest-Only AIP, which is selected by specifying a PackageParameters
* key "manifestOnly" with the value "true", refers to all its contents by * key "manifestOnly" with the value "true", refers to all its contents by
* reference only. For Community or Collection AIPs this means all references to their * reference only. For Community or Collection AIPs this means all references to their
* child objects are just via Handles. For Item AIPs all Bitreams are just * child objects are just via Handles. For Item AIPs all Bitreams are just
* referenced by their asset store location instead of finding them in the "package". * referenced by their asset store location instead of finding them in the "package".
* The Manifest-Only AIP package format is simply a METS XML document serialized into a file. * The Manifest-Only AIP package format is simply a METS XML document serialized into a file.
* <p> * <p>
* An "external" AIP (the default), is a conventional Zip-file based package * An "external" AIP (the default), is a conventional Zip-file based package
* that includes copies of all bitstreams referenced by the object as well * that includes copies of all bitstreams referenced by the object as well
* as a serialized METS XML document in the path "mets.xml". * as a serialized METS XML document in the path "mets.xml".
* *
* Configuration keys: * Configuration keys:
* *
* # instructs which xwalk plugin to use for a given type of metadata * # instructs which xwalk plugin to use for a given type of metadata
* mets.dspaceAIP.ingest.crosswalk.{mdSecName} = {pluginName} * mets.dspaceAIP.ingest.crosswalk.{mdSecName} = {pluginName}
* mets.dspaceAIP.ingest.crosswalk.DC = QDC * mets.dspaceAIP.ingest.crosswalk.DC = QDC
* mets.dspaceAIP.ingest.crosswalk.DSpaceDepositLicense = NULLSTREAM * mets.dspaceAIP.ingest.crosswalk.DSpaceDepositLicense = NULLSTREAM
* *
* # Option to save METS manifest in the item: (default is false) * # Option to save METS manifest in the item: (default is false)
* mets.default.ingest.preserveManifest = false * mets.default.ingest.preserveManifest = false
* *
* @author Larry Stone * @author Larry Stone
* @author Tim Donohue * @author Tim Donohue
* @version $Revision: 1.1 $ * @version $Revision: 1.1 $
* *
* @see AbstractMETSIngester * @see AbstractMETSIngester
* @see AbstractPackageIngester * @see AbstractPackageIngester
* @see PackageIngester * @see PackageIngester
* @see org.dspace.content.packager.METSManifest * @see org.dspace.content.packager.METSManifest
*/ */
public class DSpaceAIPIngester public class DSpaceAIPIngester
extends AbstractMETSIngester extends AbstractMETSIngester
{ {
/** log4j category */ /** log4j category */
private static Logger log = Logger.getLogger(DSpaceAIPIngester.class); private static Logger log = Logger.getLogger(DSpaceAIPIngester.class);
/** /**
* Ensure it's an AIP generated by the complementary AIP disseminator. * Ensure it's an AIP generated by the complementary AIP disseminator.
*/ */
@Override @Override
void checkManifest(METSManifest manifest) void checkManifest(METSManifest manifest)
throws MetadataValidationException throws MetadataValidationException
{ {
String profile = manifest.getProfile(); String profile = manifest.getProfile();
if (profile == null) if (profile == null)
{ {
throw new MetadataValidationException("Cannot accept METS with no PROFILE attribute!"); throw new MetadataValidationException("Cannot accept METS with no PROFILE attribute!");
} }
else if (!profile.equals(DSpaceAIPDisseminator.PROFILE_1_0)) else if (!profile.equals(DSpaceAIPDisseminator.PROFILE_1_0))
{ {
throw new MetadataValidationException("METS has unacceptable PROFILE attribute, profile=" + profile); throw new MetadataValidationException("METS has unacceptable PROFILE attribute, profile=" + profile);
} }
} }
/** /**
* Choose DMD section(s) to crosswalk. * Choose DMD section(s) to crosswalk.
* <p> * <p>
* The algorithm is:<br> * The algorithm is:<br>
* 1. Use whatever the <code>dmd</code> parameter specifies as the primary DMD.<br> * 1. Use whatever the <code>dmd</code> parameter specifies as the primary DMD.<br>
* 2. If (1) is unspecified, find DIM (preferably) or MODS as primary DMD.<br> * 2. If (1) is unspecified, find DIM (preferably) or MODS as primary DMD.<br>
* 3. If (1) or (2) succeeds, crosswalk it and ignore all other DMDs with * 3. If (1) or (2) succeeds, crosswalk it and ignore all other DMDs with
* same GROUPID<br> * same GROUPID<br>
* 4. Crosswalk remaining DMDs not eliminated already. * 4. Crosswalk remaining DMDs not eliminated already.
*/ */
@Override @Override
public void crosswalkObjectDmd(Context context, DSpaceObject dso, public void crosswalkObjectDmd(Context context, DSpaceObject dso,
METSManifest manifest, METSManifest manifest,
MdrefManager callback, MdrefManager callback,
Element dmds[], PackageParameters params) Element dmds[], PackageParameters params)
throws CrosswalkException, PackageValidationException, throws CrosswalkException, PackageValidationException,
AuthorizeException, SQLException, IOException AuthorizeException, SQLException, IOException
{ {
int found = -1; int found = -1;
// Check to see what dmdSec the user specified in the 'dmd' parameter // Check to see what dmdSec the user specified in the 'dmd' parameter
String userDmd = null; String userDmd = null;
if (params != null) if (params != null)
{ {
userDmd = params.getProperty("dmd"); userDmd = params.getProperty("dmd");
} }
if (userDmd != null && userDmd.length() > 0) if (userDmd != null && userDmd.length() > 0)
{ {
for (int i = 0; i < dmds.length; ++i) for (int i = 0; i < dmds.length; ++i)
{ {
if (userDmd.equalsIgnoreCase(manifest.getMdType(dmds[i]))) if (userDmd.equalsIgnoreCase(manifest.getMdType(dmds[i])))
{ {
found = i; found = i;
} }
} }
} }
// DIM is preferred, if nothing specified by user // DIM is preferred, if nothing specified by user
if (found == -1) if (found == -1)
{ {
// DIM is preferred for AIP // DIM is preferred for AIP
for (int i = 0; i < dmds.length; ++i) for (int i = 0; i < dmds.length; ++i)
{ {
//NOTE: METS standard actually says this should be DIM (all uppercase). But, //NOTE: METS standard actually says this should be DIM (all uppercase). But,
// just in case, we're going to be a bit more forgiving. // just in case, we're going to be a bit more forgiving.
if ("DIM".equalsIgnoreCase(manifest.getMdType(dmds[i]))) if ("DIM".equalsIgnoreCase(manifest.getMdType(dmds[i])))
{ {
found = i; found = i;
} }
} }
} }
// MODS is acceptable otehrwise.. // MODS is acceptable otehrwise..
if (found == -1) if (found == -1)
{ {
for (int i = 0; i < dmds.length; ++i) for (int i = 0; i < dmds.length; ++i)
{ {
//NOTE: METS standard actually says this should be MODS (all uppercase). But, //NOTE: METS standard actually says this should be MODS (all uppercase). But,
// just in case, we're going to be a bit more forgiving. // just in case, we're going to be a bit more forgiving.
if ("MODS".equalsIgnoreCase(manifest.getMdType(dmds[i]))) if ("MODS".equalsIgnoreCase(manifest.getMdType(dmds[i])))
{ {
found = i; found = i;
} }
} }
} }
String groupID = null; String groupID = null;
if (found >= 0) if (found >= 0)
{ {
manifest.crosswalkItemDmd(context, params, dso, dmds[found], callback); manifest.crosswalkItemDmd(context, params, dso, dmds[found], callback);
groupID = dmds[found].getAttributeValue("GROUPID"); groupID = dmds[found].getAttributeValue("GROUPID");
if (groupID != null) if (groupID != null)
{ {
for (int i = 0; i < dmds.length; ++i) for (int i = 0; i < dmds.length; ++i)
{ {
String g = dmds[i].getAttributeValue("GROUPID"); String g = dmds[i].getAttributeValue("GROUPID");
if (g != null && !g.equals(groupID)) if (g != null && !g.equals(groupID))
{ {
manifest.crosswalkItemDmd(context, params, dso, dmds[i], callback); manifest.crosswalkItemDmd(context, params, dso, dmds[i], callback);
} }
} }
} }
} }
// otherwise take the first. Don't xwalk more than one because // otherwise take the first. Don't xwalk more than one because
// each xwalk _adds_ metadata, and could add duplicate fields. // each xwalk _adds_ metadata, and could add duplicate fields.
else if (dmds.length > 0) else if (dmds.length > 0)
{ {
manifest.crosswalkItemDmd(context, params, dso, dmds[0], callback); manifest.crosswalkItemDmd(context, params, dso, dmds[0], callback);
} }
// it's an error if there is nothing to crosswalk: // it's an error if there is nothing to crosswalk:
else else
{ {
throw new MetadataValidationException("DSpaceAIPIngester: Could not find an acceptable object-wide DMD section in manifest."); throw new MetadataValidationException("DSpaceAIPIngester: Could not find an acceptable object-wide DMD section in manifest.");
} }
} }
/** /**
* Ignore license when restoring an manifest-only AIP, since it should * Ignore license when restoring an manifest-only AIP, since it should
* be a bitstream in the AIP already. * be a bitstream in the AIP already.
* Otherwise: Check item for license first; then, take deposit * Otherwise: Check item for license first; then, take deposit
* license supplied by explicit argument next, else use collection's * license supplied by explicit argument next, else use collection's
* default deposit license. * default deposit license.
* Normally the rightsMD crosswalks should provide a license. * Normally the rightsMD crosswalks should provide a license.
*/ */
@Override @Override
public void addLicense(Context context, Item item, String license, public void addLicense(Context context, Item item, String license,
Collection collection, PackageParameters params) Collection collection, PackageParameters params)
throws PackageValidationException, throws PackageValidationException,
AuthorizeException, SQLException, IOException AuthorizeException, SQLException, IOException
{ {
boolean newLicense = false; boolean newLicense = false;
if(!params.restoreModeEnabled()) if(!params.restoreModeEnabled())
{ {
//AIP is not being restored/replaced, so treat it like a SIP -- every new SIP needs a new license //AIP is not being restored/replaced, so treat it like a SIP -- every new SIP needs a new license
newLicense = true; newLicense = true;
} }
// Add deposit license if there isn't one in the object, // Add deposit license if there isn't one in the object,
// and it's not a restoration of an "manifestOnly" AIP: // and it's not a restoration of an "manifestOnly" AIP:
if (!params.getBooleanProperty("manifestOnly", false) && if (!params.getBooleanProperty("manifestOnly", false) &&
PackageUtils.findDepositLicense(context, item) == null) PackageUtils.findDepositLicense(context, item) == null)
{ {
newLicense = true; newLicense = true;
} }
if(newLicense) if(newLicense)
{ {
PackageUtils.addDepositLicense(context, license, item, collection); PackageUtils.addDepositLicense(context, license, item, collection);
} }
} }
/** /**
* Last change to fix up a DSpace Object. * Last change to fix up a DSpace Object.
* <P> * <P>
* For AIPs, if the object is an Item, we may want to make sure all of its * For AIPs, if the object is an Item, we may want to make sure all of its
* metadata fields already exist in the database (otherwise, the database * metadata fields already exist in the database (otherwise, the database
* will throw errors when we attempt to save/update the Item) * will throw errors when we attempt to save/update the Item)
* *
* @param context DSpace Context * @param context DSpace Context
* @param dso DSpace object * @param dso DSpace object
* @param params Packager Parameters * @param params Packager Parameters
*/ */
@Override @Override
public void finishObject(Context context, DSpaceObject dso, PackageParameters params) public void finishObject(Context context, DSpaceObject dso, PackageParameters params)
throws PackageValidationException, CrosswalkException, throws PackageValidationException, CrosswalkException,
AuthorizeException, SQLException, IOException AuthorizeException, SQLException, IOException
{ {
if(dso.getType()==Constants.ITEM) if(dso.getType()==Constants.ITEM)
{ {
// Check if 'createMetadataFields' option is enabled (default=true) // Check if 'createMetadataFields' option is enabled (default=true)
// This defaults to true as by default we should attempt to restore as much metadata as we can. // This defaults to true as by default we should attempt to restore as much metadata as we can.
// When 'createMetadataFields' is set to false, an ingest will fail if it attempts to ingest content to a missing metadata field. // When 'createMetadataFields' is set to false, an ingest will fail if it attempts to ingest content to a missing metadata field.
if (params.getBooleanProperty("createMetadataFields", true)) if (params.getBooleanProperty("createMetadataFields", true))
{ {
// We want to verify that all the Metadata Fields we've crosswalked // We want to verify that all the Metadata Fields we've crosswalked
// actually *exist* in the DB. If not, we'll try to create them // actually *exist* in the DB. If not, we'll try to create them
createMissingMetadataFields(context, (Item) dso); createMissingMetadataFields(context, (Item) dso);
} }
} }
} }
/** /**
* Nothing extra to do to bitstream after ingestion. * Nothing extra to do to bitstream after ingestion.
*/ */
@Override @Override
public void finishBitstream(Context context, public void finishBitstream(Context context,
Bitstream bs, Bitstream bs,
Element mfile, Element mfile,
METSManifest manifest, METSManifest manifest,
PackageParameters params) PackageParameters params)
throws MetadataValidationException, SQLException, AuthorizeException, IOException throws MetadataValidationException, SQLException, AuthorizeException, IOException
{ {
// nothing to do. // nothing to do.
} }
/** /**
* Return the type of DSpaceObject in this package; it is * Return the type of DSpaceObject in this package; it is
* in the TYPE attribute of the mets:mets element. * in the TYPE attribute of the mets:mets element.
*/ */
@Override @Override
public int getObjectType(METSManifest manifest) public int getObjectType(METSManifest manifest)
throws PackageValidationException throws PackageValidationException
{ {
Element mets = manifest.getMets(); Element mets = manifest.getMets();
String typeStr = mets.getAttributeValue("TYPE"); String typeStr = mets.getAttributeValue("TYPE");
if (typeStr == null || typeStr.length() == 0) if (typeStr == null || typeStr.length() == 0)
{ {
throw new PackageValidationException("Manifest is missing the required mets@TYPE attribute."); throw new PackageValidationException("Manifest is missing the required mets@TYPE attribute.");
} }
if (typeStr.startsWith("DSpace ")) if (typeStr.startsWith("DSpace "))
{ {
typeStr = typeStr.substring(7); typeStr = typeStr.substring(7);
} }
int type = Constants.getTypeID(typeStr); int type = Constants.getTypeID(typeStr);
if (type < 0) if (type < 0)
{ {
throw new PackageValidationException("Manifest has unrecognized value in mets@TYPE attribute: " + typeStr); throw new PackageValidationException("Manifest has unrecognized value in mets@TYPE attribute: " + typeStr);
} }
return type; return type;
} }
/** /**
* Name used to distinguish DSpace Configuration entries for this subclass. * Name used to distinguish DSpace Configuration entries for this subclass.
*/ */
@Override @Override
public String getConfigurationName() public String getConfigurationName()
{ {
return "dspaceAIP"; return "dspaceAIP";
} }
/** /**
* Verifies that all the unsaved, crosswalked metadata fields that have * Verifies that all the unsaved, crosswalked metadata fields that have
* been added to an Item actually exist in our Database. If they don't * been added to an Item actually exist in our Database. If they don't
* exist, they are created within the proper database tables. * exist, they are created within the proper database tables.
* <P> * <P>
* This method must be called *before* item.update(), as the call to update() * This method must be called *before* item.update(), as the call to update()
* will throw a SQLException when attempting to save any fields which * will throw a SQLException when attempting to save any fields which
* don't already exist in the database. * don't already exist in the database.
* <P> * <P>
* NOTE: This will NOT create a missing Metadata Schema (e.g. "dc" schema), * NOTE: This will NOT create a missing Metadata Schema (e.g. "dc" schema),
* as we do not have enough info to create schemas on the fly. * as we do not have enough info to create schemas on the fly.
* *
* @param context - DSpace Context * @param context - DSpace Context
* @param item - Item whose unsaved metadata fields we are testing * @param item - Item whose unsaved metadata fields we are testing
* @throws AuthorizeException if a metadata field doesn't exist and current user is not authorized to create it (i.e. not an Admin) * @throws AuthorizeException if a metadata field doesn't exist and current user is not authorized to create it (i.e. not an Admin)
* @throws PackageValidationException if a metadata schema doesn't exist, as we cannot autocreate a schema * @throws PackageValidationException if a metadata schema doesn't exist, as we cannot autocreate a schema
*/ */
protected static void createMissingMetadataFields(Context context, Item item) protected static void createMissingMetadataFields(Context context, Item item)
throws PackageValidationException, AuthorizeException, IOException, SQLException throws PackageValidationException, AuthorizeException, IOException, SQLException
{ {
// Get all metadata fields/values currently added to this Item // Get all metadata fields/values currently added to this Item
DCValue allMD[] = item.getMetadata(Item.ANY, Item.ANY, Item.ANY, Item.ANY); DCValue allMD[] = item.getMetadata(Item.ANY, Item.ANY, Item.ANY, Item.ANY);
// For each field, we'll check if it exists. If not, we'll create it. // For each field, we'll check if it exists. If not, we'll create it.
for(DCValue md : allMD) for(DCValue md : allMD)
{ {
MetadataSchema mdSchema = null; MetadataSchema mdSchema = null;
MetadataField mdField = null; MetadataField mdField = null;
try try
{ {
//Try to access this Schema //Try to access this Schema
mdSchema = MetadataSchema.find(context, md.schema); mdSchema = MetadataSchema.find(context, md.schema);
//If Schema found, try to locate field from database //If Schema found, try to locate field from database
if(mdSchema!=null) if(mdSchema!=null)
{ {
mdField = MetadataField.findByElement(context, mdSchema.getSchemaID(), md.element, md.qualifier); mdField = MetadataField.findByElement(context, mdSchema.getSchemaID(), md.element, md.qualifier);
} }
} }
catch(SQLException se) catch(SQLException se)
{ {
//If a SQLException error is thrown, then this field does NOT exist in DB //If a SQLException error is thrown, then this field does NOT exist in DB
//Set field to null, so we know we need to create it //Set field to null, so we know we need to create it
mdField = null; mdField = null;
} }
// If our Schema was not found, we have a problem // If our Schema was not found, we have a problem
// We cannot easily create a Schema automatically -- as we don't know its Namespace // We cannot easily create a Schema automatically -- as we don't know its Namespace
if(mdSchema==null) if(mdSchema==null)
{ {
throw new PackageValidationException("Unknown Metadata Schema encountered (" + md.schema + ") when attempting to ingest an Item. You will need to create this Metadata Schema in DSpace Schema Registry before the Item can be ingested."); throw new PackageValidationException("Unknown Metadata Schema encountered (" + md.schema + ") when attempting to ingest an Item. You will need to create this Metadata Schema in DSpace Schema Registry before the Item can be ingested.");
} }
// If our Metadata Field is null, we will attempt to create it in the proper Schema // If our Metadata Field is null, we will attempt to create it in the proper Schema
if(mdField==null) if(mdField==null)
{ {
try try
{ {
//initialize field (but don't set a scope note) & create it //initialize field (but don't set a scope note) & create it
mdField = new MetadataField(mdSchema, md.element, md.qualifier, null); mdField = new MetadataField(mdSchema, md.element, md.qualifier, null);
// NOTE: Only Adminstrators can create Metadata Fields -- create() will throw an AuthorizationException for non-Admins // NOTE: Only Adminstrators can create Metadata Fields -- create() will throw an AuthorizationException for non-Admins
mdField.create(context); mdField.create(context);
//log that field was created //log that field was created
log.info("Located a missing metadata field (schema:'" + mdSchema.getName() +"', element:'"+ md.element +"', qualifier:'"+ md.qualifier +"') while ingesting Item. This missing field has been created in the DSpace Metadata Field Registry."); log.info("Located a missing metadata field (schema:'" + mdSchema.getName() +"', element:'"+ md.element +"', qualifier:'"+ md.qualifier +"') while ingesting Item. This missing field has been created in the DSpace Metadata Field Registry.");
} }
catch(NonUniqueMetadataException ne) catch(NonUniqueMetadataException ne)
{ // This exception should never happen, as we already checked to make sure the field doesn't exist. { // This exception should never happen, as we already checked to make sure the field doesn't exist.
// But, we'll catch it anyways so that the Java compiler doesn't get upset // But, we'll catch it anyways so that the Java compiler doesn't get upset
throw new SQLException("Unable to create Metadata Field (element='" + md.element + "', qualifier='" + md.qualifier + "') in Schema "+ mdSchema.getName() +".", ne); throw new SQLException("Unable to create Metadata Field (element='" + md.element + "', qualifier='" + md.qualifier + "') in Schema "+ mdSchema.getName() +".", ne);
} }
} }
} }
} }
/** /**
* Returns a user help string which should describe the * Returns a user help string which should describe the
* additional valid command-line options that this packager * additional valid command-line options that this packager
* implementation will accept when using the <code>-o</code> or * implementation will accept when using the <code>-o</code> or
* <code>--option</code> flags with the Packager script. * <code>--option</code> flags with the Packager script.
* *
* @return a string describing additional command-line options available * @return a string describing additional command-line options available
* with this packager * with this packager
*/ */
@Override @Override
public String getParameterHelp() public String getParameterHelp()
{ {
String parentHelp = super.getParameterHelp(); String parentHelp = super.getParameterHelp();
//Return superclass help info, plus the extra parameters/options that this class supports //Return superclass help info, plus the extra parameters/options that this class supports
return parentHelp + return parentHelp +
"\n\n" + "\n\n" +
"* createMetadataFields=[boolean] " + "* createMetadataFields=[boolean] " +
"If true, ingest attempts to create any missing metadata fields." + "If true, ingest attempts to create any missing metadata fields." +
"If false, ingest will fail if a metadata field is encountered which doesn't already exist. (default = true)" + "If false, ingest will fail if a metadata field is encountered which doesn't already exist. (default = true)" +
"\n\n" + "\n\n" +
"* dmd=[dmdSecType] " + "* dmd=[dmdSecType] " +
"Type of the METS <dmdSec> which should be used to restore item metadata (defaults to DIM, then MODS)"; "Type of the METS <dmdSec> which should be used to restore item metadata (defaults to DIM, then MODS)";
} }
} }

View File

@@ -834,14 +834,16 @@ public class PackageUtils
if(dso==null) if(dso==null)
{ {
// No such object. Change the name to something harmless. // No such object. Change the name to something harmless, but predictable.
// NOTE: this name *must* be predictable. If we generate the same AIP
// twice in a row, we must end up with the same group name each time.
String newName; String newName;
if (orphanGroups.containsKey(groupName)) if (orphanGroups.containsKey(groupName))
newName = orphanGroups.get(groupName); newName = orphanGroups.get(groupName);
else else
{ {
newName= "GROUP_" + Utils.generateHexKey() + "_" newName= "ORPHANED_" + objType + "_GROUP_"
+ objType + "_" + groupType; + objID + "_" + groupType;
orphanGroups.put(groupName, newName); orphanGroups.put(groupName, newName);
// A given group should only be translated once, since the // A given group should only be translated once, since the
// new name contains unique random elements which would be // new name contains unique random elements which would be

View File

@@ -26,7 +26,7 @@ import java.util.Calendar;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.text.ParseException; import java.text.ParseException;
import com.coverity.security.Escape;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
/** /**
@@ -280,21 +280,8 @@ public final class Utils
*/ */
public static String addEntities(String value) public static String addEntities(String value)
{ {
if (value==null || value.length() == 0)
{
return value;
}
value = value.replaceAll("&", "&amp;");
value = value.replaceAll("\"", "&quot;");
// actually, &apos; is an XML entity, not in HTML. return Escape.html(value);
// that's why it's commented out.
// value = value.replaceAll("'", "&apos;");
value = value.replaceAll("<", "&lt;");
value = value.replaceAll(">", "&gt;");
return value;
} }
/** /**

View File

@@ -1,363 +1,363 @@
/** /**
* The contents of this file are subject to the license and copyright * The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source * detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at * tree and available online at
* *
* http://www.dspace.org/license/ * http://www.dspace.org/license/
*/ */
package org.dspace.ctask.general; package org.dspace.ctask.general;
// above package assignment temporary pending better aysnch release process // above package assignment temporary pending better aysnch release process
// package org.dspace.ctask.integrity; // package org.dspace.ctask.integrity;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.Socket; import java.net.Socket;
import java.net.SocketException; import java.net.SocketException;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Bitstream; import org.dspace.content.Bitstream;
import org.dspace.content.Bundle; import org.dspace.content.Bundle;
import org.dspace.content.DSpaceObject; import org.dspace.content.DSpaceObject;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.core.ConfigurationManager; import org.dspace.core.ConfigurationManager;
import org.dspace.curate.AbstractCurationTask; import org.dspace.curate.AbstractCurationTask;
import org.dspace.curate.Curator; import org.dspace.curate.Curator;
import org.dspace.curate.Suspendable; import org.dspace.curate.Suspendable;
/** ClamScan.java /** ClamScan.java
* *
* A set of methods to scan using the * A set of methods to scan using the
* clamav daemon. * clamav daemon.
* *
* TODO: add a check for the inputstream size limit * TODO: add a check for the inputstream size limit
* *
* @author wbossons * @author wbossons
*/ */
@Suspendable(invoked= Curator.Invoked.INTERACTIVE) @Suspendable(invoked= Curator.Invoked.INTERACTIVE)
public class ClamScan extends AbstractCurationTask public class ClamScan extends AbstractCurationTask
{ {
private static final int DEFAULT_CHUNK_SIZE = 4096;//2048 private static final int DEFAULT_CHUNK_SIZE = 4096;//2048
private static final byte[] INSTREAM = "zINSTREAM\0".getBytes(); private static final byte[] INSTREAM = "zINSTREAM\0".getBytes();
private static final byte[] PING = "zPING\0".getBytes(); private static final byte[] PING = "zPING\0".getBytes();
private static final byte[] STATS = "nSTATS\n".getBytes();//prefix with z private static final byte[] STATS = "nSTATS\n".getBytes();//prefix with z
private static final byte[] IDSESSION = "zIDSESSION\0".getBytes(); private static final byte[] IDSESSION = "zIDSESSION\0".getBytes();
private static final byte[] END = "zEND\0".getBytes(); private static final byte[] END = "zEND\0".getBytes();
private static final String PLUGIN_PREFIX = "clamav"; private static final String PLUGIN_PREFIX = "clamav";
private static final String INFECTED_MESSAGE = "had virus detected."; private static final String INFECTED_MESSAGE = "had virus detected.";
private static final String CLEAN_MESSAGE = "had no viruses detected."; private static final String CLEAN_MESSAGE = "had no viruses detected.";
private static final String CONNECT_FAIL_MESSAGE = "Unable to connect to virus service - check setup"; private static final String CONNECT_FAIL_MESSAGE = "Unable to connect to virus service - check setup";
private static final String SCAN_FAIL_MESSAGE = "Error encountered using virus service - check setup"; private static final String SCAN_FAIL_MESSAGE = "Error encountered using virus service - check setup";
private static final String NEW_ITEM_HANDLE = "in workflow"; private static final String NEW_ITEM_HANDLE = "in workflow";
private static Logger log = Logger.getLogger(ClamScan.class); private static Logger log = Logger.getLogger(ClamScan.class);
private static String host = null; private static String host = null;
private static int port = 0; private static int port = 0;
private static int timeout = 0; private static int timeout = 0;
private static boolean failfast = true; private static boolean failfast = true;
private int status = Curator.CURATE_UNSET; private int status = Curator.CURATE_UNSET;
private List<String> results = null; private List<String> results = null;
private Socket socket = null; private Socket socket = null;
private DataOutputStream dataOutputStream = null; private DataOutputStream dataOutputStream = null;
@Override @Override
public void init(Curator curator, String taskId) throws IOException public void init(Curator curator, String taskId) throws IOException
{ {
super.init(curator, taskId); super.init(curator, taskId);
host = ConfigurationManager.getProperty(PLUGIN_PREFIX, "service.host"); host = ConfigurationManager.getProperty(PLUGIN_PREFIX, "service.host");
port = ConfigurationManager.getIntProperty(PLUGIN_PREFIX, "service.port"); port = ConfigurationManager.getIntProperty(PLUGIN_PREFIX, "service.port");
timeout = ConfigurationManager.getIntProperty(PLUGIN_PREFIX, "socket.timeout"); timeout = ConfigurationManager.getIntProperty(PLUGIN_PREFIX, "socket.timeout");
failfast = ConfigurationManager.getBooleanProperty(PLUGIN_PREFIX, "scan.failfast"); failfast = ConfigurationManager.getBooleanProperty(PLUGIN_PREFIX, "scan.failfast");
} }
@Override @Override
public int perform(DSpaceObject dso) throws IOException public int perform(DSpaceObject dso) throws IOException
{ {
status = Curator.CURATE_SKIP; status = Curator.CURATE_SKIP;
logDebugMessage("The target dso is " + dso.getName()); logDebugMessage("The target dso is " + dso.getName());
if (dso instanceof Item) if (dso instanceof Item)
{ {
status = Curator.CURATE_SUCCESS; status = Curator.CURATE_SUCCESS;
Item item = (Item)dso; Item item = (Item)dso;
try try
{ {
openSession(); openSession();
} }
catch (IOException ioE) catch (IOException ioE)
{ {
// no point going further - set result and error out // no point going further - set result and error out
closeSession(); closeSession();
setResult(CONNECT_FAIL_MESSAGE); setResult(CONNECT_FAIL_MESSAGE);
return Curator.CURATE_ERROR; return Curator.CURATE_ERROR;
} }
try try
{ {
Bundle bundle = item.getBundles("ORIGINAL")[0]; Bundle bundle = item.getBundles("ORIGINAL")[0];
results = new ArrayList<String>(); results = new ArrayList<String>();
for (Bitstream bitstream : bundle.getBitstreams()) for (Bitstream bitstream : bundle.getBitstreams())
{ {
InputStream inputstream = bitstream.retrieve(); InputStream inputstream = bitstream.retrieve();
logDebugMessage("Scanning " + bitstream.getName() + " . . . "); logDebugMessage("Scanning " + bitstream.getName() + " . . . ");
int bstatus = scan(bitstream, inputstream, getItemHandle(item)); int bstatus = scan(bitstream, inputstream, getItemHandle(item));
inputstream.close(); inputstream.close();
if (bstatus == Curator.CURATE_ERROR) if (bstatus == Curator.CURATE_ERROR)
{ {
// no point going further - set result and error out // no point going further - set result and error out
setResult(SCAN_FAIL_MESSAGE); setResult(SCAN_FAIL_MESSAGE);
status = bstatus; status = bstatus;
break; break;
} }
if (failfast && bstatus == Curator.CURATE_FAIL) if (failfast && bstatus == Curator.CURATE_FAIL)
{ {
status = bstatus; status = bstatus;
break; break;
} }
else if (bstatus == Curator.CURATE_FAIL && else if (bstatus == Curator.CURATE_FAIL &&
status == Curator.CURATE_SUCCESS) status == Curator.CURATE_SUCCESS)
{ {
status = bstatus; status = bstatus;
} }
} }
} }
catch (AuthorizeException authE) catch (AuthorizeException authE)
{ {
throw new IOException(authE.getMessage(), authE); throw new IOException(authE.getMessage(), authE);
} }
catch (SQLException sqlE) catch (SQLException sqlE)
{ {
throw new IOException(sqlE.getMessage(), sqlE); throw new IOException(sqlE.getMessage(), sqlE);
} }
finally finally
{ {
closeSession(); closeSession();
} }
if (status != Curator.CURATE_ERROR) if (status != Curator.CURATE_ERROR)
{ {
formatResults(item); formatResults(item);
} }
} }
return status; return status;
} }
/** openSession /** openSession
* *
* This method opens a session. * This method opens a session.
*/ */
private void openSession() throws IOException private void openSession() throws IOException
{ {
socket = new Socket(); socket = new Socket();
try try
{ {
logDebugMessage("Connecting to " + host + ":" + port); logDebugMessage("Connecting to " + host + ":" + port);
socket.connect(new InetSocketAddress(host, port)); socket.connect(new InetSocketAddress(host, port));
} }
catch (IOException e) catch (IOException e)
{ {
log.error("Failed to connect to clamd . . .", e); log.error("Failed to connect to clamd . . .", e);
throw (e); throw (e);
} }
try try
{ {
socket.setSoTimeout(timeout); socket.setSoTimeout(timeout);
} }
catch (SocketException e) catch (SocketException e)
{ {
log.error("Could not set socket timeout . . . " + timeout + "ms", e); log.error("Could not set socket timeout . . . " + timeout + "ms", e);
throw (new IOException(e)); throw (new IOException(e));
} }
try try
{ {
dataOutputStream = new DataOutputStream(socket.getOutputStream()); dataOutputStream = new DataOutputStream(socket.getOutputStream());
} }
catch (IOException e) catch (IOException e)
{ {
log.error("Failed to open OutputStream . . . ", e); log.error("Failed to open OutputStream . . . ", e);
throw (e); throw (e);
} }
try try
{ {
dataOutputStream.write(IDSESSION); dataOutputStream.write(IDSESSION);
} }
catch (IOException e) catch (IOException e)
{ {
log.error("Error initiating session with IDSESSION command . . . ", e); log.error("Error initiating session with IDSESSION command . . . ", e);
throw (e); throw (e);
} }
} }
/** closeSession /** closeSession
* *
* Close the IDSESSION in CLAMD * Close the IDSESSION in CLAMD
* *
* *
*/ */
private void closeSession() private void closeSession()
{ {
if (dataOutputStream != null) if (dataOutputStream != null)
{ {
try try
{ {
dataOutputStream.write(END); dataOutputStream.write(END);
} }
catch (IOException e) catch (IOException e)
{ {
log.error("Exception closing dataOutputStream", e); log.error("Exception closing dataOutputStream", e);
} }
} }
try try
{ {
logDebugMessage("Closing the socket for ClamAv daemon . . . "); logDebugMessage("Closing the socket for ClamAv daemon . . . ");
socket.close(); socket.close();
} }
catch (IOException e) catch (IOException e)
{ {
log.error("Exception closing socket", e); log.error("Exception closing socket", e);
} }
} }
/** scan /** scan
* *
* Issue the INSTREAM command and return the response to * Issue the INSTREAM command and return the response to
* and from the clamav daemon * and from the clamav daemon
* *
* @param the bitstream for reporting results * @param the bitstream for reporting results
* @param the InputStream to read * @param the InputStream to read
* @param the item handle for reporting results * @param the item handle for reporting results
* @return a ScanResult representing the server response * @return a ScanResult representing the server response
* @throws IOException * @throws IOException
*/ */
final static byte[] buffer = new byte[DEFAULT_CHUNK_SIZE];; final static byte[] buffer = new byte[DEFAULT_CHUNK_SIZE];;
private int scan(Bitstream bitstream, InputStream inputstream, String itemHandle) private int scan(Bitstream bitstream, InputStream inputstream, String itemHandle)
{ {
try try
{ {
dataOutputStream.write(INSTREAM); dataOutputStream.write(INSTREAM);
} }
catch (IOException e) catch (IOException e)
{ {
log.error("Error writing INSTREAM command . . ."); log.error("Error writing INSTREAM command . . .");
return Curator.CURATE_ERROR; return Curator.CURATE_ERROR;
} }
int read = DEFAULT_CHUNK_SIZE; int read = DEFAULT_CHUNK_SIZE;
while (read == DEFAULT_CHUNK_SIZE) while (read == DEFAULT_CHUNK_SIZE)
{ {
try try
{ {
read = inputstream.read(buffer); read = inputstream.read(buffer);
} }
catch (IOException e) catch (IOException e)
{ {
log.error("Failed attempting to read the InputStream . . . "); log.error("Failed attempting to read the InputStream . . . ");
return Curator.CURATE_ERROR; return Curator.CURATE_ERROR;
} }
if (read == -1) if (read == -1)
{ {
break; break;
} }
try try
{ {
dataOutputStream.writeInt(read); dataOutputStream.writeInt(read);
dataOutputStream.write(buffer, 0, read); dataOutputStream.write(buffer, 0, read);
} }
catch (IOException e) catch (IOException e)
{ {
log.error("Could not write to the socket . . . "); log.error("Could not write to the socket . . . ");
return Curator.CURATE_ERROR; return Curator.CURATE_ERROR;
} }
} }
try try
{ {
dataOutputStream.writeInt(0); dataOutputStream.writeInt(0);
dataOutputStream.flush(); dataOutputStream.flush();
} }
catch (IOException e) catch (IOException e)
{ {
log.error("Error writing zero-length chunk to socket") ; log.error("Error writing zero-length chunk to socket") ;
return Curator.CURATE_ERROR; return Curator.CURATE_ERROR;
} }
try try
{ {
read = socket.getInputStream().read(buffer); read = socket.getInputStream().read(buffer);
} }
catch (IOException e) catch (IOException e)
{ {
log.error( "Error reading result from socket"); log.error( "Error reading result from socket");
return Curator.CURATE_ERROR; return Curator.CURATE_ERROR;
} }
if (read > 0) if (read > 0)
{ {
String response = new String(buffer, 0, read); String response = new String(buffer, 0, read);
logDebugMessage("Response: " + response); logDebugMessage("Response: " + response);
if (response.indexOf("FOUND") != -1) if (response.indexOf("FOUND") != -1)
{ {
String itemMsg = "item - " + itemHandle + ": "; String itemMsg = "item - " + itemHandle + ": ";
String bsMsg = "bitstream - " + bitstream.getName() + String bsMsg = "bitstream - " + bitstream.getName() +
": SequenceId - " + bitstream.getSequenceID() + ": infected"; ": SequenceId - " + bitstream.getSequenceID() + ": infected";
report(itemMsg + bsMsg); report(itemMsg + bsMsg);
results.add(bsMsg); results.add(bsMsg);
return Curator.CURATE_FAIL; return Curator.CURATE_FAIL;
} }
else else
{ {
return Curator.CURATE_SUCCESS; return Curator.CURATE_SUCCESS;
} }
} }
return Curator.CURATE_ERROR; return Curator.CURATE_ERROR;
} }
private void formatResults(Item item) throws IOException private void formatResults(Item item) throws IOException
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("Item: ").append(getItemHandle(item)).append(" "); sb.append("Item: ").append(getItemHandle(item)).append(" ");
if (status == Curator.CURATE_FAIL) if (status == Curator.CURATE_FAIL)
{ {
sb.append(INFECTED_MESSAGE); sb.append(INFECTED_MESSAGE);
int count = 0; int count = 0;
for (String scanresult : results) for (String scanresult : results)
{ {
sb.append("\n").append(scanresult).append("\n"); sb.append("\n").append(scanresult).append("\n");
count++; count++;
} }
sb.append(count).append(" virus(es) found. ") sb.append(count).append(" virus(es) found. ")
.append(" failfast: ").append(failfast); .append(" failfast: ").append(failfast);
} }
else else
{ {
sb.append(CLEAN_MESSAGE); sb.append(CLEAN_MESSAGE);
} }
setResult(sb.toString()); setResult(sb.toString());
} }
private static String getItemHandle(Item item) private static String getItemHandle(Item item)
{ {
String handle = item.getHandle(); String handle = item.getHandle();
return (handle != null) ? handle: NEW_ITEM_HANDLE; return (handle != null) ? handle: NEW_ITEM_HANDLE;
} }
private void logDebugMessage(String message) private void logDebugMessage(String message)
{ {
if (log.isDebugEnabled()) if (log.isDebugEnabled())
{ {
log.debug(message); log.debug(message);
} }
} }
} }

View File

@@ -24,7 +24,6 @@ import org.dspace.content.Site;
import org.dspace.core.Constants; import org.dspace.core.Constants;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.core.PluginManager; import org.dspace.core.PluginManager;
import org.dspace.eperson.EPerson;
import org.dspace.handle.HandleManager; import org.dspace.handle.HandleManager;
/** /**
@@ -365,19 +364,27 @@ public class Curator
} }
/** /**
* Returns the context object used in the current curation performance. * Returns the context object used in the current curation thread.
* This is primarily a utility method to allow tasks access to the context when necessary. * This is primarily a utility method to allow tasks access to the context when necessary.
* <P> * <P>
* If the context is null or not set, then this just returns * If the context is null or not set, then this just returns
* a brand new Context object representing an Anonymous User. * a brand new Context object representing an Anonymous User.
* *
* @return curation Context object (or anonymous Context if curation is null) * @return curation thread's Context object (or a new, anonymous Context if no curation Context exists)
*/ */
public static Context curationContext() throws SQLException public static Context curationContext() throws SQLException
{ {
// Return curation context or new context if undefined // Return curation context or new context if undefined/invalid
Context curCtx = curationCtx.get(); Context curCtx = curationCtx.get();
return (curCtx != null) ? curCtx : new Context();
if(curCtx==null || !curCtx.isValid())
{
//Create a new context (represents an Anonymous User)
curCtx = new Context();
//Save it to current execution thread
curationCtx.set(curCtx);
}
return curCtx;
} }
/** /**
@@ -403,10 +410,12 @@ public class Curator
Context ctx = null; Context ctx = null;
try try
{ {
ctx = curationContext(); //get access to the curation thread's current context
ctx = curationContext();
// Site-wide Tasks really should have an EPerson performer associated with them, // Site-wide Tasks really should have an EPerson performer associated with them,
// otherwise they are run as an "anonymous" user with limited access rights. // otherwise they are run as an "anonymous" user with limited access rights.
if(ctx.getCurrentUser()==null) if(ctx.getCurrentUser()==null && !ctx.ignoreAuthorization())
{ {
log.warn("You are running one or more Site-Wide curation tasks in ANONYMOUS USER mode," + log.warn("You are running one or more Site-Wide curation tasks in ANONYMOUS USER mode," +
" as there is no EPerson 'performer' associated with this task. To associate an EPerson 'performer' " + " as there is no EPerson 'performer' associated with this task. To associate an EPerson 'performer' " +
@@ -428,16 +437,9 @@ public class Curator
return false; return false;
} }
} }
//complete & close our created Context
ctx.complete();
} }
catch (SQLException sqlE) catch (SQLException sqlE)
{ {
//abort Context & all changes
if(ctx!=null)
ctx.abort();
throw new IOException(sqlE); throw new IOException(sqlE);
} }
@@ -534,7 +536,7 @@ public class Curator
} }
catch (SQLException sqlE) catch (SQLException sqlE)
{ {
throw new IOException(sqlE.getMessage()); throw new IOException(sqlE.getMessage(), sqlE);
} }
} }
} }

View File

@@ -12,10 +12,12 @@ import java.sql.SQLException;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import java.util.TimeZone;
import javax.mail.MessagingException; import javax.mail.MessagingException;
@@ -343,15 +345,23 @@ public class Subscribe
ResourceBundle labels = ResourceBundle.getBundle("Messages", supportedLocale); ResourceBundle labels = ResourceBundle.getBundle("Messages", supportedLocale);
// Get the start and end dates for yesterday // Get the start and end dates for yesterday
Date thisTimeYesterday = new Date(System.currentTimeMillis()
- (24 * 60 * 60 * 1000));
DCDate dcDateYesterday = new DCDate(thisTimeYesterday); // The date should reflect the timezone as well. Otherwise we stand to lose that information
// in truncation and roll to an earlier date than intended.
Calendar cal = Calendar.getInstance(TimeZone.getDefault());
cal.setTime(new Date());
// What we actually want to pass to Harvest is "Midnight of yesterday in my current timezone"
// Truncation will actually pass in "Midnight of yesterday in UTC", which will be,
// at least in CDT, "7pm, the day before yesterday, in my current timezone".
cal.add(Calendar.HOUR, -24);
Date thisTimeYesterday = cal.getTime();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
Date midnightYesterday = cal.getTime();
// this time yesterday in ISO 8601, stripping the time
String isoDateYesterday = dcDateYesterday.toString().substring(0, 10);
String startDate = isoDateYesterday;
// FIXME: text of email should be more configurable from an // FIXME: text of email should be more configurable from an
// i18n viewpoint // i18n viewpoint
@@ -366,7 +376,7 @@ public class Subscribe
boolean includeAll = ConfigurationManager.getBooleanProperty("harvest.includerestricted.subscription", true); boolean includeAll = ConfigurationManager.getBooleanProperty("harvest.includerestricted.subscription", true);
// we harvest all the changed item from yesterday until now // we harvest all the changed item from yesterday until now
List<HarvestedItemInfo> itemInfos = Harvest.harvest(context, c, startDate, null, 0, // Limit List<HarvestedItemInfo> itemInfos = Harvest.harvest(context, c, new DCDate(midnightYesterday).toString(), null, 0, // Limit
// and // and
// offset // offset
// zero, // zero,

View File

@@ -1,421 +1,421 @@
/** /**
* The contents of this file are subject to the license and copyright * The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source * detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at * tree and available online at
* *
* http://www.dspace.org/license/ * http://www.dspace.org/license/
*/ */
package org.dspace.harvest; package org.dspace.harvest;
import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeException;
import org.dspace.core.ConfigurationManager; import org.dspace.core.ConfigurationManager;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.storage.rdbms.DatabaseManager; import org.dspace.storage.rdbms.DatabaseManager;
import org.dspace.storage.rdbms.TableRowIterator; import org.dspace.storage.rdbms.TableRowIterator;
import org.dspace.storage.rdbms.TableRow; import org.dspace.storage.rdbms.TableRow;
import java.io.IOException; import java.io.IOException;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
/** /**
* @author Alexey Maslov * @author Alexey Maslov
*/ */
public class HarvestedCollection public class HarvestedCollection
{ {
private Context context; private Context context;
private TableRow harvestRow; private TableRow harvestRow;
public static final int TYPE_NONE = 0; public static final int TYPE_NONE = 0;
public static final int TYPE_DMD = 1; public static final int TYPE_DMD = 1;
public static final int TYPE_DMDREF = 2; public static final int TYPE_DMDREF = 2;
public static final int TYPE_FULL = 3; public static final int TYPE_FULL = 3;
public static final int STATUS_READY = 0; public static final int STATUS_READY = 0;
public static final int STATUS_BUSY = 1; public static final int STATUS_BUSY = 1;
public static final int STATUS_QUEUED = 2; public static final int STATUS_QUEUED = 2;
public static final int STATUS_OAI_ERROR = 3; public static final int STATUS_OAI_ERROR = 3;
public static final int STATUS_UNKNOWN_ERROR = -1; public static final int STATUS_UNKNOWN_ERROR = -1;
/* /*
* collection_id | integer | not null * collection_id | integer | not null
harvest_type | integer | harvest_type | integer |
oai_source | text | oai_source | text |
oai_set_id | text | oai_set_id | text |
harvest_message | text | harvest_message | text |
metadata_config_id | text | metadata_config_id | text |
harvest_status | integer | harvest_status | integer |
harvest_start_time | timestamp with time zone | harvest_start_time | timestamp with time zone |
*/ */
// TODO: make sure this guy knows to lock people out if the status is not zero. // TODO: make sure this guy knows to lock people out if the status is not zero.
// i.e. someone editing a collection's setting from the admin menu should have // i.e. someone editing a collection's setting from the admin menu should have
// to stop an ongoing harvest before they can edit the settings. // to stop an ongoing harvest before they can edit the settings.
HarvestedCollection(Context c, TableRow row) HarvestedCollection(Context c, TableRow row)
{ {
context = c; context = c;
harvestRow = row; harvestRow = row;
} }
public static void exists(Context c) throws SQLException { public static void exists(Context c) throws SQLException {
DatabaseManager.queryTable(c, "harvested_collection", "SELECT COUNT(*) FROM harvested_collection"); DatabaseManager.queryTable(c, "harvested_collection", "SELECT COUNT(*) FROM harvested_collection");
} }
/** /**
* Find the harvest settings corresponding to this collection * Find the harvest settings corresponding to this collection
* @return a HarvestInstance object corresponding to this collection's settings, null if not found. * @return a HarvestInstance object corresponding to this collection's settings, null if not found.
*/ */
public static HarvestedCollection find(Context c, int collectionId) throws SQLException public static HarvestedCollection find(Context c, int collectionId) throws SQLException
{ {
TableRow row = DatabaseManager.findByUnique(c, "harvested_collection", "collection_id", collectionId); TableRow row = DatabaseManager.findByUnique(c, "harvested_collection", "collection_id", collectionId);
if (row == null) { if (row == null) {
return null; return null;
} }
return new HarvestedCollection(c, row); return new HarvestedCollection(c, row);
} }
/** /**
* Create a new harvest instance row for a specified collection. * Create a new harvest instance row for a specified collection.
* @return a new HarvestInstance object * @return a new HarvestInstance object
*/ */
public static HarvestedCollection create(Context c, int collectionId) throws SQLException { public static HarvestedCollection create(Context c, int collectionId) throws SQLException {
TableRow row = DatabaseManager.row("harvested_collection"); TableRow row = DatabaseManager.row("harvested_collection");
row.setColumn("collection_id", collectionId); row.setColumn("collection_id", collectionId);
row.setColumn("harvest_type", 0); row.setColumn("harvest_type", 0);
DatabaseManager.insert(c, row); DatabaseManager.insert(c, row);
return new HarvestedCollection(c, row); return new HarvestedCollection(c, row);
} }
/** Returns whether the specified collection is harvestable, i.e. whether its harvesting /** Returns whether the specified collection is harvestable, i.e. whether its harvesting
* options are set up correctly. This is distinct from "ready", since this collection may * options are set up correctly. This is distinct from "ready", since this collection may
* be in process of being harvested. * be in process of being harvested.
*/ */
public static boolean isHarvestable(Context c, int collectionId) throws SQLException public static boolean isHarvestable(Context c, int collectionId) throws SQLException
{ {
HarvestedCollection hc = HarvestedCollection.find(c, collectionId); HarvestedCollection hc = HarvestedCollection.find(c, collectionId);
if (hc != null && hc.getHarvestType() > 0 && hc.getOaiSource() != null && hc.getOaiSetId() != null && if (hc != null && hc.getHarvestType() > 0 && hc.getOaiSource() != null && hc.getOaiSetId() != null &&
hc.getHarvestStatus() != HarvestedCollection.STATUS_UNKNOWN_ERROR) { hc.getHarvestStatus() != HarvestedCollection.STATUS_UNKNOWN_ERROR) {
return true; return true;
} }
return false; return false;
} }
/** Returns whether this harvest instance is actually harvestable, i.e. whether its settings /** Returns whether this harvest instance is actually harvestable, i.e. whether its settings
* options are set up correctly. This is distinct from "ready", since this collection may * options are set up correctly. This is distinct from "ready", since this collection may
* be in process of being harvested. * be in process of being harvested.
*/ */
public boolean isHarvestable() throws SQLException public boolean isHarvestable() throws SQLException
{ {
if (this.getHarvestType() > 0 && this.getOaiSource() != null && this.getOaiSetId() != null && if (this.getHarvestType() > 0 && this.getOaiSource() != null && this.getOaiSetId() != null &&
this.getHarvestStatus() != HarvestedCollection.STATUS_UNKNOWN_ERROR) { this.getHarvestStatus() != HarvestedCollection.STATUS_UNKNOWN_ERROR) {
return true; return true;
} }
return false; return false;
} }
/** Returns whether the specified collection is ready for immediate harvest. /** Returns whether the specified collection is ready for immediate harvest.
*/ */
public static boolean isReady(Context c, int collectionId) throws SQLException public static boolean isReady(Context c, int collectionId) throws SQLException
{ {
HarvestedCollection hc = HarvestedCollection.find(c, collectionId); HarvestedCollection hc = HarvestedCollection.find(c, collectionId);
return hc.isReady(); return hc.isReady();
} }
public boolean isReady() throws SQLException public boolean isReady() throws SQLException
{ {
if (this.isHarvestable() && (this.getHarvestStatus() == HarvestedCollection.STATUS_READY || this.getHarvestStatus() == HarvestedCollection.STATUS_OAI_ERROR)) if (this.isHarvestable() && (this.getHarvestStatus() == HarvestedCollection.STATUS_READY || this.getHarvestStatus() == HarvestedCollection.STATUS_OAI_ERROR))
{ {
return true; return true;
} }
return false; return false;
} }
/** Find all collections that are set up for harvesting /** Find all collections that are set up for harvesting
* *
* return: list of collection id's * return: list of collection id's
* @throws SQLException * @throws SQLException
*/ */
public static List<Integer> findAll(Context c) throws SQLException public static List<Integer> findAll(Context c) throws SQLException
{ {
TableRowIterator tri = DatabaseManager.queryTable(c, "harvested_collection", TableRowIterator tri = DatabaseManager.queryTable(c, "harvested_collection",
"SELECT * FROM harvested_collection"); "SELECT * FROM harvested_collection");
List<Integer> collectionIds = new ArrayList<Integer>(); List<Integer> collectionIds = new ArrayList<Integer>();
while (tri.hasNext()) while (tri.hasNext())
{ {
TableRow row = tri.next(); TableRow row = tri.next();
collectionIds.add(row.getIntColumn("collection_id")); collectionIds.add(row.getIntColumn("collection_id"));
} }
return collectionIds; return collectionIds;
} }
/** Find all collections that are ready for harvesting /** Find all collections that are ready for harvesting
* *
* return: list of collection id's * return: list of collection id's
* @throws SQLException * @throws SQLException
*/ */
public static List<Integer> findReady(Context c) throws SQLException public static List<Integer> findReady(Context c) throws SQLException
{ {
int harvestInterval = ConfigurationManager.getIntProperty("oai", "harvester.harvestFrequency"); int harvestInterval = ConfigurationManager.getIntProperty("oai", "harvester.harvestFrequency");
if (harvestInterval == 0) if (harvestInterval == 0)
{ {
harvestInterval = 720; harvestInterval = 720;
} }
int expirationInterval = ConfigurationManager.getIntProperty("oai", "harvester.threadTimeout"); int expirationInterval = ConfigurationManager.getIntProperty("oai", "harvester.threadTimeout");
if (expirationInterval == 0) if (expirationInterval == 0)
{ {
expirationInterval = 24; expirationInterval = 24;
} }
Date startTime; Date startTime;
Date expirationTime; Date expirationTime;
Calendar calendar = Calendar.getInstance(); Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date()); calendar.setTime(new Date());
calendar.add(Calendar.MINUTE, -1 * harvestInterval); calendar.add(Calendar.MINUTE, -1 * harvestInterval);
startTime = calendar.getTime(); startTime = calendar.getTime();
calendar.setTime(startTime); calendar.setTime(startTime);
calendar.add(Calendar.HOUR, -2 * expirationInterval); calendar.add(Calendar.HOUR, -2 * expirationInterval);
expirationTime = calendar.getTime(); expirationTime = calendar.getTime();
/* Select all collections whose last_harvest is before our start time, whose harvest_type *is not* 0 and whose status *is* 0 (available) or 3 (OAI Error). */ /* Select all collections whose last_harvest is before our start time, whose harvest_type *is not* 0 and whose status *is* 0 (available) or 3 (OAI Error). */
TableRowIterator tri = DatabaseManager.queryTable(c, "harvested_collection", TableRowIterator tri = DatabaseManager.queryTable(c, "harvested_collection",
"SELECT * FROM harvested_collection WHERE (last_harvested < ? or last_harvested is null) and harvest_type > ? and (harvest_status = ? or harvest_status = ? or (harvest_status=? and harvest_start_time < ?)) ORDER BY last_harvested", "SELECT * FROM harvested_collection WHERE (last_harvested < ? or last_harvested is null) and harvest_type > ? and (harvest_status = ? or harvest_status = ? or (harvest_status=? and harvest_start_time < ?)) ORDER BY last_harvested",
new java.sql.Timestamp(startTime.getTime()), 0, HarvestedCollection.STATUS_READY, HarvestedCollection.STATUS_OAI_ERROR, HarvestedCollection.STATUS_BUSY, new java.sql.Timestamp(expirationTime.getTime())); new java.sql.Timestamp(startTime.getTime()), 0, HarvestedCollection.STATUS_READY, HarvestedCollection.STATUS_OAI_ERROR, HarvestedCollection.STATUS_BUSY, new java.sql.Timestamp(expirationTime.getTime()));
List<Integer> collectionIds = new ArrayList<Integer>(); List<Integer> collectionIds = new ArrayList<Integer>();
while (tri.hasNext()) while (tri.hasNext())
{ {
TableRow row = tri.next(); TableRow row = tri.next();
collectionIds.add(row.getIntColumn("collection_id")); collectionIds.add(row.getIntColumn("collection_id"));
} }
return collectionIds; return collectionIds;
} }
/** /**
* Find all collections with the specified status flag * Find all collections with the specified status flag
* @param c * @param c
* @param status see HarvestInstance.STATUS_... * @param status see HarvestInstance.STATUS_...
* @return * @return
* @throws SQLException * @throws SQLException
*/ */
public static List<Integer> findByStatus(Context c, int status) throws SQLException { public static List<Integer> findByStatus(Context c, int status) throws SQLException {
TableRowIterator tri = DatabaseManager.queryTable(c, "harvested_collection", TableRowIterator tri = DatabaseManager.queryTable(c, "harvested_collection",
"SELECT * FROM harvested_collection WHERE harvest_status = ?", status); "SELECT * FROM harvested_collection WHERE harvest_status = ?", status);
List<Integer> collectionIds = new ArrayList<Integer>(); List<Integer> collectionIds = new ArrayList<Integer>();
while (tri.hasNext()) while (tri.hasNext())
{ {
TableRow row = tri.next(); TableRow row = tri.next();
collectionIds.add(row.getIntColumn("collection_id")); collectionIds.add(row.getIntColumn("collection_id"));
} }
return collectionIds; return collectionIds;
} }
/** Find the collection that was harvested the longest time ago. /** Find the collection that was harvested the longest time ago.
* @throws SQLException * @throws SQLException
*/ */
public static Integer findOldestHarvest (Context c) throws SQLException { public static Integer findOldestHarvest (Context c) throws SQLException {
String query = "select collection_id from harvested_collection where harvest_type > ? and harvest_status = ? order by last_harvested asc limit 1"; String query = "select collection_id from harvested_collection where harvest_type > ? and harvest_status = ? order by last_harvested asc limit 1";
if ("oracle".equals(ConfigurationManager.getProperty("db.name"))) if ("oracle".equals(ConfigurationManager.getProperty("db.name")))
{ {
query = "select collection_id from harvested_collection where harvest_type > ? and harvest_status = ? and rownum <= 1 order by last_harvested asc"; query = "select collection_id from harvested_collection where harvest_type > ? and harvest_status = ? and rownum <= 1 order by last_harvested asc";
} }
TableRowIterator tri = DatabaseManager.queryTable(c, "harvested_collection", TableRowIterator tri = DatabaseManager.queryTable(c, "harvested_collection",
query, 0, 0); query, 0, 0);
TableRow row = tri.next(); TableRow row = tri.next();
if (row != null) if (row != null)
{ {
return row.getIntColumn("collection_id"); return row.getIntColumn("collection_id");
} }
else else
{ {
return -1; return -1;
} }
} }
/** Find the collection that was harvested most recently. /** Find the collection that was harvested most recently.
* @throws SQLException * @throws SQLException
*/ */
public static Integer findNewestHarvest (Context c) throws SQLException { public static Integer findNewestHarvest (Context c) throws SQLException {
String query = "select collection_id from harvested_collection where harvest_type > ? and harvest_status = ? order by last_harvested desc limit 1"; String query = "select collection_id from harvested_collection where harvest_type > ? and harvest_status = ? order by last_harvested desc limit 1";
if ("oracle".equals(ConfigurationManager.getProperty("db.name"))) if ("oracle".equals(ConfigurationManager.getProperty("db.name")))
{ {
query = "select collection_id from harvested_collection where harvest_type > ? and harvest_status = ? and rownum <= 1 order by last_harvested desc"; query = "select collection_id from harvested_collection where harvest_type > ? and harvest_status = ? and rownum <= 1 order by last_harvested desc";
} }
TableRowIterator tri = DatabaseManager.queryTable(c, "harvested_collection", TableRowIterator tri = DatabaseManager.queryTable(c, "harvested_collection",
query , 0, 0); query , 0, 0);
TableRow row = tri.next(); TableRow row = tri.next();
if (row != null) if (row != null)
{ {
return row.getIntColumn("collection_id"); return row.getIntColumn("collection_id");
} }
else else
{ {
return -1; return -1;
} }
} }
/** /**
* A function to set all harvesting-related parameters at once * A function to set all harvesting-related parameters at once
*/ */
public void setHarvestParams(int type, String oaiSource, String oaiSetId, String mdConfigId) { public void setHarvestParams(int type, String oaiSource, String oaiSetId, String mdConfigId) {
setHarvestType(type); setHarvestType(type);
setOaiSource(oaiSource); setOaiSource(oaiSource);
setOaiSetId(oaiSetId); setOaiSetId(oaiSetId);
setHarvestMetadataConfig(mdConfigId); setHarvestMetadataConfig(mdConfigId);
} }
/* Setters for the appropriate harvesting-related columns */ /* Setters for the appropriate harvesting-related columns */
public void setHarvestType(int type) { public void setHarvestType(int type) {
harvestRow.setColumn("harvest_type",type); harvestRow.setColumn("harvest_type",type);
} }
/** /**
* Sets the current status of the collection. * Sets the current status of the collection.
* *
* @param status a HarvestInstance.STATUS_... constant * @param status a HarvestInstance.STATUS_... constant
*/ */
public void setHarvestStatus(int status) { public void setHarvestStatus(int status) {
harvestRow.setColumn("harvest_status",status); harvestRow.setColumn("harvest_status",status);
} }
public void setOaiSource(String oaiSource) { public void setOaiSource(String oaiSource) {
if (oaiSource == null || oaiSource.length() == 0) { if (oaiSource == null || oaiSource.length() == 0) {
harvestRow.setColumnNull("oai_source"); harvestRow.setColumnNull("oai_source");
} }
else { else {
harvestRow.setColumn("oai_source",oaiSource); harvestRow.setColumn("oai_source",oaiSource);
} }
} }
public void setOaiSetId(String oaiSetId) { public void setOaiSetId(String oaiSetId) {
if (oaiSetId == null || oaiSetId.length() == 0) { if (oaiSetId == null || oaiSetId.length() == 0) {
harvestRow.setColumnNull("oai_set_id"); harvestRow.setColumnNull("oai_set_id");
} }
else { else {
harvestRow.setColumn("oai_set_id",oaiSetId); harvestRow.setColumn("oai_set_id",oaiSetId);
} }
} }
public void setHarvestMetadataConfig(String mdConfigId) { public void setHarvestMetadataConfig(String mdConfigId) {
if (mdConfigId == null || mdConfigId.length() == 0) { if (mdConfigId == null || mdConfigId.length() == 0) {
harvestRow.setColumnNull("metadata_config_id"); harvestRow.setColumnNull("metadata_config_id");
} }
else { else {
harvestRow.setColumn("metadata_config_id",mdConfigId); harvestRow.setColumn("metadata_config_id",mdConfigId);
} }
} }
public void setHarvestResult(Date date, String message) { public void setHarvestResult(Date date, String message) {
if (date == null) { if (date == null) {
harvestRow.setColumnNull("last_harvested"); harvestRow.setColumnNull("last_harvested");
} else { } else {
harvestRow.setColumn("last_harvested", date); harvestRow.setColumn("last_harvested", date);
} }
if (message == null || message.length() == 0) { if (message == null || message.length() == 0) {
harvestRow.setColumnNull("harvest_message"); harvestRow.setColumnNull("harvest_message");
} else { } else {
harvestRow.setColumn("harvest_message", message); harvestRow.setColumn("harvest_message", message);
} }
} }
public void setHarvestMessage(String message) { public void setHarvestMessage(String message) {
if (message == null || message.length() == 0) { if (message == null || message.length() == 0) {
harvestRow.setColumnNull("harvest_message"); harvestRow.setColumnNull("harvest_message");
} else { } else {
harvestRow.setColumn("harvest_message", message); harvestRow.setColumn("harvest_message", message);
} }
} }
public void setHarvestStartTime(Date date) { public void setHarvestStartTime(Date date) {
if (date == null) { if (date == null) {
harvestRow.setColumnNull("harvest_start_time"); harvestRow.setColumnNull("harvest_start_time");
} else { } else {
harvestRow.setColumn("harvest_start_time", date); harvestRow.setColumn("harvest_start_time", date);
} }
} }
/* Getting for the appropriate harvesting-related columns */ /* Getting for the appropriate harvesting-related columns */
public int getCollectionId() { public int getCollectionId() {
return harvestRow.getIntColumn("collection_id"); return harvestRow.getIntColumn("collection_id");
} }
public int getHarvestType() { public int getHarvestType() {
return harvestRow.getIntColumn("harvest_type"); return harvestRow.getIntColumn("harvest_type");
} }
public int getHarvestStatus() { public int getHarvestStatus() {
return harvestRow.getIntColumn("harvest_status"); return harvestRow.getIntColumn("harvest_status");
} }
public String getOaiSource() { public String getOaiSource() {
return harvestRow.getStringColumn("oai_source"); return harvestRow.getStringColumn("oai_source");
} }
public String getOaiSetId() { public String getOaiSetId() {
return harvestRow.getStringColumn("oai_set_id"); return harvestRow.getStringColumn("oai_set_id");
} }
public String getHarvestMetadataConfig() { public String getHarvestMetadataConfig() {
return harvestRow.getStringColumn("metadata_config_id"); return harvestRow.getStringColumn("metadata_config_id");
} }
public String getHarvestMessage() { public String getHarvestMessage() {
return harvestRow.getStringColumn("harvest_message"); return harvestRow.getStringColumn("harvest_message");
} }
public Date getHarvestDate() { public Date getHarvestDate() {
return harvestRow.getDateColumn("last_harvested"); return harvestRow.getDateColumn("last_harvested");
} }
public Date getHarvestStartTime() { public Date getHarvestStartTime() {
return harvestRow.getDateColumn("harvest_start_time"); return harvestRow.getDateColumn("harvest_start_time");
} }
public void delete() throws SQLException { public void delete() throws SQLException {
DatabaseManager.delete(context, harvestRow); DatabaseManager.delete(context, harvestRow);
} }
public void update() throws SQLException, IOException, AuthorizeException public void update() throws SQLException, IOException, AuthorizeException
{ {
DatabaseManager.update(context, harvestRow); DatabaseManager.update(context, harvestRow);
} }
} }

View File

@@ -1,171 +1,171 @@
/** /**
* The contents of this file are subject to the license and copyright * The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source * detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at * tree and available online at
* *
* http://www.dspace.org/license/ * http://www.dspace.org/license/
*/ */
package org.dspace.harvest; package org.dspace.harvest;
import java.io.IOException; import java.io.IOException;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Date; import java.util.Date;
import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.storage.rdbms.DatabaseManager; import org.dspace.storage.rdbms.DatabaseManager;
import org.dspace.storage.rdbms.TableRow; import org.dspace.storage.rdbms.TableRow;
import org.dspace.storage.rdbms.TableRowIterator; import org.dspace.storage.rdbms.TableRowIterator;
/** /**
* @author Alexey Maslov * @author Alexey Maslov
*/ */
public class HarvestedItem public class HarvestedItem
{ {
private Context context; private Context context;
private TableRow harvestRow; private TableRow harvestRow;
HarvestedItem(Context c, TableRow row) HarvestedItem(Context c, TableRow row)
{ {
context = c; context = c;
harvestRow = row; harvestRow = row;
} }
public static void exists(Context c) throws SQLException { public static void exists(Context c) throws SQLException {
DatabaseManager.queryTable(c, "harvested_item", "SELECT COUNT(*) FROM harvested_item"); DatabaseManager.queryTable(c, "harvested_item", "SELECT COUNT(*) FROM harvested_item");
} }
/** /**
* Find the harvest parameters corresponding to the specified DSpace item * Find the harvest parameters corresponding to the specified DSpace item
* @return a HarvestedItem object corresponding to this item, null if not found. * @return a HarvestedItem object corresponding to this item, null if not found.
*/ */
public static HarvestedItem find(Context c, int item_id) throws SQLException public static HarvestedItem find(Context c, int item_id) throws SQLException
{ {
TableRow row = DatabaseManager.findByUnique(c, "harvested_item", "item_id", item_id); TableRow row = DatabaseManager.findByUnique(c, "harvested_item", "item_id", item_id);
if (row == null) { if (row == null) {
return null; return null;
} }
return new HarvestedItem(c, row); return new HarvestedItem(c, row);
} }
/* /*
* select foo.item_id from (select item.item_id, item.owning_collection from item join item2bundle on item.item_id=item2bundle.item_id where item2bundle.bundle_id=22) as foo join collection on foo.owning_collection=collection.collection_id where collection.collection_id=5; * select foo.item_id from (select item.item_id, item.owning_collection from item join item2bundle on item.item_id=item2bundle.item_id where item2bundle.bundle_id=22) as foo join collection on foo.owning_collection=collection.collection_id where collection.collection_id=5;
*/ */
/** /**
* Retrieve a DSpace Item that corresponds to this particular combination of owning collection and OAI ID. * Retrieve a DSpace Item that corresponds to this particular combination of owning collection and OAI ID.
* @param context * @param context
* @param itemOaiID the string used by the OAI-PMH provider to identify the item * @param itemOaiID the string used by the OAI-PMH provider to identify the item
* @param collectionID id of the local collection that the item should be found in * @param collectionID id of the local collection that the item should be found in
* @return DSpace Item or null if no item was found * @return DSpace Item or null if no item was found
*/ */
public static Item getItemByOAIId(Context context, String itemOaiID, int collectionID) throws SQLException public static Item getItemByOAIId(Context context, String itemOaiID, int collectionID) throws SQLException
{ {
/* /*
* FYI: This method has to be scoped to a collection. Otherwise, we could have collisions as more * FYI: This method has to be scoped to a collection. Otherwise, we could have collisions as more
* than one collection might be importing the same item. That is OAI_ID's might be unique to the * than one collection might be importing the same item. That is OAI_ID's might be unique to the
* provider but not to the harvester. * provider but not to the harvester.
*/ */
Item resolvedItem = null; Item resolvedItem = null;
TableRowIterator tri = null; TableRowIterator tri = null;
final String selectItemFromOaiId = "SELECT dsi.item_id FROM " + final String selectItemFromOaiId = "SELECT dsi.item_id FROM " +
"(SELECT item.item_id, item.owning_collection FROM item JOIN harvested_item ON item.item_id=harvested_item.item_id WHERE harvested_item.oai_id=?) " + "(SELECT item.item_id, item.owning_collection FROM item JOIN harvested_item ON item.item_id=harvested_item.item_id WHERE harvested_item.oai_id=?) " +
"dsi JOIN collection ON dsi.owning_collection=collection.collection_id WHERE collection.collection_id=?"; "dsi JOIN collection ON dsi.owning_collection=collection.collection_id WHERE collection.collection_id=?";
try try
{ {
tri = DatabaseManager.query(context, selectItemFromOaiId, itemOaiID, collectionID); tri = DatabaseManager.query(context, selectItemFromOaiId, itemOaiID, collectionID);
if (tri.hasNext()) if (tri.hasNext())
{ {
TableRow row = tri.next(); TableRow row = tri.next();
int itemID = row.getIntColumn("item_id"); int itemID = row.getIntColumn("item_id");
resolvedItem = Item.find(context, itemID); resolvedItem = Item.find(context, itemID);
} }
else { else {
return null; return null;
} }
} }
finally { finally {
if (tri != null) if (tri != null)
{ {
tri.close(); tri.close();
} }
} }
return resolvedItem; return resolvedItem;
} }
/** /**
* Create a new harvested item row for a specified item id. * Create a new harvested item row for a specified item id.
* @return a new HarvestedItem object * @return a new HarvestedItem object
*/ */
public static HarvestedItem create(Context c, int itemId, String itemOAIid) throws SQLException { public static HarvestedItem create(Context c, int itemId, String itemOAIid) throws SQLException {
TableRow row = DatabaseManager.row("harvested_item"); TableRow row = DatabaseManager.row("harvested_item");
row.setColumn("item_id", itemId); row.setColumn("item_id", itemId);
row.setColumn("oai_id", itemOAIid); row.setColumn("oai_id", itemOAIid);
DatabaseManager.insert(c, row); DatabaseManager.insert(c, row);
return new HarvestedItem(c, row); return new HarvestedItem(c, row);
} }
public String getItemID() public String getItemID()
{ {
String oai_id = harvestRow.getStringColumn("item_id"); String oai_id = harvestRow.getStringColumn("item_id");
return oai_id; return oai_id;
} }
/** /**
* Get the oai_id associated with this item * Get the oai_id associated with this item
*/ */
public String getOaiID() public String getOaiID()
{ {
String oai_id = harvestRow.getStringColumn("oai_id"); String oai_id = harvestRow.getStringColumn("oai_id");
return oai_id; return oai_id;
} }
/** /**
* Set the oai_id associated with this item * Set the oai_id associated with this item
*/ */
public void setOaiID(String itemOaiID) public void setOaiID(String itemOaiID)
{ {
harvestRow.setColumn("oai_id",itemOaiID); harvestRow.setColumn("oai_id",itemOaiID);
return; return;
} }
public void setHarvestDate(Date date) { public void setHarvestDate(Date date) {
if (date == null) { if (date == null) {
date = new Date(); date = new Date();
} }
harvestRow.setColumn("last_harvested", date); harvestRow.setColumn("last_harvested", date);
} }
public Date getHarvestDate() { public Date getHarvestDate() {
return harvestRow.getDateColumn("last_harvested"); return harvestRow.getDateColumn("last_harvested");
} }
public void delete() throws SQLException { public void delete() throws SQLException {
DatabaseManager.delete(context, harvestRow); DatabaseManager.delete(context, harvestRow);
} }
public void update() throws SQLException, IOException, AuthorizeException { public void update() throws SQLException, IOException, AuthorizeException {
DatabaseManager.update(context, harvestRow); DatabaseManager.update(context, harvestRow);
} }
} }

View File

@@ -7,16 +7,11 @@
*/ */
package org.dspace.license; package org.dspace.license;
import java.io.InputStream; import java.io.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.net.URL; import java.net.URL;
import java.net.URLConnection; import java.net.URLConnection;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator;
import javax.xml.transform.Templates; import javax.xml.transform.Templates;
import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerConfigurationException;
@@ -25,6 +20,7 @@ import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource; import javax.xml.transform.stream.StreamSource;
import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Bitstream; import org.dspace.content.Bitstream;
import org.dspace.content.BitstreamFormat; import org.dspace.content.BitstreamFormat;
@@ -34,10 +30,12 @@ import org.dspace.content.Item;
import org.dspace.core.ConfigurationManager; import org.dspace.core.ConfigurationManager;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.core.Utils; import org.dspace.core.Utils;
import org.dspace.license.CCLookup;
public class CreativeCommons public class CreativeCommons
{ {
/** log4j category */
private static Logger log = Logger.getLogger(CreativeCommons.class);
/** /**
* The Bundle Name * The Bundle Name
*/ */
@@ -429,30 +427,23 @@ public class CreativeCommons
{ {
try try
{ {
String line = "";
URL url = new URL(url_string); URL url = new URL(url_string);
URLConnection connection = url.openConnection(); URLConnection connection = url.openConnection();
byte[] bytes = new byte[connection.getContentLength()]; InputStream inputStream = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder sb = new StringBuilder();
// loop and read the data until it's done while ((line = reader.readLine()) != null)
int offset = 0;
while (true)
{ {
int len = connection.getInputStream().read(bytes, offset, sb.append(line);
bytes.length - offset);
if (len == -1)
{
break;
}
offset += len;
} }
return bytes; return sb.toString().getBytes();
} }
catch (Exception exc) catch (Exception exc)
{ {
log.error(exc.getMessage());
return null; return null;
} }
} }

View File

@@ -1,49 +1,49 @@
/** /**
* The contents of this file are subject to the license and copyright * The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source * detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at * tree and available online at
* *
* http://www.dspace.org/license/ * http://www.dspace.org/license/
*/ */
package org.dspace.search; package org.dspace.search;
import java.io.Reader; import java.io.Reader;
import org.apache.lucene.analysis.LowerCaseFilter; import org.apache.lucene.analysis.LowerCaseFilter;
import org.apache.lucene.analysis.StopFilter; import org.apache.lucene.analysis.StopFilter;
import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.Tokenizer; import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.analysis.standard.StandardFilter; import org.apache.lucene.analysis.standard.StandardFilter;
import org.apache.lucene.util.Version; import org.apache.lucene.util.Version;
/** /**
* Custom Lucene Analyzer that combines the standard filter, lowercase filter * Custom Lucene Analyzer that combines the standard filter, lowercase filter
* and stopword filter. Intentionally omits the stemming filter (which is used * and stopword filter. Intentionally omits the stemming filter (which is used
* by DSAnalyzer) * by DSAnalyzer)
*/ */
public class DSNonStemmingAnalyzer extends DSAnalyzer public class DSNonStemmingAnalyzer extends DSAnalyzer
{ {
/** /**
* Builds an analyzer * Builds an analyzer
* *
* @param matchVersion Lucene version to match * @param matchVersion Lucene version to match
*/ */
public DSNonStemmingAnalyzer(Version matchVersion) { public DSNonStemmingAnalyzer(Version matchVersion) {
super(matchVersion); super(matchVersion);
} }
/** /**
* Create a token stream for this analyzer. * Create a token stream for this analyzer.
* This is identical to DSAnalyzer, except it omits the stemming filter * This is identical to DSAnalyzer, except it omits the stemming filter
*/ */
@Override @Override
protected TokenStreamComponents createComponents(String fieldName, Reader reader) { protected TokenStreamComponents createComponents(String fieldName, Reader reader) {
final Tokenizer source = new DSTokenizer(matchVersion, reader); final Tokenizer source = new DSTokenizer(matchVersion, reader);
TokenStream result = new StandardFilter(matchVersion, source); TokenStream result = new StandardFilter(matchVersion, source);
result = new LowerCaseFilter(matchVersion, result); result = new LowerCaseFilter(matchVersion, result);
result = new StopFilter(matchVersion, result, stopSet); result = new StopFilter(matchVersion, result, stopSet);
return new TokenStreamComponents(source, result); return new TokenStreamComponents(source, result);
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,7 @@
<packaging>jar</packaging> <packaging>jar</packaging>
<groupId>org.dspace</groupId> <groupId>org.dspace</groupId>
<artifactId>dspace-discovery-provider</artifactId> <artifactId>dspace-discovery-provider</artifactId>
<version>3.0-SNAPSHOT</version> <version>1.8.3</version>
<name>DSpace Discovery :: Discovery Provider Library</name> <name>DSpace Discovery :: Discovery Provider Library</name>
<description> <description>
@@ -17,10 +17,15 @@
<parent> <parent>
<groupId>org.dspace</groupId> <groupId>org.dspace</groupId>
<artifactId>dspace-discovery</artifactId> <artifactId>dspace-discovery</artifactId>
<version>3.0-SNAPSHOT</version> <version>1.8.3</version>
<relativePath>..</relativePath> <relativePath>..</relativePath>
</parent> </parent>
<properties>
<!-- This is the path to the root [dspace-src] directory. -->
<root.basedir>${basedir}/../..</root.basedir>
</properties>
<dependencies> <dependencies>
<dependency> <dependency>
@@ -98,16 +103,4 @@
</plugins> </plugins>
</build> </build>
<!--
The Subversion repository location is used by Continuum to update
against when changes have occured, this spawns a new build cycle
and releases snapshots into the snapshot repository below.
-->
<scm>
<connection>scm:svn:http://scm.dspace.org/svn/repo/dspace/trunk/dspace-discovery/dspace-discovery-provider</connection>
<developerConnection>
scm:svn:https://scm.dspace.org/svn/repo/dspace/trunk/dspace-discovery/dspace-discovery-provider
</developerConnection>
<url>http://scm.dspace.org/svn/repo/dspace/trunk/dspace-discovery/dspace-discovery-provider</url>
</scm>
</project> </project>

View File

@@ -11,6 +11,7 @@ import org.dspace.content.DSpaceObject;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.discovery.configuration.DiscoverySortConfiguration; import org.dspace.discovery.configuration.DiscoverySortConfiguration;
import java.io.InputStream;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.List; import java.util.List;
@@ -27,9 +28,9 @@ public interface SearchService {
DiscoverResult search(Context context, DSpaceObject dso, DiscoverQuery query) throws SearchServiceException; DiscoverResult search(Context context, DSpaceObject dso, DiscoverQuery query) throws SearchServiceException;
String searchJSON(DiscoverQuery query, String jsonIdentifier) throws SearchServiceException; InputStream searchJSON(DiscoverQuery query, String jsonIdentifier) throws SearchServiceException;
String searchJSON(DiscoverQuery query, DSpaceObject dso, String jsonIdentifier) throws SearchServiceException; InputStream searchJSON(DiscoverQuery query, DSpaceObject dso, String jsonIdentifier) throws SearchServiceException;
List<DSpaceObject> search(Context context, String query, String orderfield, boolean ascending, int offset, int max, String... filterquery); List<DSpaceObject> search(Context context, String query, String orderfield, boolean ascending, int offset, int max, String... filterquery);

View File

@@ -4,16 +4,21 @@
<packaging>jar</packaging> <packaging>jar</packaging>
<groupId>org.dspace</groupId> <groupId>org.dspace</groupId>
<artifactId>dspace-discovery-solr</artifactId> <artifactId>dspace-discovery-solr</artifactId>
<version>3.0-SNAPSHOT</version> <version>1.8.3</version>
<name>DSpace Discovery :: Discovery Solr Implementation</name> <name>DSpace Discovery :: Discovery Solr Implementation</name>
<parent> <parent>
<groupId>org.dspace</groupId> <groupId>org.dspace</groupId>
<artifactId>dspace-discovery</artifactId> <artifactId>dspace-discovery</artifactId>
<version>3.0-SNAPSHOT</version> <version>1.8.3</version>
<relativePath>..</relativePath> <relativePath>..</relativePath>
</parent> </parent>
<properties>
<!-- This is the path to the root [dspace-src] directory. -->
<root.basedir>${basedir}/../..</root.basedir>
</properties>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.dspace</groupId> <groupId>org.dspace</groupId>
@@ -46,16 +51,4 @@
</dependencies> </dependencies>
<!--
The Subversion repository location is used by Continuum to update
against when changes have occured, this spawns a new build cycle
and releases snapshots into the snapshot repository below.
-->
<scm>
<connection>scm:svn:http://scm.dspace.org/svn/repo/dspace/trunk/dspace-discovery/dspace-discovery-solr</connection>
<developerConnection>
scm:svn:https://scm.dspace.org/svn/repo/dspace/trunk/dspace-discovery/dspace-discovery-solr
</developerConnection>
<url>http://scm.dspace.org/svn/repo/dspace/trunk/dspace-discovery/dspace-discovery-solr</url>
</scm>
</project> </project>

View File

@@ -17,6 +17,7 @@ import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer; import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;
import org.apache.solr.client.solrj.response.FacetField; import org.apache.solr.client.solrj.response.FacetField;
import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.util.ClientUtils;
import org.apache.solr.common.SolrDocument; import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList; import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument; import org.apache.solr.common.SolrInputDocument;
@@ -1145,7 +1146,7 @@ public class SolrServiceImpl implements SearchService, IndexingService {
} }
@Override @Override
public String searchJSON(DiscoverQuery query, DSpaceObject dso, String jsonIdentifier) throws SearchServiceException { public InputStream searchJSON(DiscoverQuery query, DSpaceObject dso, String jsonIdentifier) throws SearchServiceException {
if(dso != null){ if(dso != null){
if (dso instanceof Community) { if (dso instanceof Community) {
query.addFilterQueries("location:m" + dso.getID()); query.addFilterQueries("location:m" + dso.getID());
@@ -1159,7 +1160,7 @@ public class SolrServiceImpl implements SearchService, IndexingService {
} }
public String searchJSON(DiscoverQuery query, String jsonIdentifier) throws SearchServiceException { public InputStream searchJSON(DiscoverQuery query, String jsonIdentifier) throws SearchServiceException {
Map<String, String> params = new HashMap<String, String>(); Map<String, String> params = new HashMap<String, String>();
String solrRequestUrl = solr.getBaseURL() + "/select"; String solrRequestUrl = solr.getBaseURL() + "/select";
@@ -1229,7 +1230,7 @@ public class SolrServiceImpl implements SearchService, IndexingService {
try { try {
GetMethod get = new GetMethod(solrRequestUrl); GetMethod get = new GetMethod(solrRequestUrl);
new HttpClient().executeMethod(get); new HttpClient().executeMethod(get);
return get.getResponseBodyAsString(); return get.getResponseBodyAsStream();
} catch (Exception e) { } catch (Exception e) {
log.error("Error while getting json solr result for discovery search recommendation", e); log.error("Error while getting json solr result for discovery search recommendation", e);

View File

@@ -5,15 +5,20 @@
<packaging>jar</packaging> <packaging>jar</packaging>
<groupId>org.dspace</groupId> <groupId>org.dspace</groupId>
<artifactId>dspace-discovery-xmlui-api</artifactId> <artifactId>dspace-discovery-xmlui-api</artifactId>
<version>3.0-SNAPSHOT</version> <version>1.8.3</version>
<name>DSpace Discovery :: Discovery XMLUI API</name> <name>DSpace Discovery :: Discovery XMLUI API</name>
<parent> <parent>
<groupId>org.dspace</groupId> <groupId>org.dspace</groupId>
<artifactId>dspace-discovery</artifactId> <artifactId>dspace-discovery</artifactId>
<version>3.0-SNAPSHOT</version> <version>1.8.3</version>
<relativePath>..</relativePath> <relativePath>..</relativePath>
</parent> </parent>
<properties>
<!-- This is the path to the root [dspace-src] directory. -->
<root.basedir>${basedir}/../..</root.basedir>
</properties>
<dependencies> <dependencies>
@@ -115,18 +120,5 @@
--> -->
</plugins> </plugins>
</build> </build>
<!--
The Subversion repository location is used by Continuum to update
against when changes have occured, this spawns a new build cycle
and releases snapshots into the snapshot repository below.
-->
<scm>
<connection>scm:svn:http://scm.dspace.org/svn/repo/dspace/trunk/dspace-discovery/dspace-discovery-xmlui-api</connection>
<developerConnection>
scm:svn:https://scm.dspace.org/svn/repo/dspace/trunk/dspace-discovery/dspace-discovery-xmlui-api
</developerConnection>
<url>http://scm.dspace.org/svn/repo/dspace/trunk/dspace-discovery/dspace-discovery-xmlui-api</url>
</scm>
</project> </project>

View File

@@ -40,6 +40,7 @@ import org.xml.sax.SAXException;
import java.io.IOException; import java.io.IOException;
import java.io.Serializable; import java.io.Serializable;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.*; import java.util.*;
import java.util.List; import java.util.List;
@@ -414,7 +415,7 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach
//Add already existing filter queries //Add already existing filter queries
url = addFilterQueriesToUrl(url); url = addFilterQueriesToUrl(url);
//Last add the current filter query //Last add the current filter query
url += "&fq=" + filterQuery; url += "&fq=" + URLEncoder.encode(filterQuery, "UTF-8");
cell.addXref(url, displayedValue + " (" + value.getCount() + ")" cell.addXref(url, displayedValue + " (" + value.getCount() + ")"
); );
} }

View File

@@ -35,6 +35,7 @@ import org.xml.sax.SAXException;
import java.io.IOException; import java.io.IOException;
import java.io.Serializable; import java.io.Serializable;
import java.net.URLEncoder;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.*; import java.util.*;
import java.util.regex.Matcher; import java.util.regex.Matcher;
@@ -243,8 +244,7 @@ public class SidebarFacetsTransformer extends AbstractDSpaceTransformer implemen
"/discover?" + "/discover?" +
paramsQuery + paramsQuery +
"fq=" + "fq=" +
//TODO: encode URLEncoder ? URLEncoder.encode(filterQuery, "UTF-8"),
filterQuery,
displayedValue + " (" + value.getCount() + ")" displayedValue + " (" + value.getCount() + ")"
); );
} }

View File

@@ -28,6 +28,7 @@ import org.xml.sax.SAXException;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Map; import java.util.Map;
@@ -41,7 +42,7 @@ import java.util.Map;
public class JSONDiscoverySearcher extends AbstractReader implements Recyclable { public class JSONDiscoverySearcher extends AbstractReader implements Recyclable {
private static Logger log = Logger.getLogger(JSONDiscoverySearcher.class); private static Logger log = Logger.getLogger(JSONDiscoverySearcher.class);
private String JSONString; private InputStream JSONStream;
/** The Cocoon response */ /** The Cocoon response */
@@ -117,7 +118,7 @@ public class JSONDiscoverySearcher extends AbstractReader implements Recyclable
try { try {
Context context = ContextUtil.obtainContext(objectModel); Context context = ContextUtil.obtainContext(objectModel);
JSONString = getSearchService().searchJSON(queryArgs, getScope(context, objectModel), jsonWrf); JSONStream = getSearchService().searchJSON(queryArgs, getScope(context, objectModel), jsonWrf);
} catch (Exception e) { } catch (Exception e) {
log.error("Error while retrieving JSON string for Discovery auto complete", e); log.error("Error while retrieving JSON string for Discovery auto complete", e);
} }
@@ -125,14 +126,12 @@ public class JSONDiscoverySearcher extends AbstractReader implements Recyclable
} }
public void generate() throws IOException, SAXException, ProcessingException { public void generate() throws IOException, SAXException, ProcessingException {
if(JSONString != null){ if(JSONStream != null){
ByteArrayInputStream inputStream = new ByteArrayInputStream(JSONString.getBytes("UTF-8"));
byte[] buffer = new byte[8192]; byte[] buffer = new byte[8192];
response.setHeader("Content-Length", String.valueOf(JSONString.length())); response.setHeader("Content-Length", String.valueOf(JSONStream.available()));
int length; int length;
while ((length = inputStream.read(buffer)) > -1) while ((length = JSONStream.read(buffer)) > -1)
{ {
out.write(buffer, 0, length); out.write(buffer, 0, length);
} }

View File

@@ -1,214 +1,205 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- <!--
The contents of this file are subject to the license and copyright The contents of this file are subject to the license and copyright
detailed in the LICENSE and NOTICE files at the root of the source detailed in the LICENSE and NOTICE files at the root of the source
tree and available online at tree and available online at
http://www.dspace.org/license/ http://www.dspace.org/license/
--> -->
<!-- <!--
The ArtifactBrowser Aspect is responsible for browsing communities / The ArtifactBrowser Aspect is responsible for browsing communities /
collections / items / and bitstreams, viewing an individual item, collections / items / and bitstreams, viewing an individual item,
and searching the repository. and searching the repository.
--> -->
<map:sitemap xmlns:map="http://apache.org/cocoon/sitemap/1.0"> <map:sitemap xmlns:map="http://apache.org/cocoon/sitemap/1.0">
<map:components> <map:components>
<map:transformers> <map:transformers>
<map:transformer name="Navigation" src="org.dspace.app.xmlui.aspect.discovery.Navigation"/> <map:transformer name="Navigation" src="org.dspace.app.xmlui.aspect.discovery.Navigation"/>
<map:transformer name="SimpleSearch" src="org.dspace.app.xmlui.aspect.discovery.SimpleSearch"/> <map:transformer name="SimpleSearch" src="org.dspace.app.xmlui.aspect.discovery.SimpleSearch"/>
<map:transformer name="BrowseFacet" src="org.dspace.app.xmlui.aspect.discovery.BrowseFacet"/> <map:transformer name="BrowseFacet" src="org.dspace.app.xmlui.aspect.discovery.BrowseFacet"/>
<map:transformer name="SearchFacetFilter" src="org.dspace.app.xmlui.aspect.discovery.SearchFacetFilter"/> <map:transformer name="SearchFacetFilter" src="org.dspace.app.xmlui.aspect.discovery.SearchFacetFilter"/>
<map:transformer name="FrontPageSearch" src="org.dspace.app.xmlui.aspect.discovery.SiteViewer"/> <map:transformer name="FrontPageSearch" src="org.dspace.app.xmlui.aspect.discovery.SiteViewer"/>
<map:transformer name="SiteRecentSubmissions" src="org.dspace.app.xmlui.aspect.discovery.SiteRecentSubmissions"/> <map:transformer name="SiteRecentSubmissions" src="org.dspace.app.xmlui.aspect.discovery.SiteRecentSubmissions"/>
<map:transformer name="SidebarFacetsTransformer" src="org.dspace.app.xmlui.aspect.discovery.SidebarFacetsTransformer"/> <map:transformer name="SidebarFacetsTransformer" src="org.dspace.app.xmlui.aspect.discovery.SidebarFacetsTransformer"/>
<map:transformer name="CommunitySearch" src="org.dspace.app.xmlui.aspect.discovery.CommunitySearch"/> <map:transformer name="CommunitySearch" src="org.dspace.app.xmlui.aspect.discovery.CommunitySearch"/>
<map:transformer name="CommunityRecentSubmissions" src="org.dspace.app.xmlui.aspect.discovery.CommunityRecentSubmissions"/> <map:transformer name="CommunityRecentSubmissions" src="org.dspace.app.xmlui.aspect.discovery.CommunityRecentSubmissions"/>
<map:transformer name="CollectionSearch" src="org.dspace.app.xmlui.aspect.discovery.CollectionSearch"/> <map:transformer name="CollectionSearch" src="org.dspace.app.xmlui.aspect.discovery.CollectionSearch"/>
<map:transformer name="CollectionRecentSubmissions" src="org.dspace.app.xmlui.aspect.discovery.CollectionRecentSubmissions"/> <map:transformer name="CollectionRecentSubmissions" src="org.dspace.app.xmlui.aspect.discovery.CollectionRecentSubmissions"/>
<map:transformer name="RelatedItems" src="org.dspace.app.xmlui.aspect.discovery.RelatedItems"/> <map:transformer name="RelatedItems" src="org.dspace.app.xmlui.aspect.discovery.RelatedItems"/>
<map:transformer name="RestrictedItem" src="org.dspace.app.xmlui.aspect.artifactbrowser.RestrictedItem"/> <map:transformer name="RestrictedItem" src="org.dspace.app.xmlui.aspect.artifactbrowser.RestrictedItem"/>
</map:transformers> </map:transformers>
<map:matchers default="wildcard"> <map:matchers default="wildcard">
<map:matcher name="HandleTypeMatcher" src="org.dspace.app.xmlui.aspect.general.HandleTypeMatcher"/> <map:matcher name="HandleTypeMatcher" src="org.dspace.app.xmlui.aspect.general.HandleTypeMatcher"/>
<map:matcher name="HandleAuthorizedMatcher" src="org.dspace.app.xmlui.aspect.general.HandleAuthorizedMatcher"/> <map:matcher name="HandleAuthorizedMatcher" src="org.dspace.app.xmlui.aspect.general.HandleAuthorizedMatcher"/>
</map:matchers> </map:matchers>
<map:selectors> <map:selectors>
<map:selector name="AuthenticatedSelector" src="org.dspace.app.xmlui.aspect.general.AuthenticatedSelector"/> <map:selector name="AuthenticatedSelector" src="org.dspace.app.xmlui.aspect.general.AuthenticatedSelector"/>
</map:selectors> </map:selectors>
</map:components> </map:components>
<map:pipelines> <map:pipelines>
<map:pipeline> <map:pipeline>
<map:generate/> <map:generate/>
<!-- <!--
Add the basic navigation content to everypage. This includes: Add the basic navigation content to everypage. This includes:
1) Metadata about the current page (really just what the current 1) Metadata about the current page (really just what the current
context path is) context path is)
2) Navigation links to browse the repository. 2) Navigation links to browse the repository.
- This includes links that are relative to the currently - This includes links that are relative to the currently
selected community or collection. selected community or collection.
3) Metadata about the search urls. 3) Metadata about the search urls.
--> -->
<map:transform type="Navigation"/> <map:transform type="Navigation"/>
<!-- <!--
Display the DSpace homepage. This includes the news.xml file Display the DSpace homepage. This includes the news.xml file
along with a list of top level communities in DSpace. along with a list of top level communities in DSpace.
--> -->
<map:match pattern=""> <map:match pattern="">
<map:transform type="SidebarFacetsTransformer"/> <map:transform type="SidebarFacetsTransformer"/>
<map:transform type="FrontPageSearch"/> <map:transform type="FrontPageSearch"/>
<map:transform type="SiteRecentSubmissions"/> <map:transform type="SiteRecentSubmissions"/>
<map:serialize type="xml"/> <map:serialize type="xml"/>
</map:match> </map:match>
<!-- List all communities & collections in DSpace <!-- List all communities & collections in DSpace
<map:match pattern="community-list"> <map:match pattern="community-list">
<map:transform type="CommunityBrowser"> <map:transform type="CommunityBrowser">
<map:parameter name="depth" value="999"/> <map:parameter name="depth" value="999"/>
</map:transform> </map:transform>
<map:serialize type="xml"/> <map:serialize type="xml"/>
</map:match> --> </map:match> -->
<!-- Search --> <!-- Search -->
<map:match pattern="discover"> <map:match pattern="discover">
<map:transform type="SidebarFacetsTransformer"/> <map:transform type="SidebarFacetsTransformer"/>
<map:transform type="SimpleSearch"/> <map:transform type="SimpleSearch"/>
<map:transform type="IncludePageMeta"> <map:transform type="IncludePageMeta">
<map:parameter name="stylesheet.screen.discovery#1" value="../../static/css/discovery/style.css"/> <map:parameter name="stylesheet.screen.discovery#1" value="../../static/css/discovery/style.css"/>
<map:parameter name="javascript.static#1" value="loadJQuery.js"/> <map:parameter name="javascript.static#1" value="loadJQuery.js"/>
<map:parameter name="javascript.static#2" value="static/js/discovery/core/Core.js"/> <map:parameter name="javascript.static#2" value="static/js/discovery/core/Core.js"/>
<map:parameter name="javascript.static#3" value="static/js/discovery/core/AbstractManager.js"/> <map:parameter name="javascript.static#3" value="static/js/discovery/core/AbstractManager.js"/>
<map:parameter name="javascript.static#4" value="static/js/discovery/core/Parameter.js"/> <map:parameter name="javascript.static#4" value="static/js/discovery/core/Parameter.js"/>
<map:parameter name="javascript.static#5" value="static/js/discovery/core/ParameterStore.js"/> <map:parameter name="javascript.static#5" value="static/js/discovery/core/ParameterStore.js"/>
<map:parameter name="javascript.static#6" value="static/js/discovery/core/AbstractWidget.js"/> <map:parameter name="javascript.static#6" value="static/js/discovery/core/AbstractWidget.js"/>
<map:parameter name="javascript.static#7" value="static/js/discovery/core/AbstractFacetWidget.js"/> <map:parameter name="javascript.static#7" value="static/js/discovery/core/AbstractFacetWidget.js"/>
<map:parameter name="javascript.static#8" value="static/js/discovery/managers/Manager.jquery.js"/> <map:parameter name="javascript.static#8" value="static/js/discovery/managers/Manager.jquery.js"/>
<map:parameter name="javascript.static#9" value="static/js/jquery/jquery.autocomplete.js"/> <map:parameter name="javascript.static#9" value="static/js/jquery/jquery.autocomplete.js"/>
<map:parameter name="javascript.static#10" value="static/js/discovery/widgets/AutocompleteWidget.js"/> <map:parameter name="javascript.static#10" value="static/js/discovery/widgets/AutocompleteWidget.js"/>
<map:parameter name="javascript.static#11" value="static/js/discovery/search/search.js"/> <map:parameter name="javascript.static#11" value="static/js/discovery/search/search.js"/>
</map:transform> </map:transform>
<map:serialize type="xml"/> <map:serialize type="xml"/>
</map:match> </map:match>
<!--<map:match pattern="browse-discovery">--> <!--<map:match pattern="browse-discovery">-->
<!--<map:transform type="BrowseFacet"/>--> <!--<map:transform type="BrowseFacet"/>-->
<!--<map:serialize type="xml"/>--> <!--<map:serialize type="xml"/>-->
<!--</map:match>--> <!--</map:match>-->
<map:match pattern="search-filter"> <map:match pattern="search-filter">
<map:transform type="SearchFacetFilter"/> <map:transform type="SearchFacetFilter"/>
<map:serialize type="xml"/> <map:serialize type="xml"/>
</map:match> </map:match>
<!-- Handle specific features --> <!-- Handle specific features -->
<map:match pattern="handle/*/**"> <map:match pattern="handle/*/**">
<!-- Scoped browse by features --> <!-- Scoped browse by features -->
<map:match type="HandleAuthorizedMatcher" pattern="READ"> <map:match type="HandleAuthorizedMatcher" pattern="READ">
<map:match type="HandleTypeMatcher" pattern="community,collection"> <map:match type="HandleTypeMatcher" pattern="community,collection">
<!-- Browse (by anything) --> <!-- Browse (by anything) -->
<!--<map:match pattern="handle/*/*/browse-discovery">--> <!--<map:match pattern="handle/*/*/browse-discovery">-->
<!--<map:transform type="BrowseFacet"/>--> <!--<map:transform type="BrowseFacet"/>-->
<!--<map:serialize type="xml"/>--> <!--<map:serialize type="xml"/>-->
<!--</map:match>--> <!--</map:match>-->
<!-- Simple search --> <!-- Simple search -->
<map:match pattern="handle/*/*/discover"> <map:match pattern="handle/*/*/discover">
<map:transform type="SidebarFacetsTransformer"/> <map:transform type="SidebarFacetsTransformer"/>
<map:transform type="SimpleSearch"/> <map:transform type="SimpleSearch"/>
<map:transform type="IncludePageMeta"> <map:transform type="IncludePageMeta">
<map:parameter name="stylesheet.screen.discovery#1" value="../../static/css/discovery/style.css"/> <map:parameter name="stylesheet.screen.discovery#1" value="../../static/css/discovery/style.css"/>
<map:parameter name="javascript.static#1" value="loadJQuery.js"/> <map:parameter name="javascript.static#1" value="loadJQuery.js"/>
<map:parameter name="javascript.static#2" value="static/js/discovery/core/Core.js"/> <map:parameter name="javascript.static#2" value="static/js/discovery/core/Core.js"/>
<map:parameter name="javascript.static#3" value="static/js/discovery/core/AbstractManager.js"/> <map:parameter name="javascript.static#3" value="static/js/discovery/core/AbstractManager.js"/>
<map:parameter name="javascript.static#4" value="static/js/discovery/core/Parameter.js"/> <map:parameter name="javascript.static#4" value="static/js/discovery/core/Parameter.js"/>
<map:parameter name="javascript.static#5" value="static/js/discovery/core/ParameterStore.js"/> <map:parameter name="javascript.static#5" value="static/js/discovery/core/ParameterStore.js"/>
<map:parameter name="javascript.static#6" value="static/js/discovery/core/AbstractWidget.js"/> <map:parameter name="javascript.static#6" value="static/js/discovery/core/AbstractWidget.js"/>
<map:parameter name="javascript.static#7" value="static/js/discovery/core/AbstractFacetWidget.js"/> <map:parameter name="javascript.static#7" value="static/js/discovery/core/AbstractFacetWidget.js"/>
<map:parameter name="javascript.static#8" value="static/js/discovery/managers/Manager.jquery.js"/> <map:parameter name="javascript.static#8" value="static/js/discovery/managers/Manager.jquery.js"/>
<map:parameter name="javascript.static#9" value="static/js/jquery/jquery.autocomplete.js"/> <map:parameter name="javascript.static#9" value="static/js/jquery/jquery.autocomplete.js"/>
<map:parameter name="javascript.static#10" value="static/js/discovery/widgets/AutocompleteWidget.js"/> <map:parameter name="javascript.static#10" value="static/js/discovery/widgets/AutocompleteWidget.js"/>
<map:parameter name="javascript.static#11" value="static/js/discovery/search/search.js"/> <map:parameter name="javascript.static#11" value="static/js/discovery/search/search.js"/>
</map:transform> </map:transform>
<map:serialize type="xml"/> <map:serialize type="xml"/>
</map:match> </map:match>
<map:match pattern="handle/*/*/search-filter"> <map:match pattern="handle/*/*/search-filter">
<map:transform type="SearchFacetFilter"/> <map:transform type="SearchFacetFilter"/>
<map:serialize type="xml"/> <map:serialize type="xml"/>
</map:match> </map:match>
</map:match> </map:match>
</map:match> </map:match>
<map:match pattern="handle/*/*"> <map:match pattern="handle/*/*">
<map:match type="HandleAuthorizedMatcher" pattern="READ"> <map:match type="HandleAuthorizedMatcher" pattern="READ">
<map:match type="HandleTypeMatcher" pattern="community"> <map:match type="HandleTypeMatcher" pattern="community">
<map:transform type="SidebarFacetsTransformer"/> <map:transform type="SidebarFacetsTransformer"/>
<map:transform type="CommunitySearch"/> <map:transform type="CommunitySearch"/>
<map:transform type="CommunityRecentSubmissions"/> <map:transform type="CommunityRecentSubmissions"/>
<map:serialize type="xml"/> <map:serialize type="xml"/>
</map:match> </map:match>
<map:match type="HandleTypeMatcher" pattern="collection"> <map:match type="HandleTypeMatcher" pattern="collection">
<map:transform type="SidebarFacetsTransformer"/> <map:transform type="SidebarFacetsTransformer"/>
<map:transform type="CollectionSearch"/> <map:transform type="CollectionSearch"/>
<map:transform type="CollectionRecentSubmissions"/> <map:transform type="CollectionRecentSubmissions"/>
<map:serialize type="xml"/> <map:serialize type="xml"/>
</map:match> </map:match>
<map:match type="HandleTypeMatcher" pattern="item"> <map:match type="HandleTypeMatcher" pattern="item">
<!--<map:transform type="SidebarFacetsTransformer"/>--> <!--<map:transform type="SidebarFacetsTransformer"/>-->
<!--<map:transform type="ItemFacets"/>--> <!--<map:transform type="ItemFacets"/>-->
<map:transform type="RelatedItems"/> <map:transform type="RelatedItems"/>
<map:serialize type="xml"/> <map:serialize type="xml"/>
</map:match> </map:match>
</map:match> </map:match>
</map:match>
<map:match type="HandleAuthorizedMatcher" pattern="!READ">
<map:transform type="RestrictedItem"> </map:match> <!-- End match handle/*/** -->
<map:parameter name="header" value="xmlui.ArtifactBrowser.RestrictedItem.auth_header"/>
<map:parameter name="message" value="xmlui.ArtifactBrowser.RestrictedItem.auth_message"/> <!-- Not a URL we care about, so just pass it on. -->
</map:transform> <map:serialize type="xml"/>
<map:serialize type="xml"/>
</map:match> </map:pipeline>
</map:match>
</map:pipelines>
</map:match> <!-- End match handle/*/** --> </map:sitemap>
<!-- Not a URL we care about, so just pass it on. -->
<map:serialize type="xml"/>
</map:pipeline>
</map:pipelines>
</map:sitemap>

View File

@@ -5,16 +5,21 @@
<packaging>war</packaging> <packaging>war</packaging>
<groupId>org.dspace</groupId> <groupId>org.dspace</groupId>
<artifactId>dspace-discovery-xmlui-webapp</artifactId> <artifactId>dspace-discovery-xmlui-webapp</artifactId>
<version>3.0-SNAPSHOT</version> <version>1.8.3</version>
<name>DSpace Discovery :: Discovery XMLUI Webapp</name> <name>DSpace Discovery :: Discovery XMLUI Webapp</name>
<parent> <parent>
<groupId>org.dspace</groupId> <groupId>org.dspace</groupId>
<artifactId>dspace-discovery</artifactId> <artifactId>dspace-discovery</artifactId>
<version>3.0-SNAPSHOT</version> <version>1.8.3</version>
<relativePath>..</relativePath> <relativePath>..</relativePath>
</parent> </parent>
<properties>
<!-- This is the path to the root [dspace-src] directory. -->
<root.basedir>${basedir}/../..</root.basedir>
</properties>
<dependencies> <dependencies>
<dependency> <dependency>
@@ -31,7 +36,7 @@
<dependency> <dependency>
<groupId>org.dspace</groupId> <groupId>org.dspace</groupId>
<artifactId>dspace-discovery-xmlui-api</artifactId> <artifactId>dspace-discovery-xmlui-api</artifactId>
<version>3.0-SNAPSHOT</version> <version>1.8.3</version>
</dependency> </dependency>
<!-- external --> <!-- external -->
@@ -136,17 +141,4 @@
</plugins> </plugins>
</build> </build>
<!--
The Subversion repository location is used by Continuum to update
against when changes have occured, this spawns a new build cycle
and releases snapshots into the snapshot repository below.
-->
<scm>
<connection>scm:svn:http://scm.dspace.org/svn/repo/dspace/trunk/dspace-discovery/dspace-discovery-xmlui-webapp</connection>
<developerConnection>
scm:svn:https://scm.dspace.org/svn/repo/dspace/trunk/dspace-discovery/dspace-discovery-xmlui-webapp
</developerConnection>
<url>http://scm.dspace.org/svn/repo/dspace/trunk/dspace-discovery/dspace-discovery-xmlui-webapp</url>
</scm>
</project> </project>

View File

@@ -54,7 +54,7 @@ AjaxSolr.AutocompleteWidget = AjaxSolr.AbstractFacetWidget.extend({
} }
var fqs = $("input[name='fq']"); var fqs = $("input[name='fq']");
for(var j = 0; j < fqs.length; j ++){ for(var j = 0; j < fqs.length; j ++){
params.push('fq=' + $(fqs[j]).val()); params.push('fq=' + encodeURIComponent($(fqs[j]).val()));
} }
//Attempt to add our scope ! //Attempt to add our scope !
var scope = $("input[name='discovery-json-scope']").val(); var scope = $("input[name='discovery-json-scope']").val();

View File

@@ -5,15 +5,20 @@
<packaging>pom</packaging> <packaging>pom</packaging>
<groupId>org.dspace</groupId> <groupId>org.dspace</groupId>
<artifactId>dspace-discovery</artifactId> <artifactId>dspace-discovery</artifactId>
<version>3.0-SNAPSHOT</version> <version>1.8.3</version>
<name>DSpace Discovery :: Modules</name> <name>DSpace Discovery :: Modules</name>
<parent> <parent>
<artifactId>dspace-parent</artifactId> <artifactId>dspace-parent</artifactId>
<groupId>org.dspace</groupId> <groupId>org.dspace</groupId>
<version>3.0-SNAPSHOT</version> <version>1.8.3</version>
<relativePath>..</relativePath> <relativePath>..</relativePath>
</parent> </parent>
<properties>
<!-- This is the path to the root [dspace-src] directory. -->
<root.basedir>${basedir}/..</root.basedir>
</properties>
<modules> <modules>
<module>dspace-discovery-provider</module> <module>dspace-discovery-provider</module>
@@ -48,19 +53,6 @@
</plugins> </plugins>
</build> </build>
<!--
The Subversion repository location is used by Continuum to update
against when changes have occured, this spawns a new build cycle
and releases snapshots into the snapshot repository below.
-->
<scm>
<connection>scm:svn:http://scm.dspace.org/svn/repo/dspace/trunk/dspace-discovery</connection>
<developerConnection>
scm:svn:https://scm.dspace.org/svn/repo/dspace/trunk/dspace-discovery
</developerConnection>
<url>http://scm.dspace.org/svn/repo/dspace/trunk/dspace-discovery</url>
</scm>
<issueManagement> <issueManagement>
<system>JIRA</system> <system>JIRA</system>
<url>http://jira.dspace.org/jira/browse/DISCOVERY</url> <url>http://jira.dspace.org/jira/browse/DISCOVERY</url>

View File

@@ -14,20 +14,14 @@
<parent> <parent>
<groupId>org.dspace</groupId> <groupId>org.dspace</groupId>
<artifactId>dspace-jspui</artifactId> <artifactId>dspace-jspui</artifactId>
<version>3.0-SNAPSHOT</version> <version>1.8.3</version>
<relativePath>..</relativePath> <relativePath>..</relativePath>
</parent> </parent>
<!-- <properties>
The Subversion repository location is used by Continuum to update against <!-- This is the path to the root [dspace-src] directory. -->
when changes have occured, this spawns a new build cycle and releases snapshots <root.basedir>${basedir}/../..</root.basedir>
into the snapshot repository below. </properties>
-->
<scm>
<connection>scm:svn:http://scm.dspace.org/svn/repo/dspace/trunk/dspace-jspui/dspace-jspui-api</connection>
<developerConnection>scm:svn:https://scm.dspace.org/svn/repo/dspace/trunk/dspace-jspui/dspace-jspui-api</developerConnection>
<url>http://scm.dspace.org/svn/repo/dspace/trunk/dspace-jspui/dspace-jspui-api</url>
</scm>
<dependencies> <dependencies>
<dependency> <dependency>

View File

@@ -1,338 +1,338 @@
/** /**
* The contents of this file are subject to the license and copyright * The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source * detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at * tree and available online at
* *
* http://www.dspace.org/license/ * http://www.dspace.org/license/
*/ */
package org.dspace.app.webui.servlet; package org.dspace.app.webui.servlet;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.sql.SQLException; import java.sql.SQLException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeException;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.dspace.core.ConfigurationManager; import org.dspace.core.ConfigurationManager;
import org.dspace.core.Constants; import org.dspace.core.Constants;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.eperson.Group; import org.dspace.eperson.Group;
import org.dspace.content.DSpaceObject; import org.dspace.content.DSpaceObject;
import org.dspace.handle.HandleManager; import org.dspace.handle.HandleManager;
import org.dspace.statistics.Dataset; import org.dspace.statistics.Dataset;
import org.dspace.statistics.content.DatasetDSpaceObjectGenerator; import org.dspace.statistics.content.DatasetDSpaceObjectGenerator;
import org.dspace.statistics.content.DatasetTimeGenerator; import org.dspace.statistics.content.DatasetTimeGenerator;
import org.dspace.statistics.content.DatasetTypeGenerator; import org.dspace.statistics.content.DatasetTypeGenerator;
import org.dspace.statistics.content.StatisticsDataVisits; import org.dspace.statistics.content.StatisticsDataVisits;
import org.dspace.statistics.content.StatisticsListing; import org.dspace.statistics.content.StatisticsListing;
import org.dspace.statistics.content.StatisticsTable; import org.dspace.statistics.content.StatisticsTable;
import org.dspace.app.webui.components.StatisticsBean; import org.dspace.app.webui.components.StatisticsBean;
import org.dspace.app.webui.util.JSPManager; import org.dspace.app.webui.util.JSPManager;
/** /**
* *
* *
* @author Kim Shepherd * @author Kim Shepherd
* @version $Revision: 4386 $ * @version $Revision: 4386 $
*/ */
public class DisplayStatisticsServlet extends DSpaceServlet public class DisplayStatisticsServlet extends DSpaceServlet
{ {
/** log4j logger */ /** log4j logger */
private static Logger log = Logger.getLogger(DisplayStatisticsServlet.class); private static Logger log = Logger.getLogger(DisplayStatisticsServlet.class);
protected void doDSGet(Context context, HttpServletRequest request, protected void doDSGet(Context context, HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException, HttpServletResponse response) throws ServletException, IOException,
SQLException, AuthorizeException SQLException, AuthorizeException
{ {
// is the statistics data publically viewable? // is the statistics data publically viewable?
boolean privatereport = ConfigurationManager.getBooleanProperty("solr-statistics", "authorization.admin"); boolean privatereport = ConfigurationManager.getBooleanProperty("solr-statistics", "authorization.admin");
// is the user a member of the Administrator (1) group? // is the user a member of the Administrator (1) group?
boolean admin = Group.isMember(context, 1); boolean admin = Group.isMember(context, 1);
if (!privatereport || admin) if (!privatereport || admin)
{ {
displayStatistics(context, request, response); displayStatistics(context, request, response);
} }
else else
{ {
throw new AuthorizeException(); throw new AuthorizeException();
} }
} }
protected void displayStatistics(Context context, HttpServletRequest request, protected void displayStatistics(Context context, HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException, HttpServletResponse response) throws ServletException, IOException,
SQLException, AuthorizeException SQLException, AuthorizeException
{ {
DSpaceObject dso = null; DSpaceObject dso = null;
String handle = request.getParameter("handle"); String handle = request.getParameter("handle");
if("".equals(handle) || handle == null) if("".equals(handle) || handle == null)
{ {
// We didn't get passed a handle parameter. // We didn't get passed a handle parameter.
// That means we're looking at /handle/*/*/statistics // That means we're looking at /handle/*/*/statistics
// with handle injected as attribute from HandleServlet // with handle injected as attribute from HandleServlet
handle = (String) request.getAttribute("handle"); handle = (String) request.getAttribute("handle");
} }
if(handle != null) if(handle != null)
{ {
dso = HandleManager.resolveToObject(context, handle); dso = HandleManager.resolveToObject(context, handle);
} }
if(dso == null) if(dso == null)
{ {
response.setStatus(HttpServletResponse.SC_NOT_FOUND); response.setStatus(HttpServletResponse.SC_NOT_FOUND);
JSPManager.showJSP(request, response, "/error/404.jsp"); JSPManager.showJSP(request, response, "/error/404.jsp");
return; return;
} }
boolean isItem = false; boolean isItem = false;
StatisticsBean statsVisits = new StatisticsBean(); StatisticsBean statsVisits = new StatisticsBean();
StatisticsBean statsMonthlyVisits = new StatisticsBean(); StatisticsBean statsMonthlyVisits = new StatisticsBean();
StatisticsBean statsFileDownloads = new StatisticsBean(); StatisticsBean statsFileDownloads = new StatisticsBean();
StatisticsBean statsCountryVisits = new StatisticsBean(); StatisticsBean statsCountryVisits = new StatisticsBean();
StatisticsBean statsCityVisits = new StatisticsBean(); StatisticsBean statsCityVisits = new StatisticsBean();
try try
{ {
StatisticsListing statListing = new StatisticsListing( StatisticsListing statListing = new StatisticsListing(
new StatisticsDataVisits(dso)); new StatisticsDataVisits(dso));
statListing.setTitle("Total Visits"); statListing.setTitle("Total Visits");
statListing.setId("list1"); statListing.setId("list1");
DatasetDSpaceObjectGenerator dsoAxis = new DatasetDSpaceObjectGenerator(); DatasetDSpaceObjectGenerator dsoAxis = new DatasetDSpaceObjectGenerator();
dsoAxis.addDsoChild(dso.getType(), 10, false, -1); dsoAxis.addDsoChild(dso.getType(), 10, false, -1);
statListing.addDatasetGenerator(dsoAxis); statListing.addDatasetGenerator(dsoAxis);
Dataset dataset = statListing.getDataset(context); Dataset dataset = statListing.getDataset(context);
dataset = statListing.getDataset(); dataset = statListing.getDataset();
if (dataset == null) if (dataset == null)
{ {
dataset = statListing.getDataset(context); dataset = statListing.getDataset(context);
} }
if (dataset != null) if (dataset != null)
{ {
String[][] matrix = dataset.getMatrixFormatted(); String[][] matrix = dataset.getMatrixFormatted();
List<String> colLabels = dataset.getColLabels(); List<String> colLabels = dataset.getColLabels();
List<String> rowLabels = dataset.getRowLabels(); List<String> rowLabels = dataset.getRowLabels();
statsVisits.setMatrix(matrix); statsVisits.setMatrix(matrix);
statsVisits.setColLabels(colLabels); statsVisits.setColLabels(colLabels);
statsVisits.setRowLabels(rowLabels); statsVisits.setRowLabels(rowLabels);
} }
} catch (Exception e) } catch (Exception e)
{ {
log.error( log.error(
"Error occured while creating statistics for dso with ID: " "Error occured while creating statistics for dso with ID: "
+ dso.getID() + " and type " + dso.getType() + dso.getID() + " and type " + dso.getType()
+ " and handle: " + dso.getHandle(), e); + " and handle: " + dso.getHandle(), e);
} }
try try
{ {
StatisticsTable statisticsTable = new StatisticsTable(new StatisticsDataVisits(dso)); StatisticsTable statisticsTable = new StatisticsTable(new StatisticsDataVisits(dso));
statisticsTable.setTitle("Total Visits Per Month"); statisticsTable.setTitle("Total Visits Per Month");
statisticsTable.setId("tab1"); statisticsTable.setId("tab1");
DatasetTimeGenerator timeAxis = new DatasetTimeGenerator(); DatasetTimeGenerator timeAxis = new DatasetTimeGenerator();
timeAxis.setDateInterval("month", "-6", "+1"); timeAxis.setDateInterval("month", "-6", "+1");
statisticsTable.addDatasetGenerator(timeAxis); statisticsTable.addDatasetGenerator(timeAxis);
DatasetDSpaceObjectGenerator dsoAxis = new DatasetDSpaceObjectGenerator(); DatasetDSpaceObjectGenerator dsoAxis = new DatasetDSpaceObjectGenerator();
dsoAxis.addDsoChild(dso.getType(), 10, false, -1); dsoAxis.addDsoChild(dso.getType(), 10, false, -1);
statisticsTable.addDatasetGenerator(dsoAxis); statisticsTable.addDatasetGenerator(dsoAxis);
Dataset dataset = statisticsTable.getDataset(context); Dataset dataset = statisticsTable.getDataset(context);
dataset = statisticsTable.getDataset(); dataset = statisticsTable.getDataset();
if (dataset == null) if (dataset == null)
{ {
dataset = statisticsTable.getDataset(context); dataset = statisticsTable.getDataset(context);
} }
if (dataset != null) if (dataset != null)
{ {
String[][] matrix = dataset.getMatrixFormatted(); String[][] matrix = dataset.getMatrixFormatted();
List<String> colLabels = dataset.getColLabels(); List<String> colLabels = dataset.getColLabels();
List<String> rowLabels = dataset.getRowLabels(); List<String> rowLabels = dataset.getRowLabels();
statsMonthlyVisits.setMatrix(matrix); statsMonthlyVisits.setMatrix(matrix);
statsMonthlyVisits.setColLabels(colLabels); statsMonthlyVisits.setColLabels(colLabels);
statsMonthlyVisits.setRowLabels(rowLabels); statsMonthlyVisits.setRowLabels(rowLabels);
} }
} catch (Exception e) } catch (Exception e)
{ {
log.error( log.error(
"Error occured while creating statistics for dso with ID: " "Error occured while creating statistics for dso with ID: "
+ dso.getID() + " and type " + dso.getType() + dso.getID() + " and type " + dso.getType()
+ " and handle: " + dso.getHandle(), e); + " and handle: " + dso.getHandle(), e);
} }
if(dso instanceof org.dspace.content.Item) if(dso instanceof org.dspace.content.Item)
{ {
isItem = true; isItem = true;
try try
{ {
StatisticsListing statisticsTable = new StatisticsListing(new StatisticsDataVisits(dso)); StatisticsListing statisticsTable = new StatisticsListing(new StatisticsDataVisits(dso));
statisticsTable.setTitle("File Downloads"); statisticsTable.setTitle("File Downloads");
statisticsTable.setId("tab1"); statisticsTable.setId("tab1");
DatasetDSpaceObjectGenerator dsoAxis = new DatasetDSpaceObjectGenerator(); DatasetDSpaceObjectGenerator dsoAxis = new DatasetDSpaceObjectGenerator();
dsoAxis.addDsoChild(Constants.BITSTREAM, 10, false, -1); dsoAxis.addDsoChild(Constants.BITSTREAM, 10, false, -1);
statisticsTable.addDatasetGenerator(dsoAxis); statisticsTable.addDatasetGenerator(dsoAxis);
Dataset dataset = statisticsTable.getDataset(context); Dataset dataset = statisticsTable.getDataset(context);
dataset = statisticsTable.getDataset(); dataset = statisticsTable.getDataset();
if (dataset == null) if (dataset == null)
{ {
dataset = statisticsTable.getDataset(context); dataset = statisticsTable.getDataset(context);
} }
if (dataset != null) if (dataset != null)
{ {
String[][] matrix = dataset.getMatrixFormatted(); String[][] matrix = dataset.getMatrixFormatted();
List<String> colLabels = dataset.getColLabels(); List<String> colLabels = dataset.getColLabels();
List<String> rowLabels = dataset.getRowLabels(); List<String> rowLabels = dataset.getRowLabels();
statsFileDownloads.setMatrix(matrix); statsFileDownloads.setMatrix(matrix);
statsFileDownloads.setColLabels(colLabels); statsFileDownloads.setColLabels(colLabels);
statsFileDownloads.setRowLabels(rowLabels); statsFileDownloads.setRowLabels(rowLabels);
} }
} }
catch (Exception e) catch (Exception e)
{ {
log.error( log.error(
"Error occured while creating statistics for dso with ID: " "Error occured while creating statistics for dso with ID: "
+ dso.getID() + " and type " + dso.getType() + dso.getID() + " and type " + dso.getType()
+ " and handle: " + dso.getHandle(), e); + " and handle: " + dso.getHandle(), e);
} }
} }
try try
{ {
StatisticsListing statisticsTable = new StatisticsListing(new StatisticsDataVisits(dso)); StatisticsListing statisticsTable = new StatisticsListing(new StatisticsDataVisits(dso));
statisticsTable.setTitle("Top country views"); statisticsTable.setTitle("Top country views");
statisticsTable.setId("tab1"); statisticsTable.setId("tab1");
DatasetTypeGenerator typeAxis = new DatasetTypeGenerator(); DatasetTypeGenerator typeAxis = new DatasetTypeGenerator();
typeAxis.setType("countryCode"); typeAxis.setType("countryCode");
typeAxis.setMax(10); typeAxis.setMax(10);
statisticsTable.addDatasetGenerator(typeAxis); statisticsTable.addDatasetGenerator(typeAxis);
Dataset dataset = statisticsTable.getDataset(context); Dataset dataset = statisticsTable.getDataset(context);
dataset = statisticsTable.getDataset(); dataset = statisticsTable.getDataset();
if (dataset == null) if (dataset == null)
{ {
dataset = statisticsTable.getDataset(context); dataset = statisticsTable.getDataset(context);
} }
if (dataset != null) if (dataset != null)
{ {
String[][] matrix = dataset.getMatrixFormatted(); String[][] matrix = dataset.getMatrixFormatted();
List<String> colLabels = dataset.getColLabels(); List<String> colLabels = dataset.getColLabels();
List<String> rowLabels = dataset.getRowLabels(); List<String> rowLabels = dataset.getRowLabels();
statsCountryVisits.setMatrix(matrix); statsCountryVisits.setMatrix(matrix);
statsCountryVisits.setColLabels(colLabels); statsCountryVisits.setColLabels(colLabels);
statsCountryVisits.setRowLabels(rowLabels); statsCountryVisits.setRowLabels(rowLabels);
} }
} }
catch (Exception e) catch (Exception e)
{ {
log.error( log.error(
"Error occured while creating statistics for dso with ID: " "Error occured while creating statistics for dso with ID: "
+ dso.getID() + " and type " + dso.getType() + dso.getID() + " and type " + dso.getType()
+ " and handle: " + dso.getHandle(), e); + " and handle: " + dso.getHandle(), e);
} }
try try
{ {
StatisticsListing statisticsTable = new StatisticsListing(new StatisticsDataVisits(dso)); StatisticsListing statisticsTable = new StatisticsListing(new StatisticsDataVisits(dso));
statisticsTable.setTitle("Top city views"); statisticsTable.setTitle("Top city views");
statisticsTable.setId("tab1"); statisticsTable.setId("tab1");
DatasetTypeGenerator typeAxis = new DatasetTypeGenerator(); DatasetTypeGenerator typeAxis = new DatasetTypeGenerator();
typeAxis.setType("city"); typeAxis.setType("city");
typeAxis.setMax(10); typeAxis.setMax(10);
statisticsTable.addDatasetGenerator(typeAxis); statisticsTable.addDatasetGenerator(typeAxis);
Dataset dataset = statisticsTable.getDataset(context); Dataset dataset = statisticsTable.getDataset(context);
dataset = statisticsTable.getDataset(); dataset = statisticsTable.getDataset();
if (dataset == null) if (dataset == null)
{ {
dataset = statisticsTable.getDataset(context); dataset = statisticsTable.getDataset(context);
} }
if (dataset != null) if (dataset != null)
{ {
String[][] matrix = dataset.getMatrixFormatted(); String[][] matrix = dataset.getMatrixFormatted();
List<String> colLabels = dataset.getColLabels(); List<String> colLabels = dataset.getColLabels();
List<String> rowLabels = dataset.getRowLabels(); List<String> rowLabels = dataset.getRowLabels();
statsCityVisits.setMatrix(matrix); statsCityVisits.setMatrix(matrix);
statsCityVisits.setColLabels(colLabels); statsCityVisits.setColLabels(colLabels);
statsCityVisits.setRowLabels(rowLabels); statsCityVisits.setRowLabels(rowLabels);
} }
} }
catch (Exception e) catch (Exception e)
{ {
log.error( log.error(
"Error occured while creating statistics for dso with ID: " "Error occured while creating statistics for dso with ID: "
+ dso.getID() + " and type " + dso.getType() + dso.getID() + " and type " + dso.getType()
+ " and handle: " + dso.getHandle(), e); + " and handle: " + dso.getHandle(), e);
} }
request.setAttribute("statsVisits", statsVisits); request.setAttribute("statsVisits", statsVisits);
request.setAttribute("statsMonthlyVisits", statsMonthlyVisits); request.setAttribute("statsMonthlyVisits", statsMonthlyVisits);
request.setAttribute("statsFileDownloads", statsFileDownloads); request.setAttribute("statsFileDownloads", statsFileDownloads);
request.setAttribute("statsCountryVisits",statsCountryVisits); request.setAttribute("statsCountryVisits",statsCountryVisits);
request.setAttribute("statsCityVisits", statsCityVisits); request.setAttribute("statsCityVisits", statsCityVisits);
request.setAttribute("isItem", isItem); request.setAttribute("isItem", isItem);
JSPManager.showJSP(request, response, "display-statistics.jsp"); JSPManager.showJSP(request, response, "display-statistics.jsp");
} }
} }

View File

@@ -163,7 +163,15 @@ public class Authenticate
{ {
loggedIn(context, request, context.getCurrentUser()); loggedIn(context, request, context.getCurrentUser());
log.info(LogManager.getHeader(context, "login", "type=implicit")); log.info(LogManager.getHeader(context, "login", "type=implicit"));
return true; if(context.getCurrentUser() != null){
//We have a new user
Authenticate.resumeInterruptedRequest(request, response);
return false;
}else{
//Couldn't log & authentication finished
return true;
}
} }
else else
{ {

View File

@@ -14,20 +14,14 @@
<parent> <parent>
<groupId>org.dspace</groupId> <groupId>org.dspace</groupId>
<artifactId>dspace-jspui</artifactId> <artifactId>dspace-jspui</artifactId>
<version>3.0-SNAPSHOT</version> <version>1.8.3</version>
<relativePath>..</relativePath> <relativePath>..</relativePath>
</parent> </parent>
<!-- <properties>
The Subversion repository location is used by Continuum to update against <!-- This is the path to the root [dspace-src] directory. -->
when changes have occured, this spawns a new build cycle and releases snapshots <root.basedir>${basedir}/../..</root.basedir>
into the snapshot repository below. </properties>
-->
<scm>
<connection>scm:svn:http://scm.dspace.org/svn/repo/dspace/trunk/dspace-jspui/dspace-jspui-webapp</connection>
<developerConnection>scm:svn:https://scm.dspace.org/svn/repo/dspace/trunk/dspace-jspui/dspace-jspui-webapp</developerConnection>
<url>http://scm.dspace.org/svn/repo/dspace/trunk/dspace-jspui/dspace-jspui-webapp</url>
</scm>
<build> <build>
<plugins> <plugins>

View File

@@ -27,6 +27,7 @@
<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> <%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %>
<%@ page import="org.dspace.eperson.EPerson" %> <%@ page import="org.dspace.eperson.EPerson" %>
<%@ page import="org.dspace.core.Utils" %>
<% <%
EPerson[] epeople = EPerson[] epeople =
@@ -115,10 +116,10 @@
<%= (e.getEmail() == null ? "" : e.getEmail()) %> <%= (e.getEmail() == null ? "" : e.getEmail()) %>
</td> </td>
<td headers="t3" class="<%= row %>RowOddCol"> <td headers="t3" class="<%= row %>RowOddCol">
<%= (e.getLastName() == null ? "" : e.getLastName()) %> <%= (e.getLastName() == null ? "" : Utils.addEntities(e.getLastName())) %>
</td> </td>
<td headers="t4" class="<%= row %>RowEvenCol"> <td headers="t4" class="<%= row %>RowEvenCol">
<%= (e.getFirstName() == null ? "" : e.getFirstName()) %> <%= (e.getFirstName() == null ? "" : Utils.addEntities(e.getFirstName())) %>
</td> </td>
<td headers="t5" class="<%= row %>RowOddCol" align="center"> <td headers="t5" class="<%= row %>RowOddCol" align="center">
<%= e.canLogIn() ? "yes" : "no" %> <%= e.canLogIn() ? "yes" : "no" %>
@@ -130,7 +131,7 @@
<%= e.getSelfRegistered() ? "yes" : "no" %> <%= e.getSelfRegistered() ? "yes" : "no" %>
</td> </td>
<td headers="t8" class="<%= row %>RowEvenCol"> <td headers="t8" class="<%= row %>RowEvenCol">
<%= (e.getMetadata("phone") == null ? "" : e.getMetadata("phone")) %> <%= (e.getMetadata("phone") == null ? "" : Utils.addEntities(e.getMetadata("phone"))) %>
</td> </td>
<td headers="t9" class="<%= row %>RowOddCol"> <td headers="t9" class="<%= row %>RowOddCol">
<input type="hidden" name="eperson_id" value="<%= e.getID() %>"/> <input type="hidden" name="eperson_id" value="<%= e.getID() %>"/>

View File

@@ -20,6 +20,7 @@
prefix="fmt" %> prefix="fmt" %>
<%@ page import="org.dspace.eperson.EPerson" %> <%@ page import="org.dspace.eperson.EPerson" %>
<%@ page import="org.dspace.core.Utils" %>
<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> <%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %>
@@ -32,9 +33,9 @@
parenttitlekey="jsp.administer" parenttitlekey="jsp.administer"
parentlink="/dspace-admin"> parentlink="/dspace-admin">
<%-- <h1>Delete e-person: <%= eperson.getFullName() %> (<%= eperson.getEmail() %>)</h1> --%> <%-- <h1>Delete e-person: <%= Utils.addEntities(eperson.getFullName()) %> (<%= eperson.getEmail() %>)</h1> --%>
<h1><fmt:message key="jsp.dspace-admin.eperson-confirm-delete.heading"> <h1><fmt:message key="jsp.dspace-admin.eperson-confirm-delete.heading">
<fmt:param><%= eperson.getFullName() %></fmt:param> <fmt:param><%= Utils.addEntities(eperson.getFullName()) %></fmt:param>
<fmt:param><%= eperson.getEmail() %></fmt:param> <fmt:param><%= eperson.getEmail() %></fmt:param>
</fmt:message></h1> </fmt:message></h1>

View File

@@ -28,11 +28,12 @@
<%@ page import="org.dspace.eperson.EPerson" %> <%@ page import="org.dspace.eperson.EPerson" %>
<%@ page import="java.util.List" %> <%@ page import="java.util.List" %>
<%@ page import="java.util.Iterator" %> <%@ page import="java.util.Iterator" %>
<%@ page import="org.dspace.core.Utils" %>
<% <%
EPerson eperson = (EPerson) request.getAttribute("eperson"); EPerson eperson = (EPerson) request.getAttribute("eperson");
List tableList = (List) request.getAttribute("tableList"); List tableList = (List) request.getAttribute("tableList");
String fullName = eperson.getFullName(); String fullName = Utils.addEntities(eperson.getFullName());
Iterator tableIt = tableList.iterator(); Iterator tableIt = tableList.iterator();
%> %>

View File

@@ -28,6 +28,7 @@
<%@ page import="org.dspace.eperson.EPerson" %> <%@ page import="org.dspace.eperson.EPerson" %>
<%@ page import="org.dspace.eperson.Group" %> <%@ page import="org.dspace.eperson.Group" %>
<%@ page import="org.dspace.content.WorkspaceItem" %> <%@ page import="org.dspace.content.WorkspaceItem" %>
<%@ page import="org.dspace.core.Utils" %>
<% <%
// get item and group out of the request // get item and group out of the request
@@ -75,7 +76,7 @@
<br/><br/> <br/><br/>
<strong><fmt:message key="jsp.dspace-admin.supervise-confirm-remove.authorheader"/></strong>: <strong><fmt:message key="jsp.dspace-admin.supervise-confirm-remove.authorheader"/></strong>:
<br/> <br/>
<a href="mailto:<%= submitter.getEmail() %>"><%= submitter.getFullName() %></a> <a href="mailto:<%= submitter.getEmail() %>"><%= Utils.addEntities(submitter.getFullName()) %></a>
<br/><br/> <br/><br/>
<strong><fmt:message key="jsp.dspace-admin.supervise-confirm-remove.supervisorgroupheader"/></strong>: <strong><fmt:message key="jsp.dspace-admin.supervise-confirm-remove.supervisorgroupheader"/></strong>:
<br/> <br/>

View File

@@ -28,6 +28,7 @@
<%@ page import="org.dspace.eperson.EPerson" %> <%@ page import="org.dspace.eperson.EPerson" %>
<%@ page import="org.dspace.eperson.Group" %> <%@ page import="org.dspace.eperson.Group" %>
<%@ page import="org.dspace.eperson.Supervisor" %> <%@ page import="org.dspace.eperson.Supervisor" %>
<%@ page import="org.dspace.core.Utils" %>
<% <%
// get objects from request // get objects from request
@@ -109,7 +110,7 @@
<%= workspaceItems[i].getID() %> <%= workspaceItems[i].getID() %>
</td> </td>
<td class="<%= row %>RowEvenCol"> <td class="<%= row %>RowEvenCol">
<a href="mailto:<%= submitter.getEmail() %>"><%= submitter.getFullName() %></a> <a href="mailto:<%= submitter.getEmail() %>"><%= Utils.addEntities(submitter.getFullName()) %></a>
</td> </td>
<td class="<%= row %>RowOddCol"> <td class="<%= row %>RowOddCol">
<% <%

View File

@@ -25,6 +25,7 @@
<%@ page import="org.dspace.content.SupervisedItem" %> <%@ page import="org.dspace.content.SupervisedItem" %>
<%@ page import="org.dspace.eperson.EPerson" %> <%@ page import="org.dspace.eperson.EPerson" %>
<%@ page import="org.dspace.eperson.Group" %> <%@ page import="org.dspace.eperson.Group" %>
<%@ page import="org.dspace.core.Utils" %>
<% <%
// get the object array out of the request // get the object array out of the request
@@ -97,7 +98,7 @@
<%= supervisors[j].getName() %> <%= supervisors[j].getName() %>
</td> </td>
<td class="<%= row %>RowOddCol"> <td class="<%= row %>RowOddCol">
<a href="mailto:<%= submitter.getEmail() %>"><%= submitter.getFullName() %></a> <a href="mailto:<%= submitter.getEmail() %>"><%= Utils.addEntities(submitter.getFullName()) %></a>
</td> </td>
<td class="<%= row %>RowEvenCol"> <td class="<%= row %>RowEvenCol">
<% <%

View File

@@ -1,35 +1,35 @@
==== ====
The contents of this file are subject to the license and copyright The contents of this file are subject to the license and copyright
detailed in the LICENSE and NOTICE files at the root of the source detailed in the LICENSE and NOTICE files at the root of the source
tree and available online at tree and available online at
http://www.dspace.org/license/ http://www.dspace.org/license/
==== ====
The following icon files: The following icon files:
- book_key.png - book_key.png
- zoom.png - zoom.png
- bug.png - bug.png
are taken from are taken from
Silk icon set 1.3 Silk icon set 1.3
_________________________________________ _________________________________________
Mark James Mark James
http://www.famfamfam.com/lab/icons/silk/ http://www.famfamfam.com/lab/icons/silk/
_________________________________________ _________________________________________
This work is licensed under a This work is licensed under a
Creative Commons Attribution 2.5 License. Creative Commons Attribution 2.5 License.
[ http://creativecommons.org/licenses/by/2.5/ ] [ http://creativecommons.org/licenses/by/2.5/ ]
This means you may use it for any purpose, This means you may use it for any purpose,
and make any changes you like. and make any changes you like.
All I ask is that you include a link back All I ask is that you include a link back
to this page in your credits. to this page in your credits.
Are you using this icon set? Send me an email Are you using this icon set? Send me an email
(including a link or picture if available) to (including a link or picture if available) to
mjames@gmail.com mjames@gmail.com
Any other questions about this icon set please Any other questions about this icon set please
contact mjames@gmail.com contact mjames@gmail.com

View File

@@ -1,53 +1,53 @@
==== ====
The contents of this file are subject to the license and copyright The contents of this file are subject to the license and copyright
detailed in the LICENSE and NOTICE files at the root of the source detailed in the LICENSE and NOTICE files at the root of the source
tree and available online at tree and available online at
http://www.dspace.org/license/ http://www.dspace.org/license/
==== ====
16x16 Free Application Icons 16x16 Free Application Icons
This icon set is free for use in personal and commercial projects. This icon set is free for use in personal and commercial projects.
License Agreement License Agreement
By purchasing icons from Aha-Soft, You (the purchaser) By purchasing icons from Aha-Soft, You (the purchaser)
agree to the terms of this agreement, as detailed below. agree to the terms of this agreement, as detailed below.
You may use the icons from Aha-Soft in commercial and You may use the icons from Aha-Soft in commercial and
personal design projects, software or Internet products. personal design projects, software or Internet products.
Icons can be displayed in documentation, help files, and Icons can be displayed in documentation, help files, and
advertising materials. You are free to sell and distribute advertising materials. You are free to sell and distribute
products and projects using purchased icons without further products and projects using purchased icons without further
royalty fees. royalty fees.
All icon files are provided 'as is'. Aha-Soft cannot be All icon files are provided 'as is'. Aha-Soft cannot be
held liable for any negative issues that may occur as a held liable for any negative issues that may occur as a
result of using the icons. result of using the icons.
You agree that all ownership and copyright of the icons You agree that all ownership and copyright of the icons
remains the property of Aha-Soft. You may not resell, remains the property of Aha-Soft. You may not resell,
distribute, lease, license or sub-license the icons or distribute, lease, license or sub-license the icons or
modified icons (or a subset of the icons), to any third modified icons (or a subset of the icons), to any third
party unless they are incorporated into your software or party unless they are incorporated into your software or
design products. design products.
If you have any questions regarding copyright or licensing, If you have any questions regarding copyright or licensing,
including whether another license is required for icon use including whether another license is required for icon use
within products, please contact us here: www.aha-soft.com/support.htm within products, please contact us here: www.aha-soft.com/support.htm
Product page: http://www.small-icons.com/stock-icons/16x16-free-application-icons.htm Product page: http://www.small-icons.com/stock-icons/16x16-free-application-icons.htm
Icon Design Service Icon Design Service
We can design custom icons for you. Please find the basic information We can design custom icons for you. Please find the basic information
about ordering icons, pricing and the portfolio here: about ordering icons, pricing and the portfolio here:
www.aha-soft.com/customdev/design.htm www.aha-soft.com/customdev/design.htm
Notice Notice
Web-site small-icons.com belongs to Aha-Soft. Web-site small-icons.com belongs to Aha-Soft.
Support page: http://www.aha-soft.com/support.htm Support page: http://www.aha-soft.com/support.htm
Copyright <20> 2009 Aha-Soft. All rights reserved. Copyright <20> 2009 Aha-Soft. All rights reserved.

View File

@@ -25,7 +25,6 @@
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt"
prefix="fmt" %> prefix="fmt" %>
<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> <%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %>
<%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %> <%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %>
@@ -78,7 +77,7 @@
<tr> <tr>
<td align="left"> <td align="left">
<h1> <h1>
<fmt:message key="jsp.mydspace"/>: <%= user.getFullName() %> <fmt:message key="jsp.mydspace"/>: <%= Utils.addEntities(user.getFullName()) %>
</h1> </h1>
</td> </td>
<td align="right" class="standard"> <td align="right" class="standard">
@@ -136,7 +135,7 @@
</td> </td>
<td headers="t2" class="<%= row %>RowEvenCol"><%= Utils.addEntities(title) %></td> <td headers="t2" class="<%= row %>RowEvenCol"><%= Utils.addEntities(title) %></td>
<td headers="t3" class="<%= row %>RowOddCol"><%= owned[i].getCollection().getMetadata("name") %></td> <td headers="t3" class="<%= row %>RowOddCol"><%= owned[i].getCollection().getMetadata("name") %></td>
<td headers="t4" class="<%= row %>RowEvenCol"><a href="mailto:<%= submitter.getEmail() %>"><%= submitter.getFullName() %></a></td> <td headers="t4" class="<%= row %>RowEvenCol"><a href="mailto:<%= submitter.getEmail() %>"><%= Utils.addEntities(submitter.getFullName()) %></a></td>
<!-- <td headers="t5" class="<%= row %>RowOddCol"></td> --> <!-- <td headers="t5" class="<%= row %>RowOddCol"></td> -->
<td headers="t5" class="<%= row %>RowEvenCol"> <td headers="t5" class="<%= row %>RowEvenCol">
<form action="<%= request.getContextPath() %>/mydspace" method="post"> <form action="<%= request.getContextPath() %>/mydspace" method="post">
@@ -200,7 +199,7 @@
</td> </td>
<td headers="t7" class="<%= row %>RowEvenCol"><%= Utils.addEntities(title) %></td> <td headers="t7" class="<%= row %>RowEvenCol"><%= Utils.addEntities(title) %></td>
<td headers="t8" class="<%= row %>RowOddCol"><%= pooled[i].getCollection().getMetadata("name") %></td> <td headers="t8" class="<%= row %>RowOddCol"><%= pooled[i].getCollection().getMetadata("name") %></td>
<td headers="t9" class="<%= row %>RowEvenCol"><a href="mailto:<%= submitter.getEmail() %>"><%= submitter.getFullName() %></a></td> <td headers="t9" class="<%= row %>RowEvenCol"><a href="mailto:<%= submitter.getEmail() %>"><%= Utils.addEntities(submitter.getFullName()) %></a></td>
<td class="<%= row %>RowOddCol"> <td class="<%= row %>RowOddCol">
<form action="<%= request.getContextPath() %>/mydspace" method="post"> <form action="<%= request.getContextPath() %>/mydspace" method="post">
<input type="hidden" name="step" value="<%= MyDSpaceServlet.MAIN_PAGE %>" /> <input type="hidden" name="step" value="<%= MyDSpaceServlet.MAIN_PAGE %>" />
@@ -285,7 +284,7 @@
</form> </form>
</td> </td>
<td headers="t10" class="<%= row %>RowEvenCol"> <td headers="t10" class="<%= row %>RowEvenCol">
<a href="mailto:<%= submitter.getEmail() %>"><%= submitter.getFullName() %></a> <a href="mailto:<%= submitter.getEmail() %>"><%= Utils.addEntities(submitter.getFullName()) %></a>
</td> </td>
<td headers="t11" class="<%= row %>RowOddCol"><%= Utils.addEntities(title) %></td> <td headers="t11" class="<%= row %>RowOddCol"><%= Utils.addEntities(title) %></td>
<td headers="t12" class="<%= row %>RowEvenCol"><%= workspaceItems[i].getCollection().getMetadata("name") %></td> <td headers="t12" class="<%= row %>RowEvenCol"><%= workspaceItems[i].getCollection().getMetadata("name") %></td>
@@ -332,7 +331,7 @@
</form> </form>
</td> </td>
<td class="<%= row %>RowEvenCol"> <td class="<%= row %>RowEvenCol">
<a href="mailto:<%= submitter.getEmail() %>"><%= submitter.getFullName() %></a> <a href="mailto:<%= submitter.getEmail() %>"><%= Utils.addEntities(submitter.getFullName()) %></a>
</td> </td>
<td class="<%= row %>RowOddCol"><%= Utils.addEntities(title) %></td> <td class="<%= row %>RowOddCol"><%= Utils.addEntities(title) %></td>
<td class="<%= row %>RowEvenCol"><%= supervisedItems[i].getCollection().getMetadata("name") %></td> <td class="<%= row %>RowEvenCol"><%= supervisedItems[i].getCollection().getMetadata("name") %></td>

View File

@@ -29,6 +29,7 @@
<%@ page import="org.dspace.app.webui.servlet.RegisterServlet" %> <%@ page import="org.dspace.app.webui.servlet.RegisterServlet" %>
<%@ page import="org.dspace.eperson.EPerson" %> <%@ page import="org.dspace.eperson.EPerson" %>
<%@ page import="org.dspace.core.Utils" %>
<% <%
EPerson eperson = (EPerson) request.getAttribute("eperson"); EPerson eperson = (EPerson) request.getAttribute("eperson");
@@ -43,9 +44,9 @@
<%-- <h1>Enter a New Password</h1> --%> <%-- <h1>Enter a New Password</h1> --%>
<h1><fmt:message key="jsp.register.new-password.title"/></h1> <h1><fmt:message key="jsp.register.new-password.title"/></h1>
<!-- <p>Hello <%= eperson.getFullName() %>,</p> --> <!-- <p>Hello <%= Utils.addEntities(eperson.getFullName()) %>,</p> -->
<p><fmt:message key="jsp.register.new-password.hello"> <p><fmt:message key="jsp.register.new-password.hello">
<fmt:param><%= eperson.getFullName() %></fmt:param> <fmt:param><%= Utils.addEntities(eperson.getFullName()) %></fmt:param>
</fmt:message></p> </fmt:message></p>
<% <%

View File

@@ -25,6 +25,7 @@
<%@ page import="org.dspace.app.webui.servlet.RegisterServlet" %> <%@ page import="org.dspace.app.webui.servlet.RegisterServlet" %>
<%@ page import="org.dspace.eperson.EPerson" %> <%@ page import="org.dspace.eperson.EPerson" %>
<%@ page import="org.dspace.core.Utils" %>
<% <%
EPerson eperson = (EPerson) request.getAttribute("eperson"); EPerson eperson = (EPerson) request.getAttribute("eperson");
@@ -35,9 +36,9 @@
<%-- <h1>Registration Complete</h1> --%> <%-- <h1>Registration Complete</h1> --%>
<h1><fmt:message key="jsp.register.registered.title"/></h1> <h1><fmt:message key="jsp.register.registered.title"/></h1>
<%-- <p>Thank you <%= eperson.getFirstName() %>,</p> --%> <%-- <p>Thank you <%= Utils.addEntities(eperson.getFirstName()) %>,</p> --%>
<p><fmt:message key="jsp.register.registered.thank"> <p><fmt:message key="jsp.register.registered.thank">
<fmt:param><%= eperson.getFirstName() %></fmt:param> <fmt:param><%= Utils.addEntities(eperson.getFirstName()) %></fmt:param>
</fmt:message></p> </fmt:message></p>
<%-- <p>You're now registered to use the DSpace system. You can subscribe to <%-- <p>You're now registered to use the DSpace system. You can subscribe to

View File

@@ -50,6 +50,7 @@
<%@ page import="org.dspace.content.authority.ChoiceAuthorityManager" %> <%@ page import="org.dspace.content.authority.ChoiceAuthorityManager" %>
<%@ page import="org.dspace.content.authority.Choices" %> <%@ page import="org.dspace.content.authority.Choices" %>
<%@ page import="org.dspace.core.ConfigurationManager" %> <%@ page import="org.dspace.core.ConfigurationManager" %>
<%@ page import="org.dspace.core.Utils" %>
<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> <%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
@@ -325,9 +326,9 @@
if (repeatable && !readonly && i < defaults.length) if (repeatable && !readonly && i < defaults.length)
{ {
name.setLength(0); name.setLength(0);
name.append(dpn.getLastName()) name.append(Utils.addEntities(dpn.getLastName()))
.append(' ') .append(' ')
.append(dpn.getFirstNames()); .append(Utils.addEntities(dpn.getFirstNames()));
// put a remove button next to filled in values // put a remove button next to filled in values
sb.append("<td><input type=\"submit\" name=\"submit_") sb.append("<td><input type=\"submit\" name=\"submit_")
.append(fieldName) .append(fieldName)

View File

@@ -281,7 +281,7 @@ function clearEPeople()
{ {
EPerson e = epeople[i]; EPerson e = epeople[i];
// Make sure no quotes in full name will mess up our Javascript // Make sure no quotes in full name will mess up our Javascript
String fullname = e.getFullName().replace('\'', ' '); String fullname = Utils.addEntities(e.getFullName().replace('\'', ' '));
%> %>
<tr> <tr>
<td headers="t1" class="<%= row %>RowOddCol"> <td headers="t1" class="<%= row %>RowOddCol">
@@ -291,10 +291,10 @@ function clearEPeople()
<td headers="t2" class="<%= row %>RowEvenCol"><%= e.getID() %></td> <td headers="t2" class="<%= row %>RowEvenCol"><%= e.getID() %></td>
<td headers="t3" class="<%= row %>RowOddCol"><%= e.getEmail() %></td> <td headers="t3" class="<%= row %>RowOddCol"><%= e.getEmail() %></td>
<td headers="t4" class="<%= row %>RowEvenCol"> <td headers="t4" class="<%= row %>RowEvenCol">
<%= (e.getLastName() == null ? "" : e.getLastName()) %> <%= (e.getLastName() == null ? "" : Utils.addEntities(e.getLastName())) %>
</td> </td>
<td headers="t5" class="<%= row %>RowOddCol"> <td headers="t5" class="<%= row %>RowOddCol">
<%= (e.getFirstName() == null ? "" : e.getFirstName()) %> <%= (e.getFirstName() == null ? "" : Utils.addEntities(e.getFirstName())) %>
</td> </td>
<td headers="t6" class="<%= row %>RowOddCol"> <td headers="t6" class="<%= row %>RowOddCol">
<%= (e.getLanguage() == null ? "" : e.getLanguage()) %> <%= (e.getLanguage() == null ? "" : e.getLanguage()) %>

View File

@@ -26,6 +26,7 @@
<%@ page import="org.dspace.content.WorkspaceItem" %> <%@ page import="org.dspace.content.WorkspaceItem" %>
<%@ page import="org.dspace.eperson.EPerson" %> <%@ page import="org.dspace.eperson.EPerson" %>
<%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %> <%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %>
<%@ page import="org.dspace.core.Utils" %>
<% <%
// get the workspace item from the request // get the workspace item from the request
@@ -73,7 +74,7 @@
} }
%> %>
<p><strong><a href="mailto:<%= submitter.getEmail() %>"><%= submitter.getFullName() %></a></strong></p> <p><strong><a href="mailto:<%= submitter.getEmail() %>"><%= Utils.addEntities(submitter.getFullName()) %></a></strong></p>
<p><fmt:message key="jsp.workspace.ws-main.submitmsg"/> <p><fmt:message key="jsp.workspace.ws-main.submitmsg"/>
<%= workspaceItem.getCollection().getMetadata("name") %></p> <%= workspaceItem.getCollection().getMetadata("name") %></p>

View File

@@ -14,20 +14,14 @@
<parent> <parent>
<groupId>org.dspace</groupId> <groupId>org.dspace</groupId>
<artifactId>dspace-parent</artifactId> <artifactId>dspace-parent</artifactId>
<version>3.0-SNAPSHOT</version> <version>1.8.3</version>
<relativePath>..</relativePath> <relativePath>..</relativePath>
</parent> </parent>
<!-- <properties>
The Subversion repository location is used by Continuum to update against <!-- This is the path to the root [dspace-src] directory. -->
when changes have occured, this spawns a new build cycle and releases snapshots <root.basedir>${basedir}/..</root.basedir>
into the snapshot repository below. </properties>
-->
<scm>
<connection>scm:svn:http://scm.dspace.org/svn/repo/dspace/trunk/dspace-jspui</connection>
<developerConnection>scm:svn:https://scm.dspace.org/svn/repo/dspace/trunk/dspace-jspui</developerConnection>
<url>http://scm.dspace.org/svn/repo/dspace/trunk/dspace-jspui</url>
</scm>
<modules> <modules>
<module>dspace-jspui-api</module> <module>dspace-jspui-api</module>

View File

@@ -12,15 +12,14 @@
<parent> <parent>
<groupId>org.dspace</groupId> <groupId>org.dspace</groupId>
<artifactId>dspace-lni</artifactId> <artifactId>dspace-lni</artifactId>
<version>3.0-SNAPSHOT</version> <version>1.8.3</version>
<relativePath>..</relativePath> <relativePath>..</relativePath>
</parent> </parent>
<scm> <properties>
<connection>scm:svn:https://scm.dspace.org/svn/repo/dspace/trunk/dspace-lni/dspace-lni-client</connection> <!-- This is the path to the root [dspace-src] directory. -->
<developerConnection>scm:svn:https://scm.dspace.org/svn/repo/dspace/trunk/dspace-lni/dspace-lni-client</developerConnection> <root.basedir>${basedir}/../..</root.basedir>
<url>http://scm.dspace.org/svn/repo/dspace/trunk/dspace-lni/dspace-lni-client</url> </properties>
</scm>
<profiles> <profiles>
<profile> <profile>

View File

@@ -1,4 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
The contents of this file are subject to the license and copyright
detailed in the LICENSE and NOTICE files at the root of the source
tree and available online at
http://www.dspace.org/license/
-->
<wsdl:definitions targetNamespace="http://dspace.org/xmlns/lni" xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="http://dspace.org/xmlns/lni" xmlns:intf="http://dspace.org/xmlns/lni" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns1="http://lang.java" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <wsdl:definitions targetNamespace="http://dspace.org/xmlns/lni" xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="http://dspace.org/xmlns/lni" xmlns:intf="http://dspace.org/xmlns/lni" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns1="http://lang.java" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<!--WSDL created by Apache Axis version: 1.3 <!--WSDL created by Apache Axis version: 1.3
Built on Oct 05, 2005 (05:23:37 EDT)--> Built on Oct 05, 2005 (05:23:37 EDT)-->

View File

@@ -10,15 +10,14 @@
<parent> <parent>
<groupId>org.dspace</groupId> <groupId>org.dspace</groupId>
<artifactId>dspace-lni</artifactId> <artifactId>dspace-lni</artifactId>
<version>3.0-SNAPSHOT</version> <version>1.8.3</version>
<relativePath>..</relativePath> <relativePath>..</relativePath>
</parent> </parent>
<scm> <properties>
<connection>scm:svn:https://scm.dspace.org/svn/repo/dspace/trunk/dspace-lni/dspace-lni-core</connection> <!-- This is the path to the root [dspace-src] directory. -->
<developerConnection>scm:svn:https://scm.dspace.org/svn/repo/dspace/trunk/dspace-lni/dspace-lni-core</developerConnection> <root.basedir>${basedir}/../..</root.basedir>
<url>http://scm.dspace.org/svn/repo/dspace/trunk/dspace-lni/dspace-lni-core</url> </properties>
</scm>
<dependencies> <dependencies>
<dependency> <dependency>

View File

@@ -89,7 +89,12 @@ abstract class DAVDSpaceObject extends DAVResource
int hs; int hs;
if (handleSeparator != '/') if (handleSeparator != '/')
{ {
handle = handle.replaceFirst("/", String.valueOf(handleSeparator)); if(handleSeparator != '$') {
handle = handle.replaceFirst("/", String.valueOf(handleSeparator));
} else {
// handle $ specially
handle = handle.replaceFirst("/", "\\$");
}
} }
return "dso_" + encodeHandle(handle); return "dso_" + encodeHandle(handle);
} }

View File

@@ -289,80 +289,92 @@ public class DAVServlet extends HttpServlet
{ {
Context context = new Context(); Context context = new Context();
if (getAuthFromCookie(context, request)) try {
{ if (getAuthFromCookie(context, request))
putAuthCookie(context, request, response, false); {
return context; putAuthCookie(context, request, response, false);
} Context returnContext = context;
context = null;
return returnContext;
}
// get username/password from Basic auth header if avail:
String cred = request.getHeader("Authorization");
if (cred != null && username == null && password == null)
{
log.info(LogManager.getHeader(context, "got creds", "Authorize: "
+ cred));
StringTokenizer ct = new StringTokenizer(cred);
// format: Basic {username:password in base64}
if (ct.nextToken().equalsIgnoreCase("Basic"))
{
String crud = ct.nextToken();
String dcrud = new String(Base64.decodeBase64(crud.getBytes()));
int colon = dcrud.indexOf(':');
if (colon > 0)
{
username = decodeFromURL(dcrud.substring(0, colon));
password = decodeFromURL(dcrud.substring(colon + 1));
log
.info(LogManager.getHeader(context, "auth",
"Got username=\"" + username
+ "\" out of \"" + crud + "\"."));
}
}
}
// get username/password from Basic auth header if avail: // Authenticate the user.
String cred = request.getHeader("Authorization"); if (AuthenticationManager.authenticate(context, username, password,
if (cred != null && username == null && password == null) null, request) == AuthenticationMethod.SUCCESS)
{ {
log.info(LogManager.getHeader(context, "got creds", "Authorize: " log.info(LogManager.getHeader(context, "auth",
+ cred)); "Authentication returned SUCCESS, eperson="
StringTokenizer ct = new StringTokenizer(cred); + context.getCurrentUser().getEmail()));
}
// format: Basic {username:password in base64} else
if (ct.nextToken().equalsIgnoreCase("Basic")) {
{ if (username == null)
String crud = ct.nextToken(); {
String dcrud = new String(Base64.decodeBase64(crud.getBytes())); log.info(LogManager.getHeader(context, "auth",
int colon = dcrud.indexOf(':'); "No credentials, so sending WWW-Authenticate header."));
if (colon > 0) }
{ else
username = decodeFromURL(dcrud.substring(0, colon)); {
password = decodeFromURL(dcrud.substring(colon + 1)); log.warn(LogManager.getHeader(context, "auth",
log "Authentication FAILED, cred=" + cred));
.info(LogManager.getHeader(context, "auth", }
"Got username=\"" + username
+ "\" out of \"" + crud + "\".")); // ...EXCEPT if dav.access.anonymous is true in config:
} if (!allowAnonymousAccess)
} {
if (response != null)
{
response.setHeader("WWW-Authenticate",
"Basic realm=\"dspace\"");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
return null;
}
}
// Set any special groups - invoke the authentication mgr.
int[] groupIDs = AuthenticationManager.getSpecialGroups(context,
request);
for (int element : groupIDs)
{
context.setSpecialGroup(element);
log.debug("Adding Special Group id=" + String.valueOf(element));
}
putAuthCookie(context, request, response, true);
Context returnContext = context;
context = null;
return returnContext;
} finally {
if(context != null)
context.abort();
} }
if (AuthenticationManager.authenticate(context, username, password,
null, request) == AuthenticationMethod.SUCCESS)
{
log.info(LogManager.getHeader(context, "auth",
"Authentication returned SUCCESS, eperson="
+ context.getCurrentUser().getEmail()));
}
else
{
if (username == null)
{
log.info(LogManager.getHeader(context, "auth",
"No credentials, so sending WWW-Authenticate header."));
}
else
{
log.warn(LogManager.getHeader(context, "auth",
"Authentication FAILED, cred=" + cred));
}
// ...EXCEPT if dav.access.anonymous is true in config:
if (!allowAnonymousAccess)
{
if (response != null)
{
response.setHeader("WWW-Authenticate",
"Basic realm=\"dspace\"");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
return null;
}
}
// Set any special groups - invoke the authentication mgr.
int[] groupIDs = AuthenticationManager.getSpecialGroups(context,
request);
for (int element : groupIDs)
{
context.setSpecialGroup(element);
log.debug("Adding Special Group id=" + String.valueOf(element));
}
putAuthCookie(context, request, response, true);
return context;
} }
/** /**

View File

@@ -12,15 +12,14 @@
<parent> <parent>
<groupId>org.dspace</groupId> <groupId>org.dspace</groupId>
<artifactId>dspace-lni</artifactId> <artifactId>dspace-lni</artifactId>
<version>3.0-SNAPSHOT</version> <version>1.8.3</version>
<relativePath>..</relativePath> <relativePath>..</relativePath>
</parent> </parent>
<scm> <properties>
<connection>scm:svn:https://scm.dspace.org/svn/repo/dspace/trunk/dspace-lni/dspace-lni-webapp</connection> <!-- This is the path to the root [dspace-src] directory. -->
<developerConnection>scm:svn:https://scm.dspace.org/svn/repo/dspace/trunk/dspace-lni/dspace-lni-webapp</developerConnection> <root.basedir>${basedir}/../..</root.basedir>
<url>http://scm.dspace.org/svn/repo/dspace/trunk/dspace-lni/dspace-lni-webapp</url> </properties>
</scm>
<build> <build>
<plugins> <plugins>

View File

@@ -1,4 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
The contents of this file are subject to the license and copyright
detailed in the LICENSE and NOTICE files at the root of the source
tree and available online at
http://www.dspace.org/license/
-->
<!-- <!--
Description of DSpace Lightweight Network Interface (LNI) API Description of DSpace Lightweight Network Interface (LNI) API
This is the WSDD (Web Services Deployment Descriptor) for This is the WSDD (Web Services Deployment Descriptor) for

View File

@@ -1,4 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
The contents of this file are subject to the license and copyright
detailed in the LICENSE and NOTICE files at the root of the source
tree and available online at
http://www.dspace.org/license/
-->
<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"> <deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<!-- Server Deployment Descriptor for DSpace LNI, on Axis 1.2 <!-- Server Deployment Descriptor for DSpace LNI, on Axis 1.2

View File

@@ -12,20 +12,14 @@
<parent> <parent>
<groupId>org.dspace</groupId> <groupId>org.dspace</groupId>
<artifactId>dspace-parent</artifactId> <artifactId>dspace-parent</artifactId>
<version>3.0-SNAPSHOT</version> <version>1.8.3</version>
<relativePath>..</relativePath> <relativePath>..</relativePath>
</parent> </parent>
<!-- <properties>
The Subversion repository location is used by Continuum to update against <!-- This is the path to the root [dspace-src] directory. -->
when changes have occured, this spawns a new build cycle and releases snapshots <root.basedir>${basedir}/..</root.basedir>
into the snapshot repository below. </properties>
-->
<scm>
<connection>scm:svn:http://scm.dspace.org/svn/repo/dspace/trunk/dspace-lni</connection>
<developerConnection>scm:svn:https://scm.dspace.org/svn/repo/dspace/trunk/dspace-lni</developerConnection>
<url>http://scm.dspace.org/svn/repo/dspace/trunk/dspace-lni</url>
</scm>
<modules> <modules>
<module>dspace-lni-core</module> <module>dspace-lni-core</module>

View File

@@ -14,20 +14,14 @@
<parent> <parent>
<groupId>org.dspace</groupId> <groupId>org.dspace</groupId>
<artifactId>dspace-oai</artifactId> <artifactId>dspace-oai</artifactId>
<version>3.0-SNAPSHOT</version> <version>1.8.3</version>
<relativePath>..</relativePath> <relativePath>..</relativePath>
</parent> </parent>
<!-- <properties>
The Subversion repository location is used by Continuum to update against <!-- This is the path to the root [dspace-src] directory. -->
when changes have occured, this spawns a new build cycle and releases snapshots <root.basedir>${basedir}/../..</root.basedir>
into the snapshot repository below. </properties>
-->
<scm>
<connection>scm:svn:http://scm.dspace.org/svn/repo/dspace/trunk/dspace-oai/dspace-oai-api</connection>
<developerConnection>scm:svn:https://scm.dspace.org/svn/repo/dspace/trunk/dspace-oai/dspace-oai-api</developerConnection>
<url>http://scm.dspace.org/svn/repo/dspace/trunk/dspace-oai/dspace-oai-api</url>
</scm>
<dependencies> <dependencies>
<dependency> <dependency>

View File

@@ -14,20 +14,14 @@
<parent> <parent>
<groupId>org.dspace</groupId> <groupId>org.dspace</groupId>
<artifactId>dspace-oai</artifactId> <artifactId>dspace-oai</artifactId>
<version>3.0-SNAPSHOT</version> <version>1.8.3</version>
<relativePath>..</relativePath> <relativePath>..</relativePath>
</parent> </parent>
<!-- <properties>
The Subversion repository location is used by Continuum to update against <!-- This is the path to the root [dspace-src] directory. -->
when changes have occured, this spawns a new build cycle and releases snapshots <root.basedir>${basedir}/../..</root.basedir>
into the snapshot repository below. </properties>
-->
<scm>
<connection>scm:svn:http://scm.dspace.org/svn/repo/dspace/trunk/dspace-oai/dspace-oai-webapp</connection>
<developerConnection>scm:svn:https://scm.dspace.org/svn/repo/dspace/trunk/dspace-oai/dspace-oai-webapp</developerConnection>
<url>http://scm.dspace.org/svn/repo/dspace/trunk/dspace-oai/dspace-oai-webapp</url>
</scm>
<build> <build>
<plugins> <plugins>

View File

@@ -14,20 +14,14 @@
<parent> <parent>
<groupId>org.dspace</groupId> <groupId>org.dspace</groupId>
<artifactId>dspace-parent</artifactId> <artifactId>dspace-parent</artifactId>
<version>3.0-SNAPSHOT</version> <version>1.8.3</version>
<relativePath>..</relativePath> <relativePath>..</relativePath>
</parent> </parent>
<!-- <properties>
The Subversion repository location is used by Continuum to update against <!-- This is the path to the root [dspace-src] directory. -->
when changes have occured, this spawns a new build cycle and releases snapshots <root.basedir>${basedir}/..</root.basedir>
into the snapshot repository below. </properties>
-->
<scm>
<connection>scm:svn:http://scm.dspace.org/svn/repo/dspace/trunk/dspace-oai</connection>
<developerConnection>scm:svn:https://scm.dspace.org/svn/repo/dspace/trunk/dspace-oai</developerConnection>
<url>http://scm.dspace.org/svn/repo/dspace/trunk/dspace-oai</url>
</scm>
<modules> <modules>
<module>dspace-oai-api</module> <module>dspace-oai-api</module>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>dspace-parent</artifactId> <artifactId>dspace-parent</artifactId>
<groupId>org.dspace</groupId> <groupId>org.dspace</groupId>
<version>3.0-SNAPSHOT</version> <version>1.8.3</version>
<relativePath>..</relativePath> <relativePath>..</relativePath>
</parent> </parent>
@@ -11,19 +11,13 @@
<groupId>org.dspace</groupId> <groupId>org.dspace</groupId>
<artifactId>dspace-stats</artifactId> <artifactId>dspace-stats</artifactId>
<name>DSpace Solr Statistics Logging Client Library</name> <name>DSpace Solr Statistics Logging Client Library</name>
<version>3.0-SNAPSHOT</version> <version>1.8.3</version>
<description>Library of Shared UsageEvent and EventConsumer Tools for Logging to Solr.</description> <description>Library of Shared UsageEvent and EventConsumer Tools for Logging to Solr.</description>
<!-- <properties>
The Subversion repository location is used by Continuum to update <!-- This is the path to the root [dspace-src] directory. -->
against when changes have occured, this spawns a new build cycle and <root.basedir>${basedir}/..</root.basedir>
releases snapshots into the snapshot repository below. </properties>
-->
<scm>
<connection>scm:svn:http://scm.dspace.org/svn/repo/dspace/trunk/dspace-stats</connection>
<developerConnection>scm:svn:https://scm.dspace.org/svn/repo/dspace/trunk/dspace-stats</developerConnection>
<url>http://scm.dspace.org/svn/repo/dspace/trunk/dspace-stats</url>
</scm>
<developers> <developers>
<developer> <developer>

View File

@@ -1,47 +1,47 @@
/** /**
* The contents of this file are subject to the license and copyright * The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source * detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at * tree and available online at
* *
* http://www.dspace.org/license/ * http://www.dspace.org/license/
*/ */
package org.dspace.statistics.util; package org.dspace.statistics.util;
import org.dspace.core.ConfigurationManager; import org.dspace.core.ConfigurationManager;
import org.xbill.DNS.*; import org.xbill.DNS.*;
import java.io.IOException; import java.io.IOException;
/** /**
* XBill DNS resolver to retrieve hostnames for client IP addresses. * XBill DNS resolver to retrieve hostnames for client IP addresses.
* *
* @author kevinvandevelde at atmire.com * @author kevinvandevelde at atmire.com
* @author ben at atmire.com * @author ben at atmire.com
*/ */
public class DnsLookup { public class DnsLookup {
public static String reverseDns(String hostIp) throws IOException { public static String reverseDns(String hostIp) throws IOException {
Resolver res = new ExtendedResolver(); Resolver res = new ExtendedResolver();
// set the timeout, defaults to 200 milliseconds // set the timeout, defaults to 200 milliseconds
int timeout = ConfigurationManager.getIntProperty("solr-statistics", "resolver.timeout", 200); int timeout = ConfigurationManager.getIntProperty("solr-statistics", "resolver.timeout", 200);
res.setTimeout(0, timeout); res.setTimeout(0, timeout);
Name name = ReverseMap.fromAddress(hostIp); Name name = ReverseMap.fromAddress(hostIp);
int type = Type.PTR; int type = Type.PTR;
int dclass = DClass.IN; int dclass = DClass.IN;
Record rec = Record.newRecord(name, type, dclass); Record rec = Record.newRecord(name, type, dclass);
Message query = Message.newQuery(rec); Message query = Message.newQuery(rec);
Message response = res.send(query); Message response = res.send(query);
Record[] answers = response.getSectionArray(Section.ANSWER); Record[] answers = response.getSectionArray(Section.ANSWER);
if (answers.length == 0) if (answers.length == 0)
{ {
return hostIp; return hostIp;
} }
else else
{ {
return answers[0].rdataToString(); return answers[0].rdataToString();
} }
} }
} }

View File

@@ -1,155 +1,155 @@
/** /**
* The contents of this file are subject to the license and copyright * The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source * detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at * tree and available online at
* *
* http://www.dspace.org/license/ * http://www.dspace.org/license/
*/ */
package org.dspace.statistics.util; package org.dspace.statistics.util;
import org.apache.commons.cli.*; import org.apache.commons.cli.*;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.apache.tools.ant.taskdefs.Get; import org.apache.tools.ant.taskdefs.Get;
import org.dspace.core.ConfigurationManager; import org.dspace.core.ConfigurationManager;
import org.dspace.statistics.SolrLogger; import org.dspace.statistics.SolrLogger;
import java.io.*; import java.io.*;
import java.net.URL; import java.net.URL;
/** /**
* Class to load intermediate statistics files into solr * Class to load intermediate statistics files into solr
* *
* @author Stuart Lewis * @author Stuart Lewis
*/ */
public class StatisticsClient public class StatisticsClient
{ {
private static final Logger log = Logger.getLogger(StatisticsClient.class); private static final Logger log = Logger.getLogger(StatisticsClient.class);
/** /**
* Print the help message * Print the help message
* *
* @param options The command line options the user gave * @param options The command line options the user gave
* @param exitCode the system exit code to use * @param exitCode the system exit code to use
*/ */
private static void printHelp(Options options, int exitCode) private static void printHelp(Options options, int exitCode)
{ {
// print the help message // print the help message
HelpFormatter myhelp = new HelpFormatter(); HelpFormatter myhelp = new HelpFormatter();
myhelp.printHelp("StatisticsClient\n", options); myhelp.printHelp("StatisticsClient\n", options);
System.exit(exitCode); System.exit(exitCode);
} }
/** /**
* Main method to run the statistics importer. * Main method to run the statistics importer.
* *
* @param args The command line arguments * @param args The command line arguments
* @throws Exception If something goes wrong * @throws Exception If something goes wrong
*/ */
public static void main(String[] args) throws Exception public static void main(String[] args) throws Exception
{ {
CommandLineParser parser = new PosixParser(); CommandLineParser parser = new PosixParser();
Options options = new Options(); Options options = new Options();
options.addOption("u", "update-spider-files", false, options.addOption("u", "update-spider-files", false,
"Update Spider IP Files from internet into " + "Update Spider IP Files from internet into " +
ConfigurationManager.getProperty("dspace.dir") + "/config/spiders"); ConfigurationManager.getProperty("dspace.dir") + "/config/spiders");
options.addOption("m", "mark-spiders", false, "Update isBot Flag in Solr"); options.addOption("m", "mark-spiders", false, "Update isBot Flag in Solr");
options.addOption("f", "delete-spiders-by-flag", false, "Delete Spiders in Solr By isBot Flag"); options.addOption("f", "delete-spiders-by-flag", false, "Delete Spiders in Solr By isBot Flag");
options.addOption("i", "delete-spiders-by-ip", false, "Delete Spiders in Solr By IP Address"); options.addOption("i", "delete-spiders-by-ip", false, "Delete Spiders in Solr By IP Address");
options.addOption("o", "optimize", false, "Run maintenance on the SOLR index"); options.addOption("o", "optimize", false, "Run maintenance on the SOLR index");
options.addOption("b", "reindex-bitstreams", false, "Reindex the bitstreams to ensure we have the bundle name"); options.addOption("b", "reindex-bitstreams", false, "Reindex the bitstreams to ensure we have the bundle name");
options.addOption("r", "remove-deleted-bitstreams", false, "While indexing the bundle names remove the statistics about deleted bitstreams"); options.addOption("r", "remove-deleted-bitstreams", false, "While indexing the bundle names remove the statistics about deleted bitstreams");
options.addOption("h", "help", false, "help"); options.addOption("h", "help", false, "help");
CommandLine line = parser.parse(options, args); CommandLine line = parser.parse(options, args);
// Did the user ask to see the help? // Did the user ask to see the help?
if (line.hasOption('h')) if (line.hasOption('h'))
{ {
printHelp(options, 0); printHelp(options, 0);
} }
if(line.hasOption("u")) if(line.hasOption("u"))
{ {
StatisticsClient.updateSpiderFiles(); StatisticsClient.updateSpiderFiles();
} }
else if (line.hasOption('m')) else if (line.hasOption('m'))
{ {
SolrLogger.markRobotsByIP(); SolrLogger.markRobotsByIP();
} }
else if(line.hasOption('f')) else if(line.hasOption('f'))
{ {
SolrLogger.deleteRobotsByIsBotFlag(); SolrLogger.deleteRobotsByIsBotFlag();
} }
else if(line.hasOption('i')) else if(line.hasOption('i'))
{ {
SolrLogger.deleteRobotsByIP(); SolrLogger.deleteRobotsByIP();
} }
else if(line.hasOption('o')) else if(line.hasOption('o'))
{ {
SolrLogger.optimizeSOLR(); SolrLogger.optimizeSOLR();
} }
else if(line.hasOption('b')) else if(line.hasOption('b'))
{ {
SolrLogger.reindexBitstreamHits(line.hasOption('r')); SolrLogger.reindexBitstreamHits(line.hasOption('r'));
} }
else else
{ {
printHelp(options, 0); printHelp(options, 0);
} }
} }
/** /**
* Method to update Spiders in config directory. * Method to update Spiders in config directory.
*/ */
private static void updateSpiderFiles() private static void updateSpiderFiles()
{ {
try try
{ {
System.out.println("Downloading latest spider IP addresses:"); System.out.println("Downloading latest spider IP addresses:");
// Get the list URLs to download from // Get the list URLs to download from
String urls = ConfigurationManager.getProperty("solr-statistics", "spiderips.urls"); String urls = ConfigurationManager.getProperty("solr-statistics", "spiderips.urls");
if ((urls == null) || ("".equals(urls))) if ((urls == null) || ("".equals(urls)))
{ {
System.err.println(" - Missing setting from dspace.cfg: solr.spiderips.urls"); System.err.println(" - Missing setting from dspace.cfg: solr.spiderips.urls");
System.exit(0); System.exit(0);
} }
// Get the location of spiders directory // Get the location of spiders directory
File spiders = new File(ConfigurationManager.getProperty("dspace.dir"),"config/spiders"); File spiders = new File(ConfigurationManager.getProperty("dspace.dir"),"config/spiders");
if (!spiders.exists() && !spiders.mkdirs()) if (!spiders.exists() && !spiders.mkdirs())
{ {
log.error("Unable to create spiders directory"); log.error("Unable to create spiders directory");
} }
String[] values = urls.split(","); String[] values = urls.split(",");
for (String value : values) for (String value : values)
{ {
value = value.trim(); value = value.trim();
System.out.println(" Downloading: " + value); System.out.println(" Downloading: " + value);
URL url = new URL(value); URL url = new URL(value);
Get get = new Get(); Get get = new Get();
get.setDest(new File(spiders, url.getHost() + url.getPath().replace("/","-"))); get.setDest(new File(spiders, url.getHost() + url.getPath().replace("/","-")));
get.setSrc(url); get.setSrc(url);
get.setUseTimestamp(true); get.setUseTimestamp(true);
get.execute(); get.execute();
} }
} catch (Exception e) } catch (Exception e)
{ {
System.err.println(" - Error: " + e.getMessage()); System.err.println(" - Error: " + e.getMessage());
e.printStackTrace(); e.printStackTrace();
System.exit(1); System.exit(1);
} }
} }
} }

View File

@@ -1,427 +1,427 @@
/** /**
* The contents of this file are subject to the license and copyright * The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source * detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at * tree and available online at
* *
* http://www.dspace.org/license/ * http://www.dspace.org/license/
*/ */
package org.dspace.statistics.util; package org.dspace.statistics.util;
import org.apache.commons.cli.*; import org.apache.commons.cli.*;
import org.apache.commons.lang.time.DateFormatUtils; import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.solr.common.SolrInputDocument; import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer; import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.core.Constants; import org.dspace.core.Constants;
import org.dspace.core.ConfigurationManager; import org.dspace.core.ConfigurationManager;
import org.dspace.content.DSpaceObject; import org.dspace.content.DSpaceObject;
import org.dspace.content.Bitstream; import org.dspace.content.Bitstream;
import org.dspace.content.DCValue; import org.dspace.content.DCValue;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.eperson.EPerson; import org.dspace.eperson.EPerson;
import org.dspace.statistics.SolrLogger; import org.dspace.statistics.SolrLogger;
import java.util.Date; import java.util.Date;
import java.util.Map; import java.util.Map;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import com.maxmind.geoip.LookupService; import com.maxmind.geoip.LookupService;
import com.maxmind.geoip.Location; import com.maxmind.geoip.Location;
/** /**
* Test class to generate random statistics data. * Test class to generate random statistics data.
* Used for load testing of searches. Inputs are slow * Used for load testing of searches. Inputs are slow
* due to inefficient randomizer. * due to inefficient randomizer.
* *
* @author kevinvandevelde at atmire.com * @author kevinvandevelde at atmire.com
* @author ben at atmire.com * @author ben at atmire.com
*/ */
public class StatisticsDataGenerator { public class StatisticsDataGenerator {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
CommandLineParser parser = new PosixParser(); CommandLineParser parser = new PosixParser();
Options options = new Options(); Options options = new Options();
options.addOption("n", "nrlogs", true, options.addOption("n", "nrlogs", true,
"type: nr of logs to be generated"); "type: nr of logs to be generated");
options.addOption("s", "startDate", true, options.addOption("s", "startDate", true,
"type: the start date from which we start generating our logs"); "type: the start date from which we start generating our logs");
options.addOption("e", "endDate", true, options.addOption("e", "endDate", true,
"type: the end date from which we start generating our logs"); "type: the end date from which we start generating our logs");
options.addOption("a", "cms", true, "The starting id of our community"); options.addOption("a", "cms", true, "The starting id of our community");
options.addOption("b", "cme", true, "The end id of our community"); options.addOption("b", "cme", true, "The end id of our community");
options options
.addOption("c", "cls", true, .addOption("c", "cls", true,
"The starting id of our collection"); "The starting id of our collection");
options.addOption("d", "cle", true, "The end if of our collection"); options.addOption("d", "cle", true, "The end if of our collection");
options.addOption("f", "is", true, "The starting id of our item"); options.addOption("f", "is", true, "The starting id of our item");
options.addOption("g", "ie", true, "The end id of our item"); options.addOption("g", "ie", true, "The end id of our item");
options.addOption("h", "bs", true, "The starting id of our bitstream"); options.addOption("h", "bs", true, "The starting id of our bitstream");
options.addOption("i", "be", true, "The end id of our bitstream"); options.addOption("i", "be", true, "The end id of our bitstream");
options.addOption("j", "ps", true, "The starting id of our epersons"); options.addOption("j", "ps", true, "The starting id of our epersons");
options.addOption("k", "pe", true, "The end id of our epersons"); options.addOption("k", "pe", true, "The end id of our epersons");
CommandLine line = parser.parse(options, args); CommandLine line = parser.parse(options, args);
int nrLogs; int nrLogs;
long startDate; long startDate;
long endDate; long endDate;
long commStartId; long commStartId;
long commEndId; long commEndId;
long collStartId; long collStartId;
long collEndId; long collEndId;
long itemStartId; long itemStartId;
long itemEndId; long itemEndId;
long bitStartId; long bitStartId;
long bitEndId; long bitEndId;
long epersonStartId; long epersonStartId;
long epersonEndId; long epersonEndId;
if (line.hasOption("n")) if (line.hasOption("n"))
{ {
nrLogs = Integer.parseInt(line.getOptionValue("n")); nrLogs = Integer.parseInt(line.getOptionValue("n"));
} }
else { else {
System.out System.out
.println("We need to know how many logs we need to create"); .println("We need to know how many logs we need to create");
return; return;
} }
if (line.hasOption("s")) { if (line.hasOption("s")) {
startDate = getDateInMiliseconds(line.getOptionValue("s")); startDate = getDateInMiliseconds(line.getOptionValue("s"));
} else } else
{ {
startDate = getDateInMiliseconds("01/01/2006"); startDate = getDateInMiliseconds("01/01/2006");
} }
if (line.hasOption("e")) { if (line.hasOption("e")) {
endDate = getDateInMiliseconds(line.getOptionValue("e")); endDate = getDateInMiliseconds(line.getOptionValue("e"));
} else } else
{ {
endDate = new Date().getTime(); endDate = new Date().getTime();
} }
if (line.hasOption("a")) if (line.hasOption("a"))
{ {
commStartId = Long.parseLong(line.getOptionValue("a")); commStartId = Long.parseLong(line.getOptionValue("a"));
} }
else else
{ {
return; return;
} }
if (line.hasOption("b")) if (line.hasOption("b"))
{ {
commEndId = Long.parseLong(line.getOptionValue("b")); commEndId = Long.parseLong(line.getOptionValue("b"));
} }
else else
{ {
return; return;
} }
if (line.hasOption("c")) if (line.hasOption("c"))
{ {
collStartId = Long.parseLong(line.getOptionValue("c")); collStartId = Long.parseLong(line.getOptionValue("c"));
} }
else else
{ {
return; return;
} }
if (line.hasOption("d")) if (line.hasOption("d"))
{ {
collEndId = Long.parseLong(line.getOptionValue("d")); collEndId = Long.parseLong(line.getOptionValue("d"));
} }
else else
{ {
return; return;
} }
if (line.hasOption("f")) if (line.hasOption("f"))
{ {
itemStartId = Long.parseLong(line.getOptionValue("f")); itemStartId = Long.parseLong(line.getOptionValue("f"));
} }
else else
{ {
return; return;
} }
if (line.hasOption("g")) if (line.hasOption("g"))
{ {
itemEndId = Long.parseLong(line.getOptionValue("g")); itemEndId = Long.parseLong(line.getOptionValue("g"));
} }
else else
{ {
return; return;
} }
if (line.hasOption("h")) if (line.hasOption("h"))
{ {
bitStartId = Long.parseLong(line.getOptionValue("h")); bitStartId = Long.parseLong(line.getOptionValue("h"));
} }
else else
{ {
return; return;
} }
if (line.hasOption("i")) if (line.hasOption("i"))
{ {
bitEndId = Long.parseLong(line.getOptionValue("i")); bitEndId = Long.parseLong(line.getOptionValue("i"));
} }
else else
{ {
return; return;
} }
if (line.hasOption("j")) if (line.hasOption("j"))
{ {
epersonStartId = Long.parseLong(line.getOptionValue("j")); epersonStartId = Long.parseLong(line.getOptionValue("j"));
} }
else else
{ {
return; return;
} }
if (line.hasOption("k")) if (line.hasOption("k"))
{ {
epersonEndId = Long.parseLong(line.getOptionValue("k")); epersonEndId = Long.parseLong(line.getOptionValue("k"));
} }
else else
{ {
return; return;
} }
// Get the max id range // Get the max id range
long maxIdTotal = Math.max(commEndId, collEndId); long maxIdTotal = Math.max(commEndId, collEndId);
maxIdTotal = Math.max(maxIdTotal, itemEndId); maxIdTotal = Math.max(maxIdTotal, itemEndId);
maxIdTotal = Math.max(maxIdTotal, bitEndId); maxIdTotal = Math.max(maxIdTotal, bitEndId);
// We got 3/4 chance the person visting the dso is not logged in // We got 3/4 chance the person visting the dso is not logged in
epersonEndId *= 4; epersonEndId *= 4;
// We got all our parameters now get the rest // We got all our parameters now get the rest
Context context = new Context(); Context context = new Context();
// Find our solr server // Find our solr server
CommonsHttpSolrServer solr = new CommonsHttpSolrServer( CommonsHttpSolrServer solr = new CommonsHttpSolrServer(
ConfigurationManager.getProperty("solr-statistics", "server")); ConfigurationManager.getProperty("solr-statistics", "server"));
solr.deleteByQuery("*:*"); solr.deleteByQuery("*:*");
solr.commit(); solr.commit();
Map<String, String> metadataStorageInfo = SolrLogger.getMetadataStorageInfo(); Map<String, String> metadataStorageInfo = SolrLogger.getMetadataStorageInfo();
String prevIp = null; String prevIp = null;
String dbfile = ConfigurationManager.getProperty("solr-statistics", "dbfile"); String dbfile = ConfigurationManager.getProperty("solr-statistics", "dbfile");
LookupService cl = new LookupService(dbfile, LookupService cl = new LookupService(dbfile,
LookupService.GEOIP_STANDARD); LookupService.GEOIP_STANDARD);
int countryErrors = 0; int countryErrors = 0;
for (int i = 0; i < nrLogs; i++) { for (int i = 0; i < nrLogs; i++) {
String ip = ""; String ip = "";
Date time; Date time;
String continent; String continent;
String countryCode; String countryCode;
float longitude; float longitude;
float latitude; float latitude;
String city; String city;
// 1. Generate an ip for our user // 1. Generate an ip for our user
StringBuilder ipBuilder = new StringBuilder(); StringBuilder ipBuilder = new StringBuilder();
for (int j = 0; j < 4; j++) { for (int j = 0; j < 4; j++) {
ipBuilder.append(getRandomNumberInRange(0, 254)); ipBuilder.append(getRandomNumberInRange(0, 254));
if (j != 3) if (j != 3)
{ {
ipBuilder.append("."); ipBuilder.append(".");
} }
} }
ip = ipBuilder.toString(); ip = ipBuilder.toString();
// 2 Depending on our ip get all the location info // 2 Depending on our ip get all the location info
Location location; Location location;
try { try {
location = cl.getLocation(ip); location = cl.getLocation(ip);
} catch (Exception e) { } catch (Exception e) {
location = null; location = null;
} }
if (location == null) { if (location == null) {
// If we haven't got a prev ip this is pretty useless so move on // If we haven't got a prev ip this is pretty useless so move on
// to the next one // to the next one
if (prevIp == null) if (prevIp == null)
{ {
continue; continue;
} }
ip = prevIp; ip = prevIp;
location = cl.getLocation(ip); location = cl.getLocation(ip);
} }
city = location.city; city = location.city;
countryCode = location.countryCode; countryCode = location.countryCode;
longitude = location.longitude; longitude = location.longitude;
latitude = location.latitude; latitude = location.latitude;
try { try {
continent = LocationUtils.getContinentCode(countryCode); continent = LocationUtils.getContinentCode(countryCode);
} catch (Exception e) { } catch (Exception e) {
// We could get an error if our country == Europa this doesn't // We could get an error if our country == Europa this doesn't
// matter for generating statistics so ignore it // matter for generating statistics so ignore it
System.out.println("COUNTRY ERROR: " + countryCode); System.out.println("COUNTRY ERROR: " + countryCode);
countryErrors++; countryErrors++;
continue; continue;
} }
// 3. Generate a date that the object was visited // 3. Generate a date that the object was visited
time = new Date(getRandomNumberInRange(startDate, endDate)); time = new Date(getRandomNumberInRange(startDate, endDate));
// 4. Get our dspaceobject we are supposed to be working on // 4. Get our dspaceobject we are supposed to be working on
// We got mostly item views so lets say we got 1/2 chance that we // We got mostly item views so lets say we got 1/2 chance that we
// got an item view // got an item view
// What type have we got (PS: I know we haven't got 5 as a dso type // What type have we got (PS: I know we haven't got 5 as a dso type
// we can log but it is used so our item gets move traffic) // we can log but it is used so our item gets move traffic)
int type = (int) getRandomNumberInRange(0, 8); int type = (int) getRandomNumberInRange(0, 8);
if (type == Constants.BUNDLE || type >= 5) if (type == Constants.BUNDLE || type >= 5)
{ {
type = Constants.ITEM; type = Constants.ITEM;
} }
int dsoId = -1; int dsoId = -1;
// Now we need to find a valid id // Now we need to find a valid id
switch (type) { switch (type) {
case Constants.COMMUNITY: case Constants.COMMUNITY:
dsoId = (int) getRandomNumberInRange(commStartId, commEndId); dsoId = (int) getRandomNumberInRange(commStartId, commEndId);
break; break;
case Constants.COLLECTION: case Constants.COLLECTION:
dsoId = (int) getRandomNumberInRange(collStartId, collEndId); dsoId = (int) getRandomNumberInRange(collStartId, collEndId);
break; break;
case Constants.ITEM: case Constants.ITEM:
dsoId = (int) getRandomNumberInRange(itemStartId, itemEndId); dsoId = (int) getRandomNumberInRange(itemStartId, itemEndId);
break; break;
case Constants.BITSTREAM: case Constants.BITSTREAM:
dsoId = (int) getRandomNumberInRange(bitStartId, bitEndId); dsoId = (int) getRandomNumberInRange(bitStartId, bitEndId);
break; break;
} }
// Now find our dso // Now find our dso
DSpaceObject dso = DSpaceObject.find(context, type, dsoId); DSpaceObject dso = DSpaceObject.find(context, type, dsoId);
if (dso instanceof Bitstream) { if (dso instanceof Bitstream) {
Bitstream bit = (Bitstream) dso; Bitstream bit = (Bitstream) dso;
if (bit.getFormat().isInternal()) { if (bit.getFormat().isInternal()) {
dso = null; dso = null;
} }
} }
// Make sure we got a dso // Make sure we got a dso
boolean substract = false; boolean substract = false;
while (dso == null) { while (dso == null) {
// If our dsoId gets higher then our maxIdtotal we need to lower // If our dsoId gets higher then our maxIdtotal we need to lower
// to find a valid id // to find a valid id
if (dsoId == maxIdTotal) if (dsoId == maxIdTotal)
{ {
substract = true; substract = true;
} }
if (substract) if (substract)
{ {
dsoId--; dsoId--;
} }
else else
{ {
dsoId++; dsoId++;
} }
dso = DSpaceObject.find(context, type, dsoId); dso = DSpaceObject.find(context, type, dsoId);
if (dso instanceof Bitstream) { if (dso instanceof Bitstream) {
Bitstream bit = (Bitstream) dso; Bitstream bit = (Bitstream) dso;
if (bit.getFormat().isInternal()) { if (bit.getFormat().isInternal()) {
dso = null; dso = null;
} }
} }
// System.out.println("REFIND"); // System.out.println("REFIND");
} }
// Find the person who is visting us // Find the person who is visting us
int epersonId = (int) getRandomNumberInRange(epersonStartId, epersonEndId); int epersonId = (int) getRandomNumberInRange(epersonStartId, epersonEndId);
EPerson eperson = EPerson.find(context, epersonId); EPerson eperson = EPerson.find(context, epersonId);
if (eperson == null) if (eperson == null)
{ {
epersonId = -1; epersonId = -1;
} }
// System.out.println(ip); // System.out.println(ip);
// System.out.println(country + " " + // System.out.println(country + " " +
// LocationUtils.getCountryName(countryCode)); // LocationUtils.getCountryName(countryCode));
// Resolve the dns // Resolve the dns
String dns = null; String dns = null;
try { try {
dns = DnsLookup.reverseDns(ip); dns = DnsLookup.reverseDns(ip);
} catch (Exception e) { } catch (Exception e) {
} }
System.out.println(ip); System.out.println(ip);
System.out.println(dns); System.out.println(dns);
// Save it in our server // Save it in our server
SolrInputDocument doc1 = new SolrInputDocument(); SolrInputDocument doc1 = new SolrInputDocument();
doc1.addField("ip", ip); doc1.addField("ip", ip);
doc1.addField("type", dso.getType()); doc1.addField("type", dso.getType());
doc1.addField("id", dso.getID()); doc1.addField("id", dso.getID());
doc1.addField("time", DateFormatUtils.format(time, doc1.addField("time", DateFormatUtils.format(time,
SolrLogger.DATE_FORMAT_8601)); SolrLogger.DATE_FORMAT_8601));
doc1.addField("continent", continent); doc1.addField("continent", continent);
// doc1.addField("country", country); // doc1.addField("country", country);
doc1.addField("countryCode", countryCode); doc1.addField("countryCode", countryCode);
doc1.addField("city", city); doc1.addField("city", city);
doc1.addField("latitude", latitude); doc1.addField("latitude", latitude);
doc1.addField("longitude", longitude); doc1.addField("longitude", longitude);
if (epersonId > 0) if (epersonId > 0)
{ {
doc1.addField("epersonid", epersonId); doc1.addField("epersonid", epersonId);
} }
if (dns != null) if (dns != null)
{ {
doc1.addField("dns", dns.toLowerCase()); doc1.addField("dns", dns.toLowerCase());
} }
if (dso instanceof Item) { if (dso instanceof Item) {
Item item = (Item) dso; Item item = (Item) dso;
// Store the metadata // Store the metadata
for (Map.Entry<String, String> entry : metadataStorageInfo.entrySet()) for (Map.Entry<String, String> entry : metadataStorageInfo.entrySet())
{ {
String dcField = entry.getValue(); String dcField = entry.getValue();
DCValue[] vals = item.getMetadata(dcField.split("\\.")[0], DCValue[] vals = item.getMetadata(dcField.split("\\.")[0],
dcField.split("\\.")[1], dcField.split("\\.")[2], dcField.split("\\.")[1], dcField.split("\\.")[2],
Item.ANY); Item.ANY);
for (DCValue val1 : vals) { for (DCValue val1 : vals) {
String val = val1.value; String val = val1.value;
doc1.addField(entry.getKey(), val); doc1.addField(entry.getKey(), val);
doc1.addField(entry.getKey() + "_search", val.toLowerCase()); doc1.addField(entry.getKey() + "_search", val.toLowerCase());
} }
} }
} }
SolrLogger.storeParents(doc1, dso); SolrLogger.storeParents(doc1, dso);
solr.add(doc1); solr.add(doc1);
// Make sure we have a previous ip // Make sure we have a previous ip
prevIp = ip; prevIp = ip;
} }
System.out.println("Nr of countryErrors: " + countryErrors); System.out.println("Nr of countryErrors: " + countryErrors);
// Commit at the end cause it takes a while // Commit at the end cause it takes a while
solr.commit(); solr.commit();
} }
/** /**
* Method returns a random integer between the given int * Method returns a random integer between the given int
* *
* @param min * @param min
* the random number must be greater or equal to this * the random number must be greater or equal to this
* @param max * @param max
* the random number must be smaller or equal to this * the random number must be smaller or equal to this
* @return a random in * @return a random in
*/ */
private static long getRandomNumberInRange(long min, long max) { private static long getRandomNumberInRange(long min, long max) {
return min + (long) (Math.random() * ((max - min) + 1)); return min + (long) (Math.random() * ((max - min) + 1));
} }
/** /**
* Method to get the miliseconds from a datestring * Method to get the miliseconds from a datestring
* *
* @param dateString * @param dateString
* the string containing our date in a string * the string containing our date in a string
* @return the nr of miliseconds in the given datestring * @return the nr of miliseconds in the given datestring
* @throws java.text.ParseException * @throws java.text.ParseException
* should not happen * should not happen
*/ */
private static long getDateInMiliseconds(String dateString) private static long getDateInMiliseconds(String dateString)
throws java.text.ParseException { throws java.text.ParseException {
SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy"); SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
return formatter.parse(dateString).getTime(); return formatter.parse(dateString).getTime();
} }
} }

View File

@@ -5,15 +5,20 @@
<packaging>jar</packaging> <packaging>jar</packaging>
<groupId>org.dspace</groupId> <groupId>org.dspace</groupId>
<artifactId>dspace-sword-client-api</artifactId> <artifactId>dspace-sword-client-api</artifactId>
<version>3.0-SNAPSHOT</version> <version>1.8.3</version>
<name>DSpace Sword Client :: Sword Client API</name> <name>DSpace Sword Client :: Sword Client API</name>
<parent> <parent>
<groupId>org.dspace</groupId> <groupId>org.dspace</groupId>
<artifactId>dspace-sword-client</artifactId> <artifactId>dspace-sword-client</artifactId>
<version>3.0-SNAPSHOT</version> <version>1.8.3</version>
<relativePath>..</relativePath> <relativePath>..</relativePath>
</parent> </parent>
<properties>
<!-- This is the path to the root [dspace-src] directory. -->
<root.basedir>${basedir}/../..</root.basedir>
</properties>
<dependencies> <dependencies>
<dependency> <dependency>
@@ -26,18 +31,5 @@
</dependency> </dependency>
</dependencies> </dependencies>
<!--
The Subversion repository location is used by Continuum to update
against when changes have occured, this spawns a new build cycle
and releases snapshots into the snapshot repository below.
-->
<scm>
<connection>scm:svn:http://scm.dspace.org/svn/repo/dspace/trunk/dspace-sword-client/dspace-sword-client-api</connection>
<developerConnection>
scm:svn:https://scm.dspace.org/svn/repo/dspace/trunk/dspace-sword-client/dspace-sword-client-api
</developerConnection>
<url>http://scm.dspace.org/svn/repo/dspace/trunk/dspace-sword-client/dspace-sword-client-api</url>
</scm>
</project> </project>

View File

@@ -1,234 +1,234 @@
/** /**
* The contents of this file are subject to the license and copyright * The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source * detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at * tree and available online at
* *
* http://www.dspace.org/license/ * http://www.dspace.org/license/
*/ */
package org.dspace.sword.client; package org.dspace.sword.client;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.dspace.content.DSpaceObject; import org.dspace.content.DSpaceObject;
import org.dspace.content.packager.PackageDisseminator; import org.dspace.content.packager.PackageDisseminator;
import org.dspace.content.packager.PackageParameters; import org.dspace.content.packager.PackageParameters;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.core.PluginManager; import org.dspace.core.PluginManager;
import org.dspace.handle.HandleManager; import org.dspace.handle.HandleManager;
import org.dspace.sword.client.exceptions.HttpException; import org.dspace.sword.client.exceptions.HttpException;
import org.dspace.sword.client.exceptions.InvalidHandleException; import org.dspace.sword.client.exceptions.InvalidHandleException;
import org.dspace.sword.client.exceptions.PackageFormatException; import org.dspace.sword.client.exceptions.PackageFormatException;
import org.dspace.sword.client.exceptions.PackagerException; import org.dspace.sword.client.exceptions.PackagerException;
import org.purl.sword.base.DepositResponse; import org.purl.sword.base.DepositResponse;
import org.purl.sword.base.SWORDEntry; import org.purl.sword.base.SWORDEntry;
import org.purl.sword.base.ServiceDocument; import org.purl.sword.base.ServiceDocument;
import org.purl.sword.client.Client; import org.purl.sword.client.Client;
import org.purl.sword.client.PostMessage; import org.purl.sword.client.PostMessage;
import org.purl.sword.client.SWORDClientException; import org.purl.sword.client.SWORDClientException;
import org.purl.sword.client.Status; import org.purl.sword.client.Status;
import java.io.File; import java.io.File;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.UUID; import java.util.UUID;
/** /**
* User: Robin Taylor * User: Robin Taylor
* Date: 15/02/11 * Date: 15/02/11
* Time: 21:12 * Time: 21:12
*/ */
public class DSpaceSwordClient public class DSpaceSwordClient
{ {
private Client client; private Client client;
private PostMessage message; private PostMessage message;
private String onBehalfOf; private String onBehalfOf;
private String serviceDocUrl; private String serviceDocUrl;
private String filename; private String filename;
private String tempDirectory; private String tempDirectory;
private String packageFormat; private String packageFormat;
private PackageParameters pkgParams; private PackageParameters pkgParams;
private static Logger log = Logger.getLogger(DSpaceSwordClient.class); private static Logger log = Logger.getLogger(DSpaceSwordClient.class);
public DSpaceSwordClient() public DSpaceSwordClient()
{ {
client = new Client(); client = new Client();
// The default timeout is way too low so increase it x10. // The default timeout is way too low so increase it x10.
client.setSocketTimeout(200000); client.setSocketTimeout(200000);
client.setUserAgent("DSpace Sword Client"); client.setUserAgent("DSpace Sword Client");
message = new PostMessage(); message = new PostMessage();
message.setUseMD5(false); message.setUseMD5(false);
message.setChecksumError(false); message.setChecksumError(false);
message.setVerbose(false); message.setVerbose(false);
message.setNoOp(false); message.setNoOp(false);
message.setUserAgent("DSpace Sword Client"); message.setUserAgent("DSpace Sword Client");
setFilename(); setFilename();
} }
public void setFilename() public void setFilename()
{ {
if ((tempDirectory == null) || (tempDirectory.equals(""))) if ((tempDirectory == null) || (tempDirectory.equals("")))
{ {
tempDirectory = System.getProperty("java.io.tmpdir"); tempDirectory = System.getProperty("java.io.tmpdir");
} }
if (!tempDirectory.endsWith(System.getProperty("file.separator"))) if (!tempDirectory.endsWith(System.getProperty("file.separator")))
{ {
tempDirectory += System.getProperty("file.separator"); tempDirectory += System.getProperty("file.separator");
} }
filename = tempDirectory + UUID.randomUUID().toString(); filename = tempDirectory + UUID.randomUUID().toString();
} }
public void setRemoteServer(String chosenUrl) throws MalformedURLException public void setRemoteServer(String chosenUrl) throws MalformedURLException
{ {
serviceDocUrl = chosenUrl; serviceDocUrl = chosenUrl;
URL url = new URL(chosenUrl); URL url = new URL(chosenUrl);
client.setServer(url.getHost(), url.getPort()); client.setServer(url.getHost(), url.getPort());
} }
public void setCredentials(String username, String password, String onBehalfOf) public void setCredentials(String username, String password, String onBehalfOf)
{ {
client.setCredentials(username, password); client.setCredentials(username, password);
this.onBehalfOf = onBehalfOf; this.onBehalfOf = onBehalfOf;
} }
public ServiceDocument getServiceDocument() throws HttpException, SWORDClientException public ServiceDocument getServiceDocument() throws HttpException, SWORDClientException
{ {
log.info("Getting Sword Service Document from " + serviceDocUrl); log.info("Getting Sword Service Document from " + serviceDocUrl);
ServiceDocument sd = client.getServiceDocument(serviceDocUrl, onBehalfOf); ServiceDocument sd = client.getServiceDocument(serviceDocUrl, onBehalfOf);
Status status = client.getStatus(); Status status = client.getStatus();
if (status.getCode() == 200) if (status.getCode() == 200)
{ {
log.info("Sword Service Document successfully retrieved from " + serviceDocUrl); log.info("Sword Service Document successfully retrieved from " + serviceDocUrl);
return sd; return sd;
} }
else else
{ {
log.info("Error retrieving Sword Service Document from " + serviceDocUrl); log.info("Error retrieving Sword Service Document from " + serviceDocUrl);
throw new HttpException("No service document available - Http status code " + status); throw new HttpException("No service document available - Http status code " + status);
} }
} }
public void setCollection(String destination) public void setCollection(String destination)
{ {
message.setDestination(destination); message.setDestination(destination);
} }
public void setFileType(String fileType) public void setFileType(String fileType)
{ {
message.setFiletype(fileType); message.setFiletype(fileType);
} }
public void setPackageFormat(String packageFormat) throws PackageFormatException public void setPackageFormat(String packageFormat) throws PackageFormatException
{ {
// todo : Read all this stuff from config // todo : Read all this stuff from config
if (packageFormat.equals("http://purl.org/net/sword-types/METSDSpaceSIP")) if (packageFormat.equals("http://purl.org/net/sword-types/METSDSpaceSIP"))
{ {
this.packageFormat = "METS"; this.packageFormat = "METS";
pkgParams = new PackageParameters(); pkgParams = new PackageParameters();
pkgParams.addProperty("dmd", "MODS"); pkgParams.addProperty("dmd", "MODS");
message.setFormatNamespace("http://purl.org/net/sword-types/METSDSpaceSIP"); message.setFormatNamespace("http://purl.org/net/sword-types/METSDSpaceSIP");
} }
else else
{ {
throw new PackageFormatException("Invalid package format selected"); throw new PackageFormatException("Invalid package format selected");
} }
} }
public void deposit(Context context, String handle) throws InvalidHandleException, PackagerException, SWORDClientException, PackageFormatException, HttpException public void deposit(Context context, String handle) throws InvalidHandleException, PackagerException, SWORDClientException, PackageFormatException, HttpException
{ {
File file = new File(filename); File file = new File(filename);
createPackage(context, handle, file); createPackage(context, handle, file);
sendMessage(); sendMessage();
} }
/** /**
* Create the package and write it to disk. * Create the package and write it to disk.
*/ */
public void createPackage(Context context, String handle, File file) throws InvalidHandleException, PackagerException, PackageFormatException public void createPackage(Context context, String handle, File file) throws InvalidHandleException, PackagerException, PackageFormatException
{ {
// Note - in the future we may need to allow for more than zipped up packages. // Note - in the future we may need to allow for more than zipped up packages.
PackageDisseminator dip = (PackageDisseminator) PluginManager PackageDisseminator dip = (PackageDisseminator) PluginManager
.getNamedPlugin(PackageDisseminator.class, packageFormat); .getNamedPlugin(PackageDisseminator.class, packageFormat);
if (dip == null) if (dip == null)
{ {
log.error("Error - unknown package type " + packageFormat); log.error("Error - unknown package type " + packageFormat);
throw new PackageFormatException("Unknown package type " + packageFormat); throw new PackageFormatException("Unknown package type " + packageFormat);
} }
DSpaceObject dso = null; DSpaceObject dso = null;
try try
{ {
dso = HandleManager.resolveToObject(context, handle); dso = HandleManager.resolveToObject(context, handle);
} }
catch (SQLException e) catch (SQLException e)
{ {
log.error("Unable to resolve handle " + handle); log.error("Unable to resolve handle " + handle);
throw new InvalidHandleException("Unable to resolve handle " + handle); throw new InvalidHandleException("Unable to resolve handle " + handle);
} }
if (dso == null) if (dso == null)
{ {
log.error("Unable to resolve handle " + handle); log.error("Unable to resolve handle " + handle);
throw new InvalidHandleException("Unable to resolve handle " + handle); throw new InvalidHandleException("Unable to resolve handle " + handle);
} }
try try
{ {
dip.disseminate(context, dso, pkgParams, file); dip.disseminate(context, dso, pkgParams, file);
} }
catch (Exception e) catch (Exception e)
{ {
log.error("Error creating package", e); log.error("Error creating package", e);
throw new PackagerException("Error creating package", e); throw new PackagerException("Error creating package", e);
} }
} }
/** /**
* Reads the file, probably a zipped package, and sends it to the Sword server. * Reads the file, probably a zipped package, and sends it to the Sword server.
* *
* @return A unique ID returned by a successful deposit * @return A unique ID returned by a successful deposit
* @throws org.purl.sword.client.SWORDClientException * @throws org.purl.sword.client.SWORDClientException
* *
*/ */
public String sendMessage() throws SWORDClientException, HttpException public String sendMessage() throws SWORDClientException, HttpException
{ {
message.setFilepath(filename); message.setFilepath(filename);
DepositResponse resp = client.postFile(message); DepositResponse resp = client.postFile(message);
Status status = client.getStatus(); Status status = client.getStatus();
if ((status.getCode() == 201) || (status.getCode() == 202)) if ((status.getCode() == 201) || (status.getCode() == 202))
{ {
SWORDEntry se = resp.getEntry(); SWORDEntry se = resp.getEntry();
return se.getId(); return se.getId();
} }
else else
{ {
String error = status.getCode() + " " + status.getMessage() + " - " + resp.getEntry().getSummary().getContent(); String error = status.getCode() + " " + status.getMessage() + " - " + resp.getEntry().getSummary().getContent();
log.info("Error depositing Sword package : " + error); log.info("Error depositing Sword package : " + error);
throw new HttpException(error); throw new HttpException(error);
} }
} }
} }

View File

@@ -1,111 +1,111 @@
/** /**
* The contents of this file are subject to the license and copyright * The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source * detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at * tree and available online at
* *
* http://www.dspace.org/license/ * http://www.dspace.org/license/
*/ */
package org.dspace.sword.client; package org.dspace.sword.client;
import org.dspace.core.ConfigurationManager; import org.dspace.core.ConfigurationManager;
import org.purl.sword.base.Collection; import org.purl.sword.base.Collection;
import org.purl.sword.base.ServiceDocument; import org.purl.sword.base.ServiceDocument;
import org.purl.sword.base.SwordAcceptPackaging; import org.purl.sword.base.SwordAcceptPackaging;
import org.purl.sword.base.Workspace; import org.purl.sword.base.Workspace;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
/** /**
* User: Robin Taylor * User: Robin Taylor
* Date: 15/02/11 * Date: 15/02/11
* Time: 21:12 * Time: 21:12
*/ */
public class ServiceDocumentHelper { public class ServiceDocumentHelper {
public static List<Collection> getCollections(ServiceDocument serviceDoc) public static List<Collection> getCollections(ServiceDocument serviceDoc)
{ {
List<Collection> allCollections = new ArrayList<Collection>(); List<Collection> allCollections = new ArrayList<Collection>();
List<Workspace> workspaces = serviceDoc.getService().getWorkspacesList(); List<Workspace> workspaces = serviceDoc.getService().getWorkspacesList();
for (Workspace ws : workspaces) for (Workspace ws : workspaces)
{ {
List<Collection> collections = ws.getCollections(); List<Collection> collections = ws.getCollections();
allCollections.addAll(collections); allCollections.addAll(collections);
} }
return allCollections; return allCollections;
} }
public static Collection getCollection(ServiceDocument serviceDoc, String location) public static Collection getCollection(ServiceDocument serviceDoc, String location)
{ {
List<Collection> allCollections = getCollections(serviceDoc); List<Collection> allCollections = getCollections(serviceDoc);
for (Collection collection : allCollections) for (Collection collection : allCollections)
{ {
if (collection.getLocation().equals(location)) if (collection.getLocation().equals(location))
{ {
return collection; return collection;
} }
} }
// If we got here then we didn't find a match. // If we got here then we didn't find a match.
return null; return null;
} }
public static String[] getCommonFileTypes(ServiceDocument serviceDoc, String location) public static String[] getCommonFileTypes(ServiceDocument serviceDoc, String location)
{ {
String FTsString = ConfigurationManager.getProperty("sword-client", "file-types"); String FTsString = ConfigurationManager.getProperty("sword-client", "file-types");
String[] clientFTsArray = FTsString.split(","); String[] clientFTsArray = FTsString.split(",");
List<String> clientFTs = Arrays.asList(clientFTsArray); List<String> clientFTs = Arrays.asList(clientFTsArray);
List<String> commonFTs = new ArrayList<String>(); List<String> commonFTs = new ArrayList<String>();
Collection collection = ServiceDocumentHelper.getCollection(serviceDoc, location); Collection collection = ServiceDocumentHelper.getCollection(serviceDoc, location);
String[] serverFTs = collection.getAccepts(); String[] serverFTs = collection.getAccepts();
for (String serverFT : serverFTs) for (String serverFT : serverFTs)
{ {
if (clientFTs.contains(serverFT)) if (clientFTs.contains(serverFT))
{ {
commonFTs.add(serverFT); commonFTs.add(serverFT);
} }
} }
return commonFTs.toArray(new String[commonFTs.size()]); return commonFTs.toArray(new String[commonFTs.size()]);
} }
public static String[] getCommonPackageFormats(ServiceDocument serviceDoc, String location) public static String[] getCommonPackageFormats(ServiceDocument serviceDoc, String location)
{ {
String PFsString = ConfigurationManager.getProperty("sword-client", "package-formats"); String PFsString = ConfigurationManager.getProperty("sword-client", "package-formats");
String[] clientPFsArray = PFsString.split(","); String[] clientPFsArray = PFsString.split(",");
List<String> clientPFs = Arrays.asList(clientPFsArray); List<String> clientPFs = Arrays.asList(clientPFsArray);
List<String> commonPFs = new ArrayList<String>(); List<String> commonPFs = new ArrayList<String>();
Collection collection = ServiceDocumentHelper.getCollection(serviceDoc, location); Collection collection = ServiceDocumentHelper.getCollection(serviceDoc, location);
List<SwordAcceptPackaging> serverPFs = collection.getAcceptPackaging(); List<SwordAcceptPackaging> serverPFs = collection.getAcceptPackaging();
for (SwordAcceptPackaging serverPF : serverPFs) for (SwordAcceptPackaging serverPF : serverPFs)
{ {
if (clientPFs.contains(serverPF.getContent())) if (clientPFs.contains(serverPF.getContent()))
{ {
commonPFs.add(serverPF.getContent()); commonPFs.add(serverPF.getContent());
} }
} }
return commonPFs.toArray(new String[commonPFs.size()]); return commonPFs.toArray(new String[commonPFs.size()]);
} }
public static String[] getPackageFormats(Collection collection) public static String[] getPackageFormats(Collection collection)
{ {
List<String> packageFormats = new ArrayList<String>(); List<String> packageFormats = new ArrayList<String>();
List<SwordAcceptPackaging> pfs = collection.getAcceptPackaging(); List<SwordAcceptPackaging> pfs = collection.getAcceptPackaging();
for (SwordAcceptPackaging pf : pfs) for (SwordAcceptPackaging pf : pfs)
{ {
packageFormats.add(pf.getContent()); packageFormats.add(pf.getContent());
} }
return packageFormats.toArray(new String[pfs.size()]); return packageFormats.toArray(new String[pfs.size()]);
} }
} }

Some files were not shown because too many files have changed in this diff Show More