001/*
002 * The contents of this file are subject to the license and copyright
003 * detailed in the LICENSE and NOTICE files at the root of the source
004 * tree.
005 */
006package org.fcrepo.camel.httpforwarding;
007
008import org.apache.camel.CamelContext;
009import org.apache.camel.Produce;
010import org.apache.camel.ProducerTemplate;
011import org.apache.camel.builder.AdviceWith;
012import org.apache.camel.builder.RouteBuilder;
013import org.apache.camel.component.mock.MockEndpoint;
014import org.apache.camel.model.ModelCamelContext;
015import org.apache.camel.spring.javaconfig.CamelConfiguration;
016import org.junit.BeforeClass;
017import org.junit.Test;
018import org.junit.runner.RunWith;
019import org.springframework.beans.factory.annotation.Autowired;
020import org.springframework.context.annotation.Bean;
021import org.springframework.context.annotation.ComponentScan;
022import org.springframework.context.annotation.Configuration;
023import org.springframework.test.annotation.DirtiesContext;
024import org.springframework.test.context.ContextConfiguration;
025import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
026import org.springframework.test.context.support.AnnotationConfigContextLoader;
027
028import java.util.HashMap;
029import java.util.List;
030import java.util.Map;
031
032import static java.util.Arrays.asList;
033import static java.util.Collections.emptyList;
034import static org.fcrepo.camel.FcrepoHeaders.FCREPO_AGENT;
035import static org.fcrepo.camel.FcrepoHeaders.FCREPO_DATE_TIME;
036import static org.fcrepo.camel.FcrepoHeaders.FCREPO_EVENT_TYPE;
037import static org.fcrepo.camel.FcrepoHeaders.FCREPO_RESOURCE_TYPE;
038import static org.fcrepo.camel.FcrepoHeaders.FCREPO_URI;
039
040/**
041 * Test the route workflow.
042 *
043 * @author Aaron Coburn
044 * @author Demian Katz
045 * @since 2015-04-10
046 */
047@RunWith(SpringJUnit4ClassRunner.class)
048@ContextConfiguration(classes = {RouteTest.ContextConfig.class}, loader = AnnotationConfigContextLoader.class)
049public class RouteTest {
050    private final String EVENT_NS = "https://www.w3.org/ns/activitystreams#";
051    private static final String baseURL = "http://localhost/rest";
052    private static final String httpURL = "http://localhost/http_endpoint";
053    private static final String fileID = "/file1";
054    private static final String eventDate = "2015-04-06T22:45:20Z";
055    private static final String userID = "bypassAdmin";
056    private static final String userAgent = "curl/7.37.1";
057    private static final String auditContainer = "/audit";
058    private static final String inputStream = "seda:foo";
059    private static final String reindexStream = "seda:bar";
060
061    @Autowired
062    private CamelContext camelContext;
063
064    @Produce("direct:start")
065    protected ProducerTemplate template;
066
067    @BeforeClass
068    public static void beforeClass() {
069        System.setProperty("http.enabled", "true");
070        System.setProperty("http.filter.containers", baseURL + auditContainer);
071        System.setProperty("http.input.stream", inputStream);
072        System.setProperty("http.reindex.stream", reindexStream);
073        System.setProperty("error.maxRedeliveries", "10");
074        System.setProperty("fcrepo.baseUrl", baseURL);
075        System.setProperty("http.baseUrl", httpURL);
076        System.setProperty("http.reindex.stream", "seda:reindex");
077    }
078
079    @DirtiesContext
080    @Test
081    public void testEventTypeForwarding() throws Exception {
082        // Let's be sure "Delete" gets passed along as expected
083        final List<String> eventTypes = asList(EVENT_NS + "Delete");
084
085        final var context = camelContext.adapt(ModelCamelContext.class);
086        AdviceWith.adviceWith(context, "FcrepoHttpSend", a -> {
087            a.mockEndpointsAndSkip(httpURL);
088        });
089
090        final var sendEndpoint = MockEndpoint.resolve(camelContext, "mock:http:localhost/http_endpoint");
091        sendEndpoint.expectedMessageCount(1);
092        sendEndpoint.expectedHeaderReceived(FCREPO_EVENT_TYPE, "https://www.w3.org/ns/activitystreams#Delete");
093        template.sendBodyAndHeaders(inputStream, "{}",
094                createEvent(baseURL + fileID, eventTypes));
095
096        MockEndpoint.assertIsSatisfied(sendEndpoint);
097    }
098
099    @DirtiesContext
100    @Test
101    public void testEventTypeInjection() throws Exception {
102        // Let's make sure "Update" is the default when no event type is provided
103        final List<String> eventTypes = emptyList();
104
105        final var context = camelContext.adapt(ModelCamelContext.class);
106        AdviceWith.adviceWith(context, "FcrepoHttpSend", a -> {
107            a.mockEndpointsAndSkip(httpURL);
108        });
109
110        final var sendEndpoint = MockEndpoint.resolve(camelContext, "mock:http:localhost/http_endpoint");
111        sendEndpoint.expectedMessageCount(1);
112        // We expect "Update" as default if nothing is provided
113        sendEndpoint.expectedHeaderReceived(FCREPO_EVENT_TYPE, "https://www.w3.org/ns/activitystreams#Update");
114        template.sendBodyAndHeaders(inputStream, "{}",
115                createEvent(baseURL + fileID, eventTypes));
116
117        MockEndpoint.assertIsSatisfied(sendEndpoint);
118    }
119
120    private static Map<String, Object> createEvent(final String identifier, final List<String> eventTypes) {
121        return createEvent(identifier, eventTypes, emptyList());
122    }
123
124    private static Map<String, Object> createEvent(final String identifier, final List<String> eventTypes,
125                                                   final List<String> resourceTypes) {
126        final Map<String, Object> headers = new HashMap<>();
127        headers.put(FCREPO_URI, identifier);
128        headers.put(FCREPO_DATE_TIME, eventDate);
129        headers.put(FCREPO_AGENT, asList(userID, userAgent));
130        // The HttpRouter expects to find org.fcrepo.jms.eventtype and move it into
131        // FCREPO_EVENT_TYPE (or set a default)
132        if (eventTypes.size() > 0) {
133            headers.put("org.fcrepo.jms.eventtype", eventTypes.get(0));
134        }
135        headers.put(FCREPO_RESOURCE_TYPE, resourceTypes);
136        return headers;
137    }
138
139    @Configuration
140    @ComponentScan(resourcePattern = "**/Fcrepo*.class")
141    static class ContextConfig extends CamelConfiguration {
142
143        @Bean
144        public RouteBuilder route() {
145            return new HttpRouter();
146        }
147    }
148}