<plugin>\r
<groupId>org.apache.maven.plugins</groupId>\r
<artifactId>maven-war-plugin</artifactId>\r
- <version>2.0</version>\r
+ <version>2.1.1</version>\r
<configuration>\r
<warSourceExcludes>WEB-INF/lib/*.jar</warSourceExcludes>\r
<archive>\r
<groupId>log4j</groupId>\r
<artifactId>log4j</artifactId>\r
<version>1.2.14</version>\r
+ <scope>provided</scope>\r
</dependency>\r
<!-- somewhere dependency is added 1.5.8 unnecessarily -->\r
<dependency>\r
<artifactId>org.collectionspace.services.dimension.service</artifactId>\r
<version>${project.version}</version>\r
</dependency>\r
+ <dependency>\r
+ <groupId>org.collectionspace.services</groupId>\r
+ <artifactId>org.collectionspace.services.article.service</artifactId>\r
+ <version>${project.version}</version>\r
+ </dependency>\r
<dependency>\r
<groupId>org.collectionspace.services</groupId>\r
<artifactId>org.collectionspace.services.servicegroup.service</artifactId>\r
<dependency>\r
<artifactId>servlet-api</artifactId>\r
<groupId>javax.servlet</groupId>\r
- <version>2.5</version>\r
<scope>provided</scope>\r
</dependency>\r
\r
<dependency>\r
<groupId>org.nuxeo.ecm.core</groupId>\r
<artifactId>nuxeo-core-api</artifactId>\r
- <version>${nuxeo.core.version}</version> \r
</dependency>\r
<dependency>\r
<groupId>org.nuxeo.ecm.core</groupId>\r
<plugin>\r
<groupId>org.codehaus.mojo</groupId>\r
<artifactId>properties-maven-plugin</artifactId>\r
- <version>1.0-alpha-2</version>\r
<executions>\r
<execution>\r
<phase>initialize</phase>\r
<plugin>\r
<groupId>org.apache.maven.plugins</groupId>\r
<artifactId>maven-war-plugin</artifactId>\r
- <version>2.1.1</version>\r
<configuration>\r
<webResources>\r
<resource>\r
import org.collectionspace.services.vocabulary.VocabularyResource;
import org.collectionspace.services.organization.OrgAuthorityResource;
import org.collectionspace.services.person.PersonAuthorityResource;
-import org.collectionspace.services.workflow.WorkflowResource;
+import org.collectionspace.services.article.ArticleResource;
//import org.collectionspace.services.query.QueryResource;
import javax.servlet.ServletContext;
import javax.ws.rs.core.Application;
-import javax.ws.rs.core.Context;
-import java.util.HashMap;
import java.util.HashSet;
-import java.util.Map;
import java.util.Set;
//import org.collectionspace.services.common.FileUtils;
import org.collectionspace.services.common.ResourceMapImpl;
import org.collectionspace.services.common.relation.RelationResource;
import org.collectionspace.services.common.security.SecurityInterceptor;
-import org.jboss.resteasy.core.Dispatcher;
-import org.jboss.resteasy.spi.ResteasyProviderFactory;
-//import org.collectionspace.services.common.document.DocumentUtils;
-//import org.collectionspace.services.common.imaging.nuxeo.NuxeoImageUtils;
-//import org.collectionspace.services.common.profile.Profiler;
/**
* CollectionSpaceJaxRsApplication, the root application
singletons.add(new ServiceGroupResource());
singletons.add(new ImportsResource());
-
addResourceToMapAndSingletons(new VocabularyResource());
addResourceToMapAndSingletons(new PersonAuthorityResource());
addResourceToMapAndSingletons(new OrgAuthorityResource());
addResourceToMapAndSingletons(new BlobResource());
addResourceToMapAndSingletons(new MovementResource());
addResourceToMapAndSingletons(new ReportResource());
+ addResourceToMapAndSingletons(new ArticleResource());
singletons.add(new IDResource());
resourceMap.put(resource.getServiceName(), resource);
}
-
@Override
public Set<Class<?>> getClasses() {
return empty;
org.apache.catalina.core
org.springframework.security
-->
-
+
<bean id="springSecurityFilterChain"
class="org.springframework.security.web.FilterChainProxy">
<sec:filter-chain-map path-type="ant">
+ <!-- Exclude the "PublishedResourcesServlet" paths from AuthN and AuthZ. Let's us publish resources with anonymous access. -->
+ <sec:filter-chain pattern="/articles/**"
+ filters="none"/>
<sec:filter-chain pattern="/**"
filters="securityContextPersistenceFilter,basicAuthenticationFilter,logoutFilter,exTranslationFilter,filterInvocationInterceptor"/>
</sec:filter-chain-map>
</bean>
+
<bean id="securityContextPersistenceFilter"
class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> \r
<display-name>CollectionSpace Services</display-name>\r
\r
+ <!-- \r
<login-config>\r
<auth-method>BASIC</auth-method>\r
<realm-name>CollectionSpace realm</realm-name>\r
</login-config>\r
+ -->\r
\r
<env-entry>\r
<description>Sets the logging context for the Tiger web-app</description>\r
<filter-name>CSpaceFilter</filter-name>\r
<filter-class>org.collectionspace.services.common.profile.CSpaceFilter</filter-class>\r
</filter>\r
+ \r
<filter-mapping>\r
<filter-name>CSpaceFilter</filter-name>\r
<url-pattern>/*</url-pattern>\r
<servlet-class>\r
org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher\r
</servlet-class>\r
- </servlet>\r
- \r
+ </servlet> \r
<servlet-mapping>\r
<servlet-name>Resteasy</servlet-name>\r
<url-pattern>/*</url-pattern>\r
</servlet-mapping>\r
+ \r
+ <servlet>\r
+ <servlet-name>PublishedResourcesServlet</servlet-name>\r
+ <servlet-class>\r
+ org.collectionspace.services.common.servlet.PublishedResourcesServlet\r
+ </servlet-class>\r
+ </servlet> \r
+ <servlet-mapping>\r
+ <servlet-name>PublishedResourcesServlet</servlet-name>\r
+ <url-pattern>/published/*</url-pattern>\r
+ </servlet-mapping>\r
\r
</web-app>\r
--- /dev/null
+
+<project name="article.3rdparty" default="package" basedir=".">
+ <description>
+ article service 3rdparty
+ </description>
+ <!-- set global properties for this build -->
+ <property name="services.trunk" value="../../.."/>
+ <!-- enviornment should be declared before reading build.properties -->
+ <property environment="env" />
+ <property file="${services.trunk}/build.properties" />
+ <property name="mvn.opts" value="" />
+ <property name="src" location="src"/>
+
+ <condition property="osfamily-unix">
+ <os family="unix" />
+ </condition>
+ <condition property="osfamily-windows">
+ <os family="windows" />
+ </condition>
+
+ <target name="init" >
+ <!-- Create the time stamp -->
+ <tstamp/>
+ </target>
+
+ <target name="package" depends="package-unix,package-windows"
+ description="Package CollectionSpace Services" />
+ <target name="package-unix" if="osfamily-unix">
+ <exec executable="mvn" failonerror="true">
+ <arg value="package" />
+ <arg value="-Dmaven.test.skip=true" />
+ <arg value="-f" />
+ <arg value="${basedir}/pom.xml" />
+ <arg value="-N" />
+ <arg value="${mvn.opts}" />
+ </exec>
+ </target>
+ <target name="package-windows" if="osfamily-windows">
+ <exec executable="cmd" failonerror="true">
+ <arg value="/c" />
+ <arg value="mvn.bat" />
+ <arg value="package" />
+ <arg value="-Dmaven.test.skip=true" />
+ <arg value="-f" />
+ <arg value="${basedir}/pom.xml" />
+ <arg value="-N" />
+ <arg value="${mvn.opts}" />
+ </exec>
+ </target>
+
+ <target name="install" depends="install-unix,install-windows"
+ description="Install" />
+ <target name="install-unix" if="osfamily-unix">
+ <exec executable="mvn" failonerror="true">
+ <arg value="install" />
+ <arg value="-Dmaven.test.skip=true" />
+ <arg value="-f" />
+ <arg value="${basedir}/pom.xml" />
+ <arg value="-N" />
+ <arg value="${mvn.opts}" />
+ </exec>
+ </target>
+ <target name="install-windows" if="osfamily-windows">
+ <exec executable="cmd" failonerror="true">
+ <arg value="/c" />
+ <arg value="mvn.bat" />
+ <arg value="install" />
+ <arg value="-Dmaven.test.skip=true" />
+ <arg value="-f" />
+ <arg value="${basedir}/pom.xml" />
+ <arg value="-N" />
+ <arg value="${mvn.opts}" />
+ </exec>
+ </target>
+
+ <target name="clean" depends="clean-unix,clean-windows"
+ description="Delete target directories" >
+ <delete dir="${build}"/>
+ </target>
+ <target name="clean-unix" if="osfamily-unix">
+ <exec executable="mvn" failonerror="true">
+ <arg value="clean" />
+ <arg value="${mvn.opts}" />
+ </exec>
+ </target>
+ <target name="clean-windows" if="osfamily-windows">
+ <exec executable="cmd" failonerror="true">
+ <arg value="/c" />
+ <arg value="mvn.bat" />
+ <arg value="clean" />
+ <arg value="${mvn.opts}" />
+ </exec>
+ </target>
+
+ <target name="test" depends="test-unix,test-windows" description="Run tests" />
+ <target name="test-unix" if="osfamily-unix">
+ <exec executable="mvn" failonerror="true">
+ <arg value="test" />
+ <arg value="${mvn.opts}" />
+ </exec>
+ </target>
+ <target name="test-windows" if="osfamily-windows">
+ <exec executable="cmd" failonerror="true">
+ <arg value="/c" />
+ <arg value="mvn.bat" />
+ <arg value="test" />
+ <arg value="${mvn.opts}" />
+ </exec>
+ </target>
+
+ <target name="deploy" depends="install"
+ description="deploy article in ${jee.server.nuxeo}">
+ <ant antfile="nuxeo-platform-cs-article/build.xml" target="deploy" inheritall="false"/>
+ </target>
+
+ <target name="undeploy"
+ description="undeploy article from ${jee.server.nuxeo}">
+ <ant antfile="nuxeo-platform-cs-article/build.xml" target="undeploy" inheritall="false"/>
+ </target>
+
+ <target name="dist"
+ description="generate distribution for article" depends="package">
+ <ant antfile="nuxeo-platform-cs-article/build.xml" target="dist" inheritall="false"/>
+ </target>
+
+
+</project>
--- /dev/null
+
+<project name="nuxeo-platform-cs-article" default="package" basedir=".">
+ <description>
+ article nuxeo document type
+ </description>
+ <!-- set global properties for this build -->
+ <property name="services.trunk" value="../../../.."/>
+ <!-- environment should be declared before reading build.properties -->
+ <property environment="env" />
+ <property file="${services.trunk}/build.properties" />
+ <property name="mvn.opts" value="" />
+ <property name="src" location="src"/>
+ <property name="nuxeo.article.jar"
+ value="org.collectionspace.services.article.3rdparty.nuxeo-${cspace.release}.jar"/>
+ <property name="nuxeo.article.jars.all"
+ value="org.collectionspace.services.article.3rdparty.nuxeo-*.jar"/>
+
+ <condition property="osfamily-unix">
+ <os family="unix" />
+ </condition>
+ <condition property="osfamily-windows">
+ <os family="windows" />
+ </condition>
+
+ <target name="init" >
+ <!-- Create the time stamp -->
+ <tstamp/>
+ </target>
+
+ <target name="package" depends="package-unix,package-windows"
+ description="Package CollectionSpace Services" />
+ <target name="package-unix" if="osfamily-unix">
+ <exec executable="mvn" failonerror="true">
+ <arg value="package" />
+ <arg value="-Dmaven.test.skip=true" />
+ <arg value="-f" />
+ <arg value="${basedir}/pom.xml" />
+ <arg value="-N" />
+ <arg value="${mvn.opts}" />
+ </exec>
+ </target>
+ <target name="package-windows" if="osfamily-windows">
+ <exec executable="cmd" failonerror="true">
+ <arg value="/c" />
+ <arg value="mvn.bat" />
+ <arg value="package" />
+ <arg value="-Dmaven.test.skip=true" />
+ <arg value="-f" />
+ <arg value="${basedir}/pom.xml" />
+ <arg value="-N" />
+ <arg value="${mvn.opts}" />
+ </exec>
+ </target>
+
+ <target name="install" depends="install-unix,install-windows"
+ description="Install" />
+ <target name="install-unix" if="osfamily-unix">
+ <exec executable="mvn" failonerror="true">
+ <arg value="install" />
+ <arg value="-Dmaven.test.skip=true" />
+ <arg value="-f" />
+ <arg value="${basedir}/pom.xml" />
+ <arg value="-N" />
+ <arg value="${mvn.opts}" />
+ </exec>
+ </target>
+ <target name="install-windows" if="osfamily-windows">
+ <exec executable="cmd" failonerror="true">
+ <arg value="/c" />
+ <arg value="mvn.bat" />
+ <arg value="install" />
+ <arg value="-Dmaven.test.skip=true" />
+ <arg value="-f" />
+ <arg value="${basedir}/pom.xml" />
+ <arg value="-N" />
+ <arg value="${mvn.opts}" />
+ </exec>
+ </target>
+
+ <target name="clean" depends="clean-unix,clean-windows"
+ description="Delete target directories" >
+ <delete dir="${build}"/>
+ </target>
+ <target name="clean-unix" if="osfamily-unix">
+ <exec executable="mvn" failonerror="true">
+ <arg value="clean" />
+ <arg value="${mvn.opts}" />
+ </exec>
+ </target>
+ <target name="clean-windows" if="osfamily-windows">
+ <exec executable="cmd" failonerror="true">
+ <arg value="/c" />
+ <arg value="mvn.bat" />
+ <arg value="clean" />
+ <arg value="${mvn.opts}" />
+ </exec>
+ </target>
+
+ <target name="test" depends="test-unix,test-windows" description="Run tests" />
+ <target name="test-unix" if="osfamily-unix">
+ <exec executable="mvn" failonerror="true">
+ <arg value="test" />
+ <arg value="${mvn.opts}" />
+ </exec>
+ </target>
+ <target name="test-windows" if="osfamily-windows">
+ <exec executable="cmd" failonerror="true">
+ <arg value="/c" />
+ <arg value="mvn.bat" />
+ <arg value="test" />
+ <arg value="${mvn.opts}" />
+ </exec>
+ </target>
+
+ <target name="deploy" depends="install"
+ description="deploy article doctype in ${jee.server.nuxeo}">
+ <copy file="${basedir}/target/${nuxeo.article.jar}"
+ todir="${jee.deploy.nuxeo.plugins}"/>
+ </target>
+
+ <target name="undeploy"
+ description="undeploy article doctype from ${jee.server.nuxeo}">
+ <delete>
+ <fileset dir="${jee.deploy.nuxeo.plugins}">
+ <include name="${nuxeo.article.jars.all}"/>
+ </fileset>
+ </delete>
+ </target>
+
+ <target name="dist"
+ description="generate distribution for article doctype" depends="package">
+ <copy todir="${services.trunk}/${dist.deploy.nuxeo.plugins}">
+ <fileset file="${basedir}/target/${nuxeo.article.jar}"/>
+ </copy>
+ </target>
+
+</project>
+
--- /dev/null
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <parent>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.article.3rdparty</artifactId>
+ <version>3.2.1-SNAPSHOT</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.article.3rdparty.nuxeo</artifactId>
+ <name>services.article.3rdparty.nuxeo</name>
+ <packaging>jar</packaging>
+ <description>
+ Article Nuxeo Document Type
+ </description>
+
+ <properties>
+ <ServiceName>article</ServiceName>
+ <NuxeoDocTypeName>Article</NuxeoDocTypeName>
+ <CommonSchemaName>articles_common</CommonSchemaName>
+ <Lifecycle>cs_default</Lifecycle>
+ </properties>
+
+ <build>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>true</filtering>
+ </resource>
+ <resource>
+ <directory>../../../../3rdparty/nuxeo/nuxeo-doctype/src/main/resources</directory>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifestFile>target/classes/META-INF/MANIFEST.MF</manifestFile>
+ <manifestEntries>
+ <Bundle-Version>${eclipseVersion}</Bundle-Version>
+ <Bundle-ManifestVersion>2</Bundle-ManifestVersion>
+ </manifestEntries>
+ </archive>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+ ArticlesCommon XML Schema (XSD) for Nuxeo
+
+ Entity : ArticlesCommon
+ Used for: Nuxeo EP core document type
+
+ $LastChangedRevision$
+ $LastChangedDate$
+-->
+
+<xs:schema
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:ns="http://collectionspace.org/article/"
+ xmlns="http://collectionspace.org/article/"
+ targetNamespace="http://collectionspace.org/article/"
+ version="0.1">
+
+ <xs:element name="articleNumber" type="xs:string"/> <!-- An ID for the article (different than the CSID) -->
+ <xs:element name="articleContentUrl" type="xs:string"/> <!-- The URL of the article's content -->
+ <xs:element name="articleJobId" type="xs:string"/> <!-- The asynch job ID -if any -->
+ <xs:element name="articleSource" type="xs:string"/> <!-- The name of the service/resource that was used to create the article. -->
+ <xs:element name="articlePublisher" type="xs:string"/> <!-- The user who published the article -->
+ <xs:element name="accessExpirationDate" type="xs:dateTime"/> <!-- When the article is no longer available for access -->
+ <xs:element name="accessedCount" type="xs:integer"/> <!-- How many times the article has been accessed. -->
+ <xs:element name="accessCountLimit" type="xs:integer"/> <!-- The maximum times the article can be accessed. -->
+</xs:schema>
--- /dev/null
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <parent>
+ <artifactId>org.collectionspace.services.article</artifactId>
+ <groupId>org.collectionspace.services</groupId>
+ <version>3.2.1-SNAPSHOT</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.article.3rdparty</artifactId>
+ <name>services.article.3rdparty</name>
+ <packaging>pom</packaging>
+
+ <description>
+ 3rd party build for article service
+ </description>
+
+ <modules>
+ <module>nuxeo-platform-cs-article</module>
+ </modules>
+</project>
--- /dev/null
+
+<project name="article" default="package" basedir=".">
+ <description>
+ article service
+ </description>
+ <!-- set global properties for this build -->
+ <property name="services.trunk" value="../.."/>
+ <!-- enviornment should be declared before reading build.properties -->
+ <property environment="env" />
+ <property file="${services.trunk}/build.properties" />
+ <property name="mvn.opts" value="" />
+ <property name="src" location="src"/>
+
+ <condition property="osfamily-unix">
+ <os family="unix" />
+ </condition>
+ <condition property="osfamily-windows">
+ <os family="windows" />
+ </condition>
+
+ <target name="package" depends="package-unix,package-windows"
+ description="Package CollectionSpace Services" />
+
+ <target name="package-unix" if="osfamily-unix">
+ <exec executable="mvn" failonerror="true">
+ <arg value="package" />
+ <arg value="-Dmaven.test.skip=true" />
+ <arg value="-f" />
+ <arg value="${basedir}/pom.xml" />
+ <arg value="-N" />
+ <arg value="${mvn.opts}" />
+ </exec>
+ </target>
+
+ <target name="package-windows" if="osfamily-windows">
+ <exec executable="cmd" failonerror="true">
+ <arg value="/c" />
+ <arg value="mvn.bat" />
+ <arg value="package" />
+ <arg value="-Dmaven.test.skip=true" />
+ <arg value="-f" />
+ <arg value="${basedir}/pom.xml" />
+ <arg value="-N" />
+ <arg value="${mvn.opts}" />
+ </exec>
+ </target>
+
+
+ <target name="install" depends="install-unix,install-windows"
+ description="Install" />
+ <target name="install-unix" if="osfamily-unix">
+ <exec executable="mvn" failonerror="true">
+ <arg value="install" />
+ <arg value="-Dmaven.test.skip=true" />
+ <arg value="-f" />
+ <arg value="${basedir}/pom.xml" />
+ <arg value="-N" />
+ <arg value="${mvn.opts}" />
+ </exec>
+ </target>
+ <target name="install-windows" if="osfamily-windows">
+ <exec executable="cmd" failonerror="true">
+ <arg value="/c" />
+ <arg value="mvn.bat" />
+ <arg value="install" />
+ <arg value="-Dmaven.test.skip=true" />
+ <arg value="-f" />
+ <arg value="${basedir}/pom.xml" />
+ <arg value="-N" />
+ <arg value="${mvn.opts}" />
+ </exec>
+ </target>
+
+ <target name="clean" depends="clean-unix,clean-windows"
+ description="Delete target directories" >
+ <delete dir="${build}"/>
+ </target>
+ <target name="clean-unix" if="osfamily-unix">
+ <exec executable="mvn" failonerror="true">
+ <arg value="clean" />
+ <arg value="${mvn.opts}" />
+ </exec>
+ </target>
+ <target name="clean-windows" if="osfamily-windows">
+ <exec executable="cmd" failonerror="true">
+ <arg value="/c" />
+ <arg value="mvn.bat" />
+ <arg value="clean" />
+ <arg value="${mvn.opts}" />
+ </exec>
+ </target>
+
+ <target name="test" depends="test-unix,test-windows" description="Run tests" />
+ <target name="test-unix" if="osfamily-unix">
+ <exec executable="mvn" failonerror="true">
+ <arg value="test" />
+ <arg value="${mvn.opts}" />
+ </exec>
+ </target>
+ <target name="test-windows" if="osfamily-windows">
+ <exec executable="cmd" failonerror="true">
+ <arg value="/c" />
+ <arg value="mvn.bat" />
+ <arg value="test" />
+ <arg value="${mvn.opts}" />
+ </exec>
+ </target>
+
+ <target name="deploy" depends="install"
+ description="deploy article service">
+ <ant antfile="3rdparty/build.xml" target="deploy" inheritall="false"/>
+ </target>
+
+ <target name="undeploy"
+ description="undeploy article service">
+ <ant antfile="3rdparty/build.xml" target="undeploy" inheritall="false"/>
+ </target>
+
+ <target name="dist" depends="package"
+ description="distribute article service">
+ <ant antfile="3rdparty/build.xml" target="dist" inheritall="false"/>
+ </target>
+
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <parent>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.article</artifactId>
+ <version>3.2.1-SNAPSHOT</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.article.client</artifactId>
+ <name>services.article.client</name>
+
+ <dependencies>
+ <!-- keep slf4j dependencies on the top -->
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <scope>test</scope>
+ </dependency>
+<!-- CollectionSpace dependencies -->
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.jaxb</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.common</artifactId>
+ <optional>true</optional>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.client</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.article.jaxb</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.person.client</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.authority.jaxb</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+<!-- External dependencies -->
+ <dependency>
+ <groupId>org.testng</groupId>
+ <artifactId>testng</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-jaxrs</artifactId>
+ <!-- filter out unwanted jars -->
+ <exclusions>
+ <exclusion>
+ <groupId>tjws</groupId>
+ <artifactId>webserver</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-jaxb-provider</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-multipart-provider</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-httpclient</groupId>
+ <artifactId>commons-httpclient</artifactId>
+ <version>3.1</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <finalName>collectionspace-services-article-client</finalName>
+ </build>
+</project>
--- /dev/null
+/**
+ * This document is a part of the source code and related artifacts
+ * for CollectionSpace, an open source collections management system
+ * for museums and related institutions:
+ *
+ * http://www.collectionspace.org
+ * http://wiki.collectionspace.org
+ *
+ * Copyright (c) 2009 Regents of the University of California
+ *
+ * Licensed under the Educational Community License (ECL), Version 2.0.
+ * You may not use this file except in compliance with this License.
+ *
+ * You may obtain a copy of the ECL 2.0 License at
+ * https://source.collectionspace.org/collection-space/LICENSE.txt
+ */
+package org.collectionspace.services.client;
+
+/**
+ * ArticleClient.java
+ *
+ * $LastChangedRevision$
+ * $LastChangedDate$
+ *
+ */
+public class ArticleClient extends AbstractCommonListPoxServiceClientImpl<ArticleProxy> {
+
+ public static final String SERVICE_NAME = "articles";
+ public static final String SERVICE_PATH_COMPONENT = SERVICE_NAME;
+ public static final String SERVICE_PATH = "/" + SERVICE_PATH_COMPONENT;
+ public static final String SERVICE_PATH_PROXY = SERVICE_PATH + "/";
+ public static final String SERVICE_PAYLOAD_NAME = SERVICE_NAME;
+
+ /* (non-Javadoc)
+ * @see org.collectionspace.services.client.AbstractServiceClientImpl#getServicePathComponent()
+ */
+ @Override
+ public String getServicePathComponent() {
+ return SERVICE_PATH_COMPONENT;
+ }
+
+ @Override
+ public String getServiceName() {
+ return SERVICE_NAME;
+ }
+
+ @Override
+ public Class<ArticleProxy> getProxyClass() {
+ return ArticleProxy.class;
+ }
+
+}
--- /dev/null
+/**
+ * This document is a part of the source code and related artifacts
+ * for CollectionSpace, an open source collections management system
+ * for museums and related institutions:
+ *
+ * http://www.collectionspace.org
+ * http://wiki.collectionspace.org
+ *
+ * Copyright (c) 2009 Regents of the University of California
+ *
+ * Licensed under the Educational Community License (ECL), Version 2.0.
+ * You may not use this file except in compliance with this License.
+ *
+ * You may obtain a copy of the ECL 2.0 License at
+ * https://source.collectionspace.org/collection-space/LICENSE.txt
+ */
+package org.collectionspace.services.client;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+/**
+ * ArticleProxy.java
+ *
+ * $LastChangedRevision$
+ * $LastChangedDate$
+ *
+ */
+@Path(ArticleClient.SERVICE_PATH_PROXY)
+@Produces({"application/xml"})
+@Consumes({"application/xml"})
+public interface ArticleProxy extends CollectionSpaceCommonListPoxProxy {
+}
--- /dev/null
+/**
+ * This document is a part of the source code and related artifacts
+ * for CollectionSpace, an open source collections management system
+ * for museums and related institutions:
+ *
+ * http://www.collectionspace.org
+ * http://wiki.collectionspace.org
+ *
+ * Copyright © 2009 Regents of the University of California
+ *
+ * Licensed under the Educational Community License (ECL), Version 2.0.
+ * You may not use this file except in compliance with this License.
+ *
+ * You may obtain a copy of the ECL 2.0 License at
+ * https://source.collectionspace.org/collection-space/LICENSE.txt
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.collectionspace.services.client.test;
+
+//import java.util.ArrayList;
+import javax.ws.rs.core.Response;
+
+import org.collectionspace.services.client.AbstractCommonListUtils;
+import org.collectionspace.services.client.CollectionSpaceClient;
+import org.collectionspace.services.client.ArticleClient;
+import org.collectionspace.services.client.PayloadInputPart;
+import org.collectionspace.services.client.PayloadOutputPart;
+import org.collectionspace.services.client.PoxPayloadIn;
+import org.collectionspace.services.client.PoxPayloadOut;
+import org.collectionspace.services.common.api.GregorianCalendarDateTimeUtils;
+import org.collectionspace.services.jaxb.AbstractCommonList;
+import org.collectionspace.services.article.ArticlesCommon;
+
+import org.jboss.resteasy.client.ClientResponse;
+import org.testng.Assert;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * ArticleServiceTest, carries out tests against a deployed and running Articles
+ * Service.
+ *
+ * $LastChangedRevision$ $LastChangedDate$
+ */
+public class ArticleServiceTest extends
+ AbstractPoxServiceTestImpl<AbstractCommonList, ArticlesCommon> {
+
+ /** The logger. */
+ private final String CLASS_NAME = ArticleServiceTest.class.getName();
+ private final Logger logger = LoggerFactory.getLogger(CLASS_NAME);
+ // Instance variables specific to this test.
+ /** The service path component. */
+ final String SERVICE_NAME = "articles";
+ final String SERVICE_PATH_COMPONENT = "articles";
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.collectionspace.services.client.test.BaseServiceTest#getClientInstance
+ * ()
+ */
+ @Override
+ protected ArticleClient getClientInstance() {
+ return new ArticleClient();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.collectionspace.services.client.test.BaseServiceTest#
+ * getAbstractCommonList(org.jboss.resteasy.client.ClientResponse)
+ */
+ @Override
+ protected AbstractCommonList getCommonList(
+ ClientResponse<AbstractCommonList> response) {
+ return response.getEntity(AbstractCommonList.class);
+ }
+
+ // ---------------------------------------------------------------
+ // CRUD tests : CREATE tests
+ // ---------------------------------------------------------------
+
+ // Success outcomes
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.collectionspace.services.client.test.ServiceTest#create(java.lang
+ * .String)
+ */
+ @Override
+ // @Test(dataProvider = "testName", dataProviderClass =
+ // AbstractServiceTestImpl.class)
+ public void create(String testName) throws Exception {
+ // Perform setup, such as initializing the type of service request
+ // (e.g. CREATE, DELETE), its valid and expected status codes, and
+ // its associated HTTP method name (e.g. POST, DELETE).
+ setupCreate();
+
+ // Submit the request to the service and store the response.
+ ArticleClient client = new ArticleClient();
+ String identifier = createIdentifier();
+ PoxPayloadOut multipart = createArticleInstance(identifier);
+ String newID = null;
+ ClientResponse<Response> res = client.create(multipart);
+ try {
+ int statusCode = res.getStatus();
+
+ // Check the status code of the response: does it match
+ // the expected response(s)?
+ //
+ // Specifically:
+ // Does it fall within the set of valid status codes?
+ // Does it exactly match the expected status code?
+ if (logger.isDebugEnabled()) {
+ logger.debug(testName + ": status = " + statusCode);
+ }
+ Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
+ invalidStatusCodeMessage(testRequestType, statusCode));
+ Assert.assertEquals(statusCode, testExpectedStatusCode);
+
+ newID = extractId(res);
+ } finally {
+ if (res != null) {
+ res.releaseConnection();
+ }
+ }
+
+ // Store the ID returned from the first resource created
+ // for additional tests below.
+ if (knownResourceId == null) {
+ knownResourceId = newID;
+ if (logger.isDebugEnabled()) {
+ logger.debug(testName + ": knownResourceId=" + knownResourceId);
+ }
+ }
+
+ // Store the IDs from every resource created by tests,
+ // so they can be deleted after tests have been run.
+ allResourceIdsCreated.add(newID);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.collectionspace.services.client.test.AbstractServiceTestImpl#createList
+ * (java.lang.String)
+ */
+ @Override
+ // @Test(dataProvider = "testName", dataProviderClass =
+ // AbstractServiceTestImpl.class,
+ // dependsOnMethods = {"create"})
+ public void createList(String testName) throws Exception {
+ for (int i = 0; i < 3; i++) {
+ create(testName);
+ }
+ }
+
+ // ---------------------------------------------------------------
+ // CRUD tests : READ tests
+ // ---------------------------------------------------------------
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.collectionspace.services.client.test.AbstractServiceTestImpl#read
+ * (java.lang.String)
+ */
+ @Override
+ // @Test(dataProvider = "testName", dataProviderClass =
+ // AbstractServiceTestImpl.class,
+ // dependsOnMethods = {"create"})
+ public void read(String testName) throws Exception {
+ // Perform setup.
+ setupRead();
+
+ // Submit the request to the service and store the response.
+ ArticleClient client = new ArticleClient();
+ ClientResponse<String> res = client.read(knownResourceId);
+ PoxPayloadIn input = null;
+ try {
+ assertStatusCode(res, testName);
+ input = new PoxPayloadIn(res.getEntity());
+ } finally {
+ if (res != null) {
+ res.releaseConnection();
+ }
+ }
+
+ // Get the common part of the response and verify that it is not null.
+ PayloadInputPart payloadInputPart = input.getPart(client
+ .getCommonPartName());
+ ArticlesCommon articlesCommon = null;
+ if (payloadInputPart != null) {
+ articlesCommon = (ArticlesCommon) payloadInputPart.getBody();
+ }
+ Assert.assertNotNull(articlesCommon);
+
+ }
+
+ // Failure outcomes
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#
+ * readNonExistent(java.lang.String)
+ */
+ @Override
+ // @Test(dataProvider = "testName", dataProviderClass =
+ // AbstractServiceTestImpl.class,
+ // dependsOnMethods = {"read"})
+ public void readNonExistent(String testName) throws Exception {
+ // Perform setup.
+ setupReadNonExistent();
+
+ // Submit the request to the service and store the response.
+ ArticleClient client = new ArticleClient();
+ ClientResponse<String> res = client.read(NON_EXISTENT_ID);
+ try {
+ int statusCode = res.getStatus();
+
+ // Check the status code of the response: does it match
+ // the expected response(s)?
+ if (logger.isDebugEnabled()) {
+ logger.debug(testName + ": status = " + statusCode);
+ }
+ Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
+ invalidStatusCodeMessage(testRequestType, statusCode));
+ Assert.assertEquals(statusCode, testExpectedStatusCode);
+ } finally {
+ if (res != null) {
+ res.releaseConnection();
+ }
+ }
+ }
+
+ // ---------------------------------------------------------------
+ // CRUD tests : READ_LIST tests
+ // ---------------------------------------------------------------
+
+ // Success outcomes
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.collectionspace.services.client.test.AbstractServiceTestImpl#readList
+ * (java.lang.String)
+ */
+ @Override
+ // @Test(dataProvider = "testName", dataProviderClass =
+ // AbstractServiceTestImpl.class,
+ // dependsOnMethods = {"createList", "read"})
+ public void readList(String testName) throws Exception {
+ // Perform setup.
+ setupReadList();
+
+ // Submit the request to the service and store the response.
+ AbstractCommonList list = null;
+ ArticleClient client = new ArticleClient();
+ ClientResponse<AbstractCommonList> res = client.readList();
+ assertStatusCode(res, testName);
+ try {
+ int statusCode = res.getStatus();
+
+ // Check the status code of the response: does it match
+ // the expected response(s)?
+ if (logger.isDebugEnabled()) {
+ logger.debug(testName + ": status = " + statusCode);
+ }
+ Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
+ invalidStatusCodeMessage(testRequestType, statusCode));
+ Assert.assertEquals(statusCode, testExpectedStatusCode);
+
+ list = res.getEntity();
+ } finally {
+ if (res != null) {
+ res.releaseConnection();
+ }
+ }
+
+ // Optionally output additional data about list members for debugging.
+ boolean iterateThroughList = true;
+ if (iterateThroughList && logger.isDebugEnabled()) {
+ AbstractCommonListUtils.ListItemsInAbstractCommonList(list, logger,
+ testName);
+ }
+
+ }
+
+ // Failure outcomes
+ // None at present.
+
+ // ---------------------------------------------------------------
+ // CRUD tests : UPDATE tests
+ // ---------------------------------------------------------------
+
+ // Success outcomes
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.collectionspace.services.client.test.AbstractServiceTestImpl#update
+ * (java.lang.String)
+ */
+ @Override
+ // @Test(dataProvider = "testName", dataProviderClass =
+ // AbstractServiceTestImpl.class,
+ // dependsOnMethods = {"read"})
+ public void update(String testName) throws Exception {
+ // Perform setup.
+ setupRead();
+
+ // Retrieve the contents of a resource to update.
+ ArticleClient client = new ArticleClient();
+ ClientResponse<String> res = client.read(knownResourceId);
+ PoxPayloadIn input = null;
+ try {
+ assertStatusCode(res, testName);
+ input = new PoxPayloadIn(res.getEntity());
+ if (logger.isDebugEnabled()) {
+ logger.debug("got object to update with ID: " + knownResourceId);
+ }
+ } finally {
+ if (res != null) {
+ res.releaseConnection();
+ }
+ }
+
+ // Extract the common part from the response.
+ PayloadInputPart payloadInputPart = input.getPart(client
+ .getCommonPartName());
+ ArticlesCommon articlesCommon = null;
+ if (payloadInputPart != null) {
+ articlesCommon = (ArticlesCommon) payloadInputPart.getBody();
+ }
+ Assert.assertNotNull(articlesCommon);
+
+ // Update the content of this resource.
+ articlesCommon.setArticleNumber("updated-"
+ + articlesCommon.getArticleNumber());
+ articlesCommon.setArticleJobId("updated-" + articlesCommon.getArticleJobId());
+ if (logger.isDebugEnabled()) {
+ logger.debug("to be updated object");
+ logger.debug(objectAsXmlString(articlesCommon, ArticlesCommon.class));
+ }
+
+ setupUpdate();
+
+ // Submit the updated common part in an update request to the service
+ // and store the response.
+ PoxPayloadOut output = new PoxPayloadOut(this.getServicePathComponent());
+ PayloadOutputPart commonPart = output.addPart(
+ client.getCommonPartName(), articlesCommon);
+ res = client.update(knownResourceId, output);
+ try {
+ assertStatusCode(res, testName);
+ int statusCode = res.getStatus();
+ // Check the status code of the response: does it match the expected
+ // response(s)?
+ if (logger.isDebugEnabled()) {
+ logger.debug(testName + ": status = " + statusCode);
+ }
+ Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
+ invalidStatusCodeMessage(testRequestType, statusCode));
+ Assert.assertEquals(statusCode, testExpectedStatusCode);
+ input = new PoxPayloadIn(res.getEntity());
+ } finally {
+ if (res != null) {
+ res.releaseConnection();
+ }
+ }
+
+ // Extract the updated common part from the response.
+ payloadInputPart = input.getPart(client.getCommonPartName());
+ ArticlesCommon updatedArticleCommon = null;
+ if (payloadInputPart != null) {
+ updatedArticleCommon = (ArticlesCommon) payloadInputPart.getBody();
+ }
+ Assert.assertNotNull(updatedArticleCommon);
+
+ // Check selected fields in the updated common part.
+ Assert.assertEquals(updatedArticleCommon.getArticleNumber(),
+ articlesCommon.getArticleNumber(),
+ "Data in updated object did not match submitted data.");
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("UTF-8 data sent=" + articlesCommon.getArticleJobId()
+ + "\n" + "UTF-8 data received="
+ + updatedArticleCommon.getArticleJobId());
+ }
+ Assert.assertTrue(
+ updatedArticleCommon.getArticleJobId().contains(
+ getUTF8DataFragment()), "UTF-8 data retrieved '"
+ + updatedArticleCommon.getArticleJobId()
+ + "' does not contain expected data '"
+ + getUTF8DataFragment());
+ Assert.assertEquals(updatedArticleCommon.getArticleJobId(),
+ articlesCommon.getArticleJobId(),
+ "Data in updated object did not match submitted data.");
+ }
+
+ @Override
+ // @Test(dataProvider = "testName", dataProviderClass =
+ // AbstractServiceTestImpl.class,
+ // dependsOnMethods = {"update", "testSubmitRequest"})
+ public void updateNonExistent(String testName) throws Exception {
+ // Perform setup.
+ setupUpdateNonExistent();
+
+ // Submit the request to the service and store the response.
+ // Note: The ID used in this 'create' call may be arbitrary.
+ // The only relevant ID may be the one used in update(), below.
+ ArticleClient client = new ArticleClient();
+ PoxPayloadOut multipart = createArticleInstance(NON_EXISTENT_ID);
+ ClientResponse<String> res = client.update(NON_EXISTENT_ID, multipart);
+ try {
+ int statusCode = res.getStatus();
+
+ // Check the status code of the response: does it match
+ // the expected response(s)?
+ if (logger.isDebugEnabled()) {
+ logger.debug(testName + ": status = " + statusCode);
+ }
+ Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
+ invalidStatusCodeMessage(testRequestType, statusCode));
+ Assert.assertEquals(statusCode, testExpectedStatusCode);
+ } finally {
+ if (res != null) {
+ res.releaseConnection();
+ }
+ }
+ }
+
+ // ---------------------------------------------------------------
+ // CRUD tests : DELETE tests
+ // ---------------------------------------------------------------
+
+ // Success outcomes
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.collectionspace.services.client.test.AbstractServiceTestImpl#delete
+ * (java.lang.String)
+ */
+ @Override
+ // @Test(dataProvider = "testName", dataProviderClass =
+ // AbstractServiceTestImpl.class,
+ // dependsOnMethods = {"create", "readList", "testSubmitRequest", "update"})
+ public void delete(String testName) throws Exception {
+ // Perform setup.
+ setupDelete();
+
+ // Submit the request to the service and store the response.
+ ArticleClient client = new ArticleClient();
+ ClientResponse<Response> res = client.delete(knownResourceId);
+ try {
+ int statusCode = res.getStatus();
+
+ // Check the status code of the response: does it match
+ // the expected response(s)?
+ if (logger.isDebugEnabled()) {
+ logger.debug(testName + ": status = " + statusCode);
+ }
+ Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
+ invalidStatusCodeMessage(testRequestType, statusCode));
+ Assert.assertEquals(statusCode, testExpectedStatusCode);
+ } finally {
+ if (res != null) {
+ res.releaseConnection();
+ }
+ }
+ }
+
+ // Failure outcomes
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.collectionspace.services.client.test.AbstractServiceTestImpl#
+ * deleteNonExistent(java.lang.String)
+ */
+ @Override
+ // @Test(dataProvider = "testName", dataProviderClass =
+ // AbstractServiceTestImpl.class,
+ // dependsOnMethods = {"delete"})
+ public void deleteNonExistent(String testName) throws Exception {
+ // Perform setup.
+ setupDeleteNonExistent();
+
+ // Submit the request to the service and store the response.
+ ArticleClient client = new ArticleClient();
+ ClientResponse<Response> res = client.delete(NON_EXISTENT_ID);
+ try {
+ int statusCode = res.getStatus();
+
+ // Check the status code of the response: does it match
+ // the expected response(s)?
+ if (logger.isDebugEnabled()) {
+ logger.debug(testName + ": status = " + statusCode);
+ }
+ Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
+ invalidStatusCodeMessage(testRequestType, statusCode));
+ Assert.assertEquals(statusCode, testExpectedStatusCode);
+ } finally {
+ if (res != null) {
+ res.releaseConnection();
+ }
+ }
+ }
+
+ // ---------------------------------------------------------------
+ // Utility tests : tests of code used in tests above
+ // ---------------------------------------------------------------
+
+ /**
+ * Tests the code for manually submitting data that is used by several of
+ * the methods above.
+ */
+ // @Test(dependsOnMethods = {"create", "read"})
+ public void testSubmitRequest() {
+
+ // Expected status code: 200 OK
+ final int EXPECTED_STATUS = Response.Status.OK.getStatusCode();
+
+ // Submit the request to the service and store the response.
+ String method = ServiceRequestType.READ.httpMethodName();
+ String url = getResourceURL(knownResourceId);
+ int statusCode = submitRequest(method, url);
+
+ // Check the status code of the response: does it match
+ // the expected response(s)?
+ if (logger.isDebugEnabled()) {
+ logger.debug("testSubmitRequest: url=" + url + " status="
+ + statusCode);
+ }
+ Assert.assertEquals(statusCode, EXPECTED_STATUS);
+
+ }
+
+ // ---------------------------------------------------------------
+ // Utility methods used by tests above
+ // ---------------------------------------------------------------
+
+ @Override
+ public String getServiceName() {
+ return SERVICE_NAME;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.collectionspace.services.client.test.BaseServiceTest#
+ * getServicePathComponent()
+ */
+ @Override
+ public String getServicePathComponent() {
+ return SERVICE_PATH_COMPONENT;
+ }
+
+ @Override
+ protected PoxPayloadOut createInstance(String identifier) {
+ return createArticleInstance(identifier);
+ }
+
+ /**
+ * Creates the article instance.
+ *
+ * @param identifier
+ * the identifier
+ * @return the multipart output
+ */
+ private PoxPayloadOut createArticleInstance(String identifier) {
+ return createArticleInstance("loaninNumber-" + identifier,
+ "returnDate-" + identifier);
+ }
+
+ /**
+ * Creates the article instance.
+ *
+ * @param loaninNumber
+ * the article number
+ * @param returnDate
+ * the return date
+ * @return the multipart output
+ */
+ private PoxPayloadOut createArticleInstance(String articleNumber,
+ String articleJobId) {
+
+ ArticlesCommon articlesCommon = new ArticlesCommon();
+ articlesCommon.setArticleNumber(articleNumber);
+ articlesCommon.setArticleJobId(articleJobId);
+
+ PoxPayloadOut multipart = new PoxPayloadOut(
+ this.getServicePathComponent());
+ PayloadOutputPart commonPart = multipart.addPart(
+ new ArticleClient().getCommonPartName(), articlesCommon);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("To be created, article common:");
+ logger.debug(objectAsXmlString(articlesCommon, ArticlesCommon.class));
+ }
+
+ return multipart;
+ }
+
+ @Override
+ public void CRUDTests(String testName) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ protected PoxPayloadOut createInstance(String commonPartName,
+ String identifier) {
+ PoxPayloadOut result = createArticleInstance(identifier);
+ return result;
+ }
+
+ @Override
+ protected ArticlesCommon updateInstance(ArticlesCommon commonPartObject) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ protected void compareUpdatedInstances(ArticlesCommon original,
+ ArticlesCommon updated) throws Exception {
+ // TODO Auto-generated method stub
+
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <parent>
+ <artifactId>org.collectionspace.services.article</artifactId>
+ <groupId>org.collectionspace.services</groupId>
+ <version>3.2.1-SNAPSHOT</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>org.collectionspace.services.article.jaxb</artifactId>
+ <name>services.article.jaxb</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.jaxb</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <finalName>collectionspace-services-article-jaxb</finalName>
+ <defaultGoal>install</defaultGoal>
+ <plugins>
+ <plugin>
+ <groupId>org.jvnet.jaxb2.maven2</groupId>
+ <artifactId>maven-jaxb2-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
+
--- /dev/null
+/**
+ * String constants to access XML element names of the ArticlesCommon class.
+ */
+package org.collectionspace.services;
+
+/*
+ <xs:element name="articles_common">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="articleNumber" type="xs:string" /> <!-- An ID for the article (different than the CSID) -->
+ <xs:element name="articleContentUrl" type="xs:string" /> <!-- The URL of the article's content -->
+ <xs:element name="articleJobId" type="xs:string" /> <!-- The asynch job ID -if any -->
+ <xs:element name="articleSource" type="xs:string" /> <!-- The name of the service/resource that was used to create the article. -->
+ <xs:element name="articlePublisher" type="xs:string" /> <!-- The user who published the article -->
+ <xs:element name="accessExpirationDate" type="xs:dateTime" /> <!-- When the article is no longer available for access -->
+ <xs:element name="accessedCount" type="xs:integer" /> <!-- How many times the article has been accessed. -->
+ <xs:element name="accessCountLimit" type="xs:integer" /> <!-- The maximum times the article can be accessed. -->
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ */
+
+public interface ArticlesCommonJAXBSchema {
+ final static String ARTICLE_NUMBER = "articleNumber";
+ final static String ARTICLE_CONTENT_URL = "articleContentUrl";
+ final static String ARTICLE_JOB_ID = "articleJobId";
+ final static String ARTICLE_SOURCE = "articleSource";
+ final static String ARTICLE_PUBLISHER = "articlePublisher";
+ final static String ARTICLE_ACCESS_EXPIRATION_DATE = "accessExpirationDate";
+ final static String ARTICLE_ACCESSED_COUNT = "accessedCount";
+ final static String ARTICLE_ACCESS_COUNT_LIMIT = "accessCountLimit";
+}
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+
+<!-- ArticlesCommon XML Schema (XSD) Entity : ArticlesCommon Used for: JAXB
+ binding between XML and Java objects $LastChangedRevision$ $LastChangedDate$ -->
+
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="1.0"
+ elementFormDefault="unqualified" xmlns:ns="http://collectionspace.org/services/article"
+ xmlns="http://collectionspace.org/services/article" targetNamespace="http://collectionspace.org/services/article"
+ version="0.1">
+
+ <!-- Avoid XmlRootElement nightmare: See http://weblogs.java.net/blog/kohsuke/archive/2006/03/why_does_jaxb_p.html -->
+ <xs:element name="articles_common">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="articleNumber" type="xs:string" /> <!-- An ID for the article (different than the CSID) -->
+ <xs:element name="articleContentUrl" type="xs:string" /> <!-- The URL of the article's content -->
+ <xs:element name="articleJobId" type="xs:string" /> <!-- The asynch job ID -if any -->
+ <xs:element name="articleSource" type="xs:string" /> <!-- The name of the service/resource that was used to create the article. -->
+ <xs:element name="articlePublisher" type="xs:string" /> <!-- The user who published the article -->
+ <xs:element name="accessExpirationDate" type="xs:dateTime" /> <!-- When the article is no longer available for access -->
+ <xs:element name="accessedCount" type="xs:integer" /> <!-- How many times the article has been accessed. -->
+ <xs:element name="accessCountLimit" type="xs:integer" /> <!-- The maximum times the article can be accessed. -->
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+</xs:schema>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- A comment. -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <parent>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.main</artifactId>
+ <version>3.2.1-SNAPSHOT</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>org.collectionspace.services.article</artifactId>
+ <name>services.article</name>
+ <packaging>pom</packaging>
+
+ <dependencies>
+ </dependencies>
+
+ <modules>
+ <module>jaxb</module>
+ <module>client</module>
+ <module>3rdparty</module>
+ <module>service</module>
+ </modules>
+
+</project>
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <parent>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.article</artifactId>
+ <version>3.2.1-SNAPSHOT</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>org.collectionspace.services.article.service</artifactId>
+ <name>services.article.service</name>
+ <packaging>jar</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.article.jaxb</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.article.client</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.collectionobject.jaxb</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <!-- External dependencies -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.1</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.testng</groupId>
+ <artifactId>testng</artifactId>
+ </dependency>
+
+ <!-- javax -->
+
+ <dependency>
+ <groupId>javax.security</groupId>
+ <artifactId>jaas</artifactId>
+ <version>1.0.01</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>dom4j</groupId>
+ <artifactId>dom4j</artifactId>
+ <version>1.6.1</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <!-- jboss -->
+
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-jaxrs</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>tjws</groupId>
+ <artifactId>webserver</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-jaxb-provider</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-multipart-provider</artifactId>
+ </dependency>
+
+ <!-- nuxeo -->
+
+ <dependency>
+ <groupId>org.nuxeo.ecm.core</groupId>
+ <artifactId>nuxeo-core-api</artifactId>
+ <exclusions>
+ <exclusion>
+ <artifactId>jboss-remoting</artifactId>
+ <groupId>jboss</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <finalName>collectionspace-services-article</finalName>
+ </build>
+</project>
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<profilesXml xmlns="http://maven.apache.org/PROFILES/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/PROFILES/1.0.0 http://maven.apache.org/xsd/profiles-1.0.0.xsd">
+</profilesXml>
\ No newline at end of file
--- /dev/null
+/**
+ * This document is a part of the source code and related artifacts
+ * for CollectionSpace, an open source collections management system
+ * for museums and related institutions:
+
+ * http://www.collectionspace.org
+ * http://wiki.collectionspace.org
+
+ * Copyright 2009 University of California at Berkeley
+
+ * Licensed under the Educational Community License (ECL), Version 2.0.
+ * You may not use this file except in compliance with this License.
+
+ * You may obtain a copy of the ECL 2.0 License at
+
+ * https://source.collectionspace.org/collection-space/LICENSE.txt
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.collectionspace.services.article;
+
+import org.collectionspace.services.client.ArticleClient;
+import org.collectionspace.services.common.ResourceBase;
+import org.jboss.resteasy.core.ResourceMethod;
+import org.jboss.resteasy.spi.HttpRequest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+@Path(ArticleClient.SERVICE_PATH)
+@Consumes("application/xml")
+@Produces("application/xml")
+public class ArticleResource extends ResourceBase {
+
+ final Logger logger = LoggerFactory.getLogger(ArticleResource.class);
+
+ @Override
+ protected String getVersionString() {
+ final String lastChangeRevision = "$LastChangedRevision$";
+ return lastChangeRevision;
+ }
+
+ @Override
+ public String getServiceName() {
+ return ArticleClient.SERVICE_NAME;
+ }
+
+ @Override
+ public Class<ArticlesCommon> getCommonPartClass() {
+ return ArticlesCommon.class;
+ }
+
+ @Override
+ public boolean allowAnonymousAccess(HttpRequest request,
+ ResourceMethod method) {
+ return true;
+ }
+}
+
+
+
+
+
+
--- /dev/null
+/**
+ * This document is a part of the source code and related artifacts
+ * for CollectionSpace, an open source collections management system
+ * for museums and related institutions:
+
+ * http://www.collectionspace.org
+ * http://wiki.collectionspace.org
+
+ * Copyright 2009 University of California at Berkeley
+
+ * Licensed under the Educational Community License (ECL), Version 2.0.
+ * You may not use this file except in compliance with this License.
+
+ * You may obtain a copy of the ECL 2.0 License at
+
+ * https://source.collectionspace.org/collection-space/LICENSE.txt
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.collectionspace.services.article.nuxeo;
+
+/**
+ * ArticleConstants specifies constants for the Articles In service
+ *
+ */
+public class ArticleConstants {
+ public final static String NUXEO_DOCTYPE = "Article";
+ public final static String NUXEO_SCHEMA_NAME = "article";
+ public final static String NUXEO_DC_TITLE = "CollectionSpace-Article";
+}
--- /dev/null
+/**
+ * This document is a part of the source code and related artifacts
+ * for CollectionSpace, an open source collections management system
+ * for museums and related institutions:
+
+ * http://www.collectionspace.org
+ * http://wiki.collectionspace.org
+
+ * Copyright 2009 University of California at Berkeley
+
+ * Licensed under the Educational Community License (ECL), Version 2.0.
+ * You may not use this file except in compliance with this License.
+
+ * You may obtain a copy of the ECL 2.0 License at
+
+ * https://source.collectionspace.org/collection-space/LICENSE.txt
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.collectionspace.services.article.nuxeo;
+
+import org.collectionspace.services.article.ArticlesCommon;
+import org.collectionspace.services.nuxeo.client.java.DocHandlerBase;
+
+/** ArticleDocumentModelHandler
+ * $LastChangedRevision$
+ * $LastChangedDate$
+ */
+public class ArticleDocumentModelHandler
+ extends DocHandlerBase<ArticlesCommon> {
+}
+
--- /dev/null
+package org.collectionspace.services.article.nuxeo;
+
+import org.collectionspace.services.common.context.ServiceContext;
+import org.collectionspace.services.common.document.InvalidDocumentException;
+import org.collectionspace.services.common.document.ValidatorHandler;
+import org.collectionspace.services.common.document.DocumentHandler.Action;
+import org.collectionspace.services.client.PoxPayloadIn;
+import org.collectionspace.services.client.PoxPayloadOut;
+
+public class ArticleValidatorHandler implements ValidatorHandler<PoxPayloadIn, PoxPayloadOut> {
+
+ @Override
+ public void validate(Action action, ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx)
+ throws InvalidDocumentException {
+ // TODO Auto-generated method stub
+ System.out.println("ArticleValidatorHandler executed.");
+
+ }
+
+}
--- /dev/null
+package org.collectionspace.services.test;
+
+//import org.collectionspace.services.article.Article;
+//import org.collectionspace.services.article.ArticleList;
+
+/**
+ * Placeholder for server-side testing of Articles service code.
+ *
+ * @version $Revision$
+ */
+public class ArticleServiceTest {
+ //empty
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+
+ <appender name="console" class="org.apache.log4j.ConsoleAppender">
+ <param name="Target" value="System.out" />
+ <layout class="org.apache.log4j.TTCCLayout">
+ <param name="DateFormat" value="ISO8601" />
+ </layout>
+ </appender>
+
+
+ <appender name="unit-tests"
+ class="org.apache.log4j.RollingFileAppender">
+ <param name="File" value="./target/unit-tests.log" />
+ <param name="MaxFileSize" value="10240KB" />
+ <param name="MaxBackupIndex" value="6" />
+ <layout class="org.apache.log4j.TTCCLayout">
+ <param name="DateFormat" value="ISO8601" />
+ </layout>
+ </appender>
+
+ <logger name="org.apache.commons.httpclient" additivity="false">
+ <level value="warn" />
+ <appender-ref ref="console" />
+ <appender-ref ref="unit-tests" />
+ </logger>
+
+ <logger name="httpclient.wire" additivity="false">
+ <level value="info" />
+ <appender-ref ref="console" />
+ <appender-ref ref="unit-tests" />
+ </logger>
+
+ <root>
+ <priority value="debug" />
+ <appender-ref ref="console" />
+ <appender-ref ref="unit-tests" />
+ </root>
+
+</log4j:configuration>
+
+
+
+
*/
public abstract class AuthNContext {
+ public static final String ANONYMOUS_USER = "anonymous";
+ public static final String ANONYMOUS_TENANT_ID = "-1";
+ public static final String ANONYMOUS_TENANT_NAME = ANONYMOUS_USER;
+ public static final String SPRING_ADMIN_USER = "SPRING_ADMIN";
+ public static final String TENANT_ID_QUERY_PARAM = "tid";
+
/**
* getUserId returns authenticated user id
* @return
*/
package org.collectionspace.authentication.spring;
-import java.security.acl.Group;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Set;
+
+import java.security.acl.Group;
import javax.security.auth.Subject;
+
import org.collectionspace.authentication.CSpaceTenant;
import org.collectionspace.authentication.spi.AuthNContext;
+
import org.springframework.security.authentication.jaas.JaasAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
//private static final String SUBJECT_CONTEXT_KEY = "javax.security.auth.Subject.container";
public String getUserId() {
+ String result = ANONYMOUS_USER;
+
Authentication authToken = SecurityContextHolder.getContext().getAuthentication();
- return authToken.getName();
+ if (authToken != null) {
+ result = authToken.getName();
+ }
+
+ return result;
}
/**
@Override
public String getCurrentTenantId() {
- //FIXME assumption in 1.0: each user is associated with a single tenant
- String[] tenantIds = getTenantIds();
- if (tenantIds.length < 1) {
- throw new IllegalStateException("No tenant associated with user=" + getUserId());
- }
- return getTenantIds()[0];
+ String result = ANONYMOUS_TENANT_ID;
+
+ String userId = getUserId();
+ if (userId.equals(ANONYMOUS_USER) == false && userId.equals(SPRING_ADMIN_USER) == false) {
+ String[] tenantIds = getTenantIds();
+ if (tenantIds.length < 1) {
+ throw new IllegalStateException("No tenant associated with user=" + getUserId());
+ }
+ result = getTenantIds()[0];
+ }
+
+ return result;
}
public CSpaceTenant[] getTenants() {
List<CSpaceTenant> tenants = new ArrayList<CSpaceTenant>();
Subject caller = getSubject();
if (caller == null) {
- String msg = "Could not find Subject!";
- //TODO: find out why subject is not null
- //FIXME: if logger is loaded when authn comes up, use it
- //logger.warn(msg);
- System.err.println(msg);
+ if (getUserId().equals(SPRING_ADMIN_USER) == false) {
+ String msg = String.format("Could not find Subject in SpringAuthNContext for user '%s'!", getUserId());
+ System.err.println(msg);
+ }
return tenants.toArray(new CSpaceTenant[0]);
}
+
Set<Group> groups = null;
groups = caller.getPrincipals(Group.class);
if (groups != null && groups.size() == 0) {
@Override
public String getCurrentTenantName() {
- //FIXME assumption in 1.0: each user is associated with a single tenant
- CSpaceTenant[] tenants = getTenants();
- if (tenants.length < 1) {
- throw new IllegalStateException("No tenant associated with user=" + getUserId());
- }
- return getTenants()[0].getName();
+ String result = ANONYMOUS_TENANT_NAME;
+
+ if (getUserId().equals(ANONYMOUS_USER) == false) {
+ CSpaceTenant[] tenants = getTenants();
+ if (tenants.length < 1) {
+ throw new IllegalStateException("No tenant associated with user=" + getUserId());
+ }
+ result = getTenants()[0].getName();
+ }
+
+ return result;
}
public Subject getSubject() {
<parent>
<groupId>org.collectionspace.services</groupId>
<artifactId>org.collectionspace.services.blob</artifactId>
- <version>3.2-SNAPSHOT</version>
+ <version>3.2.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<url>http://www.collectionspace.org</url>
<modules>
- <module>service</module>
- <module>3rdparty</module>
<module>client</module>
+ <module>3rdparty</module>
+ <module>service</module>
</modules>
</project>
<parent>\r
<groupId>org.collectionspace.services</groupId>\r
<artifactId>org.collectionspace.services.collectionobject</artifactId>\r
- <version>3.2-SNAPSHOT</version>\r
+ <version>3.2.1-SNAPSHOT</version>\r
</parent>\r
\r
<modelVersion>4.0.0</modelVersion>\r
</tenant:serviceBindings>
<!-- end account service meta-data -->
+ <!-- begin Article service meta-data -->
+ <tenant:serviceBindings id="Articles" name="Articles" type="procedure" version="0.1">
+ <!-- other URI paths through which this service could be accessed -->
+ <!--
+ <service:uriPath xmlns:service='http://collectionspace.org/services/config/service'>
+ /articles/*/authorityrefs/
+ </service:uriPath>
+ -->
+ <service:repositoryDomain xmlns:service="http://collectionspace.org/services/config/service">default-domain</service:repositoryDomain>
+ <service:documentHandler xmlns:service="http://collectionspace.org/services/config/service">org.collectionspace.services.article.nuxeo.ArticleDocumentModelHandler</service:documentHandler>
+ <service:DocHandlerParams xmlns:service="http://collectionspace.org/services/config/service">
+ <service:params>
+ <service:ListResultsFields>
+ <service:ListResultField>
+ <service:element>articleNumber</service:element>
+ <service:xpath>articleNumber</service:xpath>
+ </service:ListResultField>
+ <service:ListResultField>
+ <service:element>articleContentUrl</service:element>
+ <service:xpath>articleContentUrl</service:xpath>
+ </service:ListResultField>
+ </service:ListResultsFields>
+ </service:params>
+ </service:DocHandlerParams>
+ <service:validatorHandler xmlns:service="http://collectionspace.org/services/config/service">org.collectionspace.services.article.nuxeo.ArticleValidatorHandler</service:validatorHandler>
+ <service:properties xmlns:service="http://collectionspace.org/services/config/service">
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
+ <types:key>objectNameProperty</types:key>
+ <types:value>articleContentUrl</types:value>
+ </types:item>
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
+ <types:key>objectNumberProperty</types:key>
+ <types:value>articleNumber</types:value>
+ </types:item>
+ </service:properties>
+ <service:object xmlns:service="http://collectionspace.org/services/config/service" name="Article" version="0.1">
+ <service:part id="0" control_group="Managed" versionable="true" auditable="false" label="articles-system" updated="" order="0">
+ <service:content contentType="application/xml">
+ <service:xmlContent namespaceURI="http://collectionspace.org/services/config/system" schemaLocation="http://collectionspace.org/services/config/system http://collectionspace.org/services/config/system/system-response.xsd" />
+ </service:content>
+ </service:part>
+ <service:part id="1" control_group="Managed" versionable="true" auditable="false" label="articles_common" updated="" order="1">
+ <service:properties>
+ <!-- Fields containing authority term references -->
+ <!-- Fields containing term list / controlled vocabulary references -->
+ </service:properties>
+ <service:content contentType="application/xml">
+ <service:xmlContent namespaceURI="http://collectionspace.org/services/article" schemaLocation="http://collectionspace.org/services/article http://services.collectionspace.org/article/articles_common.xsd" />
+ </service:content>
+ </service:part>
+ <service:part id="2" control_group="Managed" versionable="true" auditable="false" label="collectionspace_core" updated="" order="2">
+ <service:content contentType="application/xml">
+ <service:xmlContent namespaceURI="http://collectionspace.org/collectionspace_core/" schemaLocation="http://collectionspace.org/collectionspace_core/ http://services.collectionspace.org/collectionspace_core.xsd" />
+ </service:content>
+ </service:part>
+ </service:object>
+ </tenant:serviceBindings>
+ <!-- end Article service meta-data -->
+
<!-- begin dimension service meta-data -->
<tenant:serviceBindings id="Dimensions" name="Dimensions" type="utility" version="0.1">
<!-- other URI paths through which this service could be accessed -->
import org.collectionspace.services.common.security.UnauthorizedException;\r
import org.collectionspace.services.common.storage.StorageClient;\r
import org.collectionspace.services.common.storage.jpa.JpaStorageClientImpl;\r
-import org.jboss.resteasy.client.ClientResponse;\r
+import org.jboss.resteasy.core.ResourceMethod;\r
+import org.jboss.resteasy.spi.HttpRequest;\r
+\r
import org.slf4j.Logger;\r
import org.slf4j.LoggerFactory;\r
\r
\r
return result;\r
}\r
+ \r
+ @Override\r
+ public boolean allowAnonymousAccess(HttpRequest request,\r
+ ResourceMethod method) {\r
+ return false;\r
+ } \r
}\r
import org.collectionspace.services.common.document.DocumentHandler;
import org.collectionspace.services.common.repository.RepositoryClient;
import org.collectionspace.services.common.storage.StorageClient;
+import org.jboss.resteasy.core.ResourceMethod;
+import org.jboss.resteasy.spi.HttpRequest;
/**
* The Interface CollectionSpaceResource.
*/
public ServiceContextFactory<IT, OT> getServiceContextFactory();
+ /*
+ * Returns true if this resource allow anonymous access. It addition to returning 'true', this
+ * resources base URL path needs to be declared in the Spring Security config file's 'springSecurityFilterChain' bean.
+ * There needs to be a 'filter-chain' element something like the following:
+ <sec:filter-chain pattern="/articles/**"
+ filters="none"/>
+ * See the "applicationContext-security.xml" file for details.
+ */
+ public boolean allowAnonymousAccess(HttpRequest request, ResourceMethod method);
+
}
public static final String DEFAULT_ADMIN_PASSWORD = "Administrator";\r
public static final String DEFAULT_READER_PASSWORD = "reader";\r
\r
- public static String ROLE_SPRING_ADMIN_ID = "-1";\r
- public static String ROLE_SPRING_ADMIN_NAME = "ROLE_SPRING_ADMIN";\r
-\r
+ public static final String ROLE_SPRING_ADMIN_ID = "-1";\r
+ public static final String ROLE_SPRING_ADMIN_NAME = "ROLE_SPRING_ADMIN";\r
+ \r
// SQL for init tasks\r
final private static String INSERT_ACCOUNT_ROLE_SQL_MYSQL = \r
"INSERT INTO accounts_roles(account_id, user_id, role_id, role_name, created_at)"\r
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.UriInfo;
+import org.collectionspace.authentication.spi.AuthNContext;
import org.collectionspace.services.client.IQueryManager;
import org.collectionspace.services.client.workflow.WorkflowClient;
import org.collectionspace.services.common.ServiceMain;
*
* @throws UnauthorizedException the unauthorized exception
*/
- protected AbstractServiceContextImpl(String serviceName) throws UnauthorizedException {
+ protected AbstractServiceContextImpl(String serviceName, UriInfo uriInfo) throws UnauthorizedException {
//establish security context
- securityContext = new SecurityContextImpl();
+ securityContext = new SecurityContextImpl(uriInfo);
//make sure tenant context exists
checkTenantContext();
String tenantId = securityContext.getCurrentTenantId();
- if(AuthorizationCommon.ALL_TENANTS_MANAGER_TENANT_ID.equals(tenantId)) {
+ if (AuthorizationCommon.ALL_TENANTS_MANAGER_TENANT_ID.equals(tenantId) ||
+ AuthNContext.ANONYMOUS_TENANT_ID.equals(tenantId)) {
// Tenant Manager has no tenant binding, so don't bother...
tenantBinding = null;
serviceBinding = null;
* @see org.collectionspace.services.common.context.ServiceContextFactory#createServiceContext(java.lang.String)
*/
@Override
- public ServiceContext<PoxPayloadIn, PoxPayloadOut> createServiceContext(String serviceName) throws Exception {
- MultipartServiceContext ctx = new MultipartServiceContextImpl(serviceName);
+ public ServiceContext<PoxPayloadIn, PoxPayloadOut> createServiceContext(
+ String serviceName,
+ UriInfo uriInfo) throws Exception {
+ MultipartServiceContext ctx = new MultipartServiceContextImpl(serviceName, uriInfo);
return ctx;
}
*/
@Override
public ServiceContext<PoxPayloadIn, PoxPayloadOut> createServiceContext(String serviceName,
- PoxPayloadIn input) throws Exception {
- MultipartServiceContext ctx = new MultipartServiceContextImpl(serviceName, input);
+ PoxPayloadIn input,
+ UriInfo uriInfo) throws Exception {
+ MultipartServiceContext ctx = new MultipartServiceContextImpl(serviceName, input, uriInfo);
return ctx;
}
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
-import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.UriInfo;
import org.collectionspace.services.client.PayloadInputPart;
import org.collectionspace.services.common.security.UnauthorizedException;
import org.dom4j.DocumentException;
import org.dom4j.Element;
-//import org.jboss.resteasy.plugins.providers.multipart.InputPart;
-//import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
-//import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
-//import org.jboss.resteasy.plugins.providers.multipart.OutputPart;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
*
* @throws UnauthorizedException the unauthorized exception
*/
- protected MultipartServiceContextImpl(String serviceName)
+ protected MultipartServiceContextImpl(String serviceName,
+ UriInfo uriInfo)
throws DocumentException, UnauthorizedException {
- super(serviceName);
+ super(serviceName, uriInfo);
setOutput(new PoxPayloadOut(serviceName));
}
*
* @throws UnauthorizedException the unauthorized exception
*/
- protected MultipartServiceContextImpl(String serviceName, PoxPayloadIn theInput)
+ protected MultipartServiceContextImpl(String serviceName, PoxPayloadIn theInput, UriInfo uriInfo)
throws DocumentException, UnauthorizedException {
- super(serviceName, theInput);
+ super(serviceName, theInput, uriInfo);
setOutput(new PoxPayloadOut(serviceName));
}
* @see org.collectionspace.services.common.context.ServiceContextFactory#createServiceContext(java.lang.String)\r
*/\r
@Override\r
- public ServiceContext<IT, OT> createServiceContext(String serviceName) throws Exception {\r
- RemoteServiceContext<IT, OT> ctx = new RemoteServiceContextImpl<IT, OT>(serviceName);\r
+ public ServiceContext<IT, OT> createServiceContext(String serviceName, UriInfo uriInfo) throws Exception {\r
+ RemoteServiceContext<IT, OT> ctx = new RemoteServiceContextImpl<IT, OT>(serviceName, uriInfo);\r
return ctx;\r
}\r
\r
*/\r
@Override\r
public ServiceContext<IT, OT> createServiceContext(String serviceName,\r
- IT theInput) throws Exception {\r
- RemoteServiceContext<IT, OT> ctx = new RemoteServiceContextImpl<IT, OT>(serviceName, theInput);\r
+ IT theInput, UriInfo uriInfo) throws Exception {\r
+ RemoteServiceContext<IT, OT> ctx = new RemoteServiceContextImpl<IT, OT>(serviceName, theInput, uriInfo);\r
return ctx;\r
}\r
\r
*
* @throws UnauthorizedException the unauthorized exception
*/
- protected RemoteServiceContextImpl(String serviceName) throws UnauthorizedException {
- super(serviceName);
+ protected RemoteServiceContextImpl(String serviceName, UriInfo uriInfo) throws UnauthorizedException {
+ super(serviceName, uriInfo);
}
/**
*
* @throws UnauthorizedException the unauthorized exception
*/
- protected RemoteServiceContextImpl(String serviceName, IT theInput) throws UnauthorizedException {
- this(serviceName);
+ protected RemoteServiceContextImpl(String serviceName, IT theInput, UriInfo uriInfo) throws UnauthorizedException {
+ this(serviceName, uriInfo);
this.input = theInput;
}
IT theInput,
ResourceMap resourceMap,
UriInfo uriInfo) throws UnauthorizedException {
- this(serviceName, theInput);
+ this(serviceName, theInput, uriInfo);
this.setResourceMap(resourceMap);
this.setUriInfo(uriInfo);
if (uriInfo != null) {
*
* @throws Exception the exception
*/
- public ServiceContext<IT, OT> createServiceContext(String serviceName, IT input) throws Exception;
+ public ServiceContext<IT, OT> createServiceContext(String serviceName, IT input, UriInfo uriInfo) throws Exception;
/**
* Creates a new ServiceContext object.
*
* @throws Exception the exception
*/
- public ServiceContext<IT, OT> createServiceContext(String serviceName) throws Exception;
+ public ServiceContext<IT, OT> createServiceContext(String serviceName, UriInfo uriInfo) throws Exception;
/**
* Creates a new ServiceContext object.
*/
package org.collectionspace.services.common.security;
+import javax.ws.rs.core.UriInfo;
+
import org.collectionspace.authentication.AuthN;
-import org.collectionspace.authentication.CSpaceTenant;
+import org.collectionspace.authentication.spi.AuthNContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private String userId;
private String currentTenantName;
private String currentTenantId;
+
+ private String getTenantId(UriInfo uriInfo) throws UnauthorizedException {
+ String result = AuthN.get().getCurrentTenantId();
+
+ String userId = AuthN.get().getUserId();
+ if (userId.equals(AuthNContext.ANONYMOUS_USER) == true) {
+ //
+ // If anonymous access is being attempted, then a tenant ID needs to be set as a query param
+ //
+ if (uriInfo == null) {
+ String errMsg = "Anonymous access attempted without a valid tenant ID query paramter. A null 'UriInfo' instance was passed into the service context constructor.";
+ logger.error(errMsg);
+ throw new UnauthorizedException(errMsg);
+ }
+
+ String tenantId = uriInfo.getQueryParameters().getFirst(AuthNContext.TENANT_ID_QUERY_PARAM);
+ if (tenantId == null) {
+ String errMsg = String.format("Anonymous access to '%s' attempted without a valid tenant ID query paramter.",
+ uriInfo.getPath());
+ logger.error(errMsg);
+ throw new UnauthorizedException(errMsg);
+ }
+ result = tenantId;
+ }
+
+ return result;
+ }
- public SecurityContextImpl() {
+ public SecurityContextImpl(UriInfo uriInfo) throws UnauthorizedException {
userId = AuthN.get().getUserId();
- currentTenantId = AuthN.get().getCurrentTenantId();
- currentTenantName = AuthN.get().getCurrentTenantName();
+ currentTenantId = getTenantId(uriInfo);
+ currentTenantName = AuthN.get().getCurrentTenantName();
}
@Override
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
+
import org.collectionspace.authentication.AuthN;
import org.collectionspace.services.authorization.AuthZ;
import org.collectionspace.services.authorization.CSpaceResource;
import org.collectionspace.services.authorization.URIResourceImpl;
import org.collectionspace.services.client.workflow.WorkflowClient;
+import org.collectionspace.services.common.CollectionSpaceResource;
import org.collectionspace.services.common.document.JaxbUtils;
import org.collectionspace.services.common.storage.jpa.JpaStorageUtils;
import org.collectionspace.services.common.security.SecurityUtils;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final String ERROR_NUXEO_LOGOUT = "Attempt to logout when Nuxeo login context was null";
private static final String ERROR_UNBALANCED_LOGINS = "The number of Logins vs Logouts to the Nuxeo framework was unbalanced.";
+ private boolean implementsInterface(Class<?> clazz, Class<?> interfaze) {
+ boolean result = false;
+
+ Class<?>[] interfaces = clazz.getInterfaces();
+ for (Class<?> interfaceItem : interfaces) {
+ if (interfaceItem.equals(interfaze)) {
+ result = true;
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ private boolean isAnonymousRequest(HttpRequest request, ResourceMethod resourceMethod) {
+ boolean result = false;
+
+ Class<?> resourceClass = resourceMethod.getResourceClass();
+ try {
+ CollectionSpaceResource resourceInstance = (CollectionSpaceResource)resourceClass.newInstance();
+ result = resourceInstance.allowAnonymousAccess(request, resourceMethod);
+ } catch (InstantiationException e) {
+ logger.error("isAnonymousRequest: ", e);
+ } catch (IllegalAccessException e) {
+ logger.error("isAnonymousRequest: ", e);
+ }
+ return result;
+ }
+
/* (non-Javadoc)
* @see org.jboss.resteasy.spi.interception.PreProcessInterceptor#preProcess(org.jboss.resteasy.spi.HttpRequest, org.jboss.resteasy.core.ResourceMethod)
*/
@Override
- public ServerResponse preProcess(HttpRequest request, ResourceMethod method)
+ public ServerResponse preProcess(HttpRequest request, ResourceMethod resourceMethod)
throws Failure, WebApplicationException {
+ ServerResponse result = null; // A null value essentially means success for this method
+
+ if (isAnonymousRequest(request, resourceMethod) == true) {
+ // We don't need to check credentials for anonymous requests. Just login to Nuxeo and
+ // exit
+ nuxeoPreProcess(request, resourceMethod);
+
+ return result;
+ }
+
final String servicesResource = "/cspace-services/"; // HACK - this is configured in war
final int servicesResourceLen = servicesResource.length();
String httpMethod = request.getHttpMethod();
//
// Login to Nuxeo
//
- nuxeoPreProcess(request, method);
+ nuxeoPreProcess(request, resourceMethod);
//
// We've passed all the checks. Now just log the results
}
}
- return null;
+ return result;
}
@Override
//
// Nuxeo login support
//
- public ServerResponse nuxeoPreProcess(HttpRequest arg0, ResourceMethod arg1)
+ public ServerResponse nuxeoPreProcess(HttpRequest request, ResourceMethod resourceMethod)
throws Failure, WebApplicationException {
try {
nuxeoLogin();
--- /dev/null
+package org.collectionspace.services.common.servlet;
+
+import java.io.IOException;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Servlet implementation class HelloServlet
+ */
+public class PublishedResourcesServlet extends HttpServlet {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * @see HttpServlet#HttpServlet()
+ */
+ public PublishedResourcesServlet() {
+ super();
+ }
+
+ /**
+ * @see Servlet#init(ServletConfig)
+ */
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+ }
+
+ /**
+ * @see Servlet#destroy()
+ */
+ public void destroy() {
+ super.destroy();
+ }
+
+ /**
+ * @see Servlet#getServletConfig()
+ */
+ public ServletConfig getServletConfig() {
+ return super.getServletConfig();
+ }
+
+ /**
+ * @see Servlet#getServletInfo()
+ */
+ public String getServletInfo() {
+ return super.getServletInfo();
+ }
+
+ /**
+ * @see HttpServlet#service(HttpServletRequest request, HttpServletResponse response)
+ */
+ protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ super.service(request, response);
+ }
+
+ /**
+ * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
+ */
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ //super.doGet(request, response);
+ response.setStatus(200);
+ }
+
+ /**
+ * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
+ */
+ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ super.doPost(request, response);
+ }
+
+ /**
+ * @see HttpServlet#doPut(HttpServletRequest, HttpServletResponse)
+ */
+ protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ super.doPut(request, response);
+ }
+
+ /**
+ * @see HttpServlet#doDelete(HttpServletRequest, HttpServletResponse)
+ */
+ protected void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ super.doDelete(request, response);
+ }
+
+ /**
+ * @see HttpServlet#doHead(HttpServletRequest, HttpServletResponse)
+ */
+ protected void doHead(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ super.doHead(request, response);
+ }
+
+ /**
+ * @see HttpServlet#doOptions(HttpServletRequest, HttpServletResponse)
+ */
+ protected void doOptions(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ super.doOptions(request, response);
+ }
+
+ /**
+ * @see HttpServlet#doTrace(HttpServletRequest, HttpServletResponse)
+ */
+ protected void doTrace(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ super.doTrace(request, response);
+ }
+
+}
<module>contact</module>
<module>workflow</module>
<module>media</module>
- <module>JaxRsServiceProvider</module>
+ <module>article</module>
<!--module>sdk</module-->
<module>IntegrationTests</module>
<module>PerformanceTests</module>
<module>security</module>
+ <module>JaxRsServiceProvider</module>
</modules>
<dependencies>