001/* 002 * Copyright 2017 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.extraction.execution; 017 018import java.io.File; 019import java.io.IOException; 020import java.time.ZonedDateTime; 021import java.util.HashMap; 022import java.util.List; 023import java.util.Locale; 024import java.util.Map; 025 026import org.apache.avalon.framework.service.ServiceException; 027import org.apache.avalon.framework.service.ServiceManager; 028import org.apache.cocoon.ProcessingException; 029import org.apache.cocoon.environment.ObjectModelHelper; 030import org.apache.cocoon.environment.Request; 031import org.apache.cocoon.generation.ServiceableGenerator; 032import org.apache.cocoon.xml.AttributesImpl; 033import org.apache.cocoon.xml.XMLUtils; 034import org.apache.commons.lang3.StringUtils; 035import org.apache.excalibur.source.Source; 036import org.apache.excalibur.source.SourceResolver; 037import org.apache.excalibur.source.impl.FileSource; 038import org.xml.sax.SAXException; 039 040import org.ametys.cms.contenttype.ContentTypeExtensionPoint; 041import org.ametys.cms.contenttype.ContentTypesHelper; 042import org.ametys.cms.repository.Content; 043import org.ametys.core.right.RightManager; 044import org.ametys.core.right.RightManager.RightResult; 045import org.ametys.core.user.CurrentUserProvider; 046import org.ametys.plugins.extraction.ExtractionConstants; 047import org.ametys.plugins.extraction.component.ExtractionComponent; 048import org.ametys.plugins.repository.AmetysObjectResolver; 049import org.ametys.runtime.parameter.ParameterHelper; 050 051/** 052 * Extracts query results form a XML definition file 053 */ 054public class ExtractionGenerator extends ServiceableGenerator 055{ 056 /** The request parameter name for definition file path */ 057 static final String FILE_PARAM = "file"; 058 059 private RightManager _rightManager; 060 private ExtractionDefinitionReader _reader; 061 private CurrentUserProvider _currentUserProvider; 062 private ContentTypeExtensionPoint _contentTypeExtensionPoint; 063 private AmetysObjectResolver _resolver; 064 private ContentTypesHelper _contentTypesHelper; 065 private SourceResolver _sourceResolver; 066 067 @Override 068 public void service(ServiceManager serviceManager) throws ServiceException 069 { 070 super.service(serviceManager); 071 _rightManager = (RightManager) manager.lookup(RightManager.ROLE); 072 _reader = (ExtractionDefinitionReader) serviceManager.lookup(ExtractionDefinitionReader.ROLE); 073 _currentUserProvider = (CurrentUserProvider) serviceManager.lookup(CurrentUserProvider.ROLE); 074 _contentTypeExtensionPoint = (ContentTypeExtensionPoint) serviceManager.lookup(ContentTypeExtensionPoint.ROLE); 075 _resolver = (AmetysObjectResolver) serviceManager.lookup(AmetysObjectResolver.ROLE); 076 _contentTypesHelper = (ContentTypesHelper) serviceManager.lookup(ContentTypesHelper.ROLE); 077 _sourceResolver = (SourceResolver) serviceManager.lookup(SourceResolver.ROLE); 078 } 079 080 public void generate() throws IOException, SAXException, ProcessingException 081 { 082 try 083 { 084 if (_rightManager.hasRight(_currentUserProvider.getUser(), "Extraction_Rights_ExecuteExtraction", "/${WorkspaceName}") != RightResult.RIGHT_ALLOW) 085 { 086 String errorMessage = "User " + _currentUserProvider.getUser() + " try to execute extraction with no sufficient rights"; 087 getLogger().error(errorMessage); 088 throw new IllegalStateException(errorMessage); 089 } 090 091 Request request = ObjectModelHelper.getRequest(objectModel); 092 String fileName = request.getParameter(FILE_PARAM); 093 String filePath = ExtractionConstants.DEFINITIONS_DIR + fileName; 094 String lang = request.getParameter("lang"); 095 096 Source src = _sourceResolver.resolveURI(filePath); 097 File file = ((FileSource) src).getFile(); 098 099 if (!file.exists()) 100 { 101 throw new IllegalArgumentException("The file " + filePath + " does not exist."); 102 } 103 104 Extraction extraction = _reader.readExtractionDefinitionFile(file); 105 106 contentHandler.startDocument(); 107 108 AttributesImpl attributes = new AttributesImpl(); 109 attributes.addCDATAAttribute("user", _currentUserProvider.getUser().getLogin()); 110 attributes.addCDATAAttribute("date", ZonedDateTime.now().format(ParameterHelper.getISODateTimeFormatter())); 111 attributes.addCDATAAttribute("name", file.getName()); 112 XMLUtils.startElement(contentHandler, "extraction", attributes); 113 114 ExtractionExecutionContext context = new ExtractionExecutionContext(); 115 if (StringUtils.isNotEmpty(lang)) 116 { 117 context.setDefaultLocale(new Locale(lang)); 118 } 119 context.setDisplayOptionalColumns(_getDisplayOptionalColumns(extraction.getDisplayOptionalColumnsNames(), request)); 120 context.setClauseVariables(_getQueryVariables(extraction.getQueryVariablesNamesAndContentTypes(), request)); 121 122 for (ExtractionComponent component : extraction.getExtractionComponents()) 123 { 124 component.prepareComponentExecution(context); 125 component.execute(contentHandler, context); 126 } 127 128 XMLUtils.endElement(contentHandler, "extraction"); 129 contentHandler.endDocument(); 130 } 131 catch (Exception e) 132 { 133 throw new ProcessingException(e); 134 } 135 } 136 137 Map<String, Boolean> _getDisplayOptionalColumns(List<String> displayOptionalColumnsNames, Request request) 138 { 139 Map<String, Boolean> result = new HashMap<>(); 140 for (String name : displayOptionalColumnsNames) 141 { 142 String valueAsString = request.getParameter(name); 143 if (null == valueAsString) 144 { 145 throw new IllegalArgumentException("Extraction - There is a variable named '" + name + "' but there is no corresponding value"); 146 } 147 result.put(name, Boolean.valueOf(valueAsString)); 148 } 149 return result; 150 } 151 152 private Map<String, String> _getQueryVariables(Map<String, String> queryVariablesNamesAndContentTypes, Request request) 153 { 154 Map<String, String> result = new HashMap<>(); 155 for (Map.Entry<String, String> entry : queryVariablesNamesAndContentTypes.entrySet()) 156 { 157 String name = entry.getKey(); 158 String contentTypeId = entry.getValue(); 159 if (!_contentTypeExtensionPoint.hasExtension(contentTypeId)) 160 { 161 throw new IllegalArgumentException("Extraction - content type '" + contentTypeId + "' used in variable '" + name + "' definition does not exist"); 162 } 163 164 String contentId = request.getParameter(name); 165 if (null == contentId) 166 { 167 throw new IllegalArgumentException("Extraction - There is a variable named '" + name + "' but there is no corresponding value"); 168 } 169 170 Content content = _resolver.resolveById(contentId); 171 if (!_contentTypesHelper.isInstanceOf(content, contentTypeId)) 172 { 173 throw new IllegalArgumentException("Extraction - content '" + contentId + "' is not an instance of content type '" + contentTypeId + "', defined by the variable named '" + name + "'"); 174 } 175 176 result.put(name, contentId); 177 } 178 return result; 179 } 180 181}