001/*
002 *  Copyright 2014 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.file;
017
018import java.util.ArrayList;
019import java.util.Collection;
020import java.util.Date;
021import java.util.HashMap;
022import java.util.List;
023import java.util.Map;
024
025import org.apache.avalon.framework.context.Context;
026import org.apache.avalon.framework.context.ContextException;
027import org.apache.avalon.framework.context.Contextualizable;
028import org.apache.avalon.framework.parameters.Parameters;
029import org.apache.avalon.framework.service.ServiceException;
030import org.apache.avalon.framework.service.ServiceManager;
031import org.apache.cocoon.acting.ServiceableAction;
032import org.apache.cocoon.environment.ObjectModelHelper;
033import org.apache.cocoon.environment.Redirector;
034import org.apache.cocoon.environment.Request;
035import org.apache.cocoon.environment.SourceResolver;
036import org.apache.commons.lang3.StringUtils;
037import org.apache.excalibur.source.TraversableSource;
038
039import org.ametys.core.cocoon.JSonReader;
040import org.ametys.runtime.parameter.ParameterHelper;
041
042/**
043 * Abstract action for getting child files/folders of a local application folder
044 *
045 */
046public abstract class AbstractGetFilesAction extends ServiceableAction implements Contextualizable
047{
048    /** The cocoon context */
049    protected org.apache.cocoon.environment.Context _cocoonContext;
050    /** The source resolver */
051    private org.apache.excalibur.source.SourceResolver _srcResolver;
052    
053    @Override
054    public void service(ServiceManager smanager) throws ServiceException
055    {
056        _srcResolver = (org.apache.excalibur.source.SourceResolver) smanager.lookup(org.apache.excalibur.source.SourceResolver.ROLE);
057    }
058    
059    @Override
060    public void contextualize(Context context) throws ContextException
061    {
062        _cocoonContext = (org.apache.cocoon.environment.Context) context.get(org.apache.cocoon.Constants.CONTEXT_ENVIRONMENT_CONTEXT);
063    }
064    
065    public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception
066    {
067        Request request = ObjectModelHelper.getRequest(objectModel);
068        
069        String path = StringUtils.defaultString(request.getParameter("path"), "");
070        
071        String rootURI = getRootURI(request);
072        TraversableSource rootDir = (TraversableSource) _srcResolver.resolveURI(rootURI);
073        TraversableSource currentDir = (TraversableSource) _srcResolver.resolveURI(rootURI + (path.length() > 0 ? "/" + path : ""));
074        
075        List<Map<String, Object>> nodes = new ArrayList<>();
076        
077        if (currentDir.exists())
078        {
079            for (TraversableSource child : (Collection<TraversableSource>) currentDir.getChildren())
080            {
081                if (!isIgnoredSource(child.getName()))
082                {
083                    if (child.isCollection())
084                    {
085                        nodes.add(_collection2JsonObject(child, rootDir));
086                    }
087                    else
088                    {
089                        nodes.add(_resource2JsonObject(child, rootDir));
090                    }
091                }
092            }
093        }
094        
095        Map<String, Object> result = new HashMap<>();
096        result.put("nodes", nodes);
097        
098        request.setAttribute(JSonReader.OBJECT_TO_READ, result);
099        return EMPTY_MAP;
100    }
101    
102    /**
103     * Get the URI of root directory such as 'context://WEB-INF/param'
104     * @param request the request
105     * @return The root URI
106     */
107    protected abstract String getRootURI (Request request);
108    
109    /**
110     * Test if the source has to be ignored
111     * @param fileName The file name
112     * @return true if the source has to be ignored
113     */
114    protected boolean isIgnoredSource (String fileName)
115    {
116        return false;
117    }
118    
119    /**
120     * Convert collection to JSON object
121     * @param folder the folder
122     * @param root the root directory
123     * @return JSON object
124     */
125    protected Map<String, Object> _collection2JsonObject (TraversableSource folder, TraversableSource root)
126    {
127        Map<String, Object> jsonObject = new HashMap<>();
128        jsonObject.put("type", "collection");
129        jsonObject.put("name", folder.getName());
130        jsonObject.put("path", _getRelativePath(root, folder));
131        return jsonObject;
132    }
133    
134    /**
135     * Convert file to JSON object
136     * @param file the file
137     * @param root the root directory
138     * @return JSON object
139     */
140    protected Map<String, Object> _resource2JsonObject (TraversableSource file, TraversableSource root)
141    {
142        Map<String, Object> jsonObject = new HashMap<>();
143        
144        jsonObject.put("type", "resource");
145        jsonObject.put("name", file.getName());
146        jsonObject.put("path", _getRelativePath(root, file));
147        
148        jsonObject.put("size", file.getContentLength());
149        jsonObject.put("lastModified", ParameterHelper.valueToString(new Date(file.getLastModified())));
150        
151        String mimeType = _cocoonContext.getMimeType(file.getName().toLowerCase());
152        jsonObject.put("mimetype", mimeType != null ? mimeType : "application/unknown");
153        
154        return jsonObject;
155    }
156    
157    /**
158     * Get the relative path from root directory
159     * @param root The root directory
160     * @param file The file
161     * @return The relative path
162     */
163    protected String _getRelativePath (TraversableSource root, TraversableSource file)
164    {
165        String relPath = file.getURI().substring(root.getURI().length());
166        
167        if (relPath.endsWith("/"))
168        {
169            relPath = relPath.substring(0, relPath.length() - 1);
170        }
171        
172        return relPath;
173    }
174
175}