001/* 002 * Copyright 2010 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.web.workflow; 017 018import java.util.ArrayList; 019import java.util.Collection; 020import java.util.Iterator; 021import java.util.List; 022import java.util.Map; 023import java.util.Set; 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.service.ServiceException; 029import org.apache.avalon.framework.service.ServiceManager; 030import org.apache.cocoon.components.ContextHelper; 031import org.apache.cocoon.environment.Request; 032import org.apache.cocoon.xml.AttributesImpl; 033import org.apache.cocoon.xml.XMLUtils; 034import org.apache.commons.lang3.StringUtils; 035import org.xml.sax.ContentHandler; 036import org.xml.sax.SAXException; 037 038import org.ametys.cms.repository.Content; 039import org.ametys.cms.repository.ContentTypeExpression; 040import org.ametys.cms.repository.LanguageExpression; 041import org.ametys.core.user.User; 042import org.ametys.plugins.repository.AmetysRepositoryException; 043import org.ametys.plugins.repository.query.expression.Expression; 044import org.ametys.plugins.repository.query.expression.Expression.Operator; 045import org.ametys.plugins.repository.query.expression.ExpressionContext; 046import org.ametys.plugins.repository.query.expression.OrExpression; 047import org.ametys.plugins.repository.query.expression.StringExpression; 048import org.ametys.web.repository.content.WebContent; 049import org.ametys.web.repository.page.ContentTypesAssignmentHandler; 050import org.ametys.web.repository.page.Page; 051import org.ametys.web.repository.site.Site; 052import org.ametys.web.repository.site.SiteManager; 053 054/** 055 * Component for saxing tasks specific to an user.<br> 056 * The algorithm is the following : 057 * <ul> 058 * <li>First, we get all granted sites for the user with the right manager. 059 * <li>If there is at least one site allowed, we get all workflows 060 * associated with the granted sites. 061 * <li>Then for each step of each task from the configuration, we get 062 * all workflows where this step is in current steps and where 063 * the workflow is contains in the previous list. 064 * <li>For each workflow matching the previous conditions we 065 * test if the user has all the rights associated with the step (from 066 * the configuration) and then we get the content from this workflow. 067 * <li>Finally, for each content, we sax its first page in order to access 068 * it directly from an URL. 069 * </ul> 070 */ 071public class WorkflowTasksComponent extends org.ametys.cms.workflow.WorkflowTasksComponent implements Contextualizable 072{ 073 074 /** The avalon role. */ 075 @SuppressWarnings("hiding") 076 public static final String ROLE = WorkflowTasksComponent.class.getName(); 077 078 /** The site manager. */ 079 protected SiteManager _siteManager; 080 081 /** The avalon context. */ 082 protected Context _context; 083 084 /** The content types assignment handler */ 085 protected ContentTypesAssignmentHandler _cTypeHandler; 086 087 @Override 088 public void service(ServiceManager serviceManager) throws ServiceException 089 { 090 super.service(serviceManager); 091 _siteManager = (SiteManager) serviceManager.lookup(SiteManager.ROLE); 092 _cTypeHandler = (ContentTypesAssignmentHandler) serviceManager.lookup(ContentTypesAssignmentHandler.ROLE); 093 } 094 095 @Override 096 public void contextualize(Context context) throws ContextException 097 { 098 _context = context; 099 } 100 101 @Override 102 public void toSAX(ContentHandler ch, User user) throws SAXException 103 { 104 XMLUtils.startElement(ch, "tasks"); 105 106 long start = System.currentTimeMillis(); 107 108 Set<String> grantedSites = _siteManager.getGrantedSites(user.getIdentity()); 109 long gsEnd = System.currentTimeMillis(); 110 long wfEnd = 0; 111 112 Request request = ContextHelper.getRequest(_context); 113 for (String siteName : grantedSites) 114 { 115 Site site = _siteManager.getSite(siteName); 116 117 request.setAttribute("siteName", siteName); 118 119 AttributesImpl siteAttr = new AttributesImpl(); 120 siteAttr.addCDATAAttribute("name", siteName); 121 siteAttr.addCDATAAttribute("title", site.getTitle()); 122 siteAttr.addCDATAAttribute("siteContext", "/" + siteName); 123 124 XMLUtils.startElement(ch, "site", siteAttr); 125 126 long wfStart = System.currentTimeMillis(); 127 // Get the workflow corresponding to the configuration. 128 Map<Task, Collection<Content>> workflows = _getCorrespondingWorkflows(user); 129 wfEnd = System.currentTimeMillis(); 130 131 getLogger().info("Contents retrieved in " + (wfEnd - wfStart) + "ms for site '" + siteName + "'"); 132 133 for (Task task : workflows.keySet()) 134 { 135 _saxTask(ch, task, workflows.get(task)); 136 } 137 138 XMLUtils.endElement(ch, "site"); 139 } 140 141 long end = System.currentTimeMillis(); 142 143 // Display performance indicators. 144 AttributesImpl attrs = new AttributesImpl(); 145 146 attrs.addCDATAAttribute("Total", Long.toString(end - start)); 147 attrs.addCDATAAttribute("GS", Long.toString(gsEnd - start)); 148 attrs.addCDATAAttribute("WF", Long.toString(wfEnd - gsEnd)); 149 attrs.addCDATAAttribute("SAX", Long.toString(end - wfEnd)); 150 151 XMLUtils.createElement(ch, "render", attrs); 152 153 XMLUtils.endElement(ch, "tasks"); 154 } 155 156 @Override 157 public void toSAX(ContentHandler ch, User user, String taskId) throws SAXException 158 { 159 XMLUtils.startElement(ch, "tasks"); 160 161 long start = System.currentTimeMillis(); 162 163 Set<String> grantedSites = _siteManager.getGrantedSites(user.getIdentity()); 164 long gsEnd = System.currentTimeMillis(); 165 long wfEnd = 0; 166 167 Request request = ContextHelper.getRequest(_context); 168 for (String siteName : grantedSites) 169 { 170 Site site = _siteManager.getSite(siteName); 171 172 request.setAttribute("siteName", siteName); 173 174 AttributesImpl siteAttr = new AttributesImpl(); 175 siteAttr.addCDATAAttribute("name", siteName); 176 siteAttr.addCDATAAttribute("title", site.getTitle()); 177 siteAttr.addCDATAAttribute("siteContext", "/" + siteName); 178 179 XMLUtils.startElement(ch, "site", siteAttr); 180 181 long wfStart = System.currentTimeMillis(); 182 183 Task task = _tasks.get(taskId); 184 Collection<Content> contents = _getTaskContents(user, task); 185 186 wfEnd = System.currentTimeMillis(); 187 getLogger().info("Contents retrieved in " + (wfEnd - wfStart) + "ms for site '" + siteName + "'"); 188 189 _saxTask(ch, task, contents); 190 191 XMLUtils.endElement(ch, "site"); 192 } 193 194 long end = System.currentTimeMillis(); 195 196 // Display performance indicators. 197 AttributesImpl attrs = new AttributesImpl(); 198 199 attrs.addCDATAAttribute("Total", Long.toString(end - start)); 200 attrs.addCDATAAttribute("GS", Long.toString(gsEnd - start)); 201 attrs.addCDATAAttribute("WF", Long.toString(wfEnd - gsEnd)); 202 attrs.addCDATAAttribute("SAX", Long.toString(end - wfEnd)); 203 204 XMLUtils.createElement(ch, "render", attrs); 205 206 XMLUtils.endElement(ch, "tasks"); 207 } 208 209 /** 210 * SAX the contents for given user, site and task 211 * @param ch the content handler to SAX into 212 * @param user the user 213 * @param siteName the site name 214 * @param language the language. 215 * @param taskId the task id 216 * @throws SAXException if an error occurred while saxing 217 */ 218 public void toSAX(ContentHandler ch, User user, String siteName, String language, String taskId) throws SAXException 219 { 220 XMLUtils.startElement(ch, "tasks"); 221 222 long start = System.currentTimeMillis(); 223 long wfEnd = 0; 224 225 Request request = ContextHelper.getRequest(_context); 226 Site site = _siteManager.getSite(siteName); 227 228 request.setAttribute("siteName", siteName); 229 request.setAttribute("language", language); 230 231 AttributesImpl siteAttr = new AttributesImpl(); 232 siteAttr.addCDATAAttribute("name", siteName); 233 siteAttr.addCDATAAttribute("title", site.getTitle()); 234 siteAttr.addCDATAAttribute("siteContext", "/" + siteName); 235 if (language != null) 236 { 237 siteAttr.addCDATAAttribute("language", language); 238 } 239 240 XMLUtils.startElement(ch, "site", siteAttr); 241 242 long wfStart = System.currentTimeMillis(); 243 244 if (taskId != null) 245 { 246 Task task = _tasks.get(taskId); 247 Collection<Content> contents = _getTaskContents(user, task); 248 249 wfEnd = System.currentTimeMillis(); 250 251 if (getLogger().isInfoEnabled()) 252 { 253 getLogger().info("Contents retrieved in " + (wfEnd - wfStart) + "ms for site '" + siteName + "'"); 254 } 255 256 _saxTask(ch, task, contents); 257 } 258 else 259 { 260 Map<Task, Collection<Content>> workflows = _getCorrespondingWorkflows(user); 261 wfEnd = System.currentTimeMillis(); 262 263 if (getLogger().isInfoEnabled()) 264 { 265 getLogger().info("Contents retrieved in " + (wfEnd - wfStart) + "ms for site '" + siteName + "'"); 266 } 267 268 for (Task task : workflows.keySet()) 269 { 270 _saxTask(ch, task, workflows.get(task)); 271 } 272 } 273 274 XMLUtils.endElement(ch, "site"); 275 276 long end = System.currentTimeMillis(); 277 278 // Display performance indicators. 279 AttributesImpl attrs = new AttributesImpl(); 280 281 attrs.addCDATAAttribute("Total", Long.toString(end - start)); 282 attrs.addCDATAAttribute("WF", Long.toString(wfEnd - start)); 283 attrs.addCDATAAttribute("SAX", Long.toString(end - wfEnd)); 284 285 XMLUtils.createElement(ch, "render", attrs); 286 287 XMLUtils.endElement(ch, "tasks"); 288 } 289 290 /** 291 * Get the list of contents for a given user, task and site. 292 * @param user the user. 293 * @param taskId the task ID. 294 * @param siteName the site name. 295 * @param language the language. 296 * @param limit the maximum number of results, 0 for all. 297 * @return the contents as an iterable collection of contents. 298 * @throws AmetysRepositoryException if an error occurred 299 */ 300 public Collection<Content> getContents(User user, String taskId, String siteName, String language, int limit) throws AmetysRepositoryException 301 { 302 Request request = ContextHelper.getRequest(_context); 303 request.setAttribute("siteName", siteName); 304 request.setAttribute("language", siteName); 305 306 return super.getContents(user, taskId, limit); 307 } 308 309 @Override 310 protected List<Expression> _getContentsAndExpressions(TaskStep step, User user) 311 { 312 List<Expression> exprs = super._getContentsAndExpressions(step, user); 313 314 Request request = ContextHelper.getRequest(_context); 315 String siteName = (String) request.getAttribute("siteName"); 316 if (StringUtils.isNotEmpty(siteName)) 317 { 318 exprs.add(new StringExpression("site", Operator.EQ, siteName, ExpressionContext.newInstance().withInternal(true))); 319 } 320 321 Expression cTypeExpr = _getContentTypeExpression (siteName); 322 if (cTypeExpr != null) 323 { 324 exprs.add(cTypeExpr); 325 } 326 327 String language = (String) request.getAttribute("language"); 328 if (StringUtils.isNotEmpty(language)) 329 { 330 exprs.add(new LanguageExpression(Operator.EQ, language)); 331 } 332 333 return exprs; 334 } 335 336 /** 337 * The content type expression 338 * @param siteName the site name 339 * @return The content type expression 340 */ 341 protected Expression _getContentTypeExpression (String siteName) 342 { 343 Site site = _siteManager.getSite(siteName); 344 345 List<Expression> cTypeExprs = new ArrayList<>(); 346 347 Set<String> cTypeIds = _cTypeHandler.getAvailableContentTypes(site, false); 348 for (String cTypeId : cTypeIds) 349 { 350 cTypeExprs.add(new ContentTypeExpression(Operator.EQ, cTypeId)); 351 } 352 353 if (cTypeIds.size() == 0) 354 { 355 return null; 356 } 357 358 return new OrExpression(cTypeExprs.toArray(new Expression[cTypeExprs.size()])); 359 } 360 361 @Override 362 protected void _saxAdditionalAttributes(Content content, Task task, AttributesImpl attrs) throws SAXException 363 { 364 if (content instanceof WebContent) 365 { 366 WebContent webContent = (WebContent) content; 367 Iterator<Page> pages = webContent.getReferencingPages().iterator(); 368 if (pages.hasNext()) 369 { 370 Page page = pages.next(); 371 attrs.addCDATAAttribute("pageTitle", page.getTitle()); 372 attrs.addCDATAAttribute("pageUri", page.getSitemapName() + "/" + page.getPathInSitemap()); 373 attrs.addCDATAAttribute("pageId", page.getId()); 374 } 375 } 376 } 377}