001/*
002 * (C) Copyright 2014 Nuxeo SA (http://nuxeo.com/) and others.
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 *
016 * Contributors:
017 *     Thierry Delprat
018 */
019package org.nuxeo.segment.io.listener;
020
021import java.io.Serializable;
022import java.security.Principal;
023import java.util.ArrayList;
024import java.util.HashMap;
025import java.util.List;
026import java.util.Map;
027
028import javax.security.auth.login.LoginContext;
029import javax.security.auth.login.LoginException;
030
031import org.nuxeo.ecm.core.api.NuxeoException;
032import org.nuxeo.ecm.core.api.NuxeoPrincipal;
033import org.nuxeo.ecm.core.event.Event;
034import org.nuxeo.ecm.core.event.EventBundle;
035import org.nuxeo.ecm.core.event.PostCommitEventListener;
036import org.nuxeo.ecm.core.event.impl.DocumentEventContext;
037import org.nuxeo.ecm.platform.usermanager.UserManager;
038import org.nuxeo.runtime.api.Framework;
039import org.nuxeo.segment.io.SegmentIO;
040import org.nuxeo.segment.io.SegmentIOMapper;
041
042public class SegmentIOAsyncListener implements PostCommitEventListener {
043
044    @Override
045    public void handleEvent(EventBundle bundle) {
046
047        SegmentIO service = Framework.getService(SegmentIO.class);
048
049        List<String> eventToProcess = new ArrayList<>();
050
051        for (String event : service.getMappedEvents()) {
052            if (bundle.containsEventName(event)) {
053                eventToProcess.add(event);
054            }
055        }
056
057        if (eventToProcess.size() > 0) {
058            Map<String, List<SegmentIOMapper>> event2Mappers = service.getMappers(eventToProcess);
059
060            try {
061                // Force system login in order to have access to user directory
062                LoginContext login = Framework.login();
063                try {
064                    processEvents(event2Mappers, bundle);
065                } finally {
066                    if (login != null) {
067                        login.logout();
068                    }
069                }
070            } catch (LoginException e) {
071                throw new NuxeoException(e);
072            }
073        }
074    }
075
076    protected void processEvents(Map<String, List<SegmentIOMapper>> event2Mappers, EventBundle bundle) {
077
078        for (Event event : bundle) {
079            List<SegmentIOMapper> mappers = event2Mappers.get(event.getName());
080            if (mappers == null || mappers.size() == 0) {
081                continue;
082            }
083
084            for (SegmentIOMapper mapper : mappers) {
085                Map<String, Object> ctx = new HashMap<>();
086
087                Principal princ = event.getContext().getPrincipal();
088                SegmentIO service = Framework.getService(SegmentIO.class);
089                if (!service.mustTrackprincipal(princ.getName())) {
090                    break;
091                }
092
093                NuxeoPrincipal principal;
094                if (princ instanceof NuxeoPrincipal) {
095                    principal = (NuxeoPrincipal) princ;
096                } else {
097                    principal = Framework.getService(UserManager.class).getPrincipal(princ.getName());
098                }
099
100                ctx.put("event", event);
101                ctx.put("eventContext", event.getContext());
102                ctx.put("principal", principal);
103                if (event.getContext() instanceof DocumentEventContext) {
104                    DocumentEventContext docCtx = (DocumentEventContext) event.getContext();
105                    ctx.put("doc", docCtx.getSourceDocument());
106                    ctx.put("repository", docCtx.getRepositoryName());
107                    ctx.put("session", docCtx.getCoreSession());
108                    ctx.put("dest", docCtx.getDestination());
109                }
110
111                Map<String, Serializable> mapped = mapper.getMappedData(ctx);
112                if (mapper.isIdentify()) {
113                    service.identify(principal, mapped);
114                } else if (mapper.isPage()) {
115                    service.page(principal, getNameWithDefault(event, "page"), mapped);
116                } else if (mapper.isScreen()) {
117                    service.screen(principal, getNameWithDefault(event, "screen"), mapped);
118                } else {
119                    service.track(principal, event.getName(), mapped);
120                }
121            }
122        }
123    }
124
125    protected String getNameWithDefault(Event e, String defaultName) {
126        return (String) e.getContext().getProperties().getOrDefault("name", defaultName);
127    }
128}