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.reindexing;
019
020import static org.fcrepo.camel.FcrepoHeaders.FCREPO_IDENTIFIER;
021import static org.fcrepo.camel.FcrepoHeaders.FCREPO_BASE_URL;
022
023import java.net.InetAddress;
024import java.util.HashMap;
025import java.util.Map;
026import java.util.Properties;
027
028import org.apache.camel.EndpointInject;
029import org.apache.camel.Exchange;
030import org.apache.camel.Produce;
031import org.apache.camel.ProducerTemplate;
032import org.apache.camel.builder.AdviceWithRouteBuilder;
033import org.apache.camel.component.mock.MockEndpoint;
034import org.apache.camel.model.TransformDefinition;
035import org.apache.camel.test.blueprint.CamelBlueprintTestSupport;
036import org.apache.camel.util.ObjectHelper;
037
038import org.junit.Test;
039
040/**
041 * Test the route workflow.
042 *
043 * @author acoburn
044 * @since 2015-05-22
045 */
046public class RouteTest extends CamelBlueprintTestSupport {
047
048    private static final String restPrefix = "/reindexing";
049    private static final String reindexingStream = "broker:queue:foo";
050
051    @EndpointInject(uri = "mock:result")
052    protected MockEndpoint resultEndpoint;
053
054    @Produce(uri = "direct:start")
055    protected ProducerTemplate template;
056
057    @Override
058    public boolean isUseAdviceWith() {
059        return true;
060    }
061
062    @Override
063    public boolean isUseRouteBuilder() {
064        return false;
065    }
066
067    @Override
068    protected String getBlueprintDescriptor() {
069        return "/OSGI-INF/blueprint/blueprint-test.xml";
070    }
071
072    @Override
073    protected Properties useOverridePropertiesWithPropertiesComponent() {
074
075        final String restPort = System.getProperty("fcrepo.dynamic.reindexing.port", "9080");
076
077        final Properties props = new Properties();
078        props.put("reindexing.stream", reindexingStream);
079        props.put("rest.prefix", restPrefix);
080        props.put("rest.port", restPort);
081        return props;
082    }
083
084    @Test
085    public void testUsageRoute() throws Exception {
086
087        final String restPort = System.getProperty("fcrepo.dynamic.reindexing.port", "9080");
088
089        context.getRouteDefinition("FcrepoReindexingTraverse").adviceWith(context, new AdviceWithRouteBuilder() {
090            @Override
091            public void configure() throws Exception {
092                replaceFromWith("direct:traverse");
093                mockEndpointsAndSkip("broker:*");
094                mockEndpointsAndSkip("fcrepo:*");
095            }
096        });
097        context.getRouteDefinition("FcrepoReindexingUsage").adviceWith(context, new AdviceWithRouteBuilder() {
098            @Override
099            public void configure() throws Exception {
100                weaveAddLast().to("mock:result");
101            }
102        });
103
104        context.start();
105
106        getMockEndpoint("mock:result").expectedMessageCount(1);
107        getMockEndpoint("mock:result").message(0).body().contains("Fedora Reindexing Service");
108        getMockEndpoint("mock:result").message(0).body().contains(
109                InetAddress.getLocalHost().getHostName() + ":" + restPort + restPrefix);
110
111        template.sendBody("direct:usage", null);
112
113        assertMockEndpointsSatisfied();
114    }
115
116
117    @Test
118    public void testReindexNoEndpointsRoute() throws Exception {
119        final String id = "/foo";
120
121        context.getRouteDefinition("FcrepoReindexingReindex").adviceWith(context, new AdviceWithRouteBuilder() {
122            @Override
123            public void configure() throws Exception {
124                mockEndpointsAndSkip(reindexingStream + "?disableTimeToLive=true");
125                weaveByType(TransformDefinition.class).after().to("mock:result");
126            }
127        });
128        context.getRouteDefinition("FcrepoReindexingTraverse").adviceWith(context, new AdviceWithRouteBuilder() {
129            @Override
130            public void configure() throws Exception {
131                replaceFromWith("direct:traverse");
132                mockEndpointsAndSkip("broker:*");
133                mockEndpointsAndSkip("fcrepo:*");
134            }
135        });
136        context.start();
137
138        getMockEndpoint("mock:" + reindexingStream).expectedMessageCount(0);
139        getMockEndpoint("mock:result").expectedMessageCount(1);
140        getMockEndpoint("mock:result").expectedHeaderReceived(FCREPO_IDENTIFIER, id);
141        getMockEndpoint("mock:result").expectedBodiesReceived("No endpoints configured for indexing");
142
143
144        final Map<String, Object> headers = new HashMap<>();
145        headers.put(Exchange.HTTP_PATH, id);
146        headers.put(ReindexingHeaders.RECIPIENTS, "");
147
148        template.sendBodyAndHeaders("direct:reindex", null, headers);
149
150        assertMockEndpointsSatisfied();
151    }
152
153    @Test
154    public void testReindexWithEndpointsRoute() throws Exception {
155        final String id = "/foo";
156
157        context.getRouteDefinition("FcrepoReindexingReindex").adviceWith(context, new AdviceWithRouteBuilder() {
158            @Override
159            public void configure() throws Exception {
160                mockEndpointsAndSkip(reindexingStream + "?disableTimeToLive=true");
161                weaveByType(TransformDefinition.class).after().to("mock:result");
162            }
163        });
164        context.getRouteDefinition("FcrepoReindexingTraverse").adviceWith(context, new AdviceWithRouteBuilder() {
165            @Override
166            public void configure() throws Exception {
167                replaceFromWith("direct:traverse");
168                mockEndpointsAndSkip("broker:*");
169                mockEndpointsAndSkip("fcrepo:*");
170            }
171        });
172        context.start();
173
174        getMockEndpoint("mock:" + reindexingStream).expectedMessageCount(1);
175        getMockEndpoint("mock:result").expectedMessageCount(1);
176        getMockEndpoint("mock:result").expectedHeaderReceived(FCREPO_IDENTIFIER, id);
177        getMockEndpoint("mock:result").expectedBodiesReceived("Indexing started at " + id);
178
179        final Map<String, Object> headers = new HashMap<>();
180        headers.put(Exchange.HTTP_PATH, id);
181        headers.put(ReindexingHeaders.RECIPIENTS, "mock:endpoint");
182
183        template.sendBodyAndHeaders("direct:reindex", null, headers);
184
185        assertMockEndpointsSatisfied();
186    }
187
188    @Test
189    public void testTraversal() throws Exception {
190
191        getMockEndpoint("mock:direct:recipients").expectedMessageCount(1);
192        getMockEndpoint("mock:" + reindexingStream).expectedMessageCount(7);
193        getMockEndpoint("mock:" + reindexingStream).expectedHeaderValuesReceivedInAnyOrder(FCREPO_IDENTIFIER,
194                "/foo/a", "/foo/b", "/foo/c", "/foo/d", "/foo/e", "/foo/f", "/foo/g");
195
196        context.getRouteDefinition("FcrepoReindexingTraverse").adviceWith(context, new AdviceWithRouteBuilder() {
197            @Override
198            public void configure() throws Exception {
199                replaceFromWith("direct:traverse");
200                mockEndpointsAndSkip("fcrepo:*");
201                mockEndpointsAndSkip(reindexingStream + "*");
202                mockEndpointsAndSkip("direct:recipients");
203            }
204        });
205        context.start();
206
207        template.sendBodyAndHeader("direct:traverse", ObjectHelper.loadResourceAsStream("indexable.rdf"),
208                FCREPO_BASE_URL, "http://localhost:8080/fcrepo4/rest");
209
210        assertMockEndpointsSatisfied();
211    }
212
213    @Test
214    public void testRecipientList() throws Exception {
215        final String id = "/foo";
216
217        context.getRouteDefinition("FcrepoReindexingTraverse").adviceWith(context, new AdviceWithRouteBuilder() {
218            @Override
219            public void configure() throws Exception {
220                replaceFromWith("direct:traverse");
221                mockEndpointsAndSkip("broker:*");
222                mockEndpointsAndSkip("fcrepo:*");
223            }
224        });
225        context.start();
226
227        getMockEndpoint("mock:foo").expectedMessageCount(1);
228        getMockEndpoint("mock:foo").expectedHeaderReceived(FCREPO_IDENTIFIER, id);
229        getMockEndpoint("mock:bar").expectedMessageCount(1);
230        getMockEndpoint("mock:bar").expectedHeaderReceived(FCREPO_IDENTIFIER, id);
231
232        final Map<String, Object> headers = new HashMap<>();
233        headers.put(FCREPO_IDENTIFIER, id);
234        headers.put(ReindexingHeaders.RECIPIENTS, "mock:foo,mock:bar");
235
236        template.sendBodyAndHeaders("direct:recipients", null, headers);
237
238        assertMockEndpointsSatisfied();
239    }
240}