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