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