Commit 353e4158 authored by acoburn's avatar acoburn
Browse files

reorganize module layout

parent c5d55734
<?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/xsd/maven-4.0.0.xsd">
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
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.
-->
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>repo-services</artifactId>
<groupId>edu.amherst.acdc</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>acrepo-idmapper-pgsql</artifactId>
<packaging>bundle</packaging>
<name>Postgresql Dataservice Bundle</name>
<description>OSGi dataservice connector for Postgres.</description>
<properties>
<osgi.export.packages>edu.amherst.acdc.pgsql*;version=${project.version}</osgi.export.packages>
</properties>
<dependencies>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>attach-artifact</goal>
</goals>
<configuration>
<artifacts>
<artifact>
<file>src/main/cfg/edu.amherst.acdc.pgsql.cfg</file>
<type>cfg</type>
<classifier>configuration</classifier>
</artifact>
</artifacts>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
pgsql.host=localhost
pgsql.port=5432
pgsql.database=idmapper
pgsql.username=
pgsql.password=
pgsql.ssl=false
pgsql.sslfactory=org.postgresql.ssl.NonValidatingFactory
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0 http://aries.apache.org/schemas/blueprint-cm/blueprint-cm-1.1.0.xsd"
default-activation="lazy">
<cm:property-placeholder persistent-id="edu.amherst.acdc.pgsql" update-strategy="reload" >
<cm:default-properties>
<cm:property name="pgsql.host" value="localhost"/>
<cm:property name="pgsql.port" value="5432"/>
<cm:property name="pgsql.database" value="idmapper"/>
<cm:property name="pgsql.username" value=""/>
<cm:property name="pgsql.password" value=""/>
<cm:property name="pgsql.ssl" value="false"/>
<cm:property name="pgsql.sslfactory" value="org.postgresql.ssl.NonValidatingFactory"/>
</cm:default-properties>
</cm:property-placeholder>
<bean id="dataService" class="org.postgresql.ds.PGPoolingDataSource" destroy-method="close">
<property name="serverName" value="${pgsql.host}"/>
<property name="portNumber" value="${pgsql.port}"/>
<property name="databaseName" value="${pgsql.database}"/>
<property name="user" value="${pgsql.username}"/>
<property name="password" value="${pgsql.password}"/>
<property name="initialConnections" value="2"/>
<property name="maxConnections" value="4"/>
<property name="ssl" value="${pgsql.ssl}"/>
<property name="sslfactory" value="${pgsql.sslfactory}"/>
</bean>
<service interface="javax.sql.DataSource" ref="dataService">
<service-properties>
<entry key="osgi.jndi.service.name" value="idmapperds"/>
</service-properties>
</service>
</blueprint>
#Fedora Audit Service (Triplestore)
This application implements a bridge to an external, triplestore-based
[Audit Service](https://wiki.duraspace.org/display/FF/Design+-+Audit+Service)
for [Fedora4](http://fcrepo.org).
**This application is currently in development**
##Building
To build this project use
mvn install
##Running from the command line
To run the project you can execute the following Maven goal
mvn camel:run
##Deploying in OSGi
This project can be deployed in an OSGi container. For example using
[Apache ServiceMix](http://servicemix.apache.org/) or
[Apache Karaf](http://karaf.apache.org), you can run the following
command from its shell:
feature:repo-add mvn:org.fcrepo.camel/fcrepo-camel-toolbox/LATEST/xml/features
feature:install fcrepo-audit-triplestore
Or by copying the compiled bundle into `$KARAF_HOME/deploy`.
##Configuration
The application can be configured by creating the following configuration
file `$KARAF_HOME/etc/org.fcrepo.camel.audit.cfg`. The following values
are available for configuration:
The name of the container where internal audit events are created (if using
[fcrepo-audit](http://github.com/fcrepo4-exts/fcrepo-audit)). Events about
resources in this container are ignored.
audit.container=/audit
In the event of failure, the maximum number of times a redelivery will be attempted.
error.maxRedeliveries=10
The baseUri to use for event URIs in the triplestore. A `UUID` will be appended
to this value, forming, for instance: `http://example.com/event/{UUID}`
event.baseUri=http://example.com/event
The connection URI used to connect to a local or remote ActiveMQ broker
jms.brokerUrl=tcp://localhost:61616
The camel URI for the incoming message stream.
input.stream=activemq:topic:fedora
The base URL of the triplestore being used.
triplestore.baseUrl=localhost:8080/fuseki/test/update
By editing this file, any currently running routes will be immediately redeployed
with the new values.
For more help see the Apache Camel documentation
http://camel.apache.org/
......@@ -9,7 +9,7 @@
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>repo-id-mapper</artifactId>
<artifactId>acrepo-idmapper</artifactId>
<packaging>bundle</packaging>
<name>ID mapping service</name>
......@@ -25,12 +25,11 @@
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-blueprint</artifactId>
<artifactId>camel-sql</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-cassandraql</artifactId>
<version>${camel.version}</version>
<artifactId>camel-blueprint</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
......@@ -40,23 +39,49 @@
<groupId>org.fcrepo.camel</groupId>
<artifactId>fcrepo-camel</artifactId>
</dependency>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.codehaus.woodstox</groupId>
<artifactId>woodstox-core-asl</artifactId>
<version>4.4.1</version>
</dependency>
<!-- logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
<!-- testing -->
<dependency>
<groupId>edu.amherst.acdc</groupId>
<artifactId>acrepo-idmapper-pgsql</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-test-blueprint</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
......
......@@ -13,15 +13,16 @@
*/
package edu.amherst.acdc.idmapper;
import org.apache.camel.builder.xml.Namespaces;
import org.apache.camel.LoggingLevel;
import org.apache.camel.PropertyInject;
import org.apache.camel.RuntimeCamelException;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.builder.xml.Namespaces;
/**
* A content router for handling JMS events.
*
* @author Aaron Coburn
* @author escowles
*/
public class EventRouter extends RouteBuilder {
......@@ -29,14 +30,25 @@ public class EventRouter extends RouteBuilder {
private static final String CQL_GET = "";
private static final String CQL_DELETE = "";
@PropertyInject(value = "rest.port", defaultValue = "9081")
private String port;
/**
* Configure the message route workflow.
*/
public void configure() throws Exception {
final Namespaces ns = new Namespaces("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
ns.add("dc", "http://purl.org/dc/elements/1.1/");
try {
final String property = getContext().resolvePropertyPlaceholders("{{id.property}}");
final String namespace = getContext().resolvePropertyPlaceholders("{{id.namespace}}");
final String prefix = property.substring(0, property.indexOf(":"));
ns.add(prefix, namespace);
} catch (final Exception ex) {
throw new RuntimeCamelException("Could not resolve property placeholders", ex);
}
/**
* A generic error handler (specific to this RouteBuilder)
......@@ -45,11 +57,14 @@ public class EventRouter extends RouteBuilder {
.maximumRedeliveries("{{error.maxRedeliveries}}")
.log("Event Routing Error: ${routeId}");
restConfiguration().component("jetty").port(
System.getProperty("acdc.ext.idmapper.port", port));
/**
* Process a message.
*/
from("{{input.stream}}")
.routeId("IdMapperRouter")
.routeId("IdMappingRouter")
.to("direct:event");
from("direct:event")
......@@ -57,12 +72,14 @@ public class EventRouter extends RouteBuilder {
.log(LoggingLevel.INFO, "edu.amherst.acdc.idmapper",
"IdMapping Event: ${headers[org.fcrepo.jms.identifier]}")
.to("fcrepo:localhost:8080/rest?preferOmit=PreferContainment")
.filter(ns.xpath("/rdf:RDF/rdf:Description/dc:identifier"))
.split().xtokenize("//dc:identifier", ns)
.transform().xpath("/dc:identifier/@rdf:resource|/dc:identifier/text()", String.class, ns)
.log("Body: ${body}")
.process(new IdProcessor())
.to("jdbc:idmapper");
.split().xtokenize("//{{id.property}}", 'i', ns)
.transform().xpath("/{{id.property}}/@rdf:resource | /{{id.property}}/text()", String.class, ns)
.process(new IdProcessor())
.to("direct:update");
from("direct:update")
.routeId("IdMappingUpdateRouter")
.to("sql:select count(*) from uris");
from("direct:get")
.routeId("IdMappingFetchRouter")
......@@ -72,7 +89,7 @@ public class EventRouter extends RouteBuilder {
from("direct:put")
.routeId("IdMappingPutRouter")
.log("${headers}")
.to("mock:jdbc:idmapper");
.to("direct:update");
from("direct:delete")
.routeId("IdMappingDeleteRouter")
......
......@@ -13,20 +13,24 @@
<cm:property name="error.maxRedeliveries" value="10"/>
<cm:property name="jms.brokerUrl" value="tcp://localhost:61616"/>
<cm:property name="input.stream" value="activemq:topic:fedora"/>
<cm:property name="triplestore.baseUrl" value="localhost:8080/fuseki/test/update"/>
<!-- Base URI to be used in contructing the URI for the JMS event -->
<cm:property name="event.baseUri" value="http://example.com/event"/>
<cm:property name="audit.container" value="/audit"/>
<cm:property name="id.property" value="dc:identifier"/>
<cm:property name="id.namespace" value="http://purl.org/dc/elements/1.1/"/>
</cm:default-properties>
</cm:property-placeholder>
<reference id="dataSource" interface="javax.sql.DataSource" filter="(osgi.jndi.service.name=idmapperds)"/>
<!-- component-wide configuration of jdbc -->
<bean id="sql" class="org.apache.camel.component.sql.SqlComponent">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="brokerURL" value="${jms.brokerUrl}"/>
</bean>
<camelContext xmlns="http://camel.apache.org/schema/blueprint">
<package>org.fcrepo.camel.audit.triplestore</package>
<package>edu.amherst.acdc.idmapper</package>
</camelContext>
</blueprint>
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 edu.amherst.acdc.idmapper;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import org.apache.camel.EndpointInject;
import org.apache.camel.Produce;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.builder.AdviceWithRouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.test.blueprint.CamelBlueprintTestSupport;
import org.apache.camel.util.KeyValueHolder;
import org.apache.camel.util.ObjectHelper;
import org.apache.commons.io.IOUtils;
import org.fcrepo.camel.JmsHeaders;
import org.postgresql.ds.PGPoolingDataSource;
import org.junit.Test;
/**
* Test the route workflow.
*
* @author Aaron Coburn
* @since 2015-04-10
*/
public class RouteTest extends CamelBlueprintTestSupport {
@EndpointInject(uri = "mock:result")
protected MockEndpoint resultEndpoint;
@Produce(uri = "direct:start")
protected ProducerTemplate template;
@Override
protected String getBlueprintDescriptor() {
return "/OSGI-INF/blueprint/blueprint.xml";
}
@Override
public boolean isUseAdviceWith() {
return true;
}
@Override
public boolean isUseRouteBuilder() {
return false;
}
@Override
protected Properties useOverridePropertiesWithPropertiesComponent() {
final Properties props = new Properties();
props.put("input.stream", "seda:foo");
return props;
}
@Override
protected void addServicesOnStartup(final Map<String, KeyValueHolder<Object, Dictionary>> services) {
services.put("dataSource", asService(new PGPoolingDataSource(), "name", "idmapperds"));
}
@Test
public void testEvent() throws Exception {
context.getRouteDefinition("IdMappingRouter").adviceWith(context, new AdviceWithRouteBuilder() {
@Override
public void configure() throws Exception {
replaceFromWith("direct:start");
}
});
context.getRouteDefinition("IdMappingEventRouter").adviceWith(context, new AdviceWithRouteBuilder() {
@Override
public void configure() throws Exception {
mockEndpointsAndSkip("fcrepo*");
}
});
context.getRouteDefinition("IdMappingUpdateRouter").adviceWith(context, new AdviceWithRouteBuilder() {
@Override
public void configure() throws Exception {
mockEndpointsAndSkip("sql*");
weaveAddLast().to("mock:result");
}
});
context.start();
getMockEndpoint("mock:result").expectedMessageCount(2);
final Map<String, Object> headers = new HashMap<>();
headers.put(JmsHeaders.IDENTIFIER, "/foo/bar");
template.sendBodyAndHeaders(
IOUtils.toString(ObjectHelper.loadResourceAsStream("indexable.rdf"),
"UTF-8"), headers);
assertMockEndpointsSatisfied();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about="http://localhost:8080/fcrepo4/rest/foo">
<rdf:type rdf:resource="http://www.w3.org/ns/ldp#RDFSource"/>
<rdf:type rdf:resource="http://www.w3.org/ns/ldp#Container"/>
<rdf:type rdf:resource="http://fedora.info/definitions/v4/repository#Container"/>
<rdf:type rdf:resource="http://fedora.info/definitions/v4/repository#Resource"/>
<dc:identifier rdf:resource="http://example.org/object/1"/>
<dc:identifier rdf:resource="http://example.org/object/2"/>
</rdf:Description>
</rdf:RDF>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%p %d{HH:mm:ss.SSS} \(%c{0}\) %m%n</pattern>
</encoder>
</appender>
<logger name="edu.amherst.acdc.idmapper" additivity="false" level="INFO">
<appender-ref ref="STDOUT"/>
</logger>
<logger name="org.apache.camel" additivity="false" level="INFO">
<appender-ref ref="STDOUT"/>
</logger>
<logger name="org.fcrepo.camel" additivity="false" level="INFO">
<appender-ref ref="STDOUT"/>
</logger>
<root additivity="false" level="INFO">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
......@@ -9,9 +9,8 @@
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>repo-karaf</artifactId>
<artifactId>acrepo-karaf</artifactId>
<packaging>pom</packaging>
<version>1.0.0-SNAPSHOT</version>
<name>Karaf Provisioning Features for repository services</name>
......
<?xml version='1.0' encoding='UTF-8'?>
<features xmlns="http://karaf.apache.org/xmlns/features/v1.0.0" name="amherst-acdc-repo-services-${project.version}">
<features xmlns="http://karaf.apache.org/xmlns/features/v1.0.0" name="amherst-repo-services-${project.version}">
<repository>mvn:org.fcrepo.camel/fcrepo-camel/${fcrepo-camel.version}/xml/features</repository>
<repository>mvn:org.apache.camel.karaf/apache-camel/${camel.version}/xml/features</repository>
<repository>mvn:org.apache.activemq/activemq-karaf/${activemq.version}/xml/features</repository>
<feature name="repo-id-mapper" version="${project.version}" resolver="(obr)" start-level="50">
<details>Installs the geneva synchronizer</details>
<feature name="acrepo-idmapper" version="${project.version}" resolver="(obr)" start-level="50">
<details>Installs the id mapping service</details>
<feature version="${camel.version}">camel</feature>
<feature version="${camel.version}">camel-blueprint</feature>
......@@ -15,15 +15,15 @@
<bundle>mvn:edu.amherst.acdc/repo-id-mapper/{project.version}</bundle>
<configfile finalname="/etc/edu.amherst.acdc.idmapper.cfg">mvn:edu.amherst.acdc/repo-id-mapper/${project.version}/cfg/configuration</configfile>
<configfile finalname="/etc/edu.amherst.acdc.idmapper.cfg">mvn:edu.amherst.acdc/acrepo-idmapper/${project.version}/cfg/configuration</configfile>
</feature>