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;
038
039public class DirectoryServiceImpl extends DefaultComponent implements DirectoryService {
040
041    protected static final String DELIMITER_BETWEEN_DIRECTORY_NAME_AND_SUFFIX = "_";
042
043    private static final Log log = LogFactory.getLog(DirectoryServiceImpl.class);
044
045    protected DirectoryRegistry registry = new DirectoryRegistry();
046
047    @Override
048    public void activate(ComponentContext context) {
049    }
050
051    @Override
052    public void deactivate(ComponentContext context) {
053        registry.shutdown();
054    }
055
056    @Override
057    public void registerContribution(Object contribution, String extensionPoint, ComponentInstance contributor) {
058        DirectoryFactoryDescriptor factoryDescriptor = (DirectoryFactoryDescriptor) contribution;
059        String factoryName = factoryDescriptor.getFactoryName();
060        log.warn("No need to register factoryDescriptor anymore: " + factoryName);
061    }
062
063    @Override
064    public void registerDirectoryDescriptor(BaseDirectoryDescriptor descriptor) {
065        registry.addContribution(descriptor);
066    }
067
068    @Override
069    public void unregisterDirectoryDescriptor(BaseDirectoryDescriptor descriptor) {
070        registry.removeContribution(descriptor);
071    }
072
073    @Override
074    public int getApplicationStartedOrder() {
075        // earlier than the repository init, which has order 100,
076        // but later than the cache service, which has order 95 (100-5)
077        return 97;
078    }
079
080    @Override
081    public void start(ComponentContext context) {
082        List<Directory> directories = getDirectories();
083        directories.forEach(Directory::initialize);
084        directories.forEach(Directory::initializeReferences);
085        directories.forEach(Directory::initializeInverseReferences);
086    }
087
088    protected DirectoryConfiguration getDirectoryConfiguration(DocumentModel documentContext) {
089        LocalConfigurationService localConfigurationService = Framework.getService(LocalConfigurationService.class);
090
091        if (localConfigurationService == null) {
092            log.info("Local configuration not deployed, will use default configuration");
093            return null;
094        }
095
096        return localConfigurationService.getConfiguration(DirectoryConfiguration.class, DIRECTORY_CONFIGURATION_FACET,
097                documentContext);
098    }
099
100    /**
101     * This will return the local directory name according the local configuration. If the local configuration is null
102     * or the suffix value is null or the suffix value trimmed is an empty string the returned value is the
103     * directoryName given in parameter. If not this is directoryName + DELIMITER_BETWEEN_DIRECTORY_NAME_AND_SUFFIX +
104     * suffix. if directoryName is null, return null.
105     */
106    protected String getWaitingLocalDirectoryName(String directoryName, DirectoryConfiguration configuration) {
107        if (directoryName == null) {
108            return null;
109        }
110
111        if (configuration != null && configuration.getDirectorySuffix() != null) {
112            String suffix = configuration.getDirectorySuffix().trim();
113            if (!"".equals(suffix)) {
114                return directoryName + DELIMITER_BETWEEN_DIRECTORY_NAME_AND_SUFFIX + suffix;
115            }
116            log.warn("The local configuration detected is an empty value, we consider it as no configuration set.");
117            log.debug("Directory Local Configuration is on : " + configuration.getDocumentRef());
118        }
119
120        return directoryName;
121    }
122
123    @Override
124    public BaseDirectoryDescriptor getDirectoryDescriptor(String id) {
125        return registry.getDirectoryDescriptor(id);
126    }
127
128    @Override
129    public Directory getDirectory(String id) {
130        if (id == null) {
131            // TODO throw an exception
132            return null;
133        }
134        return registry.getDirectory(id);
135    }
136
137    @Override
138    public Directory getDirectory(String id, DocumentModel documentContext) {
139        if (id == null) {
140            // TODO throw an exception
141            return null;
142        }
143        String localDirectoryName = getWaitingLocalDirectoryName(id, getDirectoryConfiguration(documentContext));
144        Directory dir = getDirectory(localDirectoryName);
145        if (dir == null && !id.equals(localDirectoryName)) {
146            log.debug(String.format(
147                    "The local directory named '%s' was" + " not found. Look for the default one named: %s",
148                    localDirectoryName, id));
149            dir = getDirectory(id);
150        }
151        return dir;
152    }
153
154    protected Directory getDirectoryOrFail(String name) {
155        return getDirectoryOrFail(name, null);
156    }
157
158    protected Directory getDirectoryOrFail(String id, DocumentModel documentContext) {
159        Directory dir = getDirectory(id, documentContext);
160        if (dir == null) {
161            throw new DirectoryException("No directory registered with name: " + id);
162        }
163        return dir;
164    }
165
166    @Override
167    public List<Directory> getDirectories() {
168        return registry.getDirectories();
169    }
170
171    @Override
172    public List<String> getDirectoryNames() {
173        return registry.getDirectoryIds();
174    }
175
176    @Override
177    public String getDirectorySchema(String directoryName) {
178        return getDirectoryOrFail(directoryName).getSchema();
179    }
180
181    @Override
182    public String getDirectoryIdField(String directoryName) {
183        return getDirectoryOrFail(directoryName).getIdField();
184    }
185
186    @Override
187    public String getDirectoryPasswordField(String directoryName) {
188        return getDirectoryOrFail(directoryName).getPasswordField();
189    }
190
191    @Override
192    public String getParentDirectoryName(String directoryName) {
193        return getDirectoryOrFail(directoryName).getParentDirectory();
194    }
195
196    @Override
197    public Session open(String directoryName) {
198        return getDirectoryOrFail(directoryName).getSession();
199    }
200
201    @Override
202    public Session open(String directoryName, DocumentModel documentContext) {
203        return getDirectoryOrFail(directoryName, documentContext).getSession();
204    }
205
206}