diff --git a/.gitignore b/.gitignore index 49e3a54..6cd325f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,38 +1,29 @@ -/target -*.pydevproject +**/.classpath +**/.DS_Store +**/nb-configuration.xml +**/.springBeans +**/testing.properties +*.iml .project +.idea .metadata -.springBeans -bin/** -tmp/** -tmp/**/* -*.tmp -*.bak -*.swp -*~.nib -local.properties -.classpath -.settings/ -.loadpath .DS_Store -# External tool builders -.externalToolBuilders/ - -# Locally stored "Eclipse launch configurations" -*.launch - -# CDT-specific -.cproject - -# PDT-specific -.buildpath - -#Version file -src/**/RestVersion.java - -#removed files -test-certs/public.pem -test-certs/private.pem -test-certs/cakey.pem -test-certs/cacert.pem -src/main/resources/admpriv.bin +Servers +.settings +.classpath +target +mvn-repo +bin +*.war +*.log +*/nbactions.xml +*.eml +nbactions.xml +testing.properties +*/test-output +JargonVersion.java +**/${test.option.mount.basedir} +*.*~ +**/.project +**/.settings +**/target diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..caca18c --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,28 @@ +iRODS license terms and copyright info from the irods site at: https://www.irods.org/index.php/License + +License +iRODS Copyright and Licensing + +iRODS is open source software released under a BSD License, see license text in "iRODS License Terms and Conditions" below. +The BSD license has been described in very general terms as allowing you to do whatever you want to with the software and +source code as long as you acknowledge who wrote it and that, as with any open source software, there is no warranty and you're using the code "as is." +In the spirit of collaborative open source software, the iRODS community encourages you to communicate with us, letting us know what features you like, +features that would be useful, problems, bugs, suggestions, etc., and to perhaps contribute source code. +The iRODS community has formed the Data Intensive Cyberinfrastructure Foundation, a 501(c)(3) nonprofit corporation established to serve + as the home of the iRODS open source community over the long term. If you choose to contribute new code, you'll receive full acknowledgment. All you do is complete the Contributor's Agreement, under which you retain copyright ownership + in your code but give a free license to the iRODS nonprofit foundation, allowing your code to be integrated into iRODS and in turn released under the BSD license. +Note: The above text is an educational overview of iRODS open source licensing, and not intended as legal advice nor is it part of the iRODS license agreement, which is below. As always, for legal advice consult an attorney. + +iRODS License Terms and Conditions Notice + +Copyright (c) 2005-2011, Regents of the University of California, the University of North Carolina, and the Data Intensive Cyberinfrastructure Foundation +All rights reserved. +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +Neither the name of the University of California, San Diego (UCSD) nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT +NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/README.md b/README.md index 53fc060..a349231 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,23 @@ -# dfc-dataone -DataONE Member Node Implementation for iRODS -============================================ -Supports DataONE Member Node Tier 1 Implementaion v2.0 +# Project: DataONE Member Node Service +#### Date: +#### Release Version: +#### git tag: +#### Developer: Lisa Stillwell - RENCI,Mike Conway - DICE -Uses: Jargon, Spring, RestEasy +DataONE Member Node software and supporting libraries -Projects using this code for an iRODS based D1 member node implementation must customize: -1. resources/d1_client.properties -1. implementation of events/EventLogAO interface -1. implementation of id/UniqueIdAO interface +======= -To Do: ------- -Develop Tests +Please go to [[https://github.com/DFC-Incubator/dfc-dataone]] for the latest news and info. + + +## Requirements + +* Jargon depends on Java 1.8+ +* Jargon is built using Apache Maven2, see POM for dependencies +* Jargon supports iRODS 3.0 through iRODS 3.3.1 community, as well as iRODS 4.2.0 consortium + +## Libraries diff --git a/dataone-node/Dockerfile b/dataone-node/Dockerfile new file mode 100644 index 0000000..6383c0d --- /dev/null +++ b/dataone-node/Dockerfile @@ -0,0 +1,18 @@ +FROM tomcat:jre8-alpine +LABEL organization="RENCI" +LABEL maintainer="michael_conway@unc.edu" +LABEL description="DFC Member Node" +ADD target/dataone-node.war /usr/local/tomcat/webapps/ +ADD runit.sh / +ADD context.xml /usr/local/tomcat/conf +CMD ["/runit.sh"] +#CMD ["sh"] +# build: docker build -t diceunc/dataone:4.2.1.0-SNAPSHOT . + + +# run: docker run -i -p 8080:8080 -v /etc/irods-ext:/etc/irods-ext -v /etc/irods-ext/d1plugins:/etc/irods-ext/d1plugins -v /home/mcc/webdavcert:/tmp/cert --add-host irods420.irodslocal:172.16.250.101 diceunc/dataone:4.2.1.0-SNAPSHOT + +# to add addl libs -v /etc/irods-ext/d1libs:/tmp/lib + + +# docker run -i -p 8080:8080 -v /home/mcc/external:/tmp/lib -v /etc/irods-ext:/etc/irods-ext -v /home/mcc/d1plugin:/etc/irods-ext/d1plugins -v /home/mcc/webdavcert:/tmp/cert --add-host irods420.irodslocal:172.16.250.101 diceunc/dataone:4.2.1.0-SNAPSHOT \ No newline at end of file diff --git a/dataone-node/README.md b/dataone-node/README.md new file mode 100644 index 0000000..df225f6 --- /dev/null +++ b/dataone-node/README.md @@ -0,0 +1,24 @@ + +# Project: DataONE Node +#### Date: +#### Release Version: +#### git tag: +#### Developer: Lisa Stillwell - RENCI, Mike Conway - DFC/RENCI + +## News + + +## Requirements + +* Depends on Java 1.8+ +* Built using Apache Maven2, see POM for dependencies +* Supports iRODS 3.0 through iRODS 3.3.1 community, as well as iRODS 4.2.0 consortium + +## Running + +``` +mvn spring-boot:run + +``` + +## Changes diff --git a/dataone-node/TESTING.md b/dataone-node/TESTING.md new file mode 100644 index 0000000..d6508d6 --- /dev/null +++ b/dataone-node/TESTING.md @@ -0,0 +1,53 @@ +# Testing setup notes + +### maven profile + +add the following to your maven settings.xml profile in your home/.m2 directory + +```xml + + + dataone + + /home/mconway/temp/dataonejar + + + + + +``` + +That .jar directory will be the place to put the .jar files for your pid and event service plugins. These are discovered by the PluginDiscoveryService. + +### build and place your plugin jars in the test plugin jar location + +Dummy plugins are being built, including the dummy-event-service-impl included in this repo. These dummy jar files can be copied out of the target directory of the dummy subproject +in order to run the unit and integration tests that depend on successful lookup + +### sample unit test + +Check out the PluginDiscoveryServiceTest unit test for examples of testing the loading of a plugin, as in this simple case: + +```java + +@Test + public void testInstanceEventService() throws Exception { + IRODSAccessObjectFactory aof = Mockito + .mock(IRODSAccessObjectFactory.class); + PublicationContext publicationContext = new PublicationContext(); + RestConfiguration restConfiguration = new RestConfiguration(); + restConfiguration.setPluginJarLocation(dataOneTestHelper + .getPluginJarLocation(dataOneProperties)); + publicationContext.setRestConfiguration(restConfiguration); + publicationContext.setIrodsAccessObjectFactory(aof); + PluginDiscoveryService pluginDiscoveryService = new PluginDiscoveryService(); + pluginDiscoveryService.setPublicationContext(publicationContext); + pluginDiscoveryService.init(); + + EventServiceAO eventServiceAO = pluginDiscoveryService + .instanceEventService(); + Assert.assertNotNull("no eventServiceAO", eventServiceAO); + } + + +``` \ No newline at end of file diff --git a/dataone-node/context.xml b/dataone-node/context.xml new file mode 100644 index 0000000..9954abb --- /dev/null +++ b/dataone-node/context.xml @@ -0,0 +1,36 @@ + + + + + + + + WEB-INF/web.xml + ${catalina.base}/conf/web.xml + + + + + + + \ No newline at end of file diff --git a/src/main/resources/d1client.properties b/dataone-node/etc/irods-ext/d1client.properties similarity index 76% rename from src/main/resources/d1client.properties rename to dataone-node/etc/irods-ext/d1client.properties index 4b5c9c6..8e29e66 100644 --- a/src/main/resources/d1client.properties +++ b/dataone-node/etc/irods-ext/d1client.properties @@ -57,3 +57,23 @@ irods.dataone.events.elasticsearch.searchindex=databook irods.dataone.events.elasticsearch.searchtype=entity irods.dataone.events.elasticsearch.cluster.name=databookIndexer +# REST Props +irods.host=localhost +irods.port=1247 +irods.zone=tempZone +# user and password for dataone user +irods.username=test1 +irods.password=test +# STANDARD | PAM AUTH +auth.type=STANDARD +default.storage.resource= +# web.interface.url is currently optional and not fully implemented, it can be left blank. +# sets jargon ssl negotiation policy for the client. Leaving to DONT_CARE defers to the server, and is recommended +# NO_NEGOTIATION, CS_NEG_REFUSE, CS_NEG_REQUIRE, CS_NEG_DONT_CARE +ssl.negotiation.policy=CS_NEG_DONT_CARE +# location for discovered plug-ins +plugin.jar.location=/etc/irods-ext/d1plugins + +plugin.factory.pid= +plugin.factory.event=org.irods.jargon.dataone.events.defdb.DefaultEventServiceFactory +plugin.factory.repo= diff --git a/dataone-node/pom.xml b/dataone-node/pom.xml new file mode 100644 index 0000000..2ae0e5d --- /dev/null +++ b/dataone-node/pom.xml @@ -0,0 +1,247 @@ + + + 4.0.0 + dataone-node + + org.irods + dfc-dataone + 4.2.1.0-SNAPSHOT + + war + DataONE Node + + + javax.inject + javax.inject + 1 + + + org.eclipse.jdt.core.compiler + ecj + 4.2.1 + + + org.jboss.resteasy + resteasy-jaxrs + + + org.jboss.resteasy + resteasy-jackson-provider + + + org.jboss.resteasy + tjws + test + + + org.jboss.resteasy + resteasy-multipart-provider + + + org.jboss.resteasy + resteasy-jettison-provider + + + javax.servlet + javax.servlet-api + + + org.springframework + spring-test + test + + + + org.jboss.resteasy + resteasy-jaxb-provider + + + + org.jboss.resteasy + resteasy-spring + + + org.irods.jargon + jargon-core + ${project.version} + + + uk.org.mygrid.resources + cog-jglobus + + + + + + junit + junit + test + + + org.slf4j + slf4j-api + + + log4j + log4j + + + org.mockito + mockito-all + + + org.springframework + spring-core + + + org.springframework + spring-expression + + + org.springframework + spring-aop + + + org.springframework + spring-webmvc + + + org.springframework + spring-context + + + org.springframework + spring-beans + + + org.dataone + d1_libclient_java + + + ch.qos.logback + logback-classic + + + + + org.irods + pid-service-api + ${project.version} + + + org.irods + repo-service-api + ${project.version} + + + org.irods + event-service-api + ${project.version} + + + org.irods + dataone-utils + ${project.version} + + + + org.xeustechnologies + jcl-core + + + org.reflections + reflections + + + + org.irods + default-event-service-api-impl + ${project.version} + + + + + + maven-war-plugin + 2.5 + + src/main/webapp + true + dataone-node + + + + + maven-antrun-plugin + + + + run + + generate-sources + + + + + + + + + + + + + + + + + + 0 + validate + + + + + + irods.user=${jargon.test.irods.user} + irods.password=${jargon.test.irods.password} + irods.resource=${jargon.test.irods.resource} + irods.host=${jargon.test.irods.host} + irods.port=${jargon.test.irods.port} + irods.zone=${jargon.test.irods.zone} + plugin.jar.location=${test.plugin.jar.location} + + + + + + + + run + + + + + + + + + + + diff --git a/dataone-node/runit.sh b/dataone-node/runit.sh new file mode 100755 index 0000000..452f456 --- /dev/null +++ b/dataone-node/runit.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +if [ -f /tmp/cert/server.crt ]; +then + echo "Cert will be imported" + keytool -delete -noprompt -alias mycert -keystore /usr/lib/jvm/default-jvm/jre/lib/security/cacerts -storepass changeit + keytool -import -trustcacerts -keystore /usr/lib/jvm/default-jvm/jre/lib/security/cacerts -storepass changeit -noprompt -alias mycert -file /tmp/cert/server.crt +else + echo "No cert to import" +fi + +echo "augmenting libs" + +if [ -d /tmp/lib ]; +then +echo "additional libs found in /tmp/lib" + cp -R /tmp/lib /usr/local/tomcat +else + echo "No libs to import" +fi + + +echo "running catalina" + +catalina.sh run + diff --git a/dataone-node/src/main/java/org/irods/jargon/dataone/IrodsDataoneVersion.java b/dataone-node/src/main/java/org/irods/jargon/dataone/IrodsDataoneVersion.java new file mode 100644 index 0000000..e707956 --- /dev/null +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/IrodsDataoneVersion.java @@ -0,0 +1,6 @@ +package org.irods.jargon.dataone; + +public final class IrodsDataoneVersion { + public static String VERSION = "0.0.1-SNAPSHOT"; + public static String BUILD_TIME = "20131014-0959"; +} diff --git a/dataone-node/src/main/java/org/irods/jargon/dataone/MemberNodeService.java b/dataone-node/src/main/java/org/irods/jargon/dataone/MemberNodeService.java new file mode 100644 index 0000000..0e7aa85 --- /dev/null +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/MemberNodeService.java @@ -0,0 +1,427 @@ +package org.irods.jargon.dataone; + +import java.io.IOException; +import java.io.StringReader; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.List; +import java.util.Map; +import java.util.TimeZone; + +import javax.inject.Named; +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.Consumes; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.HEAD; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.xml.bind.JAXB; + +import org.dataone.service.exceptions.InsufficientResources; +import org.dataone.service.exceptions.InvalidRequest; +import org.dataone.service.exceptions.InvalidToken; +import org.dataone.service.exceptions.NotAuthorized; +import org.dataone.service.exceptions.NotFound; +import org.dataone.service.exceptions.NotImplemented; +import org.dataone.service.exceptions.ServiceFailure; +import org.dataone.service.exceptions.SynchronizationFailed; +import org.dataone.service.types.v1.Checksum; +import org.dataone.service.types.v1.DescribeResponse; +import org.dataone.service.types.v1.Event; +import org.dataone.service.types.v1.Identifier; +import org.dataone.service.types.v1.Log; +import org.dataone.service.types.v1.Node; +import org.dataone.service.types.v1.ObjectFormatIdentifier; +import org.dataone.service.types.v1.ObjectList; +import org.dataone.service.types.v1.SystemMetadata; +import org.irods.jargon.core.connection.IRODSAccount; +import org.irods.jargon.core.exception.JargonException; +import org.irods.jargon.dataone.auth.RestAuthUtils; +import org.irods.jargon.dataone.configuration.PluginDiscoveryService; +import org.irods.jargon.dataone.configuration.PluginNotFoundException; +import org.irods.jargon.dataone.configuration.PublicationContext; +import org.irods.jargon.dataone.domain.MNChecksum; +import org.irods.jargon.dataone.domain.MNError; +import org.irods.jargon.dataone.domain.MNLog; +import org.irods.jargon.dataone.domain.MNNode; +import org.irods.jargon.dataone.domain.MNObjectList; +import org.irods.jargon.dataone.domain.MNSystemMetadata; +import org.irods.jargon.dataone.events.DataOneEventServiceAO; +import org.irods.jargon.dataone.tier1.MNCoreImpl; +import org.irods.jargon.dataone.tier1.MNReadImpl; +import org.irods.jargon.dataone.utils.ISO8601; +import org.jboss.resteasy.annotations.providers.jaxb.json.Mapped; +import org.jboss.resteasy.annotations.providers.jaxb.json.XmlNsMap; +import org.jboss.resteasy.plugins.providers.multipart.InputPart; +import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * User: Lisa Stillwell - RENCI, UNC @ Chapel Hill Date: 10/4/13 Time: 2:22 PM + */ + +@Named +@Path("/mn/v1") +public class MemberNodeService { + + private Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private PublicationContext publicationContext; + @Autowired + private PluginDiscoveryService pluginDiscoveryService; + + @GET + @Path("/monitor/ping") + @Produces(MediaType.TEXT_XML) + @Mapped(namespaceMap = { @XmlNsMap(namespace = "http://irods.org/dfc-dataone", jsonName = "dfc-dataone") }) + // public Response handlePing(@HeaderParam("Authorization") final String + // authorization) + public Response handlePing() throws NotImplemented, ServiceFailure, InsufficientResources, JargonException { + + if (publicationContext == null) { + throw new IllegalArgumentException("null publicationContext"); + } + + MNCoreImpl mnCoreImpl = new MNCoreImpl(publicationContext, pluginDiscoveryService); + Date irodsDate = mnCoreImpl.ping(); + + SimpleDateFormat df = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz"); + String dateStr = df.format(irodsDate); + + Response.ResponseBuilder builder = Response.ok(); + builder.header("Date", dateStr); + builder.type("text/xml"); + builder.header("Content-Length", "0"); + + return builder.build(); + } + + @GET + @Path("/node") + @Produces(MediaType.TEXT_XML) + @Mapped(namespaceMap = { @XmlNsMap(namespace = "http://irods.org/dfc-dataone", jsonName = "dfc-dataone") }) + public MNNode handleGetCapabilities() throws NotImplemented, ServiceFailure { + + MNNode nodeCapabilities = new MNNode(); + + MNCoreImpl mnCoreImpl = new MNCoreImpl(publicationContext, pluginDiscoveryService); + Node node = mnCoreImpl.getCapabilities(); + + nodeCapabilities.copy(node); + + return nodeCapabilities; + } + + @GET + @Path("/") + @Produces(MediaType.TEXT_XML) + @Mapped(namespaceMap = { @XmlNsMap(namespace = "http://irods.org/dfc-dataone", jsonName = "dfc-dataone") }) + public MNNode handleDefaultGetCapabilities() throws NotImplemented, ServiceFailure { + + MNNode nodeCapabilities = handleGetCapabilities(); + + return nodeCapabilities; + } + + // log?[fromDate={fromDate}][&toDate={toDate}][&event={event}][&pidFilter={pidFilter}][&start={start}][&count={count}] + @GET + @Path("/log") + @Produces(MediaType.TEXT_XML) + @Mapped(namespaceMap = { @XmlNsMap(namespace = "http://irods.org/dfc-dataone", jsonName = "dfc-dataone") }) + public MNLog handleGetLogRecords(@QueryParam("fromDate") final String fromDateStr, + @QueryParam("toDate") final String toDateStr, @QueryParam("event") final String event, + @QueryParam("pidFilter") final String pidFilter, @DefaultValue("0") @QueryParam("start") final int start, + @DefaultValue("500") @QueryParam("count") final int count) + throws NotImplemented, ServiceFailure, NotAuthorized, InvalidRequest, InvalidToken { + + logger.info("/log request: fromData={} toDate={}", fromDateStr, toDateStr); + logger.info("/log request: event={} pidFilter={}", event, pidFilter); + logger.info("/log request: start={} count={}", start, count); + + MNCoreImpl mnCoreImpl = new MNCoreImpl(publicationContext, pluginDiscoveryService); + + // parse date strings + Date fromDate = null; + Date toDate = null; + try { + if (fromDateStr != null) { + fromDate = ISO8601.toCalendar(fromDateStr).getTime(); + } + if (toDateStr != null) { + toDate = ISO8601.toCalendar(toDateStr).getTime(); + } + } catch (ParseException e) { + logger.error("handleListObjects: unable to parse query dates"); + throw new InvalidRequest("1480", e.getMessage()); + } + + Event e = Event.convert(event); + + Log log = mnCoreImpl.getLogRecords(fromDate, toDate, e, pidFilter, start, count); + logger.info("returned log={}", log.toString()); + + // set Log attributes in MNLog + MNLog mnLog = new MNLog(); + mnLog.copy(log); + + return mnLog; + } + + @GET + @Path("/object/{id}") + @Produces(MediaType.APPLICATION_OCTET_STREAM) + public void handleRead(@PathParam("id") final String pid, @Context final HttpServletResponse response) + throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, InsufficientResources { + + MNReadImpl mnReadImpl = new MNReadImpl(publicationContext, pluginDiscoveryService); + + Identifier id = new Identifier(); + id.setValue(pid); + // Had to write new method in mnReadImpl since I + // couldn't figure out how to override the get method + mnReadImpl.streamObject(response, id); + + try { + IRODSAccount irodsAccount = RestAuthUtils + .getIRODSAccountFromBasicAuthValues(publicationContext.getRestConfiguration()); + DataOneEventServiceAO eventServiceAO = pluginDiscoveryService.instanceEventService(irodsAccount); + eventServiceAO.recordEvent(Event.READ, id, "DataONE replication"); + + } catch (PluginNotFoundException | JargonException e) { + logger.error("Unable to log EVENT: {} for data object id: {}", Event.READ, pid); + } + + } + + @GET + @Path("/checksum/{id}") + @Produces(MediaType.TEXT_XML) + public MNChecksum handleGetChecksum(@PathParam("id") final String pid, + @DefaultValue("MD5") @QueryParam("checksumAlgorithm") final String algorithm) + throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, InvalidRequest { + + MNChecksum mnChecksum = new MNChecksum(); + + if (!algorithm.toUpperCase().equals("MD5")) { + throw new InvalidRequest("1402", "invalid checksum algorithm requested - only MD5 supported"); + } + + Identifier id = new Identifier(); + id.setValue(pid); + + MNReadImpl mnReadImpl = new MNReadImpl(publicationContext, pluginDiscoveryService); + Checksum checksum = mnReadImpl.getChecksum(id, algorithm); + + mnChecksum.copy(checksum); + + return mnChecksum; + } + + @GET + @Path("/replica/{id}") + @Produces(MediaType.APPLICATION_OCTET_STREAM) + public void handleReplica(@PathParam("id") final String pid, @Context final HttpServletResponse response) + throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, InsufficientResources { + + MNReadImpl mnReadImpl = new MNReadImpl(publicationContext, pluginDiscoveryService); + + Identifier id = new Identifier(); + id.setValue(pid); + + // Had to write new method in mnReadImpl since I + // couldn't figure out how to override the get method + mnReadImpl.streamObject(response, id); + + try { + IRODSAccount irodsAccount = RestAuthUtils + .getIRODSAccountFromBasicAuthValues(publicationContext.getRestConfiguration()); + DataOneEventServiceAO eventServiceAO = pluginDiscoveryService.instanceEventService(irodsAccount); + eventServiceAO.recordEvent(Event.READ, id, "DataONE replication"); + + } catch (PluginNotFoundException | JargonException e) { + logger.error("Unable to log EVENT: {} for data object id: {}", Event.READ, pid); + } + + } + + @GET + @Path("/meta/{id}") + @Produces(MediaType.TEXT_XML) + public MNSystemMetadata handleGetSystemMetadata(@PathParam("id") final String pid) + // @Context final HttpServletResponse response) + throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, InvalidRequest { + + MNSystemMetadata mnSystemMetadata = new MNSystemMetadata(); + + Identifier id = new Identifier(); + id.setValue(pid); + + MNReadImpl mnReadImpl = new MNReadImpl(publicationContext, pluginDiscoveryService); + SystemMetadata sysMetadata = mnReadImpl.getSystemMetadata(id); + + mnSystemMetadata.copy(sysMetadata); + + return mnSystemMetadata; + } + + @HEAD + @Path("/object/{id}") + @Produces(MediaType.TEXT_XML) + @Mapped(namespaceMap = { @XmlNsMap(namespace = "http://irods.org/dfc-dataone", jsonName = "dfc-dataone") }) + public Response handleDescribe(@PathParam("id") final String pid) + // @Context final HttpServletResponse response) + throws NotAuthorized, NotImplemented, ServiceFailure, NotFound, InvalidToken { + + Identifier id = new Identifier(); + id.setValue(pid); + + DescribeResponse describeResponse; + + MNReadImpl mnReadImpl = new MNReadImpl(publicationContext, pluginDiscoveryService); + try { + describeResponse = mnReadImpl.describe(id); + } catch (NotFound ex) { + + Response.ResponseBuilder builder = Response.ok(); + builder.status(Status.NOT_FOUND); + builder.type(MediaType.TEXT_XML); + builder.header("DataONE-Exception-Name", "NotFound"); + builder.header("DataONE-Exception-DetailCode", ex.getDetail_code()); + builder.header("DataONE-Exception-Description", ex.getDescription()); + builder.header("DataONE-Exception-PID", pid); + + return builder.build(); + } + + Checksum checksum = describeResponse.getDataONE_Checksum(); + String checksumStr = checksum.getAlgorithm() + "," + checksum.getValue(); + + // Convert data to GMT and format for HTTP header + DateFormat gmtFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss "); + TimeZone gmtTimeZone = TimeZone.getTimeZone("GMT"); + gmtFormat.setTimeZone(gmtTimeZone); + Calendar calendar = new GregorianCalendar(); + calendar.setTime(describeResponse.getLast_Modified()); + calendar.setTimeZone(gmtTimeZone); + String dateStr = gmtFormat.format(calendar.getTime()); + dateStr += "GMT"; + + Response.ResponseBuilder builder = Response.ok(); + builder.header("Last-Modified", dateStr); + builder.header("Content-Length", describeResponse.getContent_Length().toString()); + builder.type(MediaType.APPLICATION_OCTET_STREAM); + builder.header("DataONE-formatId", describeResponse.getDataONE_ObjectFormatIdentifier().getValue().toString()); + builder.header("DataONE-Checksum", checksumStr); + builder.header("DataONE-SerialVersion", describeResponse.getSerialVersion().toString()); + + return builder.build(); + } + + @POST + @Path("/error") + @Produces(MediaType.TEXT_XML) + @Consumes(MediaType.MULTIPART_FORM_DATA) + @Mapped(namespaceMap = { @XmlNsMap(namespace = "http://irods.org/dfc-dataone", jsonName = "dfc-dataone") }) + public Response handleSynchronizationFailed(final MultipartFormDataInput input) + throws NotAuthorized, NotImplemented, ServiceFailure, InvalidToken { + + Map> uploadForm = input.getFormDataMap(); + List inputParts = uploadForm.get("message"); + if (inputParts == null || inputParts.size() == 0) { + throw new ServiceFailure("2161", "Synch Failure Exception cannot parse message"); + } + String str_xml = null; + try { + str_xml = inputParts.get(0).getBodyAsString(); + } catch (IOException e) { + throw new ServiceFailure("2161", "Synch Failure Exception cannot extract message xml"); + } + + MNError error = JAXB.unmarshal(new StringReader(str_xml), MNError.class); + SynchronizationFailed message = error.copyToSynchronizationFailed(); + + if (message == null) { + throw new ServiceFailure("2161", "Synch Failure Exception message is null"); + } + + MNReadImpl mnReadImpl = new MNReadImpl(publicationContext, pluginDiscoveryService); + boolean success = mnReadImpl.synchronizationFailed(message); + + if (!success) { + throw new ServiceFailure("2161", "Failed to log Synchronization Failure event"); + } + + Response.ResponseBuilder builder = Response.ok(); + + return builder.build(); + } + + // GET /object[?fromDate={fromDate}&toDate={toDate}&formatId={formatId} + // &replicaStatus={replicaStatus} &start={start}&count={count}] + @GET + @Path("/object") + @Produces(MediaType.TEXT_XML) + public MNObjectList handleListObjects(@QueryParam("fromDate") final String fromDateStr, + @QueryParam("toDate") final String toDateStr, @QueryParam("formatId") final String formatIdStr, + @QueryParam("replicaStatus") final Boolean replicaStatus, + @DefaultValue("0") @QueryParam("start") final Integer start, + @DefaultValue("500") @QueryParam("count") final Integer count) + throws InvalidToken, ServiceFailure, NotAuthorized, InvalidRequest, NotImplemented { + + MNObjectList mnObjectList = new MNObjectList(); + + // parse any query arguments to convert into correct formats, + // if not handled by data type constructors + ObjectFormatIdentifier formatId = new ObjectFormatIdentifier(); + formatId.setValue(formatIdStr); + + Date fromDate = null; + Date toDate = null; + try { + if (fromDateStr != null) { + fromDate = ISO8601.toCalendar(fromDateStr).getTime(); + } + if (toDateStr != null) { + toDate = ISO8601.toCalendar(toDateStr).getTime(); + } + } catch (ParseException e) { + logger.error("handleListObjects: unable to parse query dates"); + throw new InvalidRequest("1540", e.getMessage()); + } + + MNReadImpl mnReadImpl = new MNReadImpl(publicationContext, pluginDiscoveryService); + ObjectList objectList = mnReadImpl.listObjects(fromDate, toDate, formatId, replicaStatus, start, count); + mnObjectList.copy(objectList); + + return mnObjectList; + } + + /** + * @return the publicationContext + */ + public PublicationContext getPublicationContext() { + return publicationContext; + } + + /** + * @return the pluginDiscoveryService + */ + public PluginDiscoveryService getPluginDiscoveryService() { + return pluginDiscoveryService; + } +} diff --git a/dataone-node/src/main/java/org/irods/jargon/dataone/app/DataOneApp.java b/dataone-node/src/main/java/org/irods/jargon/dataone/app/DataOneApp.java new file mode 100644 index 0000000..802e207 --- /dev/null +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/app/DataOneApp.java @@ -0,0 +1,12 @@ +package org.irods.jargon.dataone.app; + +import javax.ws.rs.ApplicationPath; +import javax.ws.rs.core.Application; + +import org.springframework.stereotype.Component; + +@Component +@ApplicationPath("/dataone-node/") +public class DataOneApp extends Application { + +} diff --git a/dataone-node/src/main/java/org/irods/jargon/dataone/app/package-info.java b/dataone-node/src/main/java/org/irods/jargon/dataone/app/package-info.java new file mode 100644 index 0000000..b4a2a8d --- /dev/null +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/app/package-info.java @@ -0,0 +1,9 @@ +/** + * + */ +/** + * App layer for member node for dynamic discovery of plugins and spring boot + * @author mconway + * + */ +package org.irods.jargon.dataone.app; \ No newline at end of file diff --git a/src/main/java/org/irods/jargon/dataone/auth/BasicAuthFilter.java b/dataone-node/src/main/java/org/irods/jargon/dataone/auth/BasicAuthFilter.java similarity index 96% rename from src/main/java/org/irods/jargon/dataone/auth/BasicAuthFilter.java rename to dataone-node/src/main/java/org/irods/jargon/dataone/auth/BasicAuthFilter.java index d0f407a..765c23e 100644 --- a/src/main/java/org/irods/jargon/dataone/auth/BasicAuthFilter.java +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/auth/BasicAuthFilter.java @@ -1,5 +1,5 @@ /** - * + * */ package org.irods.jargon.dataone.auth; @@ -26,9 +26,9 @@ /** * Servlet filter implements anonymous auth - * + * * @author Lisa Stillwell - RENCI (www.renci.org) - * + * */ @Named public class BasicAuthFilter implements Filter { @@ -40,14 +40,14 @@ public class BasicAuthFilter implements Filter { private IRODSAccessObjectFactory irodsAccessObjectFactory; /** - * + * */ public BasicAuthFilter() { } /* * (non-Javadoc) - * + * * @see javax.servlet.Filter#init(javax.servlet.FilterConfig) */ @Override @@ -57,14 +57,14 @@ public void init(final FilterConfig filterConfig) throws ServletException { /* * (non-Javadoc) - * + * * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, * javax.servlet.ServletResponse, javax.servlet.FilterChain) */ @Override public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) - throws IOException, ServletException { + throws IOException, ServletException { log.info("doFilter()"); @@ -83,11 +83,11 @@ public void doFilter(final ServletRequest request, log.info("authResponse:{}", authResponse); log.info("success!"); - + chain.doFilter(httpRequest, httpResponse); return; - } catch (JargonException e) { + } catch (JargonException e) { log.warn("auth exception", e); sendAuthError(httpResponse); return; @@ -106,7 +106,7 @@ private void sendAuthError(final HttpServletResponse httpResponse) /* * (non-Javadoc) - * + * * @see javax.servlet.Filter#destroy() */ @Override diff --git a/src/main/java/org/irods/jargon/dataone/auth/DefaultHttpClientAndContext.java b/dataone-node/src/main/java/org/irods/jargon/dataone/auth/DefaultHttpClientAndContext.java similarity index 99% rename from src/main/java/org/irods/jargon/dataone/auth/DefaultHttpClientAndContext.java rename to dataone-node/src/main/java/org/irods/jargon/dataone/auth/DefaultHttpClientAndContext.java index b2964d4..b5b00fe 100644 --- a/src/main/java/org/irods/jargon/dataone/auth/DefaultHttpClientAndContext.java +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/auth/DefaultHttpClientAndContext.java @@ -1,5 +1,5 @@ /** - * + * */ package org.irods.jargon.dataone.auth; @@ -8,7 +8,7 @@ /** * @author Mike Conway - DICE (www.irods.org) - * + * */ public class DefaultHttpClientAndContext { private DefaultHttpClient httpClient; diff --git a/src/main/java/org/irods/jargon/dataone/auth/RestAuthUtils.java b/dataone-node/src/main/java/org/irods/jargon/dataone/auth/RestAuthUtils.java similarity index 86% rename from src/main/java/org/irods/jargon/dataone/auth/RestAuthUtils.java rename to dataone-node/src/main/java/org/irods/jargon/dataone/auth/RestAuthUtils.java index 9e8ef30..30d58a1 100644 --- a/src/main/java/org/irods/jargon/dataone/auth/RestAuthUtils.java +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/auth/RestAuthUtils.java @@ -1,11 +1,10 @@ /** - * + * */ package org.irods.jargon.dataone.auth; import java.util.Properties; -import org.apache.commons.codec.binary.Base64; import org.apache.http.HttpHost; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; @@ -26,16 +25,15 @@ /** * @author Lisa Stillwell - RENCI (www.renci.org) - * + * */ public class RestAuthUtils { private static Logger log = LoggerFactory.getLogger(RestAuthUtils.class); /** - * from anonymous build an iRODS - * account - * + * from anonymous build an iRODS account + * * @param restConfiguration * @return * @throws JargonException @@ -49,18 +47,16 @@ public static IRODSAccount getIRODSAccountFromBasicAuthValues( throw new IllegalArgumentException("null restConfiguration"); } -// return IRODSAccount.instanceForAnonymous( -// restConfiguration.getIrodsHost(), -// restConfiguration.getIrodsPort(), -// "", -// restConfiguration.getIrodsZone(), -// restConfiguration.getDefaultStorageResource()); - return IRODSAccount.instance( - restConfiguration.getIrodsHost(), + // return IRODSAccount.instanceForAnonymous( + // restConfiguration.getIrodsHost(), + // restConfiguration.getIrodsPort(), + // "", + // restConfiguration.getIrodsZone(), + // restConfiguration.getDefaultStorageResource()); + return IRODSAccount.instance(restConfiguration.getIrodsHost(), restConfiguration.getIrodsPort(), restConfiguration.getIrodsUserName(), - restConfiguration.getIrodsUserPswd(), - "", + restConfiguration.getIrodsUserPswd(), "", restConfiguration.getIrodsZone(), restConfiguration.getDefaultStorageResource()); @@ -68,7 +64,7 @@ public static IRODSAccount getIRODSAccountFromBasicAuthValues( /** * Return boilerplate http client for testing that uses basic auth - * + * * @param irodsAccount * @param testingProperties * @return @@ -76,7 +72,7 @@ public static IRODSAccount getIRODSAccountFromBasicAuthValues( */ public static DefaultHttpClientAndContext httpClientSetup( final IRODSAccount irodsAccount, final Properties testingProperties) - throws TestingUtilsException { + throws TestingUtilsException { if (irodsAccount == null) { throw new IllegalArgumentException("null irodsAccount"); diff --git a/src/main/java/org/irods/jargon/dataone/auth/package-info.java b/dataone-node/src/main/java/org/irods/jargon/dataone/auth/package-info.java similarity index 97% rename from src/main/java/org/irods/jargon/dataone/auth/package-info.java rename to dataone-node/src/main/java/org/irods/jargon/dataone/auth/package-info.java index bee7346..8f50f9e 100644 --- a/src/main/java/org/irods/jargon/dataone/auth/package-info.java +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/auth/package-info.java @@ -1,6 +1,6 @@ /** * Implementation of the DataONE REST API - * + * * @author Lisa Stillwell - RENCI - UNC, Chapel Hill (www.renci.org) * */ diff --git a/dataone-node/src/main/java/org/irods/jargon/dataone/configuration/PluginDiscoveryService.java b/dataone-node/src/main/java/org/irods/jargon/dataone/configuration/PluginDiscoveryService.java new file mode 100644 index 0000000..9d47089 --- /dev/null +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/configuration/PluginDiscoveryService.java @@ -0,0 +1,300 @@ +/** + * + */ +package org.irods.jargon.dataone.configuration; + +import java.io.File; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; +import java.util.Set; + +import javax.annotation.PostConstruct; + +import org.irods.jargon.core.connection.IRODSAccount; +import org.irods.jargon.dataone.events.DataOneEventServiceAO; +import org.irods.jargon.dataone.events.DataOneEventServiceFactory; +import org.irods.jargon.dataone.reposervice.AbstractDataOneRepoFactory; +import org.irods.jargon.dataone.reposervice.DataOneRepoServiceAO; +import org.irods.jargon.dataone.reposervice.DataOneRepoServiceFactory; +import org.irods.jargon.dataone.utils.PropertiesLoader; +import org.irods.jargon.pid.pidservice.AbstractDataOnePidFactory; +import org.irods.jargon.pid.pidservice.DataOnePidServiceFactory; +import org.irods.jargon.pid.pidservice.UniqueIdAO; +import org.reflections.Reflections; +import org.reflections.scanners.SubTypesScanner; +import org.reflections.scanners.TypeAnnotationsScanner; +import org.reflections.util.ConfigurationBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.xeustechnologies.jcl.JarClassLoader; +import org.xeustechnologies.jcl.context.DefaultContextLoader; +import org.xeustechnologies.jcl.context.JclContext; + +/** + * Service to locate and surface provided publisher plug-ins. Handles all the + * classloader and reflection tasks. + * + * @author Mike Conway - DICE + * + */ +@Component +public class PluginDiscoveryService { + + private JarClassLoader jcl; + private List urls = new ArrayList<>(); + @Autowired + private PublicationContext publicationContext; + + private DataOneEventServiceFactory dataOneEventServiceFactory; + private DataOnePidServiceFactory dataOnePidServiceFactory; + private DataOneRepoServiceFactory dataOneRepoServiceFactory; + + public static final Logger log = LoggerFactory.getLogger(PluginDiscoveryService.class); + + public PluginDiscoveryService() { + } + + public DataOneEventServiceAO instanceEventService(IRODSAccount irodsAccount) throws PluginNotFoundException { + log.info("instanceEventService()"); + log.info("dataOneEventServiceFactory:{}", dataOneEventServiceFactory); + log.info("publicationContext:{}", getPublicationContext()); + log.info("irodsAccount:{}", irodsAccount); + return dataOneEventServiceFactory.instance(getPublicationContext(), irodsAccount); + } + + public UniqueIdAO instanceUniqueIdService(IRODSAccount irodsAccount) throws PluginNotFoundException { + log.info("instancePidService()"); + return dataOnePidServiceFactory.instance(getPublicationContext(), irodsAccount); + } + + public DataOneRepoServiceAO instanceRepoService(IRODSAccount irodsAccount) throws PluginNotFoundException { + log.info("instancePidService()"); + return dataOneRepoServiceFactory.instance(getPublicationContext(), irodsAccount); + } + + @SuppressWarnings("unchecked") + private final Class loadImplClass(Class clazz) throws PluginNotFoundException { + + /* + * see: https://github.com/ronmamo/reflections + */ + + ConfigurationBuilder configurationBuilder = new ConfigurationBuilder(); + configurationBuilder.setUrls(urls).addClassLoader(JclContext.get()).addScanners(new SubTypesScanner(), + new TypeAnnotationsScanner()); + Reflections reflections = new Reflections(configurationBuilder); + + Set mechanisms = reflections.getSubTypesOf(clazz); + + // .getTypesAnnotatedWith(clazz, + // true); + log.info("mechanisms:{}", mechanisms); + + if (mechanisms.isEmpty()) { + throw new PluginNotFoundException("no plugin found for class:" + clazz.getName()); + } + + return (Class) mechanisms.iterator().next(); + + } + + /** + * Initialize publisher based on (required) configuration + * + * @throws PluginNotFoundException + * + * @throws PublicationException + */ + + @PostConstruct + public void init() throws PluginNotFoundException { + log.info("init()"); + if (publicationContext == null) { + throw new PluginRuntimeException("init() cannot be called, no provided publicationContext"); + } + + if (publicationContext.getRestConfiguration().getPluginJarLocation() == null + || publicationContext.getRestConfiguration().getPluginJarLocation().isEmpty()) { + throw new PluginRuntimeException("no jar file plugin directory specified"); + } + + log.info("scanning for plugin jars at:{}", publicationContext.getRestConfiguration().getPluginJarLocation()); + loadCandidateClasspaths(publicationContext.getRestConfiguration().getPluginJarLocation()); + initializeFactories(); + + } + + /** + * Look up and instantiate service factories, part of the startup process + */ + private void initializeFactories() throws PluginNotFoundException { + log.info("initializeFactories()"); + + log.info("pid factory..."); + Class clazz = loadImplClass(AbstractDataOnePidFactory.class); + try { + Constructor ctor = clazz.getConstructor(); + dataOnePidServiceFactory = (DataOnePidServiceFactory) ctor.newInstance(new Object[] {}); + log.info("dataOnePidServiceFactory success"); + } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException + | IllegalArgumentException | InvocationTargetException e) { + log.error("cannot find appropriate plugin", e); + throw new PluginNotFoundException(e); + } + + log.info("event factory..."); + /* + * Class clazzEvent = + * loadImplClass(AbstractDataOneEventServiceFactory.class); try { + * Constructor ctor = clazzEvent.getConstructor(); + * dataOneEventServiceFactory = (DataOneEventServiceFactory) + * ctor.newInstance(new Object[] {}); + * log.info("dataOneEventServiceFactory success"); } catch + * (NoSuchMethodException | SecurityException | InstantiationException | + * IllegalAccessException | IllegalArgumentException | + * InvocationTargetException e) { + * log.error("cannot find appropriate plugin", e); throw new + * PluginNotFoundException(e); } + */ + + PropertiesLoader propertiesLoader = new PropertiesLoader(); + Properties props = propertiesLoader.getProperties(); + String eventFactoryClassName = props.getProperty("plugin.factory.event"); + if (eventFactoryClassName == null || eventFactoryClassName.isEmpty()) { + log.error("cannot find appropriate plugin class name config in properties"); + throw new PluginNotFoundException("cannot find event factory plugin class name in properties"); + } + + log.info("load event factory class:{}", eventFactoryClassName); + try { + Class eventClass = Class.forName(eventFactoryClassName.trim()); + dataOneEventServiceFactory = (DataOneEventServiceFactory) eventClass.newInstance(); + log.info("event factory created"); + + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { + log.error("cannot find appropriate plugin", e); + throw new PluginNotFoundException(e); + } + + log.info("repo factory..."); + Class clazzRepo = loadImplClass(AbstractDataOneRepoFactory.class); + try { + Constructor ctor = clazzRepo.getConstructor(); + dataOneRepoServiceFactory = (DataOneRepoServiceFactory) ctor.newInstance(new Object[] {}); + log.info("dataOneRepoServiceFactory success"); + } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException + | IllegalArgumentException | InvocationTargetException e) { + log.error("cannot find appropriate plugin", e); + throw new PluginNotFoundException(e); + } + + log.info("plugin factories loaded"); + + } + + private void loadCandidateClasspaths(String libDir) { + + /* + * See https://github.com/kamranzafar/JCL for usage of JCL + */ + + File dependencyDirectory = new File(libDir); + File[] files = dependencyDirectory.listFiles(); + ArrayList uris = new ArrayList<>(); + for (int i = 0; i < files.length; i++) { + if (files[i].getName().endsWith(".jar")) { + log.info("adding jar:{} to candidates", files[i]); + uris.add(files[i].toURI()); + } + } + + log.info("creating jar class loader..."); + jcl = new JarClassLoader(); + + for (URI uri : uris) { + log.info("adding uri for jar:{}", uri); + try { + jcl.add(uri.toURL()); + urls.add(uri.toURL()); // testing outside jcl FIXME: decide! + } catch (MalformedURLException e) { + log.error("malformed url for jar file:{}", uri, e); + throw new PluginRuntimeException("error loading jar file", e); + } + } + + if (JclContext.get() == null) { + DefaultContextLoader context = new DefaultContextLoader(jcl); + context.loadContext(); + } + + } + + /** + * @return the publicationContext + */ + public PublicationContext getPublicationContext() { + return publicationContext; + } + + /** + * @param publicationContext + * the publicationContext to set + */ + public void setPublicationContext(PublicationContext publicationContext) { + this.publicationContext = publicationContext; + } + + /** + * @return the dataOneEventServiceFactory + */ + DataOneEventServiceFactory getDataOneEventServiceFactory() { + return dataOneEventServiceFactory; + } + + /** + * @param dataOneEventServiceFactory + * the dataOneEventServiceFactory to set + */ + void setDataOneEventServiceFactory(DataOneEventServiceFactory dataOneEventServiceFactory) { + this.dataOneEventServiceFactory = dataOneEventServiceFactory; + } + + /** + * @return the dataOnePidServiceFactory + */ + DataOnePidServiceFactory getDataOnePidServiceFactory() { + return dataOnePidServiceFactory; + } + + /** + * @param dataOnePidServiceFactory + * the dataOnePidServiceFactory to set + */ + void setDataOnePidServiceFactory(DataOnePidServiceFactory dataOnePidServiceFactory) { + this.dataOnePidServiceFactory = dataOnePidServiceFactory; + } + + /** + * @return the dataOneRepoServiceFactory + */ + DataOneRepoServiceFactory getDataOneRepoServiceFactory() { + return dataOneRepoServiceFactory; + } + + /** + * @param dataOneRepoServiceFactory + * the dataOneRepoServiceFactory to set + */ + void setDataOneRepoServiceFactory(DataOneRepoServiceFactory dataOneRepoServiceFactory) { + this.dataOneRepoServiceFactory = dataOneRepoServiceFactory; + } + +} diff --git a/src/main/java/org/irods/jargon/dataone/configuration/package-info.java b/dataone-node/src/main/java/org/irods/jargon/dataone/configuration/package-info.java similarity index 97% rename from src/main/java/org/irods/jargon/dataone/configuration/package-info.java rename to dataone-node/src/main/java/org/irods/jargon/dataone/configuration/package-info.java index 0abfb66..4d9c60a 100644 --- a/src/main/java/org/irods/jargon/dataone/configuration/package-info.java +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/configuration/package-info.java @@ -1,6 +1,6 @@ /** * Implementation of the DataONE REST API - * + * * @author Lisa Stillwell - RENCI - UNC, Chapel Hill (www.renci.org) * */ diff --git a/src/main/java/org/irods/jargon/dataone/context/SpringApplicationContext.java b/dataone-node/src/main/java/org/irods/jargon/dataone/context/SpringApplicationContext.java similarity index 70% rename from src/main/java/org/irods/jargon/dataone/context/SpringApplicationContext.java rename to dataone-node/src/main/java/org/irods/jargon/dataone/context/SpringApplicationContext.java index b3b61da..6575b3f 100644 --- a/src/main/java/org/irods/jargon/dataone/context/SpringApplicationContext.java +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/context/SpringApplicationContext.java @@ -9,16 +9,17 @@ public class SpringApplicationContext implements ApplicationContextAware { private static ApplicationContext appContext; // Private constructor prevents instantiation from other classes - private SpringApplicationContext() {} - + private SpringApplicationContext() { + } + @Override - public void setApplicationContext(ApplicationContext applicationContext) - throws BeansException { + public void setApplicationContext( + final ApplicationContext applicationContext) throws BeansException { appContext = applicationContext; } - public static Object getBean(String beanName) { + public static Object getBean(final String beanName) { return appContext.getBean(beanName); } diff --git a/src/main/java/org/irods/jargon/dataone/context/package-info.java b/dataone-node/src/main/java/org/irods/jargon/dataone/context/package-info.java similarity index 97% rename from src/main/java/org/irods/jargon/dataone/context/package-info.java rename to dataone-node/src/main/java/org/irods/jargon/dataone/context/package-info.java index f37755a..74cacec 100644 --- a/src/main/java/org/irods/jargon/dataone/context/package-info.java +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/context/package-info.java @@ -1,6 +1,6 @@ /** * Implementation of the DataONE REST API - * + * * @author Lisa Stillwell - RENCI - UNC, Chapel Hill (www.renci.org) * */ diff --git a/src/main/java/org/irods/jargon/dataone/domain/MNAccessPolicy.java b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNAccessPolicy.java similarity index 76% rename from src/main/java/org/irods/jargon/dataone/domain/MNAccessPolicy.java rename to dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNAccessPolicy.java index 1eb6447..9691408 100644 --- a/src/main/java/org/irods/jargon/dataone/domain/MNAccessPolicy.java +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNAccessPolicy.java @@ -5,22 +5,22 @@ import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; -@XmlType(propOrder={"subject","permission"}) +@XmlType(propOrder = { "subject", "permission" }) public class MNAccessPolicy { - + private String subject; // MNSubject type? private List permission; - + public MNAccessPolicy() { - + } - + @XmlElement(name = "permission") public List getPermission() { return permission; } - - public void setPermission(List p) { + + public void setPermission(final List p) { permission = p; } @@ -28,7 +28,7 @@ public String getSubject() { return subject; } - public void setSubject(String subject) { + public void setSubject(final String subject) { this.subject = subject; } diff --git a/src/main/java/org/irods/jargon/dataone/domain/MNChecksum.java b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNChecksum.java similarity index 57% rename from src/main/java/org/irods/jargon/dataone/domain/MNChecksum.java rename to dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNChecksum.java index 32a07b2..c945de4 100644 --- a/src/main/java/org/irods/jargon/dataone/domain/MNChecksum.java +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNChecksum.java @@ -8,44 +8,46 @@ @XmlRootElement(name = "checksum") public class MNChecksum { - + @XmlAttribute private String algorithm; - + @XmlValue private String value; - + public MNChecksum() { - - } - -// public String getValue() { -// return value; -// } - public void setValue(String value) { + + } + + // public String getValue() { + // return value; + // } + public void setValue(final String value) { this.value = value; } -// public String getAlgorithm() { -// return algorithm; -// } - public void setAlgorithm(String algorithm) { + + // public String getAlgorithm() { + // return algorithm; + // } + public void setAlgorithm(final String algorithm) { this.algorithm = algorithm; } - - public void copy(Checksum checksum) { - + + public void copy(final Checksum checksum) { + if (checksum == null) { - throw new IllegalArgumentException("MNChecksum::copy - Checksum is null"); + throw new IllegalArgumentException( + "MNChecksum::copy - Checksum is null"); } - + if (checksum.getValue() != null) { - this.value = checksum.getValue(); + value = checksum.getValue(); } - + if (checksum.getAlgorithm() != null) { - this.algorithm = checksum.getAlgorithm(); + algorithm = checksum.getAlgorithm(); } - + } } diff --git a/dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNError.java b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNError.java new file mode 100644 index 0000000..161508c --- /dev/null +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNError.java @@ -0,0 +1,78 @@ +package org.irods.jargon.dataone.domain; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.dataone.service.exceptions.SynchronizationFailed; + +@XmlRootElement(name = "error") +@XmlAccessorType(XmlAccessType.FIELD) +public class MNError { + + @XmlAttribute + private String detailCode; + @XmlAttribute + private String errorCode; + @XmlAttribute + private String name; + @XmlAttribute + private String pid; + @XmlElement + private String description; + + public MNError() { + } + + public String getDetailCode() { + return detailCode; + } + + public void setDetailCode(final String detailCode) { + this.detailCode = detailCode; + } + + public String getErrorCode() { + return errorCode; + } + + public void setErrorCode(final String errorCode) { + this.errorCode = errorCode; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public String getPid() { + return pid; + } + + public void setPid(final String pid) { + this.pid = pid; + } + + public String getDescription() { + return description; + } + + public void setDescription(final String description) { + this.description = description; + } + + public SynchronizationFailed copyToSynchronizationFailed() { + SynchronizationFailed syncFailed = new SynchronizationFailed( + detailCode, description); + + syncFailed.setPid(pid); + + return syncFailed; + + } +} diff --git a/src/main/java/org/irods/jargon/dataone/domain/MNLog.java b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNLog.java similarity index 71% rename from src/main/java/org/irods/jargon/dataone/domain/MNLog.java rename to dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNLog.java index 77a6e13..9510bc9 100644 --- a/src/main/java/org/irods/jargon/dataone/domain/MNLog.java +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNLog.java @@ -3,51 +3,51 @@ import java.util.ArrayList; import java.util.List; -import org.dataone.service.types.v1.Log; -import org.dataone.service.types.v1.LogEntry; - import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlRootElement; +import org.dataone.service.types.v1.Log; +import org.dataone.service.types.v1.LogEntry; + @XmlRootElement(name = "log") public class MNLog { @XmlAttribute private String count; - + @XmlAttribute private String start; - - @XmlAttribute + + @XmlAttribute private String total; - + private List logEntry; public List getLogEntry() { return logEntry; } - public void setLogEntry(List logEntry) { + public void setLogEntry(final List logEntry) { this.logEntry = logEntry; } - - public void copy(Log log) { - + + public void copy(final Log log) { + if (log == null) { throw new IllegalArgumentException("MNLogy::copy - Log is null"); } - - this.count = String.valueOf(log.getCount()); - this.start = String.valueOf(log.getStart()); - this.total = String.valueOf(log.getTotal()); - + + count = String.valueOf(log.getCount()); + start = String.valueOf(log.getStart()); + total = String.valueOf(log.getTotal()); + if (log.getLogEntryList() != null) { List logEntryList = log.getLogEntryList(); - this.logEntry = new ArrayList(); - + logEntry = new ArrayList(); + for (LogEntry l : logEntryList) { MNLogEntry mnLogEntry = new MNLogEntry(); mnLogEntry.copy(l); - this.logEntry.add(mnLogEntry); + logEntry.add(mnLogEntry); } } } diff --git a/src/main/java/org/irods/jargon/dataone/domain/MNLogEntry.java b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNLogEntry.java similarity index 56% rename from src/main/java/org/irods/jargon/dataone/domain/MNLogEntry.java rename to dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNLogEntry.java index 49dab47..d631608 100644 --- a/src/main/java/org/irods/jargon/dataone/domain/MNLogEntry.java +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNLogEntry.java @@ -1,18 +1,15 @@ package org.irods.jargon.dataone.domain; -import java.util.Date; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlType; import org.dataone.service.types.v1.LogEntry; import org.irods.jargon.dataone.utils.ISO8601; //@XmlAccessorType(XmlAccessType.NONE) -@XmlType(propOrder={"entryId","identifier","ipAddress","userAgent","subject","event","dateLogged","nodeIdentifier"}) +@XmlType(propOrder = { "entryId", "identifier", "ipAddress", "userAgent", + "subject", "event", "dateLogged", "nodeIdentifier" }) public class MNLogEntry { - + private String entryId; private String dateLogged; private String event; @@ -21,110 +18,118 @@ public class MNLogEntry { private String ipAddress; private String userAgent; private String subject; - + public String getEntryId() { return entryId; } - public void setEntryId(String entryId) { + + public void setEntryId(final String entryId) { this.entryId = entryId; } - + public String getDateLogged() { return dateLogged; } - public void setDateLogged(String dateLogged) { + + public void setDateLogged(final String dateLogged) { this.dateLogged = dateLogged; } - + public String getEvent() { return event; } - public void setEvent(String event) { + + public void setEvent(final String event) { this.event = event; } - + public String getIdentifier() { return identifier; } - public void setIdentifier(String identifier) { + + public void setIdentifier(final String identifier) { this.identifier = identifier; } - + public String getNodeIdentifier() { return nodeIdentifier; } - public void setNodeIdentifier(String nodeIdentifier) { + + public void setNodeIdentifier(final String nodeIdentifier) { this.nodeIdentifier = nodeIdentifier; } - + public String getIpAddress() { return ipAddress; } - public void setIpAddress(String ipAddress) { + + public void setIpAddress(final String ipAddress) { this.ipAddress = ipAddress; } - + public String getUserAgent() { return userAgent; } - public void setUserAgent(String userAgent) { + + public void setUserAgent(final String userAgent) { this.userAgent = userAgent; } - + public String getSubject() { return subject; } - public void setSubject(String subject) { + + public void setSubject(final String subject) { this.subject = subject; } - - public void copy(LogEntry logEntry) { - + + public void copy(final LogEntry logEntry) { + if (logEntry == null) { - throw new IllegalArgumentException("MNLogEntry::copy - LogEntry is null"); + throw new IllegalArgumentException( + "MNLogEntry::copy - LogEntry is null"); } - + if (logEntry.getEntryId() != null) { - this.entryId = logEntry.getEntryId(); + entryId = logEntry.getEntryId(); } - + if (logEntry.getDateLogged() != null) { - this.dateLogged = ISO8601.convertToGMTString(logEntry.getDateLogged()); + dateLogged = ISO8601.convertToGMTString(logEntry.getDateLogged()); } - + if (logEntry.getEvent() != null) { - this.event = logEntry.getEvent().xmlValue(); + event = logEntry.getEvent().xmlValue(); } - + if (logEntry.getIdentifier() != null) { - this.identifier = logEntry.getIdentifier().getValue(); + identifier = logEntry.getIdentifier().getValue(); } - + if (logEntry.getNodeIdentifier() != null) { - this.nodeIdentifier = logEntry.getNodeIdentifier().getValue(); + nodeIdentifier = logEntry.getNodeIdentifier().getValue(); } - + if (logEntry.getIpAddress() != null) { - this.ipAddress = logEntry.getIpAddress(); + ipAddress = logEntry.getIpAddress(); } - + else { // need to use empty string to make this tag show up - this.ipAddress = new String(); + ipAddress = new String(); } - + if (logEntry.getUserAgent() != null) { - this.userAgent = logEntry.getUserAgent(); - } - else { + userAgent = logEntry.getUserAgent(); + } else { // need to use empty string to make this tag show up - this.userAgent = new String(); + userAgent = new String(); } - + if (logEntry.getSubject() != null) { - this.subject = logEntry.getSubject().getValue(); - } - + subject = logEntry.getSubject().getValue(); + } + } - + } diff --git a/src/main/java/org/irods/jargon/dataone/domain/MNNode.java b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNNode.java similarity index 53% rename from src/main/java/org/irods/jargon/dataone/domain/MNNode.java rename to dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNNode.java index 7046c3d..896b0d7 100644 --- a/src/main/java/org/irods/jargon/dataone/domain/MNNode.java +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNNode.java @@ -1,8 +1,5 @@ - package org.irods.jargon.dataone.domain; -import java.io.IOException; -import java.io.InputStream; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; @@ -20,111 +17,94 @@ import org.dataone.service.types.v1.Services; import org.dataone.service.types.v1.Subject; import org.dataone.service.types.v1.Synchronization; +import org.irods.jargon.dataone.utils.PropertiesLoader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @XmlRootElement(name = "node") -@XmlType(propOrder={"identifier","name","description","baseURL", - "services","synchronization","ping","subject","contactSubject"}) +@XmlType(propOrder = { "identifier", "name", "description", "baseURL", "services", "synchronization", "ping", "subject", + "contactSubject" }) public class MNNode { - + private final String serviceKey = "irods.dataone.service."; private final String serviceKeyName = ".name"; - + @XmlAttribute private String replicate; - + @XmlAttribute private String synchronize; - - @XmlAttribute + + @XmlAttribute private String type; - + @XmlAttribute private String state; - + private String identifier; // MN NodeReference type private String name; private String description; private String baseURL; private List services; private MNSynchronization synchronization; -// private NodeReplicationPolicy nodeReplicationPolicy; + // private NodeReplicationPolicy nodeReplicationPolicy; private MNPing ping; private List subject; private List contactSubject; - + private Logger log = LoggerFactory.getLogger(this.getClass()); - + public MNNode() { initializeProperties(); } - + private void initializeProperties() { - Properties prop = new Properties(); - InputStream input = null; - - try { - String filename = "d1client.properties"; - input = getClass().getClassLoader().getResourceAsStream(filename); - - // load a properties file - prop.load(input); - - this.replicate = prop.getProperty("irods.dataone.replicate"); - this.synchronize = prop.getProperty("irods.dataone.synchronize"); - this.type = prop.getProperty("irods.dataone.type"); - //TODO: make sure proper exceptions are caught and handled - - this.identifier = prop.getProperty("irods.dataone.identifier"); - this.name = prop.getProperty("irods.dataone.name"); - this.description = prop.getProperty("irods.dataone.description"); - this.baseURL = prop.getProperty("irods.dataone.baseurl"); - this.services = initServices(prop); - this.synchronization = initSychronization(prop); -// this.subject = initSubjects(prop); -// this.contactSubject = initContactSubjects(prop); - - } catch (IOException ex) { - ex.printStackTrace(); - } finally { - if (input != null) { - try { - input.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } + PropertiesLoader loader = new PropertiesLoader(); + Properties prop = loader.getProperties(); + + replicate = prop.getProperty("irods.dataone.replicate"); + synchronize = prop.getProperty("irods.dataone.synchronize"); + type = prop.getProperty("irods.dataone.type"); + // TODO: make sure proper exceptions are caught and handled + + identifier = prop.getProperty("irods.dataone.identifier"); + name = prop.getProperty("irods.dataone.name"); + description = prop.getProperty("irods.dataone.description"); + baseURL = prop.getProperty("irods.dataone.baseurl"); + services = initServices(prop); + synchronization = initSychronization(prop); + // this.subject = initSubjects(prop); + // this.contactSubject = initContactSubjects(prop); + } - - private List initContactSubjects(Properties prop) { + + private List initContactSubjects(final Properties prop) { // TODO Auto-generated method stub return null; } - private List initSubjects(Properties prop) { + private List initSubjects(final Properties prop) { // TODO Auto-generated method stub return null; } - private MNSynchronization initSychronization(Properties prop) { + private MNSynchronization initSychronization(final Properties prop) { MNSynchronization mnSynchronization = new MNSynchronization(); - + return mnSynchronization; } - private List initServices(Properties prop) { - List services = new ArrayList(); - + private List initServices(final Properties prop) { + List services = new ArrayList<>(); + Enumeration keys = prop.propertyNames(); while (keys.hasMoreElements()) { String key = (String) keys.nextElement(); - if((key.startsWith(this.serviceKey)) && (key.endsWith(this.serviceKeyName))) { + if ((key.startsWith(serviceKey)) && (key.endsWith(serviceKeyName))) { String serviceName = prop.getProperty(key); MNService service = new MNService(); service.setName(serviceName); - String isServiceAvailableKey = this.serviceKey + serviceName.toLowerCase(); + String isServiceAvailableKey = serviceKey + serviceName.toLowerCase(); String isServiceAvailableValue = prop.getProperty(isServiceAvailableKey); service.setAvailable(Boolean.parseBoolean(isServiceAvailableValue)); String verKey = isServiceAvailableKey + ".version"; @@ -132,172 +112,180 @@ private List initServices(Properties prop) { services.add(service); } } - + return services; } - //public NodeReference getIdentifier() { + // public NodeReference getIdentifier() { public String getIdentifier() { return identifier; } - public void setIdentifier(String identifier) { + + public void setIdentifier(final String identifier) { this.identifier = identifier; } - + public String getName() { return name; } - public void setName(String name) { + + public void setName(final String name) { this.name = name; } - + public String getDescription() { return description; } - public void setDescription(String description) { + + public void setDescription(final String description) { this.description = description; } - + public String getBaseURL() { return baseURL; } - public void setBaseURL(String baseURL) { + + public void setBaseURL(final String baseURL) { this.baseURL = baseURL; } - + @XmlElementWrapper(name = "services") @XmlElement(name = "service") public List getServices() { return services; } - public void setServices(List services) { + + public void setServices(final List services) { this.services = services; } - + public MNSynchronization getSynchronization() { return synchronization; } - public void setSynchronization(MNSynchronization synchronization) { + + public void setSynchronization(final MNSynchronization synchronization) { this.synchronization = synchronization; } - + public MNPing getPing() { return ping; } - public void setPing(MNPing ping) { + + public void setPing(final MNPing ping) { this.ping = ping; } - -// public MNSubject getSubject() { -// return subject; -// } -// public void setSubject(MNSubject subject) { -// this.subject = subject; -// } -// -// public MNSubject getContactSubject() { -// return contactSubject; -// } -// public void setContactSubject(MNSubject contactSubject) { -// this.contactSubject = contactSubject; -// } - + + // public MNSubject getSubject() { + // return subject; + // } + // public void setSubject(MNSubject subject) { + // this.subject = subject; + // } + // + // public MNSubject getContactSubject() { + // return contactSubject; + // } + // public void setContactSubject(MNSubject contactSubject) { + // this.contactSubject = contactSubject; + // } + public List getSubject() { return subject; } - public void setSubject(List subject) { + + public void setSubject(final List subject) { this.subject = subject; } - - + public List getContactSubject() { return contactSubject; } - public void setContactSubject(List contactSubject) { + + public void setContactSubject(final List contactSubject) { this.contactSubject = contactSubject; } - -// public NodeReplicationPolicy getNodeReplicationPolicy() { -// return nodeReplicationPolicy; -// } -// -// public void setNodeReplicationPolicy(NodeReplicationPolicy nodeReplicationPolicy) { -// this.nodeReplicationPolicy = nodeReplicationPolicy; -// } - - - public void copy(Node node) { - + + // public NodeReplicationPolicy getNodeReplicationPolicy() { + // return nodeReplicationPolicy; + // } + // + // public void setNodeReplicationPolicy(NodeReplicationPolicy + // nodeReplicationPolicy) { + // this.nodeReplicationPolicy = nodeReplicationPolicy; + // } + + public void copy(final Node node) { + if (node == null) { throw new IllegalArgumentException("MNNode::copy - Node is null"); } - - this.replicate = Boolean.toString(node.isReplicate()); - this.synchronize = Boolean.toString(node.isSynchronize()); - + + replicate = Boolean.toString(node.isReplicate()); + synchronize = Boolean.toString(node.isSynchronize()); + if (node.getType() != null) { - this.type = node.getType().name(); + type = node.getType().name(); } - + if (node.getState() != null) { - this.state = node.getState().xmlValue(); + state = node.getState().xmlValue(); } - + if (node.getIdentifier() != null) { - this.identifier = node.getIdentifier().getValue(); + identifier = node.getIdentifier().getValue(); } - + if (node.getName() != null) { - this.name = node.getName(); + name = node.getName(); } - + if (node.getDescription() != null) { - this.description = node.getDescription(); + description = node.getDescription(); } - + if (node.getBaseURL() != null) { - this.baseURL = node.getBaseURL(); + baseURL = node.getBaseURL(); } - + if (node.getServices() != null) { Services services = node.getServices(); List serviceList = services.getServiceList(); - this.services = new ArrayList(); - + this.services = new ArrayList<>(); + for (Service s : serviceList) { MNService mnService = new MNService(); mnService.copy(s); this.services.add(mnService); } } - + if (node.getSynchronization() != null) { Synchronization synch = node.getSynchronization(); - this.synchronization = new MNSynchronization(); - this.synchronization.copy(synch); + synchronization = new MNSynchronization(); + synchronization.copy(synch); } - + if (node.getPing() != null) { Ping ping = node.getPing(); this.ping = new MNPing(); - this.ping.copy(ping); + this.ping.copy(ping); } - + if (node.getSubjectList() != null) { List subjectList = node.getSubjectList(); - this.subject = new ArrayList(); + subject = new ArrayList<>(); for (Subject s : subjectList) { - this.subject.add(s.getValue()); + subject.add(s.getValue()); } } if (node.getContactSubjectList() != null) { List subjectList = node.getContactSubjectList(); - this.contactSubject = new ArrayList(); + contactSubject = new ArrayList<>(); for (Subject s : subjectList) { - this.contactSubject.add(s.getValue()); + contactSubject.add(s.getValue()); } } } diff --git a/src/main/java/org/irods/jargon/dataone/domain/MNObjectInfo.java b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNObjectInfo.java similarity index 58% rename from src/main/java/org/irods/jargon/dataone/domain/MNObjectInfo.java rename to dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNObjectInfo.java index 8d262ac..3bf06a6 100644 --- a/src/main/java/org/irods/jargon/dataone/domain/MNObjectInfo.java +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNObjectInfo.java @@ -1,81 +1,91 @@ package org.irods.jargon.dataone.domain; -import java.util.Date; - import javax.xml.bind.annotation.XmlType; import org.dataone.service.types.v1.Checksum; import org.dataone.service.types.v1.ObjectInfo; import org.irods.jargon.dataone.utils.ISO8601; -@XmlType(propOrder={"identifier","formatId","checksum","dateSysMetadataModified","size"}) +@XmlType(propOrder = { "identifier", "formatId", "checksum", + "dateSysMetadataModified", "size" }) public class MNObjectInfo { - + private String identifier; private String formatId; private MNChecksum checksum; private String dateSysMetadataModified; private long size; - + public String getIdentifier() { return identifier; } - public void setIdentifier(String identifier) { + + public void setIdentifier(final String identifier) { this.identifier = identifier; } + public String getFormatId() { return formatId; } - public void setFormatId(String formatId) { + + public void setFormatId(final String formatId) { this.formatId = formatId; } + public MNChecksum getChecksum() { return checksum; } - public void setChecksum(MNChecksum checksum) { + + public void setChecksum(final MNChecksum checksum) { this.checksum = checksum; } + public String getDateSysMetadataModified() { return dateSysMetadataModified; } - public void setDateSysMetadataModified(String dateSysMetadataModified) { + + public void setDateSysMetadataModified(final String dateSysMetadataModified) { this.dateSysMetadataModified = dateSysMetadataModified; } + public long getSize() { return size; } - public void setSize(long size) { + + public void setSize(final long size) { this.size = size; } - - public void copy(ObjectInfo objectInfo){ - + + public void copy(final ObjectInfo objectInfo) { + if (objectInfo == null) { - throw new IllegalArgumentException("MNObjectInfo::copy - ObjectInfo is null"); + throw new IllegalArgumentException( + "MNObjectInfo::copy - ObjectInfo is null"); } - + if (objectInfo.getIdentifier() != null) { - this.identifier = objectInfo.getIdentifier().getValue(); + identifier = objectInfo.getIdentifier().getValue(); } - + if (objectInfo.getFormatId() != null) { - this.formatId = objectInfo.getFormatId().getValue(); + formatId = objectInfo.getFormatId().getValue(); } - + if (objectInfo.getChecksum() != null) { Checksum newChecksum = objectInfo.getChecksum(); - this.checksum = new MNChecksum(); - this.checksum.copy(newChecksum); + checksum = new MNChecksum(); + checksum.copy(newChecksum); } - + if (objectInfo.getDateSysMetadataModified() != null) { - this.dateSysMetadataModified = ISO8601.convertToGMTString(objectInfo.getDateSysMetadataModified()); + dateSysMetadataModified = ISO8601.convertToGMTString(objectInfo + .getDateSysMetadataModified()); } - + if (objectInfo.getSize() != null) { - this.size = objectInfo.getSize().longValue(); + size = objectInfo.getSize().longValue(); } - + } } diff --git a/src/main/java/org/irods/jargon/dataone/domain/MNObjectList.java b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNObjectList.java similarity index 60% rename from src/main/java/org/irods/jargon/dataone/domain/MNObjectList.java rename to dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNObjectList.java index 57f72d1..f5b84b8 100644 --- a/src/main/java/org/irods/jargon/dataone/domain/MNObjectList.java +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNObjectList.java @@ -11,59 +11,60 @@ @XmlRootElement(name = "objectList") public class MNObjectList { - + @XmlAttribute private int count; - + @XmlAttribute private int start; - + @XmlAttribute private int total; - + private List objectInfo; - - public void setCnt(int cnt) { - this.count = cnt; + + public void setCnt(final int cnt) { + count = cnt; } - - public void setStrt(int strt) { - this.start = strt; + + public void setStrt(final int strt) { + start = strt; } - - public void setTot(int tot) { - this.total = tot; + + public void setTot(final int tot) { + total = tot; } public List getObjectInfo() { return objectInfo; } - public void setObjectInfo(List objectInfo) { + public void setObjectInfo(final List objectInfo) { this.objectInfo = objectInfo; } - - public void copy(ObjectList objectList) { - + + public void copy(final ObjectList objectList) { + if (objectList == null) { - throw new IllegalArgumentException("MNObjectList::copy - ObjectList is null"); + throw new IllegalArgumentException( + "MNObjectList::copy - ObjectList is null"); } - - this.count = objectList.getCount(); - this.start = objectList.getStart(); - this.total = objectList.getTotal(); - + + count = objectList.getCount(); + start = objectList.getStart(); + total = objectList.getTotal(); + if (objectList.getObjectInfoList() != null) { List newObjectInfoList = objectList.getObjectInfoList(); - this.objectInfo = new ArrayList(); - + objectInfo = new ArrayList(); + for (ObjectInfo oi : newObjectInfoList) { MNObjectInfo mnObjectInfo = new MNObjectInfo(); mnObjectInfo.copy(oi); - this.objectInfo.add(mnObjectInfo); + objectInfo.add(mnObjectInfo); } } - + } } diff --git a/src/main/java/org/irods/jargon/dataone/domain/MNPermissionEnum.java b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNPermissionEnum.java similarity index 75% rename from src/main/java/org/irods/jargon/dataone/domain/MNPermissionEnum.java rename to dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNPermissionEnum.java index 0e17917..af07579 100644 --- a/src/main/java/org/irods/jargon/dataone/domain/MNPermissionEnum.java +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNPermissionEnum.java @@ -4,34 +4,36 @@ import org.irods.jargon.core.protovalues.FilePermissionEnum; public enum MNPermissionEnum { - READ("read", FilePermissionEnum.READ, Permission.READ), - WRITE("write", FilePermissionEnum.WRITE, Permission.WRITE), - CHANGE("changePermission", FilePermissionEnum.OWN, Permission.CHANGE_PERMISSION); - + READ("read", FilePermissionEnum.READ, Permission.READ), WRITE("write", + FilePermissionEnum.WRITE, Permission.WRITE), CHANGE( + "changePermission", FilePermissionEnum.OWN, + Permission.CHANGE_PERMISSION); + private String permission; private FilePermissionEnum irodsPermissionEnum; private Permission dataOnePermissionEnum; - - private MNPermissionEnum(String p, FilePermissionEnum i, Permission d) { - this.permission = p; - this.irodsPermissionEnum = i; - this.dataOnePermissionEnum = d; + + private MNPermissionEnum(final String p, final FilePermissionEnum i, + final Permission d) { + permission = p; + irodsPermissionEnum = i; + dataOnePermissionEnum = d; } - + public String getPermission() { return permission; } - + public FilePermissionEnum getIrodsPermissionEnum() { return irodsPermissionEnum; } - + public Permission getDataOnePermissionEnum() { return dataOnePermissionEnum; } - + public static MNPermissionEnum valueForWeb(final Permission p) { - switch(p) { + switch (p) { case READ: return MNPermissionEnum.READ; case WRITE: @@ -42,9 +44,9 @@ public static MNPermissionEnum valueForWeb(final Permission p) { return MNPermissionEnum.READ; } } - + public static FilePermissionEnum valueForIrods(final Permission p) { - switch(p) { + switch (p) { case READ: return FilePermissionEnum.READ; case WRITE: @@ -55,9 +57,9 @@ public static FilePermissionEnum valueForIrods(final Permission p) { return FilePermissionEnum.READ; } } - + public static Permission valueForDataOne(final FilePermissionEnum p) { - switch(p) { + switch (p) { case READ: return Permission.READ; case WRITE: diff --git a/src/main/java/org/irods/jargon/dataone/domain/MNPing.java b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNPing.java similarity index 80% rename from src/main/java/org/irods/jargon/dataone/domain/MNPing.java rename to dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNPing.java index 04eb302..f9e505a 100644 --- a/src/main/java/org/irods/jargon/dataone/domain/MNPing.java +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNPing.java @@ -8,25 +8,26 @@ @XmlAccessorType(XmlAccessType.NONE) public class MNPing { - + @XmlAttribute private boolean success; public boolean getSuccess() { return success; } - public void setSuccess(boolean success) { + + public void setSuccess(final boolean success) { this.success = success; } - - public void copy(Ping ping) { - + + public void copy(final Ping ping) { + if (ping == null) { throw new IllegalArgumentException("MNPing::copy - Ping is null"); } - + if (ping.getSuccess() != null) { - this.success = ping.getSuccess().booleanValue(); + success = ping.getSuccess().booleanValue(); } } diff --git a/src/main/java/org/irods/jargon/dataone/domain/MNReplicationPolicy.java b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNReplicationPolicy.java similarity index 80% rename from src/main/java/org/irods/jargon/dataone/domain/MNReplicationPolicy.java rename to dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNReplicationPolicy.java index de3d658..05b8cf5 100644 --- a/src/main/java/org/irods/jargon/dataone/domain/MNReplicationPolicy.java +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNReplicationPolicy.java @@ -3,15 +3,15 @@ import javax.xml.bind.annotation.XmlAttribute; public class MNReplicationPolicy { - + @XmlAttribute private boolean replicationAllowed; - + public MNReplicationPolicy() { - + } - - public void setReplicationAllowed(boolean flag) { + + public void setReplicationAllowed(final boolean flag) { replicationAllowed = flag; } diff --git a/dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNSchedule.java b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNSchedule.java new file mode 100644 index 0000000..80201ea --- /dev/null +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNSchedule.java @@ -0,0 +1,133 @@ +package org.irods.jargon.dataone.domain; + +import java.util.Properties; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; + +import org.dataone.service.types.v1.Schedule; +import org.irods.jargon.dataone.utils.PropertiesLoader; + +@XmlAccessorType(XmlAccessType.NONE) +public class MNSchedule { + + @XmlAttribute + private String hour; + @XmlAttribute + private String mday; + @XmlAttribute + private String min; + @XmlAttribute + private String mon; + @XmlAttribute + private String sec; + @XmlAttribute + private String wday; + @XmlAttribute + private String year; + + public MNSchedule() { + initializeProperties(); + } + + private void initializeProperties() { + PropertiesLoader loader = new PropertiesLoader(); + Properties prop = loader.getProperties(); + + hour = prop.getProperty("irods.dataone.sync.schedule.hour"); + mday = prop.getProperty("irods.dataone.sync.schedule.mday"); + min = prop.getProperty("irods.dataone.sync.schedule.min"); + mon = prop.getProperty("irods.dataone.sync.schedule.mon"); + sec = prop.getProperty("irods.dataone.sync.schedule.sec"); + wday = prop.getProperty("irods.dataone.sync.schedule.wday"); + year = prop.getProperty("irods.dataone.sync.schedule.year"); + + } + + // public String getHour() { + // return hour; + // } + // public void setHour(String hour) { + // this.hour = hour; + // } + // + // public String getMday() { + // return mday; + // } + // public void setMday(String mday) { + // this.mday = mday; + // } + // + // public String getMin() { + // return min; + // } + // public void setMin(String min) { + // this.min = min; + // } + // + // public String getMon() { + // return mon; + // } + // public void setMon(String mon) { + // this.mon = mon; + // } + // + // public String getSec() { + // return sec; + // } + // public void setSec(String sec) { + // this.sec = sec; + // } + // + // public String getWday() { + // return wday; + // } + // public void setWday(String wday) { + // this.wday = wday; + // } + // + // public String getYear() { + // return year; + // } + // public void setYear(String year) { + // this.year = year; + // } + + public void copy(final Schedule s) { + + if (s == null) { + return; + // TODO: log something here? + } + + if (s.getHour() != null) { + hour = s.getHour(); + } + + if (s.getMday() != null) { + mday = s.getMday(); + } + + if (s.getMin() != null) { + min = s.getMin(); + } + + if (s.getMon() != null) { + mon = s.getMon(); + } + + if (s.getSec() != null) { + sec = s.getSec(); + } + + if (s.getWday() != null) { + wday = s.getWday(); + } + + if (s.getYear() != null) { + year = s.getYear(); + } + } + +} diff --git a/src/main/java/org/irods/jargon/dataone/domain/MNService.java b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNService.java similarity index 64% rename from src/main/java/org/irods/jargon/dataone/domain/MNService.java rename to dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNService.java index 4e59ffd..d08dd1c 100644 --- a/src/main/java/org/irods/jargon/dataone/domain/MNService.java +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNService.java @@ -1,61 +1,61 @@ package org.irods.jargon.dataone.domain; -import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlRootElement; import org.dataone.service.types.v1.Service; @XmlAccessorType(XmlAccessType.NONE) public class MNService { - + @XmlAttribute private String name; @XmlAttribute private String version; @XmlAttribute private boolean available; - + public String getName() { return name; } - - public void setName(String name) { + + public void setName(final String name) { this.name = name; } - + public String getVersion() { return version; } - - public void setVersion(String version) { + + public void setVersion(final String version) { this.version = version; } - + public boolean isAvailable() { return available; } - - public void setAvailable(boolean available) { + + public void setAvailable(final boolean available) { this.available = available; } - - public void copy(Service service) { + + public void copy(final Service service) { if (service == null) { - throw new IllegalArgumentException("MNService::copy - Service is null"); + throw new IllegalArgumentException( + "MNService::copy - Service is null"); } - + if (service.getName() != null) { - this.name = service.getName(); + name = service.getName(); } - + if (service.getVersion() != null) { - this.version = service.getVersion(); + version = service.getVersion(); } - + if (service.getAvailable() != null) { - this.available = service.getAvailable().booleanValue(); + available = service.getAvailable().booleanValue(); } } diff --git a/src/main/java/org/irods/jargon/dataone/domain/MNSynchronization.java b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNSynchronization.java similarity index 52% rename from src/main/java/org/irods/jargon/dataone/domain/MNSynchronization.java rename to dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNSynchronization.java index 8e87450..9e8a42e 100644 --- a/src/main/java/org/irods/jargon/dataone/domain/MNSynchronization.java +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNSynchronization.java @@ -1,33 +1,27 @@ package org.irods.jargon.dataone.domain; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - import javax.xml.bind.annotation.XmlType; import org.dataone.service.types.v1.Schedule; -import org.dataone.service.types.v1.Service; -import org.dataone.service.types.v1.Services; import org.dataone.service.types.v1.Synchronization; import org.irods.jargon.dataone.utils.ISO8601; -@XmlType(propOrder={"schedule","lastHarvested","lastCompleteHarvest"}) +@XmlType(propOrder = { "schedule", "lastHarvested", "lastCompleteHarvest" }) public class MNSynchronization { - + private String lastHarvested; private String lastCompleteHarvest; private MNSchedule schedule; - + public MNSynchronization() { - this.schedule = new MNSchedule(); + schedule = new MNSchedule(); } - + public String getLastHarvested() { return lastHarvested; } - public void setLastHarvested(String lastHarvested) { + public void setLastHarvested(final String lastHarvested) { this.lastHarvested = lastHarvested; } @@ -35,7 +29,7 @@ public String getLastCompleteHarvest() { return lastCompleteHarvest; } - public void setLastCompleteHarvest(String lastCompleteHarvest) { + public void setLastCompleteHarvest(final String lastCompleteHarvest) { this.lastCompleteHarvest = lastCompleteHarvest; } @@ -43,28 +37,31 @@ public MNSchedule getSchedule() { return schedule; } - public void setSchedule(MNSchedule schedule) { + public void setSchedule(final MNSchedule schedule) { this.schedule = schedule; } - - public void copy(Synchronization synch) { - + + public void copy(final Synchronization synch) { + if (synch == null) { - throw new IllegalArgumentException("MNSynchronization::copy - Synchronization is null"); + throw new IllegalArgumentException( + "MNSynchronization::copy - Synchronization is null"); } - + if (synch.getLastHarvested() != null) { - this.lastHarvested = ISO8601.convertToGMTString(synch.getLastHarvested()); + lastHarvested = ISO8601 + .convertToGMTString(synch.getLastHarvested()); } - + if (synch.getLastCompleteHarvest() != null) { - this.lastCompleteHarvest = ISO8601.convertToGMTString(synch.getLastCompleteHarvest()); + lastCompleteHarvest = ISO8601.convertToGMTString(synch + .getLastCompleteHarvest()); } - + if (synch.getSchedule() != null) { Schedule s = synch.getSchedule(); - this.schedule = new MNSchedule(); - this.schedule.copy(s); + schedule = new MNSchedule(); + schedule.copy(s); } } diff --git a/src/main/java/org/irods/jargon/dataone/domain/MNSystemMetadata.java b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNSystemMetadata.java similarity index 60% rename from src/main/java/org/irods/jargon/dataone/domain/MNSystemMetadata.java rename to dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNSystemMetadata.java index 480a780..1d0d6d1 100644 --- a/src/main/java/org/irods/jargon/dataone/domain/MNSystemMetadata.java +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/MNSystemMetadata.java @@ -1,7 +1,6 @@ package org.irods.jargon.dataone.domain; import java.util.ArrayList; -import java.util.Date; import java.util.List; import javax.xml.bind.annotation.XmlElement; @@ -13,16 +12,13 @@ import org.dataone.service.types.v1.Permission; import org.dataone.service.types.v1.SystemMetadata; import org.irods.jargon.dataone.utils.ISO8601; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; @XmlRootElement(name = "systemMetadata") -@XmlType(propOrder={"serialVersion","identifier","formatId","size", - "checksum","submitter","rightsHolder","accessPolicy", - "replicationPolicy","obsoletes","obsoletedBy","archived", - "dateUploaded","dateSysMetadataModified","originMemberNode", - "authoritativeMemberNode"}) - +@XmlType(propOrder = { "serialVersion", "identifier", "formatId", "size", + "checksum", "submitter", "rightsHolder", "accessPolicy", + "replicationPolicy", "obsoletes", "obsoletedBy", "archived", + "dateUploaded", "dateSysMetadataModified", "originMemberNode", + "authoritativeMemberNode" }) public class MNSystemMetadata { private long serialVersion; @@ -30,8 +26,8 @@ public class MNSystemMetadata { private String formatId; private long size; private MNChecksum checksum; -// private MNSubject submitter; NOTE: a Subject is just a string -// private MNSubject rightsHolder; + // private MNSubject submitter; NOTE: a Subject is just a string + // private MNSubject rightsHolder; private String submitter; private String rightsHolder; private List accessPolicy; @@ -43,210 +39,180 @@ public class MNSystemMetadata { private String dateSysMetadataModified; private String originMemberNode; private String authoritativeMemberNode; - + public MNSystemMetadata() { - + } - - + @XmlElementWrapper(name = "accessPolicy") @XmlElement(name = "allow") public List getAccessPolicy() { return accessPolicy; } - - public void setAccessPolicy(List ap) { - this.accessPolicy = ap; - } + public void setAccessPolicy(final List ap) { + accessPolicy = ap; + } public long getSerialVersion() { return serialVersion; } - - public void setSerialVersion(long serialVersion) { + public void setSerialVersion(final long serialVersion) { this.serialVersion = serialVersion; } - public String getIdentifier() { return identifier; } - - public void setIdentifier(String identifier) { + public void setIdentifier(final String identifier) { this.identifier = identifier; } - public String getFormatId() { return formatId; } - - public void setFormatId(String formatId) { + public void setFormatId(final String formatId) { this.formatId = formatId; } - public long getSize() { return size; } - - public void setSize(long size) { + public void setSize(final long size) { this.size = size; } - public MNChecksum getChecksum() { return checksum; } - - public void setChecksum(MNChecksum checksum) { + public void setChecksum(final MNChecksum checksum) { this.checksum = checksum; } - public String getSubmitter() { return submitter; } - - public void setSubmitter(String submitter) { + public void setSubmitter(final String submitter) { this.submitter = submitter; } - public String getRightsHolder() { return rightsHolder; } - - public void setRightsHolder(String rightsHolder) { + public void setRightsHolder(final String rightsHolder) { this.rightsHolder = rightsHolder; } - public MNReplicationPolicy getReplicationPolicy() { return replicationPolicy; } - - public void setReplicationPolicy(MNReplicationPolicy replicationPolicy) { + public void setReplicationPolicy(final MNReplicationPolicy replicationPolicy) { this.replicationPolicy = replicationPolicy; } - public String getObsoletes() { return obsoletes; } - - public void setObsoletes(String obsoletes) { + public void setObsoletes(final String obsoletes) { this.obsoletes = obsoletes; } - public String getObsoletedBy() { return obsoletedBy; } - - public void setObsoletedBy(String obsoletedBy) { + public void setObsoletedBy(final String obsoletedBy) { this.obsoletedBy = obsoletedBy; } - public boolean isArchived() { return archived; } - - public void setArchived(boolean archived) { + public void setArchived(final boolean archived) { this.archived = archived; } - public String getDateUploaded() { return dateUploaded; } - - public void setDateUploaded(String dateUploaded) { + public void setDateUploaded(final String dateUploaded) { this.dateUploaded = dateUploaded; } - public String getDateSysMetadataModified() { return dateSysMetadataModified; } - - public void setDateSysMetadataModified(String dateSysMetadataModified) { + public void setDateSysMetadataModified(final String dateSysMetadataModified) { this.dateSysMetadataModified = dateSysMetadataModified; } - public String getOriginMemberNode() { return originMemberNode; } - - public void setOriginMemberNode(String originMemberNode) { + public void setOriginMemberNode(final String originMemberNode) { this.originMemberNode = originMemberNode; } - public String getAuthoritativeMemberNode() { return authoritativeMemberNode; } - - public void setAuthoritativeMemberNode(String authoritativeMemberNode) { + public void setAuthoritativeMemberNode(final String authoritativeMemberNode) { this.authoritativeMemberNode = authoritativeMemberNode; } - - public void copy(SystemMetadata metadata) { + public void copy(final SystemMetadata metadata) { if (metadata == null) { - throw new IllegalArgumentException("MNSystemMetadata::copy - SystemMetadata is null"); + throw new IllegalArgumentException( + "MNSystemMetadata::copy - SystemMetadata is null"); } - + if (metadata.getSerialVersion() != null) { - this.serialVersion = metadata.getSerialVersion().longValue(); + serialVersion = metadata.getSerialVersion().longValue(); } - + if (metadata.getIdentifier() != null) { - this.identifier = metadata.getIdentifier().getValue(); + identifier = metadata.getIdentifier().getValue(); } - + if (metadata.getFormatId() != null) { - this.formatId = metadata.getFormatId().getValue(); + formatId = metadata.getFormatId().getValue(); } - + if (metadata.getSize() != null) { - this.size = metadata.getSize().longValue(); + size = metadata.getSize().longValue(); } - + if (metadata.getChecksum() != null) { MNChecksum checksum = new MNChecksum(); checksum.setValue(metadata.getChecksum().getValue()); checksum.setAlgorithm(metadata.getChecksum().getAlgorithm()); this.checksum = checksum; } - + if (metadata.getSubmitter() != null) { - this.submitter = metadata.getSubmitter().getValue(); + submitter = metadata.getSubmitter().getValue(); } - + if (metadata.getRightsHolder() != null) { - this.rightsHolder = metadata.getRightsHolder().getValue(); + rightsHolder = metadata.getRightsHolder().getValue(); } - - if ((metadata.getAccessPolicy() != null) && (metadata.getAccessPolicy().sizeAllowList()) > 0) { + + if ((metadata.getAccessPolicy() != null) + && (metadata.getAccessPolicy().sizeAllowList()) > 0) { List accessPolicies = new ArrayList(); for (AccessRule rule : metadata.getAccessPolicy().getAllowList()) { MNAccessPolicy policy = new MNAccessPolicy(); @@ -258,38 +224,41 @@ public void copy(SystemMetadata metadata) { policy.setPermission(permissions); accessPolicies.add(policy); } - this.accessPolicy = accessPolicies; + accessPolicy = accessPolicies; } - + if (metadata.getReplicationPolicy() != null) { - this.replicationPolicy = new MNReplicationPolicy(); - this.replicationPolicy.setReplicationAllowed(metadata.getReplicationPolicy().getReplicationAllowed()); + replicationPolicy = new MNReplicationPolicy(); + replicationPolicy.setReplicationAllowed(metadata + .getReplicationPolicy().getReplicationAllowed()); } - + if (metadata.getObsoletes() != null) { - this.obsoletes = metadata.getObsoletes().getValue(); + obsoletes = metadata.getObsoletes().getValue(); } - + if (metadata.getObsoletedBy() != null) { - this.obsoletedBy = metadata.getObsoletedBy().getValue(); + obsoletedBy = metadata.getObsoletedBy().getValue(); } if (metadata.getArchived() != null) { - this.archived = metadata.getArchived(); + archived = metadata.getArchived(); } - - this.dateUploaded = ISO8601.convertToGMTString(metadata.getDateUploaded()); - this.dateSysMetadataModified = ISO8601.convertToGMTString(metadata.getDateSysMetadataModified()); - + + dateUploaded = ISO8601.convertToGMTString(metadata.getDateUploaded()); + dateSysMetadataModified = ISO8601.convertToGMTString(metadata + .getDateSysMetadataModified()); + if (metadata.getOriginMemberNode() != null) { - this.originMemberNode = metadata.getOriginMemberNode().getValue(); + originMemberNode = metadata.getOriginMemberNode().getValue(); } - + if (metadata.getAuthoritativeMemberNode() != null) { - this.authoritativeMemberNode = metadata.getAuthoritativeMemberNode().getValue(); - } - + authoritativeMemberNode = metadata.getAuthoritativeMemberNode() + .getValue(); + } + return; } - + } diff --git a/src/main/java/org/irods/jargon/dataone/domain/ServerInfo.java b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/ServerInfo.java similarity index 75% rename from src/main/java/org/irods/jargon/dataone/domain/ServerInfo.java rename to dataone-node/src/main/java/org/irods/jargon/dataone/domain/ServerInfo.java index a25c1b0..f3caf59 100644 --- a/src/main/java/org/irods/jargon/dataone/domain/ServerInfo.java +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/ServerInfo.java @@ -1,5 +1,5 @@ /** - * + * */ package org.irods.jargon.dataone.domain; @@ -8,15 +8,14 @@ import javax.xml.bind.annotation.XmlRootElement; import org.irods.jargon.core.connection.IRODSServerProperties.IcatEnabled; -import org.jboss.resteasy.annotations.providers.jaxb.json.BadgerFish; /** * Information about the server for representation as XML or JSON - * + * * @author Mike Conway - DICE (www.irods.org) */ @XmlRootElement(name = "serverInfo") -//@BadgerFish +// @BadgerFish public class ServerInfo { private Date initializeDate = new Date(); @@ -26,7 +25,7 @@ public class ServerInfo { private String apiVersion = ""; private String rodsZone = ""; /** - * + * */ private long currentServerTime = 0; @@ -34,7 +33,7 @@ public Date getInitializeDate() { return initializeDate; } - public void setInitializeDate(Date initializeDate) { + public void setInitializeDate(final Date initializeDate) { this.initializeDate = initializeDate; } @@ -42,7 +41,7 @@ public IcatEnabled getIcatEnabled() { return icatEnabled; } - public void setIcatEnabled(IcatEnabled icatEnabled) { + public void setIcatEnabled(final IcatEnabled icatEnabled) { this.icatEnabled = icatEnabled; } @@ -50,7 +49,7 @@ public int getServerBootTime() { return serverBootTime; } - public void setServerBootTime(int serverBootTime) { + public void setServerBootTime(final int serverBootTime) { this.serverBootTime = serverBootTime; } @@ -58,7 +57,7 @@ public String getRelVersion() { return relVersion; } - public void setRelVersion(String relVersion) { + public void setRelVersion(final String relVersion) { this.relVersion = relVersion; } @@ -66,7 +65,7 @@ public String getApiVersion() { return apiVersion; } - public void setApiVersion(String apiVersion) { + public void setApiVersion(final String apiVersion) { this.apiVersion = apiVersion; } @@ -74,7 +73,7 @@ public String getRodsZone() { return rodsZone; } - public void setRodsZone(String rodsZone) { + public void setRodsZone(final String rodsZone) { this.rodsZone = rodsZone; } @@ -82,7 +81,7 @@ public long getCurrentServerTime() { return currentServerTime; } - public void setCurrentServerTime(long currentServerTime) { + public void setCurrentServerTime(final long currentServerTime) { this.currentServerTime = currentServerTime; } diff --git a/dataone-node/src/main/java/org/irods/jargon/dataone/domain/package-info.java b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/package-info.java new file mode 100644 index 0000000..c0ac441 --- /dev/null +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/domain/package-info.java @@ -0,0 +1,14 @@ +/** + * + */ +/** + * @author lisa + * + */ +@XmlSchema(namespace = "http://ns.dataone.org/service/types/v1", elementFormDefault = XmlNsForm.UNQUALIFIED, xmlns = { @XmlNs(namespaceURI = "http://ns.dataone.org/service/types/v1", prefix = "d1") }) +package org.irods.jargon.dataone.domain; + +import javax.xml.bind.annotation.XmlNs; +import javax.xml.bind.annotation.XmlNsForm; +import javax.xml.bind.annotation.XmlSchema; + diff --git a/dataone-node/src/main/java/org/irods/jargon/dataone/exceptions/ExceptionUtils.java b/dataone-node/src/main/java/org/irods/jargon/dataone/exceptions/ExceptionUtils.java new file mode 100644 index 0000000..08cabc7 --- /dev/null +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/exceptions/ExceptionUtils.java @@ -0,0 +1,76 @@ +package org.irods.jargon.dataone.exceptions; + +import java.io.StringWriter; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.FactoryConfigurationError; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +public class ExceptionUtils { + + private Logger log = LoggerFactory.getLogger(this.getClass()); + + public static String getNotFoundXmlForObjectId(final String pid, + final String detailCode, final String description) { + + final String name = "NotFound"; + final String errorCode = "404"; + + DocumentBuilder documentBuilder; + try { + documentBuilder = DocumentBuilderFactory.newInstance() + .newDocumentBuilder(); + } catch (ParserConfigurationException e) { + return e.getMessage(); + } catch (FactoryConfigurationError e) { + return e.getMessage(); + } + Document dom = documentBuilder.newDocument(); + // create the root node of the dom + Element errorNode = dom.createElement("error"); + + errorNode.setAttribute("name", name); + errorNode.setAttribute("detailCode", detailCode); + errorNode.setAttribute("errorCode", errorCode); + + Element desc = dom.createElement("description"); + desc.appendChild(dom.createTextNode(description)); + + dom.appendChild(errorNode); + errorNode.appendChild(desc); + + try { + return domToString(dom); + } catch (Exception ex) { + // log.error(ex.getMessage()); + return ex.getMessage(); + } + } + + private static String domToString(final Document document) throws Exception { + String result = null; + StringWriter strWtr = new StringWriter(); + TransformerFactory transformerFactory = TransformerFactory + .newInstance(); + Transformer transformer = transformerFactory.newTransformer(); + + if (document != null) { + StreamResult strResult = new StreamResult(strWtr); + transformer.transform(new DOMSource(document.getDocumentElement()), + strResult); + result = strResult.getWriter().toString(); + } + return result; + } + +} diff --git a/src/main/java/org/irods/jargon/dataone/exceptions/NotFoundExceptionMapper.java b/dataone-node/src/main/java/org/irods/jargon/dataone/exceptions/NotFoundExceptionMapper.java similarity index 53% rename from src/main/java/org/irods/jargon/dataone/exceptions/NotFoundExceptionMapper.java rename to dataone-node/src/main/java/org/irods/jargon/dataone/exceptions/NotFoundExceptionMapper.java index dd4d845..f2329c6 100644 --- a/src/main/java/org/irods/jargon/dataone/exceptions/NotFoundExceptionMapper.java +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/exceptions/NotFoundExceptionMapper.java @@ -11,13 +11,15 @@ public class NotFoundExceptionMapper implements ExceptionMapper { @Override - public Response toResponse(NotFound ex) { + public Response toResponse(final NotFound ex) { + + return Response + .status(Response.Status.NOT_FOUND) + .header("Vary", "Accept-Encoding") + .entity(ExceptionUtils.getNotFoundXmlForObjectId(ex.getPid(), + ex.getDetail_code(), ex.getDescription())) + .type(MediaType.TEXT_XML).build(); - return Response.status(Response.Status.NOT_FOUND) - .header("Vary", "Accept-Encoding") - .entity(ExceptionUtils.getNotFoundXmlForObjectId(ex.getPid(), ex.getDetail_code(), ex.getDescription())) - .type(MediaType.TEXT_XML).build(); - } } \ No newline at end of file diff --git a/src/main/java/org/irods/jargon/dataone/exceptions/package-info.java b/dataone-node/src/main/java/org/irods/jargon/dataone/exceptions/package-info.java similarity index 95% rename from src/main/java/org/irods/jargon/dataone/exceptions/package-info.java rename to dataone-node/src/main/java/org/irods/jargon/dataone/exceptions/package-info.java index a4de564..4977184 100644 --- a/src/main/java/org/irods/jargon/dataone/exceptions/package-info.java +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/exceptions/package-info.java @@ -1,5 +1,5 @@ /** - * + * */ /** * @author lisa diff --git a/src/main/java/org/irods/jargon/dataone/package-info.java b/dataone-node/src/main/java/org/irods/jargon/dataone/package-info.java similarity index 97% rename from src/main/java/org/irods/jargon/dataone/package-info.java rename to dataone-node/src/main/java/org/irods/jargon/dataone/package-info.java index 697de24..f919f76 100644 --- a/src/main/java/org/irods/jargon/dataone/package-info.java +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/package-info.java @@ -1,6 +1,6 @@ /** * Implementation of the DataONE REST API - * + * * @author Lisa Stillwell - RENCI - UNC, Chapel Hill (www.renci.org) * */ diff --git a/dataone-node/src/main/java/org/irods/jargon/dataone/tier1/MNCoreImpl.java b/dataone-node/src/main/java/org/irods/jargon/dataone/tier1/MNCoreImpl.java new file mode 100644 index 0000000..2273338 --- /dev/null +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/tier1/MNCoreImpl.java @@ -0,0 +1,157 @@ +package org.irods.jargon.dataone.tier1; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.dataone.service.exceptions.InsufficientResources; +import org.dataone.service.exceptions.InvalidRequest; +import org.dataone.service.exceptions.InvalidToken; +import org.dataone.service.exceptions.NotAuthorized; +import org.dataone.service.exceptions.NotImplemented; +import org.dataone.service.exceptions.ServiceFailure; +import org.dataone.service.mn.tier1.v1.MNCore; +import org.dataone.service.types.v1.Event; +import org.dataone.service.types.v1.Log; +import org.dataone.service.types.v1.Node; +import org.dataone.service.types.v1.NodeState; +import org.dataone.service.types.v1.Ping; +import org.dataone.service.types.v1.Session; +import org.dataone.service.types.v1.Subject; +import org.dataone.service.types.v1.Synchronization; +import org.irods.jargon.core.connection.IRODSAccount; +import org.irods.jargon.core.exception.JargonException; +import org.irods.jargon.core.pub.EnvironmentalInfoAO; +import org.irods.jargon.dataone.auth.RestAuthUtils; +import org.irods.jargon.dataone.configuration.PluginDiscoveryService; +import org.irods.jargon.dataone.configuration.PluginNotFoundException; +import org.irods.jargon.dataone.configuration.PublicationContext; +import org.irods.jargon.dataone.events.DataOneEventServiceAO; +import org.irods.jargon.dataone.events.EventsEnum; +import org.irods.jargon.dataone.utils.PropertiesLoader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MNCoreImpl implements MNCore { + + private Logger log = LoggerFactory.getLogger(this.getClass()); + private final PublicationContext publicationContext; + private final PluginDiscoveryService pluginDiscoveryService; + // private final MNCoreModel mnCoreModel; + + public MNCoreImpl(final PublicationContext publicationContext, + final PluginDiscoveryService pluginDiscoveryService) { + this.publicationContext = publicationContext; + this.pluginDiscoveryService = pluginDiscoveryService; + } + + @Override + public Date ping() throws NotImplemented, ServiceFailure, InsufficientResources { + + try { + IRODSAccount irodsAccount = RestAuthUtils + .getIRODSAccountFromBasicAuthValues(publicationContext.getRestConfiguration()); + + EnvironmentalInfoAO environmentalInfoAO = publicationContext.getIrodsAccessObjectFactory() + .getEnvironmentalInfoAO(irodsAccount); + + long currentTime = environmentalInfoAO.getIRODSServerCurrentTime(); + return new Date(currentTime); + + } catch (Exception e) { + log.error("ping failed: {}", e.getMessage()); + throw new ServiceFailure("2042", "failed to contact iRODS server"); + } finally { + publicationContext.getIrodsAccessObjectFactory().closeSessionAndEatExceptions(); + } + } + + @Override + public Log getLogRecords(final Date fromDate, final Date toDate, final Event event, final String pidFilter, + final Integer startIdx, final Integer count) + throws InvalidRequest, InvalidToken, NotAuthorized, NotImplemented, ServiceFailure { + + log.info("getLogRecords: elasticsearch implementation"); + EventsEnum eventsEnum = null; + if (event != null) { + eventsEnum = EventsEnum.valueOfFromDataOne(event); + } + + try { + IRODSAccount irodsAccount = RestAuthUtils + .getIRODSAccountFromBasicAuthValues(publicationContext.getRestConfiguration()); + DataOneEventServiceAO eventService = pluginDiscoveryService.instanceEventService(irodsAccount); + return eventService.getLogs(fromDate, toDate, eventsEnum, pidFilter, startIdx, count); + } catch (PluginNotFoundException e) { + log.error("error processing event plugin", e); + throw new ServiceFailure("1490", "retrieval of log records failed"); + } catch (JargonException e) { + log.error("error processing event ", e); + throw new ServiceFailure("1490", "retrieval of log records failed"); + } + + } + + @Override + public Node getCapabilities() throws NotImplemented, ServiceFailure { + + Node node = new Node(); + + Ping ping = new Ping(); + ping.setSuccess(true); + node.setState(NodeState.UP); + + try { + IRODSAccount irodsAccount = RestAuthUtils + .getIRODSAccountFromBasicAuthValues(publicationContext.getRestConfiguration()); + EnvironmentalInfoAO environmentalInfoAO = publicationContext.getIrodsAccessObjectFactory() + .getEnvironmentalInfoAO(irodsAccount); + + environmentalInfoAO.getIRODSServerProperties().getServerBootTime(); + + } catch (Exception e) { + log.error("getCapabilities: iRODS server is not running"); + ping.setSuccess(false); + node.setState(NodeState.DOWN); + } + + // get properties + PropertiesLoader pl = new PropertiesLoader(); + String subjectString = new String(); + subjectString += pl.getProperty("irods.dataone.subject-string"); + String contactSubjectString = new String(); + contactSubjectString += pl.getProperty("irods.dataone.contact-subject-string"); + + List subjects = new ArrayList<>(); + Subject subject = new Subject(); + subject.setValue(subjectString); + subjects.add(subject); + List contactSubjects = new ArrayList<>(); + Subject contactSubject = new Subject(); + contactSubject.setValue(contactSubjectString); + contactSubjects.add(contactSubject); + + node.setPing(ping); + node.setSubjectList(subjects); + node.setContactSubjectList(contactSubjects); + + Synchronization sync = new Synchronization(); + // TODO: put correct dates here, pull from RepoService + sync.setLastCompleteHarvest(new Date()); + sync.setLastHarvested(new Date()); + node.setSynchronization(sync); + + log.info("returning node: {}", node.toString()); + + return node; + } + + @Override + public Log getLogRecords(final Session session, final Date date1, final Date date2, final Event event, + final String s, final Integer integer1, final Integer integer2) + throws InvalidRequest, InvalidToken, NotAuthorized, NotImplemented, ServiceFailure { + + throw new NotImplemented("1461", "Authenticated getLogRecords not implemented"); + } + +} diff --git a/dataone-node/src/main/java/org/irods/jargon/dataone/tier1/MNReadImpl.java b/dataone-node/src/main/java/org/irods/jargon/dataone/tier1/MNReadImpl.java new file mode 100644 index 0000000..323eebc --- /dev/null +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/tier1/MNReadImpl.java @@ -0,0 +1,637 @@ +package org.irods.jargon.dataone.tier1; + +import java.io.BufferedOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import javax.servlet.http.HttpServletResponse; + +import org.dataone.service.exceptions.InsufficientResources; +import org.dataone.service.exceptions.InvalidRequest; +import org.dataone.service.exceptions.InvalidToken; +import org.dataone.service.exceptions.NotAuthorized; +import org.dataone.service.exceptions.NotFound; +import org.dataone.service.exceptions.NotImplemented; +import org.dataone.service.exceptions.ServiceFailure; +import org.dataone.service.exceptions.SynchronizationFailed; +import org.dataone.service.mn.tier1.v1.MNRead; +import org.dataone.service.types.v1.AccessPolicy; +import org.dataone.service.types.v1.AccessRule; +import org.dataone.service.types.v1.Checksum; +import org.dataone.service.types.v1.DescribeResponse; +import org.dataone.service.types.v1.Event; +import org.dataone.service.types.v1.Identifier; +import org.dataone.service.types.v1.NodeReference; +import org.dataone.service.types.v1.ObjectFormatIdentifier; +import org.dataone.service.types.v1.ObjectInfo; +import org.dataone.service.types.v1.ObjectList; +import org.dataone.service.types.v1.Permission; +import org.dataone.service.types.v1.ReplicationPolicy; +import org.dataone.service.types.v1.Session; +import org.dataone.service.types.v1.Subject; +import org.dataone.service.types.v1.SystemMetadata; +import org.irods.jargon.core.connection.IRODSAccount; +import org.irods.jargon.core.exception.JargonException; +import org.irods.jargon.core.protovalues.FilePermissionEnum; +import org.irods.jargon.core.pub.DataObjectAO; +import org.irods.jargon.core.pub.domain.DataObject; +import org.irods.jargon.core.pub.domain.UserFilePermission; +import org.irods.jargon.core.pub.io.IRODSFile; +import org.irods.jargon.core.pub.io.IRODSFileInputStream; +import org.irods.jargon.dataone.auth.RestAuthUtils; +import org.irods.jargon.dataone.configuration.PluginDiscoveryService; +import org.irods.jargon.dataone.configuration.PluginNotFoundException; +import org.irods.jargon.dataone.configuration.PublicationContext; +import org.irods.jargon.dataone.domain.MNPermissionEnum; +import org.irods.jargon.dataone.events.DataOneEventServiceAO; +import org.irods.jargon.dataone.reposervice.DataObjectListResponse; +import org.irods.jargon.dataone.reposervice.DataOneRepoServiceAO; +import org.irods.jargon.dataone.utils.PropertiesLoader; +import org.irods.jargon.pid.pidservice.UniqueIdAO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MNReadImpl implements MNRead { + + private Logger log = LoggerFactory.getLogger(this.getClass()); + + private final PublicationContext publicationContext; + private final PluginDiscoveryService pluginDiscoveryService; + private PropertiesLoader properties = new PropertiesLoader(); + + /** + * @param publicationContext + * @param pluginDiscoveryService + */ + public MNReadImpl(final PublicationContext publicationContext, + final PluginDiscoveryService pluginDiscoveryService) { + super(); + this.publicationContext = publicationContext; + this.pluginDiscoveryService = pluginDiscoveryService; + } + + @Override + public DescribeResponse describe(final Identifier id) + throws InvalidToken, NotAuthorized, NotImplemented, ServiceFailure, NotFound { + + if (id == null || id.getValue().isEmpty()) { + log.error("id is null or empty"); + throw new NotFound("1402", "invalid iRODS data object id"); + } + + DataObject dataObject = new DataObject(); + Checksum checksum = new Checksum(); + ObjectFormatIdentifier formatIdentifier = new ObjectFormatIdentifier(); + BigInteger contentLength; + Date lastModified; + BigInteger serialVersion; + IRODSAccount irodsAccount; + DataOneRepoServiceAO repoService; + + // first try and find data object for this id + try { + irodsAccount = RestAuthUtils.getIRODSAccountFromBasicAuthValues(publicationContext.getRestConfiguration()); + repoService = pluginDiscoveryService.instanceRepoService(irodsAccount); + } catch (Exception ex) { + log.error("{}", ex.toString()); + throw new ServiceFailure("1390", ex.getMessage()); + } + + try { + irodsAccount = RestAuthUtils.getIRODSAccountFromBasicAuthValues(publicationContext.getRestConfiguration()); + + UniqueIdAO pidService = pluginDiscoveryService.instanceUniqueIdService(irodsAccount); + dataObject = pidService.getDataObjectFromIdentifier(id); + + } catch (Exception e) { + log.info("cannot find id: {}", id.getValue()); + throw new NotFound("1380", "The specified object does not exist on this node."); + } + + try { + Long contentLengthLong = dataObject.getDataSize(); + String contentLengthStr = contentLengthLong.toString(); + contentLength = new BigInteger(contentLengthStr); + + // lastModified = dataObject.getUpdatedAt(); + lastModified = repoService.getLastModifiedDateForDataObject(dataObject); + + String format = repoService.dataObjectFormat(dataObject); + formatIdentifier.setValue(format); + + String csum = dataObject.getChecksum(); + if (csum == null) { + log.info("checksum does not exist for file: {}", dataObject.getAbsolutePath()); + // throw new NotFound("404", "1420"); + } else { + checksum.setValue(csum); + checksum.setAlgorithm(properties.getProperty("irods.dataone.chksum-algorithm")); + } + + serialVersion = getSerialVersion(); + + } catch (Exception e) { + log.error("Cannot access iRODS object: {}", dataObject.getAbsolutePath()); + throw new ServiceFailure("1390", e.getMessage()); + } + + return new DescribeResponse(formatIdentifier, contentLength, lastModified, checksum, serialVersion); + } + + @Override + public DescribeResponse describe(final Session arg0, final Identifier arg1) + throws InvalidToken, NotAuthorized, NotImplemented, ServiceFailure, NotFound { + throw new NotImplemented("1361", "this service has not been implemented"); + } + + public void streamObject(final HttpServletResponse response, final Identifier id) throws ServiceFailure, NotFound { + + DataObject dataObject; + String path; + IRODSAccount irodsAccount; + IRODSFile irodsFile; + // first try and find data object for this id + try { + irodsAccount = RestAuthUtils.getIRODSAccountFromBasicAuthValues(publicationContext.getRestConfiguration()); + + UniqueIdAO pidService = pluginDiscoveryService.instanceUniqueIdService(irodsAccount); + dataObject = pidService.getDataObjectFromIdentifier(id); + + path = dataObject.getAbsolutePath(); + irodsFile = publicationContext.getIrodsAccessObjectFactory().getIRODSFileFactory(irodsAccount) + .instanceIRODSFile(path); + + if (!irodsFile.exists()) { + log.info("file does not exist"); + throw new NotFound("1020", "No data object could be found for given PID:" + id.getValue()); + } + + } catch (Exception ex) { + log.info("file does not exist"); + throw new NotFound("1020", "No data object could be found for given PID:" + id.getValue()); + } + + try { + InputStream stream = publicationContext.getIrodsAccessObjectFactory().getIRODSFileFactory(irodsAccount) + .instanceIRODSFileInputStream(irodsFile); + int contentLength = (int) irodsFile.length(); + log.info("contentLength={}", contentLength); + + response.setContentType("application/octet-stream"); + response.setHeader("Content-Disposition", "attachment;filename=" + dataObject.getDataName()); + response.setContentLength(contentLength); + // response.addHeader("Vary", "Accept-Encoding"); + log.info("response: {}", response.toString()); + + OutputStream output = new BufferedOutputStream(response.getOutputStream()); + + int readBytes = 0; + byte[] buffer = new byte[4096]; + + while ((readBytes = stream.read(buffer, 0, 4096)) != -1) { // + log.info("readBytes={}", readBytes); + output.write(buffer, 0, readBytes); + } + output.flush(); + if (stream != null) { + stream.close(); + } + if (output != null) { + output.close(); + } + + } catch (Exception e) { + log.error("Cannot stream iRODS object: {}", path); + throw new ServiceFailure("1030", "unable to stream iRODS data object"); + } + + } + + @Override + public IRODSFileInputStream get(final Identifier id) + throws InvalidToken, NotAuthorized, NotImplemented, ServiceFailure, NotFound, InsufficientResources { + + // TODO: Not sure how to implement this properly - used streamObject + // method instead + IRODSFileInputStream stream = null; + + // if (id == null || id.toString().isEmpty()) { + // throw new NotFound("invalid", "identifier is invalid"); + // } + + // String path = "/dfcmain/home/DFC-public/DFC-slide.pptx"; + // String path = "/dfcmain/home/lisa/test_this.txt"; + + // log.info("decoded path:{}", path); + // + // try { + // IRODSAccount irodsAccount = RestAuthUtils + // .getIRODSAccountFromBasicAuthValues(restConfiguration); + // IRODSFile irodsFile = irodsAccessObjectFactory + // .getIRODSFileFactory(irodsAccount).instanceIRODSFile(path); + // + // if (!irodsFile.exists()) { + // log.info("file does not exist"); + // throw new NotFound("404", + // "The iRODS member node can't find object requested - + // "+id.toString()); + // } + // + // stream = irodsAccessObjectFactory + // .getIRODSFileFactory(irodsAccount) + // .instanceIRODSFileInputStream(irodsFile); + // + // } catch (Exception e) { + // throw new ServiceFailure(e.getMessage(), e.toString()); + // } finally { + // irodsAccessObjectFactory.closeSessionAndEatExceptions(); + // + // } + + return stream; + } + + @Override + public InputStream get(final Session arg0, final Identifier arg1) + throws InvalidToken, NotAuthorized, NotImplemented, ServiceFailure, NotFound, InsufficientResources { + throw new NotImplemented("1001", "this service has not been implemented"); + } + + @Override + public Checksum getChecksum(final Identifier id, final String algorithm) + throws InvalidRequest, InvalidToken, NotAuthorized, NotImplemented, ServiceFailure, NotFound { + + if (id == null || id.getValue().isEmpty()) { + throw new NotFound("1420", "invalid iRODS data object id"); + } + + if (algorithm == null || algorithm.isEmpty()) { + throw new NotFound("1420", "invalid checksum algorithm provided"); + } + + Checksum checksum = new Checksum(); + + DataObject dataObject; + String path; + IRODSAccount irodsAccount; + IRODSFile irodsFile; + // first try and find data object for this id + try { + irodsAccount = RestAuthUtils.getIRODSAccountFromBasicAuthValues(publicationContext.getRestConfiguration()); + + UniqueIdAO pidService = pluginDiscoveryService.instanceUniqueIdService(irodsAccount); + dataObject = pidService.getDataObjectFromIdentifier(id); + + path = dataObject.getAbsolutePath(); + irodsFile = publicationContext.getIrodsAccessObjectFactory().getIRODSFileFactory(irodsAccount) + .instanceIRODSFile(path); + + if (!irodsFile.exists()) { + log.info("file does not exist"); + throw new NotFound("1020", "No data object could be found for given PID:" + id.getValue()); + } + + } catch (Exception ex) { + log.info("file does not exist"); + throw new NotFound("1020", "No data object could be found for given PID:" + id.getValue()); + } + + String csum = dataObject.getChecksum(); + if (csum == null) { + log.info("checksum does not exist for file: {}", dataObject.getAbsolutePath()); + throw new NotFound("1410", "Checksum does not exist for data object id provided"); + } + checksum.setValue(csum); + checksum.setAlgorithm(properties.getProperty("irods.dataone.chksum-algorithm")); + + return checksum; + } + + @Override + public Checksum getChecksum(final Session arg0, final Identifier arg1, final String arg2) + throws InvalidRequest, InvalidToken, NotAuthorized, NotImplemented, ServiceFailure, NotFound { + throw new NotImplemented("1401", "this service has not been implemented"); + } + + @Override + public InputStream getReplica(final Identifier arg0) + throws InvalidToken, NotAuthorized, NotImplemented, ServiceFailure, NotFound, InsufficientResources { + // This is implemented in streamObject + return null; + } + + @Override + public InputStream getReplica(final Session arg0, final Identifier arg1) + throws InvalidToken, NotAuthorized, NotImplemented, ServiceFailure, NotFound, InsufficientResources { + throw new NotImplemented("2180", "this service has not been implemented"); + } + + @Override + public SystemMetadata getSystemMetadata(final Identifier id) + throws InvalidToken, NotAuthorized, NotImplemented, ServiceFailure, NotFound { + if (id == null || id.getValue().isEmpty()) { + throw new InvalidToken("1402", "invalid iRODS data object id"); + } + + SystemMetadata metadata = new SystemMetadata(); + // TODO: hardcode version to 1 for now + metadata.setSerialVersion(getSerialVersion()); + + DataObject dataObject; + IRODSAccount irodsAccount; + Checksum checksum = new Checksum(); + + DataOneRepoServiceAO repoService; + + // first try and find data object for this id + try { + irodsAccount = RestAuthUtils.getIRODSAccountFromBasicAuthValues(publicationContext.getRestConfiguration()); + repoService = pluginDiscoveryService.instanceRepoService(irodsAccount); + } catch (Exception ex) { + log.error("{}", ex.toString()); + throw new ServiceFailure("1390", ex.getMessage()); + } + + // first try and find data object for this id + try { + + UniqueIdAO pidService = pluginDiscoveryService.instanceUniqueIdService(irodsAccount); + dataObject = pidService.getDataObjectFromIdentifier(id); + + } catch (Exception ex) { + log.info("file does not exist"); + throw new NotFound("1060", "No metadata could be found for given PID:" + id.getValue()); + } + + try { + String csum = dataObject.getChecksum(); + if (csum == null) { + log.info("checksum does not exist for file: {}", dataObject.getAbsolutePath()); // throw + // new + // NotFound("404", + // "1420"); + } else { + checksum.setValue(csum); + checksum.setAlgorithm(properties.getProperty("irods.dataone.chksum-algorithm")); + } + + String format = repoService.dataObjectFormat(dataObject); + + metadata.setIdentifier(id); + ObjectFormatIdentifier formatId = new ObjectFormatIdentifier(); + formatId.setValue(format); + metadata.setFormatId(formatId); + + Long dataSizeLong = new Long(dataObject.getDataSize()); + String dataSizeStr = dataSizeLong.toString(); + metadata.setSize(new BigInteger(dataSizeStr)); + metadata.setChecksum(checksum); + + String dataOwner = "uid=" + dataObject.getDataOwnerName(); + Subject submitter = new Subject(); + submitter.setValue(dataOwner); + metadata.setSubmitter(submitter); + + Subject rightsHolder = new Subject(); + rightsHolder.setValue(dataOwner); + metadata.setRightsHolder(rightsHolder); + + DataObjectAO dataObjectAO = publicationContext.getIrodsAccessObjectFactory().getDataObjectAO(irodsAccount); + List permissions = dataObjectAO + .listPermissionsForDataObject(dataObject.getAbsolutePath()); + if (permissions != null) { + AccessPolicy accessPolicy = new AccessPolicy(); + for (UserFilePermission permission : permissions) { + AccessRule rule = new AccessRule(); + Subject subject = new Subject(); + + // in DataONE - anonymous translates to public + // TODO: also may need to make translation for "public" to + // "authenticatedUser" + if (permission.getUserName().equals("anonymous")) { + subject.setValue("public"); + } else { + subject.setValue("uid=" + permission.getUserName()); + } + rule.addSubject(subject); + List d1Premissions = getD1Permission(permission); + for (Permission d1Premission : d1Premissions) { + rule.addPermission(d1Premission); + } + accessPolicy.addAllow(rule); + } + metadata.setAccessPolicy(accessPolicy); + } + + ReplicationPolicy replicationPolicy = new ReplicationPolicy(); + replicationPolicy.setReplicationAllowed(false); + metadata.setReplicationPolicy(replicationPolicy); + + // Add support for obsoletes or obsoletedBy? + + // Use AVU epoch date // + metadata.setDateUploaded(dataObject.getCreatedAt()); // + metadata.setDateSysMetadataModified(dataObject.getUpdatedAt()); + Date startDate = repoService.getLastModifiedDateForDataObject(dataObject); + metadata.setDateSysMetadataModified(startDate); + metadata.setDateUploaded(startDate); + + NodeReference nodeReference = new NodeReference(); + nodeReference.setValue(properties.getProperty("irods.dataone.identifier")); + metadata.setOriginMemberNode(nodeReference); + metadata.setAuthoritativeMemberNode(nodeReference); + + } catch (Exception e) { + log.error("Cannot access iRODS object: {}", dataObject.getAbsolutePath()); + throw new ServiceFailure("1090", e.getMessage()); + } + + // first try and find data object for this id + + return metadata; + } + + @Override + public SystemMetadata getSystemMetadata(final Session arg0, final Identifier arg1) + throws InvalidToken, NotAuthorized, NotImplemented, ServiceFailure, NotFound { + throw new NotImplemented("1041", "this service has not been implemented"); + } + + @Override + public ObjectList listObjects(final Date fromDate, final Date toDate, final ObjectFormatIdentifier formatId, + final Boolean replicaStatus, final Integer start, final Integer count) + throws InvalidRequest, InvalidToken, NotAuthorized, NotImplemented, ServiceFailure { + + IRODSAccount irodsAccount; + DataObjectListResponse response = new DataObjectListResponse(); + List objectInfoList = new ArrayList<>(); + ObjectList objectList = new ObjectList(); + DataOneRepoServiceAO repoService; + + // first try and find data object for this id + try { + irodsAccount = RestAuthUtils.getIRODSAccountFromBasicAuthValues(publicationContext.getRestConfiguration()); + + repoService = pluginDiscoveryService.instanceRepoService(irodsAccount); + response = repoService.getListOfDataoneExposedDataObjects(fromDate, toDate, formatId, replicaStatus, start, + count); + } catch (Exception ex) { + log.error("{}", ex.toString()); + throw new ServiceFailure("1580", "Could not retrieve list of data objects"); + } + + List dataObjects = response.getDataObjects(); + + for (DataObject dObject : dataObjects) { + + ObjectInfo oInfo = new ObjectInfo(); + + if (dObject.getChecksum() != null) { + Checksum checksum = new Checksum(); + checksum.setValue(dObject.getChecksum()); + checksum.setAlgorithm(properties.getProperty("irods.dataone.chksum-algorithm")); + oInfo.setChecksum(checksum); + } + + String format = null; + try { + format = repoService.dataObjectFormat(dObject); + + } catch (Exception e1) { + log.error(e1.toString()); + log.error("cannot retrieve mime type for object:{} setting to application/octet-stream", + dObject.getAbsolutePath()); + format = "application/octet-stream"; + } + + ObjectFormatIdentifier fId = new ObjectFormatIdentifier(); + fId.setValue(format); + oInfo.setFormatId(fId); + + Date startDate = new Date(); + try { + startDate = repoService.getLastModifiedDateForDataObject(dObject); + } catch (Exception e1) { + log.error(e1.toString()); + log.error("cannot retrieve start date for object: {}", dObject.getAbsolutePath()); + } + oInfo.setDateSysMetadataModified(startDate); + + Identifier id; + try { + UniqueIdAO pidService = pluginDiscoveryService.instanceUniqueIdService(irodsAccount); + id = pidService.getIdentifierFromDataObject(dObject); + } catch (JargonException | PluginNotFoundException e) { + log.error("could not convert data object id to identifier: {}", e.toString()); + throw new ServiceFailure("1580", "Could not retrieve list of data objects"); + } + oInfo.setIdentifier(id); + + Long dataSizeLong = new Long(dObject.getDataSize()); + String dataSizeStr = dataSizeLong.toString(); + oInfo.setSize(new BigInteger(dataSizeStr)); + objectInfoList.add(oInfo); + + } + + objectList.setObjectInfoList(objectInfoList); + objectList.setTotal(response.getTotal()); + objectList.setCount(objectInfoList.size()); + objectList.setStart(start); + + return objectList; + + } + + @Override + public ObjectList listObjects(final Session arg0, final Date arg1, final Date arg2, + final ObjectFormatIdentifier arg3, final Boolean arg4, final Integer arg5, final Integer arg6) + throws InvalidRequest, InvalidToken, NotAuthorized, NotImplemented, ServiceFailure { + throw new NotImplemented("1521", "this service has not been implemented"); + } + + @Override + public boolean synchronizationFailed(final SynchronizationFailed syncFailed) + throws InvalidToken, NotAuthorized, NotImplemented, ServiceFailure { + + Identifier pid = null; + IRODSAccount irodsAccount; + DataObject dataObject; + + if (syncFailed.getPid() != null) { + pid = new Identifier(); + pid.setValue(syncFailed.getPid()); + } else { + throw new ServiceFailure("2161", "The identifier cannot be null."); + } + + try { + irodsAccount = RestAuthUtils.getIRODSAccountFromBasicAuthValues(publicationContext.getRestConfiguration()); + + UniqueIdAO pidService = pluginDiscoveryService.instanceUniqueIdService(irodsAccount); + dataObject = pidService.getDataObjectFromIdentifier(pid); + + } catch (Exception ex) { + throw new ServiceFailure("2161", + "The identifier specified by " + syncFailed.getPid() + " was not found on this node."); + } + + try { + DataOneEventServiceAO eventServiceAO = pluginDiscoveryService.instanceEventService(irodsAccount); + eventServiceAO.recordEvent(Event.SYNCHRONIZATION_FAILED, pid, syncFailed.getDescription()); + + } catch (PluginNotFoundException | JargonException e) { + log.error("failed to log synchronization failed event: {}", e.toString()); + throw new ServiceFailure("2161", "Failed to log Synchronization Failure event"); + } + + return true; + } + + @Override + public boolean synchronizationFailed(final Session arg0, final SynchronizationFailed arg1) + throws InvalidToken, NotAuthorized, NotImplemented, ServiceFailure { + throw new NotImplemented("2160", "this service has not been implemented"); + } + + // need to return every DataONE permission implied by iRODS permissions i.e. + // write would require read and write to be listed as DataONE permissions + // and + // own would include read, write, and changePermission + private List getD1Permission(final UserFilePermission p) { + List permissions = new ArrayList<>(); + FilePermissionEnum fpEnum = p.getFilePermissionEnum(); + switch (fpEnum) { + case READ: + permissions.add(MNPermissionEnum.valueForDataOne(fpEnum)); + break; + + case WRITE: + permissions.add(Permission.READ); + permissions.add(MNPermissionEnum.valueForDataOne(fpEnum)); + break; + + case OWN: + permissions.add(Permission.READ); + permissions.add(Permission.WRITE); + permissions.add(MNPermissionEnum.valueForDataOne(fpEnum)); + break; + default: + permissions.add(MNPermissionEnum.valueForDataOne(fpEnum)); + break; + } + return permissions; + } + + private BigInteger getSerialVersion() { + // TODO: hardcode version to 1 for now + Long verLong = new Long(1); + String verStr = verLong.toString(); + return new BigInteger(verStr); + } + +} diff --git a/src/main/java/org/irods/jargon/dataone/tier1/package-info.java b/dataone-node/src/main/java/org/irods/jargon/dataone/tier1/package-info.java similarity index 97% rename from src/main/java/org/irods/jargon/dataone/tier1/package-info.java rename to dataone-node/src/main/java/org/irods/jargon/dataone/tier1/package-info.java index 91bf3d0..fe87484 100644 --- a/src/main/java/org/irods/jargon/dataone/tier1/package-info.java +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/tier1/package-info.java @@ -1,6 +1,6 @@ /** * Implementation of the DataONE REST API - * + * * @author Lisa Stillwell - RENCI - UNC, Chapel Hill (www.renci.org) * */ diff --git a/dataone-node/src/main/java/org/irods/jargon/dataone/utils/DataOneTestHelper.java b/dataone-node/src/main/java/org/irods/jargon/dataone/utils/DataOneTestHelper.java new file mode 100644 index 0000000..10a5500 --- /dev/null +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/utils/DataOneTestHelper.java @@ -0,0 +1,96 @@ +package org.irods.jargon.dataone.utils; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import org.irods.jargon.testutils.TestingUtilsException; + +/** + * Utilities to load testing properties from a properties file + * + * @author Mike Conway, DICE (www.irods.org) + * @since 10/18/2009 + */ +public class DataOneTestHelper { + + public static final String JAR_DIRECTORY_PROP = "plugin.jar.location"; + + public String getPluginJarLocation(final Properties testingProperties) { + return testingProperties.getProperty(JAR_DIRECTORY_PROP); + } + + /** + * Return the given property (by key) as an int + * + * @param testingProperties + * @param key + * @return + * @throws TestingUtilsException + */ + public int getPropertyValueAsInt(final Properties testingProperties, + final String key) throws TestingUtilsException { + String propVal = (String) testingProperties.get(key); + + if (propVal == null || propVal.length() == 0) { + throw new TestingUtilsException( + "missing or invalid value in test-dataone.properties"); + } + + int retVal = 0; + + try { + retVal = Integer.parseInt(propVal); + } catch (NumberFormatException nfe) { + throw new TestingUtilsException( + "port is in valid format to convert to int:" + propVal, nfe); + } + + return retVal; + } + + /** + * Load the properties that control various tests from the + * testing.properties file on the code path + * + * @return Properties class with the test values + * @throws TestingUtilsException + */ + public Properties getTestProperties() throws TestingUtilsException { + ClassLoader loader = this.getClass().getClassLoader(); + InputStream in = loader.getResourceAsStream("test-dataone.properties"); + Properties properties = new Properties(); + + try { + properties.load(in); + } catch (IOException ioe) { + throw new TestingUtilsException( + "error loading test-dataone properties", ioe); + } finally { + try { + in.close(); + } catch (Exception e) { + // ignore + } + } + return properties; + } + + /** + * Get the given property as a boolean + * + * @param testingProperties + * @param key + * @return + */ + public boolean getPropertyValueAsBoolean( + final Properties testingProperties, final String key) { + String val = (String) testingProperties.get(key); + if (val == null) { + return false; + } else { + return Boolean.parseBoolean(val); + } + } + +} diff --git a/dataone-node/src/main/java/org/irods/jargon/dataone/utils/RestVersion.java b/dataone-node/src/main/java/org/irods/jargon/dataone/utils/RestVersion.java new file mode 100644 index 0000000..8bc9c19 --- /dev/null +++ b/dataone-node/src/main/java/org/irods/jargon/dataone/utils/RestVersion.java @@ -0,0 +1,5 @@ +package org.irods.jargon.dataone.utils; +public final class RestVersion { + public static String VERSION="4.2.1.0-SNAPSHOT"; + public static String BUILD_TIME="2017-06-21T15:40:13Z"; +} diff --git a/src/main/lib/cnriutil.jar b/dataone-node/src/main/lib/cnriutil.jar similarity index 100% rename from src/main/lib/cnriutil.jar rename to dataone-node/src/main/lib/cnriutil.jar diff --git a/src/main/lib/handle.jar b/dataone-node/src/main/lib/handle.jar similarity index 100% rename from src/main/lib/handle.jar rename to dataone-node/src/main/lib/handle.jar diff --git a/src/main/resources/config.xml b/dataone-node/src/main/resources/config.xml similarity index 100% rename from src/main/resources/config.xml rename to dataone-node/src/main/resources/config.xml diff --git a/dataone-node/src/main/resources/jargon-beans.xml b/dataone-node/src/main/resources/jargon-beans.xml new file mode 100644 index 0000000..3199b98 --- /dev/null +++ b/dataone-node/src/main/resources/jargon-beans.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/log4j.properties b/dataone-node/src/main/resources/log4j.properties similarity index 92% rename from src/main/resources/log4j.properties rename to dataone-node/src/main/resources/log4j.properties index 251c3d8..e62d7b6 100644 --- a/src/main/resources/log4j.properties +++ b/dataone-node/src/main/resources/log4j.properties @@ -1,6 +1,6 @@ # Set root logger level to DEBUG and its only appender to A1. # log4j.rootLogger=INFO, A1 -log4j.rootLogger=WARN, A1 +log4j.rootLogger=INFO, A1 # A1 is set to be a ConsoleAppender. log4j.appender.A1=org.apache.log4j.ConsoleAppender diff --git a/src/main/webapp/WEB-INF/rest-servlet.xml b/dataone-node/src/main/webapp/WEB-INF/rest-servlet.xml similarity index 91% rename from src/main/webapp/WEB-INF/rest-servlet.xml rename to dataone-node/src/main/webapp/WEB-INF/rest-servlet.xml index 3b31aeb..95aa61b 100644 --- a/src/main/webapp/WEB-INF/rest-servlet.xml +++ b/dataone-node/src/main/webapp/WEB-INF/rest-servlet.xml @@ -11,6 +11,7 @@ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"> + diff --git a/src/main/webapp/WEB-INF/web.xml b/dataone-node/src/main/webapp/WEB-INF/web.xml similarity index 100% rename from src/main/webapp/WEB-INF/web.xml rename to dataone-node/src/main/webapp/WEB-INF/web.xml diff --git a/src/main/webapp/accessDenied.htm b/dataone-node/src/main/webapp/accessDenied.htm similarity index 100% rename from src/main/webapp/accessDenied.htm rename to dataone-node/src/main/webapp/accessDenied.htm diff --git a/src/main/webapp/index.html b/dataone-node/src/main/webapp/index.html similarity index 100% rename from src/main/webapp/index.html rename to dataone-node/src/main/webapp/index.html diff --git a/dataone-node/src/test/java/org/irods/jargon/dataone/configuration/PluginDiscoveryServiceTest.java b/dataone-node/src/test/java/org/irods/jargon/dataone/configuration/PluginDiscoveryServiceTest.java new file mode 100644 index 0000000..5e782d4 --- /dev/null +++ b/dataone-node/src/test/java/org/irods/jargon/dataone/configuration/PluginDiscoveryServiceTest.java @@ -0,0 +1,80 @@ +package org.irods.jargon.dataone.configuration; + +import java.io.File; + +import org.irods.jargon.core.connection.IRODSAccount; +import org.irods.jargon.core.utils.LocalFileUtils; +import org.irods.jargon.dataone.events.DataOneEventServiceAO; +import org.irods.jargon.dataone.reposervice.DataOneRepoServiceAO; +import org.irods.jargon.pid.pidservice.UniqueIdAO; +import org.junit.Assert; +import org.junit.Test; + +public class PluginDiscoveryServiceTest { + + @Test + public void testInit() throws Exception { + PublicationContext publicationContext = new PublicationContext(); + File rescFile = LocalFileUtils.getClasspathResourceAsFile("/dummyjars"); + Assert.assertNotNull("no file path", rescFile); + RestConfiguration restConfiguration = new RestConfiguration(); + restConfiguration.setPluginJarLocation(rescFile.getAbsolutePath()); + publicationContext.setRestConfiguration(restConfiguration); + PluginDiscoveryService pluginDiscoveryService = new PluginDiscoveryService(); + pluginDiscoveryService.setPublicationContext(publicationContext); + pluginDiscoveryService.init(); + Assert.assertNotNull("no pid factory", pluginDiscoveryService.getDataOnePidServiceFactory()); + Assert.assertNotNull("no event factory", pluginDiscoveryService.getDataOneEventServiceFactory()); + Assert.assertNotNull("no repo factory", pluginDiscoveryService.getDataOneRepoServiceFactory()); + + } + + @Test + public void testInstanceEventService() throws Exception { + IRODSAccount dummyAccount = new IRODSAccount("xxx", 1247, "xxx", "xxx", "xxx", "xxx", "xxx"); + PublicationContext publicationContext = new PublicationContext(); + File rescFile = new File("/home/mcc/d1plugin"); + Assert.assertNotNull("no file path", rescFile); + RestConfiguration restConfiguration = new RestConfiguration(); + restConfiguration.setPluginJarLocation(rescFile.getAbsolutePath()); + publicationContext.setRestConfiguration(restConfiguration); + PluginDiscoveryService pluginDiscoveryService = new PluginDiscoveryService(); + pluginDiscoveryService.setPublicationContext(publicationContext); + pluginDiscoveryService.init(); + DataOneEventServiceAO actual = pluginDiscoveryService.instanceEventService(dummyAccount); + Assert.assertNotNull("no impl created", actual); + } + + @Test + public void testInstanceUniqueIdService() throws Exception { + IRODSAccount dummyAccount = new IRODSAccount("xxx", 1247, "xxx", "xxx", "xxx", "xxx", "xxx"); + PublicationContext publicationContext = new PublicationContext(); + File rescFile = new File("/home/mcc/d1plugin"); + Assert.assertNotNull("no file path", rescFile); + RestConfiguration restConfiguration = new RestConfiguration(); + restConfiguration.setPluginJarLocation(rescFile.getAbsolutePath()); + publicationContext.setRestConfiguration(restConfiguration); + PluginDiscoveryService pluginDiscoveryService = new PluginDiscoveryService(); + pluginDiscoveryService.setPublicationContext(publicationContext); + pluginDiscoveryService.init(); + UniqueIdAO actual = pluginDiscoveryService.instanceUniqueIdService(dummyAccount); + Assert.assertNotNull("no impl created", actual); + } + + @Test + public void testInstanceRepoService() throws Exception { + IRODSAccount dummyAccount = new IRODSAccount("xxx", 1247, "xxx", "xxx", "xxx", "xxx", "xxx"); + PublicationContext publicationContext = new PublicationContext(); + File rescFile = new File("/home/mcc/d1plugin"); + Assert.assertNotNull("no file path", rescFile); + RestConfiguration restConfiguration = new RestConfiguration(); + restConfiguration.setPluginJarLocation(rescFile.getAbsolutePath()); + publicationContext.setRestConfiguration(restConfiguration); + PluginDiscoveryService pluginDiscoveryService = new PluginDiscoveryService(); + pluginDiscoveryService.setPublicationContext(publicationContext); + pluginDiscoveryService.init(); + DataOneRepoServiceAO actual = pluginDiscoveryService.instanceRepoService(dummyAccount); + Assert.assertNotNull("no impl created", actual); + } + +} diff --git a/src/test/java/org/irods/jargon/rest/service/package-info.java b/dataone-node/src/test/java/org/irods/jargon/rest/service/package-info.java similarity index 98% rename from src/test/java/org/irods/jargon/rest/service/package-info.java rename to dataone-node/src/test/java/org/irods/jargon/rest/service/package-info.java index 4d62544..6034811 100644 --- a/src/test/java/org/irods/jargon/rest/service/package-info.java +++ b/dataone-node/src/test/java/org/irods/jargon/rest/service/package-info.java @@ -1,6 +1,6 @@ /** * Various services used by the REST command classes, providing things like persistance, environmental and contextual info - * + * * @author Mike Conway - DICE (www.irods.org) * */ diff --git a/dataone-node/src/test/resources/dummyjars/dummy-event-service-impl-4.2.1.0-SNAPSHOT.jar b/dataone-node/src/test/resources/dummyjars/dummy-event-service-impl-4.2.1.0-SNAPSHOT.jar new file mode 100644 index 0000000..82092ee Binary files /dev/null and b/dataone-node/src/test/resources/dummyjars/dummy-event-service-impl-4.2.1.0-SNAPSHOT.jar differ diff --git a/dataone-node/src/test/resources/dummyjars/dummy-pid-service-impl-4.2.1.0-SNAPSHOT.jar b/dataone-node/src/test/resources/dummyjars/dummy-pid-service-impl-4.2.1.0-SNAPSHOT.jar new file mode 100644 index 0000000..3fe6171 Binary files /dev/null and b/dataone-node/src/test/resources/dummyjars/dummy-pid-service-impl-4.2.1.0-SNAPSHOT.jar differ diff --git a/dataone-node/src/test/resources/dummyjars/dummy-repo-service-impl-4.2.1.0-SNAPSHOT.jar b/dataone-node/src/test/resources/dummyjars/dummy-repo-service-impl-4.2.1.0-SNAPSHOT.jar new file mode 100644 index 0000000..6e124a3 Binary files /dev/null and b/dataone-node/src/test/resources/dummyjars/dummy-repo-service-impl-4.2.1.0-SNAPSHOT.jar differ diff --git a/dataone-node/src/test/resources/log4j.properties b/dataone-node/src/test/resources/log4j.properties new file mode 100644 index 0000000..0228b8f --- /dev/null +++ b/dataone-node/src/test/resources/log4j.properties @@ -0,0 +1,9 @@ +# Set root logger level and appender +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 diff --git a/src/test/resources/rest-servlet.xml b/dataone-node/src/test/resources/rest-servlet.xml similarity index 92% rename from src/test/resources/rest-servlet.xml rename to dataone-node/src/test/resources/rest-servlet.xml index 040c833..5dd5b3e 100644 --- a/src/test/resources/rest-servlet.xml +++ b/dataone-node/src/test/resources/rest-servlet.xml @@ -9,6 +9,7 @@ + diff --git a/dataone-node/src/test/resources/test-dataone.properties b/dataone-node/src/test/resources/test-dataone.properties new file mode 100644 index 0000000..afa00d0 --- /dev/null +++ b/dataone-node/src/test/resources/test-dataone.properties @@ -0,0 +1,7 @@ +irods.user=test1 + irods.password=test + irods.resource=test1-resc + irods.host=irods420.irodslocal + irods.port=1247 + irods.zone=zone1 + plugin.jar.location=/home/mconway/temp/dataonejar \ No newline at end of file diff --git a/test-certs/notes.txt b/dataone-node/test-certs/notes.txt similarity index 100% rename from test-certs/notes.txt rename to dataone-node/test-certs/notes.txt diff --git a/dataone-utils/pom.xml b/dataone-utils/pom.xml new file mode 100644 index 0000000..bcbd98a --- /dev/null +++ b/dataone-utils/pom.xml @@ -0,0 +1,77 @@ + + + 4.0.0 + dataone-utils + + org.irods + dfc-dataone + 4.2.1.0-SNAPSHOT + + jar + DataONE utilities + + + org.irods.jargon + jargon-core + ${project.version} + + + + junit + junit + test + + + org.slf4j + slf4j-api + + + log4j + log4j + + + org.mockito + mockito-all + + + org.apache.tika + tika-core + + + org.springframework + spring-core + + + org.springframework + spring-expression + + + org.springframework + spring-aop + + + org.springframework + spring-webmvc + + + org.springframework + spring-context + + + org.springframework + spring-beans + + + org.xeustechnologies + jcl-core + + + org.reflections + reflections + + + + + diff --git a/dataone-utils/src/main/java/org/irods/jargon/dataone/configuration/PluginNotFoundException.java b/dataone-utils/src/main/java/org/irods/jargon/dataone/configuration/PluginNotFoundException.java new file mode 100644 index 0000000..d5ea4ae --- /dev/null +++ b/dataone-utils/src/main/java/org/irods/jargon/dataone/configuration/PluginNotFoundException.java @@ -0,0 +1,24 @@ +/** + * + */ +package org.irods.jargon.dataone.configuration; + +/** + * Warns of a missing plugin of a given type + * + * @author mconway + * + */ +public class PluginNotFoundException extends Exception { + + private static final long serialVersionUID = 2365990131845450987L; + + public PluginNotFoundException(String string) { + super(string); + } + + public PluginNotFoundException(Exception e) { + super(e); + } + +} diff --git a/dataone-utils/src/main/java/org/irods/jargon/dataone/configuration/PluginRuntimeException.java b/dataone-utils/src/main/java/org/irods/jargon/dataone/configuration/PluginRuntimeException.java new file mode 100644 index 0000000..2f61abb --- /dev/null +++ b/dataone-utils/src/main/java/org/irods/jargon/dataone/configuration/PluginRuntimeException.java @@ -0,0 +1,56 @@ +/** + * + */ +package org.irods.jargon.dataone.configuration; + +/** + * @author mconway + * + */ +public class PluginRuntimeException extends RuntimeException { + + /** + * + */ + private static final long serialVersionUID = 1878244280920075564L; + + /** + * + */ + public PluginRuntimeException() { + } + + /** + * @param arg0 + */ + public PluginRuntimeException(String arg0) { + super(arg0); + } + + /** + * @param arg0 + */ + public PluginRuntimeException(Throwable arg0) { + super(arg0); + } + + /** + * @param arg0 + * @param arg1 + */ + public PluginRuntimeException(String arg0, Throwable arg1) { + super(arg0, arg1); + } + + /** + * @param arg0 + * @param arg1 + * @param arg2 + * @param arg3 + */ + public PluginRuntimeException(String arg0, Throwable arg1, boolean arg2, + boolean arg3) { + super(arg0, arg1, arg2, arg3); + } + +} diff --git a/dataone-utils/src/main/java/org/irods/jargon/dataone/configuration/PublicationContext.java b/dataone-utils/src/main/java/org/irods/jargon/dataone/configuration/PublicationContext.java new file mode 100644 index 0000000..e8fea4a --- /dev/null +++ b/dataone-utils/src/main/java/org/irods/jargon/dataone/configuration/PublicationContext.java @@ -0,0 +1,88 @@ +/** + * + */ +package org.irods.jargon.dataone.configuration; + +import java.util.Properties; + +import javax.annotation.PostConstruct; + +import org.irods.jargon.core.pub.IRODSAccessObjectFactory; +import org.irods.jargon.dataone.utils.PropertiesLoader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * Sharable context elements between components of the DataONE service + * + * @author mconway + * + */ +@Component +public class PublicationContext { + @Autowired + private IRODSAccessObjectFactory irodsAccessObjectFactory; + + @Autowired + private RestConfiguration restConfiguration; + + private Properties additionalProperties; + + public static final Logger log = LoggerFactory.getLogger(PublicationContext.class); + + @PostConstruct + public void init() { + log.info("init()"); + PropertiesLoader loader = new PropertiesLoader(); + additionalProperties = loader.getProperties(); + log.info("etc properties loaded successfully"); + } + + /** + * @return the irodsAccessObjectFactory + */ + public IRODSAccessObjectFactory getIrodsAccessObjectFactory() { + return irodsAccessObjectFactory; + } + + /** + * @param irodsAccessObjectFactory + * the irodsAccessObjectFactory to set + */ + public void setIrodsAccessObjectFactory(IRODSAccessObjectFactory irodsAccessObjectFactory) { + this.irodsAccessObjectFactory = irodsAccessObjectFactory; + } + + /** + * @return the restConfiguration + */ + public RestConfiguration getRestConfiguration() { + return restConfiguration; + } + + /** + * @param restConfiguration + * the restConfiguration to set + */ + public void setRestConfiguration(RestConfiguration restConfiguration) { + this.restConfiguration = restConfiguration; + } + + /** + * @return the additionalProperties + */ + public Properties getAdditionalProperties() { + return additionalProperties; + } + + /** + * @param additionalProperties + * the additionalProperties to set + */ + public void setAdditionalProperties(Properties additionalProperties) { + this.additionalProperties = additionalProperties; + } + +} diff --git a/src/main/java/org/irods/jargon/dataone/configuration/RestConfiguration.java b/dataone-utils/src/main/java/org/irods/jargon/dataone/configuration/RestConfiguration.java similarity index 54% rename from src/main/java/org/irods/jargon/dataone/configuration/RestConfiguration.java rename to dataone-utils/src/main/java/org/irods/jargon/dataone/configuration/RestConfiguration.java index b448572..ad43d2d 100644 --- a/src/main/java/org/irods/jargon/dataone/configuration/RestConfiguration.java +++ b/dataone-utils/src/main/java/org/irods/jargon/dataone/configuration/RestConfiguration.java @@ -2,15 +2,15 @@ /** * Pojo containing configuration information - * + * * @author Mike Conway - DICE (www.irods.org) - * + * */ public class RestConfiguration { - private String irodsHost = "iren2.renci.org"; + private String irodsHost = ""; private int irodsPort = 1247; - private String irodsZone = "dfcmain"; + private String irodsZone = ""; private String defaultStorageResource = ""; private String realm = "dfc-dataone"; private boolean smimeEncryptAdminFunctions = false; @@ -18,8 +18,8 @@ public class RestConfiguration { private String publicKeyAbsPath = ""; private String irodsUserName; private String irodsUserPswd; - - private String handlePrefix = "11333/"; + private String pluginJarLocation; + private String authType = ""; /** * Optional URL for a web interface to access grid data (typically an @@ -113,7 +113,7 @@ public boolean isSmimeEncryptAdminFunctions() { * @param smimeEncryptAdminFunctions * the smimeEncryptAdminFunctions to set */ - public void setSmimeEncryptAdminFunctions(boolean smimeEncryptAdminFunctions) { + public void setSmimeEncryptAdminFunctions(final boolean smimeEncryptAdminFunctions) { this.smimeEncryptAdminFunctions = smimeEncryptAdminFunctions; } @@ -128,7 +128,7 @@ public String getPrivateCertAbsPath() { * @param privateCertAbsPath * the privateCertAbsPath to set */ - public void setPrivateCertAbsPath(String privateCertAbsPath) { + public void setPrivateCertAbsPath(final String privateCertAbsPath) { this.privateCertAbsPath = privateCertAbsPath; } @@ -143,7 +143,7 @@ public String getPublicKeyAbsPath() { * @param publicKeyAbsPath * the publicKeyAbsPath to set */ - public void setPublicKeyAbsPath(String publicKeyAbsPath) { + public void setPublicKeyAbsPath(final String publicKeyAbsPath) { this.publicKeyAbsPath = publicKeyAbsPath; } @@ -151,7 +151,7 @@ public String getWebInterfaceURL() { return webInterfaceURL; } - public void setWebInterfaceURL(String webInterfaceURL) { + public void setWebInterfaceURL(final String webInterfaceURL) { this.webInterfaceURL = webInterfaceURL; } @@ -159,7 +159,7 @@ public String getIrodsUserName() { return irodsUserName; } - public void setIrodsUserName(String irodsUserName) { + public void setIrodsUserName(final String irodsUserName) { this.irodsUserName = irodsUserName; } @@ -167,10 +167,83 @@ public String getIrodsUserPswd() { return irodsUserPswd; } - public void setIrodsUserPswd(String irodsUserPswd) { + public void setIrodsUserPswd(final String irodsUserPswd) { this.irodsUserPswd = irodsUserPswd; } - -} + /** + * @return the pluginJarLocation + */ + public String getPluginJarLocation() { + return pluginJarLocation; + } + + /** + * @param pluginJarLocation + * the pluginJarLocation to set + */ + public void setPluginJarLocation(String pluginJarLocation) { + this.pluginJarLocation = pluginJarLocation; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("RestConfiguration ["); + if (irodsHost != null) { + builder.append("irodsHost=").append(irodsHost).append(", "); + } + builder.append("irodsPort=").append(irodsPort).append(", "); + if (irodsZone != null) { + builder.append("irodsZone=").append(irodsZone).append(", "); + } + if (defaultStorageResource != null) { + builder.append("defaultStorageResource=").append(defaultStorageResource).append(", "); + } + if (realm != null) { + builder.append("realm=").append(realm).append(", "); + } + builder.append("smimeEncryptAdminFunctions=").append(smimeEncryptAdminFunctions).append(", "); + if (privateCertAbsPath != null) { + builder.append("privateCertAbsPath=").append(privateCertAbsPath).append(", "); + } + if (publicKeyAbsPath != null) { + builder.append("publicKeyAbsPath=").append(publicKeyAbsPath).append(", "); + } + if (irodsUserName != null) { + builder.append("irodsUserName=").append(irodsUserName).append(", "); + } + if (irodsUserPswd != null) { + builder.append("irodsUserPswd=").append(irodsUserPswd).append(", "); + } + if (pluginJarLocation != null) { + builder.append("pluginJarLocation=").append(pluginJarLocation).append(", "); + } + if (webInterfaceURL != null) { + builder.append("webInterfaceURL=").append(webInterfaceURL); + } + builder.append("]"); + return builder.toString(); + } + + /** + * @return the authType + */ + public String getAuthType() { + return authType; + } + /** + * @param authType + * the authType to set + */ + public void setAuthType(String authType) { + this.authType = authType; + } + +} diff --git a/dataone-utils/src/main/java/org/irods/jargon/dataone/configuration/package-info.java b/dataone-utils/src/main/java/org/irods/jargon/dataone/configuration/package-info.java new file mode 100644 index 0000000..4d9c60a --- /dev/null +++ b/dataone-utils/src/main/java/org/irods/jargon/dataone/configuration/package-info.java @@ -0,0 +1,7 @@ +/** + * Implementation of the DataONE REST API + * + * @author Lisa Stillwell - RENCI - UNC, Chapel Hill (www.renci.org) + * + */ +package org.irods.jargon.dataone.configuration; \ No newline at end of file diff --git a/dataone-utils/src/main/java/org/irods/jargon/dataone/plugin/AbstractDataOnePlugin.java b/dataone-utils/src/main/java/org/irods/jargon/dataone/plugin/AbstractDataOnePlugin.java new file mode 100644 index 0000000..aef6da7 --- /dev/null +++ b/dataone-utils/src/main/java/org/irods/jargon/dataone/plugin/AbstractDataOnePlugin.java @@ -0,0 +1,45 @@ +package org.irods.jargon.dataone.plugin; + +import org.irods.jargon.core.connection.IRODSAccount; +import org.irods.jargon.dataone.configuration.PublicationContext; + +/** + * + * @author mconway + * + */ +public class AbstractDataOnePlugin { + + private final IRODSAccount irodsAccount; + + /** + * Represents a handle to iRODS connection and general configuration + * information + */ + private final PublicationContext publicationContext; + + /** + * @param irodsAccount + * @param publicationContext + */ + public AbstractDataOnePlugin(IRODSAccount irodsAccount, PublicationContext publicationContext) { + super(); + this.irodsAccount = irodsAccount; + this.publicationContext = publicationContext; + } + + /** + * @return the publicationContext + */ + protected PublicationContext getPublicationContext() { + return publicationContext; + } + + /** + * @return the irodsAccount + */ + public IRODSAccount getIrodsAccount() { + return irodsAccount; + } + +} diff --git a/dataone-utils/src/main/java/org/irods/jargon/dataone/plugin/package-info.java b/dataone-utils/src/main/java/org/irods/jargon/dataone/plugin/package-info.java new file mode 100644 index 0000000..1e69e92 --- /dev/null +++ b/dataone-utils/src/main/java/org/irods/jargon/dataone/plugin/package-info.java @@ -0,0 +1,6 @@ +/** + * Plugin framework for dataone + * @author mconway + * + */ +package org.irods.jargon.dataone.plugin; \ No newline at end of file diff --git a/dataone-utils/src/main/java/org/irods/jargon/dataone/utils/ISO8601.java b/dataone-utils/src/main/java/org/irods/jargon/dataone/utils/ISO8601.java new file mode 100644 index 0000000..1bb1e0a --- /dev/null +++ b/dataone-utils/src/main/java/org/irods/jargon/dataone/utils/ISO8601.java @@ -0,0 +1,109 @@ +package org.irods.jargon.dataone.utils; + +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.TimeZone; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class ISO8601 { + + private Logger logger = LoggerFactory.getLogger(this.getClass()); + + /** Transform Calendar to ISO 8601 string. */ + public static String fromCalendar(final Calendar calendar) { + Date date = calendar.getTime(); + String formatted = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ") + .format(date); + // add ":" to timezone offset, like this 2013-10-10T13:13:23.000-04:00 + return formatted.substring(0, 26) + ":" + formatted.substring(26); + } + + /** Get current date and time formatted as ISO 8601 string. */ + public static String now() { + return fromCalendar(Calendar.getInstance()); + } + + /** Transform ISO 8601 string to Calendar. */ + // have to handle this: 2016-04-12T18:18:00+00:00 + // and this 2016-04-12T18:18:00.000+00:00 + // and this 2016-04-12T18:18:00.001 + // and this 2016-04-12T18:18:00 + // and this 2016-04-12T18:18:00+00:00 + // etc + public static Calendar toCalendar(final String iso8601string) + throws ParseException { + Calendar calendar = Calendar.getInstance(); + String s = iso8601string; + + // add the GMT timezone default, if it is not explicitly specified + if ((!iso8601string.contains("+")) && (!iso8601string.contains("-"))) { + // GMT is default + s = s + "+0000"; + } else { + // need to remove ":" from timezone, if there + int len = s.length(); + if (s.charAt(len - 3) == ':') { + try { + s = s.substring(0, len - 3) + s.substring(len - 2); // to + // get + // rid + // of + // the + // ":" + } catch (IndexOutOfBoundsException e) { + throw new ParseException("Invalid length", 0); + } + } + } + + Date date; + // check for milliseconds extension + if (s.contains(".")) { + date = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ").parse(s); + } else { + date = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").parse(s); + } + + calendar.setTime(date); + return calendar; + } + + public static Date convertToGMT(final Date date) { + Date gmtDate = null; + + DateFormat gmtFormat = new SimpleDateFormat( + "yyyy-MM-dd'T'HH:mm:ss.SSSZ"); + TimeZone gmtTime = TimeZone.getTimeZone("GMT"); + gmtFormat.setTimeZone(gmtTime); + String gmtStr = gmtFormat.format(date); + try { + gmtDate = gmtFormat.parse(gmtStr); + } catch (ParseException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return gmtDate; + } + + public static String convertToGMTString(final Date date) { + + DateFormat gmtFormat = new SimpleDateFormat( + "yyyy-MM-dd'T'HH:mm:ss.SSS+"); + TimeZone gmtTimeZone = TimeZone.getTimeZone("GMT"); + gmtFormat.setTimeZone(gmtTimeZone); + Calendar calendar = new GregorianCalendar(); + calendar.setTime(date); + calendar.setTimeZone(gmtTimeZone); + String dateStr = gmtFormat.format(calendar.getTime()); + dateStr += "00:00"; + + return dateStr; + } +} diff --git a/dataone-utils/src/main/java/org/irods/jargon/dataone/utils/PropertiesLoader.java b/dataone-utils/src/main/java/org/irods/jargon/dataone/utils/PropertiesLoader.java new file mode 100644 index 0000000..8fd8592 --- /dev/null +++ b/dataone-utils/src/main/java/org/irods/jargon/dataone/utils/PropertiesLoader.java @@ -0,0 +1,78 @@ +package org.irods.jargon.dataone.utils; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class PropertiesLoader { + + private Properties properties; + + private String propertiesFilename = "/etc/irods-ext/d1client.properties"; + private Logger log = LoggerFactory.getLogger(this.getClass()); + + public PropertiesLoader() { + + properties = new Properties(); + InputStream input = null; + File propsFile = new File(propertiesFilename); + if (!propsFile.exists()) { + log.error("illegal state exception, cannot find /etc/irods-ext/dlclient.properties"); + throw new IllegalStateException("unable to load properties file at /etc/irods-ext/dlclient.properties"); + } + + try { + input = new FileInputStream(propsFile); + } catch (FileNotFoundException e1) { + log.error("cannot open /etc/irods-ext/dlclient.properties"); + throw new IllegalStateException("unable to stream properties file at /etc/irods-ext/dlclient.properties"); + } + + // input = getClass().getClassLoader().getResourceAsStream( + // propertiesFilename); + + // load a properties file + try { + properties.load(input); + } catch (IOException e) { + log.error("Cannot load Member Node properties file: {}", propertiesFilename); + log.error("IOException: {}", e); + properties = new Properties(); + } finally { + if (input != null) { + try { + input.close(); + } catch (IOException e) { + // do nothing + } + } + } + } + + /** + * Get all available properties + * + * @return {@link Properties} configured in etc + */ + public Properties getProperties() { + return properties; + } + + /** + * Get an individual property from etc by key + * + * @param key + * String with the prop key + * @return String with the property value, or null + */ + public String getProperty(final String key) { + return properties.getProperty(key); + } + +} diff --git a/src/main/java/org/irods/jargon/dataone/utils/RestTestingProperties.java b/dataone-utils/src/main/java/org/irods/jargon/dataone/utils/RestTestingProperties.java similarity index 95% rename from src/main/java/org/irods/jargon/dataone/utils/RestTestingProperties.java rename to dataone-utils/src/main/java/org/irods/jargon/dataone/utils/RestTestingProperties.java index 1b20269..51436f4 100644 --- a/src/main/java/org/irods/jargon/dataone/utils/RestTestingProperties.java +++ b/dataone-utils/src/main/java/org/irods/jargon/dataone/utils/RestTestingProperties.java @@ -1,13 +1,13 @@ /** - * + * */ package org.irods.jargon.dataone.utils; /** * Handy properties used in testing these services - * + * * @author Mike Conway - DICE (www.irods.org) - * + * */ public class RestTestingProperties { public static final String REST_PORT_PROPERTY = "test.rest.port"; diff --git a/src/main/java/org/irods/jargon/dataone/utils/package-info.java b/dataone-utils/src/main/java/org/irods/jargon/dataone/utils/package-info.java similarity index 97% rename from src/main/java/org/irods/jargon/dataone/utils/package-info.java rename to dataone-utils/src/main/java/org/irods/jargon/dataone/utils/package-info.java index 5abd5e2..5484dc5 100644 --- a/src/main/java/org/irods/jargon/dataone/utils/package-info.java +++ b/dataone-utils/src/main/java/org/irods/jargon/dataone/utils/package-info.java @@ -1,6 +1,6 @@ /** * Implementation of the DataONE REST API - * + * * @author Lisa Stillwell - RENCI - UNC, Chapel Hill (www.renci.org) * */ diff --git a/default-event-service/default-event-service-api-impl/pom.xml b/default-event-service/default-event-service-api-impl/pom.xml new file mode 100644 index 0000000..ea26ad0 --- /dev/null +++ b/default-event-service/default-event-service-api-impl/pom.xml @@ -0,0 +1,98 @@ + + + 4.0.0 + default-event-service-api-impl + + org.irods + default-event-service + 4.2.1.0-SNAPSHOT + + jar + Default event service api implementation + + + junit + junit + test + + + org.slf4j + slf4j-api + + + log4j + log4j + + + org.slf4j + slf4j-log4j12 + + + org.irods + dataone-utils + ${project.version} + + + org.irods + event-service-api + ${project.version} + provided + + + org.irods + default-event-service-persist + ${project.version} + + + com.impossibl.pgjdbc-ng + pgjdbc-ng + + + + + + maven-assembly-plugin + 3.0.0 + + + jar-with-dependencies + + + + + make-assembly + package + + single + + + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.0.1 + + + copy-dependencies + package + + copy-dependencies + + + + org.apache.mavens:maven-archiver + org.apache.maven:maven-artifact + org.apache.maven:maven-artifact-manager + org.apache.maven:model + org.apache.maven.plugins:maven-clean-plugin + + + + + + + + + \ No newline at end of file diff --git a/default-event-service/default-event-service-api-impl/src/main/java/.gitinclude b/default-event-service/default-event-service-api-impl/src/main/java/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/default-event-service/default-event-service-api-impl/src/main/java/org/irods/jargon/dataone/events/defdb/DefaultEventServiceAOImpl.java b/default-event-service/default-event-service-api-impl/src/main/java/org/irods/jargon/dataone/events/defdb/DefaultEventServiceAOImpl.java new file mode 100644 index 0000000..70f46ff --- /dev/null +++ b/default-event-service/default-event-service-api-impl/src/main/java/org/irods/jargon/dataone/events/defdb/DefaultEventServiceAOImpl.java @@ -0,0 +1,82 @@ +/** + * + */ +package org.irods.jargon.dataone.events.defdb; + +import java.util.Date; + +import org.dataone.service.exceptions.ServiceFailure; +import org.dataone.service.types.v1.Event; +import org.dataone.service.types.v1.Identifier; +import org.dataone.service.types.v1.Log; +import org.irods.jargon.core.connection.IRODSAccount; +import org.irods.jargon.core.exception.InvalidArgumentException; +import org.irods.jargon.core.exception.JargonException; +import org.irods.jargon.dataone.configuration.PublicationContext; +import org.irods.jargon.dataone.def.event.persist.dao.AccessLogDAO; +import org.irods.jargon.dataone.events.AbstractEventServiceAO; +import org.irods.jargon.dataone.events.EventsEnum; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Persistence based event service + * + * @author mcc + * + */ +public class DefaultEventServiceAOImpl extends AbstractEventServiceAO { + + private static final Logger log = LoggerFactory.getLogger(DefaultEventServiceAOImpl.class); + private AccessLogDAO accessLogDAO; + + /** + * @param irodsAccount + * @param publicationContext + */ + public DefaultEventServiceAOImpl(final IRODSAccount irodsAccount, final PublicationContext publicationContext, + final AccessLogDAO accessLogDAO) { + super(irodsAccount, publicationContext); + if (accessLogDAO == null) { + throw new IllegalArgumentException("null accessLogDAO"); + } + this.accessLogDAO = accessLogDAO; + } + + /* + * (non-Javadoc) + * + * @see + * org.irods.jargon.dataone.events.AbstractEventServiceAO#getLogs(java.util. + * Date, java.util.Date, org.irods.jargon.dataone.events.EventsEnum, + * java.lang.String, int, int) + */ + @Override + public Log getLogs(final Date start, final Date end, final EventsEnum event, final String pid, final int offset, + final int limit) { + return null; + } + + /* + * (non-Javadoc) + * + * @see + * org.irods.jargon.dataone.events.AbstractEventServiceAO#recordEvent(org. + * dataone.service.types.v1.Event, org.dataone.service.types.v1.Identifier, + * java.lang.String) + */ + @Override + public void recordEvent(final Event arg0, final Identifier arg1, final String arg2) + throws InvalidArgumentException, JargonException, ServiceFailure { + // TODO Auto-generated method stub + + } + + /** + * @return the accessLogDAO + */ + public AccessLogDAO getAccessLogDAO() { + return accessLogDAO; + } + +} diff --git a/default-event-service/default-event-service-api-impl/src/main/java/org/irods/jargon/dataone/events/defdb/DefaultEventServiceFactory.java b/default-event-service/default-event-service-api-impl/src/main/java/org/irods/jargon/dataone/events/defdb/DefaultEventServiceFactory.java new file mode 100644 index 0000000..c25691d --- /dev/null +++ b/default-event-service/default-event-service-api-impl/src/main/java/org/irods/jargon/dataone/events/defdb/DefaultEventServiceFactory.java @@ -0,0 +1,46 @@ +package org.irods.jargon.dataone.events.defdb; + +import org.irods.jargon.core.connection.IRODSAccount; +import org.irods.jargon.dataone.configuration.PublicationContext; +import org.irods.jargon.dataone.def.event.persist.dao.AccessLogDAO; +import org.irods.jargon.dataone.events.AbstractDataOneEventServiceFactory; +import org.irods.jargon.dataone.events.DataOneEventServiceAO; +import org.irods.jargon.dataone.events.DataOneEventServiceFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +/** + * @author dennis + */ +public class DefaultEventServiceFactory extends AbstractDataOneEventServiceFactory + implements DataOneEventServiceFactory { + + private AccessLogDAO accessLogDAO; + + public DefaultEventServiceFactory() { + super(); + this.accessLogDAO = init(); + } + + private static final Logger log = LoggerFactory.getLogger(DefaultEventServiceFactory.class); + + @Override + public DataOneEventServiceAO instance(PublicationContext publicationContext, IRODSAccount irodsAccount) { + // log.info("calling init("); + // AccessLogDAO accessLogDAO = init(); + log.info("accessLogDAO acquired:{}", accessLogDAO); + return new DefaultEventServiceAOImpl(irodsAccount, publicationContext, accessLogDAO); + } + + private AccessLogDAO init() { + log.info("init()"); + ApplicationContext context = new ClassPathXmlApplicationContext( + new String[] { "event-service-beans.xml", "event-dao-hibernate-spring.cfg.xml" }); + log.info("applicationContext built"); + AccessLogDAO accessLogDAO = (AccessLogDAO) context.getBean("accessLogDAO"); + log.info("successfully loaded DAO"); + return accessLogDAO; + } +} diff --git a/default-event-service/default-event-service-api-impl/src/main/java/org/irods/jargon/dataone/events/defdb/package-info.java b/default-event-service/default-event-service-api-impl/src/main/java/org/irods/jargon/dataone/events/defdb/package-info.java new file mode 100644 index 0000000..de5fa78 --- /dev/null +++ b/default-event-service/default-event-service-api-impl/src/main/java/org/irods/jargon/dataone/events/defdb/package-info.java @@ -0,0 +1,10 @@ +/** + * + */ +/** + * Database persistence of events + * + * @author mcc + * + */ +package org.irods.jargon.dataone.events.defdb; \ No newline at end of file diff --git a/default-event-service/default-event-service-api-impl/src/main/resources/.gitinclude b/default-event-service/default-event-service-api-impl/src/main/resources/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/default-event-service/default-event-service-api-impl/src/main/resources/event-dao-hibernate-spring.cfg.xml b/default-event-service/default-event-service-api-impl/src/main/resources/event-dao-hibernate-spring.cfg.xml new file mode 100644 index 0000000..08c0171 --- /dev/null +++ b/default-event-service/default-event-service-api-impl/src/main/resources/event-dao-hibernate-spring.cfg.xml @@ -0,0 +1,9 @@ + + + + + + + diff --git a/default-event-service/default-event-service-api-impl/src/main/resources/event-service-beans.xml b/default-event-service/default-event-service-api-impl/src/main/resources/event-service-beans.xml new file mode 100644 index 0000000..b22bf7e --- /dev/null +++ b/default-event-service/default-event-service-api-impl/src/main/resources/event-service-beans.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + ${hibernate.dialect} + false + false + false + 4 + 8 + 900 + 50 + false + false + + + + + + + + + + + + + + + + + + + diff --git a/default-event-service/default-event-service-api-impl/src/test/java/.gitinclude b/default-event-service/default-event-service-api-impl/src/test/java/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/default-event-service/default-event-service-api-impl/src/test/java/org/irods/jargon/dataone/events/defdb/DefaultEventServiceAOImplTest.java b/default-event-service/default-event-service-api-impl/src/test/java/org/irods/jargon/dataone/events/defdb/DefaultEventServiceAOImplTest.java new file mode 100644 index 0000000..3d56e17 --- /dev/null +++ b/default-event-service/default-event-service-api-impl/src/test/java/org/irods/jargon/dataone/events/defdb/DefaultEventServiceAOImplTest.java @@ -0,0 +1,25 @@ +package org.irods.jargon.dataone.events.defdb; + +import org.irods.jargon.core.connection.IRODSAccount; +import org.irods.jargon.core.pub.IRODSAccessObjectFactory; +import org.irods.jargon.dataone.configuration.PublicationContext; +import org.irods.jargon.dataone.def.event.persist.dao.AccessLogDAO; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; + +public class DefaultEventServiceAOImplTest { + + @Test + public void testLoad() throws Exception { + IRODSAccount dummyAccount = IRODSAccount.instance("host", 1247, "user", "pwd", "", "zone", ""); + IRODSAccessObjectFactory iaf = Mockito.mock(IRODSAccessObjectFactory.class); + PublicationContext context = new PublicationContext(); + context.setIrodsAccessObjectFactory(iaf); + AccessLogDAO accessLogDAO = Mockito.mock(AccessLogDAO.class); + DefaultEventServiceAOImpl defaultEventServiceAO = new DefaultEventServiceAOImpl(dummyAccount, context, + accessLogDAO); + Assert.assertNotNull("no event service returned", defaultEventServiceAO); + } + +} diff --git a/default-event-service/default-event-service-api-impl/src/test/java/org/irods/jargon/dataone/events/defdb/DefaultEventServiceFactoryTest.java b/default-event-service/default-event-service-api-impl/src/test/java/org/irods/jargon/dataone/events/defdb/DefaultEventServiceFactoryTest.java new file mode 100644 index 0000000..6ae8e60 --- /dev/null +++ b/default-event-service/default-event-service-api-impl/src/test/java/org/irods/jargon/dataone/events/defdb/DefaultEventServiceFactoryTest.java @@ -0,0 +1,28 @@ +package org.irods.jargon.dataone.events.defdb; + +import org.irods.jargon.core.connection.IRODSAccount; +import org.irods.jargon.core.pub.IRODSAccessObjectFactory; +import org.irods.jargon.dataone.configuration.PublicationContext; +import org.irods.jargon.dataone.events.DataOneEventServiceAO; +import org.irods.jargon.dataone.events.DataOneEventServiceFactory; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; + +public class DefaultEventServiceFactoryTest { + + @Test + public void testLoadFromFactory() throws Exception { + IRODSAccount dummyAccount = IRODSAccount.instance("host", 1247, "user", "pwd", "", "zone", ""); + IRODSAccessObjectFactory iaf = Mockito.mock(IRODSAccessObjectFactory.class); + PublicationContext context = new PublicationContext(); + context.setIrodsAccessObjectFactory(iaf); + DefaultEventServiceFactory defaultEventServiceFactory = new DefaultEventServiceFactory(); + DataOneEventServiceAO dataOneEventServiceAO = defaultEventServiceFactory.instance(context, dummyAccount); + Assert.assertNotNull("no event service created", dataOneEventServiceAO); + // make sure I can cast + DataOneEventServiceFactory castFactory = defaultEventServiceFactory; + castFactory.instance(context, dummyAccount); + } + +} diff --git a/default-event-service/default-event-service-api-impl/src/test/java/org/irods/jargon/dataone/events/defdb/unittest/AllTests.java b/default-event-service/default-event-service-api-impl/src/test/java/org/irods/jargon/dataone/events/defdb/unittest/AllTests.java new file mode 100644 index 0000000..9dccc9b --- /dev/null +++ b/default-event-service/default-event-service-api-impl/src/test/java/org/irods/jargon/dataone/events/defdb/unittest/AllTests.java @@ -0,0 +1,13 @@ +package org.irods.jargon.dataone.events.defdb.unittest; + +import org.irods.jargon.dataone.events.defdb.DefaultEventServiceAOImplTest; +import org.irods.jargon.dataone.events.defdb.DefaultEventServiceFactoryTest; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses({ DefaultEventServiceAOImplTest.class, DefaultEventServiceFactoryTest.class }) +public class AllTests { + +} diff --git a/default-event-service/default-event-service-api-impl/src/test/java/org/irods/jargon/dataone/events/defdb/unittest/package-info.java b/default-event-service/default-event-service-api-impl/src/test/java/org/irods/jargon/dataone/events/defdb/unittest/package-info.java new file mode 100644 index 0000000..25334d4 --- /dev/null +++ b/default-event-service/default-event-service-api-impl/src/test/java/org/irods/jargon/dataone/events/defdb/unittest/package-info.java @@ -0,0 +1,8 @@ + +/** + * Suites and general support + * + * @author mcc + * + */ +package org.irods.jargon.dataone.events.defdb.unittest; \ No newline at end of file diff --git a/default-event-service/default-event-service-indexer/misc/etc/irods-ext/default-event-indexer.properties b/default-event-service/default-event-service-indexer/misc/etc/irods-ext/default-event-indexer.properties new file mode 100644 index 0000000..8048592 --- /dev/null +++ b/default-event-service/default-event-service-indexer/misc/etc/irods-ext/default-event-indexer.properties @@ -0,0 +1,5 @@ +jdbc.url=jdbc:pgsql://irods420.irodslocal/IRODS-EXT?user=irodsext&password=password +jdbc.user=irodsext +jdbc.password=password +jdbc.driver=com.impossibl.postgres.jdbc.PGDriver +hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect diff --git a/default-event-service/default-event-service-indexer/misc/rules/default-dataone-indexer.re b/default-event-service/default-event-service-indexer/misc/rules/default-dataone-indexer.re new file mode 100644 index 0000000..8e0942c --- /dev/null +++ b/default-event-service/default-event-service-indexer/misc/rules/default-dataone-indexer.re @@ -0,0 +1,13 @@ + + acPostProcForOpen { + *err = errormsg(ipc_acPostProcForOpen, *msg); + if (*err < 0) { writeLine('serverLog', *msg); } + } + + + sendDataObjectOpen(*Data) = + let *msg = ipc_jsonDocument(list(mkEntityField(*Data), + mkPathField($objPath), + mkUserObject('author', $userNameClient, $rodsZoneClient))) + in sendMsg(DATA_OBJECT_TYPE ++ '.open', *msg) + \ No newline at end of file diff --git a/default-event-service/default-event-service-indexer/pom.xml b/default-event-service/default-event-service-indexer/pom.xml new file mode 100644 index 0000000..84227c7 --- /dev/null +++ b/default-event-service/default-event-service-indexer/pom.xml @@ -0,0 +1,107 @@ + + + 4.0.0 + default-event-service-indexer + + org.irods + default-event-service + 4.2.1.0-SNAPSHOT + + jar + Default event service + + + junit + junit + test + + + org.slf4j + slf4j-api + + + log4j + log4j + + + org.slf4j + slf4j-log4j12 + + + org.irods + default-event-service-persist + ${project.version} + + + org.irods + event-service-api + ${project.version} + + + org.springframework.integration + spring-integration-core + + + org.irods.jargon + jargon-core + ${project.version} + + + org.springframework.boot + spring-boot-starter-actuator + + + org.slf4j + log4j-over-slf4j + + + ch.qos.logback + logback-classic + + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.integration + spring-integration-core + + + org.springframework.integration + spring-integration-stream + + + org.springframework.integration + spring-integration-amqp + + + com.impossibl.pgjdbc-ng + pgjdbc-ng + + + + + + org.springframework.boot + spring-boot-maven-plugin + 1.5.3.RELEASE + + ${start-class} + JAR + + + + + repackage + + + + + + + + diff --git a/default-event-service/default-event-service-indexer/src/main/java/.gitinclude b/default-event-service/default-event-service-indexer/src/main/java/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/default-event-service/default-event-service-indexer/src/main/java/org/irods/jargon/dataone/events/def/indexer/Accessor.java b/default-event-service/default-event-service-indexer/src/main/java/org/irods/jargon/dataone/events/def/indexer/Accessor.java new file mode 100644 index 0000000..f206bb5 --- /dev/null +++ b/default-event-service/default-event-service-indexer/src/main/java/org/irods/jargon/dataone/events/def/indexer/Accessor.java @@ -0,0 +1,60 @@ +package org.irods.jargon.dataone.events.def.indexer; + +public class Accessor { + + private String name = ""; + private String zone = ""; + + public Accessor() { + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name + * the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the zone + */ + public String getZone() { + return zone; + } + + /** + * @param zone + * the zone to set + */ + public void setZone(String zone) { + this.zone = zone; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("Accessor ["); + if (name != null) { + builder.append("name=").append(name).append(", "); + } + if (zone != null) { + builder.append("zone=").append(zone); + } + builder.append("]"); + return builder.toString(); + } + +} diff --git a/default-event-service/default-event-service-indexer/src/main/java/org/irods/jargon/dataone/events/def/indexer/Application.java b/default-event-service/default-event-service-indexer/src/main/java/org/irods/jargon/dataone/events/def/indexer/Application.java new file mode 100644 index 0000000..2ba504e --- /dev/null +++ b/default-event-service/default-event-service-indexer/src/main/java/org/irods/jargon/dataone/events/def/indexer/Application.java @@ -0,0 +1,115 @@ +/** + * + */ +package org.irods.jargon.dataone.events.def.indexer; + +import org.irods.jargon.dataone.def.event.persist.dao.AccessLogDAO; +import org.irods.jargon.dataone.def.event.persist.dao.domain.AccessLog; +import org.irods.jargon.dataone.events.EventLoggingException; +import org.irods.jargon.dataone.events.EventsEnum; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.amqp.rabbit.connection.ConnectionFactory; +import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ImportResource; +import org.springframework.integration.amqp.inbound.AmqpInboundChannelAdapter; +import org.springframework.integration.annotation.IntegrationComponentScan; +import org.springframework.integration.annotation.ServiceActivator; +import org.springframework.integration.channel.DirectChannel; +import org.springframework.integration.config.EnableIntegration; +import org.springframework.messaging.Message; +import org.springframework.messaging.MessageChannel; +import org.springframework.messaging.MessageHandler; +import org.springframework.messaging.MessagingException; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +/** + * Master flow core + * + * @author mcc + * + */ + +@SpringBootApplication +@EnableIntegration +@IntegrationComponentScan +@ImportResource({ "/event-dao-hibernate-spring.cfg.xml", "/event-service-beans.xml" }) +public class Application { + + private static final Logger log = LoggerFactory.getLogger(Application.class); + + /** + * + */ + public Application() { + } + + public static void main(String[] args) throws Exception { + ConfigurableApplicationContext ctx = new SpringApplication(Application.class).run(args); + System.out.println("Hit Enter to terminate"); + System.in.read(); + ctx.close(); + } + + @Bean + public MessageChannel amqpInputChannel() { + return new DirectChannel(); + } + + @Bean + public AmqpInboundChannelAdapter inbound(SimpleMessageListenerContainer listenerContainer, + @Qualifier("amqpInputChannel") MessageChannel channel) { + AmqpInboundChannelAdapter adapter = new AmqpInboundChannelAdapter(listenerContainer); + adapter.setOutputChannel(channel); + return adapter; + } + + @Bean + public SimpleMessageListenerContainer container(ConnectionFactory connectionFactory) { + SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory); + container.setQueueNames("irods.dataone.logger"); + container.setConcurrentConsumers(2); + // ... + return container; + } + + @Bean + @ServiceActivator(inputChannel = "amqpInputChannel") + public MessageHandler handler(AccessLogDAO accessLogDAO) { + return new MessageHandler() { + + @Override + @Transactional(rollbackFor = { MessagingException.class }, propagation = Propagation.REQUIRED) + + public void handleMessage(Message message) throws MessagingException { + EventConverterUtil util = new EventConverterUtil(); + LoggingEvent event; + try { + event = util.loggingEventFromPayload((byte[]) message.getPayload()); + log.info("event:{}", event); + AccessLog accessLog = new AccessLog(); + accessLog.setIrodsPath(event.getPath()); + accessLog.setDateAdded(util.dateFromTimestamp(event.getTimestamp())); + accessLog.setEvent(EventsEnum.READ); + accessLog.setNodeIdentifier("foo"); + accessLog.setSubject(event.getAuthor().getName()); + log.info("access log to write:{}", accessLog); + accessLogDAO.save(accessLog); + log.info("saved!"); + } catch (EventLoggingException e) { + log.error("error converting message", e); + throw new MessagingException("error converting message", e); + } + log.info("msg:{}", event); + } + + }; + } + +} diff --git a/default-event-service/default-event-service-indexer/src/main/java/org/irods/jargon/dataone/events/def/indexer/EventConverterUtil.java b/default-event-service/default-event-service-indexer/src/main/java/org/irods/jargon/dataone/events/def/indexer/EventConverterUtil.java new file mode 100644 index 0000000..9853370 --- /dev/null +++ b/default-event-service/default-event-service-indexer/src/main/java/org/irods/jargon/dataone/events/def/indexer/EventConverterUtil.java @@ -0,0 +1,54 @@ +/** + * + */ +package org.irods.jargon.dataone.events.def.indexer; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import org.irods.jargon.dataone.events.EventLoggingException; +import org.joda.time.DateTime; +import org.joda.time.format.DateTimeFormat; +import org.joda.time.format.DateTimeFormatter; + +import java.io.IOException; +import java.util.Date; + +/** + * Utility for JSON conversion + * + * @author mcc + * + */ +public class EventConverterUtil { + + private ObjectMapper mapper = new ObjectMapper(); + private DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd.HH:mm:ss"); + + /** + * + */ + public EventConverterUtil() { + } + + public LoggingEvent loggingEventFromPayload(final byte[] payload) throws EventLoggingException { + String jsonRaw = new String(payload); + LoggingEvent event; + try { + event = mapper.readValue(jsonRaw, LoggingEvent.class); + } catch (IOException e) { + throw new EventLoggingException("unable to translate json", e); + } + return event; + + } + + public Date dateFromTimestamp(final String timestamp) throws EventLoggingException { + DateTime result; + try { + result = fmt.parseDateTime(timestamp); + } catch (IllegalArgumentException e) { + throw new EventLoggingException("unable to parse timestamp: " + timestamp, e); + } + return result.toDate(); + } +} diff --git a/default-event-service/default-event-service-indexer/src/main/java/org/irods/jargon/dataone/events/def/indexer/EventQueueLogger.java b/default-event-service/default-event-service-indexer/src/main/java/org/irods/jargon/dataone/events/def/indexer/EventQueueLogger.java new file mode 100644 index 0000000..37ea6a7 --- /dev/null +++ b/default-event-service/default-event-service-indexer/src/main/java/org/irods/jargon/dataone/events/def/indexer/EventQueueLogger.java @@ -0,0 +1,23 @@ +/** + * + */ +package org.irods.jargon.dataone.events.def.indexer; + +import org.springframework.stereotype.Component; + +/** + * Logger attached to an amqp event log queue + * + * @author mcc + * + */ +@Component +public class EventQueueLogger { + + /** + * + */ + public EventQueueLogger() { + } + +} diff --git a/default-event-service/default-event-service-indexer/src/main/java/org/irods/jargon/dataone/events/def/indexer/LoggingEvent.java b/default-event-service/default-event-service-indexer/src/main/java/org/irods/jargon/dataone/events/def/indexer/LoggingEvent.java new file mode 100644 index 0000000..02c2ee5 --- /dev/null +++ b/default-event-service/default-event-service-indexer/src/main/java/org/irods/jargon/dataone/events/def/indexer/LoggingEvent.java @@ -0,0 +1,108 @@ +/** + * + */ +package org.irods.jargon.dataone.events.def.indexer; + +/** + * @author mcc + * + */ +public class LoggingEvent { + + private String entity = ""; + private String path = ""; + private Accessor author; + private String timestamp; + + /** + * + */ + public LoggingEvent() { + } + + /** + * @return the entity + */ + public String getEntity() { + return entity; + } + + /** + * @param entity + * the entity to set + */ + public void setEntity(String entity) { + this.entity = entity; + } + + /** + * @return the path + */ + public String getPath() { + return path; + } + + /** + * @param path + * the path to set + */ + public void setPath(String path) { + this.path = path; + } + + /** + * @return the author + */ + public Accessor getAuthor() { + return author; + } + + /** + * @param author + * the author to set + */ + public void setAuthor(Accessor author) { + this.author = author; + } + + /** + * @return the timestamp + */ + public String getTimestamp() { + return timestamp; + } + + /** + * @param timestamp + * the timestamp to set. + */ + public void setTimestamp(String timestamp) { + this.timestamp = timestamp; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("LoggingEvent ["); + if (entity != null) { + builder.append("entity=").append(entity).append(", "); + } + if (path != null) { + builder.append("path=").append(path).append(", "); + } + if (author != null) { + builder.append("author=").append(author).append(", "); + } + if (timestamp != null) { + builder.append("timestamp=").append(timestamp); + } + builder.append("]"); + return builder.toString(); + } + +} diff --git a/default-event-service/default-event-service-indexer/src/main/java/org/irods/jargon/dataone/events/def/indexer/package-info.java b/default-event-service/default-event-service-indexer/src/main/java/org/irods/jargon/dataone/events/def/indexer/package-info.java new file mode 100644 index 0000000..c41fde5 --- /dev/null +++ b/default-event-service/default-event-service-indexer/src/main/java/org/irods/jargon/dataone/events/def/indexer/package-info.java @@ -0,0 +1,9 @@ +/** + * + */ +/** + * + * @author mcc + * + */ +package org.irods.jargon.dataone.events.def.indexer; \ No newline at end of file diff --git a/default-event-service/default-event-service-indexer/src/main/resources/.gitinclude b/default-event-service/default-event-service-indexer/src/main/resources/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/default-event-service/default-event-service-indexer/src/main/resources/event-dao-hibernate-spring.cfg.xml b/default-event-service/default-event-service-indexer/src/main/resources/event-dao-hibernate-spring.cfg.xml new file mode 100644 index 0000000..08c0171 --- /dev/null +++ b/default-event-service/default-event-service-indexer/src/main/resources/event-dao-hibernate-spring.cfg.xml @@ -0,0 +1,9 @@ + + + + + + + diff --git a/default-event-service/default-event-service-indexer/src/main/resources/event-service-beans.xml b/default-event-service/default-event-service-indexer/src/main/resources/event-service-beans.xml new file mode 100644 index 0000000..861d9b9 --- /dev/null +++ b/default-event-service/default-event-service-indexer/src/main/resources/event-service-beans.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + ${hibernate.dialect} + false + false + false + 4 + 8 + 900 + 50 + false + false + + + + + + + + + + + + + + + + + + + diff --git a/default-event-service/default-event-service-indexer/src/main/resources/integration.xml b/default-event-service/default-event-service-indexer/src/main/resources/integration.xml new file mode 100644 index 0000000..bcc3824 --- /dev/null +++ b/default-event-service/default-event-service-indexer/src/main/resources/integration.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/default-event-service/default-event-service-indexer/src/test/java/.gitinclude b/default-event-service/default-event-service-indexer/src/test/java/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/default-event-service/default-event-service-indexer/src/test/java/org/irods/jargon/dataone/events/def/indexer/EventConverterUtilTest.java b/default-event-service/default-event-service-indexer/src/test/java/org/irods/jargon/dataone/events/def/indexer/EventConverterUtilTest.java new file mode 100644 index 0000000..fc86bd8 --- /dev/null +++ b/default-event-service/default-event-service-indexer/src/test/java/org/irods/jargon/dataone/events/def/indexer/EventConverterUtilTest.java @@ -0,0 +1,22 @@ +package org.irods.jargon.dataone.events.def.indexer; + +import java.nio.file.Files; +import java.nio.file.Paths; + +import org.junit.Assert; +import org.junit.Test; + +public class EventConverterUtilTest { + + @Test + public void testJsonToLoggingEvent() throws Exception { + String myFile = "/sample-messages/msg1.json"; + + String jsonString = new String(Files.readAllBytes(Paths.get(getClass().getResource(myFile).toURI()))); + EventConverterUtil converter = new EventConverterUtil(); + LoggingEvent actual = converter.loggingEventFromPayload(jsonString.getBytes()); + Assert.assertNotNull("no logging event returned", actual); + + } + +} diff --git a/default-event-service/default-event-service-indexer/src/test/resources/event.properties b/default-event-service/default-event-service-indexer/src/test/resources/event.properties new file mode 100644 index 0000000..ee3f467 --- /dev/null +++ b/default-event-service/default-event-service-indexer/src/test/resources/event.properties @@ -0,0 +1,6 @@ +jdbc.url=jdbc:postgresql://irods420.irodslocal/IRODS-EXT?user=irodsext&password=password +jdbc.user=irodsext +jdbc.password=password +jdbc.driver=com.impossibl.postgres.jdbc.PGDriver + +hibernate.dialect=org.hibernate.dialect.PostgreSQL93Dialect diff --git a/default-event-service/default-event-service-indexer/src/test/resources/sample-messages/msg1.json b/default-event-service/default-event-service-indexer/src/test/resources/sample-messages/msg1.json new file mode 100644 index 0000000..a31070b --- /dev/null +++ b/default-event-service/default-event-service-indexer/src/test/resources/sample-messages/msg1.json @@ -0,0 +1 @@ +{"entity":"a401d352-4a33-11e7-9d94-1a5a300ff36f","path":"/iplant/home/dennis/foo.md","author":{"name":"rods","zone":"iplant"}} \ No newline at end of file diff --git a/default-event-service/default-event-service-indexer/src/test/resources/sample-messages/msg2.json b/default-event-service/default-event-service-indexer/src/test/resources/sample-messages/msg2.json new file mode 100644 index 0000000..8154dcc --- /dev/null +++ b/default-event-service/default-event-service-indexer/src/test/resources/sample-messages/msg2.json @@ -0,0 +1 @@ +'data-object.open':'{"entity":"a401d352-4a33-11e7-9d94-1a5a300ff36f","path":"/iplant/home/dennis/foo.md","author":{"name":"rods","zone":"iplant"}} \ No newline at end of file diff --git a/default-event-service/default-event-service-persist/README.md b/default-event-service/default-event-service-persist/README.md new file mode 100644 index 0000000..c5d0228 --- /dev/null +++ b/default-event-service/default-event-service-persist/README.md @@ -0,0 +1,91 @@ +## Running + +#### update db coordinates + +temporary until we pull in props....edit src/main/resources/event.properties for: + +* jdbc url +* user +* password + +#### add amqp queue in rabbitmq console + +add irods.dataone.logger as a queue (we'll make that a property l8r) + +#### put in the database (though we're still settling this) + +#### mvn install to build + +#### run it + +cd into the default-event-service-indexer project + +run mvn spring-boot:run + +Off you go! + +#### in amqp console put json into queue + +``` +{"entity":"a401d352-4a33-11e7-9d94-1a5a300ff36f","path":"/iplant/home/dennis/foo.md","author":{"name":"rods","zone":"iplant"}} + +``` + + + + + + + + + + + + + + + +## Database setup notes + +If you don't have an IRODS-EXT extensions db, add one and a user + +``` +$ (sudo) su - postgres +postgres$ psql +psql> CREATE USER irodsext WITH PASSWORD 'password'; +psql> CREATE DATABASE "IRODS-EXT"; +psql> GRANT ALL PRIVILEGES ON DATABASE "IRODS-EXT" TO irodsext; + +``` + + +Create the table for the event log + +``` + +CREATE TABLE IF NOT EXISTS access_log ( id BIGSERIAL PRIMARY KEY, file_key VARCHAR(1024) NOT NULL, event_id VARCHAR(30) NOT NULL, event_detail VARCHAR(200) NULL, access_principal VARCHAR(50) NULL, date_added TIMESTAMP DEFAULT NULL ); + + +``` + +(no other indexes yet...may add) + +yields + +``` + ^ +IRODS-EXT=# \d access_log + Table "public.access_log" + Column | Type | Modifiers +------------------+-----------------------------+--------------------------------------------------------- + id | bigint | not null default nextval('access_log_id_seq'::regclass) + file_key | character varying(1024) | not null + event_id | character varying(30) | not null + event_detail | character varying(200) | + access_principal | character varying(50) | + date_added | timestamp without time zone | +Indexes: + "access_log_pkey" PRIMARY KEY, btree (id) + + +``` \ No newline at end of file diff --git a/default-event-service/default-event-service-persist/pom.xml b/default-event-service/default-event-service-persist/pom.xml new file mode 100644 index 0000000..9dbc122 --- /dev/null +++ b/default-event-service/default-event-service-persist/pom.xml @@ -0,0 +1,97 @@ + + + 4.0.0 + default-event-service-persist + + org.irods + default-event-service + 4.2.1.0-SNAPSHOT + + jar + Default event service persistence + + + org.irods.jargon + jargon-core + ${project.version} + + + + junit + junit + test + + + org.slf4j + slf4j-api + + + log4j + log4j + + + org.slf4j + slf4j-log4j12 + + + org.irods + dataone-utils + ${project.version} + + + org.irods + event-service-api + ${project.version} + + + org.springframework + spring-test + + + org.springframework + spring-context + + + org.springframework + spring-beans + + + org.springframework + spring-orm + + + org.hibernate + hibernate-core + + + + org.springframework + spring-core + + + org.springframework + spring-aop + + + org.springframework + spring-jdbc + + + org.springframework + spring-tx + + + org.hibernate.javax.persistence + hibernate-jpa-2.1-api + + + javax.transaction + jta + + + + diff --git a/default-event-service/default-event-service-persist/src/main/java/.gitinclude b/default-event-service/default-event-service-persist/src/main/java/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/default-event-service/default-event-service-persist/src/main/java/org/irods/jargon/dataone/def/event/persist/dao/AccessLogDAO.java b/default-event-service/default-event-service-persist/src/main/java/org/irods/jargon/dataone/def/event/persist/dao/AccessLogDAO.java new file mode 100644 index 0000000..f9f265c --- /dev/null +++ b/default-event-service/default-event-service-persist/src/main/java/org/irods/jargon/dataone/def/event/persist/dao/AccessLogDAO.java @@ -0,0 +1,70 @@ +/** + * + */ +package org.irods.jargon.dataone.def.event.persist.dao; + +import org.irods.jargon.dataone.def.event.persist.dao.domain.AccessLog; +import org.irods.jargon.dataone.events.EventLoggingException; +import org.irods.jargon.dataone.events.EventsEnum; + +import java.util.Date; +import java.util.List; + +/** + * DAO interface for Access log + * + * @author Mike Conway + * + */ +public interface AccessLogDAO { + + /** + * Save the AccessLog entry in the audit database + * + * @param accessLog + * {@link AccessLog} entry containing the event + * @throws EventLoggingException + */ + void save(AccessLog accessLog) throws EventLoggingException; + + /** + * locate the access log entry by ID + * + * @param id + * Long with the access id + * @return {@link AccessLog} or null + * @throws EventLoggingException + */ + AccessLog findById(Long id) throws EventLoggingException; + + /** + * Delete the given entry + * + * @param accessLog + * {@link AccessLog} to delete + * @throws EventLoggingException + */ + void delete(AccessLog accessLog) throws EventLoggingException; + + /** + * Finds a set of access log entries. + * + * @param start + * the start date for the search, if any + * @param end + * the end date for the search, if any + * @param eventType + * the selected event type, if any + * @param pid + * the permanent identifier, if any + * @param offset + * the starting offset for paged listings + * @param limit + * the maximum number of results for paged listings. + * + * @return the list of matching events + * @throws EventLoggingException if an error occurs in the query + */ + List find(Date start, Date end, EventsEnum eventType, String pid, int offset, int limit) + throws EventLoggingException; +} diff --git a/default-event-service/default-event-service-persist/src/main/java/org/irods/jargon/dataone/def/event/persist/dao/AccessLogDAOImpl.java b/default-event-service/default-event-service-persist/src/main/java/org/irods/jargon/dataone/def/event/persist/dao/AccessLogDAOImpl.java new file mode 100644 index 0000000..f5ef2cb --- /dev/null +++ b/default-event-service/default-event-service-persist/src/main/java/org/irods/jargon/dataone/def/event/persist/dao/AccessLogDAOImpl.java @@ -0,0 +1,149 @@ +/** + * + */ +package org.irods.jargon.dataone.def.event.persist.dao; + +import java.util.Date; +import java.util.List; + +import org.hibernate.Criteria; +import org.hibernate.SessionFactory; +import org.hibernate.criterion.Restrictions; +import org.irods.jargon.dataone.def.event.persist.dao.domain.AccessLog; +import org.irods.jargon.dataone.events.EventLoggingException; +import org.irods.jargon.dataone.events.EventsEnum; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * Impl of an access log + * + * @author mcc + * + */ +public class AccessLogDAOImpl implements AccessLogDAO { + + private static final Logger log = LoggerFactory.getLogger(AccessLogDAOImpl.class); + + @Autowired + private SessionFactory sessionFactory; + + /** + * + */ + public AccessLogDAOImpl() { + } + + /* + * (non-Javadoc) + * + * @see + * org.irods.jargon.dataone.def.event.persist.dao.AccessLogDAO#save(org. + * irods.jargon.dataone.def.event.persist.dao.domain.AccessLog) + */ + @Override + public void save(AccessLog accessLog) throws EventLoggingException { + + log.info("save accessLog:{}", accessLog); + + try { + sessionFactory.getCurrentSession().saveOrUpdate(accessLog); + } catch (Exception e) { + log.error("error in save(AccessLog)", e); + throw new EventLoggingException("Failed save(accessLog)", e); + } + + } + + /* + * (non-Javadoc) + * + * @see + * org.irods.jargon.dataone.def.event.persist.dao.AccessLogDAO#findById(java + * .lang.Long) + */ + @Override + public AccessLog findById(Long id) throws EventLoggingException { + + log.info("find accessLog:{}", id); + + Criteria criteria = sessionFactory.getCurrentSession().createCriteria(AccessLog.class); + return (AccessLog) criteria.uniqueResult(); + + } + + /* + * (non-Javadoc) + * + * @see + * org.irods.jargon.dataone.def.event.persist.dao.AccessLogDAO#delete(org. + * irods.jargon.dataone.def.event.persist.dao.domain.AccessLog) + */ + @Override + public void delete(AccessLog accessLog) throws EventLoggingException { + log.info("entering delete(AccessLog)"); + + try { + sessionFactory.getCurrentSession().delete(accessLog); + } catch (Exception e) { + log.error("error in delete(AccessLog)", e); + throw new EventLoggingException("Failed delete(AccessLog)", e); + } + } + + @SuppressWarnings("unchecked") + @Override + public List find(Date start, Date end, EventsEnum eventType, String pid, int offset, int limit) + throws EventLoggingException { + log.info("find start:{}, end:{}, eventType:{}, pid:{}, offset:{}, limit:{}", start, end, eventType, pid, offset, + limit); + + List results; + try { + Criteria crit = sessionFactory.getCurrentSession().createCriteria(AccessLog.class); + if (start != null) { + crit.add(Restrictions.ge("dateAdded", start)); + } + if (end != null) { + crit.add(Restrictions.le("dateAdded", end)); + } + if (eventType != null) { + crit.add(Restrictions.eq("event", eventType)); + } + if (pid != null) { + crit.add(Restrictions.eq("permanentId", pid)); + } + crit.setFirstResult(offset); + crit.setMaxResults(limit); + results = crit.list(); + } catch (Exception e) { + log.error("error in find(start, end, eventType, offset, limit)", e); + throw new EventLoggingException("failed find(start, end, eventType, offset, limit)", e); + } + return results; + } + + /** + * @return the log + */ + public static Logger getLog() { + return log; + } + + /** + * @return the sessionFactory + */ + public SessionFactory getSessionFactory() { + return sessionFactory; + } + + /** + * @param sessionFactory + * the sessionFactory to set + */ + public void setSessionFactory(SessionFactory sessionFactory) { + this.sessionFactory = sessionFactory; + } + +} diff --git a/default-event-service/default-event-service-persist/src/main/java/org/irods/jargon/dataone/def/event/persist/dao/domain/AccessLog.java b/default-event-service/default-event-service-persist/src/main/java/org/irods/jargon/dataone/def/event/persist/dao/domain/AccessLog.java new file mode 100644 index 0000000..33f4858 --- /dev/null +++ b/default-event-service/default-event-service-persist/src/main/java/org/irods/jargon/dataone/def/event/persist/dao/domain/AccessLog.java @@ -0,0 +1,246 @@ +/** + * + */ +package org.irods.jargon.dataone.def.event.persist.dao.domain; + +import org.hibernate.annotations.ColumnTransformer; +import org.irods.jargon.dataone.events.EventsEnum; + +import java.util.Date; +import java.util.UUID; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Temporal; + +/** + * + * @author mcc + * + */ +@Entity +@Table(name = "event_log") +public class AccessLog { + + @Id() + @GeneratedValue + @Column(name = "id", columnDefinition = "uuid", updatable = false) + private UUID id; + + @Column(name = "permanent_id", nullable = true) + private String permanentId; + + @Column(name = "ip_address", nullable = true) + private String ipAddress; + + @Column(name = "irods_path", nullable = true) + private String irodsPath; + + @Column(name = "user_agent", nullable = true) + private String userAgent; + + @Column(name = "subject", nullable = true) + private String subject; + + @Column(name = "event", columnDefinition = "event_type", nullable = false) + @Enumerated(EnumType.STRING) + private EventsEnum event; + + @Column(name = "date_logged") + @Temporal(javax.persistence.TemporalType.TIMESTAMP) + private Date dateAdded; + + @Column(name = "node_identifier", nullable = false) + private String nodeIdentifier; + + /** + * + */ + public AccessLog() { + } + + /** + * @return the dateAdded + */ + public Date getDateAdded() { + return dateAdded; + } + + /** + * @param dateAdded + * the dateAdded to set + */ + public void setDateAdded(Date dateAdded) { + this.dateAdded = dateAdded; + } + + /** + * + * + * /** + * + * @return the ipAddress + */ + public String getIpAddress() { + return ipAddress; + } + + /** + * @param ipAddress + * the ipAddress to set + */ + public void setIpAddress(String ipAddress) { + this.ipAddress = ipAddress; + } + + /** + * @return the userAgent + */ + public String getUserAgent() { + return userAgent; + } + + /** + * @param userAgent + * the userAgent to set + */ + public void setUserAgent(String userAgent) { + this.userAgent = userAgent; + } + + /** + * @return the subject + */ + public String getSubject() { + return subject; + } + + /** + * @param subject + * the subject to set + */ + public void setSubject(String subject) { + this.subject = subject; + } + + /** + * @return the nodeIdentifier + */ + public String getNodeIdentifier() { + return nodeIdentifier; + } + + /** + * @param nodeIdentifier + * the nodeIdentifier to set + */ + public void setNodeIdentifier(String nodeIdentifier) { + this.nodeIdentifier = nodeIdentifier; + } + + /** + * @return the permanentId + */ + public String getPermanentId() { + return permanentId; + } + + /** + * @param permanentId + * the permanentId to set + */ + public void setPermanentId(String permanentId) { + this.permanentId = permanentId; + } + + /** + * @return the irodsPath + */ + public String getIrodsPath() { + return irodsPath; + } + + /** + * @param irodsPath + * the irodsPath to set + */ + public void setIrodsPath(String irodsPath) { + this.irodsPath = irodsPath; + } + + /** + * @return the id + */ + public UUID getId() { + return id; + } + + /** + * @param id + * the id to set + */ + public void setId(UUID id) { + this.id = id; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("AccessLog ["); + if (id != null) { + builder.append("id=").append(id).append(", "); + } + if (permanentId != null) { + builder.append("permanentId=").append(permanentId).append(", "); + } + if (ipAddress != null) { + builder.append("ipAddress=").append(ipAddress).append(", "); + } + if (irodsPath != null) { + builder.append("irodsPath=").append(irodsPath).append(", "); + } + if (userAgent != null) { + builder.append("userAgent=").append(userAgent).append(", "); + } + if (subject != null) { + builder.append("subject=").append(subject).append(", "); + } + if (event != null) { + builder.append("event=").append(event).append(", "); + } + if (dateAdded != null) { + builder.append("dateAdded=").append(dateAdded).append(", "); + } + if (nodeIdentifier != null) { + builder.append("nodeIdentifier=").append(nodeIdentifier); + } + builder.append("]"); + return builder.toString(); + } + + /** + * @return the event + */ + public EventsEnum getEvent() { + return event; + } + + /** + * @param event + * the event to set + */ + public void setEvent(EventsEnum event) { + this.event = event; + } + +} diff --git a/default-event-service/default-event-service-persist/src/main/java/org/irods/jargon/dataone/def/event/persist/dao/domain/package-info.java b/default-event-service/default-event-service-persist/src/main/java/org/irods/jargon/dataone/def/event/persist/dao/domain/package-info.java new file mode 100644 index 0000000..29e531d --- /dev/null +++ b/default-event-service/default-event-service-persist/src/main/java/org/irods/jargon/dataone/def/event/persist/dao/domain/package-info.java @@ -0,0 +1,10 @@ +/** + * + */ +/** + * Persistance daos representing data in event service db + * + * @author mcc + * + */ +package org.irods.jargon.dataone.def.event.persist.dao.domain; \ No newline at end of file diff --git a/default-event-service/default-event-service-persist/src/main/java/org/irods/jargon/dataone/def/event/persist/dao/package-info.java b/default-event-service/default-event-service-persist/src/main/java/org/irods/jargon/dataone/def/event/persist/dao/package-info.java new file mode 100644 index 0000000..3c09706 --- /dev/null +++ b/default-event-service/default-event-service-persist/src/main/java/org/irods/jargon/dataone/def/event/persist/dao/package-info.java @@ -0,0 +1,10 @@ +/** + * + */ +/** + * DAO layer for event logging + * + * @author mcc + * + */ +package org.irods.jargon.dataone.def.event.persist.dao; \ No newline at end of file diff --git a/default-event-service/default-event-service-persist/src/main/java/org/irods/jargon/dataone/def/event/persist/package-info.java b/default-event-service/default-event-service-persist/src/main/java/org/irods/jargon/dataone/def/event/persist/package-info.java new file mode 100644 index 0000000..a374111 --- /dev/null +++ b/default-event-service/default-event-service-persist/src/main/java/org/irods/jargon/dataone/def/event/persist/package-info.java @@ -0,0 +1,10 @@ +/** + * + */ +/** + * Persistence for event service + * + * @author mcc + * + */ +package org.irods.jargon.dataone.def.event.persist; \ No newline at end of file diff --git a/default-event-service/default-event-service-persist/src/main/resources/.gitinclude b/default-event-service/default-event-service-persist/src/main/resources/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/default-event-service/default-event-service-persist/src/test/java/.gitinclude b/default-event-service/default-event-service-persist/src/test/java/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/default-event-service/pom.xml b/default-event-service/pom.xml new file mode 100644 index 0000000..7552f17 --- /dev/null +++ b/default-event-service/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + default-event-service + + org.irods + dfc-dataone + 4.2.1.0-SNAPSHOT + + pom + Default event service parent + + + + org.hibernate.javax.persistence + hibernate-jpa-2.1-api + 1.0.0.Final + + + + javax.transaction + jta + 1.1 + + + + + + default-event-service-persist + default-event-service-indexer + default-event-service-api-impl + + diff --git a/dfc-repo-service-impl/pom.xml b/dfc-repo-service-impl/pom.xml new file mode 100644 index 0000000..d172d0b --- /dev/null +++ b/dfc-repo-service-impl/pom.xml @@ -0,0 +1,58 @@ + + + 4.0.0 + dfc-repo-service-impl + DFC repo service + + org.irods + dfc-dataone + 4.2.1.0-SNAPSHOT + + jar + + + org.irods.jargon + jargon-core + ${project.version} + + + + junit + junit + test + + + org.slf4j + slf4j-api + + + log4j + log4j + + + org.slf4j + slf4j-log4j12 + + + org.mockito + mockito-all + + + org.irods + repo-service-api + ${project.version} + + + org.irods + dataone-utils + ${project.version} + + + org.irods + repo-service-api + ${project.version} + + + diff --git a/dfc-repo-service-impl/src/main/java/.gitinclude b/dfc-repo-service-impl/src/main/java/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/dfc-repo-service-impl/src/main/java/org/irods/jargon/dataone/repo/dfc/DfcRepoServiceImpl.java b/dfc-repo-service-impl/src/main/java/org/irods/jargon/dataone/repo/dfc/DfcRepoServiceImpl.java new file mode 100644 index 0000000..e6735b3 --- /dev/null +++ b/dfc-repo-service-impl/src/main/java/org/irods/jargon/dataone/repo/dfc/DfcRepoServiceImpl.java @@ -0,0 +1,276 @@ +/** + * + */ +package org.irods.jargon.dataone.repo.dfc; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.apache.tika.detect.DefaultDetector; +import org.apache.tika.metadata.Metadata; +import org.apache.tika.metadata.TikaMetadataKeys; +import org.apache.tika.mime.MediaType; +import org.dataone.service.types.v1.Identifier; +import org.dataone.service.types.v1.ObjectFormatIdentifier; +import org.irods.jargon.core.connection.IRODSAccount; +import org.irods.jargon.core.exception.FileNotFoundException; +import org.irods.jargon.core.exception.JargonException; +import org.irods.jargon.core.pub.DataObjectAO; +import org.irods.jargon.core.pub.domain.DataObject; +import org.irods.jargon.core.pub.io.IRODSFile; +import org.irods.jargon.core.pub.io.IRODSFileInputStream; +import org.irods.jargon.core.query.AVUQueryElement; +import org.irods.jargon.core.query.AVUQueryElement.AVUQueryPart; +import org.irods.jargon.core.query.JargonQueryException; +import org.irods.jargon.core.query.MetaDataAndDomainData; +import org.irods.jargon.core.query.QueryConditionOperators; +import org.irods.jargon.dataone.configuration.PublicationContext; +import org.irods.jargon.dataone.reposervice.AbstractDataOneRepoServiceAO; +import org.irods.jargon.dataone.reposervice.DataObjectListResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author mcc + * + */ +public class DfcRepoServiceImpl extends AbstractDataOneRepoServiceAO { + + public DfcRepoServiceImpl(IRODSAccount irodsAccount, PublicationContext publicationContext) { + super(irodsAccount, publicationContext); + } + + private Logger log = LoggerFactory.getLogger(this.getClass()); + + @Override + public DataObjectListResponse getListOfDataoneExposedDataObjects(final Date fromDate, final Date toDate, + final ObjectFormatIdentifier formatId, final Boolean replicaStatus, final Integer start, + final Integer count) throws JargonException { + + // get complete list of exposed data objects + // TODO: see if this can be done differently to just request list + // using filter items + DataObjectListResponse dataObjectListResponse = new DataObjectListResponse(); + List dataObjectListTmp = new ArrayList<>(); + List dataObjectListFinal = new ArrayList<>(); + List ids = getListOfDataoneExposedIdentifiers(); + + log.info("finding list of data objects with list of {} identifiers", ids.size()); + // TODO: what is this? + for (Identifier id : ids) { + DataObject dataObject; + dataObject = null; // TODO://recast + // getDataObjectFromIdentifier(id); + + if (dataObject != null) { + Date modifiedDate = dataObject.getUpdatedAt(); + + if (matchesFromDate(fromDate, modifiedDate) && matchesToDate(toDate, modifiedDate) && + // matchesFormatId(formatId, dataObject) && support not + // required + matchesReplicaStatus(replicaStatus)) { + dataObjectListTmp.add(dataObject); + } + } + } + // save total before filtering with start and count + dataObjectListResponse.setTotal(dataObjectListTmp.size()); + + // now filter this list according to start and count + if (dataObjectListTmp.size() > 0) { + DataObject[] dataObjectArray = dataObjectListTmp.toArray(new DataObject[dataObjectListTmp.size()]); + int end = start + count; + for (int i = start; i < dataObjectArray.length && i < end; i++) { + dataObjectListFinal.add(dataObjectArray[i]); + } + } + + dataObjectListResponse.setCount(dataObjectListFinal.size()); + dataObjectListResponse.setDataObjects(dataObjectListFinal); + + log.info("returning list of dataObjects: {}", dataObjectListFinal.toString()); + return dataObjectListResponse; + } + + private boolean matchesFromDate(final Date fromDate, final Date dataObjectModDate) { + + if (fromDate == null || fromDate.getTime() <= 0) { + log.info("fromDate : returning matches"); + return true; + } + + if (fromDate.getTime() <= dataObjectModDate.getTime()) { + log.info("fromDate : returning matches"); + return true; + } + + log.info("fromDate : returning no match"); + return false; + } + + private boolean matchesToDate(final Date toDate, final Date dataObjectModDate) { + + if (toDate == null || toDate.getTime() <= 0) { + log.info("toDate : returning matches"); + return true; + } + + if (toDate.getTime() >= dataObjectModDate.getTime()) { + log.info("toDate : returning matches"); + return true; + } + + log.info("toDate : returning no match"); + return false; + } + + private boolean matchesFormatId(final ObjectFormatIdentifier formatId, final DataObject dataObject) + throws JargonException, JargonQueryException { + + String dataFormat = dataObjectFormat(dataObject); + + if ((formatId.getValue() == null) || (formatId.getValue().equals(dataFormat))) { + return true; + } + return false; + } + + private boolean matchesReplicaStatus(final Boolean replicaStatus) { + + // replication is always set to false for now + if (replicaStatus == null || replicaStatus == false) { + log.info("replicastatus : returning matches"); + return true; + } + + log.info("toDate : returning no match"); + return false; + } + + // TODO: do we need this method? + @Override + public List getListOfDataoneExposedIdentifiers() throws JargonException { + + List identifiers = new ArrayList<>(); + + // FIXME: recast + return identifiers; + } + + @Override + public Date getLastModifiedDateForDataObject(DataObject dataObject) throws JargonException { + long epoch = 0; + AVUQueryElement avuQuery = null; + List avuQueryList = new ArrayList<>(); + List metadataAndDomainDataList = new ArrayList<>(); + String dateAttr = "StartDateTime"; + + try { + avuQuery = AVUQueryElement.instanceForValueQuery(AVUQueryPart.ATTRIBUTE, QueryConditionOperators.EQUAL, + dateAttr); + avuQueryList.add(avuQuery); + + DataObjectAO dataObjectAO = this.getPublicationContext().getIrodsAccessObjectFactory() + .getDataObjectAO(this.getIrodsAccount()); + + metadataAndDomainDataList = dataObjectAO.findMetadataValuesForDataObjectUsingAVUQuery(avuQueryList, + dataObject.getAbsolutePath()); + } catch (JargonQueryException e) { + log.error("error querying metadata", e); + throw new JargonException(e); + } + + String value = null; + for (MetaDataAndDomainData data : metadataAndDomainDataList) { + value = data.getAvuValue(); + // just take the 1st one + break; + } + epoch = Long.parseLong(value); + // need to convert it 2 milliseconds for Java date + Date theDate = new Date(epoch * 1000); + + return theDate; + } + + @Override + public String dataObjectFormat(DataObject dataObject) throws FileNotFoundException, JargonException { + String format = getDataObjectFormatFromMetadata(dataObject); + if (format == null) { + format = getDataObjectMimeType(dataObject); + } + + return format; + + } + + private String getDataObjectMimeType(DataObject dataObject) throws JargonException { + String mimeType = null; + String filename = dataObject.getAbsolutePath(); + + DefaultDetector typeDetector = new DefaultDetector(); + IRODSFile irodsFile = this.getPublicationContext().getIrodsAccessObjectFactory() + .getIRODSFileFactory(this.getIrodsAccount()).instanceIRODSFile(filename); + IRODSFileInputStream irodsStream = this.getPublicationContext().getIrodsAccessObjectFactory() + .getIRODSFileFactory(this.getIrodsAccount()).instanceIRODSFileInputStream(irodsFile); + InputStream stream = new BufferedInputStream(irodsStream); + Metadata metadata = new Metadata(); + metadata.add(TikaMetadataKeys.RESOURCE_NAME_KEY, filename); + + MediaType type; + try { + type = typeDetector.detect(stream, metadata); + } catch (IOException e) { + throw new FileNotFoundException("Cannot stream file in order to detect file type"); + } + + // if mime type is returned as "application/x-netcdf" change to + // DataONE accepted name: "netCDF-4" + mimeType = type.toString(); + if (mimeType.equals("application/x-netcdf")) { + mimeType = "netCDF-4"; + } + + return mimeType; + } + + private String getDataObjectFormatFromMetadata(final DataObject dataObject) + throws FileNotFoundException, JargonException { + + String dataFormat = null; + String formatAttr = "Format"; + List avuQueryList = new ArrayList<>(); + + // List result = + // dataObjectAO.findMetadataValuesForDataObject(dataObject.getAbsolutePath()); + List result; + try { + AVUQueryElement avuQuery = AVUQueryElement.instanceForValueQuery(AVUQueryPart.ATTRIBUTE, + QueryConditionOperators.EQUAL, formatAttr); + avuQueryList.add(avuQuery); + + DataObjectAO dataObjectAO = this.getPublicationContext().getIrodsAccessObjectFactory() + .getDataObjectAO(this.getIrodsAccount()); + result = dataObjectAO.findMetadataValuesForDataObjectUsingAVUQuery(avuQueryList, + dataObject.getAbsolutePath()); + } catch (JargonQueryException e) { + log.error("metadata query error", e); + throw new JargonException("cannot query for metadata", e); + } + + for (MetaDataAndDomainData metadata : result) { + if (metadata.getAvuAttribute().equals("Format")) { + dataFormat = metadata.getAvuValue(); + break; + } + } + + return dataFormat; + + } + +} diff --git a/dfc-repo-service-impl/src/main/java/org/irods/jargon/dataone/repo/dfc/package-info.java b/dfc-repo-service-impl/src/main/java/org/irods/jargon/dataone/repo/dfc/package-info.java new file mode 100644 index 0000000..885b42f --- /dev/null +++ b/dfc-repo-service-impl/src/main/java/org/irods/jargon/dataone/repo/dfc/package-info.java @@ -0,0 +1,10 @@ +/** + * + */ +/** + * Existing DFC implementation of repo processing + * + * @author mcc + * + */ +package org.irods.jargon.dataone.repo.dfc; \ No newline at end of file diff --git a/dfc-repo-service-impl/src/main/resources/.gitinclude b/dfc-repo-service-impl/src/main/resources/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/dfc-repo-service-impl/src/test/java/.gitinclude b/dfc-repo-service-impl/src/test/java/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/dfc-repo-service-impl/src/test/resources/.gitinclude b/dfc-repo-service-impl/src/test/resources/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/dummy-event-service-impl/pom.xml b/dummy-event-service-impl/pom.xml new file mode 100644 index 0000000..bb9dc73 --- /dev/null +++ b/dummy-event-service-impl/pom.xml @@ -0,0 +1,53 @@ + + + 4.0.0 + dummy-event-service-impl + + org.irods + dfc-dataone + 4.2.1.0-SNAPSHOT + + jar + Event service dummy implementation for testing purposes + + + org.irods.jargon + jargon-core + ${project.version} + + + + junit + junit + test + + + org.slf4j + slf4j-api + + + log4j + log4j + + + org.slf4j + slf4j-log4j12 + + + org.mockito + mockito-all + + + org.irods + event-service-api + ${project.version} + + + org.irods + dataone-utils + ${project.version} + + + diff --git a/dummy-event-service-impl/src/main/java/.gitinclude b/dummy-event-service-impl/src/main/java/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/dummy-event-service-impl/src/main/java/org/irods/jargon/dataone/events/impl/dummy/DummyEventServiceAOImpl.java b/dummy-event-service-impl/src/main/java/org/irods/jargon/dataone/events/impl/dummy/DummyEventServiceAOImpl.java new file mode 100644 index 0000000..dcb3f77 --- /dev/null +++ b/dummy-event-service-impl/src/main/java/org/irods/jargon/dataone/events/impl/dummy/DummyEventServiceAOImpl.java @@ -0,0 +1,67 @@ +/** + * + */ +package org.irods.jargon.dataone.events.impl.dummy; + +import java.util.Date; + +import org.dataone.service.exceptions.ServiceFailure; +import org.dataone.service.types.v1.Event; +import org.dataone.service.types.v1.Identifier; +import org.dataone.service.types.v1.Log; +import org.irods.jargon.core.connection.IRODSAccount; +import org.irods.jargon.core.exception.InvalidArgumentException; +import org.irods.jargon.core.exception.JargonException; +import org.irods.jargon.dataone.configuration.PublicationContext; +import org.irods.jargon.dataone.events.AbstractEventServiceAO; +import org.irods.jargon.dataone.events.EventsEnum; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Dummy implementation of an event service suitable for testing of discovery + * and loading + * + * @author mconway + * + */ +public class DummyEventServiceAOImpl extends AbstractEventServiceAO { + + public static final Logger log = LoggerFactory.getLogger(DummyEventServiceAOImpl.class); + + public DummyEventServiceAOImpl(IRODSAccount irodsAccount, PublicationContext publicationContext) { + super(irodsAccount, publicationContext); + } + + /* + * (non-Javadoc) + * + * @see + * org.irods.jargon.dataone.events.AbstractEventServiceAO#getLogs(java.util + * .Date, java.util.Date, org.irods.jargon.dataone.events.EventsEnum, + * java.lang.String, int, int) + */ + @Override + public Log getLogs(Date fromDate, Date toDate, EventsEnum event, String pidFilter, int startIdx, int count) { + log.info("getLogs()"); + return new Log(); + } + + /* + * (non-Javadoc) + * + * @see + * org.irods.jargon.dataone.events.AbstractEventServiceAO#recordEvent(org + * .dataone.service.types.v1.Event, org.dataone.service.types.v1.Identifier, + * java.lang.String) + */ + @Override + public void recordEvent(Event event, Identifier id, String description) + throws InvalidArgumentException, JargonException, ServiceFailure { + log.info("recordEvent()"); + log.info("event:{}", event); + log.info("id:{}", id); + log.info("description:{}", description); + } + +} diff --git a/dummy-event-service-impl/src/main/java/org/irods/jargon/dataone/events/impl/dummy/DummyEventServiceFactory.java b/dummy-event-service-impl/src/main/java/org/irods/jargon/dataone/events/impl/dummy/DummyEventServiceFactory.java new file mode 100644 index 0000000..c439eaa --- /dev/null +++ b/dummy-event-service-impl/src/main/java/org/irods/jargon/dataone/events/impl/dummy/DummyEventServiceFactory.java @@ -0,0 +1,35 @@ +/** + * + */ +package org.irods.jargon.dataone.events.impl.dummy; + +import org.irods.jargon.core.connection.IRODSAccount; +import org.irods.jargon.dataone.configuration.PublicationContext; +import org.irods.jargon.dataone.events.AbstractDataOneEventServiceFactory; +import org.irods.jargon.dataone.events.DataOneEventServiceAO; + +/** + * @author mcc + * + */ +public class DummyEventServiceFactory extends AbstractDataOneEventServiceFactory { + + /** + * + */ + public DummyEventServiceFactory() { + } + + /* + * (non-Javadoc) + * + * @see org.irods.jargon.dataone.events.AbstractDataOneEventServiceFactory# + * instance(org.irods.jargon.dataone.configuration.PublicationContext, + * org.irods.jargon.core.connection.IRODSAccount) + */ + @Override + public DataOneEventServiceAO instance(PublicationContext publicationContext, IRODSAccount irodsAccount) { + return new DummyEventServiceAOImpl(irodsAccount, publicationContext); + } + +} diff --git a/dummy-event-service-impl/src/main/java/org/irods/jargon/dataone/events/impl/dummy/package-info.java b/dummy-event-service-impl/src/main/java/org/irods/jargon/dataone/events/impl/dummy/package-info.java new file mode 100644 index 0000000..57f8956 --- /dev/null +++ b/dummy-event-service-impl/src/main/java/org/irods/jargon/dataone/events/impl/dummy/package-info.java @@ -0,0 +1,6 @@ +/** + * Dummy impl of an events service + * @author mconway + * + */ +package org.irods.jargon.dataone.events.impl.dummy; \ No newline at end of file diff --git a/dummy-event-service-impl/src/main/resources/.gitinclude b/dummy-event-service-impl/src/main/resources/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/dummy-event-service-impl/src/test/java/.gitinclude b/dummy-event-service-impl/src/test/java/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/dummy-event-service-impl/src/test/resources/.gitinclude b/dummy-event-service-impl/src/test/resources/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/dummy-event-service-impl/src/test/resources/log4j.properties b/dummy-event-service-impl/src/test/resources/log4j.properties new file mode 100644 index 0000000..0228b8f --- /dev/null +++ b/dummy-event-service-impl/src/test/resources/log4j.properties @@ -0,0 +1,9 @@ +# Set root logger level and appender +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 diff --git a/dummy-pid-service-impl/pom.xml b/dummy-pid-service-impl/pom.xml new file mode 100644 index 0000000..9c05238 --- /dev/null +++ b/dummy-pid-service-impl/pom.xml @@ -0,0 +1,53 @@ + + + 4.0.0 + dummy-pid-service-impl + + org.irods + dfc-dataone + 4.2.1.0-SNAPSHOT + + jar + Pid service dummy implementation for testing purposes + + + org.irods.jargon + jargon-core + ${project.version} + + + + junit + junit + test + + + org.slf4j + slf4j-api + + + log4j + log4j + + + org.slf4j + slf4j-log4j12 + + + org.mockito + mockito-all + + + org.irods + pid-service-api + ${project.version} + + + org.irods + dataone-utils + ${project.version} + + + diff --git a/dummy-pid-service-impl/src/main/java/.gitinclude b/dummy-pid-service-impl/src/main/java/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/dummy-pid-service-impl/src/main/java/org/irods/jargon/dataone/pidservice/impl/dummy/DummyPidServiceAOImpl.java b/dummy-pid-service-impl/src/main/java/org/irods/jargon/dataone/pidservice/impl/dummy/DummyPidServiceAOImpl.java new file mode 100644 index 0000000..4833865 --- /dev/null +++ b/dummy-pid-service-impl/src/main/java/org/irods/jargon/dataone/pidservice/impl/dummy/DummyPidServiceAOImpl.java @@ -0,0 +1,32 @@ +package org.irods.jargon.dataone.pidservice.impl.dummy; + +import org.dataone.service.types.v1.Identifier; +import org.irods.jargon.core.connection.IRODSAccount; +import org.irods.jargon.core.exception.JargonException; +import org.irods.jargon.core.pub.domain.DataObject; +import org.irods.jargon.dataone.configuration.PublicationContext; +import org.irods.jargon.pid.pidservice.AbstractUniqueIdAO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DummyPidServiceAOImpl extends AbstractUniqueIdAO { + + public static final Logger log = LoggerFactory.getLogger(DummyPidServiceAOImpl.class); + + public DummyPidServiceAOImpl(IRODSAccount irodsAccount, PublicationContext publicationContext) { + super(irodsAccount, publicationContext); + } + + @Override + public Identifier getIdentifierFromDataObject(DataObject dataObject) throws JargonException { + Identifier id = new Identifier(); + id.setValue(new String("http://handle/dummy/" + String.valueOf(System.currentTimeMillis()))); + return id; + } + + @Override + public DataObject getDataObjectFromIdentifier(Identifier identifier) throws JargonException { + return new DataObject(); + } + +} diff --git a/dummy-pid-service-impl/src/main/java/org/irods/jargon/dataone/pidservice/impl/dummy/DummyPidServiceFactory.java b/dummy-pid-service-impl/src/main/java/org/irods/jargon/dataone/pidservice/impl/dummy/DummyPidServiceFactory.java new file mode 100644 index 0000000..413e5a6 --- /dev/null +++ b/dummy-pid-service-impl/src/main/java/org/irods/jargon/dataone/pidservice/impl/dummy/DummyPidServiceFactory.java @@ -0,0 +1,37 @@ +/** + * + */ +package org.irods.jargon.dataone.pidservice.impl.dummy; + +import org.irods.jargon.core.connection.IRODSAccount; +import org.irods.jargon.dataone.configuration.PublicationContext; +import org.irods.jargon.pid.pidservice.AbstractDataOnePidFactory; +import org.irods.jargon.pid.pidservice.UniqueIdAO; + +/** + * @author mcc + * + */ +public class DummyPidServiceFactory extends AbstractDataOnePidFactory { + + /** + * + */ + public DummyPidServiceFactory() { + } + + /* + * (non-Javadoc) + * + * @see + * org.irods.jargon.pid.pidservice.AbstractDataOnePidFactory#instance(org. + * irods.jargon.dataone.configuration.PublicationContext, + * org.irods.jargon.core.connection.IRODSAccount) + */ + @Override + public UniqueIdAO instance(PublicationContext publicationContext, IRODSAccount irodsAccount) { + + return new DummyPidServiceAOImpl(irodsAccount, publicationContext); + } + +} diff --git a/dummy-pid-service-impl/src/main/java/org/irods/jargon/dataone/pidservice/impl/dummy/package-info.java b/dummy-pid-service-impl/src/main/java/org/irods/jargon/dataone/pidservice/impl/dummy/package-info.java new file mode 100644 index 0000000..20b876f --- /dev/null +++ b/dummy-pid-service-impl/src/main/java/org/irods/jargon/dataone/pidservice/impl/dummy/package-info.java @@ -0,0 +1,8 @@ +/** + * + */ +/** + * @author mconway + * Dummy implementation of a pid service + */ +package org.irods.jargon.dataone.pidservice.impl.dummy; \ No newline at end of file diff --git a/dummy-pid-service-impl/src/main/resources/.gitinclude b/dummy-pid-service-impl/src/main/resources/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/dummy-pid-service-impl/src/test/java/.gitinclude b/dummy-pid-service-impl/src/test/java/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/dummy-pid-service-impl/src/test/resources/.gitinclude b/dummy-pid-service-impl/src/test/resources/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/dummy-repo-service-impl/pom.xml b/dummy-repo-service-impl/pom.xml new file mode 100644 index 0000000..e3c4338 --- /dev/null +++ b/dummy-repo-service-impl/pom.xml @@ -0,0 +1,53 @@ + + + 4.0.0 + dummy-repo-service-impl + + org.irods + dfc-dataone + 4.2.1.0-SNAPSHOT + + jar + Repo service dummy implementation for testing purposes + + + org.irods.jargon + jargon-core + ${project.version} + + + + junit + junit + test + + + org.slf4j + slf4j-api + + + log4j + log4j + + + org.slf4j + slf4j-log4j12 + + + org.mockito + mockito-all + + + org.irods + dataone-utils + ${project.version} + + + org.irods + repo-service-api + ${project.version} + + + diff --git a/dummy-repo-service-impl/src/main/java/.gitinclude b/dummy-repo-service-impl/src/main/java/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/dummy-repo-service-impl/src/main/java/org/irods/jargon/dataone/repo/impl/dummy/DummyRepoServiceFactory.java b/dummy-repo-service-impl/src/main/java/org/irods/jargon/dataone/repo/impl/dummy/DummyRepoServiceFactory.java new file mode 100644 index 0000000..bc9a807 --- /dev/null +++ b/dummy-repo-service-impl/src/main/java/org/irods/jargon/dataone/repo/impl/dummy/DummyRepoServiceFactory.java @@ -0,0 +1,37 @@ +/** + * + */ +package org.irods.jargon.dataone.repo.impl.dummy; + +import org.irods.jargon.core.connection.IRODSAccount; +import org.irods.jargon.dataone.configuration.PublicationContext; +import org.irods.jargon.dataone.reposervice.AbstractDataOneRepoFactory; +import org.irods.jargon.dataone.reposervice.DataOneRepoServiceAO; + +/** + * @author mcc + * + */ +public class DummyRepoServiceFactory extends AbstractDataOneRepoFactory { + + /** + * + */ + public DummyRepoServiceFactory() { + // TODO Auto-generated constructor stub + } + + /* + * (non-Javadoc) + * + * @see + * org.irods.jargon.dataone.reposervice.AbstractDataOneRepoFactory#instance( + * org.irods.jargon.dataone.configuration.PublicationContext, + * org.irods.jargon.core.connection.IRODSAccount) + */ + @Override + public DataOneRepoServiceAO instance(PublicationContext publicationContext, IRODSAccount irodsAccount) { + return new DummyRepoServiceImpl(irodsAccount, publicationContext); + } + +} diff --git a/dummy-repo-service-impl/src/main/java/org/irods/jargon/dataone/repo/impl/dummy/DummyRepoServiceImpl.java b/dummy-repo-service-impl/src/main/java/org/irods/jargon/dataone/repo/impl/dummy/DummyRepoServiceImpl.java new file mode 100644 index 0000000..a5de89f --- /dev/null +++ b/dummy-repo-service-impl/src/main/java/org/irods/jargon/dataone/repo/impl/dummy/DummyRepoServiceImpl.java @@ -0,0 +1,59 @@ +/** + * + */ +package org.irods.jargon.dataone.repo.impl.dummy; + +import java.util.Date; +import java.util.List; + +import org.dataone.service.types.v1.Identifier; +import org.dataone.service.types.v1.ObjectFormatIdentifier; +import org.irods.jargon.core.connection.IRODSAccount; +import org.irods.jargon.core.exception.FileNotFoundException; +import org.irods.jargon.core.exception.JargonException; +import org.irods.jargon.core.pub.domain.DataObject; +import org.irods.jargon.dataone.configuration.PublicationContext; +import org.irods.jargon.dataone.reposervice.AbstractDataOneRepoServiceAO; +import org.irods.jargon.dataone.reposervice.DataObjectListResponse; + +/** + * @author mcc + * + */ +public class DummyRepoServiceImpl extends AbstractDataOneRepoServiceAO { + + public DummyRepoServiceImpl(IRODSAccount irodsAccount, PublicationContext publicationContext) { + super(irodsAccount, publicationContext); + } + + /* + * (non-Javadoc) + * + * @see org.irods.jargon.dataone.repo.reposervice.AbstractRepoServiceAO# + * getListOfDataoneExposedDataObjects(java.util.Date, java.util.Date, + * org.dataone.service.types.v1.ObjectFormatIdentifier, java.lang.Boolean, + * java.lang.Integer, java.lang.Integer) + */ + @Override + public DataObjectListResponse getListOfDataoneExposedDataObjects(Date arg0, Date arg1, ObjectFormatIdentifier arg2, + Boolean arg3, Integer arg4, Integer arg5) throws JargonException { + return new DataObjectListResponse(); + } + + @Override + public List getListOfDataoneExposedIdentifiers() throws JargonException { + // FIXME: narrow down the needed public methods + return null; + } + + @Override + public Date getLastModifiedDateForDataObject(DataObject dataObject) throws JargonException { + return new Date(); + } + + @Override + public String dataObjectFormat(DataObject dataObject) throws FileNotFoundException, JargonException { + return ""; + } + +} diff --git a/dummy-repo-service-impl/src/main/java/org/irods/jargon/dataone/repo/impl/dummy/package-info.java b/dummy-repo-service-impl/src/main/java/org/irods/jargon/dataone/repo/impl/dummy/package-info.java new file mode 100644 index 0000000..856c113 --- /dev/null +++ b/dummy-repo-service-impl/src/main/java/org/irods/jargon/dataone/repo/impl/dummy/package-info.java @@ -0,0 +1,7 @@ +/** + * Dummy impl of a repo service + * + * @author mconway + * + */ +package org.irods.jargon.dataone.repo.impl.dummy; \ No newline at end of file diff --git a/dummy-repo-service-impl/src/main/resources/.gitinclude b/dummy-repo-service-impl/src/main/resources/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/dummy-repo-service-impl/src/test/java/.gitinclude b/dummy-repo-service-impl/src/test/java/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/dummy-repo-service-impl/src/test/resources/.gitinclude b/dummy-repo-service-impl/src/test/resources/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/dummy-repo-service-impl/src/test/resources/log4j.properties b/dummy-repo-service-impl/src/test/resources/log4j.properties new file mode 100644 index 0000000..0228b8f --- /dev/null +++ b/dummy-repo-service-impl/src/test/resources/log4j.properties @@ -0,0 +1,9 @@ +# Set root logger level and appender +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 diff --git a/eclipse-formatting.xml b/eclipse-formatting.xml new file mode 100644 index 0000000..d2776ff --- /dev/null +++ b/eclipse-formatting.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/event-service-api/pom.xml b/event-service-api/pom.xml new file mode 100644 index 0000000..224178c --- /dev/null +++ b/event-service-api/pom.xml @@ -0,0 +1,54 @@ + + + 4.0.0 + event-service-api + + org.irods + dfc-dataone + 4.2.1.0-SNAPSHOT + + jar + Event service API + + + org.irods.jargon + jargon-core + ${project.version} + + + + junit + junit + test + + + org.slf4j + slf4j-api + + + log4j + log4j + + + org.slf4j + slf4j-log4j12 + + + org.mockito + mockito-all + + + org.dataone + d1_libclient_java + + + org.irods + dataone-utils + ${project.version} + + + + + diff --git a/event-service-api/src/main/java/.gitinclude b/event-service-api/src/main/java/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/event-service-api/src/main/java/org/irods/jargon/dataone/events/AbstractDataOneEventServiceFactory.java b/event-service-api/src/main/java/org/irods/jargon/dataone/events/AbstractDataOneEventServiceFactory.java new file mode 100644 index 0000000..170e758 --- /dev/null +++ b/event-service-api/src/main/java/org/irods/jargon/dataone/events/AbstractDataOneEventServiceFactory.java @@ -0,0 +1,29 @@ +/** + * + */ +package org.irods.jargon.dataone.events; + +import org.irods.jargon.core.connection.IRODSAccount; +import org.irods.jargon.dataone.configuration.PublicationContext; + +/** + * Factory to create event services + * + * @author mcc + * + */ +public abstract class AbstractDataOneEventServiceFactory implements DataOneEventServiceFactory { + + /** + * Create an instance of the pid service + * + * @param publicationContext + * {@link PublicationContext} with configuration information + * @param irodsAccount + * {@link IRODSAccount} associated with the instance + * @return + */ + @Override + public abstract DataOneEventServiceAO instance(PublicationContext publicationContext, IRODSAccount irodsAccount); + +} diff --git a/event-service-api/src/main/java/org/irods/jargon/dataone/events/AbstractEventServiceAO.java b/event-service-api/src/main/java/org/irods/jargon/dataone/events/AbstractEventServiceAO.java new file mode 100644 index 0000000..27d18af --- /dev/null +++ b/event-service-api/src/main/java/org/irods/jargon/dataone/events/AbstractEventServiceAO.java @@ -0,0 +1,63 @@ +/** + * + */ +package org.irods.jargon.dataone.events; + +import java.util.Date; + +import org.dataone.service.exceptions.ServiceFailure; +import org.dataone.service.types.v1.Event; +import org.dataone.service.types.v1.Identifier; +import org.dataone.service.types.v1.Log; +import org.irods.jargon.core.connection.IRODSAccount; +import org.irods.jargon.core.exception.InvalidArgumentException; +import org.irods.jargon.core.exception.JargonException; +import org.irods.jargon.dataone.configuration.PublicationContext; +import org.irods.jargon.dataone.plugin.AbstractDataOnePlugin; + +/** + * Abstract superclass for the event service that accepts context and + * configuration information from the member node service + * + * @author mconway + * + */ +public abstract class AbstractEventServiceAO extends AbstractDataOnePlugin implements DataOneEventServiceAO { + + /** + * Default constructor with required values + * + * @param irodsAccount + * {@link IRODSAccount} for the current iRODS connection + * @param publicationContext + * {@link PublicationContext} with configuration and other + * information + */ + public AbstractEventServiceAO(IRODSAccount irodsAccount, PublicationContext publicationContext) { + super(irodsAccount, publicationContext); + } + + /* + * (non-Javadoc) + * + * @see + * org.irods.jargon.dataone.events.EventServiceAO#getLogs(java.util.Date, + * java.util.Date, org.irods.jargon.dataone.events.EventsEnum, + * java.lang.String, int, int) + */ + @Override + public abstract Log getLogs(Date fromDate, Date toDate, EventsEnum event, String pidFilter, int startIdx, + int count); + + /* + * (non-Javadoc) + * + * @see + * org.irods.jargon.dataone.events.EventServiceAO#recordEvent(org.dataone + * .service.types.v1.Event, org.dataone.service.types.v1.Identifier, + * java.lang.String) + */ + @Override + public abstract void recordEvent(Event event, Identifier id, String description) + throws InvalidArgumentException, JargonException, ServiceFailure; +} diff --git a/event-service-api/src/main/java/org/irods/jargon/dataone/events/DataOneEventServiceAO.java b/event-service-api/src/main/java/org/irods/jargon/dataone/events/DataOneEventServiceAO.java new file mode 100644 index 0000000..0f24fe9 --- /dev/null +++ b/event-service-api/src/main/java/org/irods/jargon/dataone/events/DataOneEventServiceAO.java @@ -0,0 +1,47 @@ +package org.irods.jargon.dataone.events; + +import java.util.Date; + +import org.dataone.service.exceptions.ServiceFailure; +import org.dataone.service.types.v1.Event; +import org.dataone.service.types.v1.Identifier; +import org.dataone.service.types.v1.Log; +import org.irods.jargon.core.exception.InvalidArgumentException; +import org.irods.jargon.core.exception.JargonException; + +/** + * API for accessing event registry for published objects + * + * @author mconway + * + */ +public interface DataOneEventServiceAO { + + /** + * Retrieve logs from the event registry given the parameters + * + * @param fromDate + * @param toDate + * @param event + * @param pidFilter + * @param startIdx + * @param count + * @return {@link Log} with the log data + */ + public Log getLogs(Date fromDate, Date toDate, EventsEnum event, + String pidFilter, int startIdx, int count); + + /** + * Add a given event to the log data + * + * @param event + * @param id + * @param description + * @throws InvalidArgumentException + * @throws JargonException + * @throws ServiceFailure + */ + public void recordEvent(Event event, Identifier id, String description) + throws InvalidArgumentException, JargonException, ServiceFailure; + +} diff --git a/event-service-api/src/main/java/org/irods/jargon/dataone/events/DataOneEventServiceFactory.java b/event-service-api/src/main/java/org/irods/jargon/dataone/events/DataOneEventServiceFactory.java new file mode 100644 index 0000000..db9134f --- /dev/null +++ b/event-service-api/src/main/java/org/irods/jargon/dataone/events/DataOneEventServiceFactory.java @@ -0,0 +1,19 @@ +/** + * + */ +package org.irods.jargon.dataone.events; + +import org.irods.jargon.core.connection.IRODSAccount; +import org.irods.jargon.dataone.configuration.PublicationContext; + +/** + * Factory interface that will discover and create the event service + * + * @author mconway + * + */ +public interface DataOneEventServiceFactory { + + public DataOneEventServiceAO instance(PublicationContext publicationContext, IRODSAccount irodsAccount); + +} diff --git a/event-service-api/src/main/java/org/irods/jargon/dataone/events/EventLoggingException.java b/event-service-api/src/main/java/org/irods/jargon/dataone/events/EventLoggingException.java new file mode 100644 index 0000000..7a1a854 --- /dev/null +++ b/event-service-api/src/main/java/org/irods/jargon/dataone/events/EventLoggingException.java @@ -0,0 +1,68 @@ +/** + * + */ +package org.irods.jargon.dataone.events; + +import org.irods.jargon.core.exception.JargonException; + +/** + * Exception in event logging + * + * @author mcc + * + */ +public class EventLoggingException extends JargonException { + + /** + * + */ + private static final long serialVersionUID = -5743883673770774132L; + + /** + * @param message + */ + public EventLoggingException(String message) { + super(message); + } + + /** + * @param message + * @param cause + */ + public EventLoggingException(String message, Throwable cause) { + super(message, cause); + } + + /** + * @param cause + */ + public EventLoggingException(Throwable cause) { + super(cause); + } + + /** + * @param message + * @param cause + * @param underlyingIRODSExceptionCode + */ + public EventLoggingException(String message, Throwable cause, int underlyingIRODSExceptionCode) { + super(message, cause, underlyingIRODSExceptionCode); + } + + /** + * @param cause + * @param underlyingIRODSExceptionCode + */ + public EventLoggingException(Throwable cause, int underlyingIRODSExceptionCode) { + super(cause, underlyingIRODSExceptionCode); + } + + /** + * @param message + * @param underlyingIRODSExceptionCode + */ + public EventLoggingException(String message, int underlyingIRODSExceptionCode) { + super(message, underlyingIRODSExceptionCode); + } + +} diff --git a/event-service-api/src/main/java/org/irods/jargon/dataone/events/EventsEnum.java b/event-service-api/src/main/java/org/irods/jargon/dataone/events/EventsEnum.java new file mode 100644 index 0000000..b40189b --- /dev/null +++ b/event-service-api/src/main/java/org/irods/jargon/dataone/events/EventsEnum.java @@ -0,0 +1,78 @@ +package org.irods.jargon.dataone.events; + +import org.dataone.service.types.v1.Event; + +// Use this class to convert iRODS/Databook type events to DataONE events +public enum EventsEnum { + FAILED(Event.REPLICATION_FAILED, "failed"), CREATE(Event.CREATE, "put"), READ( + Event.READ, "get"), UPDATE(Event.UPDATE, "overwrite"), DELETE( + Event.DELETE, "delete"), REPLICATE(Event.REPLICATE, "replicate"), SYNCHRONIZATION_FAILED( + Event.SYNCHRONIZATION_FAILED, "synch_failure"), ; + // REPLICATION_FAILED(),; not supported yet + + private String internalEvent; + private Event dataoneEvent; + + EventsEnum(final Event dataoneEvent, final String databookEvent) { + this.internalEvent = databookEvent; + this.dataoneEvent = dataoneEvent; + } + + public Event getDataoneEvent() { + return dataoneEvent; + } + + public void setDataoneEvent(final Event dataoneEvent) { + this.dataoneEvent = dataoneEvent; + } + + public String getInternalEvent() { + return internalEvent; + } + + public void setInternalEvent(final String internalEvent) { + this.internalEvent = internalEvent; + } + + public static EventsEnum valueOfFromDataOne(final Event e) { + switch (e) { + case CREATE: + return CREATE; + case READ: + return READ; + case UPDATE: + return UPDATE; + case DELETE: + return DELETE; + case REPLICATE: + return REPLICATE; + case SYNCHRONIZATION_FAILED: + return SYNCHRONIZATION_FAILED; + // case REPLICATION_FAILED: not supported yet + default: + return READ; + } + } + + public static EventsEnum valueFromInternal(final String e) { + if (e.equals("put") || e.equals("data object put")) { + return CREATE; + } else if (e.equals("get") || e.equals("data object get")) { + return READ; + } else if (e.equals("overwrite") || e.equals("data object overwrite")) { + return UPDATE; + } else if (e.equals("delete") || e.equals("data object delete")) { + return DELETE; + } else if (e.equals("replicate") || e.equals("data object replicate")) { + return REPLICATE; + } else if (e.equals("synch_failure") + || e.equals("data object synch_failure")) { + return SYNCHRONIZATION_FAILED; + // else if (e.equals("?")) + // return REPLICATION_FAILED; not supported yet + } else { + return FAILED; + } + } + +} \ No newline at end of file diff --git a/src/main/java/org/irods/jargon/dataone/events/package-info.java b/event-service-api/src/main/java/org/irods/jargon/dataone/events/package-info.java similarity index 94% rename from src/main/java/org/irods/jargon/dataone/events/package-info.java rename to event-service-api/src/main/java/org/irods/jargon/dataone/events/package-info.java index 9234856..ccfc78b 100644 --- a/src/main/java/org/irods/jargon/dataone/events/package-info.java +++ b/event-service-api/src/main/java/org/irods/jargon/dataone/events/package-info.java @@ -1,5 +1,5 @@ /** - * + * */ /** * @author lisa diff --git a/event-service-api/src/main/resources/.gitinclude b/event-service-api/src/main/resources/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/event-service-api/src/test/java/.gitinclude b/event-service-api/src/test/java/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/pid-service-api/pom.xml b/pid-service-api/pom.xml new file mode 100644 index 0000000..5a7907f --- /dev/null +++ b/pid-service-api/pom.xml @@ -0,0 +1,49 @@ + + + 4.0.0 + pid-service-api + + org.irods + dfc-dataone + 4.2.1.0-SNAPSHOT + + jar + PID service API + + + org.irods.jargon + jargon-core + ${project.version} + + + + junit + junit + test + + + org.slf4j + slf4j-api + + + log4j + log4j + + + org.slf4j + slf4j-log4j12 + + + org.dataone + d1_libclient_java + + + org.irods + dataone-utils + ${project.version} + + + + diff --git a/pid-service-api/src/main/java/.gitinclude b/pid-service-api/src/main/java/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/pid-service-api/src/main/java/org/irods/jargon/pid/pidservice/AbstractDataOnePidFactory.java b/pid-service-api/src/main/java/org/irods/jargon/pid/pidservice/AbstractDataOnePidFactory.java new file mode 100644 index 0000000..3177507 --- /dev/null +++ b/pid-service-api/src/main/java/org/irods/jargon/pid/pidservice/AbstractDataOnePidFactory.java @@ -0,0 +1,23 @@ +/** + * + */ +package org.irods.jargon.pid.pidservice; + +import org.irods.jargon.core.connection.IRODSAccount; +import org.irods.jargon.dataone.configuration.PublicationContext; + +/** + * Factory to create pid services + * + * @author mcc + * + */ +public abstract class AbstractDataOnePidFactory implements DataOnePidServiceFactory { + + /* (non-Javadoc) + * @see org.irods.jargon.pid.pidservice.DataOnePidFactory#instance(org.irods.jargon.dataone.configuration.PublicationContext, org.irods.jargon.core.connection.IRODSAccount) + */ + @Override + public abstract UniqueIdAO instance(PublicationContext publicationContext, IRODSAccount irodsAccount); + +} diff --git a/pid-service-api/src/main/java/org/irods/jargon/pid/pidservice/AbstractUniqueIdAO.java b/pid-service-api/src/main/java/org/irods/jargon/pid/pidservice/AbstractUniqueIdAO.java new file mode 100644 index 0000000..eeabf1b --- /dev/null +++ b/pid-service-api/src/main/java/org/irods/jargon/pid/pidservice/AbstractUniqueIdAO.java @@ -0,0 +1,55 @@ +/** + * + */ +package org.irods.jargon.pid.pidservice; + +import org.dataone.service.types.v1.Identifier; +import org.irods.jargon.core.connection.IRODSAccount; +import org.irods.jargon.core.exception.JargonException; +import org.irods.jargon.core.pub.domain.DataObject; +import org.irods.jargon.dataone.configuration.PublicationContext; +import org.irods.jargon.dataone.plugin.AbstractDataOnePlugin; + +/** + * Abstract superclass for a pid handler that will accept the provided context + * from the DataONE service when created by the discovery mechanism + * + * @author mconway + * + */ +public abstract class AbstractUniqueIdAO extends AbstractDataOnePlugin implements UniqueIdAO { + + /** + * Default constructor with required values + * + * @param irodsAccount + * {@link IRODSAccount} for the current iRODS connection + * @param publicationContext + * {@link PublicationContext} with configuration and other + * information + */ + public AbstractUniqueIdAO(IRODSAccount irodsAccount, PublicationContext publicationContext) { + super(irodsAccount, publicationContext); + } + + /* + * (non-Javadoc) + * + * @see + * org.irods.jargon.pid.pidservice.UniqueIdAO#getIdentifierFromDataObject + * (org.irods.jargon.core.pub.domain.DataObject) + */ + @Override + public abstract Identifier getIdentifierFromDataObject(DataObject dataObject) throws JargonException; + + /* + * (non-Javadoc) + * + * @see + * org.irods.jargon.pid.pidservice.UniqueIdAO#getDataObjectFromIdentifier + * (org.dataone.service.types.v1.Identifier) + */ + @Override + public abstract DataObject getDataObjectFromIdentifier(Identifier identifier) throws JargonException; + +} diff --git a/pid-service-api/src/main/java/org/irods/jargon/pid/pidservice/DataOnePidServiceFactory.java b/pid-service-api/src/main/java/org/irods/jargon/pid/pidservice/DataOnePidServiceFactory.java new file mode 100644 index 0000000..5889fe3 --- /dev/null +++ b/pid-service-api/src/main/java/org/irods/jargon/pid/pidservice/DataOnePidServiceFactory.java @@ -0,0 +1,19 @@ +package org.irods.jargon.pid.pidservice; + +import org.irods.jargon.core.connection.IRODSAccount; +import org.irods.jargon.dataone.configuration.PublicationContext; + +public interface DataOnePidServiceFactory { + + /** + * Create an instance of the pid service + * + * @param publicationContext + * {@link PublicationContext} with configuration information + * @param irodsAccount + * {@link IRODSAccount} associated with the instance + * @return + */ + UniqueIdAO instance(PublicationContext publicationContext, IRODSAccount irodsAccount); + +} \ No newline at end of file diff --git a/pid-service-api/src/main/java/org/irods/jargon/pid/pidservice/UniqueIdAO.java b/pid-service-api/src/main/java/org/irods/jargon/pid/pidservice/UniqueIdAO.java new file mode 100644 index 0000000..33877b6 --- /dev/null +++ b/pid-service-api/src/main/java/org/irods/jargon/pid/pidservice/UniqueIdAO.java @@ -0,0 +1,36 @@ +package org.irods.jargon.pid.pidservice; + +import org.dataone.service.types.v1.Identifier; +import org.irods.jargon.core.exception.JargonException; +import org.irods.jargon.core.pub.domain.DataObject; + +// Access object for unique identifiers that are associated with iRODS Data Objects + +public interface UniqueIdAO { + + // These methods are intended for future support of DataONE MN tiers > 1 + // public Identifier createNewIdentifier(); + // public Identifier createNewIdentifier(String identifier); + // public void deleteIdentifier(String identifier); + + /** + * Returns a DataONE Identifier object for the iRODS Data Object specified + * + * @param dataObject + * DataObject of iRODS Data Object associated with + * the identifier to be returned. + * @throws JargonException + */ + public Identifier getIdentifierFromDataObject(DataObject dataObject) throws JargonException; + + /** + * Returns an iRODS Data Object for the DataONE Identifier object specified + * + * @param identifier + * Identifier associated with the iRODS Data Object + * to be returned. + * @throws JargonException + */ + public DataObject getDataObjectFromIdentifier(Identifier identifier) throws JargonException; + +} diff --git a/pid-service-api/src/main/java/org/irods/jargon/pid/pidservice/package-info.java b/pid-service-api/src/main/java/org/irods/jargon/pid/pidservice/package-info.java new file mode 100644 index 0000000..5c92a2c --- /dev/null +++ b/pid-service-api/src/main/java/org/irods/jargon/pid/pidservice/package-info.java @@ -0,0 +1,7 @@ +/** + * Base API for processing persistent identifiers in a uniform, pluggable manner. + * + * @author mconway + * + */ +package org.irods.jargon.pid.pidservice; \ No newline at end of file diff --git a/pid-service-api/src/main/resources/.gitinclude b/pid-service-api/src/main/resources/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/pid-service-api/src/test/java/.gitinclude b/pid-service-api/src/test/java/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/pid-service-handle-impl/pom.xml b/pid-service-handle-impl/pom.xml new file mode 100644 index 0000000..084cdee --- /dev/null +++ b/pid-service-handle-impl/pom.xml @@ -0,0 +1,60 @@ + + + 4.0.0 + pid-service-handle-impl + Handle PID server impl + + org.irods + dfc-dataone + 4.2.1.0-SNAPSHOT + + jar + + + org.irods.jargon + jargon-core + ${project.version} + + + + junit + junit + test + + + org.slf4j + slf4j-api + + + log4j + log4j + + + org.slf4j + slf4j-log4j12 + + + org.mockito + mockito-all + + + handle + org.handle + system + 1.0.0 + ${project.basedir}/src/main/lib/handle.jar + + + org.irods + pid-service-api + ${project.version} + + + org.irods + dataone-utils + ${project.version} + + + diff --git a/pid-service-handle-impl/src/main/java/.gitinclude b/pid-service-handle-impl/src/main/java/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/pid-service-handle-impl/src/main/java/org/irods/jargon/dataone/id/handle/HandleListerRunnable.java b/pid-service-handle-impl/src/main/java/org/irods/jargon/dataone/id/handle/HandleListerRunnable.java new file mode 100644 index 0000000..47acfbf --- /dev/null +++ b/pid-service-handle-impl/src/main/java/org/irods/jargon/dataone/id/handle/HandleListerRunnable.java @@ -0,0 +1,178 @@ +package org.irods.jargon.dataone.id.handle; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.PrivateKey; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +import net.handle.hdllib.AbstractMessage; +import net.handle.hdllib.AbstractResponse; +import net.handle.hdllib.HandleException; +import net.handle.hdllib.HandleResolver; +import net.handle.hdllib.ListHandlesRequest; +import net.handle.hdllib.ListHandlesResponse; +import net.handle.hdllib.PublicKeyAuthenticationInfo; +import net.handle.hdllib.ResolutionRequest; +import net.handle.hdllib.ResponseMessageCallback; +import net.handle.hdllib.ServerInfo; +import net.handle.hdllib.SiteInfo; +import net.handle.hdllib.Util; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +// ./hdl-list -s 0.NA/11333 300 ../../svr_1/admpriv.bin 11333 +public class HandleListerRunnable implements Runnable, ResponseMessageCallback { + + HandleResolver resolver = new HandleResolver(); + private final String authHandle; + private final String authIndex; + private final String privateKey; + private final String namingAuthority; + boolean showValues = true; + // private Queue> results; + private LinkedList> results; + private final List handles; + private Logger log = LoggerFactory.getLogger(this.getClass()); + + public HandleListerRunnable( + // Queue> queue, + final LinkedList> queue, final String authHandle, + final String authIndex, final String privateKey, + final String namingAuthority) { + + // TODO: check for valid args here + log.info("in HandleListerRunnable"); + results = queue; + this.authHandle = authHandle; + this.authIndex = authIndex; + this.privateKey = privateKey; + this.namingAuthority = namingAuthority; + handles = new ArrayList(); + + // byte[] key = null; + // FileInputStream fs = null; + // //InputStream fs = null; + // try { + // //fs = + // getClass().getClassLoader().getResourceAsStream(this.privateKey); + // File f = new File(this.privateKey); + // fs = new FileInputStream(f); + // key = new byte[(int)f.length()]; + // int n=0; + // while(n getHandles() { + // return this.handles; + // } + +} diff --git a/pid-service-handle-impl/src/main/java/org/irods/jargon/dataone/id/handle/UniqueIdAOHandleImpl.java b/pid-service-handle-impl/src/main/java/org/irods/jargon/dataone/id/handle/UniqueIdAOHandleImpl.java new file mode 100644 index 0000000..6865ec4 --- /dev/null +++ b/pid-service-handle-impl/src/main/java/org/irods/jargon/dataone/id/handle/UniqueIdAOHandleImpl.java @@ -0,0 +1,130 @@ +package org.irods.jargon.dataone.id.handle; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import org.dataone.service.types.v1.Identifier; +import org.irods.jargon.core.exception.FileNotFoundException; +import org.irods.jargon.core.exception.JargonException; +import org.irods.jargon.core.pub.DataObjectAO; +import org.irods.jargon.core.pub.domain.DataObject; +import org.irods.jargon.core.service.AbstractJargonService; +import org.irods.jargon.pid.pidservice.UniqueIdAO; +//import org.irods.jargon.dataprofile.DataProfile; +//import org.irods.jargon.dataprofile.DataProfileService; +//import org.irods.jargon.dataprofile.DataProfileServiceImpl; +//import org.irods.jargon.dataprofile.DataTypeResolutionService; +//import org.irods.jargon.dataprofile.DataTypeResolutionServiceImpl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class UniqueIdAOHandleImpl extends AbstractJargonService implements UniqueIdAO { + + private Properties properties; + private String propertiesFilename = "d1client.properties"; + private Logger log = LoggerFactory.getLogger(this.getClass()); + + @Override + public DataObject getDataObjectFromIdentifier(final Identifier identifier) + throws JargonException, FileNotFoundException { + + DataObject dataObject = null; + log.info("retrieving irods data object id from identifier: {}", identifier.getValue()); + long dataObjectId = getDataObjectIdFromDataOneIdentifier(identifier); + log.info("got id: {}", dataObjectId); + + if (dataObjectId < 0) { + throw new FileNotFoundException(""); + } + + try { + + DataObjectAO dataObjectAO = irodsAccessObjectFactory.getDataObjectAO(irodsAccount); + log.info("got dataObjectAO: {}", dataObjectAO.toString()); + // Find iRODS object here from Identifier + dataObject = dataObjectAO.findById(new Long(dataObjectId).intValue()); + if (dataObject != null) { + log.info("found iRODS file: {}", dataObject.getAbsolutePath()); + } else { + log.warn("did not find data object for id={}", dataObjectId); + } + + // } catch (Exception e) { + // log.warn("Cannot access iRODS object for id={}", dataObjectId); + // throw e; + } finally { + irodsAccessObjectFactory.closeSessionAndEatExceptions(); + } + + return dataObject; + } + + @Override + public Identifier getIdentifierFromDataObject(final DataObject dataObject) throws JargonException { + + if (dataObject == null) { + log.error("getIdentifierFromDataObject: dataObject is null"); + throw new JargonException("dataObject is null"); + } + Identifier identifier = new Identifier(); + + String prefix = getHandlePrefix(); + if (prefix == null) { + log.error("getIdentifierFromDataObject: prefix is null"); + throw new JargonException("prefix is null"); + } + String objectId = String.valueOf(dataObject.getId()); + + identifier.setValue(prefix + "/" + objectId); + + return identifier; + } + + public long getDataObjectIdFromDataOneIdentifier(final Identifier pid) { + + int idIdx = pid.getValue().indexOf("/") + 1; + long dataObjectId; + try { + dataObjectId = Long.parseLong(pid.getValue().substring(idIdx)); + } catch (NumberFormatException e) { + // set to catch illegal object identifiers for iRODS MN + dataObjectId = -1; + } + + log.info("getDataObjectIdFromDataOneIdentifier: returning data object id: {}", dataObjectId); + return dataObjectId; + } + + public String getHandlePrefix() throws JargonException { + String prefix = null; + + prefix = properties.getProperty("irods.dataone.handle.prefix"); + + return prefix; + } + + private void loadProperties() { + properties = new Properties(); + InputStream input = null; + input = getClass().getClassLoader().getResourceAsStream(propertiesFilename); + + // load a properties file + try { + properties.load(input); + } catch (IOException e) { + log.error("Cannot load Member Node properties file: {}", propertiesFilename); + log.error("IOException", e); + properties = new Properties(); + } finally { + if (input != null) { + try { + input.close(); + } catch (IOException e) { + // do nothing + } + } + } + } + +} diff --git a/pid-service-handle-impl/src/main/java/org/irods/jargon/dataone/id/handle/UniqueIdAOHandleInMetadataImpl.java b/pid-service-handle-impl/src/main/java/org/irods/jargon/dataone/id/handle/UniqueIdAOHandleInMetadataImpl.java new file mode 100644 index 0000000..65db503 --- /dev/null +++ b/pid-service-handle-impl/src/main/java/org/irods/jargon/dataone/id/handle/UniqueIdAOHandleInMetadataImpl.java @@ -0,0 +1,135 @@ +package org.irods.jargon.dataone.id.handle; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import org.dataone.service.types.v1.Identifier; +import org.irods.jargon.core.connection.IRODSAccount; +import org.irods.jargon.core.exception.FileNotFoundException; +import org.irods.jargon.core.exception.JargonException; +import org.irods.jargon.core.pub.DataObjectAO; +import org.irods.jargon.core.pub.domain.DataObject; +import org.irods.jargon.dataone.configuration.PublicationContext; +import org.irods.jargon.pid.pidservice.AbstractUniqueIdAO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class UniqueIdAOHandleInMetadataImpl extends AbstractUniqueIdAO { + + private Properties properties; + private String propertiesFilename = "d1client.properties"; + private Logger log = LoggerFactory.getLogger(this.getClass()); + + public UniqueIdAOHandleInMetadataImpl(IRODSAccount irodsAccount, PublicationContext publicationContext) { + super(irodsAccount, publicationContext); + } + + @Override + public DataObject getDataObjectFromIdentifier(final Identifier identifier) + throws JargonException, FileNotFoundException { + + DataObject dataObject = null; + log.info("retrieving irods data object id from identifier: {}", identifier.getValue()); + long dataObjectId = getDataObjectIdFromDataOneIdentifier(identifier); + log.info("got id: {}", dataObjectId); + + // DataObjectAO.findDomainByMetadataQuery + // returns List + + if (dataObjectId < 0) { + throw new FileNotFoundException(""); + } + + try { + + DataObjectAO dataObjectAO = this.getPublicationContext().getIrodsAccessObjectFactory() + .getDataObjectAO(getIrodsAccount()); + log.info("got dataObjectAO: {}", dataObjectAO.toString()); + // Find iRODS object here from Identifier + dataObject = dataObjectAO.findById(new Long(dataObjectId).intValue()); + + if (dataObject != null) { + log.info("found iRODS file: {}", dataObject.getAbsolutePath()); + } else { + log.warn("did not find data object for id={}", dataObjectId); + } + + // } catch (Exception e) { + // log.warn("Cannot access iRODS object for id={}", dataObjectId); + // throw e; + } finally { + this.getPublicationContext().getIrodsAccessObjectFactory().closeSessionAndEatExceptions(); + } + + return dataObject; + } + + @Override + public Identifier getIdentifierFromDataObject(final DataObject dataObject) throws JargonException { + + if (dataObject == null) { + log.error("getIdentifierFromDataObject: dataObject is null"); + throw new JargonException("dataObject is null"); + } + Identifier identifier = new Identifier(); + + String prefix = getHandlePrefix(); + if (prefix == null) { + log.error("getIdentifierFromDataObject: prefix is null"); + throw new JargonException("prefix is null"); + } + String objectId = String.valueOf(dataObject.getId()); + + identifier.setValue(prefix + "/" + objectId); + + return identifier; + } + + public long getDataObjectIdFromDataOneIdentifier(final Identifier pid) { + + int idIdx = pid.getValue().indexOf("/") + 1; + long dataObjectId; + try { + dataObjectId = Long.parseLong(pid.getValue().substring(idIdx)); + } catch (NumberFormatException e) { + // set to catch illegal object identifiers for iRODS MN + dataObjectId = -1; + } + + log.info("getDataObjectIdFromDataOneIdentifier: returning data object id: {}", dataObjectId); + return dataObjectId; + } + + public String getHandlePrefix() throws JargonException { + String prefix = null; + + prefix = properties.getProperty("irods.dataone.handle.prefix"); + + return prefix; + } + + private void loadProperties() { + properties = new Properties(); + InputStream input = null; + + input = getClass().getClassLoader().getResourceAsStream(this.propertiesFilename); + + // load a properties file + try { + properties.load(input); + } catch (IOException e) { + log.error("Cannot load Member Node properties file: {}", propertiesFilename, e); + properties = new Properties(); + } finally { + if (input != null) { + try { + input.close(); + } catch (IOException e) { + // do nothing + } + } + } + } + +} diff --git a/pid-service-handle-impl/src/main/java/org/irods/jargon/dataone/id/handle/package-info.java b/pid-service-handle-impl/src/main/java/org/irods/jargon/dataone/id/handle/package-info.java new file mode 100644 index 0000000..d57b6fc --- /dev/null +++ b/pid-service-handle-impl/src/main/java/org/irods/jargon/dataone/id/handle/package-info.java @@ -0,0 +1,9 @@ +/** + * + */ +/** + * @author lisa + * Handle implemementation of PID + * + */ +package org.irods.jargon.dataone.id.handle; \ No newline at end of file diff --git a/pid-service-handle-impl/src/main/lib/cnriutil.jar b/pid-service-handle-impl/src/main/lib/cnriutil.jar new file mode 100644 index 0000000..211a869 Binary files /dev/null and b/pid-service-handle-impl/src/main/lib/cnriutil.jar differ diff --git a/pid-service-handle-impl/src/main/lib/handle.jar b/pid-service-handle-impl/src/main/lib/handle.jar new file mode 100644 index 0000000..aed4710 Binary files /dev/null and b/pid-service-handle-impl/src/main/lib/handle.jar differ diff --git a/pid-service-handle-impl/src/main/resources/.gitinclude b/pid-service-handle-impl/src/main/resources/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/pid-service-handle-impl/src/test/java/.gitinclude b/pid-service-handle-impl/src/test/java/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/pid-service-handle-impl/src/test/resources/.gitinclude b/pid-service-handle-impl/src/test/resources/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/pom.xml b/pom.xml index f8e0f55..66193d1 100644 --- a/pom.xml +++ b/pom.xml @@ -2,22 +2,18 @@ 4.0.0 - org.irods dfc-dataone - 0.0.1-SNAPSHOT - war - dfc-dataone - REST API for iRODS DataONE Member Node Implementation based on Jargon + + org.irods + jargon-pom + 4.2.1.0-SNAPSHOT + + pom + DFC DataONE Adapter Framework + DataONE Member Node service and supporting libraries https://code.renci.org/gf/project/dfc-dataone/ - UTF-8 - - - 4.0.2.3-RELEASE - 2.3.6.Final - 3.1.0.RELEASE - 3.1.0.RELEASE - 1.3.0-SNAPSHOT + ${spring.core.version} gForge @@ -43,21 +39,68 @@ developer + + michael-conway + Mike Conway + michael_conway@unc.edu + http://www.renci.org + RENCI + http://www.renci.org + + developer + + + + + + org.dataone + d1_libclient_java + 2.3.0 + jar + + + org.slf4j + log4j-over-slf4j + + + + + org.xeustechnologies + jcl-core + 2.7 + + + org.reflections + reflections + 0.9.10 + + + + org.springframework.integration + spring-integration-core + ${spring.integration.version} + + + + org.springframework.integration + spring-integration-stream + ${spring.integration.version} + + + + org.springframework.integration + spring-integration-amqp + ${spring.integration.version} + + + com.impossibl.pgjdbc-ng + pgjdbc-ng + 0.7.1 + + + - - ibiblio.repository - ibiblio.repository - http://mirrors.ibiblio.org/pub/mirrors/maven2 - - true - - - true - never - fail - - dice.repository snaps dice.repository.snapshots @@ -84,538 +127,18 @@ warn - - jboss - jboss.repository - https://repository.jboss.org/nexus/content/groups/public-jboss/ - - true - - - true - never - fail - - - - dataone.org - http://dev-testing.dataone.org/maven - - true - - - true - - - - - renci.repository - renci.repository - https://ci-dev.renci.org/nexus/content/repositories/release - - - renci.snapshots - renci.snapshots - https://ci-dev.renci.org/nexus/content/repositories/snapshots - - - - - - org.codehaus.mojo - taglist-maven-plugin - - - org.codehaus.mojo - jxr-maven-plugin - - - maven-surefire-plugin - - - org.apache.maven.plugins - maven-surefire-report-plugin - - - org.apache.maven.plugins - maven-javadoc-plugin - - - http://java.sun.com/javase/6/docs/api/ - http://java.sun.com/javaee/5/docs/api/ - http://commons.apache.org/logging/apidocs/ - http://commons.apache.org/io/apidocs/ - http://commons.apache.org/lang/apidocs/ - http://www.junit.org/junit/javadoc/ - http://logging.apache.org/log4j/docs/api/ - http://velocity.apache.org/engine/devel/apidocs/ - - - - - org.apache.maven.plugins - maven-changelog-plugin - - - org.codehaus.mojo - cobertura-maven-plugin - 2.4 - - - - - - - org.jboss.resteasy - resteasy-jaxrs - ${resteasy.version} - - - - org.jboss.resteasy - resteasy-jaxb-provider - ${resteasy.version} - - - org.jboss.resteasy - resteasy-jettison-provider - ${resteasy.version} - - - - - org.jboss.resteasy - resteasy-cache-core - ${resteasy.version} - - - org.jboss.resteasy - resteasy-jackson-provider - ${resteasy.version} - - - org.jboss.resteasy - resteasy-crypto - ${resteasy.version} - - - org.jboss.resteasy - resteasy-multipart-provider - ${resteasy.version} - - - - - - - - - - org.jboss.resteasy - resteasy-spring - ${resteasy.version} - - - - - - - - - - - org.irods.jargon - jargon-core - ${jargon.version} - - - - junit - junit - 4.8.2 - test - - - org.slf4j - slf4j-api - 1.5.10 - - - log4j - log4j - 1.2.16 - - - org.slf4j - slf4j-log4j12 - 1.5.10 - - - org.mockito - mockito-all - 1.8.1 - test - - - org.springframework - spring-core - ${spring.core.version} - - - org.springframework - spring-aop - ${spring.core.version} - - - org.springframework - spring-expression - ${spring.core.version} - - - org.springframework - spring-webmvc - ${spring.core.version} - - - org.springframework - spring-context - ${spring.core.version} - - - org.springframework - spring-beans - ${spring.core.version} - - - - org.jboss.resteasy - tjws - ${resteasy.version} - - - javax.servlet - servlet-api - 2.5 - - - org.springframework - spring-test - ${spring.core.version} - - - org.dataone - d1_libclient_java - ${d1_libclient_version} - jar - - - org.handle - handle - 7.3.1 - system - ${project.basedir}/src/main/lib/handle.jar - - - org.elasticsearch - elasticsearch - 1.4.4 - - - org.apache.tika - tika-core - 1.8 - - - - - - javax.inject - javax.inject - 1 - - - org.eclipse.jdt.core.compiler - ecj - 4.2.1 - - - org.jboss.resteasy - resteasy-jaxrs - - - org.jboss.resteasy - resteasy-jackson-provider - - - org.jboss.resteasy - resteasy-crypto - - - org.jboss.resteasy - tjws - test - - - org.jboss.resteasy - resteasy-multipart-provider - - - javax.servlet - servlet-api - provided - - - org.springframework - spring-test - test - - - - org.jboss.resteasy - resteasy-jaxb-provider - - - - - org.jboss.resteasy - resteasy-spring - - - org.irods.jargon - jargon-core - - - - junit - junit - test - - - org.slf4j - slf4j-api - - - log4j - log4j - - - org.slf4j - slf4j-log4j12 - - - org.mockito - mockito-all - test - - - org.springframework - spring-core - - - org.springframework - spring-expression - - - org.springframework - spring-aop - - - org.springframework - spring-webmvc - - - spring-expression - org.springframework - - - - - org.springframework - spring-context - - - spring-aop - org.springframework - - - spring-expression - org.springframework - - - - - org.springframework - spring-beans - - - org.dataone - d1_libclient_java - - - handle - org.handle - system - ${project.basedir}/src/main/lib/handle.jar - - - org.elasticsearch - elasticsearch - - - org.apache.tika - tika-core - - - - - - maven-antrun-plugin - - - - run - - generate-sources - - - - - - - - - - - - - - - - - - 0 - validate - - - - - - test.confirm=${jargon.test.confirm} - test.data.directory=${jargon.test.data.directory} - test.irods.user=${jargon.test.irods.user} - test.irods.password=${jargon.test.irods.password} - test.irods.resource=${jargon.test.irods.resource} - test.irods.host=${jargon.test.irods.host} - test.irods.port=${jargon.test.irods.port} - test.irods.zone=${jargon.test.irods.zone} - test.irods.scratch.subdir=${jargon.test.irods.scratch.subdir} - test.rest.port=${test.rest.port} - - - - - - - - run - - - - - - maven-compiler-plugin - 3.0 - - 1.6 - 1.6 - - - - maven-war-plugin - 2.3 - - src/main/webapp - true - - - - - - - - org.eclipse.m2e - lifecycle-mapping - 1.0.0 - - - - - - - org.apache.maven.plugins - - - maven-antrun-plugin - - - [1.3,) - - - run - - - - - - - - - - - - - + + dataone-node + pid-service-api + event-service-api + repo-service-api + dummy-repo-service-impl + pid-service-handle-impl + dataone-utils + dummy-event-service-impl + dummy-pid-service-impl + dfc-repo-service-impl + default-event-service + diff --git a/repo-service-api/pom.xml b/repo-service-api/pom.xml new file mode 100644 index 0000000..3d136be --- /dev/null +++ b/repo-service-api/pom.xml @@ -0,0 +1,53 @@ + + + 4.0.0 + repo-service-api + + org.irods + dfc-dataone + 4.2.1.0-SNAPSHOT + + jar + Repository service API + + + org.irods.jargon + jargon-core + ${project.version} + + + + junit + junit + test + + + org.slf4j + slf4j-api + + + log4j + log4j + + + org.slf4j + slf4j-log4j12 + + + org.mockito + mockito-all + + + org.dataone + d1_libclient_java + + + org.irods + dataone-utils + ${project.version} + + + + diff --git a/repo-service-api/src/main/java/.gitinclude b/repo-service-api/src/main/java/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/repo-service-api/src/main/java/org/irods/jargon/dataone/reposervice/AbstractDataOneRepoFactory.java b/repo-service-api/src/main/java/org/irods/jargon/dataone/reposervice/AbstractDataOneRepoFactory.java new file mode 100644 index 0000000..027dd9c --- /dev/null +++ b/repo-service-api/src/main/java/org/irods/jargon/dataone/reposervice/AbstractDataOneRepoFactory.java @@ -0,0 +1,23 @@ +/** + * + */ +package org.irods.jargon.dataone.reposervice; + +import org.irods.jargon.core.connection.IRODSAccount; +import org.irods.jargon.dataone.configuration.PublicationContext; + +/** + * Factory to create repo services + * + * @author mcc + * + */ +public abstract class AbstractDataOneRepoFactory implements DataOneRepoServiceFactory { + + /* (non-Javadoc) + * @see org.irods.jargon.dataone.reposervice.DataOneRepoFactory#instance(org.irods.jargon.dataone.configuration.PublicationContext, org.irods.jargon.core.connection.IRODSAccount) + */ + @Override + public abstract DataOneRepoServiceAO instance(PublicationContext publicationContext, IRODSAccount irodsAccount); + +} diff --git a/repo-service-api/src/main/java/org/irods/jargon/dataone/reposervice/AbstractDataOneRepoServiceAO.java b/repo-service-api/src/main/java/org/irods/jargon/dataone/reposervice/AbstractDataOneRepoServiceAO.java new file mode 100644 index 0000000..e394f5b --- /dev/null +++ b/repo-service-api/src/main/java/org/irods/jargon/dataone/reposervice/AbstractDataOneRepoServiceAO.java @@ -0,0 +1,80 @@ +/** + * + */ +package org.irods.jargon.dataone.reposervice; + +import java.util.Date; +import java.util.List; + +import org.dataone.service.types.v1.Identifier; +import org.dataone.service.types.v1.ObjectFormatIdentifier; +import org.irods.jargon.core.connection.IRODSAccount; +import org.irods.jargon.core.exception.FileNotFoundException; +import org.irods.jargon.core.exception.JargonException; +import org.irods.jargon.core.pub.domain.DataObject; +import org.irods.jargon.dataone.configuration.PublicationContext; +import org.irods.jargon.dataone.plugin.AbstractDataOnePlugin; + +/** + * Abstract implementation of a dataone repo service. This service is in charge + * of coordinating data objects that are to be provided to DataONE polling + * + * @author mconway + * + */ +public abstract class AbstractDataOneRepoServiceAO extends AbstractDataOnePlugin implements DataOneRepoServiceAO { + + /** + * Default constructor with required values + * + * @param irodsAccount + * {@link IRODSAccount} for the current iRODS connection + * @param publicationContext + * {@link PublicationContext} with configuration and other + * information + */ + public AbstractDataOneRepoServiceAO(IRODSAccount irodsAccount, PublicationContext publicationContext) { + super(irodsAccount, publicationContext); + } + + /* + * (non-Javadoc) + * + * @see org.irods.jargon.dataone.reposervice.DataOneRepoAO# + * getListOfDataoneExposedIdentifiers() + */ + @Override + public abstract List getListOfDataoneExposedIdentifiers() throws JargonException; + + /* + * (non-Javadoc) + * + * @see org.irods.jargon.dataone.reposervice.DataOneRepoAO# + * getListOfDataoneExposedDataObjects(java.util.Date, java.util.Date, + * org.dataone.service.types.v1.ObjectFormatIdentifier, java.lang.Boolean, + * java.lang.Integer, java.lang.Integer) + */ + @Override + public abstract DataObjectListResponse getListOfDataoneExposedDataObjects(Date fromDate, Date toDate, + ObjectFormatIdentifier formatId, Boolean replicaStatus, Integer start, Integer count) + throws JargonException; + + /* + * (non-Javadoc) + * + * @see org.irods.jargon.dataone.reposervice.DataOneRepoServiceAO# + * getLastModifiedDateForDataObject(org.irods.jargon.core.pub.domain. + * DataObject) + */ + @Override + public abstract Date getLastModifiedDateForDataObject(DataObject dataObject) throws JargonException; + + /* + * (non-Javadoc) + * + * @see org.irods.jargon.dataone.reposervice.DataOneRepoServiceAO# + * dataObjectFormat(org.irods.jargon.core.pub.domain.DataObject) + */ + @Override + public abstract String dataObjectFormat(DataObject dataObject) throws FileNotFoundException, JargonException; +} diff --git a/src/main/java/org/irods/jargon/dataone/id/DataObjectListResponse.java b/repo-service-api/src/main/java/org/irods/jargon/dataone/reposervice/DataObjectListResponse.java similarity index 92% rename from src/main/java/org/irods/jargon/dataone/id/DataObjectListResponse.java rename to repo-service-api/src/main/java/org/irods/jargon/dataone/reposervice/DataObjectListResponse.java index f57d1a9..efb231c 100644 --- a/src/main/java/org/irods/jargon/dataone/id/DataObjectListResponse.java +++ b/repo-service-api/src/main/java/org/irods/jargon/dataone/reposervice/DataObjectListResponse.java @@ -1,4 +1,4 @@ -package org.irods.jargon.dataone.id; +package org.irods.jargon.dataone.reposervice; import java.util.List; diff --git a/repo-service-api/src/main/java/org/irods/jargon/dataone/reposervice/DataOneRepoServiceAO.java b/repo-service-api/src/main/java/org/irods/jargon/dataone/reposervice/DataOneRepoServiceAO.java new file mode 100644 index 0000000..cc91706 --- /dev/null +++ b/repo-service-api/src/main/java/org/irods/jargon/dataone/reposervice/DataOneRepoServiceAO.java @@ -0,0 +1,64 @@ +package org.irods.jargon.dataone.reposervice; + +import java.util.Date; +import java.util.List; + +import org.dataone.service.types.v1.Identifier; +import org.dataone.service.types.v1.ObjectFormatIdentifier; +import org.irods.jargon.core.exception.FileNotFoundException; +import org.irods.jargon.core.exception.JargonException; +import org.irods.jargon.core.pub.domain.DataObject; + +/** + * Abstraction of management of the DataOne repository (objects to list, + * maintenance of status of DataOne published objects) + * + * @author mconway + * + */ +public interface DataOneRepoServiceAO { + + /** + * Returns a complete list of Unique Identifiers that are associated with + * iRODS objects that are exposed to DataONE + * + * @return List<Identifier> + * @throws JargonException + */ + public List getListOfDataoneExposedIdentifiers() throws JargonException; + + /** + * Returns an iRODS Data Object for the DataONE Identifier object specified + * + * @return List<DataObject> + * @throws JargonException + */ + public DataObjectListResponse getListOfDataoneExposedDataObjects(Date fromDate, Date toDate, + ObjectFormatIdentifier formatId, Boolean replicaStatus, Integer start, Integer count) + throws JargonException; + + /** + * TODO:// why is this not just last mod from data object? mcc + * + * Get last modified data for a data object + * + * @param dataObject + * {@link DataObject} to determine mod date + * @return {@link Date} last modded + * @throws JargonException + */ + public Date getLastModifiedDateForDataObject(final DataObject dataObject) throws JargonException; + + /** + * Get a string representing the MIME type of the data object using the + * technique or metadata in the target system + * + * @param dataObject + * {@link DataObject} + * @return String with the MIME type + * @throws FileNotFoundException + * @throws JargonException + */ + public String dataObjectFormat(final DataObject dataObject) throws FileNotFoundException, JargonException; + +} diff --git a/repo-service-api/src/main/java/org/irods/jargon/dataone/reposervice/DataOneRepoServiceFactory.java b/repo-service-api/src/main/java/org/irods/jargon/dataone/reposervice/DataOneRepoServiceFactory.java new file mode 100644 index 0000000..8d56f5c --- /dev/null +++ b/repo-service-api/src/main/java/org/irods/jargon/dataone/reposervice/DataOneRepoServiceFactory.java @@ -0,0 +1,19 @@ +package org.irods.jargon.dataone.reposervice; + +import org.irods.jargon.core.connection.IRODSAccount; +import org.irods.jargon.dataone.configuration.PublicationContext; + +public interface DataOneRepoServiceFactory { + + /** + * Create an instance of the pid service + * + * @param publicationContext + * {@link PublicationContext} with configuration information + * @param irodsAccount + * {@link IRODSAccount} associated with the instance + * @return + */ + DataOneRepoServiceAO instance(PublicationContext publicationContext, IRODSAccount irodsAccount); + +} \ No newline at end of file diff --git a/repo-service-api/src/main/java/org/irods/jargon/dataone/reposervice/package-info.java b/repo-service-api/src/main/java/org/irods/jargon/dataone/reposervice/package-info.java new file mode 100644 index 0000000..c78e517 --- /dev/null +++ b/repo-service-api/src/main/java/org/irods/jargon/dataone/reposervice/package-info.java @@ -0,0 +1,10 @@ +/** + * + */ +/** + * Repository management service abstraction for dataone + * + * @author mconway + * + */ +package org.irods.jargon.dataone.reposervice; \ No newline at end of file diff --git a/repo-service-api/src/main/resources/.gitinclude b/repo-service-api/src/main/resources/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/repo-service-api/src/test/java/.gitinclude b/repo-service-api/src/test/java/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/repo-service-api/src/test/resources/.gitinclude b/repo-service-api/src/test/resources/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/repo-service-handle-impl/pom.xml b/repo-service-handle-impl/pom.xml new file mode 100644 index 0000000..8bc6d0d --- /dev/null +++ b/repo-service-handle-impl/pom.xml @@ -0,0 +1,60 @@ + + + 4.0.0 + repo-service-handle-impl + Handle repo server impl + + org.irods + dfc-dataone + 4.2.1.0-SNAPSHOT + + jar + + + org.irods.jargon + jargon-core + ${project.version} + + + + junit + junit + test + + + org.slf4j + slf4j-api + + + log4j + log4j + + + org.slf4j + slf4j-log4j12 + + + org.mockito + mockito-all + + + handle + org.handle + system + 1.0.0 + ${project.basedir}/src/main/lib/handle.jar + + + org.irods + repo-service-api + ${project.version} + + + org.irods + dataone-utils + ${project.version} + + + diff --git a/repo-service-handle-impl/src/main/java/.gitinclude b/repo-service-handle-impl/src/main/java/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/repo-service-handle-impl/src/main/java/org/irods/jargon/dataone/reposervice/handle/HandleRepoServiceAOImpl.java b/repo-service-handle-impl/src/main/java/org/irods/jargon/dataone/reposervice/handle/HandleRepoServiceAOImpl.java new file mode 100644 index 0000000..596ab47 --- /dev/null +++ b/repo-service-handle-impl/src/main/java/org/irods/jargon/dataone/reposervice/handle/HandleRepoServiceAOImpl.java @@ -0,0 +1,262 @@ +/** + * + */ +package org.irods.jargon.dataone.reposervice.handle; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Properties; + +import org.dataone.service.types.v1.Identifier; +import org.dataone.service.types.v1.ObjectFormatIdentifier; +import org.irods.jargon.core.exception.JargonException; +import org.irods.jargon.core.pub.DataObjectAO; +import org.irods.jargon.core.pub.domain.DataObject; +import org.irods.jargon.core.query.AVUQueryElement; +import org.irods.jargon.core.query.AVUQueryElement.AVUQueryPart; +import org.irods.jargon.core.query.JargonQueryException; +import org.irods.jargon.core.query.QueryConditionOperators; +import org.irods.jargon.dataone.configuration.PublicationContext; +import org.irods.jargon.dataone.reposervice.AbstractDataOneRepoAO; +import org.irods.jargon.dataone.reposervice.DataObjectListResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author mconway + * + */ +public class HandleRepoServiceAOImpl extends AbstractDataOneRepoAO { + + private Properties properties; + private String propertiesFilename = "d1client.properties"; + private Logger log = LoggerFactory.getLogger(this.getClass()); + + /** + * @param publicationContext + */ + public HandleRepoServiceAOImpl(PublicationContext publicationContext) { + super(publicationContext); + loadProperties(); + } + + @Override + public List getListOfDataoneExposedIdentifiers() throws JargonException { + + AVUQueryElement avuQuery1 = null; + AVUQueryElement avuQuery2 = null; + + String handleAttr = properties.getProperty("irods.dataone.publish_entity_metadata_attr"); + String handleValue = properties.getProperty("irods.dataone.publish_entity_metadata_value"); + + List identifiers = new ArrayList(); + + try { + avuQuery1 = AVUQueryElement.instanceForValueQuery(AVUQueryPart.ATTRIBUTE, QueryConditionOperators.EQUAL, + handleAttr); + + avuQuery2 = AVUQueryElement.instanceForValueQuery(AVUQueryPart.VALUE, QueryConditionOperators.EQUAL, + + handleValue); + + } catch (JargonQueryException e) { + log.error("getListOfDataoneExposedIdentifiers: failed to create AVU query elements"); + return identifiers; + } + + DataObjectAO dataObjectAO = this.getPublicationContext().getIrodsAccessObjectFactory() + .getDataObjectAO(irodsAccount); + List dataObjects = new ArrayList(); + try { + dataObjects = dataObjectAO.findDomainByMetadataQuery(Arrays.asList(avuQuery1, avuQuery2)); + } catch (JargonQueryException e) { + log.error("getListOfDataoneExposedIdentifiers: failed to execute AVU query"); + return identifiers; + } + + // restrict start date for now to 2/10/16 + Date afterDate = new Date(Long.parseLong("1455062400") * 1000); + for (DataObject dataObject : dataObjects) { + if (dataObject.getCreatedAt().after(afterDate)) { + identifiers.add(getIdentifierFromDataObject(dataObject)); + } + } + + log.info("returning identifiers: {}", identifiers); + return identifiers; + } + + @Override + public DataObjectListResponse getListOfDataoneExposedDataObjects(final Date fromDate, final Date toDate, + final ObjectFormatIdentifier formatId, final Boolean replicaStatus, final Integer start, + final Integer count) throws JargonException { + + int total = 0; + + DataObjectListResponse dataObjectListResponse = new DataObjectListResponse(); + + List avuQueryList = createAVUQueryElementList(fromDate, toDate, formatId); + + DataObjectAO dataObjectAO = this.getPublicationContext().getIrodsAccessObjectFactory() + .getDataObjectAO(irodsAccount); + List dataObjects = new ArrayList(); + + try { + dataObjects = dataObjectAO.findDomainByMetadataQuery(avuQueryList, start); + // save original size of set returned + total = dataObjects.size(); + } catch (JargonQueryException e) { + log.error("test_getListOfDataoneExposedDataObjects: failed to execute AVU query"); + return dataObjectListResponse; + } + + // truncate list if count is specified and it is less than the total + List finalDataObjects = new ArrayList(); + if ((count >= 0) && (count < total)) { + finalDataObjects = dataObjects.subList(0, count); + } else { + finalDataObjects = dataObjects; + } + + dataObjectListResponse.setTotal(total); + dataObjectListResponse.setCount(finalDataObjects.size()); + dataObjectListResponse.setDataObjects(finalDataObjects); + + return dataObjectListResponse; + } + + private void loadProperties() { + properties = new Properties(); + InputStream input = null; + + input = getClass().getClassLoader().getResourceAsStream(this.propertiesFilename); + + // load a properties file + try { + properties.load(input); + } catch (IOException e) { + log.error("Cannot load Member Node properties file: {}", propertiesFilename, e); + properties = new Properties(); + } finally { + if (input != null) { + try { + input.close(); + } catch (IOException e) { + // do nothing + } + } + } + } + + private List createAVUQueryElementList(Date fromDate, Date toDate, + ObjectFormatIdentifier formatId) { + + // TODO: probably should move these to properties + String dateAttr = "StartDateTime"; + String formatAttr = "Format"; + List avuQueryList = new ArrayList(); + String handleAttr = properties.getProperty("irods.dataone.publish_entity_metadata_attr"); + String handleValue = properties.getProperty("irods.dataone.publish_entity_metadata_value"); + + AVUQueryElement avuQuery; + try { + // DataOne exposed query + avuQuery = AVUQueryElement.instanceForValueQuery(AVUQueryPart.ATTRIBUTE, QueryConditionOperators.EQUAL, + handleAttr); + avuQueryList.add(avuQuery); + + avuQuery = AVUQueryElement.instanceForValueQuery(AVUQueryPart.VALUE, QueryConditionOperators.EQUAL, + + handleValue); + avuQueryList.add(avuQuery); + + // handle any date queries + // restrict start date for now to 2/17/16 00:00:01 : 1455667201 + // 3-23-16 Update - now changed earliest data to 3/23/16 00:00:01 : + // 1458691201 + // 3-31-16 Update - now changed earliest data to 3/28/16 00:00:01 + // GMT : 1459123201 + long newFromDate; + if (fromDate != null) { + newFromDate = java.lang.Math.max(fromDate.getTime() / 1000, Long.parseLong("1459123201")); + } else { + newFromDate = Long.parseLong("1459123201"); + } + + // fromDate query + avuQuery = AVUQueryElement.instanceForValueQuery(AVUQueryPart.ATTRIBUTE, QueryConditionOperators.EQUAL, + dateAttr); + avuQueryList.add(avuQuery); + + avuQuery = AVUQueryElement.instanceForValueQuery(AVUQueryPart.VALUE, + QueryConditionOperators.GREATER_THAN_OR_EQUAL_TO, Long.toString(newFromDate)); + + avuQueryList.add(avuQuery); + + // toDate query + if ((toDate != null) && ((toDate.getTime() / 1000) >= newFromDate)) { + + avuQuery = AVUQueryElement.instanceForValueQuery(AVUQueryPart.ATTRIBUTE, QueryConditionOperators.EQUAL, + dateAttr); + avuQueryList.add(avuQuery); + + avuQuery = AVUQueryElement.instanceForValueQuery(AVUQueryPart.VALUE, QueryConditionOperators.LESS_THAN, + Long.toString(toDate.getTime() / 1000)); + avuQueryList.add(avuQuery); + + } + + // if ((toDate != null) && (toDate.getTime() >= newFromDate)) { + // avuQuery = AVUQueryElement.instanceForValueQuery( + // AVUQueryPart.ATTRIBUTE, + // AVUQueryOperatorEnum.EQUAL, + // dateAttr); + // avuQueryList.add(avuQuery); + // + // avuQuery = AVUQueryElement.instanceForValueQuery( + // AVUQueryPart.VALUE, + // AVUQueryOperatorEnum.BETWEEN, + // Long.toString(toDate.getTime()/1000)); + // avuQueryList.add(avuQuery); + // + // } + // else { + // avuQuery = AVUQueryElement.instanceForValueQuery( + // AVUQueryPart.ATTRIBUTE, + // AVUQueryOperatorEnum.EQUAL, + // dateAttr); + // avuQueryList.add(avuQuery); + // + // avuQuery = AVUQueryElement.instanceForValueQuery( + // AVUQueryPart.VALUE, + // AVUQueryOperatorEnum.GREATER_OR_EQUAL, + // Long.toString(newFromDate)); + // avuQueryList.add(avuQuery); + // + // } + + // handle data format query + if ((formatId != null) && (formatId.getValue() != null)) { + + avuQuery = AVUQueryElement.instanceForValueQuery(AVUQueryPart.ATTRIBUTE, QueryConditionOperators.EQUAL, + formatAttr); + avuQueryList.add(avuQuery); + + avuQuery = AVUQueryElement.instanceForValueQuery(AVUQueryPart.VALUE, QueryConditionOperators.EQUAL, + formatId.getValue()); + avuQueryList.add(avuQuery); + + } + } catch (JargonQueryException e) { + log.error("createAVUQueryElementList: failed to construct AVU query"); + return avuQueryList; + } + + return avuQueryList; + } + +} diff --git a/repo-service-handle-impl/src/main/java/org/irods/jargon/dataone/reposervice/handle/package-info.java b/repo-service-handle-impl/src/main/java/org/irods/jargon/dataone/reposervice/handle/package-info.java new file mode 100644 index 0000000..6695bb7 --- /dev/null +++ b/repo-service-handle-impl/src/main/java/org/irods/jargon/dataone/reposervice/handle/package-info.java @@ -0,0 +1,10 @@ +/** + * + */ +/** + * Original handle-based repo service implementation + * + * @author mconway + * + */ +package org.irods.jargon.dataone.reposervice.handle; \ No newline at end of file diff --git a/repo-service-handle-impl/src/main/lib/cnriutil.jar b/repo-service-handle-impl/src/main/lib/cnriutil.jar new file mode 100644 index 0000000..211a869 Binary files /dev/null and b/repo-service-handle-impl/src/main/lib/cnriutil.jar differ diff --git a/repo-service-handle-impl/src/main/lib/handle.jar b/repo-service-handle-impl/src/main/lib/handle.jar new file mode 100644 index 0000000..aed4710 Binary files /dev/null and b/repo-service-handle-impl/src/main/lib/handle.jar differ diff --git a/repo-service-handle-impl/src/main/resources/.gitinclude b/repo-service-handle-impl/src/main/resources/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/repo-service-handle-impl/src/test/java/.gitinclude b/repo-service-handle-impl/src/test/java/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/repo-service-handle-impl/src/test/resources/.gitinclude b/repo-service-handle-impl/src/test/resources/.gitinclude new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/org/irods/jargon/dataone/IrodsDataoneVersion.java b/src/main/java/org/irods/jargon/dataone/IrodsDataoneVersion.java deleted file mode 100644 index fc0922e..0000000 --- a/src/main/java/org/irods/jargon/dataone/IrodsDataoneVersion.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.irods.jargon.dataone; -public final class IrodsDataoneVersion { - public static String VERSION="0.0.1-SNAPSHOT"; - public static String BUILD_TIME="20131014-0959"; -} diff --git a/src/main/java/org/irods/jargon/dataone/MemberNodeService.java b/src/main/java/org/irods/jargon/dataone/MemberNodeService.java deleted file mode 100644 index d24aed0..0000000 --- a/src/main/java/org/irods/jargon/dataone/MemberNodeService.java +++ /dev/null @@ -1,461 +0,0 @@ -package org.irods.jargon.dataone; - -import org.dataone.service.exceptions.InsufficientResources; -import org.dataone.service.exceptions.InvalidRequest; -import org.dataone.service.exceptions.InvalidToken; -import org.dataone.service.exceptions.NotAuthorized; -import org.dataone.service.exceptions.NotFound; -import org.dataone.service.exceptions.NotImplemented; -import org.dataone.service.exceptions.ServiceFailure; -import org.dataone.service.exceptions.SynchronizationFailed; -import org.dataone.service.types.v1.Checksum; -import org.dataone.service.types.v1.DescribeResponse; -import org.dataone.service.types.v1.Event; -import org.dataone.service.types.v1.Identifier; -import org.dataone.service.types.v1.Log; -import org.dataone.service.types.v1.Node; -import org.dataone.service.types.v1.ObjectFormatIdentifier; -import org.dataone.service.types.v1.ObjectList; -import org.dataone.service.types.v1.SystemMetadata; -import org.irods.jargon.core.exception.JargonException; -import org.irods.jargon.core.pub.IRODSAccessObjectFactory; -import org.irods.jargon.dataone.tier1.MNCoreImpl; -import org.irods.jargon.dataone.tier1.MNReadImpl; -import org.irods.jargon.dataone.utils.ISO8601; -import org.irods.jargon.dataone.configuration.RestConfiguration; -import org.irods.jargon.dataone.domain.MNChecksum; -import org.irods.jargon.dataone.domain.MNError; -import org.irods.jargon.dataone.domain.MNLog; -import org.irods.jargon.dataone.domain.MNObjectList; -import org.irods.jargon.dataone.domain.MNNode; -import org.irods.jargon.dataone.domain.MNSystemMetadata; -import org.irods.jargon.dataone.events.EventLogAOElasticSearchImpl; -import org.jboss.resteasy.annotations.providers.jaxb.json.Mapped; -import org.jboss.resteasy.annotations.providers.jaxb.json.XmlNsMap; -import org.jboss.resteasy.plugins.providers.multipart.InputPart; -import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.inject.Inject; -import javax.inject.Named; -import javax.servlet.http.HttpServletResponse; -import javax.ws.rs.Consumes; -import javax.ws.rs.DefaultValue; -import javax.ws.rs.GET; -import javax.ws.rs.HEAD; -import javax.ws.rs.POST; -import javax.ws.rs.PathParam; -import javax.ws.rs.QueryParam; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.Status; -import javax.xml.bind.JAXB; - -import java.io.IOException; -import java.io.StringReader; -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.List; -import java.util.Map; -import java.util.TimeZone; - -/** - * User: Lisa Stillwell - RENCI, UNC @ Chapel Hill - * Date: 10/4/13 - * Time: 2:22 PM - */ - -@Named -@Path("/mn/v1") -public class MemberNodeService { - - private Logger logger = LoggerFactory.getLogger(this.getClass()); - - @Inject - IRODSAccessObjectFactory irodsAccessObjectFactory; - - @Inject - RestConfiguration restConfiguration; - - @GET - @Path("/monitor/ping") - @Produces(MediaType.TEXT_XML) - @Mapped(namespaceMap = { @XmlNsMap(namespace = "http://irods.org/dfc-dataone", jsonName = "dfc-dataone") }) -// public Response handlePing(@HeaderParam("Authorization") final String authorization) - public Response handlePing() - throws NotImplemented, ServiceFailure, InsufficientResources, JargonException { - -// if (authorization == null || authorization.isEmpty()) { -// throw new IllegalArgumentException("null or empty authorization"); -// } - - if (irodsAccessObjectFactory == null) { - throw new IllegalArgumentException("null irodsAccessObjectFactory"); - } - -// MNCoreImpl mnCoreImpl = new MNCoreImpl(irodsAccessObjectFactory, restConfiguration, authorization); - MNCoreImpl mnCoreImpl = new MNCoreImpl(irodsAccessObjectFactory, restConfiguration); - Date irodsDate = mnCoreImpl.ping(); - - SimpleDateFormat df = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz"); - String dateStr = df.format(irodsDate); - - Response.ResponseBuilder builder = Response.ok(); - builder.header("Date", dateStr); - builder.type("text/xml"); - builder.header("Content-Length", "0"); - - return builder.build(); - } - - @GET - @Path("/node") - @Produces(MediaType.TEXT_XML) - @Mapped(namespaceMap = { @XmlNsMap(namespace = "http://irods.org/dfc-dataone", jsonName = "dfc-dataone") }) - public MNNode handleGetCapabilities() - throws NotImplemented, ServiceFailure { - - MNNode nodeCapabilities = new MNNode(); - - MNCoreImpl mnCoreImpl = new MNCoreImpl(irodsAccessObjectFactory, restConfiguration); - Node node = mnCoreImpl.getCapabilities(); - - nodeCapabilities.copy(node); - - return nodeCapabilities; - } - - @GET - @Path("/") - @Produces(MediaType.TEXT_XML) - @Mapped(namespaceMap = { @XmlNsMap(namespace = "http://irods.org/dfc-dataone", jsonName = "dfc-dataone") }) - public MNNode handleDeafaultGetCapabilities() - throws NotImplemented, ServiceFailure { - - MNNode nodeCapabilities = handleGetCapabilities(); - - return nodeCapabilities; - } - - //log?[fromDate={fromDate}][&toDate={toDate}][&event={event}][&pidFilter={pidFilter}][&start={start}][&count={count}] - @GET - @Path("/log") - @Produces(MediaType.TEXT_XML) - @Mapped(namespaceMap = { @XmlNsMap(namespace = "http://irods.org/dfc-dataone", jsonName = "dfc-dataone") }) - public MNLog handleGetLogRecords( - @QueryParam("fromDate") String fromDateStr, - @QueryParam("toDate") String toDateStr, - @QueryParam("event") String event, - @QueryParam("pidFilter") String pidFilter, - @DefaultValue("0") @QueryParam("start") int start, - @DefaultValue("500") @QueryParam("count") int count - ) - throws NotImplemented, - ServiceFailure, - NotAuthorized, - InvalidRequest, - InvalidToken { - - logger.info("/log request: fromData={} toDate={}", fromDateStr, toDateStr); - logger.info("/log request: event={} pidFilter={}", event, pidFilter); - logger.info("/log request: start={} count={}", start, count); - - MNCoreImpl mnCoreImpl = new MNCoreImpl(irodsAccessObjectFactory, restConfiguration); - - // parse date strings - Date fromDate = null; - Date toDate = null; - try { - if (fromDateStr != null) { - fromDate = ISO8601.toCalendar(fromDateStr).getTime(); - } - if (toDateStr != null) { - toDate = ISO8601.toCalendar(toDateStr).getTime(); - } - } catch (ParseException e) { - logger.error("handleListObjects: unable to parse query dates"); - throw new InvalidRequest("1480", e.getMessage()); - } - - Event e = Event.convert(event); - - Log log = mnCoreImpl.getLogRecords( - fromDate, - toDate, - e, - pidFilter, - start, - count); - logger.info("returned log={}", log.toString()); - - - // set Log attributes in MNLog - MNLog mnLog = new MNLog(); - mnLog.copy(log); - - return mnLog; - } - - @GET - @Path("/object/{id}") - @Produces(MediaType.APPLICATION_OCTET_STREAM) - public void handleRead(@PathParam("id") final String pid, - @Context final HttpServletResponse response) - throws InvalidToken, - ServiceFailure, - NotAuthorized, - NotFound, - NotImplemented, - InsufficientResources { - - MNReadImpl mnReadImpl = new MNReadImpl(irodsAccessObjectFactory, restConfiguration); - - Identifier id = new Identifier(); - id.setValue(pid); - // Had to write new method in mnReadImpl since I - // couldn't figure out how to override the get method - mnReadImpl.streamObject(response, id); - - // now log the event - EventLogAOElasticSearchImpl eventLog = new EventLogAOElasticSearchImpl(irodsAccessObjectFactory, restConfiguration); - try { - eventLog.recordEvent(Event.READ, id, "DataONE replication"); - } catch (Exception e) { - logger.error("Unable to log EVENT: {} for data object id: {}", Event.READ, pid); - } - - } - - @GET - @Path("/checksum/{id}") - @Produces(MediaType.TEXT_XML) - public MNChecksum handleGetChecksum(@PathParam("id") final String pid, - @DefaultValue("MD5") @QueryParam("checksumAlgorithm") final String algorithm) - throws InvalidToken, - ServiceFailure, - NotAuthorized, - NotFound, - NotImplemented, - InvalidRequest { - - MNChecksum mnChecksum = new MNChecksum(); - - if (!algorithm.toUpperCase().equals("MD5")) { - throw new InvalidRequest("1402", "invalid checksum algorithm requested - only MD5 supported"); - } - - Identifier id = new Identifier(); - id.setValue(pid); - - MNReadImpl mnReadImpl = new MNReadImpl(irodsAccessObjectFactory, restConfiguration); - Checksum checksum = mnReadImpl.getChecksum(id, algorithm); - - mnChecksum.copy(checksum); - - return mnChecksum; - } - - @GET - @Path("/replica/{id}") - @Produces(MediaType.APPLICATION_OCTET_STREAM) - public void handleReplica(@PathParam("id") final String pid, - @Context final HttpServletResponse response) - throws InvalidToken, - ServiceFailure, - NotAuthorized, - NotFound, - NotImplemented, - InsufficientResources { - - MNReadImpl mnReadImpl = new MNReadImpl(irodsAccessObjectFactory, restConfiguration); - - Identifier id = new Identifier(); - id.setValue(pid); - - // Had to write new method in mnReadImpl since I - // couldn't figure out how to override the get method - mnReadImpl.streamObject(response, id); - - // now log the event - EventLogAOElasticSearchImpl eventLog = new EventLogAOElasticSearchImpl(irodsAccessObjectFactory, restConfiguration); - try { - eventLog.recordEvent(Event.REPLICATE, id, "DataONE replication"); - } catch (Exception e) { - logger.error("Unable to log EVENT: {} for data object id: {}", Event.REPLICATE, pid); - } - - } - - @GET - @Path("/meta/{id}") - @Produces(MediaType.TEXT_XML) - public MNSystemMetadata handleGetSystemMetadata(@PathParam("id") final String pid) - //@Context final HttpServletResponse response) - throws InvalidToken, - ServiceFailure, - NotAuthorized, - NotFound, - NotImplemented, - InvalidRequest { - - MNSystemMetadata mnSystemMetadata = new MNSystemMetadata(); - - Identifier id = new Identifier(); - id.setValue(pid); - - MNReadImpl mnReadImpl = new MNReadImpl(irodsAccessObjectFactory, restConfiguration); - SystemMetadata sysMetadata = mnReadImpl.getSystemMetadata(id); - - mnSystemMetadata.copy(sysMetadata); - - return mnSystemMetadata; - } - - @HEAD - @Path("/object/{id}") - @Produces(MediaType.TEXT_XML) - @Mapped(namespaceMap = { @XmlNsMap(namespace = "http://irods.org/dfc-dataone", jsonName = "dfc-dataone") }) - public Response handleDescribe(@PathParam("id") final String pid) - //@Context final HttpServletResponse response) - throws NotAuthorized, NotImplemented, ServiceFailure, NotFound, InvalidToken { - - Identifier id = new Identifier(); - id.setValue(pid); - - DescribeResponse describeResponse; - - MNReadImpl mnReadImpl = new MNReadImpl(irodsAccessObjectFactory, restConfiguration); - try { - describeResponse = mnReadImpl.describe(id); - } catch (NotFound ex) { - - Response.ResponseBuilder builder = Response.ok(); - builder.status(Status.NOT_FOUND); - builder.type(MediaType.TEXT_XML); - builder.header("DataONE-Exception-Name", "NotFound"); - builder.header("DataONE-Exception-DetailCode", ex.getDetail_code()); - builder.header("DataONE-Exception-Description", ex.getDescription()); - builder.header("DataONE-Exception-PID", pid); - - return builder.build(); - } - - Checksum checksum = describeResponse.getDataONE_Checksum(); - String checksumStr = checksum.getAlgorithm() + "," + checksum.getValue(); - - // Convert data to GMT and format for HTTP header - DateFormat gmtFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss "); - TimeZone gmtTimeZone = TimeZone.getTimeZone("GMT"); - gmtFormat.setTimeZone(gmtTimeZone); - Calendar calendar = new GregorianCalendar(); - calendar.setTime(describeResponse.getLast_Modified()); - calendar.setTimeZone(gmtTimeZone); - String dateStr = gmtFormat.format(calendar.getTime()); - dateStr += "GMT"; - - Response.ResponseBuilder builder = Response.ok(); - builder.header("Last-Modified", dateStr); - builder.header("Content-Length", describeResponse.getContent_Length().toString()); - builder.type(MediaType.APPLICATION_OCTET_STREAM); - builder.header("DataONE-formatId", describeResponse.getDataONE_ObjectFormatIdentifier().getValue().toString()); - builder.header("DataONE-Checksum", checksumStr); - builder.header("DataONE-SerialVersion", describeResponse.getSerialVersion().toString()); - - return builder.build(); - } - - @POST - @Path("/error") - @Produces(MediaType.TEXT_XML) - @Consumes(MediaType.MULTIPART_FORM_DATA) - @Mapped(namespaceMap = { @XmlNsMap(namespace = "http://irods.org/dfc-dataone", jsonName = "dfc-dataone") }) - public Response handleSynchronizationFailed( - MultipartFormDataInput input) - throws NotAuthorized, NotImplemented, ServiceFailure, InvalidToken { - - Map> uploadForm = input.getFormDataMap(); - List inputParts = uploadForm.get("message"); - if (inputParts == null || inputParts.size() == 0) { - throw new ServiceFailure("2161", "Synch Failure Exception cannot parse message"); - } - String str_xml = null; - try { - str_xml = inputParts.get(0).getBodyAsString(); - } catch (IOException e) { - throw new ServiceFailure("2161", "Synch Failure Exception cannot extract message xml"); - } - - MNError error = JAXB.unmarshal(new StringReader(str_xml), MNError.class); - SynchronizationFailed message = error.copyToSynchronizationFailed(); - - if (message == null) { - throw new ServiceFailure("2161", "Synch Failure Exception message is null"); - } - - MNReadImpl mnReadImpl = new MNReadImpl(irodsAccessObjectFactory, restConfiguration); - boolean success = mnReadImpl.synchronizationFailed(message); - - if (!success) { - throw new ServiceFailure("2161", "Failed to log Synchronization Failure event"); - } - - Response.ResponseBuilder builder = Response.ok(); - - return builder.build(); - } - - // GET /object[?fromDate={fromDate}&toDate={toDate}&formatId={formatId} - // &replicaStatus={replicaStatus} &start={start}&count={count}] - @GET - @Path("/object") - @Produces(MediaType.TEXT_XML) - public MNObjectList handleListObjects( - @QueryParam("fromDate") final String fromDateStr, - @QueryParam("toDate") final String toDateStr, - @QueryParam("formatId") final String formatIdStr, - @QueryParam("replicaStatus") final Boolean replicaStatus, - @DefaultValue("0") @QueryParam("start") final Integer start, - @DefaultValue("500") @QueryParam("count") final Integer count - ) throws - InvalidToken, - ServiceFailure, - NotAuthorized, - InvalidRequest, - NotImplemented { - - MNObjectList mnObjectList = new MNObjectList(); - - // parse any query arguments to convert into correct formats, - // if not handled by data type constructors - ObjectFormatIdentifier formatId = new ObjectFormatIdentifier(); - formatId.setValue(formatIdStr); - - Date fromDate = null; - Date toDate = null; - try { - if (fromDateStr != null) { - fromDate = ISO8601.toCalendar(fromDateStr).getTime(); - } - if (toDateStr != null) { - toDate = ISO8601.toCalendar(toDateStr).getTime(); - } - } catch (ParseException e) { - logger.error("handleListObjects: unable to parse query dates"); - throw new InvalidRequest("1540", e.getMessage()); - } - - MNReadImpl mnReadImpl = new MNReadImpl(irodsAccessObjectFactory, restConfiguration); - ObjectList objectList = mnReadImpl.listObjects(fromDate, toDate, formatId, replicaStatus, start, count); - mnObjectList.copy(objectList); - - return mnObjectList; - } -} diff --git a/src/main/java/org/irods/jargon/dataone/domain/MNError.java b/src/main/java/org/irods/jargon/dataone/domain/MNError.java deleted file mode 100644 index 8af2a62..0000000 --- a/src/main/java/org/irods/jargon/dataone/domain/MNError.java +++ /dev/null @@ -1,79 +0,0 @@ -package org.irods.jargon.dataone.domain; - -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAccessType; - -import org.dataone.service.exceptions.SynchronizationFailed; - -@XmlRootElement(name = "error") -@XmlAccessorType(XmlAccessType.FIELD) -public class MNError { - - @XmlAttribute - private String detailCode; - @XmlAttribute - private String errorCode; - @XmlAttribute - private String name; - @XmlAttribute - private String pid; - @XmlElement - private String description; - - public MNError() { - } - - public String getDetailCode() { - return detailCode; - } - - public void setDetailCode(String detailCode) { - this.detailCode = detailCode; - } - - public String getErrorCode() { - return errorCode; - } - - public void setErrorCode(String errorCode) { - this.errorCode = errorCode; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getPid() { - return pid; - } - - public void setPid(String pid) { - this.pid = pid; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public SynchronizationFailed copyToSynchronizationFailed() { - SynchronizationFailed syncFailed = new SynchronizationFailed( - this.detailCode, - this.description); - - syncFailed.setPid(this.pid); - - return syncFailed; - - } -} diff --git a/src/main/java/org/irods/jargon/dataone/domain/MNSchedule.java b/src/main/java/org/irods/jargon/dataone/domain/MNSchedule.java deleted file mode 100644 index 9fb005a..0000000 --- a/src/main/java/org/irods/jargon/dataone/domain/MNSchedule.java +++ /dev/null @@ -1,154 +0,0 @@ -package org.irods.jargon.dataone.domain; - -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Properties; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; - -import org.dataone.service.types.v1.Schedule; - -@XmlAccessorType(XmlAccessType.NONE) -public class MNSchedule { - - @XmlAttribute - private String hour; - @XmlAttribute - private String mday; - @XmlAttribute - private String min; - @XmlAttribute - private String mon; - @XmlAttribute - private String sec; - @XmlAttribute - private String wday; - @XmlAttribute - private String year; - - public MNSchedule() { - initializeProperties(); - } - - private void initializeProperties() { - Properties prop = new Properties(); - InputStream input = null; - - try { - - String filename = "d1client.properties"; - input = getClass().getClassLoader().getResourceAsStream(filename); - - // load a properties file - prop.load(input); - - this.hour = prop.getProperty("irods.dataone.sync.schedule.hour"); - this.mday = prop.getProperty("irods.dataone.sync.schedule.mday"); - this.min = prop.getProperty("irods.dataone.sync.schedule.min"); - this.mon = prop.getProperty("irods.dataone.sync.schedule.mon"); - this.sec = prop.getProperty("irods.dataone.sync.schedule.sec"); - this.wday = prop.getProperty("irods.dataone.sync.schedule.wday"); - this.year = prop.getProperty("irods.dataone.sync.schedule.year"); - - } catch (IOException ex) { - ex.printStackTrace(); - } finally { - if (input != null) { - try { - input.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - } -// public String getHour() { -// return hour; -// } -// public void setHour(String hour) { -// this.hour = hour; -// } -// -// public String getMday() { -// return mday; -// } -// public void setMday(String mday) { -// this.mday = mday; -// } -// -// public String getMin() { -// return min; -// } -// public void setMin(String min) { -// this.min = min; -// } -// -// public String getMon() { -// return mon; -// } -// public void setMon(String mon) { -// this.mon = mon; -// } -// -// public String getSec() { -// return sec; -// } -// public void setSec(String sec) { -// this.sec = sec; -// } -// -// public String getWday() { -// return wday; -// } -// public void setWday(String wday) { -// this.wday = wday; -// } -// -// public String getYear() { -// return year; -// } -// public void setYear(String year) { -// this.year = year; -// } - - - public void copy(Schedule s) { - - if (s == null) { - return; - // TODO: log something here? - } - - if (s.getHour() != null) { - this.hour = s.getHour(); - } - - if (s.getMday() != null) { - this.mday = s.getMday(); - } - - if (s.getMin() != null) { - this.min = s.getMin(); - } - - if (s.getMon() != null) { - this.mon = s.getMon(); - } - - if (s.getSec() != null) { - this.sec = s.getSec(); - } - - if (s.getWday() != null) { - this.wday = s.getWday(); - } - - if (s.getYear() != null) { - this.year = s.getYear(); - } - } - -} diff --git a/src/main/java/org/irods/jargon/dataone/domain/package-info.java b/src/main/java/org/irods/jargon/dataone/domain/package-info.java deleted file mode 100644 index d3b966f..0000000 --- a/src/main/java/org/irods/jargon/dataone/domain/package-info.java +++ /dev/null @@ -1,18 +0,0 @@ -/** - * - */ -/** - * @author lisa - * - */ -@XmlSchema( - namespace = "http://ns.dataone.org/service/types/v1", - elementFormDefault = XmlNsForm.UNQUALIFIED, - xmlns = { - @XmlNs(namespaceURI = "http://ns.dataone.org/service/types/v1", prefix = "d1") - } -) -package org.irods.jargon.dataone.domain; -import javax.xml.bind.annotation.XmlSchema; -import javax.xml.bind.annotation.XmlNs; -import javax.xml.bind.annotation.XmlNsForm; diff --git a/src/main/java/org/irods/jargon/dataone/events/EventLogAO.java b/src/main/java/org/irods/jargon/dataone/events/EventLogAO.java deleted file mode 100644 index 4ca3cfc..0000000 --- a/src/main/java/org/irods/jargon/dataone/events/EventLogAO.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.irods.jargon.dataone.events; - -import java.util.Date; - -import org.dataone.service.exceptions.ServiceFailure; -import org.dataone.service.types.v1.Event; -import org.dataone.service.types.v1.Identifier; -import org.dataone.service.types.v1.Log; -import org.irods.jargon.core.exception.JargonException; -import org.irods.jargon.core.exception.InvalidArgumentException; - -// implements access to the iRODS event log -public interface EventLogAO { - - // retrieve list of logEntry (events) - //log?[fromDate={fromDate}][&toDate={toDate}][&event={event}][&pidFilter={pidFilter}][&start={start}][&count={count}] - // use elastic search api to retrieve events - public Log getLogs(Date fromDate, Date toDate, EventsEnum event, String pidFilter, int startIdx, int count); - - - // execute rule to add event to databook event log - // sendAccess("synch_failure", user name, data object identifier, timestamp in seconds, short description); - public void recordEvent(Event event, Identifier id, String description) - throws InvalidArgumentException, JargonException, ServiceFailure; - -} diff --git a/src/main/java/org/irods/jargon/dataone/events/EventLogAOElasticSearchImpl.java b/src/main/java/org/irods/jargon/dataone/events/EventLogAOElasticSearchImpl.java deleted file mode 100644 index 4302647..0000000 --- a/src/main/java/org/irods/jargon/dataone/events/EventLogAOElasticSearchImpl.java +++ /dev/null @@ -1,428 +0,0 @@ -package org.irods.jargon.dataone.events; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Map; - -import org.dataone.service.exceptions.ServiceFailure; -import org.dataone.service.types.v1.Event; -import org.dataone.service.types.v1.Identifier; -import org.dataone.service.types.v1.Log; -import org.dataone.service.types.v1.LogEntry; -import org.dataone.service.types.v1.NodeReference; -import org.dataone.service.types.v1.Subject; -import org.irods.jargon.core.connection.IRODSAccount; -import org.irods.jargon.core.exception.FileNotFoundException; -import org.irods.jargon.core.exception.InvalidArgumentException; -import org.irods.jargon.core.exception.JargonException; -import org.irods.jargon.core.pub.CollectionAndDataObjectListAndSearchAO; -import org.irods.jargon.core.pub.DataObjectAO; -import org.irods.jargon.core.pub.IRODSAccessObjectFactory; -import org.irods.jargon.core.pub.RuleProcessingAO; -import org.irods.jargon.core.pub.domain.DataObject; -import org.irods.jargon.core.pub.domain.ObjStat; -import org.irods.jargon.core.pub.io.IRODSFile; -import org.irods.jargon.core.rule.IRODSRuleExecResult; -import org.irods.jargon.dataone.auth.RestAuthUtils; -import org.irods.jargon.dataone.configuration.RestConfiguration; -import org.irods.jargon.dataone.id.UniqueIdAOHandleImpl; -import org.irods.jargon.dataone.utils.PropertiesLoader; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.elasticsearch.action.search.SearchRequestBuilder; -import org.elasticsearch.action.search.SearchResponse; -import org.elasticsearch.client.Client; -import org.elasticsearch.client.transport.NoNodeAvailableException; -import org.elasticsearch.client.transport.TransportClient; -import org.elasticsearch.common.settings.ImmutableSettings; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.transport.InetSocketTransportAddress; -import org.elasticsearch.index.query.BoolQueryBuilder; -import org.elasticsearch.index.query.FilterBuilders; -import org.elasticsearch.index.query.QueryBuilders; -import org.elasticsearch.index.query.RangeFilterBuilder; -import org.elasticsearch.search.SearchHit; - -public class EventLogAOElasticSearchImpl implements EventLogAO { - - // Hard-code subject for now - private final String SUBJECT_USER = "dataone"; - final IRODSAccessObjectFactory irodsAccessObjectFactory; - final RestConfiguration restConfiguration; - - private Logger logger = LoggerFactory.getLogger(this.getClass()); - - public EventLogAOElasticSearchImpl(IRODSAccessObjectFactory irodsAccessObjectFactory, - RestConfiguration restConfiguration) { - - this.irodsAccessObjectFactory = irodsAccessObjectFactory; - this.restConfiguration = restConfiguration; - } - - - // retrieve list of logEntry (events) - @SuppressWarnings("resource") - // log?[fromDate={fromDate}][&toDate={toDate}][&event={event}][&pidFilter={pidFilter}][&start={start}][&count={count}] - // TODO: The response MUST contain only records for which the requester has permission to read. This is - // always okay because access is anonymous and read only? - @Override - public Log getLogs(Date fromDate, Date toDate, EventsEnum event, String pidFilter, int startIdx, int count) - throws NoNodeAvailableException { - - if (fromDate != null) { - logger.info("getLogs: fromDate= {}", fromDate.toString()); - } - if (toDate != null) { - logger.info("getLogs: toDate={}", toDate.toString()); - } - if (event != null) { - logger.info("getLogs: event={}", event.name()); - } - if (pidFilter != null) { - logger.info("getLogs: pidFilter={}", pidFilter); - } - logger.info("getLogs: startIdx={}, count={}", startIdx, count); - - // ignoring pidFilter for now - - boolean datesExist = true; - if (fromDate == null && toDate == null) { - datesExist = false; - } - - // restrict search to DataONE exposed data objects - // get this list from the Handle server - // should return something like this: - // 10/9/15 - worked with how to change databook rules so messages only get - // created for objects under a certain dir: i.e. /eesZone/home/nexrad/NEXRAD_LEVEL_2/*.nc - // so just assume we can query all elastic search messages, since they are only created - // for the nexrad data - String uriRegex = null; - /* so don't need this anymore - try { - // "\"/dfc3/home/rods/fabfile.py2\".*|\"/dfc3/home/rods/fabfile.py3\".*" - uriRegex = getDataOneDataObjectsRegex(); - } catch (JargonException e) { - logger.error("error getting DataOne uids and converting to regex"); - throw new NoNodeAvailableException(e.getMessage()); - } */ - - // maybe implement spring bean for these settings? - // get elasticsearch properties - PropertiesLoader loader = new PropertiesLoader(); - String elasticsearchDNS = loader.getProperty("irods.dataone.events.elasticsearch.dns"); - int elasticsearchport = Integer.parseInt(loader.getProperty("irods.dataone.events.elasticsearch.port")); - String searchIndex = loader.getProperty("irods.dataone.events.elasticsearch.searchindex"); - String searchType = loader.getProperty("irods.dataone.events.elasticsearch.searchtype"); - String clusterName = loader.getProperty("irods.dataone.events.elasticsearch.cluster.name"); - String rangeField = "created"; - - BoolQueryBuilder boolQuery = QueryBuilders.boolQuery() - .must(QueryBuilders.matchQuery("type", "databook.persistence.rule.rdf.ruleset.Access")); - //.must(QueryBuilders.matchQuery("userEntityLink", userEntityLink)); - if (event != null) { - boolQuery.must(QueryBuilders.matchQuery("title", event.getDatabookEvent())); - } - // skip any events of no interest to DataONE - boolQuery.mustNot(QueryBuilders.matchQuery("title", "metadata add")); - - if (uriRegex != null && !uriRegex.isEmpty()) { - boolQuery.must(QueryBuilders.regexpQuery("uri", uriRegex)); - } - - // Note that date time precision is limited to one millisecond. - // TODO: If no timezone information is provided UTC will be assumed. - RangeFilterBuilder filterBuilder = FilterBuilders - .rangeFilter(rangeField); - if (datesExist) { - if (fromDate != null) { - filterBuilder - .from(fromDate.getTime()) - //.from(fromDate.getTime()/1000) - .includeLower(true); - } - else { - filterBuilder - .from(0) - .includeLower(true); - } - if (toDate != null) { - filterBuilder - .to(toDate.getTime()) - .includeUpper(false); - } - else { - filterBuilder - .to(System.currentTimeMillis()) - .includeUpper(false); - } - } - - logger.info("creating elastic search transport client: dns={}, port={}", elasticsearchDNS, elasticsearchport); - Settings settings = ImmutableSettings.settingsBuilder() //TODO: put this in config file - .put("cluster.name", clusterName).build(); - Client client = null; - if(elasticsearchDNS != null && elasticsearchDNS.length() > 0) { - client = new TransportClient(settings) - .addTransportAddress(new InetSocketTransportAddress(elasticsearchDNS, elasticsearchport)); - } - else { - client = new TransportClient(settings) - .addTransportAddress(new InetSocketTransportAddress("localhost", 9300)); - } - - SearchRequestBuilder srBuilder = client.prepareSearch(searchIndex) - .setTypes(searchType) - //.setSearchType(SearchType.DEFAULT) - .setQuery(boolQuery) - //.setPostFilter(filterBuilder) - .setFrom(startIdx).setSize(startIdx + count); - if (datesExist) { - srBuilder.setPostFilter(filterBuilder); - } - logger.info("getLogs: built search request: {}", srBuilder.toString()); - - SearchResponse response = srBuilder.execute().actionGet(); - logger.info("getLogs: got search response: {}", response.toString()); - - SearchHit[] searchHits = response.getHits().getHits(); - Log log = new Log(); - if (searchHits.length > 0) { - // now put data and put in Log object - try { - log = copyHitsToLog(startIdx, count, response.getHits().getTotalHits(), searchHits); - } catch (JargonException e) { - client.close(); - logger.error("error copying elastic search hits into Log entries"); - throw new NoNodeAvailableException(e.getMessage()); - } - } - client.close(); - - return log; - } - - - private Log copyHitsToLog(int start, int count, long totalHits, SearchHit[] searchHits) throws JargonException { - - int skipped = 0; - Log log = new Log(); - // load properties for some log entries - PropertiesLoader props = new PropertiesLoader(); - - // go through search hits and populate log entries - if (count > searchHits.length) count = searchHits.length; - for (int c = 0; c < count; c++) { - LogEntry logEntry = new LogEntry(); - // DataONE's Mark Servilla said this entry id should be an object id. - // now set below, near setIdentifier - //logEntry.setEntryId(String.valueOf(start++)); - - Map hit = searchHits[c].sourceAsMap(); - // If this is not a databook event that we recognize, just skip this record - String eventTitle = (String)hit.get("title"); - if ( EventsEnum.valueOfFromDatabook(eventTitle) == EventsEnum.FAILED) { - skipped++; - logger.info("Unrecognized event '{}' when parsing databook events - event skipped", eventTitle); - continue; - } - - Event event = EventsEnum.valueOfFromDatabook((String)hit.get("title")).getDataoneEvent(); - logEntry.setEvent(event); - Date createdDate = new Date((Long)hit.get("created")); - logEntry.setDateLogged(createdDate); - - ArrayList linkingDataEntity = (ArrayList)hit.get("linkingDataEntity"); - Map linkingDataEntity0 = (Map)linkingDataEntity.get(0); - Map dataEntity = (Map)linkingDataEntity0.get("dataEntity"); - - String objectUri = new String((String)dataEntity.get("uri")); - int end = objectUri.indexOf('@'); - String objectPath = objectUri.substring(0, end); - - // check to make sure we can find this data object - // if not just abandon this log entry - String objectId = null; - try { - objectId = getDataObjectEntryId(objectPath); - } catch (FileNotFoundException fnf) { - skipped++; - logger.info("Cannot find dataObject id for : {} - may have been removed - event skipped", objectPath); - continue; - } - - logger.info("found data object id: {}",objectId); - logEntry.setEntryId(objectId); - - // check to make sure we can find this data object in handle server - // if not just abandon this log entry - Identifier identifier = getDataObjectIdentifier(objectPath); - logEntry.setIdentifier(identifier); - NodeReference nodeReference = new NodeReference(); - String nodeIdentifierProp = props.getProperty("irods.dataone.identifier"); - if (nodeIdentifierProp != null) { - nodeReference.setValue(nodeIdentifierProp); - logEntry.setNodeIdentifier(nodeReference); - } - - // ipAddress? not included in elastic search response - - // userAgent not set - - Subject subject = new Subject(); - String subjectString = new String(); - subjectString += props.getProperty("irods.dataone.subject-string"); - subject.setValue(subjectString); - logEntry.setSubject(subject); - - logger.info("adding new log entry: {}", logEntry.getEntryId()); - logger.info(" date logged: {}", logEntry.getDateLogged()); - logger.info(" event: {}", logEntry.getEvent()); - logger.info(" object identifier: {}", logEntry.getIdentifier().getValue()); - logger.info(" node identifier: {}", logEntry.getNodeIdentifier().getValue()); - logger.info(" subject: {}", logEntry.getSubject().getValue()); - log.addLogEntry(logEntry); - } - - // finally - set header values - int total = 0; - log.setStart(start); - log.setCount(searchHits.length - skipped); - if ( totalHits > (long)Integer.MAX_VALUE ) { - total = Integer.MAX_VALUE - skipped; - } - else { - total = (int)totalHits - skipped; - } - log.setTotal(total); - - return log; - } - - - private String getDataOneDataObjectsRegex() throws JargonException { - StringBuilder regexBuilder = new StringBuilder(); - - UniqueIdAOHandleImpl handleImpl = new UniqueIdAOHandleImpl(restConfiguration, irodsAccessObjectFactory); - List uids = handleImpl.getListOfDataoneExposedIdentifiers(); - - for (Identifier uid : uids) { - DataObject dataObject = handleImpl.getDataObjectFromIdentifier(uid); - if (dataObject != null) { - if (regexBuilder.length() > 0) { - regexBuilder.append("|"); - } - regexBuilder.append("\""); - regexBuilder.append(dataObject.getAbsolutePath()); - regexBuilder.append("\".*"); - } - else { - logger.warn("iRODS data object with uid: {} not found " + - "- expecting that this is a DataOne exposed object"); - } - logger.info("regex={}", regexBuilder.toString()); - } - - return regexBuilder.toString(); - } - - - // execute rule to add event to databook event log - // sendAccess("synch_failure", user name, data object uri, object type, timestamp in seconds, short description); - @Override - public void recordEvent(Event event, Identifier id, String description) - throws InvalidArgumentException, JargonException, ServiceFailure { - - // check for valid input parameters - if (event == null) { - throw new InvalidArgumentException("invalid Event parameter"); - } - if (id == null) { - throw new InvalidArgumentException("invalid data object identifier"); - } - - EventsEnum e = EventsEnum.valueOfFromDataOne(event); - String databookEvent = e.getDatabookEvent(); - //Long timeNow = new Long(java.lang.System.currentTimeMillis()/1000); - Long timeNow = new Long(java.lang.System.currentTimeMillis()); - String timeNowStr = timeNow.toString(); - - UniqueIdAOHandleImpl handleImpl = new UniqueIdAOHandleImpl(restConfiguration, irodsAccessObjectFactory); - DataObject dataObject = handleImpl.getDataObjectFromIdentifier(id); - // going to use dataObject path for description - as suggested by Hao 5/1/15 - // this is required in order to be able to query event logs by path later - String pathDescription = dataObject.getAbsolutePath(); - int dataObjectId = dataObject.getId(); - String dataObjIdStr = new Integer(dataObjectId).toString(); -// long dataObjectId = handleImpl.getDataObjectIdFromDataOneIdentifier(id); -// String dataObjIdStr = new Long(dataObjectId).toString(); - - IRODSAccount irodsAccount = RestAuthUtils - .getIRODSAccountFromBasicAuthValues(this.restConfiguration); - RuleProcessingAO ruleProcessingAO = irodsAccessObjectFactory - .getRuleProcessingAO(irodsAccount); - IRODSFile irodsFile = irodsAccessObjectFactory - .getIRODSFileFactory(irodsAccount).instanceIRODSFile(pathDescription); - Long createTime = new Long(irodsFile.lastModified()); - String createTimeStr = createTime.toString(); - - StringBuilder sb = new StringBuilder(); - sb.append("addEventRule {\n"); - sb.append(" sendAccess(\""); - sb.append(databookEvent); - sb.append("\", \""); - sb.append(SUBJECT_USER); - sb.append("\", \""); - sb.append(pathDescription); - sb.append("@"); - sb.append(createTimeStr); - sb.append("\", \""); - sb.append("DataObject"); - sb.append("\", \""); - sb.append(timeNowStr); - - if (description != null) { - sb.append("\", \""); - sb.append(description); - } - sb.append("\");\n}\n"); - sb.append("OUTPUT ruleExecOut"); - String ruleString = sb.toString(); - - IRODSRuleExecResult result = ruleProcessingAO.executeRule(ruleString); - } - - private String getDataObjectEntryId(String dataObjectPath) throws JargonException { - String dataObjectId = null; - - IRODSAccount irodsAccount = RestAuthUtils - .getIRODSAccountFromBasicAuthValues(restConfiguration); - - CollectionAndDataObjectListAndSearchAO collectionAndDataObjectListAndSearchAO = - irodsAccessObjectFactory.getCollectionAndDataObjectListAndSearchAO(irodsAccount); - logger.info("getting object records associated with path: {}", dataObjectPath); - ObjStat objStat = collectionAndDataObjectListAndSearchAO - .retrieveObjectStatForPath(dataObjectPath); - int id = objStat.getDataId(); - dataObjectId = String.valueOf(id); - - return dataObjectId; - } - - private Identifier getDataObjectIdentifier(String dataObjectPath) throws JargonException { - - Identifier identifier = null; - - IRODSAccount irodsAccount = RestAuthUtils - .getIRODSAccountFromBasicAuthValues(restConfiguration); - - DataObjectAO dataObjectAO = irodsAccessObjectFactory.getDataObjectAO(irodsAccount); - UniqueIdAOHandleImpl uniqueIdAOHandleImpl = new UniqueIdAOHandleImpl(restConfiguration, - irodsAccessObjectFactory); - identifier = uniqueIdAOHandleImpl.getIdentifierFromDataObject(dataObjectAO.findByAbsolutePath(dataObjectPath)); - - return identifier; - } - -} diff --git a/src/main/java/org/irods/jargon/dataone/events/EventsEnum.java b/src/main/java/org/irods/jargon/dataone/events/EventsEnum.java deleted file mode 100644 index 143ef20..0000000 --- a/src/main/java/org/irods/jargon/dataone/events/EventsEnum.java +++ /dev/null @@ -1,78 +0,0 @@ -package org.irods.jargon.dataone.events; - -import org.dataone.service.types.v1.Event; - -// Use this class to convert iRODS/Databook type events to DataONE events -public enum EventsEnum { - FAILED(Event.REPLICATION_FAILED, "failed"), - CREATE(Event.CREATE, "put"), - READ(Event.READ, "get"), - UPDATE(Event.UPDATE, "overwrite"), - DELETE(Event.DELETE, "delete"), - REPLICATE(Event.REPLICATE, "replicate"), - SYNCHRONIZATION_FAILED(Event.SYNCHRONIZATION_FAILED, "synch_failure"),; - //REPLICATION_FAILED(),; not supported yet - - private String databookEvent; - private Event dataoneEvent; - - EventsEnum(Event dataoneEvent, String databookEvent) { - this.databookEvent = databookEvent; - this.dataoneEvent = dataoneEvent; - } - - - public Event getDataoneEvent() { - return dataoneEvent; - } - public void setDataoneEvent(Event dataoneEvent) { - this.dataoneEvent = dataoneEvent; - } - - public String getDatabookEvent() { - return databookEvent; - } - public void setDatabookEvent(String databookEvent) { - this.databookEvent = databookEvent; - } - - public static EventsEnum valueOfFromDataOne(Event e) { - switch (e) { - case CREATE: - return CREATE; - case READ: - return READ; - case UPDATE: - return UPDATE; - case DELETE: - return DELETE; - case REPLICATE: - return REPLICATE; - case SYNCHRONIZATION_FAILED: - return SYNCHRONIZATION_FAILED; - //case REPLICATION_FAILED: not supported yet - default: - return READ; - } - } - - public static EventsEnum valueOfFromDatabook(String e) { - if (e.equals("put") || e.equals("data object put")) - return CREATE; - else if (e.equals("get") || e.equals("data object get")) - return READ; - else if (e.equals("overwrite") || e.equals("data object overwrite")) - return UPDATE; - else if (e.equals("delete") || e.equals("data object delete")) - return DELETE; - else if (e.equals("replicate") || e.equals("data object replicate")) - return REPLICATE; - else if (e.equals("synch_failure") || e.equals("data object synch_failure")) - return SYNCHRONIZATION_FAILED; - //else if (e.equals("?")) - //return REPLICATION_FAILED; not supported yet - else - return FAILED; - } - -} \ No newline at end of file diff --git a/src/main/java/org/irods/jargon/dataone/exceptions/ExceptionUtils.java b/src/main/java/org/irods/jargon/dataone/exceptions/ExceptionUtils.java deleted file mode 100644 index 9e9eb50..0000000 --- a/src/main/java/org/irods/jargon/dataone/exceptions/ExceptionUtils.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.irods.jargon.dataone.exceptions; - -import java.io.StringWriter; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.FactoryConfigurationError; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -public class ExceptionUtils { - - private Logger log = LoggerFactory.getLogger(this.getClass()); - - public static String getNotFoundXmlForObjectId(String pid, String detailCode, String description) { - - final String name = "NotFound"; - final String errorCode = "404"; - - DocumentBuilder documentBuilder; - try { - documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); - } catch (ParserConfigurationException e) { - return e.getMessage(); - } catch (FactoryConfigurationError e) { - return e.getMessage(); - } - Document dom = documentBuilder.newDocument(); - // create the root node of the dom - Element errorNode = dom.createElement("error"); - - errorNode.setAttribute("name", name); - errorNode.setAttribute("detailCode", detailCode); - errorNode.setAttribute("errorCode", errorCode); - - Element desc = dom.createElement("description"); - desc.appendChild(dom.createTextNode(description)); - - dom.appendChild(errorNode); - errorNode.appendChild(desc); - - try { - return domToString(dom); - } catch (Exception ex) { -// log.error(ex.getMessage()); - return ex.getMessage(); - } - } - - private static String domToString(Document document) throws Exception { - String result = null; - StringWriter strWtr = new StringWriter(); - TransformerFactory transformerFactory = TransformerFactory.newInstance(); - Transformer transformer = transformerFactory.newTransformer(); - - if (document != null) { - StreamResult strResult = new StreamResult(strWtr); - transformer.transform(new DOMSource(document.getDocumentElement()), strResult); - result = strResult.getWriter().toString(); - } - return result; - } - -} diff --git a/src/main/java/org/irods/jargon/dataone/id/HandleListerRunnable.java b/src/main/java/org/irods/jargon/dataone/id/HandleListerRunnable.java deleted file mode 100644 index 9e86340..0000000 --- a/src/main/java/org/irods/jargon/dataone/id/HandleListerRunnable.java +++ /dev/null @@ -1,183 +0,0 @@ -package org.irods.jargon.dataone.id; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.security.PrivateKey; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.Queue; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import net.handle.hdllib.AbstractMessage; -import net.handle.hdllib.AbstractResponse; -import net.handle.hdllib.HandleException; -import net.handle.hdllib.HandleResolver; -import net.handle.hdllib.ListHandlesRequest; -import net.handle.hdllib.ListHandlesResponse; -import net.handle.hdllib.PublicKeyAuthenticationInfo; -import net.handle.hdllib.ResolutionRequest; -import net.handle.hdllib.ResponseMessageCallback; -import net.handle.hdllib.ServerInfo; -import net.handle.hdllib.SiteInfo; -import net.handle.hdllib.Util; - -// ./hdl-list -s 0.NA/11333 300 ../../svr_1/admpriv.bin 11333 -public class HandleListerRunnable implements Runnable, ResponseMessageCallback { - - - HandleResolver resolver = new HandleResolver(); - private final String authHandle; - private final String authIndex; - private final String privateKey; - private final String namingAuthority; - boolean showValues = true; - //private Queue> results; - private LinkedList> results; - private final List handles; - private Logger log = LoggerFactory.getLogger(this.getClass()); - - public HandleListerRunnable( - //Queue> queue, - LinkedList> queue, - String authHandle, - String authIndex, - String privateKey, - String namingAuthority) { - - // TODO: check for valid args here - log.info("in HandleListerRunnable"); - this.results = queue; - this.authHandle = authHandle; - this.authIndex = authIndex; - this.privateKey = privateKey; - this.namingAuthority = namingAuthority; - this.handles = new ArrayList(); - -// byte[] key = null; -// FileInputStream fs = null; -// //InputStream fs = null; -// try { -// //fs = getClass().getClassLoader().getResourceAsStream(this.privateKey); -// File f = new File(this.privateKey); -// fs = new FileInputStream(f); -// key = new byte[(int)f.length()]; -// int n=0; -// while(n getHandles() { -// return this.handles; -// } - -} diff --git a/src/main/java/org/irods/jargon/dataone/id/UniqueIdAO.java b/src/main/java/org/irods/jargon/dataone/id/UniqueIdAO.java deleted file mode 100644 index 9c7fc86..0000000 --- a/src/main/java/org/irods/jargon/dataone/id/UniqueIdAO.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.irods.jargon.dataone.id; - -import java.util.Date; -import java.util.List; - -import org.dataone.service.types.v1.Identifier; -import org.dataone.service.types.v1.ObjectFormatIdentifier; -import org.irods.jargon.core.exception.JargonException; -import org.irods.jargon.core.pub.domain.DataObject; - -// Access object for unique identifiers that are associated with iRODS Data Objects - -public interface UniqueIdAO { - - //These methods are intended for future support of DataONE MN tiers > 1 - //public Identifier createNewIdentifier(); - //public Identifier createNewIdentifier(String identifier); - //public void deleteIdentifier(String identifier); - - /** - * Returns a DataONE Identifier object for the iRODS Data Object specified - * - * @param dataObject - * DataObject of iRODS Data Object - * associated with the identifier to be returned. - * @throws JargonException - */ - public Identifier getIdentifierFromDataObject(DataObject dataObject) - throws JargonException; - - - /** - * Returns an iRODS Data Object for the DataONE Identifier object specified - * - * @param identifier - * Identifier associated with the iRODS Data Object - * to be returned. - * @throws JargonException - */ - public DataObject getDataObjectFromIdentifier(Identifier identifier) - throws JargonException; - - - - /** - * Returns a complete list of Unique Identifiers that are associated with - * iRODS objects that are exposed to DataONE - * - * @return List<Identifier> - * @throws JargonException - */ - public List getListOfDataoneExposedIdentifiers() - throws JargonException; - - - - /** - * Returns an iRODS Data Object for the DataONE Identifier object specified - * - * @return List<DataObject> - * @throws JargonException - */ - public DataObjectListResponse getListOfDataoneExposedDataObjects( - Date fromDate, - Date toDate, - ObjectFormatIdentifier formatId, - Boolean replicaStatus, - Integer start, - Integer count - ) throws JargonException; - -} diff --git a/src/main/java/org/irods/jargon/dataone/id/UniqueIdAOHandleImpl.java b/src/main/java/org/irods/jargon/dataone/id/UniqueIdAOHandleImpl.java deleted file mode 100644 index c8f6b9b..0000000 --- a/src/main/java/org/irods/jargon/dataone/id/UniqueIdAOHandleImpl.java +++ /dev/null @@ -1,341 +0,0 @@ -package org.irods.jargon.dataone.id; - -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; -import java.util.LinkedList; -import java.util.List; -import java.util.PriorityQueue; -import java.util.Properties; -import java.util.Queue; -import java.util.concurrent.LinkedBlockingQueue; - -import net.handle.hdllib.HandleValue; - -import org.dataone.service.types.v1.Identifier; -import org.dataone.service.types.v1.ObjectFormatIdentifier; -import org.irods.jargon.core.connection.IRODSAccount; -import org.irods.jargon.core.exception.FileNotFoundException; -import org.irods.jargon.core.exception.JargonException; -import org.irods.jargon.core.pub.DataObjectAO; -import org.irods.jargon.core.pub.IRODSAccessObjectFactory; -import org.irods.jargon.core.pub.domain.DataObject; -import org.irods.jargon.core.query.JargonQueryException; -import org.irods.jargon.dataone.auth.RestAuthUtils; -import org.irods.jargon.dataone.configuration.RestConfiguration; -import org.irods.jargon.dataone.utils.DataTypeUtils; -//import org.irods.jargon.dataprofile.DataProfile; -//import org.irods.jargon.dataprofile.DataProfileService; -//import org.irods.jargon.dataprofile.DataProfileServiceImpl; -//import org.irods.jargon.dataprofile.DataTypeResolutionService; -//import org.irods.jargon.dataprofile.DataTypeResolutionServiceImpl; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - - -public class UniqueIdAOHandleImpl implements UniqueIdAO { - - private final RestConfiguration restConfiguration; - private final IRODSAccessObjectFactory irodsAccessObjectFactory; - private Properties properties; - private String propertiesFilename = "d1client.properties"; - private Logger log = LoggerFactory.getLogger(this.getClass()); - - public UniqueIdAOHandleImpl(RestConfiguration restConfiguration, - IRODSAccessObjectFactory irodsAccessObjectFactory) { - this.restConfiguration = restConfiguration; - this.irodsAccessObjectFactory = irodsAccessObjectFactory; - loadProperties(); - } - - @Override - public DataObject getDataObjectFromIdentifier(Identifier identifier) - throws JargonException, FileNotFoundException { - - DataObject dataObject = null; - log.info("retrieving irods data object id from identifier: {}", identifier.getValue()); - long dataObjectId = getDataObjectIdFromDataOneIdentifier(identifier); - log.info("got id: {}", dataObjectId); - - if (dataObjectId < 0) { - throw new FileNotFoundException(""); - } - - try { - IRODSAccount irodsAccount = RestAuthUtils - .getIRODSAccountFromBasicAuthValues(this.restConfiguration); - - DataObjectAO dataObjectAO = irodsAccessObjectFactory.getDataObjectAO(irodsAccount); - log.info("got dataObjectAO: {}", dataObjectAO.toString()); - // Find iRODS object here from Identifier - dataObject = dataObjectAO.findById(new Long(dataObjectId).intValue()); - if (dataObject != null) { - log.info("found iRODS file: {}", dataObject.getAbsolutePath()); - } - else { - log.warn("did not find data object for id={}", dataObjectId); - } - -// } catch (Exception e) { -// log.warn("Cannot access iRODS object for id={}", dataObjectId); -// throw e; - } finally { - irodsAccessObjectFactory.closeSessionAndEatExceptions(); - } - - return dataObject; - } - - @Override - public Identifier getIdentifierFromDataObject(DataObject dataObject) throws JargonException { - - if (dataObject == null) { - log.error("getIdentifierFromDataObject: dataObject is null"); - throw new JargonException("dataObject is null"); - } - Identifier identifier = new Identifier(); - - String prefix = getHandlePrefix(); - if (prefix == null) { - log.error("getIdentifierFromDataObject: prefix is null"); - throw new JargonException("prefix is null"); - } - String objectId = String.valueOf(dataObject.getId()); - - identifier.setValue(prefix + "/" + objectId); - - return identifier; - } - - @Override - public List getListOfDataoneExposedIdentifiers() - throws JargonException { - - List identifiers = new ArrayList(); - - // retrieve properties to get list of current handles from - // handle server - StringBuilder hdl = new StringBuilder(); - hdl.append(properties.getProperty("irods.dataone.handle.namingAuthority")); - hdl.append("/"); - hdl.append(properties.getProperty("irods.dataone.handle.prefix")); - String authHandle = hdl.toString(); - String authIndex = properties.getProperty("irods.dataone.handle.index"); - String privateKey = properties.getProperty("irods.dataone.handle.privateKeyPath"); - String namingAuthority = properties.getProperty("irods.dataone.handle.prefix"); - - log.info("config params for handle lister:"); - log.info("authHandle: {}", authHandle); - log.info("authIndex:{}", authIndex); - log.info("privateKey: {}", privateKey); - log.info("namingAuthority: {}", namingAuthority); - - //LinkedBlockingQueue> queue = new LinkedBlockingQueue>(); - LinkedList> queue = new LinkedList>(); - - HandleListerRunnable hlThread = new HandleListerRunnable( - queue, - authHandle, - authIndex, - privateKey, - namingAuthority); - hlThread.run(); - log.info("continuing after call to run"); - - synchronized (queue) { - while (queue.isEmpty()) { - try { - queue.wait(); - } catch (InterruptedException e) { - log.warn("getListOfDataoneExposedIdentifiers: caught InterruptedException while waiting for queue"); - } - } - } - - List handles = null; - if (! queue.isEmpty()) { - log.debug("listObjects: got list of Handle values"); - handles = queue.element(); - } - - if (handles != null) { - log.info("listObjects: got list of Handle values: {}", handles.toString()); - - for (String h : handles) { - Identifier id = new Identifier(); - id.setValue(h); - identifiers.add(id); - } - } - - log.info("returning identifiers: {}", identifiers); - return identifiers; - } - - @Override - public DataObjectListResponse getListOfDataoneExposedDataObjects( - Date fromDate, - Date toDate, - ObjectFormatIdentifier formatId, - Boolean replicaStatus, - Integer start, - Integer count - ) throws JargonException { - - //get complete list of exposed data objects - // TODO: see if this can be done differently to just request list - // using filter items - DataObjectListResponse dataObjectListResponse = new DataObjectListResponse(); - List dataObjectListTmp = new ArrayList(); - List dataObjectListFinal = new ArrayList(); - List ids = getListOfDataoneExposedIdentifiers(); - - log.info("finding list of data objects with list of {} identifiers", ids.size()); - - for (Identifier id : ids) { - DataObject dataObject; - try { - dataObject = getDataObjectFromIdentifier(id); - } catch (JargonException ex) { - // just ignore this id - dataObject = null; - } - - if (dataObject != null) { - Date modifiedDate = dataObject.getUpdatedAt(); - - if (matchesFromDate(fromDate, modifiedDate) && - matchesToDate(toDate, modifiedDate) && - //matchesFormatId(formatId, dataObject) && support not required - matchesReplicaStatus(replicaStatus)) { - dataObjectListTmp.add(dataObject); - } - } - } - //save total before filtering with start and count - dataObjectListResponse.setTotal(dataObjectListTmp.size()); - - // now filter this list according to start and count - if (dataObjectListTmp.size() > 0) { - DataObject[] dataObjectArray = - dataObjectListTmp.toArray(new DataObject[dataObjectListTmp.size()]); - int end = start + count; - for (int i=start; i= dataObjectModDate.getTime()) { - log.info("toDate : returning matches"); - return true; - } - - log.info("toDate : returning no match"); - return false; - } - - private boolean matchesFormatId(ObjectFormatIdentifier formatId, DataObject dataObject) - throws JargonException, JargonQueryException { - - IRODSAccount irodsAccount = RestAuthUtils - .getIRODSAccountFromBasicAuthValues(this.restConfiguration); - String dataFormat = DataTypeUtils.getDataObjectFormatFromMetadata(irodsAccount, irodsAccessObjectFactory, dataObject); - - if ((formatId.getValue() == null) || (formatId.getValue().equals(dataFormat))) { - return true; - } - return false; - } - - private boolean matchesReplicaStatus(Boolean replicaStatus) { - - // replication is always set to false for now - if (replicaStatus == null || replicaStatus == false) { - log.info("replicastatus : returning matches"); - return true; - } - - log.info("toDate : returning no match"); - return false; - } - -} diff --git a/src/main/java/org/irods/jargon/dataone/id/UniqueIdAOHandleInMetadataImpl.java b/src/main/java/org/irods/jargon/dataone/id/UniqueIdAOHandleInMetadataImpl.java deleted file mode 100644 index 1faeb15..0000000 --- a/src/main/java/org/irods/jargon/dataone/id/UniqueIdAOHandleInMetadataImpl.java +++ /dev/null @@ -1,380 +0,0 @@ -package org.irods.jargon.dataone.id; - -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; -import java.util.List; -import java.util.Properties; - -import org.dataone.service.types.v1.Identifier; -import org.dataone.service.types.v1.ObjectFormatIdentifier; -import org.irods.jargon.core.connection.IRODSAccount; -import org.irods.jargon.core.exception.FileNotFoundException; -import org.irods.jargon.core.exception.JargonException; -import org.irods.jargon.core.pub.DataObjectAO; -import org.irods.jargon.core.pub.IRODSAccessObjectFactory; -import org.irods.jargon.core.pub.domain.DataObject; -import org.irods.jargon.core.query.AVUQueryElement; -import org.irods.jargon.core.query.AVUQueryElement.AVUQueryPart; -import org.irods.jargon.core.query.AVUQueryOperatorEnum; -import org.irods.jargon.core.query.JargonQueryException; -import org.irods.jargon.dataone.auth.RestAuthUtils; -import org.irods.jargon.dataone.configuration.RestConfiguration; -import org.irods.jargon.dataone.utils.DataTypeUtils; -//import org.irods.jargon.dataprofile.DataProfile; -//import org.irods.jargon.dataprofile.DataProfileService; -//import org.irods.jargon.dataprofile.DataProfileServiceImpl; -//import org.irods.jargon.dataprofile.DataTypeResolutionService; -//import org.irods.jargon.dataprofile.DataTypeResolutionServiceImpl; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - - -public class UniqueIdAOHandleInMetadataImpl implements UniqueIdAO { - - private final RestConfiguration restConfiguration; - private final IRODSAccessObjectFactory irodsAccessObjectFactory; - private Properties properties; - private String propertiesFilename = "d1client.properties"; - private Logger log = LoggerFactory.getLogger(this.getClass()); - - public UniqueIdAOHandleInMetadataImpl(RestConfiguration restConfiguration, - IRODSAccessObjectFactory irodsAccessObjectFactory) { - this.restConfiguration = restConfiguration; - this.irodsAccessObjectFactory = irodsAccessObjectFactory; - loadProperties(); - } - - @Override - public DataObject getDataObjectFromIdentifier(Identifier identifier) - throws JargonException, FileNotFoundException { - - DataObject dataObject = null; - log.info("retrieving irods data object id from identifier: {}", identifier.getValue()); - long dataObjectId = getDataObjectIdFromDataOneIdentifier(identifier); - log.info("got id: {}", dataObjectId); - - // DataObjectAO.findDomainByMetadataQuery - // returns List - - if (dataObjectId < 0) { - throw new FileNotFoundException(""); - } - - try { - IRODSAccount irodsAccount = RestAuthUtils - .getIRODSAccountFromBasicAuthValues(this.restConfiguration); - - DataObjectAO dataObjectAO = irodsAccessObjectFactory.getDataObjectAO(irodsAccount); - log.info("got dataObjectAO: {}", dataObjectAO.toString()); - // Find iRODS object here from Identifier - dataObject = dataObjectAO.findById(new Long(dataObjectId).intValue()); - if (dataObject != null) { - log.info("found iRODS file: {}", dataObject.getAbsolutePath()); - } - else { - log.warn("did not find data object for id={}", dataObjectId); - } - -// } catch (Exception e) { -// log.warn("Cannot access iRODS object for id={}", dataObjectId); -// throw e; - } finally { - irodsAccessObjectFactory.closeSessionAndEatExceptions(); - } - - return dataObject; - } - - @Override - public Identifier getIdentifierFromDataObject(DataObject dataObject) throws JargonException { - - if (dataObject == null) { - log.error("getIdentifierFromDataObject: dataObject is null"); - throw new JargonException("dataObject is null"); - } - Identifier identifier = new Identifier(); - - String prefix = getHandlePrefix(); - if (prefix == null) { - log.error("getIdentifierFromDataObject: prefix is null"); - throw new JargonException("prefix is null"); - } - String objectId = String.valueOf(dataObject.getId()); - - identifier.setValue(prefix + "/" + objectId); - - return identifier; - } - - @Override - public List getListOfDataoneExposedIdentifiers() - throws JargonException { - - AVUQueryElement avuQuery1 = null; - AVUQueryElement avuQuery2 = null; - - String handleAttr = properties.getProperty("irods.dataone.publish_entity_metadata_attr"); - String handleValue = properties.getProperty("irods.dataone.publish_entity_metadata_value"); - - List identifiers = new ArrayList(); - - try { - avuQuery1 = AVUQueryElement.instanceForValueQuery( - AVUQueryPart.ATTRIBUTE, - AVUQueryOperatorEnum.EQUAL, - handleAttr); - - avuQuery2 = AVUQueryElement.instanceForValueQuery( - AVUQueryPart.VALUE, - AVUQueryOperatorEnum.EQUAL, - handleValue); - - } catch (JargonQueryException e) { - log.error("getListOfDataoneExposedIdentifiers: failed to create AVU query elements"); - return identifiers; - } - - IRODSAccount irodsAccount = RestAuthUtils - .getIRODSAccountFromBasicAuthValues(this.restConfiguration); - - DataObjectAO dataObjectAO = irodsAccessObjectFactory.getDataObjectAO(irodsAccount); - List dataObjects = new ArrayList(); - try { - dataObjects = dataObjectAO.findDomainByMetadataQuery(Arrays.asList(avuQuery1, avuQuery2)); - } catch (JargonQueryException e) { - log.error("getListOfDataoneExposedIdentifiers: failed to execute AVU query"); - return identifiers; - } - - // restrict start date for now to 2/10/16 - Date afterDate = new Date(Long.parseLong("1455062400") * 1000); - for(DataObject dataObject : dataObjects) { - if(dataObject.getCreatedAt().after(afterDate)) { - identifiers.add(getIdentifierFromDataObject(dataObject)); - } - } - - log.info("returning identifiers: {}", identifiers); - return identifiers; - } - - @Override - public DataObjectListResponse getListOfDataoneExposedDataObjects( - Date fromDate, - Date toDate, - ObjectFormatIdentifier formatId, - Boolean replicaStatus, - Integer start, - Integer count - ) throws JargonException { - - int total = 0; - - DataObjectListResponse dataObjectListResponse = new DataObjectListResponse(); - - List avuQueryList = createAVUQueryElementList(fromDate, toDate, formatId); - - IRODSAccount irodsAccount = RestAuthUtils - .getIRODSAccountFromBasicAuthValues(this.restConfiguration); - - DataObjectAO dataObjectAO = irodsAccessObjectFactory.getDataObjectAO(irodsAccount); - List dataObjects = new ArrayList(); - - try { - dataObjects = dataObjectAO.findDomainByMetadataQuery(avuQueryList, start); - // save original size of set returned - total = dataObjects.size(); - } catch (JargonQueryException e) { - log.error("test_getListOfDataoneExposedDataObjects: failed to execute AVU query"); - return dataObjectListResponse; - } - - // truncate list if count is specified and it is less than the total - List finalDataObjects = new ArrayList(); - if ((count >= 0) && (count < total)) { - finalDataObjects = dataObjects.subList(0, count); - } - else { - finalDataObjects = dataObjects; - } - - dataObjectListResponse.setTotal(total); - dataObjectListResponse.count = finalDataObjects.size(); - dataObjectListResponse.setDataObjects(finalDataObjects); - - return dataObjectListResponse; - } - - - public long getDataObjectIdFromDataOneIdentifier(Identifier pid) { - - int idIdx = pid.getValue().indexOf("/")+1; - long dataObjectId; - try { - dataObjectId = Long.parseLong(pid.getValue().substring(idIdx)); - } catch (NumberFormatException e) { - // set to catch illegal object identifiers for iRODS MN - dataObjectId = -1; - } - - log.info("getDataObjectIdFromDataOneIdentifier: returning data object id: {}", dataObjectId); - return dataObjectId; - } - - public String getHandlePrefix() throws JargonException { - String prefix = null; - - prefix = properties.getProperty("irods.dataone.handle.prefix"); - - return prefix; - } - - private void loadProperties() { - this.properties = new Properties(); - InputStream input = null; - input = getClass().getClassLoader().getResourceAsStream(this.propertiesFilename); - - // load a properties file - try { - this.properties.load(input); - } catch (IOException e) { - log.error("Cannot load Member Node properties file: {}", this.propertiesFilename); - log.error("IOException: {}", e.getStackTrace()); - this.properties = new Properties(); - } finally { - if (input != null) { - try { - input.close(); - } catch (IOException e) { - // do nothing - } - } - } - } - - - private List createAVUQueryElementList( - Date fromDate, - Date toDate, - ObjectFormatIdentifier formatId) { - - // TODO: probably should move these to properties - String dateAttr = "StartDateTime"; - String formatAttr = "Format"; - List avuQueryList = new ArrayList(); - String handleAttr = properties.getProperty("irods.dataone.publish_entity_metadata_attr"); - String handleValue = properties.getProperty("irods.dataone.publish_entity_metadata_value"); - - AVUQueryElement avuQuery; - try { - // DataOne exposed query - avuQuery = AVUQueryElement.instanceForValueQuery( - AVUQueryPart.ATTRIBUTE, - AVUQueryOperatorEnum.EQUAL, - handleAttr); - avuQueryList.add(avuQuery); - - avuQuery = AVUQueryElement.instanceForValueQuery( - AVUQueryPart.VALUE, - AVUQueryOperatorEnum.EQUAL, - handleValue); - avuQueryList.add(avuQuery); - - // handle any date queries - // restrict start date for now to 2/17/16 00:00:01 : 1455667201 - // 3-23-16 Update - now changed earliest data to 3/23/16 00:00:01 : 1458691201 - // 3-31-16 Update - now changed earliest data to 3/28/16 00:00:01 GMT : 1459123201 - long newFromDate; - if(fromDate != null) { - newFromDate = java.lang.Math.max(fromDate.getTime()/1000, Long.parseLong("1459123201")); - } - else { - newFromDate = Long.parseLong("1459123201"); - } - - // fromDate query - avuQuery = AVUQueryElement.instanceForValueQuery( - AVUQueryPart.ATTRIBUTE, - AVUQueryOperatorEnum.EQUAL, - dateAttr); - avuQueryList.add(avuQuery); - - avuQuery = AVUQueryElement.instanceForValueQuery( - AVUQueryPart.VALUE, - AVUQueryOperatorEnum.GREATER_OR_EQUAL, - Long.toString(newFromDate)); - avuQueryList.add(avuQuery); - - // toDate query - if ((toDate != null) && ((toDate.getTime()/1000) >= newFromDate)) { - avuQuery = AVUQueryElement.instanceForValueQuery( - AVUQueryPart.ATTRIBUTE, - AVUQueryOperatorEnum.EQUAL, - dateAttr); - avuQueryList.add(avuQuery); - - avuQuery = AVUQueryElement.instanceForValueQuery( - AVUQueryPart.VALUE, - AVUQueryOperatorEnum.LESS_THAN, - Long.toString(toDate.getTime()/1000)); - avuQueryList.add(avuQuery); - - } - - -// if ((toDate != null) && (toDate.getTime() >= newFromDate)) { -// avuQuery = AVUQueryElement.instanceForValueQuery( -// AVUQueryPart.ATTRIBUTE, -// AVUQueryOperatorEnum.EQUAL, -// dateAttr); -// avuQueryList.add(avuQuery); -// -// avuQuery = AVUQueryElement.instanceForValueQuery( -// AVUQueryPart.VALUE, -// AVUQueryOperatorEnum.BETWEEN, -// Long.toString(toDate.getTime()/1000)); -// avuQueryList.add(avuQuery); -// -// } -// else { -// avuQuery = AVUQueryElement.instanceForValueQuery( -// AVUQueryPart.ATTRIBUTE, -// AVUQueryOperatorEnum.EQUAL, -// dateAttr); -// avuQueryList.add(avuQuery); -// -// avuQuery = AVUQueryElement.instanceForValueQuery( -// AVUQueryPart.VALUE, -// AVUQueryOperatorEnum.GREATER_OR_EQUAL, -// Long.toString(newFromDate)); -// avuQueryList.add(avuQuery); -// -// } - - // handle data format query - if ((formatId != null) && (formatId.getValue() != null)) { - avuQuery = AVUQueryElement.instanceForValueQuery( - AVUQueryPart.ATTRIBUTE, - AVUQueryOperatorEnum.EQUAL, - formatAttr); - avuQueryList.add(avuQuery); - - avuQuery = AVUQueryElement.instanceForValueQuery( - AVUQueryPart.VALUE, - AVUQueryOperatorEnum.EQUAL, - formatId.getValue()); - avuQueryList.add(avuQuery); - - } - } catch (JargonQueryException e) { - log.error("createAVUQueryElementList: failed to construct AVU query"); - return avuQueryList; - } - - return avuQueryList; - } - -} diff --git a/src/main/java/org/irods/jargon/dataone/id/package-info.java b/src/main/java/org/irods/jargon/dataone/id/package-info.java deleted file mode 100644 index 3a2f768..0000000 --- a/src/main/java/org/irods/jargon/dataone/id/package-info.java +++ /dev/null @@ -1,8 +0,0 @@ -/** - * - */ -/** - * @author lisa - * - */ -package org.irods.jargon.dataone.id; \ No newline at end of file diff --git a/src/main/java/org/irods/jargon/dataone/tier1/MNCoreImpl.java b/src/main/java/org/irods/jargon/dataone/tier1/MNCoreImpl.java deleted file mode 100644 index 2cb4691..0000000 --- a/src/main/java/org/irods/jargon/dataone/tier1/MNCoreImpl.java +++ /dev/null @@ -1,175 +0,0 @@ -package org.irods.jargon.dataone.tier1; - -import org.dataone.service.exceptions.*; -import org.dataone.service.mn.tier1.v1.MNCore; -import org.dataone.service.types.v1.Event; -import org.dataone.service.types.v1.Log; -import org.dataone.service.types.v1.Node; -import org.dataone.service.types.v1.Ping; -import org.dataone.service.types.v1.Session; -import org.dataone.service.types.v1.Subject; -import org.dataone.service.types.v1.Synchronization; -import org.dataone.service.types.v1.NodeState; -import org.elasticsearch.client.transport.NoNodeAvailableException; -import org.irods.jargon.core.connection.IRODSAccount; -import org.irods.jargon.core.pub.EnvironmentalInfoAO; -import org.irods.jargon.core.pub.IRODSAccessObjectFactory; -import org.irods.jargon.dataone.auth.RestAuthUtils; -import org.irods.jargon.dataone.configuration.RestConfiguration; -import org.irods.jargon.dataone.events.EventLogAOElasticSearchImpl; -import org.irods.jargon.dataone.events.EventsEnum; -import org.irods.jargon.dataone.utils.PropertiesLoader; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - - -public class MNCoreImpl implements MNCore { - - private Logger log = LoggerFactory.getLogger(this.getClass()); - private final IRODSAccessObjectFactory irodsAccessObjectFactory; - private final RestConfiguration restConfiguration; -// private final MNCoreModel mnCoreModel; - - public MNCoreImpl( - IRODSAccessObjectFactory irodsAccessObjectFactory, - RestConfiguration restConfiguration) { - - this.irodsAccessObjectFactory = irodsAccessObjectFactory; - this.restConfiguration = restConfiguration; -// this.mnCoreModel = new MNCoreModel(irodsAccessObjectFactory, restConfiguration); - } - - @Override - public Date ping() throws NotImplemented, ServiceFailure, InsufficientResources { - - try { - IRODSAccount irodsAccount = RestAuthUtils - .getIRODSAccountFromBasicAuthValues(restConfiguration); - - EnvironmentalInfoAO environmentalInfoAO = irodsAccessObjectFactory - .getEnvironmentalInfoAO(irodsAccount); - - long currentTime = environmentalInfoAO.getIRODSServerCurrentTime(); - return new Date(currentTime); - - } catch (Exception e) { - log.error("ping failed: {}", e.getMessage()); - throw new ServiceFailure("2042", "failed to contact iRODS server"); - } finally { - irodsAccessObjectFactory.closeSessionAndEatExceptions(); - } - } - - @Override - public Log getLogRecords( - Date fromDate, - Date toDate, - Event event, - String pidFilter, - Integer startIdx, - Integer count) - throws InvalidRequest, - InvalidToken, - NotAuthorized, - NotImplemented, - ServiceFailure { - - Log d1log = new Log(); - EventsEnum newEvent = null; - - log.info("getLogRecords: elasticsearch implementation"); - if (event != null) { - newEvent = EventsEnum.valueOfFromDataOne(event); - } - - EventLogAOElasticSearchImpl eventLogAO = - new EventLogAOElasticSearchImpl(irodsAccessObjectFactory, restConfiguration); - try { - d1log = eventLogAO.getLogs(fromDate, toDate, newEvent, pidFilter, startIdx, count); - } catch(NoNodeAvailableException ex) { - throw new ServiceFailure("1490", "retrieval of log records failed"); - } - - return d1log; - } - - @Override - public Node getCapabilities() throws NotImplemented, ServiceFailure { - - Node node = new Node(); - - Ping ping = new Ping(); - ping.setSuccess(true); - node.setState(NodeState.UP); - - try { - IRODSAccount irodsAccount = RestAuthUtils - .getIRODSAccountFromBasicAuthValues(restConfiguration); - - EnvironmentalInfoAO environmentalInfoAO = irodsAccessObjectFactory - .getEnvironmentalInfoAO(irodsAccount); - - long bootTime = environmentalInfoAO.getIRODSServerProperties().getServerBootTime(); - - } catch (Exception e) { - log.error("getCapabilities: iRODS server is not running"); - ping.setSuccess(false); - node.setState(NodeState.DOWN); - } finally { - irodsAccessObjectFactory.closeSessionAndEatExceptions(); - } - - // get properties - PropertiesLoader pl = new PropertiesLoader(); - String subjectString = new String(); - subjectString += pl.getProperty("irods.dataone.subject-string"); - String contactSubjectString = new String(); - contactSubjectString += pl.getProperty("irods.dataone.contact-subject-string"); - - List subjects = new ArrayList(); - Subject subject = new Subject(); - subject.setValue(subjectString); - subjects.add(subject); - List contactSubjects = new ArrayList(); - Subject contactSubject = new Subject(); - contactSubject.setValue(contactSubjectString); - contactSubjects.add(contactSubject); - - node.setPing(ping); - node.setSubjectList(subjects); - node.setContactSubjectList(contactSubjects); - - Synchronization sync = new Synchronization(); - // TODO: put correct dates here - sync.setLastCompleteHarvest(new Date()); - sync.setLastHarvested(new Date()); - node.setSynchronization(sync); - - log.info("returning node: {}", node.toString()); - - return node; - } - - @Override - public Log getLogRecords( - Session session, - Date date1, - Date date2, - Event event, - String s, - Integer integer1, - Integer integer2) - throws InvalidRequest, - InvalidToken, - NotAuthorized, - NotImplemented, - ServiceFailure { - - throw new NotImplemented("1461", "Authenticated getLogRecords not implemented"); - } - -} diff --git a/src/main/java/org/irods/jargon/dataone/tier1/MNReadImpl.java b/src/main/java/org/irods/jargon/dataone/tier1/MNReadImpl.java deleted file mode 100644 index 8f69440..0000000 --- a/src/main/java/org/irods/jargon/dataone/tier1/MNReadImpl.java +++ /dev/null @@ -1,714 +0,0 @@ -package org.irods.jargon.dataone.tier1; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import javax.servlet.http.HttpServletResponse; - -import org.apache.tika.detect.DefaultDetector; -import org.apache.tika.detect.TypeDetector; -import org.apache.tika.metadata.Metadata; -import org.apache.tika.mime.MediaType; -import org.dataone.service.exceptions.InsufficientResources; -import org.dataone.service.exceptions.InvalidRequest; -import org.dataone.service.exceptions.InvalidToken; -import org.dataone.service.exceptions.NotAuthorized; -import org.dataone.service.exceptions.NotFound; -import org.dataone.service.exceptions.NotImplemented; -import org.dataone.service.exceptions.ServiceFailure; -import org.dataone.service.exceptions.SynchronizationFailed; -import org.dataone.service.mn.tier1.v1.MNRead; -import org.dataone.service.types.v1.AccessPolicy; -import org.dataone.service.types.v1.AccessRule; -import org.dataone.service.types.v1.Checksum; -import org.dataone.service.types.v1.DescribeResponse; -import org.dataone.service.types.v1.Event; -import org.dataone.service.types.v1.Identifier; -import org.dataone.service.types.v1.NodeReference; -import org.dataone.service.types.v1.ObjectFormatIdentifier; -import org.dataone.service.types.v1.ObjectInfo; -import org.dataone.service.types.v1.ObjectList; -import org.dataone.service.types.v1.Permission; -import org.dataone.service.types.v1.ReplicationPolicy; -import org.dataone.service.types.v1.Session; -import org.dataone.service.types.v1.Subject; -import org.dataone.service.types.v1.SystemMetadata; -import org.irods.jargon.core.connection.IRODSAccount; -import org.irods.jargon.core.exception.FileNotFoundException; -import org.irods.jargon.core.exception.JargonException; -import org.irods.jargon.core.protovalues.FilePermissionEnum; -import org.irods.jargon.core.pub.DataObjectAO; -import org.irods.jargon.core.pub.IRODSAccessObjectFactory; -//import org.irods.jargon.dataprofile.DataProfileService; -//import org.irods.jargon.dataprofile.DataTypeResolutionService; -//import org.irods.jargon.dataprofile.DataTypeResolutionServiceImpl; -//import org.irods.jargon.dataprofile.DataProfileServiceImpl; -//import org.irods.jargon.dataprofile.DataProfile; -//import org.irods.jargon.core.pub.Stream2StreamAO; -import org.irods.jargon.core.pub.domain.DataObject; -import org.irods.jargon.core.pub.io.IRODSFile; -import org.irods.jargon.core.pub.io.IRODSFileInputStream; -import org.irods.jargon.dataone.auth.RestAuthUtils; -import org.irods.jargon.dataone.configuration.RestConfiguration; -import org.irods.jargon.dataone.domain.MNPermissionEnum; -import org.irods.jargon.dataone.events.EventLogAOElasticSearchImpl; -import org.irods.jargon.dataone.id.DataObjectListResponse; -import org.irods.jargon.dataone.id.UniqueIdAOHandleImpl; -import org.irods.jargon.dataone.id.UniqueIdAOHandleInMetadataImpl; -import org.irods.jargon.dataone.utils.DataObjectMetadataUtils; -import org.irods.jargon.dataone.utils.DataTypeUtils; -import org.irods.jargon.dataone.utils.PropertiesLoader; -import org.irods.jargon.core.pub.domain.UserFilePermission; -import org.irods.jargon.core.query.JargonQueryException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - - -public class MNReadImpl implements MNRead { - - private Logger log = LoggerFactory.getLogger(this.getClass()); - - private final IRODSAccessObjectFactory irodsAccessObjectFactory; - private final RestConfiguration restConfiguration; - - private PropertiesLoader properties = new PropertiesLoader(); - - public MNReadImpl( - IRODSAccessObjectFactory irodsAccessObjectFactory, - RestConfiguration restConfiguration) { - - this.irodsAccessObjectFactory = irodsAccessObjectFactory; - this.restConfiguration = restConfiguration; - } - - @Override - public DescribeResponse describe(Identifier id) throws InvalidToken, - NotAuthorized, NotImplemented, ServiceFailure, NotFound { - - if (id == null || id.getValue().isEmpty()) { - log.error("id is null or empty"); - throw new NotFound("1402", "invalid iRODS data object id"); - } - - DataObject dataObject = new DataObject(); - Checksum checksum = new Checksum(); - ObjectFormatIdentifier formatIdentifier = new ObjectFormatIdentifier(); - BigInteger contentLength; - Date lastModified; - BigInteger serialVersion; - - try { - // need last modified, content length, Content-Type: application/octet-stream, object format (mime), checksum, serial version - UniqueIdAOHandleImpl handleImpl = new UniqueIdAOHandleImpl(restConfiguration, irodsAccessObjectFactory); - dataObject = handleImpl.getDataObjectFromIdentifier(id); - } catch (Exception e) { - log.info("cannot find id: {}", id.getValue()); - throw new NotFound("1380", "The specified object does not exist on this node."); - } - - try { - Long contentLengthLong = dataObject.getDataSize(); - String contentLengthStr = contentLengthLong.toString(); - contentLength = new BigInteger(contentLengthStr); - - IRODSAccount irodsAccount = RestAuthUtils - .getIRODSAccountFromBasicAuthValues(restConfiguration); - - //lastModified = dataObject.getUpdatedAt(); - lastModified = DataObjectMetadataUtils.getStartDateTime(irodsAccessObjectFactory, irodsAccount, dataObject); - - String format = DataTypeUtils.getDataObjectFormatFromMetadata(irodsAccount, irodsAccessObjectFactory, dataObject); - // use back up if no format stores in dataObject AVU - if (format == null ) { - format = getDataObjectMimeType(irodsAccount, dataObject); - } - formatIdentifier.setValue(format); - - String csum = dataObject.getChecksum(); - if (csum == null) { - log.info("checksum does not exist for file: {}", dataObject.getAbsolutePath()); - //throw new NotFound("404", "1420"); - } - else { - checksum.setValue(csum); - checksum.setAlgorithm(properties.getProperty("irods.dataone.chksum-algorithm")); - } - - serialVersion = getSerialVersion(); - - } catch (Exception e) { - log.error("Cannot access iRODS object: {}", dataObject.getAbsolutePath()); - throw new ServiceFailure("1390", e.getMessage()); - } finally { - irodsAccessObjectFactory.closeSessionAndEatExceptions(); - } - return new DescribeResponse(formatIdentifier, contentLength, lastModified, checksum, serialVersion); - } - - @Override - public DescribeResponse describe(Session arg0, Identifier arg1) - throws InvalidToken, NotAuthorized, NotImplemented, ServiceFailure, - NotFound { - throw new NotImplemented("1361", "this service has not been implemented"); - } - - public void streamObject(HttpServletResponse response, Identifier id) throws ServiceFailure, NotFound { - - IRODSFileInputStream stream = null; - OutputStream output = null; - int contentLength = 0; - String path = new String(); - DataObject dataObject = new DataObject(); - IRODSAccount irodsAccount; - IRODSFile irodsFile; - - // first try and find data object for this id - try { - irodsAccount = RestAuthUtils - .getIRODSAccountFromBasicAuthValues(restConfiguration); - - UniqueIdAOHandleImpl handleImpl = new UniqueIdAOHandleImpl(restConfiguration, irodsAccessObjectFactory); - dataObject = handleImpl.getDataObjectFromIdentifier(id); - path = dataObject.getAbsolutePath(); - irodsFile = irodsAccessObjectFactory - .getIRODSFileFactory(irodsAccount).instanceIRODSFile(path); - - if (!irodsFile.exists()) { - log.info("file does not exist"); - throw new NotFound("1020", "No data object could be found for given PID:" + id.getValue()); - } - } catch(Exception ex) { - log.info("file does not exist"); - throw new NotFound("1020", "No data object could be found for given PID:" + id.getValue()); - } - - // now try and stream it - try { - - stream = irodsAccessObjectFactory - .getIRODSFileFactory(irodsAccount) - .instanceIRODSFileInputStream(irodsFile); - // TODO: need to catch and return appropriate exceptions here for no permission - - - contentLength = (int) irodsFile.length(); - log.info("contentLength={}", contentLength); - - response.setContentType("application/octet-stream"); - response.setHeader("Content-Disposition","attachment;filename=" + dataObject.getDataName()); - response.setContentLength(contentLength); - //response.addHeader("Vary", "Accept-Encoding"); - log.info("reponse: {}", response.toString()); - - output = new BufferedOutputStream(response.getOutputStream()); - -// Stream2StreamAO stream2StreamAO = getIrodsAccessObjectFactory() -// .getStream2StreamAO(irodsAccount); -// stream2StreamAO.streamToStreamCopyUsingStandardIO(input, output); - - int readBytes = 0; - byte [] buffer = new byte [4096]; - - while ((readBytes = stream.read (buffer,0,4096)) != -1) { - //log.info("readBytes={}", readBytes); - output.write (buffer,0,readBytes); - } - output.flush(); - if(stream != null) - stream.close(); - if(output != null) - output.close(); - - } catch (Exception e) { - log.error("Cannot stream iRODS object: {}", path); - throw new ServiceFailure("1030", "unable to stream iRODS data object"); - } finally { - irodsAccessObjectFactory.closeSessionAndEatExceptions(); - } - } - - @Override - public IRODSFileInputStream get(Identifier id) throws InvalidToken, NotAuthorized, - NotImplemented, ServiceFailure, NotFound, InsufficientResources { - - // TODO: Not sure how to implement this properly - used streamObject method instead - IRODSFileInputStream stream = null; - -// if (id == null || id.toString().isEmpty()) { -// throw new NotFound("invalid", "identifier is invalid"); -// } - -// String path = "/dfcmain/home/DFC-public/DFC-slide.pptx"; -// String path = "/dfcmain/home/lisa/test_this.txt"; - - -// log.info("decoded path:{}", path); -// -// try { -// IRODSAccount irodsAccount = RestAuthUtils -// .getIRODSAccountFromBasicAuthValues(restConfiguration); -// IRODSFile irodsFile = irodsAccessObjectFactory -// .getIRODSFileFactory(irodsAccount).instanceIRODSFile(path); -// -// if (!irodsFile.exists()) { -// log.info("file does not exist"); -// throw new NotFound("404", "The iRODS member node can't find object requested - "+id.toString()); -// } -// -// stream = irodsAccessObjectFactory -// .getIRODSFileFactory(irodsAccount) -// .instanceIRODSFileInputStream(irodsFile); -// -// } catch (Exception e) { -// throw new ServiceFailure(e.getMessage(), e.toString()); -// } finally { -// irodsAccessObjectFactory.closeSessionAndEatExceptions(); -// -// } - - return stream; - } - - @Override - public InputStream get(Session arg0, Identifier arg1) throws InvalidToken, - NotAuthorized, NotImplemented, ServiceFailure, NotFound, - InsufficientResources { - throw new NotImplemented("1001", "this service has not been implemented"); - } - - @Override - public Checksum getChecksum(Identifier id, String algorithm) - throws InvalidRequest, InvalidToken, NotAuthorized, NotImplemented, - ServiceFailure, NotFound { - - if (id == null || id.getValue().isEmpty()) { - throw new NotFound("1420", "invalid iRODS data object id"); - } - - if (algorithm == null || algorithm.isEmpty()) { - throw new NotFound("1420", "invalid checksum algorithm provided"); - } - - DataObject dataObject = new DataObject(); - Checksum checksum = new Checksum(); - - try { - - UniqueIdAOHandleImpl handleImpl = new UniqueIdAOHandleImpl(restConfiguration, irodsAccessObjectFactory); - dataObject = handleImpl.getDataObjectFromIdentifier(id); - String csum = dataObject.getChecksum(); - if (csum == null) { - log.info("checksum does not exist for file: {}", dataObject.getAbsolutePath()); - throw new NotFound("1410", "Checksum does not exist for data object id provided"); - } - checksum.setValue(csum); - checksum.setAlgorithm(properties.getProperty("irods.dataone.chksum-algorithm")); - - } catch (FileNotFoundException nf) { - log.error("Cannot access iRODS object: {}", dataObject.getAbsolutePath()); - throw new NotFound("1410", "No data object could be found for given PID:"); - } catch (JargonException je) { - log.error("cannot access iRODS object: {}", dataObject.getAbsolutePath()); - throw new ServiceFailure("1410", je.getMessage()); - } finally { - irodsAccessObjectFactory.closeSessionAndEatExceptions(); - } - return checksum; - } - - @Override - public Checksum getChecksum(Session arg0, Identifier arg1, String arg2) - throws InvalidRequest, InvalidToken, NotAuthorized, NotImplemented, - ServiceFailure, NotFound { - throw new NotImplemented("1401", "this service has not been implemented"); - } - - @Override - public InputStream getReplica(Identifier arg0) throws InvalidToken, - NotAuthorized, NotImplemented, ServiceFailure, NotFound, - InsufficientResources { - // This is implemented in streamObject - return null; - } - - @Override - public InputStream getReplica(Session arg0, Identifier arg1) - throws InvalidToken, NotAuthorized, NotImplemented, ServiceFailure, - NotFound, InsufficientResources { - throw new NotImplemented("2180", "this service has not been implemented"); - } - - @Override - public SystemMetadata getSystemMetadata(Identifier id) - throws InvalidToken, NotAuthorized, NotImplemented, ServiceFailure, - NotFound { - if (id == null || id.getValue().isEmpty()) { - throw new InvalidToken("1402", "invalid iRODS data object id"); - } - - DataObject dataObject = new DataObject(); - SystemMetadata metadata = new SystemMetadata(); - IRODSAccount irodsAccount; - DataObjectAO dataObjectAO; - - // TODO: hardcode version to 1 for now - metadata.setSerialVersion(getSerialVersion()); - - Checksum checksum = new Checksum(); - - // first try and find data object for this id - try { - irodsAccount = RestAuthUtils - .getIRODSAccountFromBasicAuthValues(restConfiguration); - - dataObjectAO = irodsAccessObjectFactory.getDataObjectAO(irodsAccount); - UniqueIdAOHandleImpl handleImpl = new UniqueIdAOHandleImpl(restConfiguration, irodsAccessObjectFactory); - dataObject = handleImpl.getDataObjectFromIdentifier(id); - - } catch(Exception ex) { - log.info("file does not exist"); - throw new NotFound("1060", "No metadata could be found for given PID:" + id.getValue()); - } - - try { - String csum = dataObject.getChecksum(); - if (csum == null) { - log.info("checksum does not exist for file: {}", dataObject.getAbsolutePath()); -// throw new NotFound("404", "1420"); - } - else { - checksum.setValue(csum); - checksum.setAlgorithm(properties.getProperty("irods.dataone.chksum-algorithm")); - } - - String format = DataTypeUtils.getDataObjectFormatFromMetadata(irodsAccount, irodsAccessObjectFactory, dataObject); - if (format == null) { - format = getDataObjectMimeType(irodsAccount, dataObject); - } - metadata.setIdentifier(id); - ObjectFormatIdentifier formatId = new ObjectFormatIdentifier(); - formatId.setValue(format); - metadata.setFormatId(formatId); - - Long dataSizeLong = new Long(dataObject.getDataSize()); - String dataSizeStr = dataSizeLong.toString(); - metadata.setSize(new BigInteger(dataSizeStr)); - metadata.setChecksum(checksum); - - String dataOwner = "uid=" + dataObject.getDataOwnerName(); - Subject submitter = new Subject(); - submitter.setValue(dataOwner); - metadata.setSubmitter(submitter); - - Subject rightsHolder = new Subject(); - rightsHolder.setValue(dataOwner); - metadata.setRightsHolder(rightsHolder); - - List permissions = dataObjectAO.listPermissionsForDataObject(dataObject.getAbsolutePath()); - if (permissions != null) { - AccessPolicy accessPolicy = new AccessPolicy(); - for (UserFilePermission permission : permissions) { - AccessRule rule = new AccessRule(); - Subject subject = new Subject(); - - // in DataONE - anonymous translates to public - // TODO: also may need to make translation for "public" to "authenticatedUser" - if (permission.getUserName().equals("anonymous")) { - subject.setValue("public"); - } - else { - subject.setValue("uid=" + permission.getUserName()); - } - rule.addSubject(subject); - List d1Premissions = getD1Permission(permission); - for(Permission d1Premission : d1Premissions) { - rule.addPermission(d1Premission); - } - accessPolicy.addAllow(rule); - } - metadata.setAccessPolicy(accessPolicy); - } - - ReplicationPolicy replicationPolicy = new ReplicationPolicy(); - replicationPolicy.setReplicationAllowed(false); - metadata.setReplicationPolicy(replicationPolicy); - - // Add support for obsoletes or obsoletedBy? - - // Use AVU epoch date - //metadata.setDateUploaded(dataObject.getCreatedAt()); - //metadata.setDateSysMetadataModified(dataObject.getUpdatedAt()); - Date startDate = DataObjectMetadataUtils.getStartDateTime(irodsAccessObjectFactory, irodsAccount, dataObject); - metadata.setDateSysMetadataModified(startDate); - metadata.setDateUploaded(startDate); - - NodeReference nodeReference = new NodeReference(); - nodeReference.setValue(properties.getProperty("irods.dataone.identifier")); - metadata.setOriginMemberNode(nodeReference); - metadata.setAuthoritativeMemberNode(nodeReference); - - } catch (Exception e) { - log.error("Cannot access iRODS object: {}", dataObject.getAbsolutePath()); - throw new ServiceFailure("1090", e.getMessage()); - } finally { - irodsAccessObjectFactory.closeSessionAndEatExceptions(); - } - return metadata; - } - - @Override - public SystemMetadata getSystemMetadata(Session arg0, Identifier arg1) - throws InvalidToken, NotAuthorized, NotImplemented, ServiceFailure, - NotFound { - throw new NotImplemented("1041", "this service has not been implemented"); - } - - @Override - public ObjectList listObjects( - Date fromDate, - Date toDate, - ObjectFormatIdentifier formatId, - Boolean replicaStatus, - Integer start, - Integer count) throws - InvalidRequest, - InvalidToken, - NotAuthorized, - NotImplemented, - ServiceFailure { - DataObjectListResponse dataObjectListResponse = new DataObjectListResponse(); - List dataObjectList = new ArrayList(); - List objectInfoList = new ArrayList(); - ObjectList objectList = new ObjectList(); - //UniqueIdAOHandleImpl handleImpl; - UniqueIdAOHandleInMetadataImpl handleImpl; - - try { - //handleImpl = new UniqueIdAOHandleImpl(restConfiguration, irodsAccessObjectFactory); - handleImpl = new UniqueIdAOHandleInMetadataImpl(restConfiguration, irodsAccessObjectFactory); - - //dataObjectListResponse = handleImpl.getListOfDataoneExposedDataObjects( - dataObjectListResponse = handleImpl.getListOfDataoneExposedDataObjects( - fromDate, - toDate, - formatId, - replicaStatus, - start, - count); - } catch(Exception ex) { - log.info("{}", ex.toString()); - throw new ServiceFailure("1580", "Could not retrieve list of data objects"); - } - - dataObjectList = dataObjectListResponse.getDataObjects(); - - for (DataObject dObject : dataObjectList) { - - ObjectInfo oInfo = new ObjectInfo(); - - if (dObject.getChecksum() != null) { - Checksum checksum = new Checksum(); - checksum.setValue(dObject.getChecksum()); - checksum.setAlgorithm(properties.getProperty("irods.dataone.chksum-algorithm")); - oInfo.setChecksum(checksum); - } - - // probably should combine query for format and start date at some future refactor - IRODSAccount irodsAccount = null;; - String format = null; - try { - irodsAccount = RestAuthUtils - .getIRODSAccountFromBasicAuthValues(restConfiguration); - format = DataTypeUtils.getDataObjectFormatFromMetadata(irodsAccount, irodsAccessObjectFactory, dObject); - // use back up if no format stores in dataObject AVU - if (format == null) { - format = getDataObjectMimeType(irodsAccount, dObject); - } - } catch (Exception e1) { - log.error(e1.toString()); - log.error("cannot retrieve mime type for object:{} setting to application/octet-stream", - dObject.getAbsolutePath()); - format = "application/octet-stream"; - } - ObjectFormatIdentifier fId = new ObjectFormatIdentifier(); - fId.setValue(format); - oInfo.setFormatId(fId); - - //oInfo.setDateSysMetadataModified(dObject.getUpdatedAt()); - Date startDate = new Date(); - try { - startDate = DataObjectMetadataUtils.getStartDateTime(irodsAccessObjectFactory, irodsAccount, dObject); - } catch (Exception e1) { - log.error(e1.toString()); - log.error("cannot retrieve start date for object: {}", dObject.getAbsolutePath()); - } - oInfo.setDateSysMetadataModified(startDate); - - Identifier id; - try { - id = handleImpl.getIdentifierFromDataObject(dObject); - } catch (JargonException e) { - log.error("could not convert data object id to identifier: {}", e.toString()); - throw new ServiceFailure("1580", "Could not retrieve list of data objects"); - } - oInfo.setIdentifier(id); - - Long dataSizeLong = new Long(dObject.getDataSize()); - String dataSizeStr = dataSizeLong.toString(); - oInfo.setSize(new BigInteger(dataSizeStr)); - - objectInfoList.add(oInfo); - } - - objectList.setObjectInfoList(objectInfoList); - objectList.setTotal(dataObjectListResponse.getTotal()); - objectList.setCount(objectInfoList.size()); - objectList.setStart(start); - - return objectList; - } - - @Override - public ObjectList listObjects(Session arg0, Date arg1, Date arg2, - ObjectFormatIdentifier arg3, Boolean arg4, Integer arg5, - Integer arg6) throws InvalidRequest, InvalidToken, NotAuthorized, - NotImplemented, ServiceFailure { - throw new NotImplemented("1521", "this service has not been implemented"); - } - - @Override - public boolean synchronizationFailed(SynchronizationFailed syncFailed) - throws InvalidToken, NotAuthorized, NotImplemented, ServiceFailure { - - Identifier pid = null; - - if (syncFailed.getPid() != null) { - pid = new Identifier(); - pid.setValue(syncFailed.getPid()); - } - else { - throw new ServiceFailure("2161", "The identifier cannot be null."); - } - - // check to make sure pid is valid - try { - UniqueIdAOHandleImpl handleImpl = new UniqueIdAOHandleImpl(restConfiguration, irodsAccessObjectFactory); - // just try to access the object to see if is there or not - handleImpl.getDataObjectFromIdentifier(pid); - } catch(Exception ex) { - throw new ServiceFailure("2161", "The identifier specified by " + - syncFailed.getPid() + " was not found on this node."); - } - - EventLogAOElasticSearchImpl eventLog = new EventLogAOElasticSearchImpl(irodsAccessObjectFactory, restConfiguration); - try { - eventLog.recordEvent(Event.SYNCHRONIZATION_FAILED, pid, syncFailed.getDescription()); - } catch (Exception e) { - log.error("failed to log synchronization failed event: {}", e.toString()); - throw new ServiceFailure("2161", "Failed to log Synchronization Failure event"); - } - - return true; - } - - @Override - public boolean synchronizationFailed(Session arg0, - SynchronizationFailed arg1) throws InvalidToken, NotAuthorized, - NotImplemented, ServiceFailure { - throw new NotImplemented("2160", "this service has not been implemented"); - } - - // need to return every DataONE permission implied by iRODS permissions i.e. - // write would require read and write to be listed as DataONE permissions and - // own would include read, write, and changePermission - private List getD1Permission(UserFilePermission p) { - List permissions = new ArrayList(); - FilePermissionEnum fpEnum = p.getFilePermissionEnum(); - switch(fpEnum) { - case READ: - permissions.add(MNPermissionEnum.valueForDataOne(fpEnum)); - break; - - case WRITE: - permissions.add(Permission.READ); - permissions.add(MNPermissionEnum.valueForDataOne(fpEnum)); - break; - - case OWN: - permissions.add(Permission.READ); - permissions.add(Permission.WRITE); - permissions.add(MNPermissionEnum.valueForDataOne(fpEnum)); - break; - default: - permissions.add(MNPermissionEnum.valueForDataOne(fpEnum)); - break; - } - return permissions; - } - - - private BigInteger getSerialVersion() { - // TODO: hardcode version to 1 for now - Long verLong = new Long(1); - String verStr = verLong.toString(); - return new BigInteger(verStr); - } - - private String getDataObjectMimeType(IRODSAccount irodsAccount, DataObject dataObject) - throws FileNotFoundException, JargonException { - String mimeType = null; - String filename = dataObject.getAbsolutePath(); - log.info("file name is: {}", filename); - - DefaultDetector typeDetector = new DefaultDetector(); - IRODSFile irodsFile = irodsAccessObjectFactory - .getIRODSFileFactory(irodsAccount) - .instanceIRODSFile(filename); - IRODSFileInputStream irodsStream = irodsAccessObjectFactory - .getIRODSFileFactory(irodsAccount) - .instanceIRODSFileInputStream(irodsFile); - InputStream stream = new BufferedInputStream(irodsStream); - Metadata metadata = new Metadata(); - metadata.add(Metadata.RESOURCE_NAME_KEY, filename); - - MediaType type; - try { - type = typeDetector.detect(stream, metadata); - } catch (IOException e) { - log.error("detect failed: {}", e.toString()); - throw new FileNotFoundException("Cannot stream file in order to detect file type"); - } - - // if mime type is returned as "application/x-netcdf" change to - // DataONE accepted name: "netCDF-4" - mimeType = type.toString(); - if (mimeType.equals("application/x-netcdf")) { - mimeType = "netCDF-4"; - } - - - // data-profile stuff removed from jargon!!!!!!! - -// DataTypeResolutionService resolutionService = new DataTypeResolutionServiceImpl( -// irodsAccessObjectFactory, irodsAccount); -// DataProfileService dataProfileService = new DataProfileServiceImpl( -// irodsAccessObjectFactory, irodsAccount, resolutionService); -// -// @SuppressWarnings("unchecked") -// DataProfile dataProfile = dataProfileService.retrieveDataProfile(dataObject.getAbsolutePath()); -// mimeType = dataProfile.getMimeType(); - - - log.info("mime type is: {}", mimeType); - return mimeType; - - } - -} diff --git a/src/main/java/org/irods/jargon/dataone/utils/DataObjectMetadataUtils.java b/src/main/java/org/irods/jargon/dataone/utils/DataObjectMetadataUtils.java deleted file mode 100644 index a40fa1e..0000000 --- a/src/main/java/org/irods/jargon/dataone/utils/DataObjectMetadataUtils.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.irods.jargon.dataone.utils; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import org.irods.jargon.core.connection.IRODSAccount; -import org.irods.jargon.core.exception.JargonException; -import org.irods.jargon.core.pub.DataObjectAO; -import org.irods.jargon.core.pub.IRODSAccessObjectFactory; -import org.irods.jargon.core.pub.domain.DataObject; -import org.irods.jargon.core.query.AVUQueryElement; -import org.irods.jargon.core.query.AVUQueryOperatorEnum; -import org.irods.jargon.core.query.AVUQueryElement.AVUQueryPart; -import org.irods.jargon.core.query.JargonQueryException; -import org.irods.jargon.core.query.MetaDataAndDomainData; - -public class DataObjectMetadataUtils { - - static public Date getStartDateTime( - IRODSAccessObjectFactory irodsAccessObjectFactory, - IRODSAccount irodsAccount, - DataObject dObject) - throws JargonQueryException, JargonException { - - long epoch=0; - AVUQueryElement avuQuery = null; - List avuQueryList = new ArrayList(); - List metadataAndDomainDataList = new ArrayList(); - String dateAttr = "StartDateTime"; - - avuQuery = AVUQueryElement.instanceForValueQuery( - AVUQueryPart.ATTRIBUTE, - AVUQueryOperatorEnum.EQUAL, - dateAttr); - avuQueryList.add(avuQuery); - - DataObjectAO dataObjectAO = irodsAccessObjectFactory.getDataObjectAO(irodsAccount); - - metadataAndDomainDataList = dataObjectAO.findMetadataValuesForDataObjectUsingAVUQuery(avuQueryList, dObject.getAbsolutePath()); - String value = null; - for (MetaDataAndDomainData data : metadataAndDomainDataList) { - value = data.getAvuValue(); - // just take the 1st one - break; - } - epoch = Long.parseLong(value); - // need to convert it 2 milliseconds for Java date - Date theDate = new Date(epoch*1000); - - return theDate; - } - -} diff --git a/src/main/java/org/irods/jargon/dataone/utils/DataTypeUtils.java b/src/main/java/org/irods/jargon/dataone/utils/DataTypeUtils.java deleted file mode 100644 index 4f8a5b0..0000000 --- a/src/main/java/org/irods/jargon/dataone/utils/DataTypeUtils.java +++ /dev/null @@ -1,98 +0,0 @@ -package org.irods.jargon.dataone.utils; - -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; - -import org.apache.tika.detect.DefaultDetector; -import org.apache.tika.metadata.Metadata; -import org.apache.tika.mime.MediaType; -import org.irods.jargon.core.connection.IRODSAccount; -import org.irods.jargon.core.exception.FileNotFoundException; -import org.irods.jargon.core.exception.JargonException; -import org.irods.jargon.core.pub.DataObjectAO; -import org.irods.jargon.core.pub.IRODSAccessObjectFactory; -import org.irods.jargon.core.pub.domain.DataObject; -import org.irods.jargon.core.pub.io.IRODSFile; -import org.irods.jargon.core.pub.io.IRODSFileInputStream; -import org.irods.jargon.core.query.AVUQueryElement; -import org.irods.jargon.core.query.AVUQueryOperatorEnum; -import org.irods.jargon.core.query.JargonQueryException; -import org.irods.jargon.core.query.MetaDataAndDomainData; -import org.irods.jargon.core.query.AVUQueryElement.AVUQueryPart; - -public class DataTypeUtils { - - public static String getDataObjectMimeType(IRODSAccount irodsAccount, - IRODSAccessObjectFactory irodsAccessObjectFactory, - DataObject dataObject) - throws FileNotFoundException, JargonException { - String mimeType = null; - String filename = dataObject.getAbsolutePath(); - - DefaultDetector typeDetector = new DefaultDetector(); - IRODSFile irodsFile = irodsAccessObjectFactory - .getIRODSFileFactory(irodsAccount) - .instanceIRODSFile(filename); - IRODSFileInputStream irodsStream = irodsAccessObjectFactory - .getIRODSFileFactory(irodsAccount) - .instanceIRODSFileInputStream(irodsFile); - InputStream stream = new BufferedInputStream(irodsStream); - Metadata metadata = new Metadata(); - metadata.add(Metadata.RESOURCE_NAME_KEY, filename); - - MediaType type; - try { - type = typeDetector.detect(stream, metadata); - } catch (IOException e) { - throw new FileNotFoundException("Cannot stream file in order to detect file type"); - } - - // if mime type is returned as "application/x-netcdf" change to - // DataONE accepted name: "netCDF-4" - mimeType = type.toString(); - if (mimeType.equals("application/x-netcdf")) { - mimeType = "netCDF-4"; - } - - return mimeType; - - } - - public static String getDataObjectFormatFromMetadata(IRODSAccount irodsAccount, - IRODSAccessObjectFactory irodsAccessObjectFactory, - DataObject dataObject) - throws FileNotFoundException, JargonException, JargonQueryException { - - String dataFormat = null; - String formatAttr = "Format"; - List avuQueryList = new ArrayList(); - - AVUQueryElement avuQuery = AVUQueryElement.instanceForValueQuery( - AVUQueryPart.ATTRIBUTE, - AVUQueryOperatorEnum.EQUAL, - formatAttr); - avuQueryList.add(avuQuery); - - - DataObjectAO dataObjectAO = irodsAccessObjectFactory.getDataObjectAO(irodsAccount); - //List result = dataObjectAO.findMetadataValuesForDataObject(dataObject.getAbsolutePath()); - List result = - dataObjectAO.findMetadataValuesForDataObjectUsingAVUQuery( - avuQueryList, - dataObject.getAbsolutePath()); - - for (MetaDataAndDomainData metadata : result) { - if (metadata.getAvuAttribute().equals("Format")) { - dataFormat = metadata.getAvuValue(); - break; - } - } - - return dataFormat; - - } - -} diff --git a/src/main/java/org/irods/jargon/dataone/utils/ISO8601.java b/src/main/java/org/irods/jargon/dataone/utils/ISO8601.java deleted file mode 100644 index fe5f2ae..0000000 --- a/src/main/java/org/irods/jargon/dataone/utils/ISO8601.java +++ /dev/null @@ -1,105 +0,0 @@ -package org.irods.jargon.dataone.utils; - - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.text.DateFormat; -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.TimeZone; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public final class ISO8601 { - - private Logger logger = LoggerFactory.getLogger(this.getClass()); - - /** Transform Calendar to ISO 8601 string. */ - public static String fromCalendar(final Calendar calendar) { - Date date = calendar.getTime(); - String formatted = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ") - .format(date); - // add ":" to timezone offset, like this 2013-10-10T13:13:23.000-04:00 - return formatted.substring(0, 26) + ":" + formatted.substring(26); - } - - /** Get current date and time formatted as ISO 8601 string. */ - public static String now() { - return fromCalendar(GregorianCalendar.getInstance()); - } - - /** Transform ISO 8601 string to Calendar. */ - // have to handle this: 2016-04-12T18:18:00+00:00 - // and this 2016-04-12T18:18:00.000+00:00 - // and this 2016-04-12T18:18:00.001 - // and this 2016-04-12T18:18:00 - // and this 2016-04-12T18:18:00+00:00 - // etc - public static Calendar toCalendar(final String iso8601string) - throws ParseException { - Calendar calendar = GregorianCalendar.getInstance(); - String s = iso8601string; - - // add the GMT timezone default, if it is not explicitly specified - if ((!iso8601string.contains("+")) && (!iso8601string.contains("-"))) { - // GMT is default - s = s + "+0000"; - } - else { - // need to remove ":" from timezone, if there - int len = s.length(); - if (s.charAt(len-3) == ':') { - try { - s = s.substring(0, len-3) + s.substring(len-2); // to get rid of the ":" - } catch (IndexOutOfBoundsException e) { - throw new ParseException("Invalid length", 0); - } - } - } - - Date date; - // check for milliseconds extension - if (s.contains(".")) { - date = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ").parse(s); - } - else { - date = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").parse(s); - } - - calendar.setTime(date); - return calendar; - } - - public static Date convertToGMT(Date date) { - Date gmtDate = null; - - DateFormat gmtFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); - TimeZone gmtTime = TimeZone.getTimeZone("GMT"); - gmtFormat.setTimeZone(gmtTime); - String gmtStr = gmtFormat.format(date); - try { - gmtDate = gmtFormat.parse(gmtStr); - } catch (ParseException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - return gmtDate; - } - - public static String convertToGMTString(Date date) { - - DateFormat gmtFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS+"); - TimeZone gmtTimeZone = TimeZone.getTimeZone("GMT"); - gmtFormat.setTimeZone(gmtTimeZone); - Calendar calendar = new GregorianCalendar(); - calendar.setTime(date); - calendar.setTimeZone(gmtTimeZone); - String dateStr = gmtFormat.format(calendar.getTime()); - dateStr += "00:00"; - - return dateStr; - } -} diff --git a/src/main/java/org/irods/jargon/dataone/utils/PropertiesLoader.java b/src/main/java/org/irods/jargon/dataone/utils/PropertiesLoader.java deleted file mode 100644 index 9d325dd..0000000 --- a/src/main/java/org/irods/jargon/dataone/utils/PropertiesLoader.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.irods.jargon.dataone.utils; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Properties; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class PropertiesLoader { - - private Properties properties; - - private String propertiesFilename = "d1client.properties"; - private Logger log = LoggerFactory.getLogger(this.getClass()); - - public PropertiesLoader() { - - this.properties = new Properties(); - InputStream input = null; - input = getClass().getClassLoader().getResourceAsStream(this.propertiesFilename); - - // load a properties file - try { - this.properties.load(input); - } catch (IOException e) { - log.error("Cannot load Member Node properties file: {}", this.propertiesFilename); - log.error("IOException: {}", e.getStackTrace()); - this.properties = new Properties(); - } finally { - if (input != null) { - try { - input.close(); - } catch (IOException e) { - // do nothing - } - } - } - } - - - public String getProperty(String key) { - return properties.getProperty(key); - } - -} diff --git a/src/main/resources/jargon-beans.xml b/src/main/resources/jargon-beans.xml deleted file mode 100644 index 0484023..0000000 --- a/src/main/resources/jargon-beans.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/test/java/org/irods/jargon/rest/service/SMIMEService.java b/src/test/java/org/irods/jargon/rest/service/SMIMEService.java deleted file mode 100644 index e194012..0000000 --- a/src/test/java/org/irods/jargon/rest/service/SMIMEService.java +++ /dev/null @@ -1,17 +0,0 @@ -/** - * - */ -package org.irods.jargon.rest.service; - -import javax.inject.Named; - -/** - * Services for SMIME encryption and decryption - * - * @author Mike Conway - DICE (www.irods.org) - * - */ -@Named -public class SMIMEService { - -} diff --git a/src/test/java/org/irods/jargon/rest/unittest/AllTests.java b/src/test/java/org/irods/jargon/rest/unittest/AllTests.java deleted file mode 100644 index 1cc726a..0000000 --- a/src/test/java/org/irods/jargon/rest/unittest/AllTests.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.irods.jargon.rest.unittest; - -//import org.irods.jargon.rest.commands.user.UserGroupServiceTest; -//import org.irods.jargon.rest.commands.user.UserServiceTest; -//import org.irods.jargon.rest.environment.ServerEnvironmentServiceTest; -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -//import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -//@SuiteClasses({ UserGroupServiceTest.class, UserServiceTest.class, -// ServerEnvironmentServiceTest.class }) -public class AllTests { - -} diff --git a/src/test/resources/testing.properties b/src/test/resources/testing.properties deleted file mode 100644 index 0f2cb71..0000000 --- a/src/test/resources/testing.properties +++ /dev/null @@ -1,10 +0,0 @@ -test.confirm=${jargon.test.confirm} - test.data.directory=${jargon.test.data.directory} - test.irods.user=${jargon.test.irods.user} - test.irods.password=${jargon.test.irods.password} - test.irods.resource=${jargon.test.irods.resource} - test.irods.host=${jargon.test.irods.host} - test.irods.port=${jargon.test.irods.port} - test.irods.zone=${jargon.test.irods.zone} - test.irods.scratch.subdir=${jargon.test.irods.scratch.subdir} - test.rest.port=${test.rest.port} \ No newline at end of file