cocoon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cziege...@apache.org
Subject svn commit: r348400 - in /cocoon/blocks: portal-sample/trunk/samples/coplets/docs/ portal/trunk/ portal/trunk/java/org/apache/cocoon/portal/coplet/ portal/trunk/java/org/apache/cocoon/portal/coplet/impl/ portal/trunk/java/org/apache/cocoon/portal/event...
Date Wed, 23 Nov 2005 09:15:37 GMT
Author: cziegeler
Date: Wed Nov 23 01:14:57 2005
New Revision: 348400

URL: http://svn.apache.org/viewcvs?rev=348400&view=rev
Log:
Implement auto deployment for jsr 168 portlets
HTML form actions can now marked as external
Update docs for deployment

Added:
    cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/event/coplet/CopletDataAddedEvent.java   (with props)
    cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/deployment/portlet.tld   (with props)
    cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/factory/PortletInvokerImpl.java   (with props)
    cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/servlet/PortletServlet.java   (with props)
Modified:
    cocoon/blocks/portal-sample/trunk/samples/coplets/docs/portal-demo.xml
    cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/coplet/CopletFactory.java
    cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/coplet/impl/DefaultCopletFactory.java
    cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/layout/AbstractLayout.java
    cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/PortletContainerEnvironmentImpl.java
    cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/adapter/PortletAdapter.java
    cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/deployment/Deployer.java
    cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/deployment/WebApplicationRewriter.java
    cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/factory/PortletInvokerFactoryImpl.java
    cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/om/PortletDefinitionListImpl.java
    cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/om/PortletDefinitionRegistryImpl.java
    cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/om/ServletDefinitionListImpl.java
    cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/services/factory/FactoryManagerServiceImpl.java
    cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/profile/impl/GroupBasedProfileManager.java
    cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/source/CopletSourceFactory.java
    cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/transformation/HTMLEventLinkTransformer.java
    cocoon/blocks/portal/trunk/status.xml

Modified: cocoon/blocks/portal-sample/trunk/samples/coplets/docs/portal-demo.xml
URL: http://svn.apache.org/viewcvs/cocoon/blocks/portal-sample/trunk/samples/coplets/docs/portal-demo.xml?rev=348400&r1=348399&r2=348400&view=diff
==============================================================================
--- cocoon/blocks/portal-sample/trunk/samples/coplets/docs/portal-demo.xml (original)
+++ cocoon/blocks/portal-sample/trunk/samples/coplets/docs/portal-demo.xml Wed Nov 23 01:14:57 2005
@@ -47,18 +47,27 @@
      <section title="The JSR 168">
         <p>The Cocoon portal supports portlets conforming to the JSR 168. The JSR 168 tab contains 
            a sample using the testsuite from the <fork href="http://portals.apache.org/pluto">Pluto project</fork>.</p>
-        <p>These samples only work if you follow these installation instructions:</p>
+        <p>
+          If you want to use JSR 168 portlets, you have to follow some installation instructions
+          as the current build system of Cocoon is not capable of doing so. (An easy installation
+          procedure will follow as soon as possible).
+        </p>
         <ul>
-         <li>Get the Pluto project and install it into Tomcat (Test Pluto now).</li>
-         <li>Install Cocoon as a web application in Tomcat and remove the Pluto webapp. Please note,
-             that it is currently not possible to start Cocoon directly from a war file; it has 
-             to be expanded.</li>
-         <li>Remove the pluto-*.jar and the portlet-api-*.jar from the Cocoon WEB-INF/lib directory.</li>
-         <li>Start Tomcat and run the Cocoon portal demo. You should now see two portlets.</li>
+          <li>Install Cocoon in different servlet engine than Jetty, for example Tomcat.</li>
+          <li>Enable cross context access for Cocoon (see Tomcat configuration
+             documentation for more infos).</li>
+           <li>Move (not copy!) the pluto-*.jar, the portlet-api-*.jar and the portals-bridges-*.jar
+             from the Cocoon WEB-INF/lib directory to the TOMCAT_HOME/shared/lib directory.</li>
+           <li>Copy the cocoon-portal-*.jar from the WEB-INF/lib/directory to the TOMCAT_HOME/shared/lib
+             directory.</li>
+        </ul>
+        <p>The included samples only work if you follow these additional installation instructions:</p>
+        <ul>
+         <li>Get the Pluto project and build the testsuite.war.</li>
+         <li>Copy the testsuite.war into the cocoon/samples/blocks/portal-sample/conf/deploy directory.</li>
+         <li>Start Tomcat, go to the portal sample page, give Cocoon some seconds to deploy the portlets and
+           then log into the portal.</li>
         </ul>
-        <p>The current implementation searches for portlets in all directories that are next to
-         the Cocoon webapp directory. So, if you put Cocoon into the webapps directory of Tomcat,
-         you should put your portlets there as well.</p>
      </section>
      <section title="WSRP">
         <p>The Cocoon portal supports portlets conforming to the WSRP. The WSRP tab contains 

Modified: cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/coplet/CopletFactory.java
URL: http://svn.apache.org/viewcvs/cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/coplet/CopletFactory.java?rev=348400&r1=348399&r2=348400&view=diff
==============================================================================
--- cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/coplet/CopletFactory.java (original)
+++ cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/coplet/CopletFactory.java Wed Nov 23 01:14:57 2005
@@ -46,4 +46,10 @@
      * This is also unregistered at the profile manager.
      */
     void remove(CopletInstanceData copletInstanceData);
+
+    /**
+     * Create a new coplet data instance.
+     */
+    CopletData newInstance(CopletBaseData copletBaseData, String id)
+    throws PortalException;
 }

Modified: cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/coplet/impl/DefaultCopletFactory.java
URL: http://svn.apache.org/viewcvs/cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/coplet/impl/DefaultCopletFactory.java?rev=348400&r1=348399&r2=348400&view=diff
==============================================================================
--- cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/coplet/impl/DefaultCopletFactory.java (original)
+++ cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/coplet/impl/DefaultCopletFactory.java Wed Nov 23 01:14:57 2005
@@ -16,10 +16,12 @@
 package org.apache.cocoon.portal.coplet.impl;
 
 import org.apache.cocoon.portal.PortalException;
+import org.apache.cocoon.portal.coplet.CopletBaseData;
 import org.apache.cocoon.portal.coplet.CopletData;
 import org.apache.cocoon.portal.coplet.CopletFactory;
 import org.apache.cocoon.portal.coplet.CopletInstanceData;
 import org.apache.cocoon.portal.coplet.adapter.CopletAdapter;
+import org.apache.cocoon.portal.event.coplet.CopletDataAddedEvent;
 import org.apache.cocoon.portal.event.coplet.CopletInstanceDataAddedEvent;
 import org.apache.cocoon.portal.event.coplet.CopletInstanceDataRemovedEvent;
 import org.apache.cocoon.portal.impl.AbstractComponent;
@@ -82,5 +84,25 @@
             // send an event
             this.portalService.getComponentManager().getEventManager().send(new CopletInstanceDataRemovedEvent(copletInstanceData));
         }
+    }
+
+    /**
+     * @see org.apache.cocoon.portal.coplet.CopletFactory#newInstance(org.apache.cocoon.portal.coplet.CopletBaseData, java.lang.String)
+     */
+    public CopletData newInstance(CopletBaseData copletBaseData, String id)
+    throws PortalException {
+        if (id == null ) {
+            synchronized (this) {
+                id = copletBaseData.getId() + '-' + idCounter;
+                idCounter += 1;
+            }
+        }
+        final CopletData instance = new CopletData(id);
+        instance.setCopletBaseData(copletBaseData);
+
+        // send an event
+        this.portalService.getComponentManager().getEventManager().send(new CopletDataAddedEvent(instance));
+
+        return instance;
     }
 }

Added: cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/event/coplet/CopletDataAddedEvent.java
URL: http://svn.apache.org/viewcvs/cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/event/coplet/CopletDataAddedEvent.java?rev=348400&view=auto
==============================================================================
--- cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/event/coplet/CopletDataAddedEvent.java (added)
+++ cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/event/coplet/CopletDataAddedEvent.java Wed Nov 23 01:14:57 2005
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.portal.event.coplet;
+
+import org.apache.cocoon.portal.coplet.CopletData;
+import org.apache.cocoon.portal.event.CopletDataEvent;
+import org.apache.cocoon.portal.event.impl.AbstractActionEvent;
+
+/**
+ * This event is fired when a new coplet is created.
+ *
+ * @version $Id$
+ */
+public class CopletDataAddedEvent
+    extends AbstractActionEvent
+    implements CopletDataEvent {
+
+    public CopletDataAddedEvent(CopletData target) {
+        super(target);
+    }    
+}

Propchange: cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/event/coplet/CopletDataAddedEvent.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/event/coplet/CopletDataAddedEvent.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/layout/AbstractLayout.java
URL: http://svn.apache.org/viewcvs/cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/layout/AbstractLayout.java?rev=348400&r1=348399&r2=348400&view=diff
==============================================================================
--- cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/layout/AbstractLayout.java (original)
+++ cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/layout/AbstractLayout.java Wed Nov 23 01:14:57 2005
@@ -191,7 +191,7 @@
         clone.description = this.description;
         clone.rendererName = this.rendererName;
         clone.isStatic = this.isStatic;
-        clone.parameters = new LinkedMap(this.parameters);
+        clone.temporaryAttributes = new LinkedMap(this.temporaryAttributes);
         clone.parent = null;
 
         return clone;

Modified: cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/PortletContainerEnvironmentImpl.java
URL: http://svn.apache.org/viewcvs/cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/PortletContainerEnvironmentImpl.java?rev=348400&r1=348399&r2=348400&view=diff
==============================================================================
--- cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/PortletContainerEnvironmentImpl.java (original)
+++ cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/PortletContainerEnvironmentImpl.java Wed Nov 23 01:14:57 2005
@@ -25,6 +25,9 @@
 import org.apache.avalon.framework.context.Context;
 import org.apache.avalon.framework.context.Contextualizable;
 import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.avalon.framework.parameters.ParameterException;
+import org.apache.avalon.framework.parameters.Parameterizable;
+import org.apache.avalon.framework.parameters.Parameters;
 import org.apache.avalon.framework.service.ServiceException;
 import org.apache.avalon.framework.service.ServiceManager;
 import org.apache.avalon.framework.service.Serviceable;
@@ -49,35 +52,51 @@
  */
 public class PortletContainerEnvironmentImpl 
 extends AbstractLogEnabled
-implements PortletContainerEnvironment, Serviceable, Disposable, Initializable, Contextualizable {
+    implements PortletContainerEnvironment,
+               Serviceable,
+               Disposable,
+               Initializable,
+               Contextualizable,
+               Parameterizable {
 
-    /** The service manager */
+    /** The service manager. */
     protected ServiceManager manager;
     
-    /** Services */
+    /** Services. */
     protected Map services = new HashMap();
     
-    /** Static services */
+    /** Static services. */
     protected Map staticServices = new HashMap();
     
-    /** Context */
+    /** Context. */
     protected Context context;
     
+    /** Configuration. */
+    protected Parameters parameters;
+
+    /**
+     * @see org.apache.avalon.framework.parameters.Parameterizable#parameterize(org.apache.avalon.framework.parameters.Parameters)
+     */
+    public void parameterize(Parameters params)
+    throws ParameterException {
+        this.parameters = params;
+    }
+
     /**
-     * Serviceable
+     * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
      */
     public void service(ServiceManager manager) {
         this.manager = manager;
     }
     
-    /* (non-Javadoc)
+    /**
      * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
      */
     public void contextualize(Context context) {
         this.context = context;        
     }
     
-    /* (non-Javadoc)
+    /**
      * @see org.apache.avalon.framework.activity.Initializable#initialize()
      */
     public void initialize() throws Exception {
@@ -102,6 +121,7 @@
     throws Exception {
         ContainerUtil.enableLogging(o, this.getLogger());
         ContainerUtil.contextualize(o, this.context);
+        ContainerUtil.parameterize(o, this.parameters);
         ContainerUtil.service(o, this.manager);
         if ( o instanceof PortletContainerEnabled ) {
             ((PortletContainerEnabled)o).setPortletContainerEnvironment(this);
@@ -110,7 +130,7 @@
         return o;
     }
 
-    /* (non-Javadoc)
+    /**
      * @see org.apache.avalon.framework.activity.Disposable#dispose()
      */
     public void dispose() {
@@ -124,7 +144,7 @@
         }
     }
     
-    /* (non-Javadoc)
+    /**
      * @see org.apache.pluto.services.PortletContainerEnvironment#getContainerService(java.lang.Class)
      */
     public ContainerService getContainerService(Class serviceClazz) {
@@ -143,5 +163,4 @@
         }
         return service;
     }
-
 }

Modified: cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/adapter/PortletAdapter.java
URL: http://svn.apache.org/viewcvs/cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/adapter/PortletAdapter.java?rev=348400&r1=348399&r2=348400&view=diff
==============================================================================
--- cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/adapter/PortletAdapter.java (original)
+++ cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/adapter/PortletAdapter.java Wed Nov 23 01:14:57 2005
@@ -28,6 +28,8 @@
 import org.apache.avalon.framework.container.ContainerUtil;
 import org.apache.avalon.framework.context.Context;
 import org.apache.avalon.framework.context.ContextException;
+import org.apache.avalon.framework.parameters.ParameterException;
+import org.apache.avalon.framework.parameters.Parameterizable;
 import org.apache.avalon.framework.parameters.Parameters;
 import org.apache.cocoon.ProcessingException;
 import org.apache.cocoon.components.ContextHelper;
@@ -75,7 +77,7 @@
  */
 public class PortletAdapter 
     extends AbstractCopletAdapter
-    implements PortalManagerAspect, Receiver {
+    implements PortalManagerAspect, Receiver, Parameterizable {
 	
     /** The servlet configuration for pluto. */
     protected ServletConfig servletConfig;
@@ -86,6 +88,9 @@
     /** The Portlet Container environment. */
     protected PortletContainerEnvironmentImpl portletContainerEnvironment;
 
+    /** The configuration. */
+    protected Parameters parameters;
+
     /**
      * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
      */
@@ -102,6 +107,13 @@
     }
 
     /**
+     * @see org.apache.avalon.framework.parameters.Parameterizable#parameterize(org.apache.avalon.framework.parameters.Parameters)
+     */
+    public void parameterize(Parameters params) throws ParameterException {
+        this.parameters = params;
+    }
+
+    /**
      * @see org.apache.cocoon.portal.coplet.adapter.CopletAdapter#login(org.apache.cocoon.portal.coplet.CopletInstanceData)
      */
     public void login(CopletInstanceData coplet) {
@@ -270,6 +282,7 @@
             this.portletContainerEnvironment = new PortletContainerEnvironmentImpl();
             ContainerUtil.enableLogging(this.portletContainerEnvironment, this.getLogger());
             ContainerUtil.contextualize(this.portletContainerEnvironment, this.context);
+            ContainerUtil.parameterize(this.portletContainerEnvironment, this.parameters);
             ContainerUtil.service(this.portletContainerEnvironment, this.manager);
             ContainerUtil.initialize(this.portletContainerEnvironment);
 

Modified: cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/deployment/Deployer.java
URL: http://svn.apache.org/viewcvs/cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/deployment/Deployer.java?rev=348400&r1=348399&r2=348400&view=diff
==============================================================================
--- cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/deployment/Deployer.java (original)
+++ cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/deployment/Deployer.java Wed Nov 23 01:14:57 2005
@@ -30,6 +30,7 @@
 import javax.xml.parsers.ParserConfigurationException;
 
 import org.apache.avalon.framework.logger.Logger;
+import org.apache.avalon.framework.service.ServiceManager;
 import org.apache.cocoon.CascadingIOException;
 import org.apache.cocoon.ProcessingException;
 import org.apache.cocoon.portal.deployment.DeploymentException;
@@ -47,12 +48,11 @@
  */
 public class Deployer {
 
-    protected final byte[] buffer = new byte[8192];
-
-    public Deployer(Source inputSource,
-                    String outputName,
-                    boolean stripLoggers,
-                    Logger logger)
+    public static void deploy(Source inputSource,
+                              String outputName,
+                              boolean stripLoggers,
+                              Logger logger,
+                              ServiceManager manager)
     throws DeploymentException, IOException, SAXException, ProcessingException {
         File tempFile = null;
         JarInputStream jin = null;
@@ -79,28 +79,28 @@
                 String target = src.getName();
                 if ("WEB-INF/web.xml".equals(target)) {
                     logger.debug("Found web.xml");
-                    webXml = this.parseXml(jin);
+                    webXml = parseXml(jin);
                 } else if ("WEB-INF/portlet.xml".equals(target)) {
                     logger.debug("Found WEB-INF/portlet.xml");
-                    portletXml = this.parseXml(jin);
+                    portletXml = parseXml(jin);
                 } else if ("META-INF/context.xml".equals(target)) {
                     logger.debug("Found META-INF/context.xml");
-                    contextXml = this.parseXml(jin);
+                    contextXml = parseXml(jin);
                 } else {
                     if ( stripLoggers && target.endsWith(".jar") &&
                          (target.startsWith("WEB-INF/lib/commons-logging") || target.startsWith("WEB-INF/lib/log4j"))) {
                         logger.info("Stripping logger: "+target);
                         continue;
                     }
-                    this.addFile(target, jin, jout);
+                    addFile(target, jin, jout);
                 }
             }
 
             if (webXml == null) {
-                throw new DeploymentException("WEB-INF/web.xml");
+                throw new DeploymentException("WEB-INF/web.xml is missing.");
             }
             if (portletXml == null) {
-                throw new DeploymentException("WEB-INF/portlet.xml");
+                throw new DeploymentException("WEB-INF/portlet.xml is missing.");
             }
 
             WebApplicationRewriter webRewriter = new WebApplicationRewriter(webXml);
@@ -115,7 +115,7 @@
 
             if (webRewriter.isPortletTaglibAdded()) {
                 logger.info("Attempting to add portlet.tld to war...");
-                InputStream is = this.getClass().getResourceAsStream("portlet.tld");
+                InputStream is = Deployer.class.getResourceAsStream("portlet.tld");
                 if (is == null) {
                     logger.warn("Failed to find portlet.tld in classpath");
                 } else {
@@ -182,10 +182,10 @@
         }
     }
 
-    protected Document parseXml(InputStream source) throws IOException, SAXException {
+    protected static Document parseXml(InputStream source) throws IOException, SAXException {
         try {
             DocumentBuilderFactory documentFactory = DocumentBuilderFactory.newInstance();
-            documentFactory.setNamespaceAware(false);
+            documentFactory.setNamespaceAware(true);
             documentFactory.setValidating(false);
             DocumentBuilder docBuilder = documentFactory.newDocumentBuilder();
             // Parse using the local dtds instead of remote dtds. This
@@ -205,10 +205,11 @@
         }
     }
 
-    protected void addFile(String path, InputStream source, JarOutputStream jos)
+    protected static void addFile(String path, InputStream source, JarOutputStream jos)
     throws IOException  {
         jos.putNextEntry(new ZipEntry(path));
         try {
+            byte[] buffer = new byte[4096];
             int count;
             while ((count = source.read(buffer)) > 0) {
                 jos.write(buffer, 0, count);
@@ -218,7 +219,7 @@
         }
     }
 
-    protected void addFile(String path, Document source, JarOutputStream jos)
+    protected static void addFile(String path, Document source, JarOutputStream jos)
     throws IOException, ProcessingException {
         if (source != null) {
             jos.putNextEntry(new ZipEntry(path));
@@ -231,7 +232,7 @@
         }
     }
 
-    protected String getPortletApplicationName(String path) {
+    protected static String getPortletApplicationName(String path) {
         File file = new File(path);
         String name = file.getName();
         String portletApplicationName = name;
@@ -315,4 +316,4 @@
             return this.wrapped.skip(n);
         }
     }
-}
\ No newline at end of file
+}

Modified: cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/deployment/WebApplicationRewriter.java
URL: http://svn.apache.org/viewcvs/cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/deployment/WebApplicationRewriter.java?rev=348400&r1=348399&r2=348400&view=diff
==============================================================================
--- cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/deployment/WebApplicationRewriter.java (original)
+++ cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/deployment/WebApplicationRewriter.java Wed Nov 23 01:14:57 2005
@@ -19,6 +19,7 @@
 import java.util.List;
 
 import org.apache.cocoon.portal.deployment.DeploymentException;
+import org.apache.cocoon.portal.pluto.servlet.PortletServlet;
 import org.apache.xpath.XPathAPI;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
@@ -89,7 +90,7 @@
                 servletDesc.appendChild(this.document.createTextNode("Servlet for Cocoon Portal Container"));
 
                 Element servletClass = this.document.createElement("servlet-class");
-                servletClass.appendChild(this.document.createTextNode("org.apache.pluto.core.PortletServlet"));
+                servletClass.appendChild(this.document.createTextNode(PortletServlet.class.getName()));
 
                 servletElement.appendChild(servletName);
                 servletElement.appendChild(servletDspName);

Added: cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/deployment/portlet.tld
URL: http://svn.apache.org/viewcvs/cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/deployment/portlet.tld?rev=348400&view=auto
==============================================================================
--- cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/deployment/portlet.tld (added)
+++ cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/deployment/portlet.tld Wed Nov 23 01:14:57 2005
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE taglib PUBLIC
+  "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
+  "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
+<!-- 
+Copyright 2004 The Apache Software Foundation
+Licensed  under the  Apache License,  Version 2.0  (the "License");
+you may not use  this file  except in  compliance with the License.
+You may obtain a copy of the License at 
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed  under the  License is distributed on an "AS IS" BASIS,
+WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+implied.
+
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<taglib>
+    <tlibversion>1.0</tlibversion>
+    <jspversion>1.2</jspversion>
+    <shortname>portlet</shortname>
+    <uri>http://java.sun.com/portlet</uri>
+    <tag>
+        <name>defineObjects</name>
+        <tagclass>org.apache.pluto.tags.DefineObjectsTag</tagclass>
+        <teiclass>org.apache.pluto.tags.DefineObjectsTag$TEI</teiclass>
+        <bodycontent>empty</bodycontent>
+    </tag>
+    <tag>
+        <name>param</name>
+        <tagclass>org.apache.pluto.tags.ParamTag</tagclass>
+        <bodycontent>empty</bodycontent>
+        <attribute>
+            <name>name</name>
+            <required>true</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>value</name>
+            <required>true</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+    </tag>
+    <tag>
+        <name>actionURL</name>
+        <tagclass>org.apache.pluto.tags.ActionURLTag</tagclass>
+        <teiclass>org.apache.pluto.tags.BasicURLTag$TEI</teiclass>
+        <bodycontent>JSP</bodycontent>
+        <attribute>
+            <name>windowState</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>portletMode</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>secure</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>var</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+    </tag>
+    <tag>
+        <name>renderURL</name>
+        <tagclass>org.apache.pluto.tags.RenderURLTag</tagclass>
+        <teiclass>org.apache.pluto.tags.BasicURLTag$TEI</teiclass>
+        <bodycontent>JSP</bodycontent>
+        <attribute>
+            <name>windowState</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>portletMode</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>secure</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>var</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+    </tag>
+    <tag>
+        <name>namespace</name>
+        <tagclass>org.apache.pluto.tags.NamespaceTag</tagclass>
+        <bodycontent>empty</bodycontent>
+    </tag>
+</taglib>

Propchange: cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/deployment/portlet.tld
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/factory/PortletInvokerFactoryImpl.java
URL: http://svn.apache.org/viewcvs/cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/factory/PortletInvokerFactoryImpl.java?rev=348400&r1=348399&r2=348400&view=diff
==============================================================================
--- cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/factory/PortletInvokerFactoryImpl.java (original)
+++ cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/factory/PortletInvokerFactoryImpl.java Wed Nov 23 01:14:57 2005
@@ -32,7 +32,6 @@
 import org.apache.cocoon.portal.pluto.om.PortletDefinitionImpl;
 import org.apache.pluto.factory.PortletInvokerFactory;
 import org.apache.pluto.invoker.PortletInvoker;
-import org.apache.pluto.invoker.impl.PortletInvokerImpl;
 import org.apache.pluto.om.portlet.PortletDefinition;
 
 /**

Added: cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/factory/PortletInvokerImpl.java
URL: http://svn.apache.org/viewcvs/cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/factory/PortletInvokerImpl.java?rev=348400&view=auto
==============================================================================
--- cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/factory/PortletInvokerImpl.java (added)
+++ cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/factory/PortletInvokerImpl.java Wed Nov 23 01:14:57 2005
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.portal.pluto.factory;
+
+import java.io.IOException;
+
+import javax.portlet.PortletException;
+import javax.portlet.PortletRequest;
+import javax.portlet.PortletResponse;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletRequest;
+
+import org.apache.cocoon.portal.pluto.servlet.PortletServlet;
+import org.apache.pluto.core.CoreUtils;
+import org.apache.pluto.core.InternalPortletRequest;
+import org.apache.pluto.om.portlet.PortletDefinition;
+
+/**
+ * This component invokes a portlet (using the servlet dispatcher).
+ *
+ * $Id$
+ */
+public class PortletInvokerImpl
+    extends org.apache.pluto.invoker.impl.PortletInvokerImpl {
+
+    protected final PortletDefinition portletDefinition;
+
+    public PortletInvokerImpl(PortletDefinition portletDefinition,
+                              ServletConfig servletConfig) {
+        super(portletDefinition, servletConfig);
+        this.portletDefinition = portletDefinition;
+    }
+
+    /**
+     * generic method to be used called by both, action and render
+     */
+    protected void invoke(PortletRequest portletRequest, PortletResponse portletResponse, Integer methodID) 
+    throws PortletException,IOException {
+        InternalPortletRequest internalPortletRequest = CoreUtils.getInternalRequest(portletRequest);
+        ServletRequest servletRequest = ((javax.servlet.http.HttpServletRequestWrapper)internalPortletRequest).getRequest();
+        try {
+            servletRequest.setAttribute(PortletServlet.PORTLET_DEFINITION, this.portletDefinition);
+            super.invoke(portletRequest, portletResponse, methodID);
+        } finally {
+            servletRequest.removeAttribute(PortletServlet.PORTLET_DEFINITION);
+        }
+    }
+}

Propchange: cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/factory/PortletInvokerImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/factory/PortletInvokerImpl.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/om/PortletDefinitionListImpl.java
URL: http://svn.apache.org/viewcvs/cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/om/PortletDefinitionListImpl.java?rev=348400&r1=348399&r2=348400&view=diff
==============================================================================
--- cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/om/PortletDefinitionListImpl.java (original)
+++ cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/om/PortletDefinitionListImpl.java Wed Nov 23 01:14:57 2005
@@ -19,6 +19,7 @@
 import java.util.Map;
 import java.util.Vector;
 
+import org.apache.cocoon.portal.pluto.deployment.WebApplicationRewriter;
 import org.apache.cocoon.portal.pluto.om.common.AbstractSupportSet;
 import org.apache.cocoon.portal.pluto.om.common.Support;
 import org.apache.pluto.om.common.ObjectID;
@@ -62,9 +63,8 @@
 
             ServletDefinition servlet = null;
             if (servletMap != null) {
-                servlet = (ServletDefinition)servletMap.get(portlet.getId().toString());
+                servlet = (ServletDefinition)servletMap.get(WebApplicationRewriter.CONTAINER);
             }
-
             ((Support)portlet).postBuild(servlet);
         }
     }

Modified: cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/om/PortletDefinitionRegistryImpl.java
URL: http://svn.apache.org/viewcvs/cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/om/PortletDefinitionRegistryImpl.java?rev=348400&r1=348399&r2=348400&view=diff
==============================================================================
--- cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/om/PortletDefinitionRegistryImpl.java (original)
+++ cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/om/PortletDefinitionRegistryImpl.java Wed Nov 23 01:14:57 2005
@@ -40,10 +40,12 @@
 import org.apache.cocoon.components.source.SourceUtil;
 import org.apache.cocoon.portal.PortalService;
 import org.apache.cocoon.portal.deployment.DeploymentEvent;
+import org.apache.cocoon.portal.deployment.DeploymentException;
 import org.apache.cocoon.portal.deployment.DeploymentStatus;
 import org.apache.cocoon.portal.event.Receiver;
 import org.apache.cocoon.portal.impl.AbstractComponent;
 import org.apache.cocoon.portal.pluto.deployment.Deployer;
+import org.apache.cocoon.portal.pluto.deployment.WebApplicationRewriter;
 import org.apache.cocoon.servlet.CocoonServlet;
 import org.apache.excalibur.source.Source;
 import org.apache.excalibur.source.SourceResolver;
@@ -267,17 +269,21 @@
             if ( this.getLogger().isDebugEnabled() ) {
                 this.getLogger().debug("Searching file: " + entry);
             }
-            if (entry.isDirectory()) {
-                loadWebApp(f.getAbsolutePath(), entries[i]);
-            } else if (entry.isFile()) {
-                String name = entry.getName();
-                int index = name.lastIndexOf(".war");
-                if (index > 0 && name.endsWith(".war")) {
-                    String webModule = name.substring(0, index);
-                    if (!entryList.contains(webModule)) {
-                        loadWar(entry, webModule);
+            try {
+                if (entry.isDirectory()) {
+                    this.loadWebApp(f.getAbsolutePath(), entries[i]);
+                } else if (entry.isFile()) {
+                    String name = entry.getName();
+                    int index = name.lastIndexOf(".war");
+                    if (index > 0 && name.endsWith(".war")) {
+                        String webModule = name.substring(0, index);
+                        if (!entryList.contains(webModule)) {
+                            this.loadWar(entry, webModule);
+                        }
                     }
                 }
+            } catch (DeploymentException de) {
+                this.getLogger().error("Error during deployment of portlet application.", de);
             }
         }
     }
@@ -336,11 +342,11 @@
         }
     }
 
-    private void loadWebApp(String baseDir, String webModule)
+    protected void loadWebApp(String baseDir, String webModule)
     throws Exception {
         String directory = baseDir + File.separatorChar + webModule + File.separatorChar + "WEB-INF" + File.separatorChar;
-        if (this.getLogger().isDebugEnabled()) {
-            this.getLogger().debug("Searching in directory: " + directory);
+        if (this.getLogger().isInfoEnabled()) {
+            this.getLogger().info("Searching for portlet application in directory: " + directory);
         }
 
         File portletXml = new File(directory + "portlet.xml");
@@ -369,7 +375,7 @@
         }
     }
 
-    private void load(InputSource portletXml, InputSource webXml, String webModule)
+    protected void load(InputSource portletXml, InputSource webXml, String webModule)
     throws Exception {
         if (this.getLogger().isDebugEnabled()) {
             this.getLogger().debug("Loading the following Portlet Applications XML files..." +
@@ -425,7 +431,7 @@
         this.registry.add(portletApp);
 
         if ( this.getLogger().isInfoEnabled() ) {
-            this.getLogger().info("Portlet application '" + portletApp.getAppId() + "' added to registry.");
+            this.getLogger().info("Portlet application '" + portletApp.getGUID() + "' added to registry.");
         }
 
         // fill portletsKeyObjectId
@@ -433,9 +439,11 @@
         while (portlets.hasNext()) {
             final PortletDefinition portlet = (PortletDefinition) portlets.next();
             portletsKeyObjectId.put(portlet.getId(), portlet);
-
             if (this.contextName.equals(webModule)) {
                 ((PortletDefinitionImpl) portlet).setLocalPortlet(true);
+            } else if ( portlet.getServletDefinition() == null ) {
+                throw new DeploymentException("Unable to deploy portlet '" + portlet.getId() + 
+                          "'. Servlet definition for '"+WebApplicationRewriter.CONTAINER+"' not found in web.xml.");
             }
             ((PortletDefinitionImpl) portlet).setPortletClassLoader(Thread.currentThread()
                 .getContextClassLoader());
@@ -467,10 +475,10 @@
         if (fileName.endsWith(".war")) {
             try {
                 File toFile = new File(this.webAppDir, fileName);
-                new Deployer(event.getDeploymentObject().getSource(),
-                             toFile.getAbsolutePath(), 
-                             this.stripLoggers,
-                             this.getLogger());
+                Deployer.deploy(event.getDeploymentObject().getSource(),
+                                toFile.getAbsolutePath(), 
+                                this.stripLoggers,
+                                this.getLogger(), this.manager);
                 // let's wait some seconds to give the web container time to
                 // deploy the new web app
                 Thread.sleep(10 * 1000);
@@ -478,8 +486,9 @@
                 this.loadWebApp(this.webAppDir, webModule);
                 event.setStatus(DeploymentStatus.STATUS_OKAY);
             } catch (Exception e) {
+                this.getLogger().error("Error during deployment of " + event.getDeploymentObject().getName(), e);
                 event.setStatus(DeploymentStatus.STATUS_FAILED);
             }
         }
     }
-}
\ No newline at end of file
+}

Modified: cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/om/ServletDefinitionListImpl.java
URL: http://svn.apache.org/viewcvs/cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/om/ServletDefinitionListImpl.java?rev=348400&r1=348399&r2=348400&view=diff
==============================================================================
--- cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/om/ServletDefinitionListImpl.java (original)
+++ cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/om/ServletDefinitionListImpl.java Wed Nov 23 01:14:57 2005
@@ -97,21 +97,13 @@
             ServletDefinition servlet = (ServletDefinition)iterator.next();
             ((Support)servlet).preBuild(webApplicationDefinition);
 
-            if (servlet.getInitParameterSet() != null) {
-                if (servlet.getInitParameterSet().get("portlet-guid") != null) {
-                    String guid = servlet.getInitParameterSet().get("portlet-guid").getValue();
-                    servletMap.put(guid, servlet);
-
-                    ServletMapping servletMapping = (ServletMapping)mappings.get(servlet.getServletName());
-                    if (mappings==null) {
-                        throw new ProcessingException("No corresponding servlet mapping found for servlet name '"+servlet.getServletName()+"'");
-                    }
-                    ((Support)servlet).postBuild(servletMapping);
-
-                }
+            servletMap.put(servlet.getServletName(), servlet);
+            ServletMapping servletMapping = (ServletMapping)mappings.get(servlet.getServletName());
+            if ( servletMapping == null) {
+                 throw new ProcessingException("No corresponding servlet mapping found for servlet name '"+servlet.getServletName()+"'");
             }
+            ((Support)servlet).postBuild(servletMapping);
         }
-
     }
 
     public void postBuild(Object parameter) throws Exception {

Modified: cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/services/factory/FactoryManagerServiceImpl.java
URL: http://svn.apache.org/viewcvs/cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/services/factory/FactoryManagerServiceImpl.java?rev=348400&r1=348399&r2=348400&view=diff
==============================================================================
--- cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/services/factory/FactoryManagerServiceImpl.java (original)
+++ cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/services/factory/FactoryManagerServiceImpl.java Wed Nov 23 01:14:57 2005
@@ -34,16 +34,13 @@
 import javax.portlet.RenderResponse;
 import javax.servlet.ServletConfig;
 
-import org.apache.avalon.framework.activity.Disposable;
-import org.apache.avalon.framework.activity.Initializable;
 import org.apache.avalon.framework.container.ContainerUtil;
 import org.apache.avalon.framework.context.Context;
 import org.apache.avalon.framework.context.ContextException;
-import org.apache.avalon.framework.context.Contextualizable;
-import org.apache.avalon.framework.logger.AbstractLogEnabled;
-import org.apache.avalon.framework.service.ServiceException;
-import org.apache.avalon.framework.service.ServiceManager;
-import org.apache.avalon.framework.service.Serviceable;
+import org.apache.avalon.framework.parameters.ParameterException;
+import org.apache.avalon.framework.parameters.Parameterizable;
+import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.cocoon.portal.impl.AbstractComponent;
 import org.apache.cocoon.portal.pluto.factory.ActionRequestFactoryImpl;
 import org.apache.cocoon.portal.pluto.factory.ControllerFactoryImpl;
 import org.apache.cocoon.portal.pluto.factory.ObjectIDFactoryImpl;
@@ -76,37 +73,34 @@
  * @version $Id$
  */
 public class FactoryManagerServiceImpl 
-extends AbstractLogEnabled
-implements FactoryManagerService, Initializable, Contextualizable, Serviceable, Disposable {
+    extends AbstractComponent
+    implements FactoryManagerService, Parameterizable {
 
     /** The servlet configuration */
     protected ServletConfig servletConfig;
 
-    /** The avalon context */
-    protected Context context;
-
-    /** The service manager */
-    protected ServiceManager manager;
-
     /** All factories mapped by factory class name. */
     protected Map  factoryMap  = new HashMap();
 
     /** All factories. */
     protected List factoryList = new ArrayList();
 
-    /**
+    /** The configuration. */
+    protected Parameters parameters;
+
+    /**<
      * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
      */
     public void contextualize(Context context) throws ContextException {
-        this.context = context;
-        this.servletConfig = (ServletConfig) context.get(CocoonServlet.CONTEXT_SERVLET_CONFIG);
+        super.contextualize(context);
+        this.servletConfig = (ServletConfig)this.context.get(CocoonServlet.CONTEXT_SERVLET_CONFIG);
     }
 
     /**
-     * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
+     * @see org.apache.avalon.framework.parameters.Parameterizable#parameterize(org.apache.avalon.framework.parameters.Parameters)
      */
-    public void service(ServiceManager manager) throws ServiceException {
-        this.manager = manager;
+    public void parameterize(Parameters params) throws ParameterException {
+        this.parameters = params;
     }
 
     /**
@@ -114,27 +108,41 @@
      */
     public void initialize()
     throws Exception {
+        super.initialize();
         final Map factories = new HashMap();
 
-        factories.put(ActionRequest.class.getName(), ActionRequestFactoryImpl.class.getName());
-        factories.put(RenderRequest.class.getName(), RenderRequestFactoryImpl.class.getName());
-        factories.put(RenderResponse.class.getName(), RenderResponseFactoryImpl.class.getName());
-        factories.put(PortletSession.class.getName(), PortletSessionFactoryImpl.class.getName());
-        factories.put(PortletConfig.class.getName(), PortletConfigFactoryImpl.class.getName());
-        factories.put(PortletContext.class.getName(), PortletContextFactoryImpl.class.getName());
-        factories.put(PortletPreferences.class.getName(), PortletPreferencesFactoryImpl.class.getName());
-        factories.put(PortalContext.class.getName(), PortalContextFactoryImpl.class.getName());
-        factories.put(ActionResponse.class.getName(), ActionResponseFactoryImpl.class.getName());
-        factories.put(PortletURL.class.getName(), PortletURLFactoryImpl.class.getName());
-        factories.put(PortletPreferences.class.getName(), PortletPreferencesFactoryImpl.class.getName());
-
-        factories.put(PortletInvoker.class.getName(), PortletInvokerFactoryImpl.class.getName());
+        factories.put(ActionRequest.class.getName(), 
+                      this.parameters.getParameter("action-request-factory", ActionRequestFactoryImpl.class.getName()));
+        factories.put(RenderRequest.class.getName(),
+                      this.parameters.getParameter("render-request-factory", RenderRequestFactoryImpl.class.getName()));
+        factories.put(ActionResponse.class.getName(),
+                      this.parameters.getParameter("action-response-factory", ActionResponseFactoryImpl.class.getName()));
+        factories.put(RenderResponse.class.getName(),
+                      this.parameters.getParameter("render-response-factory", RenderResponseFactoryImpl.class.getName()));
+        factories.put(PortletSession.class.getName(),
+                      this.parameters.getParameter("portlet-session-factory", PortletSessionFactoryImpl.class.getName()));
+        factories.put(PortletConfig.class.getName(),
+                      this.parameters.getParameter("portlet-config-factory", PortletConfigFactoryImpl.class.getName()));
+        factories.put(PortletContext.class.getName(),
+                      this.parameters.getParameter("portlet-context-factory", PortletContextFactoryImpl.class.getName()));
+        factories.put(PortalContext.class.getName(),
+                      this.parameters.getParameter("portal-context-factory", PortalContextFactoryImpl.class.getName()));
+        factories.put(PortletURL.class.getName(),
+                      this.parameters.getParameter("portlet-url-factory", PortletURLFactoryImpl.class.getName()));
+        factories.put(PortletPreferences.class.getName(),
+                      this.parameters.getParameter("portlet-preferences-factory", PortletPreferencesFactoryImpl.class.getName()));
+
+        factories.put(PortletInvoker.class.getName(),
+                      this.parameters.getParameter("portlet-invoker-factory", PortletInvokerFactoryImpl.class.getName()));
 
-        factories.put(NamespaceMapper.class.getName(), NamespaceMapperFactoryImpl.class.getName());
+        factories.put(NamespaceMapper.class.getName(),
+                      this.parameters.getParameter("namespace-mapper-factory", NamespaceMapperFactoryImpl.class.getName()));
 
-        factories.put(ObjectIDFactory.class.getName(), ObjectIDFactoryImpl.class.getName());
+        factories.put(ObjectIDFactory.class.getName(),
+                      this.parameters.getParameter("objectid-factory", ObjectIDFactoryImpl.class.getName()));
 
-        factories.put(ControllerFactory.class.getName(), ControllerFactoryImpl.class.getName());
+        factories.put(ControllerFactory.class.getName(),
+                      this.parameters.getParameter("controller-factory", ControllerFactoryImpl.class.getName()));
 
         for (Iterator iter = factories.entrySet().iterator(); iter.hasNext (); ) {
             Map.Entry me = (Map.Entry)iter.next();
@@ -143,12 +151,13 @@
 
             ContainerUtil.enableLogging(factory, this.getLogger());
             ContainerUtil.contextualize(factory, this.context);
+            ContainerUtil.parameterize(factory, this.parameters);
             ContainerUtil.service(factory, this.manager);
             ContainerUtil.initialize(factory);
 
             factory.init(this.servletConfig, Collections.EMPTY_MAP);
 
-            factoryMap.put(me.getKey(), factory);
+            this.factoryMap.put(me.getKey(), factory);
 
             // build up list in reverse order for later destruction
             factoryList.add (0, factory);
@@ -170,8 +179,9 @@
             }
         }
 
-        factoryList.clear();
-        factoryMap.clear();
+        this.factoryList.clear();
+        this.factoryMap.clear();
+        super.dispose();
     }
 
     /**
@@ -185,6 +195,6 @@
     public Factory getFactory (Class theClass) {
         // at this state the services map is read-only,
         // therefore we can go without synchronization
-        return ((Factory) factoryMap.get (theClass.getName()));
+        return ((Factory) this.factoryMap.get (theClass.getName()));
     }
 }

Added: cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/servlet/PortletServlet.java
URL: http://svn.apache.org/viewcvs/cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/servlet/PortletServlet.java?rev=348400&view=auto
==============================================================================
--- cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/servlet/PortletServlet.java (added)
+++ cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/servlet/PortletServlet.java Wed Nov 23 01:14:57 2005
@@ -0,0 +1,283 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.portal.pluto.servlet;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.portlet.ActionRequest;
+import javax.portlet.ActionResponse;
+import javax.portlet.Portlet;
+import javax.portlet.PortletConfig;
+import javax.portlet.PortletContext;
+import javax.portlet.PortletException;
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+import javax.portlet.UnavailableException;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.pluto.core.CoreUtils;
+import org.apache.pluto.core.InternalPortletRequest;
+import org.apache.pluto.core.InternalPortletResponse;
+import org.apache.pluto.factory.PortletObjectAccess;
+import org.apache.pluto.om.ControllerObjectAccess;
+import org.apache.pluto.om.portlet.PortletDefinition;
+import org.apache.pluto.om.portlet.PortletDefinitionCtrl;
+
+/**
+ * The wrapper servlet.
+ *
+ * @version $Id$
+ */
+public class PortletServlet extends HttpServlet {
+
+    public static final String PORTLET_DEFINITION = PortletServlet.class.getName() + "/portlet-definition";
+
+    protected ServletConfig config;
+    protected Map portlets = new HashMap();
+
+    /**
+     * @see javax.servlet.GenericServlet#init(javax.servlet.ServletConfig)
+     */
+    public void init(ServletConfig config) throws ServletException {
+        super.init(config);
+        this.config = config;
+    }
+
+    protected synchronized void init(PortletDefinition pd, HttpServletRequest request)
+    throws ServletException {
+        final String guid = pd.getId().toString();
+        PortletInfo info = (PortletInfo)this.portlets.get(guid);
+        if ( info == null ) {
+            info = new PortletInfo();
+            try {
+                info.portlet = (Portlet)Thread.currentThread().getContextClassLoader().loadClass(pd.getClassName()).newInstance();
+            } catch (ClassNotFoundException e) {
+                throw new ServletException(e);
+            } catch (IllegalAccessException e) {
+                throw new ServletException(e);
+            } catch (InstantiationException e) {
+                throw new ServletException(e);
+            }
+            // TBD - I should not use
+            PortletDefinitionCtrl portletDefCtrl = (PortletDefinitionCtrl)ControllerObjectAccess.get(pd);
+            portletDefCtrl.setPortletClassLoader(Thread.currentThread().getContextClassLoader());
+    
+            info.context = PortletObjectAccess.getPortletContext(this.config.getServletContext(),
+                                                                   pd.getPortletApplicationDefinition());
+            info.config = PortletObjectAccess.getPortletConfig(this.config, 
+                                                               info.context,
+                                                               pd);
+
+            try {
+                info.portlet.init(info.config);
+            } catch (PortletException e) {
+                throw new ServletException(e);
+            }
+            this.portlets.put(guid, info);
+        }
+    }
+
+    /**
+     * @see javax.servlet.http.HttpServlet#getLastModified(javax.servlet.http.HttpServletRequest)
+     */
+    protected long getLastModified(HttpServletRequest req) {
+        return -1;
+    }
+
+    /**
+     * @see javax.servlet.http.HttpServlet#service(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
+     */
+    public final void service(ServletRequest request, ServletResponse response)
+    throws ServletException, IOException {
+        super.service(request,response);
+    }
+
+    /**
+     * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+     */
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
+    throws ServletException, IOException {
+        dispatch(req,resp);
+    }
+
+    /**
+     * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+     */
+    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
+    throws ServletException, IOException {
+        dispatch(req,resp);
+    }
+
+    /**
+     * @see javax.servlet.http.HttpServlet#doPut(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+     */
+    protected void doPut(HttpServletRequest req, HttpServletResponse resp)
+    throws ServletException, IOException {
+        dispatch(req,resp);
+    }
+
+    /**
+     * @see javax.servlet.http.HttpServlet#doDelete(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+     */
+    protected void doDelete(HttpServletRequest req, HttpServletResponse resp)
+    throws ServletException, IOException {
+        super.doDelete(req,resp);
+    }
+
+    /**
+     * @see javax.servlet.http.HttpServlet#doOptions(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+     */
+    protected void doOptions(HttpServletRequest req, HttpServletResponse resp)
+    throws ServletException, IOException {
+        super.doOptions(req,resp);
+    }
+
+    /**
+     * @see javax.servlet.http.HttpServlet#doTrace(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+     */
+    protected void doTrace(HttpServletRequest req, HttpServletResponse resp)
+    throws ServletException, IOException {
+        super.doTrace(req,resp);
+    }
+
+    /**
+     * @see javax.servlet.GenericServlet#destroy()
+     */
+    public void destroy() {
+        synchronized (this.portlets) {
+            final Iterator i = this.portlets.values().iterator();
+            while (i.hasNext()) {
+                final PortletInfo info = (PortletInfo)i.next();
+                try {
+                    info.portlet.destroy();
+                } catch (Throwable ignore) {
+                    // we just ignore this
+                }
+            }
+            this.portlets.clear();
+        }
+        super.destroy();
+    }
+
+    /**
+     * Dispatcher.
+     * @param request
+     * @param response
+     * @throws ServletException
+     * @throws IOException
+     */
+    protected void dispatch(HttpServletRequest request, HttpServletResponse response)
+    throws ServletException, IOException {
+        final PortletDefinition pd = (PortletDefinition)request.getAttribute(PORTLET_DEFINITION);
+        final Integer method_id = (Integer)request.getAttribute(org.apache.pluto.Constants.METHOD_ID);
+        if (method_id == org.apache.pluto.Constants.METHOD_NOOP ) {
+            this.init(pd, request);
+            return;
+        }
+        final PortletInfo info = (PortletInfo)this.portlets.get(pd.getId().toString());
+        if (info == null) {
+            throw new ServletException("The portlet '" + pd.getId() + "' is not initialized.");
+        }
+        try {
+            // fill attribute, so that JSPs/servlets can access the config
+            request.setAttribute(org.apache.pluto.Constants.PORTLET_CONFIG, info.config);
+
+            if (method_id == org.apache.pluto.Constants.METHOD_RENDER) {
+                RenderRequest renderRequest = (RenderRequest)request.getAttribute(org.apache.pluto.Constants.PORTLET_REQUEST);
+                RenderResponse renderResponse = (RenderResponse)request.getAttribute(org.apache.pluto.Constants.PORTLET_RESPONSE);
+
+                // prepare container objects to run in this webModule
+                prepareRenderRequest(renderRequest, request);
+                prepareRenderResponse(renderResponse, request, response);
+
+                info.portlet.render(renderRequest,renderResponse);
+            } else if (method_id==org.apache.pluto.Constants.METHOD_ACTION) {
+                ActionRequest actionRequest = (ActionRequest)request.getAttribute(org.apache.pluto.Constants.PORTLET_REQUEST);
+                ActionResponse actionResponse = (ActionResponse)request.getAttribute(org.apache.pluto.Constants.PORTLET_RESPONSE);
+
+                // prepare container objects to run in this webModule
+                prepareActionRequest(actionRequest, request);
+                prepareActionResponse(actionResponse, request, response);
+
+                info.portlet.processAction(actionRequest,actionResponse);
+            }
+        } catch (UnavailableException e) {
+            // destroy isn't called by Tomcat, so we have to fix it
+            this.portlets.remove(pd.getId().toString());
+            try {
+                info.portlet.destroy();
+            } catch (Throwable t) {
+                // don't care for Exception
+            }
+
+            // handle everything as permanently for now
+            throw new javax.servlet.UnavailableException(e.getMessage());
+        } catch (PortletException e) {
+            throw new ServletException(e);
+        } finally {
+            request.removeAttribute(org.apache.pluto.Constants.PORTLET_CONFIG);
+        }
+    }
+
+    protected void prepareActionRequest(ActionRequest portletRequest,
+                                      HttpServletRequest servletRequest) {
+        InternalPortletRequest internalPortletRequest = 
+        CoreUtils.getInternalRequest(portletRequest);
+
+        internalPortletRequest.lateInit(servletRequest);
+    }
+
+    protected void prepareRenderRequest(RenderRequest portletRequest,
+                                      HttpServletRequest servletRequest) {
+        InternalPortletRequest internalPortletRequest = 
+        CoreUtils.getInternalRequest(portletRequest);
+
+        internalPortletRequest.lateInit(servletRequest);
+    }
+
+    protected void prepareRenderResponse(RenderResponse portletResponse,
+                                       HttpServletRequest servletRequest,
+                                       HttpServletResponse servletResponse) {
+        InternalPortletResponse internalPortletResponse = 
+        CoreUtils.getInternalResponse(portletResponse);
+
+        internalPortletResponse.lateInit(servletRequest, servletResponse);
+    }
+
+    protected void prepareActionResponse(ActionResponse portletResponse,
+                                       HttpServletRequest servletRequest,
+                                       HttpServletResponse servletResponse) {
+        InternalPortletResponse internalPortletResponse = 
+        CoreUtils.getInternalResponse(portletResponse);
+
+        internalPortletResponse.lateInit(servletRequest, servletResponse);
+    }
+
+    protected final static class PortletInfo {
+        public Portlet portlet;
+        public PortletContext context;
+        public PortletConfig config;
+    }
+}

Propchange: cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/servlet/PortletServlet.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/pluto/servlet/PortletServlet.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/profile/impl/GroupBasedProfileManager.java
URL: http://svn.apache.org/viewcvs/cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/profile/impl/GroupBasedProfileManager.java?rev=348400&r1=348399&r2=348400&view=diff
==============================================================================
--- cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/profile/impl/GroupBasedProfileManager.java (original)
+++ cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/profile/impl/GroupBasedProfileManager.java Wed Nov 23 01:14:57 2005
@@ -38,6 +38,7 @@
 import org.apache.cocoon.portal.coplet.CopletInstanceData;
 import org.apache.cocoon.portal.coplet.adapter.CopletAdapter;
 import org.apache.cocoon.portal.event.Receiver;
+import org.apache.cocoon.portal.event.coplet.CopletDataAddedEvent;
 import org.apache.cocoon.portal.event.coplet.CopletInstanceDataAddedEvent;
 import org.apache.cocoon.portal.event.coplet.CopletInstanceDataRemovedEvent;
 import org.apache.cocoon.portal.layout.Layout;
@@ -272,6 +273,15 @@
     public void inform(CopletInstanceDataAddedEvent event, PortalService service) {
         final ProfileImpl profile = this.getUserProfile(null);
         profile.add((CopletInstanceData) event.getTarget());
+    }
+
+    /**
+     * Receives a coplet data added event.
+     * @see Receiver
+     */
+    public void inform(CopletDataAddedEvent event, PortalService service) {
+        final ProfileImpl profile = this.getUserProfile(null);
+        profile.add((CopletData) event.getTarget());
     }
 
     /**

Modified: cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/source/CopletSourceFactory.java
URL: http://svn.apache.org/viewcvs/cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/source/CopletSourceFactory.java?rev=348400&r1=348399&r2=348400&view=diff
==============================================================================
--- cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/source/CopletSourceFactory.java (original)
+++ cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/source/CopletSourceFactory.java Wed Nov 23 01:14:57 2005
@@ -19,16 +19,10 @@
 import java.net.MalformedURLException;
 import java.util.Map;
 
-import org.apache.avalon.framework.context.Context;
 import org.apache.avalon.framework.context.ContextException;
-import org.apache.avalon.framework.context.Contextualizable;
-import org.apache.avalon.framework.logger.AbstractLogEnabled;
 import org.apache.avalon.framework.service.ServiceException;
-import org.apache.avalon.framework.service.ServiceManager;
-import org.apache.avalon.framework.service.Serviceable;
-import org.apache.avalon.framework.thread.ThreadSafe;
-import org.apache.cocoon.portal.PortalService;
 import org.apache.cocoon.portal.coplet.CopletInstanceData;
+import org.apache.cocoon.portal.impl.AbstractComponent;
 import org.apache.excalibur.source.Source;
 import org.apache.excalibur.source.SourceException;
 import org.apache.excalibur.source.SourceFactory;
@@ -39,25 +33,8 @@
  * @version $Id$
  */
 public class CopletSourceFactory     
-    extends AbstractLogEnabled
-    implements SourceFactory, Serviceable, ThreadSafe, Contextualizable {
-
-    protected ServiceManager manager;
-    protected Context context;
-
-    /**
-     * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
-     */
-    public void service(ServiceManager serviceManager) throws ServiceException {
-        this.manager = serviceManager;
-    }
-
-    /**
-     * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
-     */
-    public void contextualize(Context context) throws ContextException {
-        this.context = context;
-    }
+    extends AbstractComponent
+    implements SourceFactory {
 
 	/**
 	 * @see org.apache.excalibur.source.SourceFactory#getSource(String, Map)
@@ -74,10 +51,8 @@
             protocol = location.substring(0, position);
             location = location.substring(position+2);
         }
-        PortalService service = null;
         try {
-            service = (PortalService)this.manager.lookup(PortalService.ROLE);
-            CopletInstanceData coplet = service.getComponentManager().getProfileManager().getCopletInstanceData(location);
+            CopletInstanceData coplet = this.portalService.getComponentManager().getProfileManager().getCopletInstanceData(location);
             if ( coplet == null ) {
                 throw new IOException("Unable to get coplet for " + location);
             }
@@ -88,11 +63,9 @@
             copletSource.service(this.manager);
             return copletSource;
         } catch (ContextException ce) {
-            throw new SourceException("Unable to lookup profile manager.", ce);
+            throw new SourceException("Unable to setup coplet source.", ce);
         } catch (ServiceException ce) {
-            throw new SourceException("Unable to lookup profile manager.", ce);
-        } finally {
-            this.manager.release(service);
+            throw new SourceException("Unable to setup coplet source.", ce);
         }
 	}
 

Modified: cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/transformation/HTMLEventLinkTransformer.java
URL: http://svn.apache.org/viewcvs/cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/transformation/HTMLEventLinkTransformer.java?rev=348400&r1=348399&r2=348400&view=diff
==============================================================================
--- cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/transformation/HTMLEventLinkTransformer.java (original)
+++ cocoon/blocks/portal/trunk/java/org/apache/cocoon/portal/transformation/HTMLEventLinkTransformer.java Wed Nov 23 01:14:57 2005
@@ -78,8 +78,12 @@
                 processed = true;
             }
         } else if ("form".equals(name) ) {
-            this.createFormEvent(attr);
-            processed = true;
+            boolean convert = this.isExternalForm(attr);
+            this.stack.push(convert ? Boolean.TRUE: Boolean.FALSE);
+            if ( convert ) {
+                this.createFormEvent(attr);
+                processed = true;
+            }
         }
         if ( !processed ) {
             super.startElement(uri, name, raw, attr);
@@ -102,11 +106,14 @@
                 processed = true;
             }
         } else if ( "form".equals(name) ) {
-            this.xmlConsumer.endElement(CopletTransformer.NAMESPACE_URI,
-                    CopletTransformer.LINK_ELEM,
-                    "coplet:" + CopletTransformer.LINK_ELEM);
-            this.xmlConsumer.endPrefixMapping("coplet");
-            processed = true;
+            final Boolean converted = (Boolean)this.stack.pop();
+            if ( converted.booleanValue() ) {
+                this.xmlConsumer.endElement(CopletTransformer.NAMESPACE_URI,
+                        CopletTransformer.LINK_ELEM,
+                        "coplet:" + CopletTransformer.LINK_ELEM);
+                this.xmlConsumer.endPrefixMapping("coplet");
+                processed = true;
+            }
         }
         if ( !processed ) {
             super.endElement(uri, name, raw);
@@ -185,9 +192,10 @@
     }
 
     /**
-     * a link in an external application is not transformed
+     * Is this link an external link?
+     * A link in an external application is not transformed
      * if there is an attribute external="true" in the link-element
-     * or if the link starts with "mailto:".
+     * or if the link starts with "mailto:" or "javascript:".
      * 
      * @param attributes attributes of the node
      * @return true if the attribute 'external' is 'true'
@@ -202,6 +210,30 @@
         final String link = attributes.getValue("href");
         if ( link != null 
              && (link.startsWith("mailto:") || link.startsWith("javascript:") ) ) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Does this form contain an external action?
+     * A form is not transformed if there is an attribute
+     * external="true" in the form action or if the action
+     * starts with "javascript:".
+     * 
+     * @param attributes attributes of the node
+     * @return True if the action is external.
+     */
+    private boolean isExternalForm(Attributes attributes) {        
+        final String external = attributes.getValue("external");
+        // links to external documents will be not transformed to portal links
+        if (external != null && external.trim().length() > 0 
+            && external.trim().toLowerCase().equals ("true") ) {            
+            return true;
+        }
+        final String link = attributes.getValue("action");
+        if ( link != null 
+             && link.startsWith("javascript:") ) {
             return true;
         }
         return false;

Modified: cocoon/blocks/portal/trunk/status.xml
URL: http://svn.apache.org/viewcvs/cocoon/blocks/portal/trunk/status.xml?rev=348400&r1=348399&r2=348400&view=diff
==============================================================================
--- cocoon/blocks/portal/trunk/status.xml (original)
+++ cocoon/blocks/portal/trunk/status.xml Wed Nov 23 01:14:57 2005
@@ -66,6 +66,12 @@
  <changes>
   <release version="@version@" date="@date@">
     <action dev="CZ" type="add">
+      Implement (hot)deployment for JSR 168 portlets.
+    </action>
+    <action dev="CZ" type="add">
+      Support external form actions in HTML transformation.
+    </action>
+    <action dev="CZ" type="add">
       Add deployment infrastructure.
     </action>
     <action dev="CZ" type="add" fixes-bug="COCOON-1674">



Mime
View raw message