001/*
002 * (C) Copyright 2014-2016 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 *     Maxime Hilaire
018 *     Florent Guillaume
019 */
020package org.nuxeo.ecm.directory.core;
021
022import org.apache.commons.logging.Log;
023import org.apache.commons.logging.LogFactory;
024import org.nuxeo.ecm.core.api.DocumentModel;
025import org.nuxeo.ecm.core.api.DocumentNotFoundException;
026import org.nuxeo.ecm.core.api.DocumentRef;
027import org.nuxeo.ecm.core.api.PathRef;
028import org.nuxeo.ecm.core.api.UnrestrictedSessionRunner;
029import org.nuxeo.ecm.core.api.security.ACE;
030import org.nuxeo.ecm.core.api.security.ACL;
031import org.nuxeo.ecm.core.api.security.ACP;
032import org.nuxeo.ecm.core.schema.SchemaManager;
033import org.nuxeo.ecm.core.schema.types.Field;
034import org.nuxeo.ecm.core.schema.types.Schema;
035import org.nuxeo.ecm.directory.AbstractDirectory;
036import org.nuxeo.ecm.directory.DirectoryException;
037import org.nuxeo.ecm.directory.DirectoryFieldMapper;
038import org.nuxeo.ecm.directory.Session;
039import org.nuxeo.runtime.api.Framework;
040
041/**
042 * Implementation of a {@link Directory} on top of a core repository.
043 *
044 * @since 8.2
045 */
046public class CoreDirectory extends AbstractDirectory {
047
048    private static final Log log = LogFactory.getLog(CoreDirectory.class);
049
050    protected final Schema schema;
051
052    public CoreDirectory(CoreDirectoryDescriptor descriptor) {
053        super(descriptor);
054        SchemaManager schemaManager = Framework.getService(SchemaManager.class);
055        schema = schemaManager.getSchema(descriptor.schemaName);
056        fieldMapper = new DirectoryFieldMapper(descriptor.fieldMapping);
057        if (schema == null) {
058            throw new DirectoryException(
059                    String.format("Unknown schema '%s' for directory '%s' ", descriptor.schemaName, getName()));
060        }
061        start();
062    }
063
064    @Override
065    public CoreDirectoryDescriptor getDescriptor() {
066        return (CoreDirectoryDescriptor) descriptor;
067    }
068
069    public void start() {
070        CoreDirectoryDescriptor descriptor = getDescriptor();
071        UnrestrictedSessionRunner directoryInitializer = new UnrestrictedSessionRunner(descriptor.getRepositoryName()) {
072
073            @Override
074            public void run() {
075                String createPath = descriptor.getCreatePath();
076
077                DocumentModel rootFolder = null;
078                DocumentRef rootRef = new PathRef(createPath);
079                if (session.exists(rootRef)) {
080                    rootFolder = session.getDocument(rootRef);
081                }
082
083                if (rootFolder == null) {
084
085                    String parentFolder = createPath.substring(0, createPath.lastIndexOf("/"));
086                    if (createPath.lastIndexOf("/") == 0) {
087                        parentFolder = "/";
088                    }
089                    String createFolder = createPath.substring(createPath.lastIndexOf("/") + 1, createPath.length());
090
091                    log.info(String.format(
092                            "Root folder '%s' has not been found for the directory '%s' on the repository '%s', will create it with given ACL",
093                            createPath, getName(), descriptor.getRepositoryName()));
094                    if (descriptor.canCreateRootFolder()) {
095                        try {
096                            DocumentModel doc = session.createDocumentModel(parentFolder, createFolder, "Folder");
097                            doc.setProperty("dublincore", "title", createFolder);
098                            session.createDocument(doc);
099                            // Set ACL from descriptor
100                            for (int i = 0; i < descriptor.acls.length; i++) {
101                                String userOrGroupName = descriptor.acls[i].userOrGroupName;
102                                String privilege = descriptor.acls[i].privilege;
103                                boolean granted = descriptor.acls[i].granted;
104                                setACL(doc, userOrGroupName, privilege, granted);
105                            }
106                            session.save();
107
108                        } catch (DocumentNotFoundException e) {
109                            throw new DirectoryException(String.format(
110                                    "The root folder '%s' can not be created under '%s' for the directory '%s' on the repository '%s',"
111                                            + " please make sure you have set the right path or that the path exist",
112                                    createFolder, parentFolder, getName(), descriptor.getRepositoryName()), e);
113                        }
114                    }
115
116                } else {
117                    log.info(String.format(
118                            "Root folder '%s' has been found for the directory '%s' on the repository '%s', ACL will not be set",
119                            createPath, getName(), descriptor.getRepositoryName()));
120                }
121
122            }
123        };
124        directoryInitializer.runUnrestricted();
125    }
126
127    protected DocumentModel setACL(DocumentModel rootFolder, String userOrGroupName, String privilege,
128            boolean granted) {
129        ACP acp = rootFolder.getACP();
130        ACL localACL = acp.getOrCreateACL();
131        localACL.add(new ACE(userOrGroupName, privilege, granted));
132        rootFolder.setACP(acp, true);
133
134        if (log.isDebugEnabled()) {
135            log.debug(String.format(
136                    "Set ACL on root folder '%s' : userOrGroupName = '%s', privilege = '%s' , granted = '%s' ",
137                    rootFolder.getPathAsString(), userOrGroupName, privilege, granted));
138        }
139
140        return rootFolder.getCoreSession().saveDocument(rootFolder);
141    }
142
143    public Field getField(String name) throws DirectoryException {
144        Field field = schema.getField(name);
145        if (field == null) {
146            throw new DirectoryException(
147                    String.format("Field '%s' does not exist in the schema '%s'", name, schema.getName()));
148        }
149        return field;
150    }
151
152    @Override
153    public Session getSession() throws DirectoryException {
154        CoreDirectorySession session = new CoreDirectorySession(this);
155        addSession(session);
156        return session;
157    }
158
159}