/* * Licensed to DuraSpace under one or more contributor license agreements. * See the NOTICE file distributed with this work for additional information * regarding copyright ownership. * * DuraSpace 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. */ package org.fcrepo.camel.serialization; import static java.net.URI.create; import static java.util.stream.Collectors.toList; import static org.apache.camel.LoggingLevel.INFO; import static org.apache.camel.LoggingLevel.DEBUG; import static org.apache.camel.Exchange.FILE_NAME; import static org.apache.camel.builder.PredicateBuilder.in; import static org.apache.camel.builder.PredicateBuilder.not; import static org.apache.camel.builder.PredicateBuilder.or; import static org.apache.camel.component.exec.ExecBinding.EXEC_COMMAND_ARGS; import static org.fcrepo.camel.FcrepoHeaders.FCREPO_EVENT_TYPE; import static org.fcrepo.camel.FcrepoHeaders.FCREPO_URI; import static org.fcrepo.camel.processor.ProcessorUtils.tokenizePropertyPlaceholder; import java.util.List; import org.apache.camel.Predicate; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.builder.xml.Namespaces; import org.fcrepo.camel.processor.EventProcessor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * * A router for serializing fedora objects and binaries. * * @author Bethany Seeger * @since 2015-09-28 */ public class SerializationRouter extends RouteBuilder { private static final Logger LOGGER = LoggerFactory.getLogger(SerializationRouter.class); private static final String RESOURCE_DELETION = "http://fedora.info/definitions/v4/event#ResourceDeletion"; private static final String DELETE = "https://www.w3.org/ns/activitystreams#Delete"; private static final String REPOSITORY = "http://fedora.info/definitions/v4/repository#"; private static final String isBinaryResourceXPath = "/rdf:RDF/rdf:Description/rdf:type[@rdf:resource=\"" + REPOSITORY + "Binary\"]"; public static final String SERIALIZATION_PATH = "CamelSerializationPath"; public final List<Predicate> uriFilter = tokenizePropertyPlaceholder(getContext(), "{{filter.containers}}", ",") .stream().map(uri -> or( header(FCREPO_URI).startsWith(constant(uri + "/")), header(FCREPO_URI).isEqualTo(constant(uri)))) .collect(toList()); /** * 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#") .add("fedora", REPOSITORY); /** * A generic error handler (specific to this RouteBuilder) */ onException(Exception.class) .maximumRedeliveries("{{error.maxRedeliveries}}") .log("Index Routing Error: ${routeId}"); /** * Handle Serialization Events */ from("{{input.stream}}") .routeId("FcrepoSerialization") .process(new EventProcessor()) .process(exchange -> { final String uri = exchange.getIn().getHeader(FCREPO_URI, "", String.class); exchange.getIn().setHeader(SERIALIZATION_PATH, create(uri).getPath()); }) .filter(not(in(uriFilter))) .choice() .when(or(header(FCREPO_EVENT_TYPE).contains(RESOURCE_DELETION), header(FCREPO_EVENT_TYPE).contains(DELETE))) .to("direct:delete") .otherwise() .multicast().to("direct:metadata", "direct:binary"); from("{{serialization.stream}}") .routeId("FcrepoReSerialization") .filter(not(in(uriFilter))) .process(exchange -> { final String uri = exchange.getIn().getHeader(FCREPO_URI, "", String.class); exchange.getIn().setHeader(SERIALIZATION_PATH, create(uri).getPath()); }) .multicast().to("direct:metadata", "direct:binary"); from("direct:metadata") .routeId("FcrepoSerializationMetadataUpdater") .to("fcrepo:localhost?accept={{serialization.mimeType}}") .log(INFO, LOGGER, "Serializing object ${headers[CamelFcrepoUri]}") .setHeader(FILE_NAME).simple("${headers[CamelSerializationPath]}.{{serialization.extension}}") .log(DEBUG, LOGGER, "filename is ${headers[CamelFileName]}") .to("file://{{serialization.descriptions}}"); from("direct:binary") .routeId("FcrepoSerializationBinaryUpdater") .filter().simple("{{serialization.includeBinaries}} == 'true'") .to("fcrepo:localhost?preferInclude=PreferMinimalContainer" + "&accept=application/rdf+xml") .filter().xpath(isBinaryResourceXPath, ns) .log(INFO, LOGGER, "Writing binary ${headers[CamelSerializationPath]}") .to("fcrepo:localhost?metadata=false") .setHeader(FILE_NAME).header(SERIALIZATION_PATH) .log(DEBUG, LOGGER, "header filename is: ${headers[CamelFileName]}") .to("file://{{serialization.binaries}}"); from("direct:delete") .routeId("FcrepoSerializationDeleter") .setHeader(EXEC_COMMAND_ARGS).simple( "-rf {{serialization.descriptions}}${headers[CamelSerializationPath]}.{{serialization.extension}} " + "{{serialization.descriptions}}${headers[CamelSerializationPath]} " + "{{serialization.binaries}}${headers[CamelSerializationPath]}") .to("exec:rm"); } }