001/*
002 *  Copyright 2015 Anyware Services
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 */
016package org.ametys.plugins.serverdirectory;
017
018import java.util.Collection;
019import java.util.Collections;
020import java.util.HashMap;
021import java.util.Map;
022import java.util.Set;
023
024import org.apache.avalon.framework.logger.LogEnabled;
025import org.apache.avalon.framework.logger.Logger;
026import org.apache.avalon.framework.service.ServiceException;
027import org.apache.avalon.framework.service.ServiceManager;
028import org.apache.avalon.framework.service.Serviceable;
029import org.apache.commons.lang.StringUtils;
030import org.apache.excalibur.source.Source;
031import org.apache.excalibur.source.SourceException;
032import org.apache.excalibur.source.SourceResolver;
033import org.apache.excalibur.source.TraversableSource;
034
035import org.ametys.runtime.i18n.I18nizableText;
036import org.ametys.runtime.model.Enumerator;
037
038/**
039 * Enumerate sub-directories from root directories defined in configuration's parameters
040 */
041public class ServerDirectoryEnumerator implements Serviceable, Enumerator<String>, org.ametys.runtime.parameter.Enumerator, LogEnabled
042{
043    private SourceResolver _sourceResolver;
044    private Logger _logger;
045
046    public void service(ServiceManager manager) throws ServiceException
047    {
048        _sourceResolver = (SourceResolver) manager.lookup(SourceResolver.ROLE);
049    }
050    
051    @Override
052    public void enableLogging(Logger logger)
053    {
054        _logger = logger;
055    }
056    
057    @Override
058    public I18nizableText getEntry(String value) throws Exception
059    {
060        return new I18nizableText(value);
061    }
062    
063    @Override
064    public Map<String, I18nizableText> getTypedEntries() throws Exception
065    {
066        Map<String, I18nizableText> directories = new HashMap<>();
067
068        Set<String> locations = ServerDirectoryHelper.getRootServerDirectoryPaths();
069        
070        for (String location : locations)
071        {
072            Source source = null;
073            try
074            {
075                source = _sourceResolver.resolveURI(location, "file://", null);
076                
077                if (source.exists())
078                {
079                    directories.putAll(_getDirectories(source));
080                }
081                else
082                {
083                    _logger.error("The path '" + location + "' is not an existing server directory. It will be ignored");
084                }
085                
086            }
087            catch (Exception e)
088            {
089                throw new IllegalArgumentException("Cannot enumerate subdirectories for location: <" + location + ">", e);
090            }
091            finally
092            {
093                _sourceResolver.release(source);
094            }
095        }
096        
097        return directories;
098    }
099    
100    private Map<String, I18nizableText> _getDirectories(Source source) throws SourceException
101    {
102        Map<String, I18nizableText> directories = new HashMap<>();
103       
104        if (source instanceof TraversableSource)
105        {            
106            TraversableSource tSource = (TraversableSource) source;
107            
108            if (tSource.isCollection())
109            {
110                String path = StringUtils.substringAfter(source.getURI(), source.getScheme() + ":/");
111                directories.put(source.getURI(), new I18nizableText(path));
112                
113                Collection<Source> childrenSources = tSource.getChildren(); 
114                for (Source childSource : childrenSources)
115                {
116                    directories.putAll(_getDirectories(childSource));
117                }                
118            }
119        }
120        
121        return directories;
122    }
123    
124    // TODO NEWATTRIBUTEAPI: remove this method when org.ametys.runtime.parameter.Enumerator will be removed
125    public Map<Object, I18nizableText> getEntries() throws Exception
126    {
127        Map<Object, I18nizableText> result = new HashMap<>();
128        for (Map.Entry<String, I18nizableText> entry : getTypedEntries().entrySet())
129        {
130            result.put(entry.getKey(), entry.getValue());
131        }
132        return Collections.unmodifiableMap(result);
133    }
134
135    @Override
136    // TODO NEWATTRIBUTEAPI: remove this method when org.ametys.runtime.parameter.Enumerator will be removed
137    public Map<String, Object> getConfiguration()
138    {
139        return Collections.EMPTY_MAP;
140    }
141}