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