001/*
002 * (C) Copyright 2006-2008 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 *     Alexandre Russel
018 *
019 * $Id$
020 */
021
022package org.nuxeo.ecm.platform.annotations.proxy;
023
024import java.net.MalformedURLException;
025import java.net.URI;
026import java.util.ArrayList;
027import java.util.List;
028
029import org.apache.commons.logging.Log;
030import org.apache.commons.logging.LogFactory;
031import org.nuxeo.ecm.core.api.NuxeoException;
032import org.nuxeo.ecm.core.api.NuxeoPrincipal;
033import org.nuxeo.ecm.platform.annotations.api.Annotation;
034import org.nuxeo.ecm.platform.annotations.api.AnnotationManager;
035import org.nuxeo.ecm.platform.annotations.api.AnnotationsService;
036import org.nuxeo.ecm.platform.annotations.api.UriResolver;
037import org.nuxeo.ecm.platform.annotations.service.AnnotabilityManager;
038import org.nuxeo.ecm.platform.annotations.service.AnnotationConfigurationService;
039import org.nuxeo.ecm.platform.annotations.service.AnnotationsServiceImpl;
040import org.nuxeo.ecm.platform.annotations.service.EventListener;
041import org.nuxeo.ecm.platform.annotations.service.PermissionManager;
042import org.nuxeo.ecm.platform.annotations.service.URLPatternFilter;
043import org.nuxeo.ecm.platform.relations.api.Graph;
044import org.nuxeo.runtime.api.Framework;
045
046/**
047 * @author <a href="mailto:arussel@nuxeo.com">Alexandre Russel</a>
048 */
049public class AnnotationServiceProxy implements AnnotationsService {
050
051    private static final Log log = LogFactory.getLog(AnnotationServiceProxy.class);
052
053    private final AnnotationManager annotationManager = new AnnotationManager();
054
055    private AnnotationConfigurationService configurationService;
056
057    private AnnotabilityManager annotabilityManager;
058
059    private AnnotationsServiceImpl service;
060
061    private URLPatternFilter filter;
062
063    private UriResolver resolver;
064
065    private PermissionManager permissionManager;
066
067    private List<EventListener> listeners;
068
069    public void initialise() {
070        service = new AnnotationsServiceImpl();
071        configurationService = Framework.getService(AnnotationConfigurationService.class);
072        filter = configurationService.getUrlPatternFilter();
073        resolver = configurationService.getUriResolver();
074        annotabilityManager = configurationService.getAnnotabilityManager();
075        permissionManager = configurationService.getPermissionManager();
076        listeners = configurationService.getListeners();
077    }
078
079    @Override
080    public Annotation addAnnotation(Annotation annotation, NuxeoPrincipal user, String baseUrl) {
081        checkUrl(annotation);
082        Annotation translatedAnnotation = getTranslatedAnnotation(annotation);
083        if (!annotabilityManager.isAnnotable(annotation.getAnnotates())) {
084            throw new NuxeoException("Not annotable uri: " + annotation.getAnnotates());
085        }
086        checkPermission(annotation, user, configurationService.getCreateAnnotationPermission());
087        for (EventListener listener : listeners) {
088            listener.beforeAnnotationCreated(user, translatedAnnotation);
089        }
090        Annotation tmpResult = service.addAnnotation(translatedAnnotation, user, baseUrl);
091        for (EventListener listener : listeners) {
092            listener.afterAnnotationCreated(user, tmpResult);
093        }
094        return annotationManager.translateAnnotationFromRepo(resolver, baseUrl, tmpResult);
095    }
096
097    private void checkPermission(Annotation annotation, NuxeoPrincipal user, String permission) {
098        if (!permissionManager.check(user, permission, annotation.getAnnotates())) {
099            throw new NuxeoException(user + " allowed to query annotation.");
100        }
101    }
102
103    private Annotation getTranslatedAnnotation(Annotation annotation) {
104        Annotation translatedAnnotation = annotationManager.translateAnnotationToRepo(resolver, annotation);
105        return translatedAnnotation;
106    }
107
108    private void checkUrl(Annotation annotation) {
109        try {
110            URI uri = annotation.getAnnotates();
111            if (uri.toASCIIString().startsWith("urn:")) {
112                return;
113            }
114            String url = uri.toURL().toString();
115            if (!filter.allow(url)) {
116                throw new NuxeoException("Not allowed to annotate: " + url);
117            }
118        } catch (MalformedURLException e) {
119            throw new NuxeoException(e);
120        }
121    }
122
123    @Override
124    public void deleteAnnotation(Annotation annotation, NuxeoPrincipal user) {
125        checkPermission(annotation, user, configurationService.getDeleteAnnotationPermission());
126        Annotation translatedAnnotation = getTranslatedAnnotation(annotation);
127        for (EventListener listener : listeners) {
128            listener.beforeAnnotationDeleted(user, translatedAnnotation);
129        }
130        service.deleteAnnotation(translatedAnnotation, user);
131        for (EventListener listener : listeners) {
132            listener.afterAnnotationDeleted(user, translatedAnnotation);
133        }
134    }
135
136    @Override
137    public void deleteAnnotationFor(URI uri, Annotation annotation, NuxeoPrincipal user) {
138        checkPermission(annotation, user, configurationService.getDeleteAnnotationPermission());
139        Annotation translatedAnnotation = getTranslatedAnnotation(annotation);
140        for (EventListener listener : listeners) {
141            listener.beforeAnnotationDeleted(user, translatedAnnotation);
142        }
143        service.deleteAnnotationFor(resolver.translateToGraphURI(uri), translatedAnnotation, user);
144        for (EventListener listener : listeners) {
145            listener.afterAnnotationDeleted(user, translatedAnnotation);
146        }
147    }
148
149    @Override
150    public Annotation getAnnotation(String annotationId, NuxeoPrincipal user, String baseUrl) {
151        for (EventListener listener : listeners) {
152            listener.beforeAnnotationRead(user, annotationId);
153        }
154        Annotation result = service.getAnnotation(annotationId, user, null);
155        checkPermission(result, user, configurationService.getReadAnnotationPermission());
156        for (EventListener listener : listeners) {
157            listener.afterAnnotationRead(user, result);
158        }
159        return annotationManager.translateAnnotationFromRepo(resolver, baseUrl, result);
160    }
161
162    @Override
163    public Graph getAnnotationGraph() {
164        return service.getAnnotationGraph();
165    }
166
167    @Override
168    public List<Annotation> queryAnnotations(URI uri, NuxeoPrincipal user) {
169        String baseUrl = null;
170        if (!uri.toString().startsWith("urn")) {
171            baseUrl = resolver.getBaseUrl(uri);
172        }
173        List<Annotation> tempResult = service.queryAnnotations(resolver.translateToGraphURI(uri), user);
174        List<Annotation> result = new ArrayList<Annotation>();
175        for (Annotation annotation : tempResult) {
176            Annotation translatedAnnotation = annotationManager.translateAnnotationFromRepo(resolver, baseUrl,
177                    annotation);
178            for (EventListener listener : listeners) {
179                listener.afterAnnotationRead(user, translatedAnnotation);
180            }
181            checkPermission(translatedAnnotation, user, configurationService.getReadAnnotationPermission());
182            result.add(translatedAnnotation);
183        }
184        return result;
185    }
186
187    @Override
188    public int getAnnotationsCount(URI uri, NuxeoPrincipal user) {
189        String baseUrl = null;
190        if (!uri.toString().startsWith("urn")) {
191            baseUrl = resolver.getBaseUrl(uri);
192        }
193        return service.getAnnotationsCount(resolver.translateToGraphURI(uri), user);
194    }
195
196    @Override
197    public Annotation updateAnnotation(Annotation annotation, NuxeoPrincipal user, String baseUrl) {
198        checkPermission(annotation, user, configurationService.getUpdateAnnotationPermission());
199        for (EventListener listener : listeners) {
200            listener.beforeAnnotationUpdated(user, annotation);
201        }
202        Annotation result = service.updateAnnotation(getTranslatedAnnotation(annotation), user, baseUrl);
203        for (EventListener listener : listeners) {
204            listener.afterAnnotationUpdated(user, result);
205        }
206        return annotationManager.translateAnnotationFromRepo(resolver, baseUrl, result);
207    }
208}