You are viewing a plain text version of this content. The canonical link for it is here.
Posted to pluto-scm@portals.apache.org by ms...@apache.org on 2015/01/28 15:42:42 UTC

[07/14] portals-pluto git commit: Added version 3 demo portlet

Added version 3 demo portlet


Project: http://git-wip-us.apache.org/repos/asf/portals-pluto/repo
Commit: http://git-wip-us.apache.org/repos/asf/portals-pluto/commit/cea47a7c
Tree: http://git-wip-us.apache.org/repos/asf/portals-pluto/tree/cea47a7c
Diff: http://git-wip-us.apache.org/repos/asf/portals-pluto/diff/cea47a7c

Branch: refs/heads/V3Prototype
Commit: cea47a7c6b1744ec877be7ba0b8b09d2fcbcbe3d
Parents: 65df9c6
Author: Scott Nicklous <ms...@apache.org>
Authored: Wed Jan 28 10:21:41 2015 +0100
Committer: Scott Nicklous <ms...@apache.org>
Committed: Wed Jan 28 10:21:41 2015 +0100

----------------------------------------------------------------------
 PortletV3Demo/pom.xml                           | 154 ++++++++++++++
 .../java/basic/portlet/ColorSelPortlet.java     | 106 ++++++++++
 .../src/main/java/basic/portlet/Constants.java  |  53 +++++
 .../java/basic/portlet/ImageSelPortlet.java     | 105 ++++++++++
 .../java/basic/portlet/MessageBoxPortlet.java   | 168 ++++++++++++++++
 .../basic/portlet/PartialActionPortlet.java     | 114 +++++++++++
 .../java/basic/portlet/ResourcePortlet.java     | 130 ++++++++++++
 .../src/main/resources/logging.properties       |  37 ++++
 .../src/main/webapp/WEB-INF/jsp/view-csp.jsp    | 201 +++++++++++++++++++
 .../src/main/webapp/WEB-INF/jsp/view-isp.jsp    | 178 ++++++++++++++++
 .../src/main/webapp/WEB-INF/jsp/view-ivp.jsp    | 161 +++++++++++++++
 .../src/main/webapp/WEB-INF/jsp/view-mbp.jsp    |  89 ++++++++
 .../src/main/webapp/WEB-INF/jsp/view-pap.jsp    | 108 ++++++++++
 .../src/main/webapp/WEB-INF/portlet.xml         | 129 ++++++++++++
 PortletV3Demo/src/main/webapp/WEB-INF/web.xml   |   4 +
 .../src/main/webapp/resources/css/styles.css    |  16 ++
 .../main/webapp/resources/images/FullMoon.gif   | Bin 0 -> 38190 bytes
 .../webapp/resources/images/baseball-trans.gif  | Bin 0 -> 8307 bytes
 .../webapp/resources/images/fussball-trans.gif  | Bin 0 -> 8733 bytes
 .../webapp/resources/images/golfball-trans.gif  | Bin 0 -> 9359 bytes
 pom.xml                                         |   1 +
 21 files changed, 1754 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/cea47a7c/PortletV3Demo/pom.xml
----------------------------------------------------------------------
diff --git a/PortletV3Demo/pom.xml b/PortletV3Demo/pom.xml
new file mode 100644
index 0000000..3ff5884
--- /dev/null
+++ b/PortletV3Demo/pom.xml
@@ -0,0 +1,154 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+   <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.portals.pluto</groupId>
+        <artifactId>pluto</artifactId>
+        <version>3.0-SNAPSHOT</version>
+    </parent>
+
+   <artifactId>PortletV3Demo</artifactId>
+   <packaging>war</packaging>
+
+   <dependencies>
+      <dependency>
+        <groupId>org.apache.portals.pluto</groupId>
+        <artifactId>portlet-api</artifactId>
+        <version>${project.version}</version>
+        <scope>provided</scope>
+      </dependency>
+      <dependency>
+         <groupId>org.apache.tomcat</groupId>
+         <artifactId>tomcat-servlet-api</artifactId>
+         <scope>provided</scope>
+      </dependency>
+
+      <!-- for eclipse JSP tooling purposes -->
+      <dependency>
+         <groupId>javax.servlet.jsp</groupId>
+         <artifactId>jsp-api</artifactId>
+         <version>2.1</version>
+         <scope>provided</scope>
+      </dependency>
+      <dependency>
+         <groupId>org.apache.taglibs</groupId>
+         <artifactId>taglibs-standard-spec</artifactId>
+         <scope>provided</scope>
+      </dependency>
+      <dependency>
+          <groupId>org.apache.taglibs</groupId>
+          <artifactId>taglibs-standard-impl</artifactId>
+          <scope>provided</scope>
+      </dependency>
+      <dependency>
+          <groupId>org.apache.taglibs</groupId>
+          <artifactId>taglibs-standard-jstlel</artifactId>
+          <scope>provided</scope>
+      </dependency>
+      <dependency>
+         <groupId>org.apache.portals.pluto</groupId>
+         <artifactId>pluto-taglib</artifactId>
+         <version>2.1.0-M3</version>
+         <scope>provided</scope>
+      </dependency>
+   </dependencies>
+
+   <build>
+      <finalName>PortletV3Demo</finalName>
+      <plugins>
+         <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-compiler-plugin</artifactId>
+            <configuration>
+               <source>1.6</source>
+               <target>1.6</target>
+            </configuration>
+         </plugin>
+         <plugin>
+            <artifactId>maven-war-plugin</artifactId>
+            <configuration>
+               <archiveClasses>false</archiveClasses>
+            </configuration>
+         </plugin>
+      </plugins>
+   </build>
+
+   <profiles>
+      <profile>
+         <id>pluto</id>
+         <activation>
+           <property>
+             <name>!alwaysActivate</name>
+           </property>
+         </activation>
+    
+         <dependencies>
+            <dependency>
+                <groupId>org.apache.taglibs</groupId>
+                <artifactId>taglibs-standard-spec</artifactId>
+                <scope>compile</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.taglibs</groupId>
+                <artifactId>taglibs-standard-impl</artifactId>
+                <scope>compile</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.taglibs</groupId>
+                <artifactId>taglibs-standard-jstlel</artifactId>
+                <scope>compile</scope>
+            </dependency>
+         </dependencies>
+         
+         <build>
+            <plugins>
+               <plugin>
+                 <artifactId>maven-war-plugin</artifactId>
+                 <configuration>
+                   <archiveClasses>false</archiveClasses>
+                   <webXml>${project.build.directory}/pluto-resources/web.xml</webXml>
+                 </configuration>
+               </plugin>
+               <!-- bind 'pluto:assemble' goal to 'generate-resources' lifecycle -->
+               <plugin>
+                  <groupId>org.apache.portals.pluto</groupId>
+                  <artifactId>maven-pluto-plugin</artifactId>
+                  <dependencies>
+                     <dependency>
+                        <groupId>org.apache.portals.pluto</groupId>
+                        <artifactId>pluto-util</artifactId>
+                        <version>${project.version}</version>
+                        <scope>runtime</scope>
+                     </dependency>
+                  </dependencies>
+                  <executions>
+                     <execution>
+                        <phase>generate-resources</phase>
+                        <goals>
+                           <goal>assemble</goal>
+                        </goals>
+                     </execution>
+                  </executions>
+               </plugin>
+               <!-- workaround for war processing of m-r-r-plugin causing the generated NOTICE and LICENSE file to be put under WEB-INF/classes/META-INF -->
+               <plugin>
+                   <groupId>org.apache.maven.plugins</groupId>
+                   <artifactId>maven-remote-resources-plugin</artifactId>
+                   <executions>
+                       <execution>
+                           <goals>
+                               <goal>process</goal>
+                           </goals>
+                           <configuration>
+                               <outputDirectory>${project.build.directory}/${project.build.finalName}</outputDirectory>
+                               <attached>false</attached>
+                           </configuration>
+                       </execution>
+                   </executions>
+               </plugin>
+            </plugins>
+         </build>
+      </profile>
+   </profiles>
+
+</project>

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/cea47a7c/PortletV3Demo/src/main/java/basic/portlet/ColorSelPortlet.java
----------------------------------------------------------------------
diff --git a/PortletV3Demo/src/main/java/basic/portlet/ColorSelPortlet.java b/PortletV3Demo/src/main/java/basic/portlet/ColorSelPortlet.java
new file mode 100644
index 0000000..326191c
--- /dev/null
+++ b/PortletV3Demo/src/main/java/basic/portlet/ColorSelPortlet.java
@@ -0,0 +1,106 @@
+/*  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 basic.portlet;
+
+import static basic.portlet.Constants.*;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.portlet.ActionRequest;
+import javax.portlet.ActionResponse;
+import javax.portlet.GenericPortlet;
+import javax.portlet.PortletException;
+import javax.portlet.PortletRequestDispatcher;
+import javax.portlet.PortletURL;
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+import javax.portlet.ResourceRequest;
+import javax.portlet.ResourceResponse;
+import javax.xml.namespace.QName;
+
+
+/**
+ * A management portlet that displays the current deep link configuration
+ */
+public class ColorSelPortlet extends GenericPortlet {
+
+   // Set up logging
+   // private static final String LOG_CLASS = ColorSelPortlet.class.getName();
+   // private final Logger logger = Logger.getLogger(LOG_CLASS);
+
+   protected void doView(RenderRequest req, RenderResponse resp)
+         throws PortletException, IOException {
+
+      
+      resp.setContentType("text/html");
+
+      PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher(
+            "/WEB-INF/jsp/view-csp.jsp");
+         rd.include(req, resp);
+      
+}
+   
+   /* (non-Javadoc)
+    * @see javax.portlet.GenericPortlet#serveResource(javax.portlet.ResourceRequest, javax.portlet.ResourceResponse)
+    */
+   @Override
+   public void serveResource(ResourceRequest req, ResourceResponse resp)
+         throws PortletException, IOException {
+   }
+
+   public void processAction(ActionRequest req, ActionResponse resp)
+         throws PortletException, IOException {
+            
+      String[] vals = req.getParameterValues(PARAM_FG_COLOR);
+      String r = "0";
+      String g = "0";
+      String b = "0";
+      if (vals != null) {
+         for (String v : vals) {
+            if (v.equals(PARAM_FG_RED)) r = "F";
+            if (v.equals(PARAM_FG_GREEN)) g = "F";
+            if (v.equals(PARAM_FG_BLUE)) b = "F";
+         }
+      }
+      String clr = "#" + r + g + b;
+      
+      // make sure the private parameter are all on the URL for 
+      // potential back button support
+      if (vals != null) {
+         resp.setRenderParameter(PARAM_FG_COLOR, vals);
+      }
+      
+      String val = req.getParameter(PARAM_SUBTYPE);
+      if (val != null) {
+         resp.setRenderParameter(PARAM_SUBTYPE, val);
+      }
+      
+      val = req.getParameter(PARAM_MSG_INPUT);
+      if (val != null) {
+         resp.setRenderParameter(PARAM_MSG_INPUT, val);
+      }
+      
+      String msg = val + DELIM + clr;
+      QName qn = new QName(EVENT_NAMESPACE, EVENT_NAME);
+      resp.setEvent(qn, msg);
+      
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/cea47a7c/PortletV3Demo/src/main/java/basic/portlet/Constants.java
----------------------------------------------------------------------
diff --git a/PortletV3Demo/src/main/java/basic/portlet/Constants.java b/PortletV3Demo/src/main/java/basic/portlet/Constants.java
new file mode 100644
index 0000000..faf5092
--- /dev/null
+++ b/PortletV3Demo/src/main/java/basic/portlet/Constants.java
@@ -0,0 +1,53 @@
+package basic.portlet;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class Constants {
+   
+   // maps the names of the images to the paths to the images -
+   public final static Map<String, String> imgMap = new HashMap<String, String>() {
+      private static final long serialVersionUID = 1L;
+   {
+      put("baseball", "/resources/images/baseball-trans.gif");
+      put("golfball", "/resources/images/golfball-trans.gif");
+      put("fussball", "/resources/images/fussball-trans.gif");
+   }};
+
+   public final static String DEFAULT_IMAGE = "/resources/images/FullMoon.gif";
+
+   public final static String PARAM_SELTYPE = "selType";
+   public final static String PARAM_SELTYPE_RADIO = "radio";
+   public final static String PARAM_SELTYPE_DROPDOWN = "dropdown";
+   
+   // privae parameter for color selection portlet
+   public final static String PARAM_SUBTYPE = "subType";
+   public final static String PARAM_SUBTYPE_URL = "URL";
+   public final static String PARAM_SUBTYPE_FORM = "form";
+   
+   public final static String PARAM_IMGNAME = "photo";
+   public final static String PARAM_COLOR = "color";
+   public final static String PARAM_ERRMSG = "errmsg";
+   public final static String PARAM_BORDER = "bo";
+   public final static String PARAM_BORDER_COLOR = "border";
+   public final static String PARAM_CACHE = "ca";
+   public final static String PARAM_CACHE_PAGE = "pa";
+   public final static String PARAM_CACHE_PORTLET = "po";
+   public final static String PARAM_CACHE_FULL = "fu";
+   
+   public final static String PARAM_FG_COLOR = "fgcolor";
+   public final static String PARAM_FG_RED = "red";
+   public final static String PARAM_FG_GREEN = "green";
+   public final static String PARAM_FG_BLUE = "blue";
+   public final static String PARAM_MSG_INPUT = "imsg";
+   
+   public final static String PARAM_NUM_ACTIONS = "numActions";
+
+   public final static String PARAM_NUM_MSGS = "numMsgs";
+   public final static String ATTRIB_MSGS = "msgs";
+   
+   public final static String EVENT_NAMESPACE = "http://www.apache.org/portals/pluto/pub-render-params/ResourcePortlet";
+   public final static String EVENT_NAME = "Message";
+   
+   public final static String DELIM = ";%;";
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/cea47a7c/PortletV3Demo/src/main/java/basic/portlet/ImageSelPortlet.java
----------------------------------------------------------------------
diff --git a/PortletV3Demo/src/main/java/basic/portlet/ImageSelPortlet.java b/PortletV3Demo/src/main/java/basic/portlet/ImageSelPortlet.java
new file mode 100644
index 0000000..4475ebb
--- /dev/null
+++ b/PortletV3Demo/src/main/java/basic/portlet/ImageSelPortlet.java
@@ -0,0 +1,105 @@
+/*  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 basic.portlet;
+
+import static basic.portlet.Constants.PARAM_IMGNAME;
+import static basic.portlet.Constants.PARAM_SELTYPE;
+import static basic.portlet.Constants.PARAM_SELTYPE_RADIO;
+import static basic.portlet.Constants.imgMap;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.portlet.ActionRequest;
+import javax.portlet.ActionResponse;
+import javax.portlet.GenericPortlet;
+import javax.portlet.PortletException;
+import javax.portlet.PortletRequestDispatcher;
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+import javax.portlet.ResourceRequest;
+import javax.portlet.ResourceResponse;
+
+
+/**
+ * A management portlet that displays the current deep link configuraion
+ */
+public class ImageSelPortlet extends GenericPortlet {
+
+   // Set up logging
+   private static final String LOG_CLASS = ImageSelPortlet.class.getName();
+   private final Logger logger = Logger.getLogger(LOG_CLASS);
+
+   protected void doView(RenderRequest req, RenderResponse resp)
+         throws PortletException, IOException {
+      
+      if (logger.isLoggable(Level.FINE)) {
+         logger.logp(Level.FINE, this.getClass().getName(), "doView", "Entry");
+      }
+      
+      resp.setContentType("text/html");
+
+      PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher(
+            "/WEB-INF/jsp/view-isp.jsp");
+      rd.include(req, resp);
+
+   }
+   
+   /* (non-Javadoc)
+    * @see javax.portlet.GenericPortlet#serveResource(javax.portlet.ResourceRequest, javax.portlet.ResourceResponse)
+    */
+   @Override
+   public void serveResource(ResourceRequest req, ResourceResponse resp)
+         throws PortletException, IOException {
+
+	      resp.setContentType("text/html");
+	      PrintWriter writer = resp.getWriter();
+
+	      String pid = resp.getNamespace();
+	      Set<String> names = imgMap.keySet();
+	      String selType = req.getParameter(PARAM_SELTYPE);
+	      selType = (selType == null) ? PARAM_SELTYPE_RADIO : selType;
+	      String imgName = req.getParameter(PARAM_IMGNAME);
+	      imgName = (imgName == null) ? "default" : imgName;
+
+	      if (selType.equals(PARAM_SELTYPE_RADIO)) {
+	         for (String name : names) {
+	            writer.write("   <input type='radio' name='" + PARAM_IMGNAME + "' value='" + 
+	               name + "'" + (name.equals(imgName) ? "checked" : "") + ">" + name);
+	         }
+	      } else {
+	         writer.write("<select id='" + pid + "-selBox' name='" + PARAM_IMGNAME + "' size='1'>");
+	         writer.write("   <option value='default' " + 
+	               ("default".equals(imgName) ? "selected" : "") + ">-</option>");
+	         for (String name : names) {
+	            writer.write("   <option value='" + name + "'" + 
+	               (name.equals(imgName) ? "selected" : "") + ">" + name + "</option>");
+	         }
+	         writer.write("</select>");
+	      }
+	}
+
+   public void processAction(ActionRequest req, ActionResponse resp)
+         throws PortletException, IOException {
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/cea47a7c/PortletV3Demo/src/main/java/basic/portlet/MessageBoxPortlet.java
----------------------------------------------------------------------
diff --git a/PortletV3Demo/src/main/java/basic/portlet/MessageBoxPortlet.java b/PortletV3Demo/src/main/java/basic/portlet/MessageBoxPortlet.java
new file mode 100644
index 0000000..232b696
--- /dev/null
+++ b/PortletV3Demo/src/main/java/basic/portlet/MessageBoxPortlet.java
@@ -0,0 +1,168 @@
+/*  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 basic.portlet;
+
+import static basic.portlet.Constants.*;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.portlet.ActionRequest;
+import javax.portlet.ActionResponse;
+import javax.portlet.EventRequest;
+import javax.portlet.EventResponse;
+import javax.portlet.GenericPortlet;
+import javax.portlet.PortletContext;
+import javax.portlet.PortletException;
+import javax.portlet.PortletRequestDispatcher;
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+import javax.portlet.ResourceRequest;
+import javax.portlet.ResourceResponse;
+import javax.portlet.ResourceURL;
+
+/**
+ * A management portlet that displays the current deep link configuraion
+ */
+public class MessageBoxPortlet extends GenericPortlet {
+
+   // Set up logging
+   private static final String LOG_CLASS = MessageBoxPortlet.class.getName();
+   private final Logger logger = Logger.getLogger(LOG_CLASS);
+
+   protected void doView(RenderRequest req, RenderResponse resp)
+         throws PortletException, IOException {
+      
+      if (logger.isLoggable(Level.FINE)) {
+         logger.logp(Level.FINE, this.getClass().getName(), "doView", "Entry");
+      }
+      
+      resp.setContentType("text/html");
+
+      PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher(
+            "/WEB-INF/jsp/view-mbp.jsp");
+      rd.include(req, resp);
+
+   }
+
+   @Override
+   public void processAction(ActionRequest req, ActionResponse resp)
+         throws PortletException, IOException {
+
+      // the only action for this portlet is to reset the stored messages
+      
+      String actionName = req.getParameter("action");
+      logger.fine("MBP: Resetting messages. numMsgs = 0,  actionName = " + actionName);
+
+      ArrayList<String> msgs = new ArrayList<String>();
+      StringBuffer sb = new StringBuffer();
+      sb.append("<p style='margin:2px 5px 2px 5px; color:#00D;"
+            + " background-color:#AAF;'>");
+      sb.append("Reset - No messages.");
+      sb.append("</p>");
+      msgs.add(sb.toString());
+
+      resp.setRenderParameter(PARAM_NUM_MSGS, "0");
+      req.getPortletSession().setAttribute(ATTRIB_MSGS, msgs);
+   }
+   
+   @SuppressWarnings("unchecked")
+   @Override
+   public void processEvent(EventRequest req, EventResponse resp) 
+         throws PortletException ,IOException {
+      
+      ArrayList<String> msgs = (ArrayList<String>) req.getPortletSession().getAttribute(ATTRIB_MSGS);
+      if (msgs == null) {
+         msgs = new ArrayList<String>();
+      }
+      
+      String[] msg;
+      int numMsgs = 0;
+      try {
+         numMsgs = Integer.parseInt(req.getParameter(PARAM_NUM_MSGS));
+      } catch (Exception e) {}
+      
+      if (numMsgs == 0) {
+         msgs.clear();
+      }
+      
+      logger.fine("MBP: Processing message event. Current # messages = " + msgs.size());
+
+      try {
+         // Both pieces of info are transported in a delimted string rather than 
+         // an array since the Pluto impl doesn't seem to get along with array types as 
+         // event payload types.
+         String val = (String) req.getEvent().getValue();
+         msg = val.split(DELIM);
+      } catch (Exception e) {
+         msg = new String[2];
+         msg[0] = "error getting message from event.";
+         msg[1] = "#D00";
+      }
+      
+      String clr = req.getParameter(PARAM_COLOR);
+      clr = (clr == null) ? "#FFFFFF" : clr;
+      
+      StringBuffer sb = new StringBuffer();
+      sb.append("<p style='margin:2px 5px 2px 5px; color:" + msg[1] 
+            + "; background-color:" + clr + ";'>");
+      sb.append("" + (msgs.size() + 1) + ": " + msg[0]);
+      sb.append("</p>");
+      
+      msgs.add(sb.toString());
+      
+      logger.fine("Adding message: " + sb.toString());
+
+      resp.setRenderParameter(PARAM_NUM_MSGS, Integer.toString(msgs.size()));
+      req.getPortletSession().setAttribute(ATTRIB_MSGS, msgs);
+   };
+   
+   /* (non-Javadoc)
+    * @see javax.portlet.GenericPortlet#serveResource(javax.portlet.ResourceRequest, javax.portlet.ResourceResponse)
+    */
+   @SuppressWarnings("unchecked")
+   @Override
+   public void serveResource(ResourceRequest req, ResourceResponse resp)
+         throws PortletException, IOException {
+      
+      resp.setContentType("text/html");
+      PrintWriter writer = resp.getWriter();
+
+      ArrayList<String> msgs = (ArrayList<String>) req.getPortletSession().getAttribute(ATTRIB_MSGS);
+      if (msgs == null) {
+         msgs = new ArrayList<String>();
+         
+         StringBuffer sb = new StringBuffer();
+         sb.append("<p style='margin:0px 5px 0px 5px; color:#00D;"
+               + " background-color:#FFA;'>");
+         sb.append("No messages.");
+         sb.append("</p>");
+         msgs.add(sb.toString());
+      }
+
+      for (String msg : msgs) {
+         writer.write(msg);
+      }
+
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/cea47a7c/PortletV3Demo/src/main/java/basic/portlet/PartialActionPortlet.java
----------------------------------------------------------------------
diff --git a/PortletV3Demo/src/main/java/basic/portlet/PartialActionPortlet.java b/PortletV3Demo/src/main/java/basic/portlet/PartialActionPortlet.java
new file mode 100644
index 0000000..eb5b6cb
--- /dev/null
+++ b/PortletV3Demo/src/main/java/basic/portlet/PartialActionPortlet.java
@@ -0,0 +1,114 @@
+/*  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 basic.portlet;
+
+import static basic.portlet.Constants.*;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.portlet.ActionRequest;
+import javax.portlet.ActionResponse;
+import javax.portlet.EventRequest;
+import javax.portlet.EventResponse;
+import javax.portlet.GenericPortlet;
+import javax.portlet.PortletContext;
+import javax.portlet.PortletException;
+import javax.portlet.PortletRequestDispatcher;
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+import javax.portlet.ResourceRequest;
+import javax.portlet.ResourceResponse;
+import javax.portlet.ResourceURL;
+
+/**
+ * A management portlet that displays the current deep link configuraion
+ */
+public class PartialActionPortlet extends GenericPortlet {
+
+   // Set up logging
+   private static final String LOG_CLASS = PartialActionPortlet.class.getName();
+   private final Logger logger = Logger.getLogger(LOG_CLASS);
+
+   protected void doView(RenderRequest req, RenderResponse resp)
+         throws PortletException, IOException {
+      
+      if (logger.isLoggable(Level.FINE)) {
+         logger.logp(Level.FINE, this.getClass().getName(), "doView", "Entry");
+      }
+      
+      resp.setContentType("text/html");
+
+      PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher(
+            "/WEB-INF/jsp/view-pap.jsp");
+      rd.include(req, resp);
+
+   }
+
+   @Override
+   public void processAction(ActionRequest req, ActionResponse resp)
+         throws PortletException, IOException {
+
+      // the only action for this portlet is to increment the execition counter
+
+      String val = req.getParameter(PARAM_NUM_ACTIONS);
+      int na = 1;
+      if (val != null) {
+         try {
+            na = Integer.parseInt(val) + 1;
+         } catch (Exception e) {}
+      }
+      
+      String actionName = req.getParameter("action");
+      logger.fine("PAP: executing partial action. action number = " + na + ", name =  " + actionName);
+
+      resp.setRenderParameter(PARAM_NUM_ACTIONS, Integer.toString(na));
+   }
+   
+   @Override
+   public void processEvent(EventRequest req, EventResponse resp) 
+         throws PortletException ,IOException {
+   };
+   
+   /* (non-Javadoc)
+    * @see javax.portlet.GenericPortlet#serveResource(javax.portlet.ResourceRequest, javax.portlet.ResourceResponse)
+    */
+   @SuppressWarnings("unchecked")
+   @Override
+   public void serveResource(ResourceRequest req, ResourceResponse resp)
+         throws PortletException, IOException {
+      
+      resp.setContentType("text/html");
+      PrintWriter writer = resp.getWriter();
+
+      String num = req.getParameter(PARAM_NUM_ACTIONS);
+      num = (num == null) ? "error" : num;
+      
+      String pageState = req.getPageState();
+      
+      writer.write("<p>Partial Action has been executed " + num + " times.</p>\n");
+      writer.write(";#delimiter#;");
+      writer.write(pageState);
+      
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/cea47a7c/PortletV3Demo/src/main/java/basic/portlet/ResourcePortlet.java
----------------------------------------------------------------------
diff --git a/PortletV3Demo/src/main/java/basic/portlet/ResourcePortlet.java b/PortletV3Demo/src/main/java/basic/portlet/ResourcePortlet.java
new file mode 100644
index 0000000..f8bbbdd
--- /dev/null
+++ b/PortletV3Demo/src/main/java/basic/portlet/ResourcePortlet.java
@@ -0,0 +1,130 @@
+/*  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 basic.portlet;
+
+import static basic.portlet.Constants.PARAM_BORDER_COLOR;
+import static basic.portlet.Constants.PARAM_COLOR;
+import static basic.portlet.Constants.PARAM_IMGNAME;
+import static basic.portlet.Constants.imgMap;
+import static basic.portlet.Constants.DEFAULT_IMAGE;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.portlet.ActionRequest;
+import javax.portlet.ActionResponse;
+import javax.portlet.GenericPortlet;
+import javax.portlet.PortletException;
+import javax.portlet.PortletRequestDispatcher;
+import javax.portlet.PortletURL;
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+import javax.portlet.ResourceRequest;
+import javax.portlet.ResourceResponse;
+
+
+/**
+ * A management portlet that displays the current deep link configuraion
+ */
+public class ResourcePortlet extends GenericPortlet {
+
+   // Set up logging
+   private static final String LOG_CLASS = ResourcePortlet.class.getName();
+   private final Logger logger = Logger.getLogger(LOG_CLASS);
+
+
+   protected void doView(RenderRequest req, RenderResponse resp)
+         throws PortletException, IOException {
+      
+      if (logger.isLoggable(Level.FINE)) {
+         logger.logp(Level.FINE, this.getClass().getName(), "doView", "Entry");
+      }
+      
+      resp.setContentType("text/html");
+
+      PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher(
+         "/WEB-INF/jsp/view-ivp.jsp");
+      rd.include(req, resp);
+
+
+   }
+   
+   /* (non-Javadoc)
+    * @see javax.portlet.GenericPortlet#serveResource(javax.portlet.ResourceRequest, javax.portlet.ResourceResponse)
+    */
+   @Override
+   public void serveResource(ResourceRequest req, ResourceResponse resp)
+         throws PortletException, IOException {
+
+      String key = req.getParameter(PARAM_IMGNAME);
+      String imgDir = DEFAULT_IMAGE;
+      if ((key != null) && imgMap.containsKey(key)) {
+         imgDir = imgMap.get(key);
+      }
+      
+      String bc = req.getParameter(PARAM_BORDER_COLOR);
+      String imgStyle = "";
+      if (bc != null) {
+         imgStyle = " style='border:1px solid " + bc + ";' ";
+      }
+      
+      String ctx = req.getContextPath();
+      String ca = req.getCacheability();
+      
+      resp.setContentType("text/html");
+      PrintWriter writer = resp.getWriter();
+      
+      String clr = req.getParameter(PARAM_COLOR);
+      clr = (clr == null) ? "#FFFFFF" : clr;
+      
+      if (logger.isLoggable(Level.FINE)) {
+         logger.logp(Level.FINE, this.getClass().getName(), "serveResource", "photo=" + key + ", bgcolor=" + clr + ", border=" + bc);
+      }
+      
+      // add action button if cacheability allows -
+      PortletURL aurl = null;
+      String bmu = "<p>Action URL could not be created.</p>";
+      try {
+         aurl = resp.createActionURL();
+      } catch (Exception e) {}
+      if (aurl != null) {
+         bmu = "<form  METHOD='POST' ACTION='" + aurl + "'><input id='<portlet:namespace/>-clear' type='submit' name='action' value='Action' /></form>";
+      }
+
+      writer.write("<div style='background-color:" + clr + ";'>\n");
+      writer.write("   <table style='background-color:" + clr + ";'>");
+      writer.write("   <tr><td align='center' style='background-color:" + clr + ";'>");
+      writer.write("   <img src='" + ctx + imgDir + "'" + imgStyle + ">\n");
+      writer.write("   </td><td style='background-color:" + clr + ";'>");
+      writer.write("   <p>" + bmu + "</p>");
+      writer.write("   <p>Cacheability: " + ca + "</p>");
+      writer.write("   </td></tr>");
+      writer.write("   </table>");
+      writer.write("</div>\n");
+
+
+   }
+
+   public void processAction(ActionRequest req, ActionResponse resp)
+         throws PortletException, IOException {
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/cea47a7c/PortletV3Demo/src/main/resources/logging.properties
----------------------------------------------------------------------
diff --git a/PortletV3Demo/src/main/resources/logging.properties b/PortletV3Demo/src/main/resources/logging.properties
new file mode 100644
index 0000000..42a1f93
--- /dev/null
+++ b/PortletV3Demo/src/main/resources/logging.properties
@@ -0,0 +1,37 @@
+# 
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+
+handlers = org.apache.juli.FileHandler
+
+############################################################
+#
+# JDK 1.4+ logging handler specific properties for Pluto portal
+# using Tomcat's custom implementation of LogManager.
+# Logging level can be set to any one of:
+# SEVERE, WARN, INFO, CONFIG, FINE, FINEST or ALL. 
+# See the Tomcat documentation for more details.
+# 
+############################################################
+
+org.apache.juli.FileHandler.level = FINE
+org.apache.juli.FileHandler.directory = ${catalina.base}/logs
+#Log file will be named pluto.<yyyy-mm-dd>.log
+org.apache.juli.FileHandler.prefix = PortletV3Demo.
+
+org.apache.pluto.level=FINEST
+basic.portlet.level=FINEST

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/cea47a7c/PortletV3Demo/src/main/webapp/WEB-INF/jsp/view-csp.jsp
----------------------------------------------------------------------
diff --git a/PortletV3Demo/src/main/webapp/WEB-INF/jsp/view-csp.jsp b/PortletV3Demo/src/main/webapp/WEB-INF/jsp/view-csp.jsp
new file mode 100644
index 0000000..11c0475
--- /dev/null
+++ b/PortletV3Demo/src/main/webapp/WEB-INF/jsp/view-csp.jsp
@@ -0,0 +1,201 @@
+<%--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You 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.
+--%>
+<%@ page session="false" %>
+<%@ taglib uri="http://java.sun.com/portlet_2_0"  prefix="portlet" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+<%@ page import="static basic.portlet.Constants.*" %>
+
+<portlet:defineObjects />
+
+<h3>Color Selector &amp; Message Sender</h3><hr/>
+      
+<%      
+   String clr = renderRequest.getParameter(PARAM_COLOR);
+   clr = (clr == null) ? "#FFFFFF" : clr;
+   
+   String[] vals = renderRequest.getParameterValues(PARAM_FG_COLOR);
+   String r = "";
+   String g = "";
+   String b = "";
+   if (vals != null) {
+      for (String v : vals) {
+         if (v.equals(PARAM_FG_RED)) r = "checked";
+         if (v.equals(PARAM_FG_GREEN)) g = "checked";
+         if (v.equals(PARAM_FG_BLUE)) b = "checked";
+      }
+      }
+%>
+
+<form onsubmit='return false;' enctype='multipart/form-data'>
+  <table><tr>
+     <td align='left'>Enter background color (public param):</td>
+     <td>
+        <input id='<portlet:namespace/>-color' name='<%=PARAM_COLOR%>' type='text' value='<%=clr%>' size='10' maxlength='10'>
+     </td>
+     <td><div id='<portlet:namespace/>-putMsgHere'></div></td>
+  </tr></table>
+</form>
+<hr/>
+<FORM id='<portlet:namespace/>-setParams' method='POST' enctype='application/x-www-form-urlencoded'>
+   <table><tr><td align='left'>
+   Select active foreground colors:
+   </td><td>
+   <input id='<portlet:namespace/>-red' name='<%=PARAM_FG_COLOR%>' value='<%=PARAM_FG_RED%>' type='checkbox' <%=r%>>
+   Red
+   </td><td>
+   <input id='<portlet:namespace/>-green'  name='<%=PARAM_FG_COLOR%>' value='<%=PARAM_FG_GREEN%>' type='checkbox' <%=g%>>
+   Green
+   </td><td>
+   <input id='<portlet:namespace/>-blue'  name='<%=PARAM_FG_COLOR%>' value='<%=PARAM_FG_BLUE%>' type='checkbox' <%=b%>>
+   Blue
+
+   </td></tr><tr><td>
+   Enter message:
+   </td><td colspan=3>
+   <input id='<portlet:namespace/>-msg' name='<%=PARAM_MSG_INPUT%>' type='text' value='' size='50' maxlength='50'>
+   </td><td>
+
+   </td></tr><tr><td>
+   Form submission:
+   </td><td>
+   <input id='<portlet:namespace/>sType-url' type='radio' name='<%=PARAM_SUBTYPE%>' value='<%=PARAM_SUBTYPE_URL%>' checked>URL
+   </td><td>
+   <input id='<portlet:namespace/>sType-form' type='radio' name='<%=PARAM_SUBTYPE%>' value='<%=PARAM_SUBTYPE_FORM%>'>Form
+   </td><td>
+   <INPUT id ='<portlet:namespace/>-send' VALUE='send' TYPE='submit'>
+   </td></tr></table>
+</FORM>
+<p><hr/></p>
+
+<script>
+(function () {
+   'use strict';
+    
+   var pid = '<portlet:namespace/>',
+       colorEntry = '<portlet:namespace/>-color',
+       msgdiv = '<portlet:namespace/>-putMsgHere',
+       rid = '<portlet:namespace/>-red',
+       gid = '<portlet:namespace/>-green',
+       bid = '<portlet:namespace/>-blue',
+       mid = '<portlet:namespace/>-msg',
+       formid = '<portlet:namespace/>-setParams',
+       sidurl = '<portlet:namespace/>sType-url',
+       sidform = '<portlet:namespace/>sType-form',
+       currState,
+       hub,
+
+       
+   // Handler for onStateChange event
+   update = function (type, state) {
+      var oldColor = currState.p.getValue('<%=PARAM_COLOR%>'),
+      
+          // use getValue with default value that is used if the parameter is not set
+          newColor = state.p.getValue('<%=PARAM_COLOR%>', '#FFFFFF'),
+          subtype = state.p.getValue('<%=PARAM_SUBTYPE%>', '<%=PARAM_SUBTYPE_URL%>'),
+          msg = state.p.getValue('<%=PARAM_MSG_INPUT%>', ''),
+          
+          fgcolor = state.p.getValues('<%=PARAM_FG_COLOR%>'),
+          clr = {red: false, green: false, blue: false}, ii;
+      
+      console.log("CSP: state updated. Type=" + type + ", color=" + newColor);
+      
+      if (newColor !== oldColor) {
+         document.getElementById(msgdiv).innerHTML = '';
+         document.getElementById(colorEntry).value = newColor;
+      }
+      
+      // make sure controls are set according to parameters
+      
+      if (subtype === '<%=PARAM_SUBTYPE_URL%>') {
+         document.getElementById(sidurl).checked = true;
+      } else {
+         document.getElementById(sidform).checked = true;
+      }
+       
+      if (fgcolor) {
+         for (ii = 0; ii < fgcolor.length; ii++) {
+            clr[fgcolor[ii]] = true;
+         }
+      } 
+      document.getElementById(rid).checked = clr.red;
+      document.getElementById(gid).checked = clr.green;
+      document.getElementById(bid).checked = clr.blue;
+
+      document.getElementById(mid).value = msg;
+
+      currState = state;
+   };
+   
+
+   // Register portlet with Portlet Hub. Add listener for onStateChange event.
+   portlet.register(pid).then(function (pi) {
+      console.log("CSP Color Selection Portlet: registered: " + pid);
+      hub = pi;
+      currState = hub.newState();
+      hub.addEventListener("portlet.onStateChange", update);
+   });
+   
+
+   // Handle change in background color entry field
+   document.getElementById(colorEntry).onchange = function () {
+      var newColor = this.value, newState;
+      console.log("CSP: entry field updated. color=" + newColor);
+      if ((newColor === undefined) || (newColor === null) || !newColor.match(/^#(?:[A-Fa-f0-9]{3}){1,2}$/)) {
+         document.getElementById(msgdiv).innerHTML = 'Bad color. Enter #xxxxxx or #xxx.';
+      } else {
+         newState = currState.clone();
+         newState.p.setValue('color', newColor);
+         hub.setPortletState(newState);
+      }
+   };
+   
+
+   // Handler for 'send' button click. Perform Ajax action.
+   document.getElementById(formid).addEventListener('submit', function (event) {
+      var parms, clrs = [], fel, submitForm = document.getElementById(sidform).checked;
+      
+      console.log("CSP: sending message. submitForm=" + submitForm);
+      
+      // decide how form is to be sent -
+      if (submitForm) {
+         fel = this;
+         hub.action(fel);
+      } else  {
+         parms = hub.newParameters();
+         parms.setValue('action', 'send');
+         if (document.getElementById(rid).checked) {
+            clrs.push("<%=PARAM_FG_RED%>");
+         } 
+         if (document.getElementById(gid).checked) {
+            clrs.push("<%=PARAM_FG_GREEN%>");
+         } 
+         if (document.getElementById(bid).checked) {
+            clrs.push("<%=PARAM_FG_BLUE%>");
+         } 
+         if (clrs.length > 0) {
+            parms.setValue('<%=PARAM_FG_COLOR%>', clrs);
+         }
+         parms.setValue('<%=PARAM_MSG_INPUT%>', document.getElementById(mid).value);
+         hub.action(parms);
+      }
+      event.preventDefault();
+   });
+      
+}());
+</script>

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/cea47a7c/PortletV3Demo/src/main/webapp/WEB-INF/jsp/view-isp.jsp
----------------------------------------------------------------------
diff --git a/PortletV3Demo/src/main/webapp/WEB-INF/jsp/view-isp.jsp b/PortletV3Demo/src/main/webapp/WEB-INF/jsp/view-isp.jsp
new file mode 100644
index 0000000..675fe32
--- /dev/null
+++ b/PortletV3Demo/src/main/webapp/WEB-INF/jsp/view-isp.jsp
@@ -0,0 +1,178 @@
+<%--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You 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.
+--%>
+<%@ page session="false" %>
+<%@ taglib uri="http://java.sun.com/portlet_2_0"  prefix="portlet" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+
+<portlet:defineObjects />
+
+
+<h3>Image Selector</h3><hr/>
+<FORM id='<portlet:namespace/>-setParams' onsubmit='return false;' enctype='multipart/form-data'>
+   <table><tr><td align='left'>
+   Selection type (private param):
+   </td><td>
+   <input id='<portlet:namespace/>-radio' type='radio' name='selType' value='radio'>Radio Button
+   <input id='<portlet:namespace/>-dropdown' type='radio' name='selType' value='dropdown'>Drop Down
+   </td></tr><tr><td>
+   Select Image (public param):
+   </td><td>
+
+   <div id='<portlet:namespace/>-putResourceHere'></div>
+
+   </td></tr></table>
+</FORM>
+<p><hr/></p>
+
+<script>
+(function () {
+   'use strict';
+   
+   var pid = '<portlet:namespace/>',
+       fid = '<portlet:namespace/>-setParams',
+       resdiv = '<portlet:namespace/>-putResourceHere',
+       st_radio = '<portlet:namespace/>-radio',
+       st_dropdown = '<portlet:namespace/>-dropdown',
+       selBox = '<portlet:namespace/>-selBox',
+   
+       currState = {},
+       hub,
+   
+   // Set image name PRP if radio button clicked - 
+   handleImgRadio = function () {
+      console.log("ISP: image selected (radio): " + this.value);
+      
+      if (currState.parameters.photo !== this.value) {
+         var newState = currState.clone();
+         newState.p.setValue('photo', this.value);
+         hub.setPortletState(newState);
+      }
+   },
+   
+   // Set image name PRP if image selected in selection box - 
+   handleImgDropdown = function () {
+      console.log("ISP: image selected (dropdown): " + this.value);
+      
+      if (currState.parameters.photo !== this.value) {
+         var newState = currState.clone();
+         newState.p.setValue('photo', this.value);
+         hub.setPortletState(newState);
+      }
+   },
+   
+   // function to select the proper image depending on radio button or dropdown display
+   selectImage = function (seltype, imgName) {
+      var ii, f = document.getElementById(fid);
+      
+      if (!imgName) {
+         imgName = 'default';
+      }
+      
+      if (seltype === 'radio') {
+         for (ii=0; ii < f.imgName.length; ii++) {
+            if (f.imgName[ii].value === imgName) {
+               console.log("ISP: image clicked: " + imgName);
+               f.imgName[ii].checked = true;
+            } else {
+               f.imgName[ii].checked = false;
+            }
+         }
+      } else {
+         for (ii=0; ii < f.imgName.length; ii++) {
+            if (f.imgName[ii].value === imgName) {
+               console.log("ISP: image selected: " + imgName);
+               f.imgName[ii].selected = true;
+            }
+         }
+      }
+   },
+   
+   // Handler for onStateChange event
+   update = function (type, state) {
+      var oldST = currState.p.getValue('selType'),
+          newST = state.p.getValue('selType', 'radio'),
+          oldImg = currState.p.getValue('photo'),
+          newImg = state.p.getValue('photo');
+          
+      console.log("ISP: state updated. type=" + type + ", selType=" + newST + ", photo=" + newImg);
+      
+      if (oldST !== newST) {
+         hub.createResourceUrl({}).then(function (url) {
+            console.log("ISP: got url: " + url);
+            var xhr = new XMLHttpRequest();
+            xhr.onreadystatechange=function() {
+               if (xhr.readyState === 4 && xhr.status === 200) {
+                  document.getElementById(resdiv).innerHTML = xhr.responseText;
+
+                  // default is radio buttons
+                  var ii, f = document.getElementById(fid);
+                  if (newST === 'radio') {
+                     for (ii=0; ii < f.imgName.length; ii++) {
+                        console.log("ISP: adding selection handler for: " + f.imgName[ii].value);
+                        f.imgName[ii].onclick = handleImgRadio;
+                     }
+                  } else if (newST === 'dropdown') {
+                     console.log("ISP: adding selection handler to dropdown list element: " + selBox);
+                     document.getElementById(selBox).onchange = handleImgDropdown;
+                  }
+				  selectImage(newST, newImg);
+               }
+            };
+            xhr.open("GET",url,true);
+            xhr.send();
+         });
+      } else {
+         // make sure image is selected according to parameter setting. 
+         selectImage(newST, newImg);
+      }
+
+      if (newST === 'dropdown') {
+         document.getElementById(st_dropdown).checked = true;
+      } else {
+         document.getElementById(st_radio).checked = true;
+      }
+
+      currState=state;
+   },
+   
+   // set private parameter selType to store the selection display type
+   handleST = function () {
+      console.log("ISP: select display type clicked: " + this.value);
+      if (currState.parameters.selType !==  this.value) {
+         var newState = currState.clone();
+         newState.p.setValue('selType', this.value);
+         hub.setPortletState(newState);
+      }
+   };
+   
+   document.getElementById(st_radio).onclick = handleST;
+   document.getElementById(st_dropdown).onclick = handleST;
+   
+   
+   // Register with Portlet Hub, add listener for onStateChange event
+   portlet.register(pid).then(function (pi) {
+      console.log("ISP Image Selection Portlet: registered: " + pid);
+      hub = pi;
+      currState = hub.newState();
+      hub.addEventListener("portlet.onStateChange", update);
+   });
+   
+   
+}());
+</script>

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/cea47a7c/PortletV3Demo/src/main/webapp/WEB-INF/jsp/view-ivp.jsp
----------------------------------------------------------------------
diff --git a/PortletV3Demo/src/main/webapp/WEB-INF/jsp/view-ivp.jsp b/PortletV3Demo/src/main/webapp/WEB-INF/jsp/view-ivp.jsp
new file mode 100644
index 0000000..68aa575
--- /dev/null
+++ b/PortletV3Demo/src/main/webapp/WEB-INF/jsp/view-ivp.jsp
@@ -0,0 +1,161 @@
+<%--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You 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.
+--%>
+<%@ page session="false" %>
+<%@ taglib uri="http://java.sun.com/portlet_2_0"  prefix="portlet" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+
+<portlet:defineObjects />
+
+<div style='clear:both;'>
+<div style='float:left;'><h3>Image Viewer</h3></div>
+<div id=<portlet:namespace/>-counter style='float:right; font-size:250%; color:#0B0;'>1</div>
+</div><div style='clear:both;'><hr/>
+      
+<FORM id='<portlet:namespace/>-setParams'  onsubmit='return false;' enctype='multipart/form-data'>
+   <table><tr><td align='left'>
+   Cacheability setting:
+   </td><td>
+   <input id='<portlet:namespace/>-page' type='radio' name='cacheability' value='PAGE'>Page
+   <input id='<portlet:namespace/>-portlet' type='radio' name='cacheability' value='PORTLET'>Portlet
+   <input id='<portlet:namespace/>-full' type='radio' name='cacheability' value='FULL'>Full
+   </td></tr><tr><td>
+   Set border (resource parameter)
+   </td><td>
+   <input id='<portlet:namespace/>-border' type='checkbox' name='border' value='border'>
+   </td></tr></table>
+</FORM><hr/>
+
+<div id='<portlet:namespace/>-putResourceHere'></div>
+      
+<script>
+(function () {
+   'use strict';
+   
+   var pid = '<portlet:namespace/>',
+       resdiv = '<portlet:namespace/>-putResourceHere',
+       border = '<portlet:namespace/>-border',
+       ca_page = '<portlet:namespace/>-page',
+       ca_portlet = '<portlet:namespace/>-portlet',
+       ca_full = '<portlet:namespace/>-full',
+
+       cntrId = '<portlet:namespace/>-counter', 
+       cntr = 1,
+       
+       resparms = {},
+       cacheability,
+       currState,
+       hub,
+   
+   // Update function called by the Portlet Hub when an onStatechange event occurs. 
+   update = function (type, state) {
+      var bo = state.p.getValue('bo'),
+          ca = state.p.getValue('ca', hub.constants.PAGE);
+      
+      currState = state;
+      
+      console.log("IVP: state updated. event type=" + type);
+      
+      // set cacheability & border color according to parameters. Set controls
+      // according to parameers to enable back button support.
+      
+      resparms = hub.newParameters();
+      if (bo) {
+         resparms.setValue('border', bo);
+         document.getElementById(border).checked = true;
+      } else {
+         document.getElementById(border).checked = false;
+      }
+      
+      cacheability = ca;
+      switch (ca) {
+      case hub.constants.PAGE:
+         document.getElementById(ca_page).checked = true;
+         break;
+      case hub.constants.PORTLET:
+         document.getElementById(ca_portlet).checked = true;
+         break;
+      case hub.constants.FULL:
+         document.getElementById(ca_full).checked = true;
+         break;
+      }
+      
+      
+      hub.createResourceUrl(resparms, cacheability).then(function (url) {
+         var brdr = (resparms.border === undefined) ? undefined : resparms.border[0],
+             xhr = new XMLHttpRequest();
+         console.log("IVP: got url: " + url + ", res parm border=" + brdr);
+         xhr.onreadystatechange = function () {
+            if (xhr.readyState === 4 && xhr.status === 200) {
+               document.getElementById(resdiv).innerHTML=xhr.responseText;
+            }
+         };
+         xhr.open("GET",url,true);
+         xhr.send();
+      });
+   },
+   
+   // Handler for cacheability radio buttons
+   handleCA = function () {
+      var c = hub.constants[this.value], nstate;
+      console.log("IVP: cacheability button clicked: " + this.value + ", corresponding to constant value " + c);
+      if (cacheability !== c) {
+         cacheability = c;
+         nstate = currState.clone();
+         nstate.p.setValue('ca', c);
+         hub.setPortletState(nstate);
+      }
+   };
+   
+   document.getElementById(ca_page).checked = true;
+   document.getElementById(ca_page).onclick = handleCA;
+   document.getElementById(ca_portlet).onclick = handleCA;
+   document.getElementById(ca_full).onclick = handleCA;
+   
+   // Handler for 'border' checkbox 
+   document.getElementById(border).checked = false;
+   document.getElementById(border).onclick = function () {
+      var nstate = currState.clone();
+      console.log("IVP: border checked: " + this.checked);
+      if (this.checked) {
+         nstate.p.setValue('bo', '#00F');;
+      } else {
+         nstate.p.remove('bo');
+      }
+      hub.setPortletState(nstate);
+   };
+   
+   // Register this portlet with the Portlet Hub and add event listener for 
+   // the onStateChange event
+   portlet.register(pid).then(function (pi) {
+      console.log("IVP: registered: " + pid);
+      hub = pi;
+      cacheability = hub.constants.PAGE;
+      hub.addEventListener("portlet.onStateChange", update);
+   });
+   
+   // Simple counter for demonstrating that page hasn't been refreshed.
+   window.setInterval(function () {
+      document.getElementById(cntrId).innerHTML = ++cntr;
+   }, 1000);
+   
+}());
+</script>
+
+<p><hr/></p></div>
+

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/cea47a7c/PortletV3Demo/src/main/webapp/WEB-INF/jsp/view-mbp.jsp
----------------------------------------------------------------------
diff --git a/PortletV3Demo/src/main/webapp/WEB-INF/jsp/view-mbp.jsp b/PortletV3Demo/src/main/webapp/WEB-INF/jsp/view-mbp.jsp
new file mode 100644
index 0000000..5e85af0
--- /dev/null
+++ b/PortletV3Demo/src/main/webapp/WEB-INF/jsp/view-mbp.jsp
@@ -0,0 +1,89 @@
+<%--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You 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.
+--%>
+<%@ page session="false" %>
+<%@ taglib uri="http://java.sun.com/portlet_2_0"  prefix="portlet" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+
+<portlet:defineObjects />
+
+<%
+   StringBuffer style = new StringBuffer(256);
+   style.append("border-style:solid; border-width:3px;");
+   style.append(" padding:4px; overflow:auto;");
+   style.append(" border-color:#000088; min-height:70px;");
+   style.append(" background:#E0E0E0;");
+%>
+
+<div style='clear:both;'>
+<div style='float:left;'><h3>Message Box Portlet</h3></div>
+<div style='float:right;'>
+<form   onsubmit='return false;'><input id='<portlet:namespace/>-clear' type='submit' name='action' value='clear' /></form>
+</div>
+</div><div style='clear:both;'><hr/>
+<p>Messages that arrive via events from other portlets are displayed in this box.</p>
+<div id='<portlet:namespace/>-responseDiv' style="<%=style.toString()%>"></div>
+</div>
+   
+<script>
+(function () {
+   'use strict';
+   var pid = '<portlet:namespace/>',
+       resdiv = '<portlet:namespace/>-responseDiv',
+       clrButton = '<portlet:namespace/>-clear',
+   
+       state,
+       resparms,
+       cacheability,
+       hub,
+   
+   // Handler for onStateChange event
+   update = function (type, s) {
+      console.log("MBP: state updated. Event type = " + type);
+      state = s;
+      
+      hub.createResourceUrl(resparms, cacheability).then(function (url) {
+         var xhr = new XMLHttpRequest();
+         console.log("MBP: got url: " + url);
+         xhr.onreadystatechange = function () {
+            if (xhr.readyState === 4 && xhr.status === 200) {
+               document.getElementById(resdiv).innerHTML=xhr.responseText;
+            }
+         };
+         xhr.open("GET",url,true);
+         xhr.send();
+      });
+   };
+   
+   // Handler for "clear" button. execute an action which clears the stored messages
+   document.getElementById(clrButton).onclick = function () {
+      console.log("MBP: clear button clicked. ");
+      hub.action();
+   };
+   
+   // Register portlet with Portlet Hub; add onStateChange listener 
+   portlet.register(pid).then(function (pi) {
+      console.log("MBP: Message Box portlet registered: " + pid);
+      hub = pi;
+      resparms = hub.newParameters();
+      cacheability = hub.constants.PAGE;
+      hub.addEventListener("portlet.onStateChange", update);
+   });
+   
+}());
+</script>

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/cea47a7c/PortletV3Demo/src/main/webapp/WEB-INF/jsp/view-pap.jsp
----------------------------------------------------------------------
diff --git a/PortletV3Demo/src/main/webapp/WEB-INF/jsp/view-pap.jsp b/PortletV3Demo/src/main/webapp/WEB-INF/jsp/view-pap.jsp
new file mode 100644
index 0000000..c9ccb8b
--- /dev/null
+++ b/PortletV3Demo/src/main/webapp/WEB-INF/jsp/view-pap.jsp
@@ -0,0 +1,108 @@
+<%--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You 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.
+--%>
+<%@ page session="false" %>
+<%@ taglib uri="http://java.sun.com/portlet_2_0"  prefix="portlet" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+
+<portlet:defineObjects />
+
+<%
+   StringBuffer style = new StringBuffer(256);
+   style.append("border-style:solid; border-width:3px;");
+   style.append(" padding:4px; overflow:auto;");
+   style.append(" border-color:#008800; min-height:30px;");
+   style.append(" background:#E0E0E0;");
+%>
+
+<h3>Partial Action Portlet</h3>
+<hr/>
+<p>This portlet exercises the Partial Action execution path.</p>
+<form onsubmit='return false;' enctype='multipart/form-data'><input id='<portlet:namespace/>-doPA' type='submit' name='action' value='Do Partial Action' /></form>
+<div id='<portlet:namespace/>-responseDiv' style="<%=style.toString()%>"></div>
+   
+<script>
+(function () {
+   'use strict';
+   var pid = '<portlet:namespace/>',
+       resdiv = '<portlet:namespace/>-responseDiv',
+       paButton = '<portlet:namespace/>-doPA',
+   
+       state,
+       actparms,
+       hub,
+   
+   // Handler for onStateChange event
+   update = function (type, s) {
+      var nc = s.p.getValue('color', '#E0E0E0');
+      console.log("PAP: state updated. Event type = " + type);
+      
+      // change background color for message box
+      if (state.p.getValue('color') !== nc) {
+         document.getElementById(resdiv).style.background = nc;
+      }
+      state = s;
+   };
+   
+   // Handler for "partial action" button. Perform partial action sequence.
+   document.getElementById(paButton).onclick = function () {
+      var xhr = new XMLHttpRequest(), vals, pagestate = null, markup; 
+      console.log("PAP: Partial action button clicked.");
+      
+      // Add the render parameter counter as action parameter
+      actparms.setValue('numActions', state.p.getValue('numActions'));
+      
+      hub.startPartialAction(actparms).then(function (pai) {
+         
+         console.log("PAP: got partial action init object. URL: " + pai.url);
+         
+         xhr.onreadystatechange = function () {
+            if (xhr.readyState === 4) {
+               if (xhr.status === 200) {
+                  vals = xhr.responseText.split(";#delimiter#;");
+                  if (vals.length !== 2) {
+                     markup = "<p>Error parsing return data. # fields = " + vals.length + ".</p>";
+                  } else {
+                     markup = vals[0];
+                     pagestate = vals[1];
+                  }
+               } else {
+                  markup = "<p>Communication error. XHR status=" + xhr.statusText + "</p>";
+               } 
+               // Make sure setPageState is called even in error case in order to unblock the P.H.
+               pai.setPageState(pagestate);
+               document.getElementById(resdiv).innerHTML = markup;
+            }
+         };
+         xhr.open("POST",pai.url,true);
+         xhr.send();
+         
+      });
+   };
+   
+   // Register portlet with Portlet Hub; add onStateChange listener 
+   portlet.register(pid).then(function (pi) {
+      console.log("PAP: registered: " + pid);
+      hub = pi;
+      state = hub.newState();
+      actparms = hub.newParameters();
+      hub.addEventListener("portlet.onStateChange", update);
+   });
+   
+}());
+</script>

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/cea47a7c/PortletV3Demo/src/main/webapp/WEB-INF/portlet.xml
----------------------------------------------------------------------
diff --git a/PortletV3Demo/src/main/webapp/WEB-INF/portlet.xml b/PortletV3Demo/src/main/webapp/WEB-INF/portlet.xml
new file mode 100644
index 0000000..62ef563
--- /dev/null
+++ b/PortletV3Demo/src/main/webapp/WEB-INF/portlet.xml
@@ -0,0 +1,129 @@
+<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" 
+             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+           xmlns:rp="http://www.apache.org/portals/pluto/pub-render-params/ResourcePortlet"
+             xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" 
+             version="2.0"
+    		id="v3.demo.portlet">
+   <portlet>
+      <portlet-name>V3ImageViewer</portlet-name>
+      <display-name>V3 Image Viewer Portlet</display-name>
+      
+      <portlet-class>basic.portlet.ResourcePortlet</portlet-class>
+
+      <supports>
+         <mime-type>text/html</mime-type>
+         <portlet-mode>VIEW</portlet-mode>
+      </supports>
+
+      <supported-locale>en</supported-locale>        
+
+      <portlet-info>
+         <title>V3 Image Viewer Portlet</title>
+      </portlet-info>
+
+      <supported-public-render-parameter>photo</supported-public-render-parameter>
+      <supported-public-render-parameter>color</supported-public-render-parameter>
+   </portlet>
+
+   <portlet>
+      <portlet-name>MessageBoxPortlet</portlet-name>
+      <display-name>Message Box Portlet</display-name>
+      
+      <portlet-class>basic.portlet.MessageBoxPortlet</portlet-class>
+
+      <supports>
+         <mime-type>text/html</mime-type>
+         <portlet-mode>VIEW</portlet-mode>
+      </supports>
+
+      <supported-locale>en</supported-locale>        
+
+      <portlet-info>
+         <title>PH Message Box Portlet</title>
+      </portlet-info>
+
+      <supported-processing-event>
+         <qname>rp:Message</qname>
+      </supported-processing-event>
+
+      <supported-public-render-parameter>color</supported-public-render-parameter>
+   </portlet>
+
+   <portlet>
+      <portlet-name>V3ImageSelector</portlet-name>
+      <display-name>Image Selection Portlet - alt PRP name</display-name>
+      
+      <portlet-class>basic.portlet.ImageSelPortlet</portlet-class>
+
+      <supports>
+         <mime-type>text/html</mime-type>
+         <portlet-mode>VIEW</portlet-mode>
+      </supports>
+
+      <supported-locale>en</supported-locale>        
+
+      <portlet-info>
+         <title>Image Selection Portlet - alt PRP name</title>
+      </portlet-info>
+
+      <supported-public-render-parameter>photo</supported-public-render-parameter>
+   </portlet>
+
+   <portlet>
+      <portlet-name>V3ColorSelector</portlet-name>
+      <display-name>Color Selection Portlet - alt QName</display-name>
+      
+      <portlet-class>basic.portlet.ColorSelPortlet</portlet-class>
+
+      <supports>
+         <mime-type>text/html</mime-type>
+         <portlet-mode>VIEW</portlet-mode>
+         <portlet-mode>HELP</portlet-mode>
+      </supports>
+
+      <supported-locale>en</supported-locale>        
+
+      <portlet-info>
+         <title>Color Selection Portlet - alt QName</title>
+      </portlet-info>
+
+      <supported-publishing-event>
+         <qname>rp:Message</qname>
+      </supported-publishing-event>
+      <supported-public-render-parameter>color</supported-public-render-parameter>
+   </portlet>
+
+   <portlet>
+      <portlet-name>PartialActionPortlet</portlet-name>
+      <display-name>Partial Action Portlet</display-name>
+      
+      <portlet-class>basic.portlet.PartialActionPortlet</portlet-class>
+
+      <supports>
+         <mime-type>text/html</mime-type>
+         <portlet-mode>VIEW</portlet-mode>
+      </supports>
+
+      <supported-locale>en</supported-locale>        
+
+      <portlet-info>
+         <title>PH Partial Action Portlet</title>
+      </portlet-info>
+
+      <supported-public-render-parameter>color</supported-public-render-parameter>
+   </portlet>
+   
+   <event-definition>
+      <qname>rp:Message</qname>
+      <value-type>java.lang.String</value-type>
+   </event-definition>
+   
+   <public-render-parameter>
+      <identifier>photo</identifier>
+      <qname>rp:ph-imgName</qname>
+   </public-render-parameter>
+   <public-render-parameter>
+      <identifier>color</identifier>
+      <qname>rp:alt-color</qname>
+   </public-render-parameter>
+ </portlet-app>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/cea47a7c/PortletV3Demo/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/PortletV3Demo/src/main/webapp/WEB-INF/web.xml b/PortletV3Demo/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..10055f0
--- /dev/null
+++ b/PortletV3Demo/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
+	<display-name>Portlet Version 3.0 Demo</display-name>
+</web-app>

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/cea47a7c/PortletV3Demo/src/main/webapp/resources/css/styles.css
----------------------------------------------------------------------
diff --git a/PortletV3Demo/src/main/webapp/resources/css/styles.css b/PortletV3Demo/src/main/webapp/resources/css/styles.css
new file mode 100644
index 0000000..9029874
--- /dev/null
+++ b/PortletV3Demo/src/main/webapp/resources/css/styles.css
@@ -0,0 +1,16 @@
+.emphasis {
+   font-style: italic;
+   font-size: 1.3em;
+}
+
+.basicJSFApp {
+   padding: 5px;
+   background-color: #DDFFDD;
+   border: thin solid #66DD66;
+}
+
+.infoBox {
+   padding: 5px;
+   background-color: #DDDDFF;
+   border: thin solid #6666DD;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/cea47a7c/PortletV3Demo/src/main/webapp/resources/images/FullMoon.gif
----------------------------------------------------------------------
diff --git a/PortletV3Demo/src/main/webapp/resources/images/FullMoon.gif b/PortletV3Demo/src/main/webapp/resources/images/FullMoon.gif
new file mode 100644
index 0000000..a85ee1a
Binary files /dev/null and b/PortletV3Demo/src/main/webapp/resources/images/FullMoon.gif differ

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/cea47a7c/PortletV3Demo/src/main/webapp/resources/images/baseball-trans.gif
----------------------------------------------------------------------
diff --git a/PortletV3Demo/src/main/webapp/resources/images/baseball-trans.gif b/PortletV3Demo/src/main/webapp/resources/images/baseball-trans.gif
new file mode 100644
index 0000000..31c2100
Binary files /dev/null and b/PortletV3Demo/src/main/webapp/resources/images/baseball-trans.gif differ

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/cea47a7c/PortletV3Demo/src/main/webapp/resources/images/fussball-trans.gif
----------------------------------------------------------------------
diff --git a/PortletV3Demo/src/main/webapp/resources/images/fussball-trans.gif b/PortletV3Demo/src/main/webapp/resources/images/fussball-trans.gif
new file mode 100644
index 0000000..97bde92
Binary files /dev/null and b/PortletV3Demo/src/main/webapp/resources/images/fussball-trans.gif differ

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/cea47a7c/PortletV3Demo/src/main/webapp/resources/images/golfball-trans.gif
----------------------------------------------------------------------
diff --git a/PortletV3Demo/src/main/webapp/resources/images/golfball-trans.gif b/PortletV3Demo/src/main/webapp/resources/images/golfball-trans.gif
new file mode 100644
index 0000000..4ec86ce
Binary files /dev/null and b/PortletV3Demo/src/main/webapp/resources/images/golfball-trans.gif differ

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/cea47a7c/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index e355fad..e90209f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -628,6 +628,7 @@ TODO: Check if we need all of them. -->
         
         <!-- PortletHub demo portlets -->
         <module>PortletHubDemo</module>
+        <module>PortletV3Demo</module>
 
         <!-- Pluto Utilities, Maven Plugins and Ant Tasks -->
         <module>pluto-util</module>