001/* 002 * Copyright 2015 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.serverdirectory; 017 018import java.io.IOException; 019import java.net.URISyntaxException; 020import java.util.Base64; 021import java.util.Collection; 022import java.util.Set; 023 024import org.apache.avalon.framework.service.ServiceException; 025import org.apache.avalon.framework.service.ServiceManager; 026import org.apache.cocoon.ProcessingException; 027import org.apache.cocoon.environment.ObjectModelHelper; 028import org.apache.cocoon.environment.Request; 029import org.apache.cocoon.generation.ServiceableGenerator; 030import org.apache.cocoon.xml.AttributesImpl; 031import org.apache.cocoon.xml.XMLUtils; 032import org.apache.excalibur.source.Source; 033import org.apache.excalibur.source.SourceException; 034import org.apache.excalibur.source.SourceResolver; 035import org.apache.excalibur.source.TraversableSource; 036import org.xml.sax.SAXException; 037 038import org.ametys.core.user.CurrentUserProvider; 039import org.ametys.core.util.URLEncoder; 040import org.ametys.plugins.repository.AmetysRepositoryException; 041import org.ametys.runtime.authentication.AccessDeniedException; 042import org.ametys.runtime.authentication.AuthorizationRequiredException; 043import org.ametys.runtime.parameter.ParameterHelper; 044import org.ametys.web.repository.page.ZoneItem; 045 046/** 047 * Generate all subDirectory from a directory 048 */ 049public class ServerDirectoryGenerator extends ServiceableGenerator 050{ 051 /** Excalibur's source resolver */ 052 protected SourceResolver _sourceResolver; 053 054 /** The current user provider */ 055 protected CurrentUserProvider _currentUserProvider; 056 057 @Override 058 public void service(ServiceManager smanager) throws ServiceException 059 { 060 _sourceResolver = (SourceResolver) smanager.lookup(SourceResolver.ROLE); 061 _currentUserProvider = (CurrentUserProvider) smanager.lookup(CurrentUserProvider.ROLE); 062 } 063 064 public void generate() throws IOException, SAXException, ProcessingException 065 { 066 Request request = ObjectModelHelper.getRequest(objectModel); 067 068 ZoneItem zoneItem = (ZoneItem) request.getAttribute(ZoneItem.class.getName()); 069 070 String folder = ServerDirectoryHelper.normalize(zoneItem.getServiceParameters().getString("folder", "")); 071 072 try 073 { 074 contentHandler.startDocument(); 075 076 if (zoneItem.getServiceParameters().getBoolean("enableDynamicPaths", false)) 077 { 078 folder = ServerDirectoryHelper.evaluateDynamicPath(folder, (String) request.getAttribute("site"), (String) request.getAttribute("sitemapLanguage"), _currentUserProvider.getUser()); 079 } 080 081 Set<Source> rootSources = ServerDirectoryHelper.getRootServerSources(_sourceResolver); 082 083 if (!ServerDirectoryHelper.isValidPath(folder, rootSources)) 084 { 085 throw new IllegalStateException("The server directory '" + folder + "' is not an authorized directory"); 086 } 087 088 Source sourceFolder = null; 089 try 090 { 091 sourceFolder = _sourceResolver.resolveURI(folder); 092 093 if (!sourceFolder.exists()) 094 { 095 throw new IllegalArgumentException("The server directory '" + folder + "' does not exist"); 096 } 097 098 String zoneItemEncoded = new String(Base64.getUrlEncoder().encode(zoneItem.getId().getBytes("UTF-8"))); 099 saxCollection(sourceFolder, zoneItemEncoded); 100 } 101 catch (SourceException | AmetysRepositoryException | URISyntaxException e) 102 { 103 throw new IllegalArgumentException("Cannot enumerate subdirectories for server location: <" + folder + ">", e); 104 } 105 finally 106 { 107 _sourceResolver.release(sourceFolder); 108 } 109 110 contentHandler.endDocument(); 111 } 112 catch (AccessDeniedException | AuthorizationRequiredException e) 113 { 114 throw new ProcessingException("No user is connected or the user has no required permissions to access to the server directory " + folder); 115 } 116 } 117 118 /** 119 * SAX a {@link Source} 120 * @param sourceFolder The source to sax 121 * @param zoneItemId The zone item id 122 * @throws SAXException If an error occurred while saxing 123 * @throws SourceException If an error occurred while we get child from the source 124 * @throws URISyntaxException if an error occurred 125 */ 126 protected void saxCollection (Source sourceFolder, String zoneItemId) throws SAXException, SourceException, URISyntaxException 127 { 128 if (sourceFolder instanceof TraversableSource) 129 { 130 TraversableSource tSource = (TraversableSource) sourceFolder; 131 132 AttributesImpl childAtts = new AttributesImpl(); 133 childAtts.addCDATAAttribute("id", tSource.getURI()); 134 childAtts.addCDATAAttribute("name", tSource.getName()); 135 childAtts.addCDATAAttribute("encodedName", URLEncoder.encodePath(tSource.getName())); 136 childAtts.addCDATAAttribute("mimetype", tSource.getMimeType()); 137 childAtts.addCDATAAttribute("lastModified", ParameterHelper.valueToString(tSource.getLastModified())); 138 childAtts.addCDATAAttribute("size", String.valueOf(tSource.getContentLength())); 139 childAtts.addCDATAAttribute("path", URLEncoder.encodePath(tSource.getURI())); 140 141 if (tSource.isCollection()) 142 { 143 childAtts.addCDATAAttribute("type", "collection"); 144 XMLUtils.startElement(contentHandler, "Node", childAtts); 145 146 Collection<Source> childrenSources = tSource.getChildren(); 147 for (Source childSource : childrenSources) 148 { 149 saxCollection(childSource, zoneItemId); 150 } 151 XMLUtils.endElement(contentHandler, "Node"); 152 } 153 else 154 { 155 childAtts.addCDATAAttribute("type", "resource"); 156 childAtts.addCDATAAttribute("zoneItem", zoneItemId); 157 XMLUtils.createElement(contentHandler, "Node", childAtts); 158 } 159 160 } 161 } 162}