001/*
002 * (C) Copyright 2006-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 *     George Lefter
018 *     Olivier Grisel
019 *     Benjamin Jalon
020 *     Florent Guillaume
021 */
022package org.nuxeo.ecm.directory;
023
024import static org.nuxeo.ecm.directory.localconfiguration.DirectoryConfigurationConstants.DIRECTORY_CONFIGURATION_FACET;
025
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.DocumentModel;
032import org.nuxeo.ecm.core.api.localconfiguration.LocalConfigurationService;
033import org.nuxeo.ecm.directory.api.DirectoryService;
034import org.nuxeo.ecm.directory.localconfiguration.DirectoryConfiguration;
035import org.nuxeo.runtime.api.Framework;
036import org.nuxeo.runtime.model.ComponentContext;
037import org.nuxeo.runtime.model.ComponentInstance;
038import org.nuxeo.runtime.model.DefaultComponent;
039import org.nuxeo.runtime.model.Extension;
040import org.nuxeo.runtime.transaction.TransactionHelper;
041
042public class DirectoryServiceImpl extends DefaultComponent implements DirectoryService {
043
044    protected static final String DELIMITER_BETWEEN_DIRECTORY_NAME_AND_SUFFIX = "_";
045
046    private static final Log log = LogFactory.getLog(DirectoryServiceImpl.class);
047
048    protected DirectoryRegistry registry = new DirectoryRegistry();
049
050    @Override
051    public void activate(ComponentContext context) {
052    }
053
054    @Override
055    public void deactivate(ComponentContext context) {
056        registry.shutdown();
057    }
058
059    @Override
060    public void registerContribution(Object contribution, String extensionPoint, ComponentInstance contributor) {
061        DirectoryFactoryDescriptor factoryDescriptor = (DirectoryFactoryDescriptor) contribution;
062        String factoryName = factoryDescriptor.getFactoryName();
063        log.warn("No need to register factoryDescriptor anymore: " + factoryName);
064    }
065
066    @Override
067    public void registerDirectoryDescriptor(BaseDirectoryDescriptor descriptor) {
068        registry.addContribution(descriptor);
069    }
070
071    @Override
072    public void unregisterDirectoryDescriptor(BaseDirectoryDescriptor descriptor) {
073        registry.removeContribution(descriptor);
074    }
075
076    @Override
077    public void applicationStarted(ComponentContext context) {
078        if (Framework.isTestModeSet()) {
079            // when testing, DatabaseHelper init hasn't occurred yet,
080            // so keep to lazy initialization
081            return;
082        }
083        // open all directories at application startup, so that
084        // their tables are created (outside a transaction) if needed
085        for (Directory dir : getDirectories()) {
086            // open directory to init its resources (tables for SQLDirectory)
087            dir.getSession().close();
088        }
089        // commit the transaction so that tables are committed
090        if (TransactionHelper.isTransactionActiveOrMarkedRollback()) {
091            TransactionHelper.commitOrRollbackTransaction();
092            TransactionHelper.startTransaction();
093        }
094    }
095
096    protected DirectoryConfiguration getDirectoryConfiguration(DocumentModel documentContext) {
097        LocalConfigurationService localConfigurationService = Framework.getService(LocalConfigurationService.class);
098
099        if (localConfigurationService == null) {
100            log.info("Local configuration not deployed, will use default configuration");
101            return null;
102        }
103
104        return localConfigurationService.getConfiguration(DirectoryConfiguration.class, DIRECTORY_CONFIGURATION_FACET,
105                documentContext);
106    }
107
108    /**
109     * This will return the local directory name according the local configuration. If the local configuration is null
110     * or the suffix value is null or the suffix value trimmed is an empty string the returned value is the
111     * directoryName given in parameter. If not this is directoryName + DELIMITER_BETWEEN_DIRECTORY_NAME_AND_SUFFIX +
112     * suffix. if directoryName is null, return null.
113     */
114    protected String getWaitingLocalDirectoryName(String directoryName, DirectoryConfiguration configuration) {
115        if (directoryName == null) {
116            return null;
117        }
118
119        if (configuration != null && configuration.getDirectorySuffix() != null) {
120            String suffix = configuration.getDirectorySuffix().trim();
121            if (!"".equals(suffix)) {
122                return directoryName + DELIMITER_BETWEEN_DIRECTORY_NAME_AND_SUFFIX + suffix;
123            }
124            log.warn("The local configuration detected is an empty value, we consider it as no configuration set.");
125            log.debug("Directory Local Configuration is on : " + configuration.getDocumentRef());
126        }
127
128        return directoryName;
129    }
130
131    @Override
132    public BaseDirectoryDescriptor getDirectoryDescriptor(String id) {
133        return registry.getDirectoryDescriptor(id);
134    }
135
136    @Override
137    public Directory getDirectory(String id) {
138        if (id == null) {
139            // TODO throw an exception
140            return null;
141        }
142        return registry.getDirectory(id);
143    }
144
145    @Override
146    public Directory getDirectory(String id, DocumentModel documentContext) {
147        if (id == null) {
148            // TODO throw an exception
149            return null;
150        }
151        String localDirectoryName = getWaitingLocalDirectoryName(id, getDirectoryConfiguration(documentContext));
152        Directory dir = getDirectory(localDirectoryName);
153        if (dir == null && !id.equals(localDirectoryName)) {
154            log.debug(String.format(
155                    "The local directory named '%s' was" + " not found. Look for the default one named: %s",
156                    localDirectoryName, id));
157            dir = getDirectory(id);
158        }
159        return dir;
160    }
161
162    protected Directory getDirectoryOrFail(String name) throws DirectoryException {
163        return getDirectoryOrFail(name, null);
164    }
165
166    protected Directory getDirectoryOrFail(String id, DocumentModel documentContext) throws DirectoryException {
167        Directory dir = getDirectory(id, documentContext);
168        if (dir == null) {
169            throw new DirectoryException("No directory registered with name: " + id);
170        }
171        return dir;
172    }
173
174    @Override
175    public List<Directory> getDirectories() {
176        return registry.getDirectories();
177    }
178
179    @Override
180    public List<String> getDirectoryNames() {
181        return registry.getDirectoryIds();
182    }
183
184    @Override
185    public String getDirectorySchema(String directoryName) throws DirectoryException {
186        return getDirectoryOrFail(directoryName).getSchema();
187    }
188
189    @Override
190    public String getDirectoryIdField(String directoryName) throws DirectoryException {
191        return getDirectoryOrFail(directoryName).getIdField();
192    }
193
194    @Override
195    public String getDirectoryPasswordField(String directoryName) throws DirectoryException {
196        return getDirectoryOrFail(directoryName).getPasswordField();
197    }
198
199    @Override
200    public String getParentDirectoryName(String directoryName) throws DirectoryException {
201        return getDirectoryOrFail(directoryName).getParentDirectory();
202    }
203
204    @Override
205    public Session open(String directoryName) throws DirectoryException {
206        return getDirectoryOrFail(directoryName).getSession();
207    }
208
209    @Override
210    public Session open(String directoryName, DocumentModel documentContext) throws DirectoryException {
211        return getDirectoryOrFail(directoryName, documentContext).getSession();
212    }
213
214}