Author: taylor
Date: Thu Jun 21 17:39:22 2007
New Revision: 549652

URL: http://svn.apache.org/viewvc?view=rev&rev=549652
Log:
https://issues.apache.org/jira/browse/PB-70

contribution from Woonsan Ko

In summary, the followings are expected:
 - One can add a portlet preferences validator class into the portlet.xml. The 
class is a wrapper class for groovy script.
 - The wrapper class reads (read-only) preferences to find the script file and 
auto-refresh mode.
 - When auto-refresh mode is true, the modification of the validator script 
should be applied instantly.
 - Also, one can write a groovy portlet to support pre-286 header phase. 
Currently Jetspeed-2 API provides this interface. So the script developer 
implements SupportsHeaderPhase interface of Jetspeed-2 to provide header phase.
 - In such case, the developer can set the portlet-class to another wrapper 
class.

Added:
    
portals/bridges/trunk/groovy/src/java/org/apache/portals/bridges/groovy/GroovyPortletHeaderPhaseSupport.java
    
portals/bridges/trunk/groovy/src/java/org/apache/portals/bridges/groovy/GroovyPreferencesValidator.java
    portals/bridges/trunk/groovy/xdocs/headersupport.xml
    portals/bridges/trunk/groovy/xdocs/prefvalidate.xml
Modified:
    portals/bridges/trunk/.classpath
    portals/bridges/trunk/groovy/pom.xml
    portals/bridges/trunk/groovy/project.xml
    portals/bridges/trunk/groovy/xdocs/index.xml
    portals/bridges/trunk/groovy/xdocs/navigation.xml
    portals/bridges/trunk/project.properties

Modified: portals/bridges/trunk/.classpath
URL: 
http://svn.apache.org/viewvc/portals/bridges/trunk/.classpath?view=diff&rev=549652&r1=549651&r2=549652
==============================================================================
--- portals/bridges/trunk/.classpath (original)
+++ portals/bridges/trunk/.classpath Thu Jun 21 17:39:22 2007
@@ -42,6 +42,7 @@
        <classpathentry kind="var" 
path="MAVEN_REPO/org.springframework/jars/spring-web-2.0.5.jar"/>
        <classpathentry kind="var" 
path="MAVEN_REPO/org.springframework/jars/spring-portlet-2.0.5.jar"/>
        <classpathentry kind="var" 
path="MAVEN_REPO/commons-collections/jars/commons-collections-3.2.jar"/>
-       <classpathentry kind="var" 
path="MAVEN_REPO/commons-lang/jars/commons-lang-2.1.jar"/>
+       <classpathentry kind="var" 
path="MAVEN_REPO/commons-lang/jars/commons-lang-2.1.jar"/>
+       <classpathentry kind="var" 
path="MAVEN_REPO/org.apache.portals.jetspeed-2/jars/jetspeed-api-2.1.1-dev.jar"/>
    
        <classpathentry kind="output" path="bin"/>
 </classpath>

Modified: portals/bridges/trunk/groovy/pom.xml
URL: 
http://svn.apache.org/viewvc/portals/bridges/trunk/groovy/pom.xml?view=diff&rev=549652&r1=549651&r2=549652
==============================================================================
--- portals/bridges/trunk/groovy/pom.xml (original)
+++ portals/bridges/trunk/groovy/pom.xml Thu Jun 21 17:39:22 2007
@@ -72,6 +72,12 @@
             <version>1.0</version>
             <scope>compile</scope>
         </dependency>                           
+        <dependency>
+            <groupId>org.apache.portals.jetspeed-2</groupId>
+            <artifactId>jetspeed-api</artifactId>
+            <version>${jetspeed.version}</version>
+            <type>jar</type>
+        </dependency>
     </dependencies>
     
     <!-- Build Configuration -->

Modified: portals/bridges/trunk/groovy/project.xml
URL: 
http://svn.apache.org/viewvc/portals/bridges/trunk/groovy/project.xml?view=diff&rev=549652&r1=549651&r2=549652
==============================================================================
--- portals/bridges/trunk/groovy/project.xml (original)
+++ portals/bridges/trunk/groovy/project.xml Thu Jun 21 17:39:22 2007
@@ -53,11 +53,17 @@
     </contributor>    
   </contributors>
   <dependencies>
-  <dependency>
+    <dependency>
       <id>groovy:groovy</id>
       <version>1.0</version>
       <type>jar</type>
     </dependency>      
+    <dependency>
+      <groupId>org.apache.portals.jetspeed-2</groupId>
+      <artifactId>jetspeed-api</artifactId>
+      <version>${jetspeed.api.version}</version>
+      <type>jar</type>
+    </dependency>
   </dependencies>
 
   <build>

Added: 
portals/bridges/trunk/groovy/src/java/org/apache/portals/bridges/groovy/GroovyPortletHeaderPhaseSupport.java
URL: 
http://svn.apache.org/viewvc/portals/bridges/trunk/groovy/src/java/org/apache/portals/bridges/groovy/GroovyPortletHeaderPhaseSupport.java?view=auto&rev=549652
==============================================================================
--- 
portals/bridges/trunk/groovy/src/java/org/apache/portals/bridges/groovy/GroovyPortletHeaderPhaseSupport.java
 (added)
+++ 
portals/bridges/trunk/groovy/src/java/org/apache/portals/bridges/groovy/GroovyPortletHeaderPhaseSupport.java
 Thu Jun 21 17:39:22 2007
@@ -0,0 +1,68 @@
+/*
+ * 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 org.apache.portals.bridges.groovy;
+
+import java.io.IOException;
+
+import javax.portlet.PortletException;
+
+import org.codehaus.groovy.control.CompilationFailedException;
+
+import org.apache.jetspeed.portlet.SupportsHeaderPhase;
+import org.apache.jetspeed.portlet.PortletHeaderRequest;
+import org.apache.jetspeed.portlet.PortletHeaderResponse;
+
+/**
+ * <p>
+ * GroovyPortletHeaderPhaseSupport parses and invokes a groovy-scripted 
portlet. A groovy-scripted
+ * portlet just need to be implemented like any other Java-based portlet. So, a
+ * groovy-scripted portlet does not support only full features of JSR-168 
portlet, but
+ * it also supports JSR-286 header phase.
+ * 
+ * @author <a href="mailto:[EMAIL PROTECTED]">Woonsan Ko</a>
+ * @Id@
+ */
+public class GroovyPortletHeaderPhaseSupport extends GroovyPortlet implements 
SupportsHeaderPhase
+{
+    protected SupportsHeaderPhase scriptPortletInstanceWithHeaderPhase;
+    
+    public GroovyPortletHeaderPhaseSupport()
+    {
+        super();
+    }
+    
+    public void doHeader(PortletHeaderRequest request, PortletHeaderResponse 
response) throws PortletException
+    {
+        refreshPortletInstance();
+        
+        if (this.scriptPortletInstanceWithHeaderPhase != null)
+        {
+            this.scriptPortletInstanceWithHeaderPhase.doHeader(request, 
response);
+        }
+    }
+    
+    protected void createScriptPortletInstance() throws 
CompilationFailedException, InstantiationException,
+            IOException, IllegalAccessException, PortletException
+    {
+        super.createScriptPortletInstance();
+        
+        if (scriptPortletInstance instanceof SupportsHeaderPhase)
+        {
+            this.scriptPortletInstanceWithHeaderPhase = (SupportsHeaderPhase) 
scriptPortletInstance;
+        }
+    }
+}

Added: 
portals/bridges/trunk/groovy/src/java/org/apache/portals/bridges/groovy/GroovyPreferencesValidator.java
URL: 
http://svn.apache.org/viewvc/portals/bridges/trunk/groovy/src/java/org/apache/portals/bridges/groovy/GroovyPreferencesValidator.java?view=auto&rev=549652
==============================================================================
--- 
portals/bridges/trunk/groovy/src/java/org/apache/portals/bridges/groovy/GroovyPreferencesValidator.java
 (added)
+++ 
portals/bridges/trunk/groovy/src/java/org/apache/portals/bridges/groovy/GroovyPreferencesValidator.java
 Thu Jun 21 17:39:22 2007
@@ -0,0 +1,216 @@
+/*
+ * 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 org.apache.portals.bridges.groovy;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.util.Collection;
+import java.util.ArrayList;
+
+import javax.portlet.PortletPreferences;
+import javax.portlet.PreferencesValidator;
+import javax.portlet.ValidatorException;
+
+import groovy.lang.GroovyClassLoader;
+import groovy.lang.GroovyCodeSource;
+import org.codehaus.groovy.control.CompilationFailedException;
+
+/**
+ * <p>
+ * GroovyPreferencesValidator parses and invokes a groovy-scripted validator. 
A groovy-scripted
+ * PreferencesValidator just need to be implemented like any other Java-based 
preferences validator. 
+ * 
+ * @author <a href="mailto:[EMAIL PROTECTED]">Woonsan Ko</a>
+ * @Id@
+ */
+public class GroovyPreferencesValidator implements PreferencesValidator
+{
+    public static final String SCRIPT_SOURCE_PREF_KEY = 
"validator-script-source";
+
+    public static final String SCRIPT_SOURCE_URL_ENCODING_PREF_KEY = 
"validator-script-source-uri-encoding";
+
+    public static final String AUTO_REFRESH_PREF_KEY = 
"validator-auto-refresh";
+
+    protected String scriptSourceUri;
+
+    protected String scriptSourceUriEncoding = "UTF-8";
+
+    protected boolean autoRefresh;
+
+    protected long parsedFileLastModified;
+
+    protected GroovyCodeSource groovyCodeSource;
+
+    protected PreferencesValidator scriptPreferencesValidatorInstance;
+
+    protected GroovyClassLoader groovyClassLoader;
+
+    public GroovyPreferencesValidator()
+    {
+    }
+    
+    public void validate(PortletPreferences preferences) throws 
ValidatorException
+    {
+        if (this.groovyCodeSource == null)
+        {
+            initialize(preferences);
+        }
+        
+        refreshPreferencesValidatorInstance();
+        
+        this.scriptPreferencesValidatorInstance.validate(preferences);
+    }
+
+    public void initialize(PortletPreferences preferences) throws 
ValidatorException
+    {
+        this.groovyClassLoader = new GroovyClassLoader();
+
+        this.autoRefresh = 
"true".equals(preferences.getValue(AUTO_REFRESH_PREF_KEY, null));
+
+        String param = 
preferences.getValue(SCRIPT_SOURCE_URL_ENCODING_PREF_KEY, null);
+
+        if (param != null)
+        {
+            this.scriptSourceUriEncoding = param;
+        }
+
+        this.scriptSourceUri = preferences.getValue(SCRIPT_SOURCE_PREF_KEY, 
null);
+
+        if (this.scriptSourceUri == null)
+        {
+            Collection failedKeys = new ArrayList();
+            failedKeys.add(SCRIPT_SOURCE_PREF_KEY);
+            throw new ValidatorException("Configuration failed: " + 
SCRIPT_SOURCE_PREF_KEY + " should be set properly!", failedKeys);
+        }
+        else
+        {
+            try
+            {
+                if (this.scriptSourceUri.startsWith("file:"))
+                {
+                    String decodedScriptSourceUri = this.scriptSourceUri;
+
+                    try
+                    {
+                        decodedScriptSourceUri = 
URLDecoder.decode(this.scriptSourceUri, this.scriptSourceUriEncoding);
+                    }
+                    catch (UnsupportedEncodingException encodingEx)
+                    {
+                        Collection failedKeys = new ArrayList();
+                        failedKeys.add(SCRIPT_SOURCE_URL_ENCODING_PREF_KEY);
+                        throw new ValidatorException("Unsupported encoding: " 
+ this.scriptSourceUriEncoding, failedKeys);
+                    }
+
+                    this.groovyCodeSource = new GroovyCodeSource(new 
File(decodedScriptSourceUri.substring(5)));
+                }
+                else if (this.scriptSourceUri.startsWith("classpath:"))
+                {
+                    String resourceURL = 
this.groovyClassLoader.getResource(this.scriptSourceUri.substring(10))
+                            .toString();
+
+                    if (resourceURL.startsWith("file:"))
+                    {
+                        String decodedScriptSourceUri = resourceURL;
+
+                        try
+                        {
+                            decodedScriptSourceUri = 
URLDecoder.decode(resourceURL, this.scriptSourceUriEncoding);
+                        }
+                        catch (UnsupportedEncodingException encodingEx)
+                        {
+                            Collection failedKeys = new ArrayList();
+                            
failedKeys.add(SCRIPT_SOURCE_URL_ENCODING_PREF_KEY);
+                            throw new ValidatorException("Unsupported 
encoding: " + this.scriptSourceUriEncoding, failedKeys);
+                        }
+
+                        this.groovyCodeSource = new GroovyCodeSource(new 
File(decodedScriptSourceUri.substring(5)));
+                    }
+                    else
+                    {
+                        Collection failedKeys = new ArrayList();
+                        failedKeys.add(SCRIPT_SOURCE_PREF_KEY);
+                        throw new ValidatorException(SCRIPT_SOURCE_PREF_KEY
+                                + " with 'classpath:' prefix should indicate 
to a local resource", failedKeys);
+                    }
+                }
+                else
+                {
+                    Collection failedKeys = new ArrayList();
+                    failedKeys.add(SCRIPT_SOURCE_PREF_KEY);
+                    throw new ValidatorException("Configuration failed: " + 
SCRIPT_SOURCE_PREF_KEY + " should be prefixed by 'file:' or 'classpath'.", 
failedKeys);
+                }
+            }
+            catch (FileNotFoundException e)
+            {
+                Collection failedKeys = new ArrayList();
+                failedKeys.add(SCRIPT_SOURCE_PREF_KEY);
+                throw new ValidatorException("File not found: " + 
this.scriptSourceUri, failedKeys);
+            }
+
+            this.groovyCodeSource.setCachable(!this.autoRefresh);
+        }
+    }
+
+    protected void refreshPreferencesValidatorInstance() throws 
ValidatorException
+    {
+        if (this.scriptPreferencesValidatorInstance == null)
+        {
+            try
+            {
+                createScriptPreferencesValidatorInstance();
+            }
+            catch (Exception ex)
+            {
+                Collection failedKeys = new ArrayList();
+                failedKeys.add(SCRIPT_SOURCE_PREF_KEY);
+                throw new ValidatorException("Could not compile script: " + 
this.scriptSourceUri, failedKeys);
+            }
+        }
+        else if (this.autoRefresh && isScriptFileModified())
+        {
+            synchronized (this.scriptPreferencesValidatorInstance)
+            {
+                try
+                {
+                    createScriptPreferencesValidatorInstance();
+                }
+                catch (Exception ex)
+                {
+                    Collection failedKeys = new ArrayList();
+                    failedKeys.add(SCRIPT_SOURCE_PREF_KEY);
+                    throw new ValidatorException("Could not compile script: " 
+ this.scriptSourceUri, failedKeys);
+                }
+            }
+        }
+    }
+
+    protected boolean isScriptFileModified()
+    {
+        return (this.groovyCodeSource.getFile().lastModified() > 
this.parsedFileLastModified);
+    }
+
+    protected void createScriptPreferencesValidatorInstance() throws 
CompilationFailedException, InstantiationException,
+            IOException, IllegalAccessException, ValidatorException
+    {
+        Class scriptPreferencesValidatorClass = 
this.groovyClassLoader.parseClass(this.groovyCodeSource);
+        this.scriptPreferencesValidatorInstance = (PreferencesValidator) 
scriptPreferencesValidatorClass.newInstance();
+        this.parsedFileLastModified = 
this.groovyCodeSource.getFile().lastModified();
+    }
+}

Added: portals/bridges/trunk/groovy/xdocs/headersupport.xml
URL: 
http://svn.apache.org/viewvc/portals/bridges/trunk/groovy/xdocs/headersupport.xml?view=auto&rev=549652
==============================================================================
--- portals/bridges/trunk/groovy/xdocs/headersupport.xml (added)
+++ portals/bridges/trunk/groovy/xdocs/headersupport.xml Thu Jun 21 17:39:22 
2007
@@ -0,0 +1,125 @@
+<?xml version="1.0"?>
+<!--
+       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.
+-->
+<document>
+       <properties>
+               <title>Jetspeed Header Phase Support</title>
+               <subtitle>Documentation for Creating a Groovy Portlet with 
Header Phase Support</subtitle>
+               <authors>
+                       <person name="Woonsan Ko" email="[EMAIL PROTECTED]" />
+               </authors>
+       </properties>
+       <body>
+               <section name="Jetspeed Groovy Portlet with Header Phase 
Support Guide">
+            <p>Jetspeed-2 provides an interface for a portlet to be able to 
support the pre-286 header phase. If you want your portlet to support this, 
just use GroovyPortletHeaderPhaseSupport class instead of GroovyPortlet, and 
implement SupportsHeaderPhase interface.</p>
+            
+            <subsection name="1. The Portlet Class supporting header phase">
+                               <p>
+                               Create the file HelloGroovyHeaderSupport.groovy 
in a directory called
+                               groovy-simplest/WEB-INF/classes:
+                <source><![CDATA[
+import javax.portlet.GenericPortlet;
+import javax.portlet.PortletContext;
+import javax.portlet.PortletRequestDispatcher;
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+import javax.portlet.ActionRequest;
+import javax.portlet.ActionResponse;
+import javax.portlet.PortletPreferences;
+import javax.portlet.ValidatorException;
+
+import org.apache.jetspeed.headerresource.HeaderResource;
+import org.apache.jetspeed.portlet.PortletHeaderRequest;
+import org.apache.jetspeed.portlet.PortletHeaderResponse;
+import org.apache.jetspeed.portlet.SupportsHeaderPhase;
+
+public class HelloGroovyHeaderSupport extends GenericPortlet implements 
SupportsHeaderPhase
+{
+    public void doHeader(PortletHeaderRequest request, PortletHeaderResponse 
response)
+    {
+        // use header resource component to ensure header logic is included 
only once
+        HeaderResource headerResource = response.getHeaderResource();
+        headerResource.dojoEnable();
+        
+        headerResource.dojoAddCoreLibraryRequire( "dojo.lang.*" );
+        headerResource.dojoAddCoreLibraryRequire( "dojo.event.*" );
+        headerResource.dojoAddCoreLibraryRequire( "dojo.io.*" );
+        headerResource.dojoAddCoreLibraryRequire( "dojo.widget.*" );
+        headerResource.dojoAddCoreLibraryRequire( "dojo.widget.Button" );
+     }
+    
+    public void doView(RenderRequest request, RenderResponse response)
+    {
+        response.setContentType("text/html");
+        
+        // Let's put a dojo widget button for simplicity here.
+        response.getWriter().println """
+            <button widgetId="helloGroovyButton" dojoType="Button" 
onclick="alert('Hello, Groovy');">
+            Say Hello
+            </button>
+        """
+    }
+    
+}
+                ]]></source>
+                For simplicity, in the above example, the doView() method just 
writes a simple HTML fragment to show DOJO button widget.
+                </p>
+            </subsection>
+            <subsection name="2. The portlet.xml">
+                       <p>
+                <source><![CDATA[
+<?xml version="1.0" encoding="UTF-8"?>
+<portlet-app id="velocitysimplest" version="1.0">
+  <portlet id="HelloGroovyHeaderSupport">
+    <portlet-name>HelloGroovyHeaderSupport</portlet-name>
+    <display-name>Hello Groovy with Header Support Display Name</display-name>
+     
<portlet-class>org.apache.portals.bridges.groovy.GroovyPortletHeaderPhaseSupport</portlet-class>
+    <init-param>
+      <name>script-source</name>
+      <!-- Note: You can set script source in three ways.
+                 The first is to use relative path uri,
+                 the second is to use file: url,
+                 and the last is to classpath: uri -->
+      <!--
+      <value>/WEB-INF/groovy/HelloGroovy.groovy</value>
+      <value>file:/C:/Program Files/Apache Software Foundation/Tomcat 
5.5/webapps/demo/WEB-INF/groovy/HelloGroovy.groovy</value>
+      -->
+      <value>classpath:HelloGroovyHeaderSupport.groovy</value>
+    </init-param>
+    <!-- If auto-refresh is true, then a modification of script source applies 
instantly. -->
+    <init-param>
+      <name>auto-refresh</name>
+      <value>true</value>
+    </init-param>
+    <supports>
+      <mime-type>text/html</mime-type>
+      <portlet-mode>VIEW</portlet-mode>
+    </supports>
+    <supported-locale>en</supported-locale>
+    <portlet-info>
+      <title>Hello Groovy with Header Support Title</title>
+      <short-title>Hello Groovy with Header Support Short Title</short-title>
+    </portlet-info>
+  </portlet>
+</portlet-app>
+                ]]></source>
+                The &lt;portlet-class&gt; was replaced with 
'org.apache.portals.bridges.groovy.GroovyPortletHeaderPhaseSupport' instead of 
'org.apache.portals.bridges.groovy.GroovyPortlet' to support header phase.
+                </p>
+            </subsection>
+               </section>
+       </body>
+</document>

Modified: portals/bridges/trunk/groovy/xdocs/index.xml
URL: 
http://svn.apache.org/viewvc/portals/bridges/trunk/groovy/xdocs/index.xml?view=diff&rev=549652&r1=549651&r2=549652
==============================================================================
--- portals/bridges/trunk/groovy/xdocs/index.xml (original)
+++ portals/bridges/trunk/groovy/xdocs/index.xml Thu Jun 21 17:39:22 2007
@@ -228,11 +228,24 @@
                        </subsection>
             <subsection name="9. Additional Notes">
                 <ul>
-                    <li>In this example, JSP and JSTL is used for view pages. 
However, you can use other technologies such as Velocity, Groovlet or Groovy 
template.</li>
-                    <li>GroovyPortlet instantiates a groovy-scripted portlet 
instance just like any Java portlet, and so you can use any techniques used in 
Java portlet programming. For example, your groovy script portlet can extend 
org.apache.portals.bridges.common.GenericServletPortlet to simplify 
implementation.</li>
                     <li>You can make the script source simpler than Java. See 
the groovy documentation.</li>
+                    <li>GroovyPortlet instantiates a groovy-scripted portlet 
instance just like any Java portlet, and so you can use any techniques used in 
Java portlet programming. For example, your groovy script portlet can extend 
org.apache.portals.bridges.common.GenericServletPortlet to simplify 
implementation.</li>
+                    <li>In this example, JSP and JSTL is used for view pages. 
However, you can use other technologies such as Velocity, Groovlet or Groovy 
template.</li>
+                    <li>If you use Groovlet or Groovy template, a solution for 
getting renderRequest and renderResponse can be like this:
+                    <source>
+def renderRequest = request.getAttribute("javax.portlet.request")
+def renderResponse = request.getAttribute("javax.portlet.response")
+                    </source>
+                    </li>
                 </ul>
                        </subsection>
+            <subsection name="10. See Also">
+                <p>You can write preferences validator with groovy, and you 
can write a groovy script portlet supporting header phase (pre-286 feature).</p>
+                <ul>
+                    <li><a href="prefvalidate.html">Jetspeed Groovy 
PreferencesValidator Guide</a></li>
+                    <li><a href="headersupport.html">Jetspeed Groovy Portlet 
with Header Phase Support Guide</a></li>
+                </ul>
+            </subsection>
                </section>
        </body>
 </document>

Modified: portals/bridges/trunk/groovy/xdocs/navigation.xml
URL: 
http://svn.apache.org/viewvc/portals/bridges/trunk/groovy/xdocs/navigation.xml?view=diff&rev=549652&r1=549651&r2=549652
==============================================================================
--- portals/bridges/trunk/groovy/xdocs/navigation.xml (original)
+++ portals/bridges/trunk/groovy/xdocs/navigation.xml Thu Jun 21 17:39:22 2007
@@ -25,7 +25,9 @@
     </links>
 
     <menu name="Groovy Bridge">
-      <item name="Guide" href="index.html"/>
+      <item name="Jetspeed Groovy Portlet Guide" href="index.html"/>
+      <item name="Jetspeed Groovy PreferencesValidator Guide" 
href="prefvalidate.html"/>
+      <item name="Jetspeed Groovy Portlet with Header Phase Support Guide" 
href="headersupport.html"/>
     </menu>      
                   
   </body>

Added: portals/bridges/trunk/groovy/xdocs/prefvalidate.xml
URL: 
http://svn.apache.org/viewvc/portals/bridges/trunk/groovy/xdocs/prefvalidate.xml?view=auto&rev=549652
==============================================================================
--- portals/bridges/trunk/groovy/xdocs/prefvalidate.xml (added)
+++ portals/bridges/trunk/groovy/xdocs/prefvalidate.xml Thu Jun 21 17:39:22 2007
@@ -0,0 +1,157 @@
+<?xml version="1.0"?>
+<!--
+       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.
+-->
+<document>
+       <properties>
+               <title>How to use Groovy PreferencesValidator</title>
+               <subtitle>Documentation for Creating a Groovy 
PreferencesValidator</subtitle>
+               <authors>
+                       <person name="Woonsan Ko" email="[EMAIL PROTECTED]" />
+               </authors>
+       </properties>
+       <body>
+               <section name="Jetspeed Groovy PreferencesValidator Guide">
+                       <p>
+                               This guide provides a tutorial for creating a 
Groovy Preferences Validator.
+                       </p>
+                       <subsection name="1. The Groovy PreferencesValidator 
Class">
+                <p>Create the file HelloGroovyValidator.groovy in a directory 
called groovy-simplest/WEB-INF/classes:
+                <source><![CDATA[
+import javax.portlet.PortletPreferences;
+import javax.portlet.PreferencesValidator;
+import javax.portlet.ValidatorException;
+
+public class HelloGroovyValidator implements PreferencesValidator
+{
+    public void validate(PortletPreferences preferences)
+    {
+        String message = preferences.getValue("message", null);
+        
+        if (message == null || "".equals(message.trim()))
+        {
+            def failedKeys = [ "message" ];
+            throw new ValidatorException("message must be set!", failedKeys);
+        }
+    }
+}               ]]></source>
+                </p>
+            </subsection>
+                       <subsection name="2. The portlet.xml">
+                       <p>
+                       Edit the file portlet.xml in the 
groovy-simplest/WEB-INF directory to add Groovy PreferencesValidator. In this 
case, &lt;portlet-preferences&gt; element is added to the previous example.
+                       <source><![CDATA[
+<?xml version="1.0" encoding="UTF-8"?>
+<portlet-app id="velocitysimplest" version="1.0">
+  <portlet id="HelloGroovy">
+    <portlet-name>HelloGroovy</portlet-name>
+    <display-name>Hello Groovy Display Name</display-name>
+    
<portlet-class>org.apache.portals.bridges.groovy.GroovyPortlet</portlet-class>
+    <init-param>
+      <name>script-source</name>
+      <!-- Note: You can set script source in three ways.
+                 The first is to use relative path uri,
+                 the second is to use file: url,
+                 and the last is to classpath: uri -->
+      <!--
+      <value>/WEB-INF/groovy/HelloGroovy.groovy</value>
+      <value>file:/C:/Program Files/Apache Software Foundation/Tomcat 
5.5/webapps/demo/WEB-INF/groovy/HelloGroovy.groovy</value>
+      -->
+      <value>classpath:HelloGroovy.groovy</value>
+    </init-param>
+    <!-- If auto-refresh is true, then a modification of script source applies 
instantly. -->
+    <init-param>
+      <name>auto-refresh</name>
+      <value>true</value>
+    </init-param>
+    <supports>
+      <mime-type>text/html</mime-type>
+      <portlet-mode>VIEW</portlet-mode>
+      <portlet-mode>EDIT</portlet-mode>
+      <portlet-mode>HELP</portlet-mode>
+    </supports>
+    <supported-locale>en</supported-locale>
+    <portlet-info>
+      <title>Hello Groovy Title</title>
+      <short-title>Hello Groovy Short Title</short-title>
+    </portlet-info>
+    <portlet-preferences>
+      <preference>
+        <name>validator-script-source</name>
+        <!-- Note: You can set script source in two ways.
+                   The first is to use classpath: path uri,
+                   and the other is to file: url.
+                   Note that relative path uri is not supported for 
preferences validator. -->
+        <value>classpath:HelloGroovyValidator.groovy</value>
+        <!--
+        <value>file:/C:/Program Files/Apache Software Foundation/Tomcat 
5.5/webapps/demo/WEB-INF/groovy/HelloGroovyValidator.groovy</value>
+        -->
+        <read-only>true</read-only>
+      </preference>
+      <preference>
+        <name>validator-auto-refresh</name>
+        <!-- If validator-auto-refresh is true, 
+             then a modification of script source applies instantly. -->
+        <value>true</value>
+        <read-only>true</read-only>
+      </preference>
+      
<preferences-validator>org.apache.portals.bridges.groovy.GroovyPreferencesValidator</preferences-validator>
+    </portlet-preferences>
+  </portlet>
+</portlet-app>]]>
+                       </source>
+                       </p>
+                       </subsection>
+                       <subsection name="3. How to handle validation 
exception">
+                       <p>If you set a preferences validator, you should 
handle a validation exception in your portlet code like the following example. 
The HelloGroovy.groovy in the previous example now handles validation exception 
during PortletPreferences.store() call.
+                <source><![CDATA[
+    public void processAction(ActionRequest request, ActionResponse response)
+    {
+        String message = request.getParameter("message");
+        
+        PortletPreferences prefs = request.getPreferences();
+        prefs.setValue("message", message);
+        
+        try {
+            prefs.store();
+        } catch (ValidatorException e) {
+            // send this error information to the rendering phase.
+            response.setRenderParameter("errorMessage", e.getMessage());
+        }
+    }
+                ]]></source>
+                </p>
+            </subsection>
+            <subsection name="4. Additional Notes">
+                <p>In groovy, you can use powerful regular expressions like 
the following example:
+                <source><![CDATA[
+    public void validate(PortletPreferences preferences)
+    {
+        // Let's assume that we have a preference for an email address.
+        String email = preferences.getValue("email", "");
+        
+        if (!(email ==~ /[EMAIL PROTECTED]/))
+        {
+            def failedKeys = [ "email" ];
+            throw new ValidatorException("message must be set!", failedKeys);
+        }
+    }
+                ]]></source>
+                </p>
+                       </subsection>
+               </section>
+       </body>
+</document>

Modified: portals/bridges/trunk/project.properties
URL: 
http://svn.apache.org/viewvc/portals/bridges/trunk/project.properties?view=diff&rev=549652&r1=549651&r2=549652
==============================================================================
--- portals/bridges/trunk/project.properties (original)
+++ portals/bridges/trunk/project.properties Thu Jun 21 17:39:22 2007
@@ -106,6 +106,7 @@
 tomahawk.version=1.1.5
 spring.version=2.0.5
 jython.version=2.2a1
+jetspeed.api.version=2.1.1-beta1
 jetspeed.rewriter.version=2.1.1-beta1
 log4j.version=1.2.14
 # Whether or not to include log4j in war files.  Your container may already 
have this.



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to