Giter VIP home page Giter VIP logo

dspace / dspace Goto Github PK

View Code? Open in Web Editor NEW
841.0 116.0 1.3K 166.4 MB

(Official) The DSpace digital asset management system that powers your Institutional Repository

Home Page: https://wiki.lyrasis.org/display/DSDOC7x/

License: BSD 3-Clause "New" or "Revised" License

Java 97.51% HTML 0.25% XSLT 1.86% CSS 0.01% JavaScript 0.03% Shell 0.04% Perl 0.04% Batchfile 0.02% FreeMarker 0.01% TeX 0.01% Dockerfile 0.03% Rich Text Format 0.20% PLpgSQL 0.01%
dspace repository java open-access open-source rest-api

dspace's Introduction

DSpace

Build Status

DSpace Documentation | DSpace Releases | DSpace Wiki | Support

Overview

DSpace open source software is a turnkey repository application used by more than 2,000 organizations and institutions worldwide to provide durable access to digital resources. For more information, visit http://www.dspace.org/

DSpace consists of both a Java-based backend and an Angular-based frontend.

Prior versions of DSpace (v6.x and below) used two different UIs (XMLUI and JSPUI). Those UIs are no longer supported in v7 (and above).

  • A maintenance branch for older versions is still available, see dspace-6_x for 6.x maintenance.

Downloads

Documentation / Installation

Documentation for each release may be viewed online or downloaded via our Documentation Wiki.

The latest DSpace Installation instructions are available at: https://wiki.lyrasis.org/display/DSDOC7x/Installing+DSpace

Please be aware that, as a Java web application, DSpace requires a database (PostgreSQL) and a servlet container (usually Tomcat) in order to function. More information about these and all other prerequisites can be found in the Installation instructions above.

Running DSpace 7 in Docker

NOTE: At this time, we do not have production-ready Docker images for DSpace. That said, we do have quick-start Docker Compose scripts for development or testing purposes.

See Running DSpace 7 with Docker Compose

Contributing

See Contributing documentation

Getting Help

DSpace provides public mailing lists where you can post questions or raise topics for discussion. We welcome everyone to participate in these lists:

Great Q&A is also available under the DSpace tag on Stackoverflow

Additional support options are at https://wiki.lyrasis.org/display/DSPACE/Support

DSpace also has an active service provider network. If you'd rather hire a service provider to install, upgrade, customize or host DSpace, then we recommend getting in touch with one of our Registered Service Providers.

Issue Tracker

DSpace uses GitHub to track issues:

Testing

Running Tests

By default, in DSpace, Unit Tests and Integration Tests are disabled. However, they are run automatically by GitHub Actions for all Pull Requests and code commits.

  • How to run both Unit Tests (via maven-surefire-plugin) and Integration Tests (via maven-failsafe-plugin):
    mvn install -DskipUnitTests=false -DskipIntegrationTests=false
    
  • How to run only Unit Tests:
    mvn test -DskipUnitTests=false
    
  • How to run a single Unit Test
    # Run all tests in a specific test class
    # NOTE: failIfNoTests=false is required to skip tests in other modules
    mvn test -DskipUnitTests=false -Dtest=[full.package.testClassName] -DfailIfNoTests=false
    
    # Run one test method in a specific test class
    mvn test -DskipUnitTests=false -Dtest=[full.package.testClassName]#[testMethodName] -DfailIfNoTests=false
    
  • How to run only Integration Tests
    mvn install -DskipIntegrationTests=false
    
  • How to run a single Integration Test
    # Run all integration tests in a specific test class
    # NOTE: failIfNoTests=false is required to skip tests in other modules
    mvn install -DskipIntegrationTests=false -Dit.test=[full.package.testClassName] -DfailIfNoTests=false
    
    # Run one test method in a specific test class
    mvn install -DskipIntegrationTests=false -Dit.test=[full.package.testClassName]#[testMethodName] -DfailIfNoTests=false
    
  • How to run only tests of a specific DSpace module
    # Before you can run only one module's tests, other modules may need installing into your ~/.m2
    cd [dspace-src]
    mvn clean install
    
    # Then, move into a module subdirectory, and run the test command
    cd [dspace-src]/dspace-server-webapp
    # Choose your test command from the lists above
    

License

DSpace source code is freely available under a standard BSD 3-Clause license. The full license is available in the LICENSE file or online at http://www.dspace.org/license/

DSpace uses third-party libraries which may be distributed under different licenses. Those licenses are listed in the LICENSES_THIRD_PARTY file.

dspace's People

Contributors

abollini avatar aschweer avatar benbosman avatar bruno-atmire avatar cjuergen avatar cwilper avatar frabacche avatar grahamtriggs avatar helix84 avatar kevinvdv avatar kshepherd avatar lap82 avatar lucagiamminonni avatar marieverdonck avatar mdiggory avatar micheleboychuk avatar mspalti avatar mwoodiupui avatar peterdietz avatar pnbecker avatar raf-atmire avatar richard-jones avatar rtansley avatar scott-phillips avatar scottyeadon avatar stuartlewis avatar tdonohue avatar terrywbrady avatar tomdesair avatar yanadepauw avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dspace's Issues

[DS-7] HTML tags not stripped in statistics display - ID: 1896225

Imported from JIRA [DS-7] created by kipkorir2008

HTML tags are not stripped in the statistics display of searches that have
taken place.

E.g. search for '

Make sure 'search.floor' is set to 1 in dstat.cfg, and run the stats.
You'll see the effect it has on the page, near the bottom where it shows
searches that have taken place.

[DS-27] NullPointerException possible in review.jsp - ID: 1571645

Imported from JIRA [DS-27] created by kipkorir2008

In layoutSection, if inputType.equals("dropdown"),
Utils.addEntities is passed the result of
DCInput.getDisplayString(). getDisplayString is
documented to return null if the input stored-value is
not matched, which will cause addEntities to throw a
NPE. The code should probably look more like the
"qualdrop_value" case below it, i.e. change:

row.append(Utils.addEntities(displayVal));

to:

if (displayVal != null)
{
row.append(Utils.addEntities(displayVal));
}

I am still working the problem report, but I believe
that I've seen this NPE thrown in practice. In any
case the code in review.jsp does not gracefully handle
a documented return value.

BTW the doc comments for getDisplayString (and
getStoredString) don't seem to match the code.

[DS-4] Refactor LDAPServlet to use Stackable Authentication - ID: 2057231

Imported from JIRA [DS-4] created by kipkorir2008

At present LDAPServlet performs LDAP authentication within itself, rather
than delegating it to the stackable authentication.

This patch fixes that by stripping out all of the LDAP code, and replacing
it with:

int status = AuthenticationManager.authenticate(context, netid, password,
null, request);

[DS-47] Add support for rendering DOI links in JSPUI (1.4, 1.5) - ID: 2521493

Imported from JIRA [DS-47] created by kipkorir2008

SUMMARY / PURPOSE

Add support in JSPUI for identifiers stored in dc.identifier.doi to be
rendered as links to http://dx.doi.org/.
Patches against 1.4.2 source release, 1.5.1 source release, and 1.5.x
branch (revision 3371) are supplied.
As well as applying these patches, changes will need to be made to
dspace.cfg, and possibly Messages.properties, input-forms.xml and the
metadata registry if DOI identifiers haven't been used at all up to this
point.

INTRODUCTION

This patch is being uploaded as I have been asked by some members of the
community to share the changes we've made to be able to nicely use/display
DOI identifiers. If this is not the appropriate place for such patches,
please remove or let me know.

I am not sure if it should be included in DSpace or not – if it was to be,
the default Messages.properties, dublin-core-types.xml and dspace.cfg would
need patching as well. I'm not supplying patches for those here as I didn't
want to confuse or mislead anyone wanting to apply this patch to their
existing DSpace instance.

I am happy to supply patches against default (latest revision) copies of
these other files if people think that this should be included in the 1.5
branch.

INSTRUCTIONS / USAGE:

Download the patch that is appropriate for your version of DSpace.
The 1.5 SVN patch has been tested against DSpace 1.5.x branch, and is an
svn diff.
The 1.5 non-SVN patch has been tested against DSpace 1.5.1 source release,
and is a standard diff.
The 1.4.2 patch has been tested against DSpace 1.4.2 source release.

The diffs all make changes to ItemTag.java, so if you have already made
changes to this file, please review the patch and consider making the
changes manually, or merging safely with SVN in the case of the SVN diff.

As per usual, if you're not using SVN, back up your source code first!

The patches should all be applied from the root of your DSpace source
directory. Use subversion to patch if you are applying the SVN patch to
your local branch, or "patch -p0 < filename.diff" if you are applying one
of the patches made against the source releases. Again, this is from the
root of the DSpace source directory (ie. the directory that was created
when you unzipped/untarred your DSpace source release archive). If patch
fails, complaining that it can't find a file to patch, you likely are
trying to patch from the wrong directory or are using the wrong path
level.

I hope I've got the conventions right. If I haven't please let me know
because I'd rather make sure my patches are standard and conform to DSpace
convention before making them public.

FURTHER CONFIGURATION / USAGE:

DSpace's dublin core metadata registry does NOT have dc.identifier.doi
defined, so this will need to be defined within DSpace, an appropriate
label set in Messages.properties, and a relevant input form field defined
in input-forms.xml (the easiest way to get started would be to just add DOI
as another value in the Identifier dropdown menu).

DSpace's configuration file will not do anything with DOI metadata until
told to. You will need to edit the "webui.itemdisplay.default" parameter,
so that it includes "dc.identifier.doi(doi)".

Eg.

webui.itemdisplay.default = dc.title, dc.contributor.*, \
dc.date.issued(date), dc.identifier.citation,
dc.publisher, \
dc.relation.ispartofseries,
dc.identifier.doi(doi), \
dc.relation.uri(link), dc.description.abstract,
\
dc.subject, dc.type, dc.identifier.uri(link),
\
dc.description.publisherstatement,
dc.description, dc.identifier

Your Messages.properties will need a line like:

metadata.dc.identifier.doi = DOI

After the patch and config changes have been applied, and DSpace has been
restarted, you should be able to view DOI values as nice rendered links,
like the one at http://hdl.handle.net/10289/439

[DS-17] DSpace 1.5 Controlled Vocab (edit-metadata.jsp) - ID: 1931796

Imported from JIRA [DS-17] created by kipkorir2008

Error

==> selecting Subject from Popup page of controlled vocab, receiving null
or not an object error on very first Subject Text Box.

/jspui/controlledvocabulary/controlledvocabulary.jsp?ID=dc_subject_0&vocabu
lary=srsc

==> (edit-metadata.jsp, doTwoBox)

Line number 622 to 653

if i==0

".append("_").append" was removed when appending to "sb"

.append(fieldParam) = fieldName (==> dc_subject )

But when calling to doControlledVocabulary = fieldName + "_" + i ( ==>
dc_subject_0)

if (i == 0)
{
//param is just the field name
fieldParam = fieldName;
........

else
{
//param is field name and index (e.g. myfield_2)
fieldParam = fieldName + "_" + i;
sb.append(" ");
}
if (i < defaults.length)
sb.append(" .append(fieldParam) <== dc-subject
.append("\" size=\"15\" value=\"")
.append(defaults[i].value.replaceAll("\"", """))
.append("\"")
.append(hasVocabulary(vocabulary)&&closedVocabulary?"
readonly=\"readonly\" ":"")
.append("/>  .append(fieldName)
.append("remove")
.append
.append("\" value=\"")
.append(LocaleSupport.getLocalizedMessage(pageContext,
"jsp.submit.edit-metadata.button.remove2"))
.append("\"/>")
.append(doControlledVocabulary(fieldName + "_" + i, pageContext,
vocabulary)) <== dc_subject_0
.append("\n");
else
{
sb.append(" .append(fieldParam) <== dc_subject
.append("\" size=\"15\"")
.append(hasVocabulary(vocabulary)&&closedVocabulary?"
readonly=\"readonly\" ":"")
.append("/>")
.append(doControlledVocabulary(fieldName + "_" + i,
pageContext, vocabulary)) <== dc_subject_0
.append("\n");
}

[DS-28] Itemmap-browse.jsp throws Exception on items without date - ID: 1745573

Imported from JIRA [DS-28] created by kipkorir2008

Items without any date assigned make itemmap-browse.jsp to thrown an
ArrayOutOfBoundsException when an item without a date results from the
search (DSpace expects that every item has a date value?)..

java.lang.ArrayIndexOutOfBoundsException: 0
at
org.apache.jsp.tools.itemmap_002dbrowse_jsp.jspService(itemmap_002dbrowse
jsp.java:344)

BTW, patch
[ 1739899 ] Implements Feature Request #1739416

Already solves this issue.

[DS-39] Fix for toDate method in DCDate - ID: 2385187

Imported from JIRA [DS-39] created by kipkorir2008

The "toDate" method in org.dspace.content.DCDate (1.4 and 1.5) uses
GregorianCalendar to convert a DCDate into a Java Date object.

DCDate convention is to store unknown values (eg, month, day, hours, etc)
as -1, which is fine for most applications but when setting a
GregorianCalendar object, it causes dates to roll back incorrectly.

I first noticed this when it was pointed out to me that in Dspace's RSS 2.0
feeds, almost all issue dates are displayed as the year previous to the
actual issue date, on October 30 10:58pm.

When you see what is happening in "toDate", it is clear:

> utcGC.set(year, month - 1, day, hours, minutes, seconds);

Say I have an issue date of "2008". This line will set utcGC to 2008, then
roll back to November 01 2007 when a month of -2 is referenced, then back
to October 31 2007 when a day of -1 is referenced. The -1 hour will kick it
back to 11pm on the 30th, and so on.

I think there are two good solutions to this.

The first is to look for alternatives to to use in the RSS feeds.
It seems to me that a very large majority of issue dates are just a year or
a month and a year, so forcing a fully formatted date string seems
strange.
(I'm open to the fact that people use dc.date.accessioned in RSS rather
than dc.date.issued, but dc.date.issued is the Dspace default and I've seen
it used most often when looking at other repos RSS feeds)

The second is a small patch to DCDate that will make sure when it is
converted to a GregorianCalendar object, temporary 'unknowns' of 0s or 1s
are used instead of -1s, to avoid unwanted rollback:
This is not a perfect solution by any means, but it means that in
situations where we only have a year, or a year and a month for a date like
issue date, but something is trying to display that date as a full Java
Date object, we'll see more "obvious" defaults like 01 January 00:00, and
we'll preserve values that are known without rolling them back.

I have attached the patch (against 1.5 branch) for your review.

[DS-29] Imporper display of Umlauts / Encoding of messages_de.xml - ID: 2413800

Imported from JIRA [DS-29] created by kipkorir2008

The file

http://code.google.com/p/dspace-sandbox/source/browse/modules/dspace-xmlui-
lang/trunk/src/main/webapp/i18n/messages_de.xml

starts with the line:

as opposed to all other message files starting with

I have Dspace 1.4.2 with Manakin 1.1a installed as a test installation and
loaded this file, knowing that it would not work flawlessly because it is
meant for a newer version of Manakin. In my test instance Umlauts did not
display properly. However, I found that I am not the only one with this
issue and most installations of DSpace 1.5 that are already using Manakin
as their interface show the very same behaviour. E.g.

<http://minds.wisconsin.edu/>
<http://dspace.cpm.unimib.it/xmlui/>

I changed the first line to

,

rebuilt using ant build_wars. Now, my display is fine:

<http://stadtteilgeschichten.net/cvoelker_manakin/>

I am confident that omitting the encoding completely would work as well,
but I had not seen before that every other language file did it that way. I
am willing to test it if it is worth anything to test it under Manakin
1.1a.
I guess Claudia who wrote this file has a different setup for her Apache or
JSP container so that the same thing works fine at her place with the
encoding as set in the file. This is why I report my locale setting:

LANG=de_DE.UTF-8

I suggest that the first line of the messages_de.xml file in the repository
should be changed to either ommit the encoding or setting it to UTF-8 so
that messages get displayed properly on sites where the file is just used
without people in charge being aware that their site looks weird if seen in
a language which is not their mother tongue. Their could be an additional
comment line giving a hint to german users on how to switch back in case
their server setup requires them to do so.

Bye, Christian Völker, stadtteilgeschichten.net e.V.

[DS-44] Monthly statistics skip first and last of month - ID: 2541435

Imported from JIRA [DS-44] created by kipkorir2008

Adding up the monthly view totals for a given item in
/dspace/reports/report-year-month.html files yields less than the aggregate
total for the item in the current report-general-year-month-day.html.

This appears to be an issue with the logLine.beforeDate and
logLine.afterDate functions in LogLine.java as they are used in
LogAnalyser.java

They return true when the dates are equal. Which forces the function
processLogs to skip over the log line in LogAnalyser.java for the startDate
and endDate (first and last of month).

[DS-22] News stored not language dependend - ID: 2125833

Imported from JIRA [DS-22] created by kipkorir2008

I just found a surprising bug while configuring the two "News" of the main
page. We have a DSpace 1.5 (jspui) installation with English and German
GUI. There are two possibilities to configure the "News": 1. the
news-side*.html and news-top*.html in the config directory, and 2. the
administration area of the GUI.

Now my case: I edited the German text from the GUI. Then I switched to the
English GUI to set up the translation. The fields were already filled with
the German texts . And after changing them, the German texts in the
German GUI are gone. Looking in the config directory I saw that only the
files news-side.html and news-top.html were affected and news-side_de.html
and news-top_de.html were still old (= the original versions from the
language pack).

This means: Even when I edit the "News" from the German GUI, the English
files are written (and displayed)!

[DS-42] Foreign Key Problem - ID: 2593584

Imported from JIRA [DS-42] created by kipkorir2008

In quite a few places the code doesn't clean up possible foreign
relationships, effectively throwing an exception when trying to delete
something in the database, here is one of those:

org.postgresql.util.PSQLException: ERRO: atualização ou exclusão em
tabela "epersongroup" viola restrição de chave estrangeira "$7" em
"collection"
Detalhe: Chave (eperson_group_id)=(141) ainda é referenciada pela tabela
"collection".

The Colletion table still has a FK in one of the workflow fields to a group
that is being deleted.

[DS-24] Error in authorization to submit when you add collection. - ID: 1725817

Imported from JIRA [DS-24] created by kipkorir2008

When you try insert a new collection, in the Authorization to Submit step,
you can select many groups to add right, the list of these groups show a
Group who doesn't exist yet, because this group is the same group of that
collection you are creating right now, so the group of this collection can
call itself, and this recursive action generate a
java.lang.StackOverflowError Exception.

I don't know if I explained very well, but I will send some pictures for
you can understand better the bug.

DSpace version 1.4.2

[DS-38] XMLUI Submission forms display errors during add/remove - ID: 2543413

Imported from JIRA [DS-38] created by kipkorir2008

This is not a major bug, but an annoying usability problem.

When you are adding/removing values (via "Add" and "Remove" buttons) in
multi-valued fields during the XMLUI submission process, you receive
errors/warnings on empty required fields which you may not have even gotten
to yet. During local usability testing, many users found it disconcerting
that the interface displays validation errors next to fields before they
even submit the entire form.

I've found a fix to this issue which also works with the existing JSPUI.
The patches are attached. Essentially, we add logic to only perform form
validation when the "Next" button (or Progress Bar) is pressed. This
ensures that users can click "Add", "Remove" on fields (or step "Back" in
the process) without receiving validation error messages.

The attached patches are for the org.dspace.submit.step.DescribeStep class
(which performs backend processing of both XMLUI and JSPUI), and the
DRI2XHTML structural.xsl which builds the default XMLUI theme. Changes to
the DescribeStep class were tested with both the XMLUI and JSPUI (despite
the fact that this usability problem only exists on XMLUI). The patches
were built based on the latest code in dspace-1_5_x branch (as of
2009-01-28).

[DS-50] LDAP+Active Directory authentication patch - ID: 2100378

Imported from JIRA [DS-50] created by kipkorir2008

Thanks, Stuart -

I'll submit the patch to the queue.
You can grab a zip file that includes only the
changed files here:
http://erwg.lib.auburn.edu/dspace-ldap_20080828.zip

The main changes were:

*. Our A.D. setup does not allow anonymous bind,
and also has user info scattered around the LDAP tree.
To bind an arbitrary user, we pass a distinguished name
of:
DOMAIN\USER-ID
rather than some LDAP path like cn=USER&ou=People&dc=...
We detect this case by allowing the admin
to specify
windows_domain:domain-name
(something like that) as the LDAP object-context in dspace.cfg.

*. Since our user info is scattered through an LDAP tree -
I patched the "lookup user info" part of the code
to specify a recursive JNDI search.
Your last patch may have done the same thing.

*. We would like a user that successfully authenticates against A.D.
to automatically be given certain privileges.
I setup the getSpecialGroups function to accept a list of group-ids in
the
"ldap.dspace.autogroup"
dspace.cfg parameter.

*. I wanted to be able to run a standalone test case against the LDAP
authenticate and search code, so I split out the 'DataFromLDAP'
nested class to an external interface, and include a junit test case.
Also added a few lines to pom.xml to help run the test with verbose
logging, etc.

Cheers,
Reuben

>>> Stuart Lewis 9/6/2008 7:57 AM >>>
Hi Reuben,

Thanks for getting in touch. I¹ve got that email sitting in my inbox
waiting
for me to get around to replying to it - sorry it has taken a little
while.

What changes have you made to make it work with Active Directory?

It would be great if you could formally submit your patch to the DSpace
patch queue
(http://sourceforge.net/tracker/?atid=319984&group_id=19984&func=browse).
There are a few of us working on a generic LDAP authenticator which will
hopefully work with any AD / LDAP system, so it would be good to see what
changes you¹ve made to see if we can incorporate them too.

Thanks,

Stuart

On 28/08/2008 16:14, "Reuben Pasquini" wrote:

> Hello!
>
> I've put together a set of patches to the LDAPAuthentication
> code to get it working against Active Directory at Auburn
> University, support implicit-group member-ids in dspace.cfg,
> and add a JUnit regression test.
> I think the changes are backward compatable and generic,
> but I've only tested the code in my environment.
>
> I hope that we can check this patch into the dspace repository.
> An overview and svn diff follow, and a zip file with
> the modified files is available here:
> http://erwg.lib.auburn.edu/dspace-ldap_20080828.zip
> Please take a look, and let me know what you think.
>
> Cheers,
> Reuben
>
> -----------------------------------
>
> Changes under dspace-api org.dspace.authentication.
>
> *. Moved the
> LDAPAuthentication.SpeakerToLDAP
> nested class out to its own non-nested interface
> with a DefaultSpeakerToLDAP implementation.
>
> *. Refactored SpeakerToLDAP#ldapAuthenticate(...)
> to return a DataFromLDAP POJO data object
> rather than set object member variables.
>
> *. Implemented SpeakerToLDAPCase JUnit test-case
> and PackageTestSuite classes to support simple
> regression tests against SpeakerToLDAP implementations.
> Modified pom.xml so that
> 'mvn test'
> runs with a verbose log4j setting.
>
> *. Modified the way SpeakToLDAP handles the
> ldap.object_context
> dspace.cfg configuration property so that
> if the ldap.object_context matches
> 'WINDOWS_DOMAIN:DOMAIN_NAME',
> then LDAP attempts to bind with
> 'DOMAIN_NAME\NETID'
> rather than
> 'cn=NETID,ldap.object_context'
> . This change allows us to configure LDAP
> to bind with Active Directory out of the box.
>
> *. Modifed the LDAP search for user-info to take a SearchControls
> parameter that specifies a recursive tree-search under the
> ldap.search_context
> tree for a single user-object result.
> Once again - this allows LDAPAuthenticate to work
> with an Active Directory tree that has user objects
> organized into different folders under a tree.
>
> *. Modified LDAPAuthentication.getSpecialGroups
> to access the
> ldap.dspace.autogroup
> dspace.cfg configuration property
> to get the group-ids that an LDAP-authenticated
> user should be an implicit member of.
> This makes it easy to configure a system where
> every user that can authenticate can also
> submit material to some collections.
>
> *. Changed some of the if/else nesting in
> LDAPAuthentication.authenticate
> so that instead of having something like
> if ()

{ > ... > return bla; > } else {
> we have
> if () {> ...> return bla;> }

> ... // no else
> and instead of
> } else {
> if ()

{ > return goo > }

> }
> we just have
> } else if () {
> just to make the control flow a little
> easier to look at.
>
> ----------------------------------
>
> $ svn diff pom.xml src/test src/main/java/org/dspace/authenticate >
> /tmp/bla
>
> Index: pom.xml
> ===================================================================
> — pom.xml (revision 2942)
> +++ pom.xml (working copy)
> @@ -61,6 +61,7 @@
>
>
http://dspace.svn.sourceforge.net/viewvc/dspace/branches/dspace-1_5_x/
dsp
> ace
>
>
> +
>
> @@ -188,6 +189,23 @@
> com.ibm.icu
> icu4j
>
> +
> + junit
> + junit
> + 3.8.1
> + test
> +
>
>
> -
> \ No newline at end of file
> +
> +
> +
> + src/test/resources
> +
> + log4j.properties
> +
> +
> +
> +
> +
> +
> Index: src/test/java/org/dspace/authenticate/SpeakerToLDAPCase.java
> ===================================================================
> —
> src/test/java/org/dspace/authenticate/SpeakerToLDAPCase.java (revision
> 0)
> +++
> src/test/java/org/dspace/authenticate/SpeakerToLDAPCase.java (revision
> 0)
> @@ -0,0 +1,56 @@
> +package org.dspace.authenticate;
> +
> +
> +import junit.framework.TestCase;
> +
> +import org.apache.log4j.Logger;
> +
> +/**
> + * Generic test runner for SpeakerToLDAP implementations.
> + */
> +public class SpeakerToLDAPCase extends TestCase {
> + private static final Logger olog = Logger.getLogger(
> SpeakerToLDAPCase.class );
> +
> + private SpeakerToLDAP oldap;
> + private String os_netid;
> + private String os_password;
> +
> +
> + /**
> + * Inject the test dependencies - initializes test properties
> + *
> + * @param s_name of test - pass to super
> + * @param ldap instance to authenticate agains
> + * @param s_netid user-id to authenticate as
> + * @param s_password for s_netid
> + */
> + public SpeakerToLDAPCase ( String s_name, SpeakerToLDAP ldap,
> + String s_netid, String s_password
> + )

{ > + super( s_name ); > + oldap = ldap; > + os_netid = s_netid; > + os_password = s_password; > + }

> +
> + /**
> + * Try to authenticate against the constructor-supplied
> + * (SpeakerToLDAP, s_netid, s_password)
> + */
> + public void testAuthenticate() {
> + try

{ > + DataFromLDAP ldap_info = oldap.ldapAuthenticate( os_netid, > os_password ); > + assertTrue( "Test user logged in ok: " + os_netid, > + null != ldap_info > + ); > + // need e-mail to key into eperson database > + olog.info( "Got e-mail for " + os_netid + ": " + > ldap_info.getEmail () ); > + assertTrue( "Got e-mail info for " + os_netid + " from > ldap", > + null != ldap_info.getEmail () > + ); > + }

catch ( Exception e )

{ > + olog.info( "Failed to authenticate user: " + os_netid, e > ); > + assertTrue( "Failed to authenticate user: " + os_netid + > ", caught: " + e, false ); > + }

> + }
> +}
> Index: src/test/java/org/dspace/authenticate/PackageTest.java
> ===================================================================
> —
> src/test/java/org/dspace/authenticate/PackageTest.java (revision
> 0)
> +++
> src/test/java/org/dspace/authenticate/PackageTest.java (revision
> 0)
> @@ -0,0 +1,40 @@
> +package org.dspace.authenticate;
> +
> +
> +import junit.framework.TestCase;
> +import junit.framework.TestSuite;
> +
> +import org.apache.log4j.Logger;
> +
> +/**
> + * Specialization of AbstactSpeakerToLDAPTest configured
> + * to run a DefaultSpeakerToLDAPTest through a test.
> + */
> +public class PackageTest extends TestCase {
> + private static final Logger olog = Logger.getLogger(
> PackageTest.class );
> +
> +
> + /**
> + * Build up the batch of tests to run for the
> org.dspace.authenticate
> + * package. You'll have to modify the properties injected into
> the
> + * test SpeakerToLDAP to work with your environment
> + */
> + public static TestSuite suite ()

{ > + TestSuite suite = new TestSuite( PackageTest.class.getName > () ); > + SpeakerToLDAP ldap = new DefaultSpeakerToLDAP ( > "ldap://ldaps.university.edu", > + "cn", > + > "OU=People,OU=AUMain,DC=auburn,DC=edu", > + > "WINDOWS_DOMAIN:AUBURN", > + "mail", > + "givenName", > + "sn", > + > "telephoneNumber" > + ); > + suite.addTest ( new SpeakerToLDAPCase( "testAuthenticate", > ldap, > + "USER", "PASSWORD" > + ) > + ); > + return suite; > + }

> +
> +}
> Index: src/test/resources/log4j.properties
> ===================================================================
> — src/test/resources/log4j.properties (revision 0)
> +++ src/test/resources/log4j.properties (revision 0)
> @@ -0,0 +1,9 @@
> +# Set root logger level to DEBUG and its only appender to A1.
> +log4j.rootLogger=DEBUG, A1
> +
> +# A1 is set to be a ConsoleAppender.
> +log4j.appender.A1=org.apache.log4j.ConsoleAppender
> +
> +# A1 uses PatternLayout.
> +log4j.appender.A1.layout=org.apache.log4j.PatternLayout
> +log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x -
> %m%n
> Index: src/main/java/org/dspace/authenticate/LDAPAuthentication.java
> ===================================================================
> —
> src/main/java/org/dspace/authenticate/LDAPAuthentication.java (revision
> 3054)
> +++
> src/main/java/org/dspace/authenticate/LDAPAuthentication.java (working
> copy)
> @@ -40,17 +40,11 @@
> package org.dspace.authenticate;
>
> import java.sql.SQLException;
> +import java.util.ArrayList;
> +import java.util.List;
> import java.util.Hashtable;
>
> -import javax.naming.NamingEnumeration;
> import javax.naming.NamingException;
> -import javax.naming.directory.Attribute;
> -import javax.naming.directory.Attributes;
> -import javax.naming.directory.BasicAttribute;
> -import javax.naming.directory.BasicAttributes;
> -import javax.naming.directory.DirContext;
> -import javax.naming.directory.InitialDirContext;
> -import javax.naming.directory.SearchResult;
> import javax.servlet.http.HttpServletRequest;
> import javax.servlet.http.HttpServletResponse;
>
> @@ -60,6 +54,7 @@
> import org.dspace.core.Context;
> import org.dspace.core.LogManager;
> import org.dspace.eperson.EPerson;
> +import org.dspace.eperson.Group;
>
> /**
> * Authentication module to authenticate against a flat LDAP tree
> where
> @@ -72,9 +67,66 @@
> implements AuthenticationMethod {
>
> /** log4j category */
> - private static Logger log =
> Logger.getLogger(LDAPAuthentication.class);
> + private static final Logger olog =
> Logger.getLogger(LDAPAuthentication.class);
>
> + private final SpeakerToLDAP oldap;
> +
> /**
> + * Constructor injects SpeakerToLDAP dependency
> + *
> + * @param ldap SpeakerToLDAP knows how to authenticate
> + * against and query the LDAP directory
> + * @param b_autoregister set true to auto-register an eperson
> + * for a new user that succesfully authenticates
> + * with LDAP
> + * @param v_special_group ids of user groups that an
> LDAP-authenticated
> + * user should be considered an implicit member of
> + */
> + public LDAPAuthentication ( SpeakerToLDAP ldap,
> + boolean b_autoregister,
> + int[] v_special_group
> + )

{ > + oldap = ldap; > + ob_autoregister = b_autoregister; > + ov_special_group = v_special_group; > + }

> +
> + /**
> + * Constructor invoked by dspace.cfg based configuration
> + * engine sets up DefaultSpeakerToLDAP,
> + * checks ldap.autoregister and ldap.dspace.autogroup
> + * configuration values to determine canSelfRegister
> + * and getSpecialGroups property values.
> + */
> + public LDAPAuthentication () {
> + String s_groups =
> ConfigurationManager.getProperty("ldap.dspace.autogroup");
> +
> + List v_group_id = new ArrayList();
> + if ( null != s_groups ) {
> + String[] v_group_name = s_groups.trim ().split(
> ",
s*" );
> + for ( int i=0; i < v_group_name.length; ++i ) {
> + String s_group = v_group_name[i].trim ();
> + if ( s_group.length () > 0 ) {
> + try

{ > + v_group_id.add ( Integer.parseInt( s_group ) > ); > + }

catch ( Exception e )

{ > + olog.warn( "Exception parsing group " + > s_group, e ); > + }

> + }
> + }
> + }
> + oldap = new DefaultSpeakerToLDAP ();
> + ob_autoregister =
> ConfigurationManager.getBooleanProperty("webui.ldap.autoregister");
> + ov_special_group = new int[ v_group_id.size () ];
> + int i_count = 0;
> + for ( Integer i_group_id : v_group_id )

{ > + ov_special_group[ i_count ] = i_group_id; > + ++i_count; > + }

> + }
> +
> + private final boolean ob_autoregister;
> + /**
> * Let a real auth method return true if it wants.
> */
> public boolean canSelfRegister(Context context,
> @@ -83,8 +135,7 @@
> throws SQLException
>

{ > // XXX might also want to check that username exists in LDAP. > - > - return > ConfigurationManager.getBooleanProperty("webui.ldap.autoregister"); > + return ob_autoregister; > }

>
> /**
> @@ -118,12 +169,10 @@
> return false;
> }
>
> - /*
> - * Nothing here.
> - */
> + private final int[] ov_special_group;
> public int[] getSpecialGroups(Context context, HttpServletRequest
> request)
>

{ > - return new int[0]; > + return ov_special_group; > }

>
> /*
> @@ -139,261 +188,140 @@
> HttpServletRequest request)
> throws SQLException
> {
> - log.info(LogManager.getHeader(context, "auth", "attempting
> trivial auth of user="+netid));
> + olog.info(LogManager.getHeader(context, "auth", "attempting
> auth of user="+netid));
>
> // Skip out when no netid or password is given.
> - if (netid == null || password == null)
> - return BAD_ARGS;
> + if (netid == null || password == null)

{ > + return BAD_ARGS; > + }

>
> // Locate the eperson
> - EPerson eperson = null;
> + EPerson eperson = null;
> try
>

{ > - eperson = EPerson.findByNetid(context, > netid.toLowerCase()); > + eperson = EPerson.findByNetid(context, > netid.toLowerCase()); > }

> catch (SQLException e)
>

{ > }

> - boolean loggedIn = false;
> - SpeakerToLDAP ldap = new SpeakerToLDAP(log);
>
> + olog.debug( "Found eperson for " + netid );
> +
> // if they entered a netid that matches an eperson
> if (eperson != null)
> {
> // e-mail address corresponds to active account
> - if (eperson.getRequireCertificate())
> + if (eperson.getRequireCertificate())

{ > return CERT_REQUIRED; > - else if (!eperson.canLogIn()) > + }

else if (!eperson.canLogIn()) {
> return BAD_ARGS;
> - {
> - if (ldap.ldapAuthenticate(netid, password, context))
> -

{ > + }

> + try {
> + // authenticate
> + olog.debug( "Attempting LDAP auth-1 for " + netid );
> + DataFromLDAP ldap_info = oldap.ldapAuthenticate(
> netid, password );
> + if ( null != ldap_info )

{ > context.setCurrentUser(eperson = > EPerson.findByNetid(context, netid.toLowerCase())); > - log.info(LogManager > - .getHeader(context, "authenticate", > "type=ldap")); > + olog.info(LogManager > + .getHeader(context, "authenticate", > "type=ldap")); > return SUCCESS; > - }

> - else
> - return BAD_CREDENTIALS;
> + }
> + } catch ( NamingException e )

{ > + olog.warn( "Failed to authenticate user: " + netid, e > ); > }

> + //else

{ > + return BAD_CREDENTIALS; > + }

> + // eperson == null
> + if ( null != eperson )

{ > + throw new AssertionError( "eperson should be null here!" > ); > }

> -
> - // the user does not already exist so try and authenticate
> them
> - // with ldap and create an eperson for them
> - else
> - {
> - if (ldap.ldapAuthenticate(netid, password, context))
> - {
> - // Register the new user automatically
> - log.info(LogManager.getHeader(context,
> - "autoregister", "netid=" + netid));
> -
> - if
> ((ldap.ldapEmail!=null)&&(!ldap.ldapEmail.equals("")))
> - {
> - try
> - {
> - eperson = EPerson.findByEmail(context,
> ldap.ldapEmail);
> - if (eperson!=null)
> -

{ > - log.info(LogManager.getHeader(context, > - "type=ldap-login", > "type=ldap_but_already_email")); > - context.setIgnoreAuthorization(true); > - eperson.setNetid(netid); > - eperson.update(); > - context.commit(); > - context.setIgnoreAuthorization(false); > - context.setCurrentUser(eperson); > - return SUCCESS; > - }

> - else
> - {
> - if (canSelfRegister(context, request,
> netid))
> - {
> - // TEMPORARILY turn off
> authorisation
> - try
> -

{ > - > context.setIgnoreAuthorization(true); > - eperson = > EPerson.create(context); > - if > ((ldap.ldapEmail!=null)&&(!ldap.ldapEmail.equals(""))) > eperson.setEmail(ldap.ldapEmail); > - else eperson.setEmail(netid); > - if > ((ldap.ldapGivenName!=null)&&(!ldap.ldapGivenName.equals(""))) > eperson.setFirstName(ldap.ldapGivenName); > - if > ((ldap.ldapSurname!=null)&&(!ldap.ldapSurname.equals(""))) > eperson.setLastName(ldap.ldapSurname); > - if > ((ldap.ldapPhone!=null)&&(!ldap.ldapPhone.equals(""))) > eperson.setMetadata("phone", ldap.ldapPhone); > - eperson.setNetid(netid); > - eperson.setCanLogIn(true); > - > AuthenticationManager.initEPerson(context, request, eperson); > - eperson.update(); > - context.commit(); > - context.setCurrentUser(eperson); > - }

> - catch (AuthorizeException e)
> -

{ > - return NO_SUCH_USER; > - }

> - finally
> -

{ > - > context.setIgnoreAuthorization(false); > - }

> -
> -
> log.info(LogManager.getHeader(context, "authenticate",
> - "type=ldap-login,
> created ePerson"));
> - return SUCCESS;
> - }
> - else
> -

{ > - // No auto-registration for valid > certs > - > log.info(LogManager.getHeader(context, > - "failed_login", > "type=ldap_but_no_record")); > - return NO_SUCH_USER; > - }

> - }
> - }
> - catch (AuthorizeException e)
> -

{ > - eperson = null; > - }

> - finally
> -

{ > - context.setIgnoreAuthorization(false); > - }

> - }
> - }
> + olog.debug( "Attempting LDAP auth-2 for " + netid );
> + DataFromLDAP ldap_info = null;
> + try

{ > + ldap_info = oldap.ldapAuthenticate( netid, password ); > + }

catch ( NamingException e )

{ > + olog.warn( "Failed to authenticate user: " + netid, e ); > }

> - return BAD_ARGS;
> - }
> -
> - /**
> - * Internal class to manage LDAP query and results, mainly
> - * because there are multiple values to return.
> - */
> - public class SpeakerToLDAP {
> -
> - private Logger log = null;
> -
> - /** ldap email result */
> - protected String ldapEmail = null;
> -
> - /** ldap name result */
> - protected String ldapGivenName = null;
> - protected String ldapSurname = null;
> - protected String ldapPhone = null;
> -
> - SpeakerToLDAP(Logger thelog)
> - {
> - log = thelog;
> + if ( (null == ldap_info)
> + || (ldap_info.getEmail()==null)
> + || ldap_info.getEmail().equals("")
> + )

{ > + return BAD_ARGS; // failed to authenticate or get e-mail > address > }

>
> - /**
> - * contact the ldap server and attempt to authenticate
> - */
> - protected boolean ldapAuthenticate(String netid, String
> password, Context context)
> - {
> - if (!password.equals(""))
> - {
> - String ldap_provider_url =
> ConfigurationManager.getProperty("ldap.provider_url");
> - String ldap_id_field =
> ConfigurationManager.getProperty("ldap.id_field");
> - String ldap_search_context =
> ConfigurationManager.getProperty("ldap.search_context");
> - String ldap_object_context =
> ConfigurationManager.getProperty("ldap.object_context");
> -
> - // Set up environment for creating initial context
> - Hashtable env = new Hashtable(11);
> - env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY,
> "com.sun.jndi.ldap.LdapCtxFactory");
> - env.put(javax.naming.Context.PROVIDER_URL,
> ldap_provider_url);
> -
> - // Authenticate
> - env.put(javax.naming.Context.SECURITY_AUTHENTICATION,
> "simple");
> - env.put(javax.naming.Context.SECURITY_PRINCIPAL,
> ldap_id_field+"="netid","+ldap_object_context);
> - env.put(javax.naming.Context.SECURITY_CREDENTIALS,
> password);
> -
> - DirContext ctx = null;
> - try
> - {
> - // Create initial context
> - ctx = new InitialDirContext(env);
> -
> - String ldap_email_field =
> ConfigurationManager.getProperty("ldap.email_field");
> - String ldap_givenname_field =
> ConfigurationManager.getProperty("ldap.givenname_field");
> - String ldap_surname_field =
> ConfigurationManager.getProperty("ldap.surname_field");
> - String ldap_phone_field =
> ConfigurationManager.getProperty("ldap.phone_field");
> -
> - Attributes matchAttrs = new
> BasicAttributes(true);
> - matchAttrs.put(new BasicAttribute(ldap_id_field,
> netid));
> -
> - String attlist[] =

{ldap_email_field, > ldap_givenname_field, ldap_surname_field, ldap_phone_field}

;
> -
> - // look up attributes
> - try
> - {
> - NamingEnumeration answer =
> ctx.search(ldap_search_context, matchAttrs, attlist);
> - while(answer.hasMore()) {
> - SearchResult sr =
> (SearchResult)answer.next();
> - Attributes atts = sr.getAttributes();
> - Attribute att;
> -
> - if (attlist[0]!=null)
> -

{ > - att = atts.get(attlist[0]); > - if (att != null) ldapEmail = > (String)att.get(); > - }

> -
> - if (attlist[1]!=null)
> -

{ > - att = atts.get(attlist[1]); > - if (att != null) ldapGivenName = > (String)att.get(); > - }

> -
> - if (attlist[2]!=null)
> -

{ > - att = atts.get(attlist[2]); > - if (att != null) ldapSurname = > (String)att.get(); > - }

> -
> - if (attlist[3]!=null)
> -

{ > - att = atts.get(attlist[3]); > - if (att != null) ldapPhone = > (String)att.get(); > - }

> - }
> + //
> + // autoregister the ldap-authenticated user
> + //
> + olog.info(LogManager.getHeader(context,
> + "autoregister", "netid=" +
> netid)
> + );
> +
> + try {
> + eperson = EPerson.findByEmail(context,
> ldap_info.getEmail());
> + if (eperson!=null)

{ > + // Just need to set the netid on the eperson record > + olog.info(LogManager.getHeader(context, > + "type=ldap-login", > "type=ldap_but_already_email")); > + context.setIgnoreAuthorization(true); > + eperson.setNetid(netid); > + eperson.update(); > + context.commit(); > + context.setIgnoreAuthorization(false); > + context.setCurrentUser(eperson); > + return SUCCESS; > + }

else if (canSelfRegister(context, request, netid)) {
> + // TEMPORARILY turn off authorisation
> + try {
> + context.setIgnoreAuthorization(true);
> + eperson = EPerson.create(context);
> + eperson.setEmail(ldap_info.getEmail());
> + if ((ldap_info.getGivenName()!=null)
> + &&(!ldap_info.getGivenName().equals(""))
> + )

{ > + > eperson.setFirstName(ldap_info.getGivenName()); > }

> - catch (NamingException e)
> - {
> - // if the lookup fails go ahead and create a
> new record for them because the authentication
> - // succeeded
> - log.warn(LogManager.getHeader(context,
> - "ldap_attribute_lookup",
> "type=failed_search "+e));
> - return true;
> + if ((ldap_info.getSurname()!=null)
> + &&(!ldap_info.getSurname().equals(""))
> + )

{ > + eperson.setLastName(ldap_info.getSurname()); > }

> - }
> - catch (NamingException e)
> -

{ > - log.warn(LogManager.getHeader(context, > - "ldap_authentication", > "type=failed_auth "+e)); > - return false; > - }

> - finally
> - {
> - // Close the context when we're done
> - try
> - {
> - if (ctx != null)
> - ctx.close();
> + if ((ldap_info.getPhone()!=null)
> + &&(!ldap_info.getPhone().equals(""))
> + )

{ > + eperson.setMetadata("phone", > ldap_info.getPhone()); > }

> - catch (NamingException e)
> -

{ > - }

> + eperson.setNetid(ldap_info.getNetId());
> + eperson.setCanLogIn(true);
> + AuthenticationManager.initEPerson(context,
> request, eperson);
> + eperson.update();
> + context.commit();
> + context.setCurrentUser(eperson);
> + } catch (AuthorizeException e)

{ > + return NO_SUCH_USER; > + }

finally

{ > + context.setIgnoreAuthorization(false); > }
> + olog.info(LogManager.getHeader(context,
> "authenticate",
> + "type=ldap-login,
> created ePerson"));
> + return SUCCESS;
> + } else { > + // No auto-registration for valid certs > + olog.info(LogManager.getHeader(context, > + "failed_login", > "type=ldap_but_no_record")); > + return NO_SUCH_USER; > }
> - else
> - { > - return false; > - }
> -
> - return true;
> + } catch (AuthorizeException e) { > + eperson = null; > + // authentication failed > + return BAD_ARGS; > + } finally {> + context.setIgnoreAuthorization(false);> }

> -
> -
> + // Unreachable!
> }
>
> +
> /*
> * Returns URL to which to redirect to obtain credentials (either
> password
> * prompt or e.g. HTTPS port for client cert.); null means no
> redirect.
> @@ -430,4 +358,4 @@
>

{ > return "org.dspace.eperson.LDAPAuthentication.title"; > }

> -}
> \ No newline at end of file
> +}
> Index: src/main/java/org/dspace/authenticate/DefaultSpeakerToLDAP.java
> ===================================================================
> —
> src/main/java/org/dspace/authenticate/DefaultSpeakerToLDAP.java
(revision
> 0)
> +++
> src/main/java/org/dspace/authenticate/DefaultSpeakerToLDAP.java
(revision
> 0)
> @@ -0,0 +1,183 @@
> +package org.dspace.authenticate;
> +
> +import java.util.Hashtable;
> +
> +import javax.naming.NamingEnumeration;
> +import javax.naming.NamingException;
> +import javax.naming.directory.Attribute;
> +import javax.naming.directory.Attributes;
> +import javax.naming.directory.BasicAttribute;
> +import javax.naming.directory.BasicAttributes;
> +import javax.naming.directory.DirContext;
> +import javax.naming.directory.InitialDirContext;
> +import javax.naming.directory.SearchControls;
> +import javax.naming.directory.SearchResult;
> +
> +import org.apache.log4j.Logger;
> +import org.dspace.core.ConfigurationManager;
> +
> +/**
> + * Internal class to manage LDAP query and results, mainly
> + * because there are multiple values to return.
> + */
> +public class DefaultSpeakerToLDAP implements SpeakerToLDAP {
> + private static final Logger olog =
> Logger.getLogger(DefaultSpeakerToLDAP.class);
> + private final String os_provider_url;
> + private final String os_id_field;
> + private final String os_search_context;
> + private final String os_object_context;
> + private final String os_email_field;
> + private final String os_givenname_field;
> + private final String os_surname_field;
> + private final String os_phone_field;
> +
> +
> + /**
> + * Constructor allows injection of
> + * configuration parameters.
> + *
> + * @param s_provider_url to the server - we assume simple
> authentication
> + * @param s_id_field attribute of user object - usually cn
> + * @param s_search_context subtree under which to search for user
> info,
> + * ex: ou=People,dc=myschool,dc=edu
> + * @param s_object_context of user bind-path -
> + * ex: ou=People,dc=myschool,dc=edu leads to bind attempt
> + * againt cn=username,ou=People,dc=myschool,dc=edu
> + * @param s_email_field in user record
> + * @param s_givenname_field in user record
> + * @param s_surname_field in user record, usually sn
> + * @param s_phone_field in user record
> + */
> + public DefaultSpeakerToLDAP( String s_provider_url,
> + String s_id_field,
> + String s_search_context,
> + String s_object_context,
> + String s_email_field,
> + String s_givenname_field,
> + String s_surname_field,
> + String s_phone_field
> + )
> +

{ > + os_provider_url = s_provider_url; > + os_id_field = s_id_field; > + os_search_context = s_search_context; > + os_object_context = s_object_context; > + os_email_field = s_email_field; > + os_givenname_field = s_givenname_field; > + os_surname_field = s_surname_field; > + os_phone_field = s_phone_field; > + }

> +
> + /**
> + * Default constructor extracts LDAP-server parameters
> + * from ConfigurationManager (dspace.cfg):
> + * ldap.provider_url, ldap_id_field,
> + * ldap_search_contect, ldap_object_context
> + */
> + public DefaultSpeakerToLDAP()

{ > + os_provider_url = > ConfigurationManager.getProperty("ldap.provider_url"); > + os_id_field = > ConfigurationManager.getProperty("ldap.id_field"); > + os_search_context = > ConfigurationManager.getProperty("ldap.search_context"); > + os_object_context = > ConfigurationManager.getProperty("ldap.object_context"); > + os_email_field = > ConfigurationManager.getProperty("ldap.email_field"); > + os_givenname_field = > ConfigurationManager.getProperty("ldap.givenname_field"); > + os_surname_field = > ConfigurationManager.getProperty("ldap.surname_field"); > + os_phone_field = > ConfigurationManager.getProperty("ldap.phone_field"); > + }

> +
> + /**
> + * contact the ldap server and attempt to authenticate
> + */
> + public DataFromLDAP ldapAuthenticate(String s_netid, String
> s_password ) throws NamingException
> + {
> + if (s_password.equals(""))
> +

{ > + return null; > + }

> + // Set up environment for creating initial context
> + Hashtable env = new Hashtable(11);
> + env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY,
> "com.sun.jndi.ldap.LdapCtxFactory");
> + env.put(javax.naming.Context.PROVIDER_URL, os_provider_url);
> +
> + // Authenticate
> + env.put(javax.naming.Context.SECURITY_AUTHENTICATION,
> "simple");
> + final String s_ad_key = "WINDOWS_DOMAIN:";
> + if ( os_object_context.toUpperCase ().startsWith( s_ad_key ) )
>

{ > + // Active Directory bind > + String s_principal = os_object_context.substring( > s_ad_key.length () ) + "\\" + s_netid; > + olog.debug( "Binding principal to: " + s_principal ); > + env.put(javax.naming.Context.SECURITY_PRINCIPAL, > s_principal ); > + }

else

{ > + env.put(javax.naming.Context.SECURITY_PRINCIPAL, > os_id_field+"="+s_netid+","+os_object_context); > + }

> + env.put(javax.naming.Context.SECURITY_CREDENTIALS,
> s_password);
> +
> + DirContext ctx = new InitialDirContext(env);
> + try {
> + Attributes search_attributes = new BasicAttributes(true);
> + search_attributes.put(new BasicAttribute(os_id_field,
> s_netid));
> +
> + String[] v_result_atts =

{os_email_field, > os_givenname_field, os_surname_field, os_phone_field}

;
> +
> + olog.debug( "Searching LDAP for " + os_id_field + "=" +
> s_netid
> + + " under " + os_search_context
> + );
> +
> + NamingEnumeration answer = ctx.search(os_search_context,
> + "(" + os_id_field +
> "=" + s_netid + ")",
> + new SearchControls(
> SearchControls.SUBTREE_SCOPE,
> +
> 1, 20000,
> +
> v_result_atts,
> +
> false, false
> +
> )
> + );
> + if( ! answer.hasMore())

{ > + olog.info( "Able to bind as " + s_netid + ", but > unable to find LDAP record" ); > + return null; > + }

> + // look up attributes
> + String ldapEmail = null;
> + String ldapGivenName = null;
> + String ldapSurname = null;
> + String ldapPhone = null;
> + SearchResult sr = (SearchResult)answer.next();
> + Attributes atts = sr.getAttributes();
> + Attribute att;
> +
> + if (v_result_atts[0]!=null)

{ > + att = atts.get(v_result_atts[0]); > + if (att != null) ldapEmail = (String)att.get(); > + }

> +
> + if (v_result_atts[1]!=null) {
> + att = atts.get(v_result_atts[1]);
> + if (att != null)

{ > + ldapGivenName = (String)att.get(); > + }

> + }
> +
> + if (v_result_atts[2]!=null) {
> + att = atts.get(v_result_atts[2]);
> + if (att != null)

{ > + ldapSurname = (String)att.get(); > + }

> + }
> +
> + if (v_result_atts[3]!=null) {
> + att = atts.get(v_result_atts[3]);
> + if (att != null)

{ > + ldapPhone = (String)att.get(); > + }

> + }
> + return new SimpleDataFromLDAP( ldapEmail, ldapGivenName,
> ldapSurname, ldapPhone, s_netid );
> + } finally {
> + // Close the context when we're done
> + try {
> + if (ctx != null)

{ > + ctx.close(); > + }

> + } catch (NamingException e) { }
> + }
> + // Unreachable
> + }
> +}
> Index: src/main/java/org/dspace/authenticate/SimpleDataFromLDAP.java
> ===================================================================
> —
> src/main/java/org/dspace/authenticate/SimpleDataFromLDAP.java (revision
> 0)
> +++
> src/main/java/org/dspace/authenticate/SimpleDataFromLDAP.java (revision
> 0)
> @@ -0,0 +1,48 @@
> +package org.dspace.authenticate;
> +
> +
> +/**
> + * Simple implementation of DataFromLDAP
> + */
> +public class SimpleDataFromLDAP implements DataFromLDAP {
> + /**
> + * Constructor injects all the property values
> + */
> + public SimpleDataFromLDAP ( String s_email,
> + String s_given_name,
> + String s_surname,
> + String s_phone,
> + String s_netid
> + )

{ > + os_email = s_email; > + os_given_name = s_given_name; > + os_surname = s_surname; > + os_phone = s_phone; > + os_netid = s_netid; > + }

> +
> + private final String os_email;
> + public String getEmail ()

{ > + return os_email; > + }

> +
> + private final String os_given_name;
> + public String getGivenName ()

{ > + return os_given_name; > + }

> +
> + private final String os_surname;
> + public String getSurname()

{ > + return os_surname; > + }

> +
> + private final String os_phone;
> + public String getPhone ()

{ > + return os_phone; > + }

> +
> + private final String os_netid;
> + public String getNetId ()

{ > + return os_netid; > + }

> +}
> Index: src/main/java/org/dspace/authenticate/SpeakerToLDAP.java
> ===================================================================
> —
> src/main/java/org/dspace/authenticate/SpeakerToLDAP.java (revision
> 0)
> +++
> src/main/java/org/dspace/authenticate/SpeakerToLDAP.java (revision
> 0)
> @@ -0,0 +1,20 @@
> +package org.dspace.authenticate;
> +
> +import javax.naming.NamingException;
> +
> +/**
> + * Interface for LDAP interaction handler
> + */
> +public interface SpeakerToLDAP

{ > + /** > + * Authenticate the given user with LDAP, > + * and get some data about him/her from the directory. > + * > + * @param s_netid cn of the user to authenticate > + * @param s_password > + * @return user info > + */ > + public DataFromLDAP ldapAuthenticate( String s_netid, > + String s_password > + ) throws NamingException; > +}

> Index: src/main/java/org/dspace/authenticate/DataFromLDAP.java
> ===================================================================
> —
> src/main/java/org/dspace/authenticate/DataFromLDAP.java (revision
> 0)
> +++
> src/main/java/org/dspace/authenticate/DataFromLDAP.java (revision
> 0)
> @@ -0,0 +1,15 @@
> +package org.dspace.authenticate;
> +
> +
> +/**
> + * POJO data bucket interface for user-data obtained during
> + * LDAP authentication
> + */
> +public interface DataFromLDAP

{ > + public String getEmail (); > + public String getGivenName (); > + public String getSurname(); > + public String getPhone (); > + /** LDAP common name (cn) for the user */ > + public String getNetId (); > +}

>
>
>
>

[DS-26] Hardcoded Strings in DSQuery - ID: 2493794

Imported from JIRA [DS-26] created by kipkorir2008

org.dspace.search.DSQuery
doQuery(Context c, QueryArgs args) contains hardcoded Strings:

...
qr.setErrorMsg("Number format exception");
}
...
qr.setErrorMsg("Invalid search string");
...
qr.setErrorMsg("Your query was too broad. Try a narrower query.");

These strings are used in the webui and not i18n displayed to the end
user.

[DS-25] SWORD Service Document fails if Collection is untitled - ID: 1968082

Imported from JIRA [DS-25] created by kipkorir2008

If somehow you ended up with a Collection with no title in DSpace 1.5,
SWORD will fail to generate a Service Document for anyone with submit
access to that untitled Collection.

Obviously, most DSpace Collections should have a title. However, it is
possible to generate a Collection without a title. Either way, the DSpace
SWORD Server should probably be smart enough to still generate a valid
Service Document if it encounters a Collection without a title.

The following error is generated when a collection without a title is
encountered:

SEVERE: Servlet.service() for servlet servicedocument threw exception
java.lang.NullPointerException
at org.purl.sword.base.Collection.marshall(Collection.java:367)
at org.purl.sword.base.Workspace.marshall(Workspace.java:176)
at org.purl.sword.base.Service.marshall(Service.java:299)
at
org.purl.sword.base.ServiceDocument.marshall(ServiceDocument.java:260)
at
org.purl.sword.server.ServiceDocumentServlet.doGet(ServiceDocumentServlet.j
ava:86)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:690)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Applicatio
nFilterChain.java:290)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterC
hain.java:206)
at
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.j
ava:230)
at
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.j
ava:175)
at
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:12
8)
at
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:10
4)
at
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.jav
a:109)
at
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:261)

at
org.apache.jk.server.JkCoyoteHandler.invoke(JkCoyoteHandler.java:190)
at
org.apache.jk.common.HandlerRequest.invoke(HandlerRequest.java:283)
at
org.apache.jk.common.ChannelSocket.invoke(ChannelSocket.java:767)
at
org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:697
)
at
org.apache.jk.common.ChannelSocket$SocketConnection.runIt(ChannelSocket.jav
a:889)
at
org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.ja
va:686)
at java.lang.Thread.run(Thread.java:619)

[DS-8] DSpace Home link style in breadcrumb trail - ID: 1951859

Imported from JIRA [DS-8] created by kipkorir2008

The breadcrumb trail which is created in the dri:trail xsl template is
created with the CSS class "first-linklast-link" when the currently viewed
page is the DSpace Home page.

There's a missing space that's needed to give the link the classes
"first-link last-link".

[DS-41] Small JSP cleanups

Imported from JIRA [DS-41] created by mwood

While working on something else I became aware of a few malformed places in login-related JSPs: overlapped tags, missing quotes, and one place where "tabid" was used where "tabindex" seems to be meant.

[DS-21] Fix for hardcoded metadata language qualifiers - ID: 2433387

Imported from JIRA [DS-21] created by kipkorir2008

With CSS the old bug of having the metadata language qualifier hardcoded
instead of using the configuration parameter default.language has been
reintroduced.

It has been fixed in 1_5_x. This is just to make the patch available for
those using 1.5.1 in an non "en" environment.

[DS-18] DSpace 1.5.1(XMLUI) Wrong dir usage of StatisticsLoader - ID: 2137425

Imported from JIRA [DS-18] created by kipkorir2008

Statistics viewer for XMLUI, based on existing DStat view from the analysis
files (.dat)

Existing CreateStatReport ouput the (.dat) files under ("log.dir") but
StatisticsLoader use ("report.dir")

Line number 355
===============
StatisticsLoader.java
private static File[] getAnalysisAndReportFileList()
{
File reportDir = new
File(ConfigurationManager.getProperty("report.dir"));

Line number 131
===============
CreateStatReport.java
outputLogDirectory = ConfigurationManager.getProperty("log.dir") +
File.separator;

[DS-36] DSpace 1.5 XMLUI - Enable METS <amdSec> using crosswalks - ID: 2477820

Imported from JIRA [DS-36] created by kipkorir2008

By default, the Item-level METS files which the DSpace 1.5.x XMLUI
auto-generates contain only descriptive metadata (), file
() and structure mapping () sections.

This patch allows you to also generate the METS administrative metadata
() section, based on the request made. This patch itself doesn't
create the administrative metadata. Rather, it provides you a way to
utilize DSpace Crosswalks to generate the adminstrative metadata for the
.

As an example, you can now make requests similar to the following:

http://localhost/xmlui/metadata/handle/123456789/1/mets.xml?techMDTypes=PRE
MIS

Notice the "techMDTypes" is specified as "PREMIS". This tells the XMLUI
that you want to run the "PREMIS" crosswalk to generate metadata to be
placed in the subsection of . So, the result would
include the following :





[..PREMIS Crosswalk-generated metadata..]



By default, normal requests to "metadata/handle///mets.xml" will NOT
generate this section. This ensures that the default METS files
are still kept small.

However, this ability to request administrative metadata now allows more
flexibility to XMLUI Themes. It also opens up more opportunities for
Crosswalks which generate administrative metadata. Finally, it also begins
to allow one to utilize the XMLUI as a "pseudo-Web-Service" interface for
dissemination of Item-level METS representations (including administrative
metadata)

The attached patch was built against the latest DSpace 1.5.x branch (as of
30-Dec-2008).

[DS-5] DSpace1.5.1(XML) problem with Login to restricted bitstreams - ID: 2164955

Imported from JIRA [DS-5] created by kipkorir2008

Software

1. JSP 1.5.1 is fine, no issue.
2. XML 1.5 is fine. It can redirect to "This bitstream is restricted" after
login.
3. Have a very lightly customised XML 1.5.1, in style sheet only, but
asked another colleague with an out of the box XML 1.5.1 version and
similar behaviour is exhibited.

Problem:

We have bitstreams that are restricted to administrator or collection
admins, if a user who does not have authorisation to that bitstream logs
into the restricted item they continue to receive the login screen
instead of getting a "not authorised message" or they loop around
endlessly and hang the browser session.

To Test this
1. You can create a new record or use an existing one
2. Make sure that the item has read access to metadata record and change
the authorisation to either admin or a collection admin group. (we have
tried both)
3. Logout of your account and clear the cache
4. Login with another account that has no access and you will continue
to loop around in the login cycle after the second time you get an error
message, odd browser behaviour or page not found.

Here is the error message from log when the 2nd user without access logs
in.

2008-10-09 17:31:34,258 INFO
org.dspace.app.xmlui.utils.AuthenticationUtil @
[email protected]:session_id=222BFE9CA6411C87F2D
195BBBC7B1FFB:ip_addr=130.216.69.238:failed_login:email=, realm=null,
result=4
2008-10-09 17:31:34,468 INFO
org.dspace.authenticate.PasswordAuthentication @
[email protected]:session_id=222BFE9CA6411C87F2
D195BBBC7B1FFB:ip_addr=130.216.69.238:authenticate:attempting password
auth of user=
2008-10-09 17:31:34,470 INFO
org.dspace.app.xmlui.utils.AuthenticationUtil @
[email protected]:session_id=222BFE9CA6411C87F2D
195BBBC7B1FFB:ip_addr=130.216.69.238:failed_login:email=, realm=null,
result=4
2008-10-09 17:31:34,590 INFO
org.dspace.authenticate.PasswordAuthentication @
[email protected]:session_id=222BFE9CA6411C87F2
D195BBBC7B1FFB:ip_addr=130.216.69.238:authenticate:attempting password
auth of user=
2008-10-09 17:31:34,592 INFO
org.dspace.app.xmlui.utils.AuthenticationUtil @
[email protected]:session_id=222BFE9CA6411C87F2D
195BBBC7B1FFB:ip_addr=130.216.69.238:failed_login:email=, realm=null,
result=4
2008-10-09 17:31:34,733 INFO
org.dspace.authenticate.PasswordAuthentication @
[email protected]:session_id=222BFE9CA6411C87F2
D195BBBC7B1FFB:ip_addr=130.216.69.238:authenticate:attempting password
auth of user=

Leonie Hayes
Research Repository Librarian
http://www.library.auckland.ac.nz/contacts/?firstname=&lastname=hayes
http://researchspace.auckland.ac.nz

[DS-33] checksum checker can not retrieve very large bitstream - ID: 2016130

Imported from JIRA [DS-33] created by kipkorir2008

in the database there is a field for the size of a bitstream. it`s defined
as a int8 value which is at java the datatype long.

the query in the checksum checker reads this value in as a "INT" VALUE
INSTEAD OF A "LONG" VALUE. if it`s realy a big file and the size doesn`t
fit into the int, that`s causes an exception of course, which is catched as
a SQLException and logged as "Bitstream metadata could not be retrieved.
...". the size of the bitstream is handled at the hole checksum classes as
an int. that`s regarding the following classes:

  • Class: org.dspace.checker.BitstreamInfoDAO
    + Line 277: Method: findByBitstreamId
  • Class: org.dspace.checker.BitstreamInfo
    + Line 144: Constructor
    + Line 207/218: Methods: get/setSize
  • Class: org.dspace.checker.DSpaceBitstreamInfo
    + Line 137: Constructor
    + Line 202/213: Methods: get/setSize
  • Class: org.dspace.checker.DSpaceBitstreamInfo
    + Line 137: Constructor
    + Line 202/213: Methods: get/setSize

[DS-20] 2 Authentications with LoginPage cause connection exhaust - ID: 2352146

Imported from JIRA [DS-20] created by kipkorir2008

Grave problem related to chooser.jsp (Or whatever code that calls it, maybe
RegisteredFilter?).

The problem that caused the connection pool to get exhausted in our
production site can be reproduced by taking Dspace's current Trunk and
enabling at least 2 Autentication methods that have loginURLs (ie.:
PasswordAuthentication and LDAPAuthentication).

Then just go to a page (/profile for example) where chooser.jsp is called
and hit a 3 or 4 refreshs. In my machine usually it takes less than 30 secs
the following message appears:

2008-11-26 18:09:57,494 ERROR org.dspace.dao.GlobalDAO @ Um erro de E/S
ocorreu ao enviar para o processo do servidor.
2008-11-26 18:09:57,494 WARN org.dspace.storage.rdbms.DatabaseManager @
Already closed.
2008-11-26 18:09:57,516 ERROR org.dspace.dao.GlobalDAO @ Um erro de E/S
ocorreu ao enviar para o processo do servidor.
2008-11-26 18:09:57,516 WARN org.dspace.storage.rdbms.DatabaseManager @
Already closed.

And the following is outputed in the tomcat console: (might be one of the
empty SQLExceptions catch where i have put e.printStackTrace(), so might
not appear for you)

java.sql.SQLException: Already closed.
at
org.apache.commons.dbcp.PoolableConnection.close(PoolableConnection.java:84
)
at
org.apache.commons.dbcp.PoolingDriver$PoolGuardConnectionWrapper.close(Pool
ingDriver.java:269)
at
org.dspace.storage.rdbms.DatabaseManager.freeConnection(DatabaseManager.jav
a:566)
at
org.dspace.dao.postgres.GlobalDAOPostgres.abortTransaction(GlobalDAOPostgre
s.java:105)
at org.dspace.core.Context.abort(Context.java:381)
at org.dspace.core.Context.finalize(Context.java:504)
at java.lang.ref.Finalizer.invokeFinalizeMethod(Native Method)
at java.lang.ref.Finalizer.runFinalizer(Finalizer.java:83)
at java.lang.ref.Finalizer.access$100(Finalizer.java:14)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:160)

To exhaust the connection pool, use Apache's JMeter against one of these
pages where choose.jsp is called:

I am making the test with 20 simultaneous users and loop count of 5 (and
the default 30 connections in the pool). And the pool gets exhausted very
quickly.

[DS-49] Add support for DjVu-documents - ID: 2234659

Imported from JIRA [DS-49] created by kipkorir2008

Hello All

This patch based on
http://mailman.mit.edu/pipermail/dspace-general/2007-May/001513.html

In DSpace 1.5.0+ we need (before compilation)

1) Add utility djvutxt (package djvulibre), for Debian it is:
apt-get install djvulibre-bin

2) Edit [dspace-source]/dspace/config/dspace.cfg, text-block "### Media
Filter / Format Filter plugins"
and add DjVu-support in 3 places:

filter.plugins = ... \
DjVu Text Extractor

plugin.named.org.dspace.app.mediafilter.FormatFilter = ... \
org.dspace.app.mediafilter.DjVuFilter = DjVu Text Extractor

filter.org.dspace.app.mediafilter.DjVuFilter.inputFormats = DjVu

3) Edit [dspace-source]/dspace/config/registries/bitstream-formats.xml
and add next


image/vnd.djvu
DjVu
DjVu
1
false
djvu
djv

4) Create file
[dspace-source]/dspace-api/src/main/java/org/dspace/app/mediafilter/DjVuFil
ter.java
with next content

/*
DjVuFilter.java
Version: 0.1
DSpace version: 1.4.2 beta
Author: Ivan Penev
e-mail: inpenev at gmail.com
*/

package org.dspace.app.mediafilter;

import java.io.InputStream;
import java.io.FileInputStream;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.OutputStream;
import java.io.FileOutputStream;
import java.io.BufferedOutputStream;
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.File;

/**

  • This class provides a media filter for processing files of type DjVu.
  • The current implementation uses a program called
    djvutxt, which extracts the text layer from a previously
    OCR-ed DjVu file and saves it into a UTF-8 text document. The program
    is distributed with the djvulibre package which is freely
    available under the GPL license from href="http://djvu.sourceforge.net/">http://djvu.sourceforge.net/
    for both Unix and Windows operating systems. Hence, for the media
    filter to work it is required that djvutxt is a valid
    command (in the working environment).


    */

public class DjVuFilter extends MediaFilter
{
/**

  • Get a filename for a newly created filtered bitstream.
    *
  • @param sourceName
  • name of source bitstream
  • @return filename generated by the filter - for example, document.djvu
  • becomes document.djvu.txt
    */

public String getFilteredName(String sourceName)
{
return sourceName + ".txt";
}

/**

  • Get name of the bundle this filter will stick its generated
    bitstreams.
    *
  • @return "TEXT"
    */
    public String getBundleName()
    {
    return "TEXT";
    }

/**

  • Get name of the bitstream format returned by this filter.
    *
  • @return "Text"
    */

public String getFormatString()
{
return "Text";
}

/**

  • Get a string describing the newly-generated bitstream.
    *
  • @return "Extracted text"
    */

public String getDescription()
{
return "Extracted text";
}

/**

  • Get a bitstream filled with the extracted text from a DjVu bitstream.
  • The bitstream supplied as a parameter is written to a DjVu
    file on the file system (in the working directory), and the system
    command djvutxt is called on the latter to produce a
    UTF-8 text file containg the extracted text. The file is then copied
    to a bitstream. Finally, the auxiliary files are removed from the file
    system, and the generated bitsream is returned as a result.

  • WARNING! Write access to the working directory is needed for
    this method to operate! No exception handling provided!


    *
  • @param source
  • input stream
    *
  • @return result of filter's transformation, written out to a bitstream
    */

public InputStream getDestinationStream(InputStream source) throws
Exception
{
/* Some convenience initializations. */
final String cmd = "djvutxt";
final String fileName = "aux";
final String djvuFileName = fileName + ".djvu";
final String txtFileName = fileName + ".txt";

/* Store input bitstresam to auxiliary DjVu file. */
File djvuFile = streamToFile(source, djvuFileName);

/* Invoke external command djvutxt with appropriate agruments
to do the actual job... */
final String[] cmdArray =

{cmd, djvuFileName, txtFileName}

;
Process p = Runtime.getRuntime().exec(cmdArray);
/* ...and wait for it to terminate */
p.waitFor();

/* Copy extracted text from file to an independent bitstream,
and optionally print the text to standard output. */
File txtFile = new File(txtFileName);
InputStream dest = fileToStream(txtFile, MediaFilterManager.isVerbose);

/* Then remove auxiliary files...*/
djvuFile.delete();
txtFile.delete();
/* ...and return resulting bitstream. */
return dest;
}

/**

  • Write given input stream to a file on the file system.
  • WARNING! No exception handling!


    *
  • @param inStream input stream
  • @param fileName name of the file to be generated
    *
  • @return File object associated with the generated file
    *
  • @throws Exception
    */

private File streamToFile(InputStream inStream, String fileName)
throws Exception

{ /* Data will be read from input stream in chunks of size e.g. 4KB. */ final int chunkSize = 4096; byte[] byteArray = new byte[chunkSize];

/* Open the stream for buffered reading. */
InputStream bufInStream = new BufferedInputStream(inStream);

/* Create an empty file (if the file already exists, it will be left
untouched)
to store the supplied bitstream... /
File file = new File(fileName);
file.createNewFile();
/
...and associate a buffered output stream with it. */
OutputStream bufOutStream = new BufferedOutputStream(new
FileOutputStream(file));

/* Copy data from input stream to newly generated file. */
int readBytes = -1;
while ((readBytes = bufInStream.read(byteArray, 0, chunkSize)) != -1)
bufOutStream.write(byteArray, 0, readBytes);

/* Stop transactions to the file system... /
bufOutStream.close();
/
...and return result. */
return file;
}

/**

  • Produce input stream from a given file on the file system.
  • WARNING! No exception handling!

  • @param file File object associated with the given file
  • @return input stream containing the data read from file

*@throws Exception
*/

private InputStream fileToStream(File file, boolean verbose) throws
Exception
{
/* Open the stream for reading. */
InputStream inStream = new FileInputStream(file);

/* Allocate necessary memory for data buffer. */
byte[] byteArray = new byte[(int)file.length()];

/* Load file contents into buffer. */
inStream.read(byteArray);

/* And imediately close transactions with the file system. */
inStream.close();

/* If required to send the retrieved data to standard output... /
if (verbose)
{
/
Open the file again, but this tim handle it as a character stream...
/
BufferedReader bufReader = new BufferedReader(new FileReader(file));
/
...then print its contents line by line to the standard output... /
String lineOfText = null;
while ((lineOfText = bufReader.readLine()) != null)
System.out.println(lineOfText);
/
...and close connection to the file. */
bufReader.close();
}

/* Finally, generate and return input stream containing desired data. */
return new ByteArrayInputStream(byteArray);
}

}

5) Compilation/recompilation
cd [dspace-source]/dspace/dspace-1.5.0-src-release/dspace/
mvn package

6) Install or for recompilation -

{edit work bitstream-formats.xml & dspace.cfg as above and replace dspace-api-1.5.0.jar from folders webapps/jspui/WEB-INF/lib/, lib/, webapps/lni/WEB-INF/lib/, webapps/oai/WEB-INF/lib/, webapps/xmlui/WEB-INF/lib/ by compiled [dspace-source]/dspace-api/target/dspace-api-1.5.0.jar}

7) Don't forgive restart Tomcat and run
/usr/share/dspace/bin/filter-media

With best regards
Serhij Dubyk

[DS-34] Add File Format Descriptions to XMLUI 1.5.x - ID: 2433852

Imported from JIRA [DS-34] created by kipkorir2008

This is a simple patch to replace the default MIME Types (e.g.
"application/pdf") in the DSpace 1.5.x XMLUI with File Format Descriptions
(e.g. "PDF").

Although in past versions of DSpace these file format descriptions were
resolved via the Bitstream Registry, access to this registry is constrained
by the capabilities of METS. Therefore, this patch instead uses a mapping
in your 'messages.xml' to resolve these file format descriptions. For
example:

PDF

If the above "mapping" exists in your messages.xml, this would map the MIME
Type "application/pdf" to the description "PDF". If such a mapping doesn't
exist in your messages.xml, then the MIME Type is displayed by default
(making these changes backwards compatible with current XMLUI).

Two patches are attached (made against latest version of SVN 1.5.x
branch):

  • xmlui-format-General-Handler.patch
    (Patch for /themes/dri2xhtml/General-Handler.xsl)
  • xmlui-format-messages.patch
    (Patch for /i18n/messages.xml , English version)

[DS-40] SubmissionController is not thread safe

Imported from JIRA [DS-40] created by bollini

The SubmissionController servlet uses a local field to maintain request related value (currentStepConfig). Concurrent access to the servlet can change the value of the field interfering with request processing

[DS-37] Submission Forms don't preserve order of values - ID: 2541285

Imported from JIRA [DS-37] created by kipkorir2008

This bug occurs in 1.5.x XMLUI and JSPUI.

Essentially the Describe (metadata entry) page of the submission process
doesn't preserve the order that values are entered in multi-valued fields.

This is especially problematic for Author names. During a submission
author names are reordered such that the first author listed is that
last one that you enter during the submission process.

This patch modifies the org.dspace.submit.step.DescribeStep class (the
processing class) in the dspace-api module, so that it will preserve the
order in which values are entered. This way the first author listed will
always be the first author entered, etc.

This patch works for both the XMLUI and JSPUI since both of these
interfaces utilize this same backend prorcessing class to save all values
entered during the Describe step.

This patch was built off the latest code in the dspace-1_5_x branch of SVN
(as of 2009-Jan-27).

[DS-16] Hierarchical LDAP support - ID: 2057378

Imported from JIRA [DS-16] created by kipkorir2008

The attached file is a new pluggable authentication method to provide
flexible support for hierarchical LDAP trees (where users are not all in
the same subtree).

This patch builds upon two other patches:

  • [2057231] Refactor LDAPServlet to use Stackable Authentication (this
    patch only supports LDAP servers to which you can anonymously bind)
  • [1597831] Patch for Hierarchical LDAP plus Stackable fixes (this does
    not work with LDAP servers which cannot return the DN of a user as one of
    its attributes)

An additional feature is the ability to set a special group, of which all
LDAP authenticated users are a member of. This is useful for automatically
creating a group of all internal users, if you need to restrict items
internally where you can't rely on IP authentication.

It requires the following additions to dspace.cfg:

          1. Hierarchical LDAP Settings #####
  1. If your users are spread out across a hierarchical tree on your
  2. LDAP server, you will need to use the following stackable authentication
  3. class:
  4. plugin.sequence.org.dspace.authenticate.AuthenticationMethod = \
  5. org.dspace.authenticate.LDAPHierarchicalAuthentication
    #
  6. You can optionally specify the search scope. If anonymous access is not
  7. enabled on your LDAP server, you will need to specify the full DN and
  8. password of a user that is allowed to bind in order to search for the
  9. users.
  1. This is the search scope value for the LDAP search during
  2. autoregistering. This will depend on your LDAP server setup.
  3. This value must be one of the following integers corresponding
  4. to the following values:
  5. object scope : 0
  6. one level scope : 1
  7. subtree scope : 2
    #ldap.search_scope = 2
  1. The full DN and password of a user allowed to connect to the LDAP server
  2. and search for the DN of the user trying to log in.
    #ldap.search.user = cn=admin,ou=people,o=myu.edut
    #ldap.search.password = password
          1. LDAP users group #####
  1. If required, a group name can be given here, and all users who log in
  2. to LDAP will automatically become members of this group. This is useful
  3. if you want a group made up of all internal authenticated users.
    #ldap.login.specialgroup = group-name

[DS-35] Enable Google Sitemaps for XMLUI - ID: 2462293

Imported from JIRA [DS-35] created by kipkorir2008

This patch adds Sitemaps to the XMLUI for DSpace 1.5.x. It's based on the
Sitemap code for the DSpace 1.5.x JSPUI.

Essentially, it just adds a "SitemapReader" class which can read the
sitemaps generated by running the script:
[dspace]/bin/generate-sitemaps.

Attached are two patches:

(1) dspace-xmlui-webapp-sitemap.patch

Patch for sitemap.xmap in DSpace XMLUI Webapp located in
[dspace-src]/dspace-xmlui/dspace-xmlui-webapp/src/main/webapp/sitemap.xmap

(2) dspace-xmlui-api.patch

This patch just adds the org.dspace.app.xmlui.cocoon.SitemapReader class to
the XMLUI API.

These patches were made based on the lastest SVN dspace-1.5.x branch. They
will be committed to that branch shortly.

After these patches are applied the sitemaps are available at:

http://localhost/xmlui/sitemap (Sitemaps.org sitemap)
http://localhost/xmlui/htmlmap (HTML sitemap)

[DS-3] Usage event (statistics) plugin hook for 1.5 - ID: 2025998

Imported from JIRA [DS-3] created by kipkorir2008

Enable a pluggable usage event monitor class for e.g. collecting
statistical data on community, collection, item, and bitstream views. The
intent is to factor event capture out of some of the various statistical
projects and just let them plug into a common event stream.

This patch replaces parts of patches 1927351 and 1927360.

Designed to be simple, lightweight, and general.

[DS-12] Exception handling for deleting a metadata field - ID: 1606439

Imported from JIRA [DS-12] created by kipkorir2008

Trying to delete a metadatafield with associated values leads to an
"java.sql.SQLException: ERROR: update or delete on "metadatafieldregistry"
violates foreign key constraint "metadatavalue_metadata_field_id_fkey" on
"metadatavalue"" error.
This is indicated in the delete confirm page, but the error should be
caught properly.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.