001/*
002 * (C) Copyright 2006-2008 Nuxeo SAS (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Alexandre Russel
016 *
017 * $Id$
018 */
019
020package org.nuxeo.ecm.platform.annotations.proxy;
021
022import java.net.MalformedURLException;
023import java.net.URI;
024import java.util.ArrayList;
025import java.util.List;
026import java.util.Map;
027
028import org.apache.commons.logging.Log;
029import org.apache.commons.logging.LogFactory;
030import org.nuxeo.ecm.core.api.NuxeoException;
031import org.nuxeo.ecm.core.api.NuxeoPrincipal;
032import org.nuxeo.ecm.platform.annotations.api.Annotation;
033import org.nuxeo.ecm.platform.annotations.api.AnnotationManager;
034import org.nuxeo.ecm.platform.annotations.api.AnnotationsService;
035import org.nuxeo.ecm.platform.annotations.api.UriResolver;
036import org.nuxeo.ecm.platform.annotations.service.AnnotabilityManager;
037import org.nuxeo.ecm.platform.annotations.service.AnnotationConfigurationService;
038import org.nuxeo.ecm.platform.annotations.service.AnnotationsServiceImpl;
039import org.nuxeo.ecm.platform.annotations.service.EventListener;
040import org.nuxeo.ecm.platform.annotations.service.PermissionManager;
041import org.nuxeo.ecm.platform.annotations.service.URLPatternFilter;
042import org.nuxeo.ecm.platform.relations.api.Graph;
043import org.nuxeo.runtime.api.Framework;
044
045/**
046 * @author <a href="mailto:arussel@nuxeo.com">Alexandre Russel</a>
047 */
048public class AnnotationServiceProxy implements AnnotationsService {
049
050    private static final Log log = LogFactory.getLog(AnnotationServiceProxy.class);
051
052    private final AnnotationManager annotationManager = new AnnotationManager();
053
054    private AnnotationConfigurationService configurationService;
055
056    private AnnotabilityManager annotabilityManager;
057
058    private AnnotationsServiceImpl service;
059
060    private URLPatternFilter filter;
061
062    private UriResolver resolver;
063
064    private PermissionManager permissionManager;
065
066    private List<EventListener> listeners;
067
068    public void initialise() {
069        service = new AnnotationsServiceImpl();
070        configurationService = Framework.getService(AnnotationConfigurationService.class);
071        filter = configurationService.getUrlPatternFilter();
072        resolver = configurationService.getUriResolver();
073        annotabilityManager = configurationService.getAnnotabilityManager();
074        permissionManager = configurationService.getPermissionManager();
075        listeners = configurationService.getListeners();
076    }
077
078    public Annotation addAnnotation(Annotation annotation, NuxeoPrincipal user, String baseUrl) {
079        checkUrl(annotation);
080        Annotation translatedAnnotation = getTranslatedAnnotation(annotation);
081        if (!annotabilityManager.isAnnotable(annotation.getAnnotates())) {
082            throw new NuxeoException("Not annotable uri: " + annotation.getAnnotates());
083        }
084        checkPermission(annotation, user, configurationService.getCreateAnnotationPermission());
085        for (EventListener listener : listeners) {
086            listener.beforeAnnotationCreated(user, translatedAnnotation);
087        }
088        Annotation tmpResult = service.addAnnotation(translatedAnnotation, user, baseUrl);
089        for (EventListener listener : listeners) {
090            listener.afterAnnotationCreated(user, tmpResult);
091        }
092        return annotationManager.translateAnnotationFromRepo(resolver, baseUrl, tmpResult);
093    }
094
095    private void checkPermission(Annotation annotation, NuxeoPrincipal user, String permission) {
096        if (!permissionManager.check(user, permission, annotation.getAnnotates())) {
097            throw new NuxeoException(user + " allowed to query annotation.");
098        }
099    }
100
101    private Annotation getTranslatedAnnotation(Annotation annotation) {
102        Annotation translatedAnnotation = annotationManager.translateAnnotationToRepo(resolver, annotation);
103        return translatedAnnotation;
104    }
105
106    private void checkUrl(Annotation annotation) {
107        try {
108            URI uri = annotation.getAnnotates();
109            if (uri.toASCIIString().startsWith("urn:")) {
110                return;
111            }
112            String url = uri.toURL().toString();
113            if (!filter.allow(url)) {
114                throw new NuxeoException("Not allowed to annotate: " + url);
115            }
116        } catch (MalformedURLException e) {
117            throw new NuxeoException(e);
118        }
119    }
120
121    public void deleteAnnotation(Annotation annotation, NuxeoPrincipal user) {
122        checkPermission(annotation, user, configurationService.getDeleteAnnotationPermission());
123        Annotation translatedAnnotation = getTranslatedAnnotation(annotation);
124        for (EventListener listener : listeners) {
125            listener.beforeAnnotationDeleted(user, translatedAnnotation);
126        }
127        service.deleteAnnotation(translatedAnnotation, user);
128        for (EventListener listener : listeners) {
129            listener.afterAnnotationDeleted(user, translatedAnnotation);
130        }
131    }
132
133    public void deleteAnnotationFor(URI uri, Annotation annotation, NuxeoPrincipal user) {
134        checkPermission(annotation, user, configurationService.getDeleteAnnotationPermission());
135        Annotation translatedAnnotation = getTranslatedAnnotation(annotation);
136        for (EventListener listener : listeners) {
137            listener.beforeAnnotationDeleted(user, translatedAnnotation);
138        }
139        service.deleteAnnotationFor(resolver.translateToGraphURI(uri), translatedAnnotation, user);
140        for (EventListener listener : listeners) {
141            listener.afterAnnotationDeleted(user, translatedAnnotation);
142        }
143    }
144
145    public Annotation getAnnotation(String annotationId, NuxeoPrincipal user, String baseUrl) {
146        for (EventListener listener : listeners) {
147            listener.beforeAnnotationRead(user, annotationId);
148        }
149        Annotation result = service.getAnnotation(annotationId, user, null);
150        checkPermission(result, user, configurationService.getReadAnnotationPermission());
151        for (EventListener listener : listeners) {
152            listener.afterAnnotationRead(user, result);
153        }
154        return annotationManager.translateAnnotationFromRepo(resolver, baseUrl, result);
155    }
156
157    public Graph getAnnotationGraph() {
158        return service.getAnnotationGraph();
159    }
160
161    public List<Annotation> queryAnnotations(URI uri, NuxeoPrincipal user) {
162        String baseUrl = null;
163        if (!uri.toString().startsWith("urn")) {
164            baseUrl = resolver.getBaseUrl(uri);
165        }
166        List<Annotation> tempResult = service.queryAnnotations(resolver.translateToGraphURI(uri), user);
167        List<Annotation> result = new ArrayList<Annotation>();
168        for (Annotation annotation : tempResult) {
169            Annotation translatedAnnotation = annotationManager.translateAnnotationFromRepo(resolver, baseUrl,
170                    annotation);
171            for (EventListener listener : listeners) {
172                listener.afterAnnotationRead(user, translatedAnnotation);
173            }
174            checkPermission(translatedAnnotation, user, configurationService.getReadAnnotationPermission());
175            result.add(translatedAnnotation);
176        }
177        return result;
178    }
179
180    @Override
181    public int getAnnotationsCount(URI uri, NuxeoPrincipal user) {
182        String baseUrl = null;
183        if (!uri.toString().startsWith("urn")) {
184            baseUrl = resolver.getBaseUrl(uri);
185        }
186        return service.getAnnotationsCount(resolver.translateToGraphURI(uri), user);
187    }
188
189    public Annotation updateAnnotation(Annotation annotation, NuxeoPrincipal user, String baseUrl) {
190        checkPermission(annotation, user, configurationService.getUpdateAnnotationPermission());
191        for (EventListener listener : listeners) {
192            listener.beforeAnnotationUpdated(user, annotation);
193        }
194        Annotation result = service.updateAnnotation(getTranslatedAnnotation(annotation), user, baseUrl);
195        for (EventListener listener : listeners) {
196            listener.afterAnnotationUpdated(user, result);
197        }
198        return annotationManager.translateAnnotationFromRepo(resolver, baseUrl, result);
199    }
200}