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