001/*
002 *  Copyright 2012 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.cms.source;
017
018import java.io.IOException;
019import java.util.ArrayList;
020import java.util.List;
021
022import org.apache.avalon.framework.logger.AbstractLogEnabled;
023import org.apache.avalon.framework.service.ServiceException;
024import org.apache.avalon.framework.service.ServiceManager;
025import org.apache.avalon.framework.service.Serviceable;
026import org.apache.excalibur.source.Source;
027import org.apache.excalibur.source.SourceResolver;
028
029/**
030 * Default implementation of {@link ViewSelector}.
031 * First looks the wanted file in context://WEB-INF/param/view/path_to_file
032 * If it's not present, it will look in the cms plugin.
033 */
034public class DefaultViewSelector extends AbstractLogEnabled implements ViewSelector, Serviceable
035{
036    /** The source resolver */
037    protected SourceResolver _resolver;
038    
039    @Override
040    public void service(ServiceManager manager) throws ServiceException
041    {
042        _resolver = (SourceResolver) manager.lookup(SourceResolver.ROLE);
043    }
044    
045    @Override
046    public Source getSource(String pluginName, String fileLocation) throws IOException
047    {
048        for (String uri : getLocations(pluginName, fileLocation))
049        {
050            try
051            {
052                Source source = _resolver.resolveURI(uri);
053                if (!source.exists())
054                {
055                    if (getLogger().isDebugEnabled())
056                    {
057                        getLogger().debug("Failed to find a stylesheet at '" + source.getURI() + "'.");
058                    }
059                }
060                else
061                {
062                    if (getLogger().isDebugEnabled())
063                    {
064                        getLogger().debug("Using source located at '" + source.getURI() + "'.");
065                    }
066                    return source;
067                }
068            }
069            catch (IOException e)
070            {
071                if (getLogger().isDebugEnabled())
072                {
073                    getLogger().debug("Resolving protocol failed for resolving '" + fileLocation + "'.");
074                }
075            }
076        }
077        
078        // Should never occur because of the default stylesheet.
079        throw new IOException("Can't find a stylesheet for: " + fileLocation);
080    }
081    
082    /**
083     * Returns the ordered list of URI to be tested to find the corresponding view.
084     * @param pluginName The current plugin name
085     * @param filePath the requested location.
086     * @return a list of possible URIs for the resource.
087     */
088    protected List<String> getLocations(String pluginName, String filePath)
089    {
090        ArrayList<String> locations = new ArrayList<>();
091        
092        // First look in the WEB-INF folder.
093        locations.add("context://WEB-INF/param/view/" + filePath);
094        
095        // Then look in the current plugin.
096        locations.add("plugin:" + pluginName + "://" + filePath);
097        
098        // For legacy, then look in CMS plugin
099        locations.add("plugin:cms://" + filePath);
100        
101        return locations;
102    }
103}