001/*
002 * Licensed to DuraSpace under one or more contributor license agreements.
003 * See the NOTICE file distributed with this work for additional information
004 * regarding copyright ownership.
005 *
006 * DuraSpace licenses this file to you under the Apache License,
007 * Version 2.0 (the "License"); you may not use this file except in
008 * compliance with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.fcrepo.camel.audit.triplestore;
019
020import static java.util.Arrays.asList;
021import static org.fcrepo.camel.FcrepoHeaders.FCREPO_AGENT;
022import static org.fcrepo.camel.FcrepoHeaders.FCREPO_DATE_TIME;
023import static org.fcrepo.camel.FcrepoHeaders.FCREPO_EVENT_TYPE;
024import static org.fcrepo.camel.FcrepoHeaders.FCREPO_EVENT_ID;
025import static org.fcrepo.camel.FcrepoHeaders.FCREPO_RESOURCE_TYPE;
026import static org.fcrepo.camel.FcrepoHeaders.FCREPO_URI;
027import static org.fcrepo.camel.audit.triplestore.AuditSparqlProcessor.AUDIT;
028import static org.fcrepo.camel.audit.triplestore.AuditSparqlProcessor.EVENT_TYPE;
029import static org.fcrepo.camel.audit.triplestore.AuditSparqlProcessor.PREMIS;
030import static org.fcrepo.camel.audit.triplestore.AuditSparqlProcessor.XSD;
031
032import java.io.IOException;
033import java.util.HashMap;
034import java.util.List;
035import java.util.Map;
036
037import org.apache.camel.EndpointInject;
038import org.apache.camel.Exchange;
039import org.apache.camel.Produce;
040import org.apache.camel.ProducerTemplate;
041import org.apache.camel.builder.RouteBuilder;
042import org.apache.camel.component.mock.MockEndpoint;
043import org.apache.camel.test.junit4.CamelTestSupport;
044
045import org.junit.Test;
046
047/**
048 * Test the route workflow.
049 *
050 * @author escowles
051 * @author Aaron Coburn
052 * @since 2015-04-10
053 */
054public class ProcessorTest extends CamelTestSupport {
055
056    @EndpointInject(uri = "mock:result")
057    protected MockEndpoint resultEndpoint;
058
059    @Produce(uri = "direct:start")
060    protected ProducerTemplate template;
061
062    private static final String baseURL = "http://localhost/rest";
063    private static final String eventBaseURI = "http://example.com/event";
064    private static final String nodeID = "/foo";
065    private static final String fileID = "/file1";
066    private static final String eventDate = "2015-04-06T22:45:20Z";
067    private static final String userID = "bypassAdmin";
068    private static final String userAgent = "curl/7.37.1";
069    private static final String eventID = "ab/cd/ef/gh/abcdefgh12345678";
070    private static final String eventURI = eventBaseURI + "/" + eventID;
071    private static final String EVENT_NS = "http://fedora.info/definitions/v4/event#";
072    private static final String AS_NS = "https://www.w3.org/ns/activitystreams#";
073    private static final String REPOSITORY = "http://fedora.info/definitions/v4/repository#";
074
075    @Test
076    public void testNodeAdded() throws Exception {
077
078        resultEndpoint.expectedMessageCount(1);
079        resultEndpoint.expectedHeaderReceived(Exchange.CONTENT_TYPE, "application/x-www-form-urlencoded");
080        resultEndpoint.expectedHeaderReceived(Exchange.HTTP_METHOD, "POST");
081
082        template.sendBodyAndHeaders("",
083                createEvent(nodeID, asList(EVENT_NS + "ResourceCreation"), asList(REPOSITORY + "Resource"), eventID));
084
085        assertMockEndpointsSatisfied();
086        final String body = (String)resultEndpoint.assertExchangeReceived(0).getIn().getBody();
087        assertTrue("Event type not found!",
088            body.contains("<" + eventURI + "> <" + PREMIS + "hasEventType> <" + EVENT_TYPE + "cre>"));
089        assertTrue("Object link not found!",
090            body.contains("<" + eventURI + "> <" + PREMIS + "hasEventRelatedObject> <" + baseURL + nodeID + ">"));
091        assertTrue("Event date not found!",
092            body.contains("<" + eventURI + "> <" + PREMIS + "hasEventDateTime> \"" + eventDate + "\"^^<"
093                    + XSD + "dateTime>"));
094        assertTrue("Event user not found!",
095            body.contains("<" + eventURI + "> <" + PREMIS + "hasEventRelatedAgent> \"" + userID + "\" ."));
096        assertTrue("Event agent not found!",
097            body.contains("<" + eventURI + "> <" + PREMIS + "hasEventRelatedAgent> \"" + userAgent + "\" ."));
098    }
099
100    @Test
101    public void testNodeRemoved() throws Exception {
102
103        resultEndpoint.expectedMessageCount(1);
104        resultEndpoint.expectedHeaderReceived(Exchange.CONTENT_TYPE, "application/x-www-form-urlencoded");
105        resultEndpoint.expectedHeaderReceived(Exchange.HTTP_METHOD, "POST");
106
107        template.sendBodyAndHeaders("",
108                createEvent(nodeID, asList(EVENT_NS + "ResourceDeletion"), asList(REPOSITORY + "Resource"), eventID));
109
110        assertMockEndpointsSatisfied();
111        final String body = (String)resultEndpoint.assertExchangeReceived(0).getIn().getBody();
112        assertTrue("Event type not found!",
113            body.contains("<" + eventURI + "> <" + PREMIS + "hasEventType> <" + EVENT_TYPE + "del>"));
114        assertTrue("Object link not found!",
115            body.contains("<" + eventURI + "> <" + PREMIS + "hasEventRelatedObject> <" + baseURL + nodeID + ">"));
116    }
117
118    @Test
119    public void testPropertiesChanged() throws Exception {
120
121        resultEndpoint.expectedMessageCount(1);
122        resultEndpoint.expectedHeaderReceived(Exchange.CONTENT_TYPE, "application/x-www-form-urlencoded");
123        resultEndpoint.expectedHeaderReceived(Exchange.HTTP_METHOD, "POST");
124
125        template.sendBodyAndHeaders("",
126                createEvent(nodeID, asList(AS_NS + "Update"), asList(REPOSITORY + "Resource"), eventID));
127
128        assertMockEndpointsSatisfied();
129        final String body = (String)resultEndpoint.assertExchangeReceived(0).getIn().getBody();
130        assertTrue("Event type not found!",
131            body.contains("<" + eventURI + "> <" + PREMIS + "hasEventType> <" + AUDIT + "metadataModification>"));
132        assertTrue("Object link not found!",
133            body.contains("<" + eventURI + "> <" + PREMIS + "hasEventRelatedObject> <" + baseURL + nodeID + ">"));
134    }
135
136    @Test
137    public void testFileAdded() throws Exception {
138
139        resultEndpoint.expectedMessageCount(1);
140        resultEndpoint.expectedHeaderReceived(Exchange.CONTENT_TYPE, "application/x-www-form-urlencoded");
141        resultEndpoint.expectedHeaderReceived(Exchange.HTTP_METHOD, "POST");
142
143        template.sendBodyAndHeaders("",
144                createEvent(fileID, asList(AS_NS + "Create"), asList(REPOSITORY + "Binary"), eventID));
145
146        assertMockEndpointsSatisfied();
147        final String body = (String)resultEndpoint.assertExchangeReceived(0).getIn().getBody();
148        assertTrue("Event type not found!",
149            body.contains("<" + eventURI + "> <" + PREMIS + "hasEventType> <" + EVENT_TYPE + "ing>"));
150        assertTrue("Object link not found!",
151            body.contains("<" + eventURI + "> <" + PREMIS + "hasEventRelatedObject> <" + baseURL + fileID + ">"));
152    }
153
154    @Test
155    public void testFileChanged() throws Exception {
156
157        resultEndpoint.expectedMessageCount(1);
158        resultEndpoint.expectedHeaderReceived(Exchange.CONTENT_TYPE, "application/x-www-form-urlencoded");
159        resultEndpoint.expectedHeaderReceived(Exchange.HTTP_METHOD, "POST");
160
161        template.sendBodyAndHeaders("",
162                createEvent(fileID, asList(AS_NS + "Update"), asList(REPOSITORY + "Binary"), eventID));
163
164        assertMockEndpointsSatisfied();
165        final String body = (String)resultEndpoint.assertExchangeReceived(0).getIn().getBody();
166        assertTrue("Event type not found!",
167            body.contains("<" + eventURI + "> <" + PREMIS + "hasEventType> <" + AUDIT + "contentModification>"));
168        assertTrue("Object link not found!",
169            body.contains("<" + eventURI + "> <" + PREMIS + "hasEventRelatedObject> <" + baseURL + fileID + ">"));
170    }
171
172    @Test
173    public void testFileRemoved() throws Exception {
174
175        resultEndpoint.expectedMessageCount(1);
176        resultEndpoint.expectedHeaderReceived(Exchange.CONTENT_TYPE, "application/x-www-form-urlencoded");
177        resultEndpoint.expectedHeaderReceived(Exchange.HTTP_METHOD, "POST");
178
179        template.sendBodyAndHeaders("",
180                createEvent(fileID, asList(AS_NS + "Delete"), asList(REPOSITORY + "Binary"), eventID));
181
182        assertMockEndpointsSatisfied();
183        final String body = (String)resultEndpoint.assertExchangeReceived(0).getIn().getBody();
184        assertTrue("Event type not found!",
185            body.contains("<" + eventURI + "> <" + PREMIS + "hasEventType> <" + AUDIT + "contentRemoval>"));
186        assertTrue("Object link not found!",
187            body.contains("<" + eventURI + "> <" + PREMIS + "hasEventRelatedObject> <" + baseURL + fileID + ">"));
188    }
189
190    private static Map<String,Object> createEvent(final String identifier, final List<String> eventTypes,
191            final List<String> resourceTypes, final String eventID) {
192
193        final Map<String, Object> headers = new HashMap<>();
194        headers.put(FCREPO_URI, baseURL + identifier);
195        headers.put(FCREPO_DATE_TIME, eventDate);
196        headers.put(FCREPO_AGENT, asList(userID, userAgent));
197        headers.put(FCREPO_RESOURCE_TYPE, resourceTypes);
198        headers.put(FCREPO_EVENT_TYPE, eventTypes);
199        headers.put(FCREPO_EVENT_ID, eventID);
200        return headers;
201    }
202
203    @Override
204    protected RouteBuilder createRouteBuilder() {
205        return new RouteBuilder() {
206            @Override
207            public void configure() throws IOException {
208                from("direct:start")
209                    .setHeader(AuditHeaders.EVENT_BASE_URI, constant(eventBaseURI))
210                    .process(new AuditSparqlProcessor())
211                    .to("mock:result");
212            }
213        };
214    }
215}