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.core.util.DateUtils; 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", DateUtils.dateToString(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}