1 package nl.hippo.cms.workflow; 2 3 import com.opensymphony.module.propertyset.PropertySet; 4 import com.opensymphony.workflow.loader.ActionDescriptor; 5 import java.io.ByteArrayInputStream ; 6 import java.io.ByteArrayOutputStream ; 7 import java.io.IOException ; 8 import java.io.InputStream ; 9 import java.util.Collection ; 10 import java.util.HashMap ; 11 import java.util.Iterator ; 12 import java.util.List ; 13 import java.util.Map ; 14 import java.util.Set ; 15 import java.util.Vector ; 16 import javax.jdo.PersistenceManager; 17 import javax.jdo.Query; 18 import javax.jdo.Transaction; 19 import javax.xml.parsers.FactoryConfigurationError ; 20 import javax.xml.parsers.ParserConfigurationException ; 21 import javax.xml.parsers.SAXParser ; 22 import javax.xml.parsers.SAXParserFactory ; 23 import javax.xml.transform.Transformer ; 24 import javax.xml.transform.TransformerException ; 25 import javax.xml.transform.TransformerFactory ; 26 import javax.xml.transform.dom.DOMSource ; 27 import javax.xml.transform.stream.StreamResult ; 28 import nl.hippo.cms.workflows.shared.InitialDataRetriever; 29 import nl.hippo.cms.workflows.shared.InitialDataRetrieverWithContext; 30 import nl.hippo.componentcontainers.AvalonSpringBridge; 31 import nl.hippo.servermanager.Project; 32 import nl.hippo.servermanager.ProjectWorkflowRepository; 33 import nl.hippo.servermanager.ResourceLoadException; 34 import nl.hippo.servermanager.Server; 35 import nl.hippo.servermanager.ServerManager; 36 import nl.hippo.sites.taxonomy.Article; 37 import nl.hippo.sites.taxonomy.MainPlacement; 38 import nl.hippo.sites.taxonomy.Organisation; 39 import org.apache.avalon.framework.activity.Disposable; 40 import org.apache.avalon.framework.component.Component; 41 import org.apache.avalon.framework.parameters.ParameterException; 42 import org.apache.avalon.framework.service.ServiceException; 43 import org.apache.avalon.framework.service.ServiceManager; 44 import org.apache.avalon.framework.service.Serviceable; 45 import org.apache.avalon.framework.service.WrapperServiceSelector; 46 import org.apache.cocoon.ProcessingException; 47 import org.apache.cocoon.environment.Request; 48 import org.apache.cocoon.generation.AbstractGenerator; 49 import org.apache.commons.httpclient.HttpState; 50 import org.apache.webdav.lib.Property; 51 import org.apache.webdav.lib.PropertyName; 52 import org.w3c.dom.Document ; 53 import org.w3c.dom.Element ; 54 import org.xml.sax.Attributes ; 55 import org.xml.sax.InputSource ; 56 import org.xml.sax.SAXException ; 57 import org.xml.sax.helpers.AttributesImpl ; 58 59 public class AvailableActionsForPlacementsGenerator extends AbstractGenerator 60 implements 61 Serviceable, 62 Disposable 63 { 64 65 private static final Vector PROPERTIES_NEEDED_BY_WORKFLOW = new Vector (); 66 67 private static final PropertyName WORKFLOW_ID_PROPERTY_NAME = new PropertyName( 68 "http://hippo.nl/cms/1.0", "workflowId"); 69 70 private static final PropertyName CUPS_PROPERTY_NAME = new PropertyName("DAV:", 71 "current-user-privilege-set"); 72 73 static 74 { 75 PROPERTIES_NEEDED_BY_WORKFLOW.add(WORKFLOW_ID_PROPERTY_NAME); 76 PROPERTIES_NEEDED_BY_WORKFLOW.add(CUPS_PROPERTY_NAME); 77 } 78 79 private ServiceManager m_manager; 80 81 private AvalonSpringBridge m_avalonSpringBridge; 82 83 public AvailableActionsForPlacementsGenerator() 84 { 85 super(); 86 } 87 88 public void service(ServiceManager manager) throws ServiceException 89 { 90 m_manager = manager; 91 m_avalonSpringBridge = (AvalonSpringBridge) manager.lookup(AvalonSpringBridge.ROLE); 92 } 93 94 private static final Attributes EMPTY_ATTRIBUTE_LIST = new AttributesImpl (); 95 96 public void generate() throws IOException , SAXException , ProcessingException 97 { 98 Project project = null; 99 PersistenceManager persistenceManager = null; 100 try 101 { 102 String repositoryRoot = parameters.getParameter("repositoryRoot"); 103 String location = repositoryRoot + "/" + source; 104 105 Request request = (Request) objectModel.get("request"); 106 HttpState httpState = (HttpState) request.getSession().getAttribute("httpstate"); 107 108 ServerManager serverManager = (ServerManager) m_avalonSpringBridge 109 .getBean("serverManager"); 110 Server server = serverManager.getServer(); 111 project = server.getProjectByDomain(request.getServerName()); 112 113 HashMap propertiesCache = new HashMap (); 114 WorkflowHelper.movePropertiesToCache(location, 115 PROPERTIES_NEEDED_BY_WORKFLOW.elements(), propertiesCache, httpState); 116 117 Property workflowIdAsProperty = (Property) propertiesCache 118 .get(WORKFLOW_ID_PROPERTY_NAME); 119 String workflowIdAsString; 120 if (workflowIdAsProperty == null) 121 { 122 workflowIdAsString = null; 123 } 124 else 125 { 126 workflowIdAsString = workflowIdAsProperty.getPropertyAsString(); 127 } 128 129 contentHandler.startDocument(); 130 contentHandler.startElement(null, "placement-workflow-actions", 131 "placement-workflow-actions", EMPTY_ATTRIBUTE_LIST); 132 133 Map parameters = propertiesCache; 134 parameters.put("location", location); 135 parameters.put("httpstate", httpState); 136 parameters.put("propertiesCache", propertiesCache); 137 if (workflowIdAsString != null && !workflowIdAsString.equals("")) 138 { 139 ProjectWorkflowRepository workflow = null; 140 workflow = project.getWorkflowRepository(); 141 142 long workflowId = Long.parseLong(workflowIdAsString); 143 144 PropertySet articleWorkflowProperties = workflow.getPropertySet(workflowId); 145 146 String databaseName = project.getProperties().getProperty("taxonomy.databaseName"); 147 String organisationName = project.getProperties().getProperty( 148 "taxonomy.organisationName"); 149 150 persistenceManager = project.getDatabaseConnectionFactory().getPersistenceManager( 151 databaseName); 152 Transaction t = persistenceManager.currentTransaction(); 153 t.begin(); 154 155 Query q = persistenceManager.newQuery(Organisation.class, "m_name == name"); 156 q.declareParameters("String name"); 157 Map queryParameters = new HashMap (); 158 queryParameters.put("name", organisationName); 159 Object resultAsObject = q.executeWithMap(queryParameters); 160 if (resultAsObject instanceof Collection ) 161 { 162 Collection result = (Collection ) resultAsObject; 163 Iterator resultIterator = result.iterator(); 164 if (resultIterator.hasNext()) 165 { 166 Object organisationAsObject = resultIterator.next(); 167 if (organisationAsObject instanceof Organisation) 168 { 169 Organisation organisation = (Organisation) organisationAsObject; 170 Article article = organisation.findArticleByWorkflowId(workflowId); 171 if (article != null) 172 { 173 MainPlacement mainPlacement = article.getMainPlacement(); 174 if (mainPlacement != null) 175 { 176 contentHandler.startElement(null, "main-placement", 177 "main-placement", EMPTY_ATTRIBUTE_LIST); 178 179 contentHandler.startElement(null, "website", "website", EMPTY_ATTRIBUTE_LIST); 180 char[] websiteAsCharacterArray = mainPlacement.getWebsite() 181 .getName().toCharArray(); 182 contentHandler.characters(websiteAsCharacterArray, 0, 183 websiteAsCharacterArray.length); 184 contentHandler.endElement(null, "website", "website"); 185 186 contentHandler.startElement(null, "taxonomy-location", 187 "taxonomy-location", EMPTY_ATTRIBUTE_LIST); 188 char[] taxonomyLocationAsCharacterArray = mainPlacement 189 .getLocation().getPath().toString().toCharArray(); 190 contentHandler.characters(taxonomyLocationAsCharacterArray, 0, 191 taxonomyLocationAsCharacterArray.length); 192 contentHandler.endElement(null, "taxonomy-location", 193 "taxonomy-location"); 194 195 contentHandler.endElement(null, "main-placement", "main-placement"); 196 } 197 } 198 } 199 } 200 } 201 202 t.commit(); 203 204 Set secondaryPlacementWorkflowIds = (Set) articleWorkflowProperties 205 .getAsActualType("secondaryPlacementWorkflowsIds"); 206 if (secondaryPlacementWorkflowIds != null) 207 { 208 Iterator secondaryPlacementWorkflowIdsIterator = secondaryPlacementWorkflowIds 209 .iterator(); 210 while (secondaryPlacementWorkflowIdsIterator.hasNext()) 211 { 212 long secondaryPlacementWorkflowId = ((Long ) secondaryPlacementWorkflowIdsIterator 213 .next()).longValue(); 214 PropertySet secondaryPlacementProperties = workflow 215 .getPropertySet(secondaryPlacementWorkflowId); 216 contentHandler.startElement(null, "secondary-placement", 217 "secondary-placement", EMPTY_ATTRIBUTE_LIST); 218 219 outputSecondaryPlacementWorkflowId(secondaryPlacementWorkflowId); 220 outputSecondaryPlacementWebsite(secondaryPlacementProperties); 221 outputSecondaryPlacementTaxonomyLocation(secondaryPlacementProperties); 222 223 contentHandler.startElement(null, "workflow-actions", "workflow-actions", 224 EMPTY_ATTRIBUTE_LIST); 225 226 Map workflowParameters = new HashMap (); 227 workflowParameters.put("projectname", project.getName()); 228 ActionDescriptor[] actions = WorkflowHelper.getAvailableActions(workflow, 229 secondaryPlacementWorkflowId, workflowParameters); 230 231 WorkflowActionAuthorizer authorizer = WorkflowHelper.getActionsAuthorizer(workflow, secondaryPlacementWorkflowId); 232 WorkflowActionAuthorizerContext authorizerContext = new WorkflowActionAuthorizerContext(project, httpState); 233 List authorisedActions = authorizer.authorizeActions(secondaryPlacementWorkflowId, actions, authorizerContext); 234 235 for (Iterator authorisedActionsIterator = authorisedActions.iterator(); authorisedActionsIterator 236 .hasNext();) 237 { 238 ActionDescriptor actionDescriptor = (ActionDescriptor) authorisedActionsIterator.next(); 239 AttributesImpl workflowActionAttributes = new AttributesImpl (); 240 workflowActionAttributes.addAttribute(null, "name", "name", "CDATA", 241 actionDescriptor.getName()); 242 workflowActionAttributes.addAttribute(null, "workflow-id", 243 "workflow-id", "CDATA", String 244 .valueOf(actionDescriptor.getId())); 245 contentHandler.startElement(null, "workflow-action", "workflow-action", 246 workflowActionAttributes); 247 248 String label = (String ) actionDescriptor.getMetaAttributes().get( 249 "label"); 250 optionallyOutputTextElement("label", label); 251 252 outputStandardUIAction(actionDescriptor); 253 outputInputSchema(workflow, workflowId, actionDescriptor); 254 outputInputForm(workflow, workflowId, actionDescriptor); 255 256 contentHandler.startElement(null, "data", "data", EMPTY_ATTRIBUTE_LIST); 257 258 String initialDataRetrieverClass = (String ) actionDescriptor 259 .getMetaAttributes().get("initialDataRetrieverClass"); 260 if (initialDataRetrieverClass != null) 261 { 262 Object initialDataRetrieverAsObject = null; 263 try 264 { 265 initialDataRetrieverAsObject = workflow.loadComponent( 266 workflowId, initialDataRetrieverClass); 267 outputInitialData(initialDataRetrieverAsObject, location, 268 httpState, project); 269 } 270 finally 271 { 272 releaseWorkflowExtension(initialDataRetrieverAsObject); 273 } 274 } 275 276 contentHandler.endElement(null, "data", "data"); 277 278 contentHandler.endElement(null, "workflow-action", "workflow-action"); 279 } 280 281 contentHandler.endElement(null, "workflow-actions", "workflow-actions"); 282 283 contentHandler.endElement(null, "secondary-placement", 284 "secondary-placement"); 285 } 286 } 287 } 288 289 contentHandler.endElement(null, "placement-workflow-actions", 290 "placement-workflow-actions"); 291 contentHandler.endDocument(); 292 } 293 catch (ParameterException e) 294 { 295 throw new ProcessingException("Unable to retrieve repository root", e); 296 } 297 catch (ParserConfigurationException e) 298 { 299 throw new ProcessingException("Unable to create SAX parser", e); 300 } 301 catch (InstantiationException e) 302 { 303 throw new ProcessingException("Unable to lookup/instantiate workflow extension", e); 304 } 305 catch (IllegalAccessException e) 306 { 307 throw new ProcessingException("Unable to lookup/instantiate workflow extension", e); 308 } 309 catch (ClassNotFoundException e) 310 { 311 throw new ProcessingException("Unable to lookup/instantiate workflow extension", e); 312 } 313 catch (ServiceException e) 314 { 315 throw new ProcessingException("Unable to lookup needed component", e); 316 } 317 catch (Exception e) 318 { 319 throw new ProcessingException("Unknown error", e); 320 } 321 finally 322 { 323 if (persistenceManager != null) 324 { 325 project.getDatabaseConnectionFactory() 326 .releasePersistenceManager(persistenceManager); 327 } 328 } 329 } 330 331 private void outputInputForm(ProjectWorkflowRepository workflow, long workflowId, 332 ActionDescriptor actionDescriptor) throws FactoryConfigurationError , IOException , 333 ProcessingException, ParserConfigurationException , SAXException , ResourceLoadException 334 { 335 String inputForm = (String ) actionDescriptor.getMetaAttributes().get("inputForm"); 336 optionallyIncludeResource(workflow, workflowId, inputForm); 337 } 338 339 private void outputInputSchema(ProjectWorkflowRepository workflow, long workflowId, 340 ActionDescriptor actionDescriptor) throws FactoryConfigurationError , IOException , 341 ProcessingException, ParserConfigurationException , SAXException , ResourceLoadException 342 { 343 String inputSchema = (String ) actionDescriptor.getMetaAttributes().get("inputSchema"); 344 optionallyIncludeResource(workflow, workflowId, inputSchema); 345 } 346 347 private void outputStandardUIAction(ActionDescriptor actionDescriptor) throws SAXException 348 { 349 String standardUIAction = (String ) actionDescriptor.getMetaAttributes().get( 350 "standardUIAction"); 351 optionallyOutputTextElement("standard-ui-action", standardUIAction); 352 } 353 354 private void outputInitialData(Object initialDataRetrieverAsObject, String location, 355 HttpState httpState, Project project) throws SAXException , IOException , 356 TransformerException , ParserConfigurationException 357 { 358 Map data; 359 if (initialDataRetrieverAsObject instanceof InitialDataRetrieverWithContext) 360 { 361 InitialDataRetrieverWithContext dataRetrieverWithContext = (InitialDataRetrieverWithContext) initialDataRetrieverAsObject; 362 Map context = new HashMap (); 363 context.put("project", project); 364 data = dataRetrieverWithContext.getData(location, httpState, context); 365 } 366 else 367 { 368 InitialDataRetriever dataRetriever = (InitialDataRetriever) initialDataRetrieverAsObject; 369 data = dataRetriever.getData(location, httpState); 370 } 371 for (Iterator keysIterator = data.keySet().iterator(); keysIterator.hasNext();) 372 { 373 String key = (String ) keysIterator.next(); 374 Object value = data.get(key); 375 if (value == null) 376 { 377 value = ""; 378 } 379 else if (value instanceof Document ) 380 { 381 value = ((Document ) value).getDocumentElement(); 382 } 383 384 AttributesImpl valueAttributes = new AttributesImpl (); 385 valueAttributes.addAttribute(null, "name", "name", "CDATA", key); 386 contentHandler.startElement(null, "value", "value", valueAttributes); 387 if (value instanceof Element ) 388 { 389 includeElement((Element ) value); 390 } 391 else 392 { 393 char[] valueAsCharArray = value.toString().toCharArray(); 394 contentHandler.characters(valueAsCharArray, 0, valueAsCharArray.length); 395 } 396 contentHandler.endElement(null, "value", "value"); 397 } 398 } 399 400 private void outputSecondaryPlacementWorkflowId(long secondaryPlacementWorkflowId) 401 throws SAXException 402 { 403 contentHandler.startElement(null, "workflow-id", "workflow-id", EMPTY_ATTRIBUTE_LIST); 404 char[] websiteAsCharacterArray = String.valueOf(secondaryPlacementWorkflowId).toCharArray(); 405 contentHandler.characters(websiteAsCharacterArray, 0, websiteAsCharacterArray.length); 406 contentHandler.endElement(null, "workflow-id", "workflow-id"); 407 } 408 409 private void outputSecondaryPlacementWebsite(PropertySet secondaryPlacementProperties) 410 throws SAXException 411 { 412 contentHandler.startElement(null, "website", "website", EMPTY_ATTRIBUTE_LIST); 413 char[] websiteAsCharacterArray = secondaryPlacementProperties.getString("websiteName") 414 .toCharArray(); 415 contentHandler.characters(websiteAsCharacterArray, 0, websiteAsCharacterArray.length); 416 contentHandler.endElement(null, "website", "website"); 417 } 418 419 private void outputSecondaryPlacementTaxonomyLocation(PropertySet secondaryPlacementProperties) 420 throws SAXException 421 { 422 contentHandler.startElement(null, "taxonomy-location", "taxonomy-location", EMPTY_ATTRIBUTE_LIST); 423 char[] taxonomyLocationAsCharacterArray = secondaryPlacementProperties.getString( 424 "taxonomyLocation").toCharArray(); 425 contentHandler.characters(taxonomyLocationAsCharacterArray, 0, 426 taxonomyLocationAsCharacterArray.length); 427 contentHandler.endElement(null, "taxonomy-location", "taxonomy-location"); 428 } 429 430 public void dispose() 431 { 432 m_manager.release(m_avalonSpringBridge); 433 m_manager = null; 434 } 435 436 private void releaseWorkflowExtension(Object workflowExtension) 437 { 438 if (workflowExtension instanceof WrapperServiceSelector 439 || workflowExtension instanceof Component) 440 { 441 m_manager.release(workflowExtension); 442 } 443 } 444 445 private void optionallyIncludeResource(ProjectWorkflowRepository workflow, long workflowId, 446 String resourceLocation) throws FactoryConfigurationError , IOException , 447 ProcessingException, ParserConfigurationException , SAXException , ResourceLoadException 448 { 449 if (resourceLocation != null && !resourceLocation.equals("")) 450 { 451 SAXParserFactory spf = SAXParserFactory.newInstance(); 453 spf.setNamespaceAware(true); 454 spf.setValidating(false); 455 SAXParser sp = spf.newSAXParser(); 456 DelegatingContentHandler handler = new DelegatingContentHandler(contentHandler, true); 457 InputStream resourceInputStream = workflow.getResourceAsStream(workflowId, 458 resourceLocation); 459 sp.parse(new InputSource (resourceInputStream), handler); 460 466 } 467 } 468 469 private void includeElement(Element element) throws IOException , TransformerException , 470 ParserConfigurationException , SAXException 471 { 472 TransformerFactory tf = TransformerFactory.newInstance(); 474 Transformer t = tf.newTransformer(); 475 ByteArrayOutputStream o = new ByteArrayOutputStream (); 476 t.transform(new DOMSource (element), new StreamResult (o)); 477 o.close(); 478 SAXParserFactory spf = SAXParserFactory.newInstance(); 480 spf.setNamespaceAware(true); 481 spf.setValidating(false); 482 SAXParser sp = spf.newSAXParser(); 483 DelegatingContentHandler handler = new DelegatingContentHandler(contentHandler, true); 484 sp.parse(new InputSource (new ByteArrayInputStream (o.toByteArray())), handler); 485 } 486 487 private void optionallyOutputTextElement(String elementName, String text) throws SAXException 488 { 489 if (text != null) 490 { 491 contentHandler.startElement(null, elementName, elementName, EMPTY_ATTRIBUTE_LIST); 492 char[] textAsCharacterArray = text.toCharArray(); 493 contentHandler.characters(textAsCharacterArray, 0, textAsCharacterArray.length); 494 contentHandler.endElement(null, elementName, elementName); 495 } 496 } 497 498 } | Popular Tags |