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