001/**
002 * Copyright 2015 DuraSpace, Inc.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.fcrepo.jms.headers;
017
018import static com.google.common.base.Strings.isNullOrEmpty;
019import static java.util.stream.Collectors.joining;
020import static org.fcrepo.kernel.api.RdfLexicon.REPOSITORY_NAMESPACE;
021import static org.modeshape.jcr.api.JcrConstants.JCR_CONTENT;
022import static org.slf4j.LoggerFactory.getLogger;
023
024import java.io.IOException;
025import java.util.Set;
026import javax.jms.JMSException;
027import javax.jms.Message;
028
029import org.fcrepo.jms.observer.JMSEventMessageFactory;
030import org.fcrepo.kernel.api.observer.FedoraEvent;
031import org.fcrepo.kernel.api.utils.EventType;
032
033import org.slf4j.Logger;
034
035import com.fasterxml.jackson.databind.ObjectMapper;
036import com.fasterxml.jackson.databind.JsonNode;
037
038/**
039 * Generates JMS {@link Message}s composed entirely of headers, based entirely
040 * on information found in the {@link FedoraEvent} that triggers publication.
041 *
042 * @author ajs6f
043 * @author escowles
044 * @since Dec 2, 2013
045 */
046public class DefaultMessageFactory implements JMSEventMessageFactory {
047
048    public static final String JMS_NAMESPACE = "org.fcrepo.jms.";
049
050    public static final String TIMESTAMP_HEADER_NAME = JMS_NAMESPACE
051            + "timestamp";
052
053    public static final String IDENTIFIER_HEADER_NAME = JMS_NAMESPACE
054            + "identifier";
055
056    public static final String EVENT_TYPE_HEADER_NAME = JMS_NAMESPACE
057            + "eventType";
058
059    public static final String BASE_URL_HEADER_NAME = JMS_NAMESPACE
060            + "baseURL";
061
062    public static final String PROPERTIES_HEADER_NAME = JMS_NAMESPACE
063            + "properties";
064
065    public static final String USER_HEADER_NAME = JMS_NAMESPACE + "user";
066    public static final String USER_AGENT_HEADER_NAME = JMS_NAMESPACE + "userAgent";
067    public static final String EVENT_ID_HEADER_NAME = JMS_NAMESPACE + "eventID";
068
069    private String baseURL;
070    private String userAgent;
071
072    @Override
073    public Message getMessage(final FedoraEvent jcrEvent,
074        final javax.jms.Session jmsSession) throws JMSException {
075
076        final Message message = jmsSession.createMessage();
077        message.setLongProperty(TIMESTAMP_HEADER_NAME, jcrEvent.getDate());
078        String path = jcrEvent.getPath();
079        if ( path.endsWith("/" + JCR_CONTENT) ) {
080            path = path.replaceAll("/" + JCR_CONTENT,"");
081        }
082
083        // extract baseURL and userAgent from event UserData
084        try {
085            final String userdata = jcrEvent.getUserData();
086            if (!isNullOrEmpty(userdata)) {
087                final ObjectMapper mapper = new ObjectMapper();
088                final JsonNode json = mapper.readTree(userdata);
089                String url = json.get("baseURL").asText();
090                while (url.endsWith("/")) {
091                    url = url.substring(0, url.length() - 1);
092                }
093                this.baseURL = url;
094                this.userAgent = json.get("userAgent").asText();
095                LOGGER.debug("MessageFactory baseURL: {}, userAgent: {}", baseURL, userAgent);
096
097            } else {
098                LOGGER.warn("MessageFactory event UserData is empty!");
099            }
100
101        } catch ( final IOException ex ) {
102            LOGGER.warn("Error setting baseURL or userAgent", ex);
103        }
104
105        message.setStringProperty(IDENTIFIER_HEADER_NAME, path);
106        message.setStringProperty(EVENT_TYPE_HEADER_NAME, getEventURIs( jcrEvent
107                .getTypes()));
108        message.setStringProperty(BASE_URL_HEADER_NAME, baseURL);
109        message.setStringProperty(USER_HEADER_NAME, jcrEvent.getUserID());
110        message.setStringProperty(USER_AGENT_HEADER_NAME, userAgent);
111        message.setStringProperty(PROPERTIES_HEADER_NAME, String.join(",", jcrEvent.getProperties()));
112        message.setStringProperty(EVENT_ID_HEADER_NAME, jcrEvent.getEventID());
113
114        LOGGER.trace("getMessage() returning: {}", message);
115        return message;
116    }
117
118    private static String getEventURIs(final Set<Integer> types) {
119        final String uris = types.stream()
120                                 .map(EventType::valueOf)
121                                 .map(EventType::toString)
122                                 .map(REPOSITORY_NAMESPACE::concat)
123                                 .collect(joining(","));
124
125        LOGGER.debug("Constructed event type URIs: {}", uris);
126        return uris;
127    }
128
129    private static final Logger LOGGER = getLogger(DefaultMessageFactory.class);
130
131}