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