Initial Import of Pluto 1.1 seed code.

git-svn-id: https://svn.apache.org/repos/asf/portals/pluto/branches/container@54049 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/.cvsignore b/.cvsignore
new file mode 100644
index 0000000..28002d5
--- /dev/null
+++ b/.cvsignore
@@ -0,0 +1,4 @@
+target

+*.log

+.classpath

+.project
\ No newline at end of file
diff --git a/build.xml b/build.xml
new file mode 100644
index 0000000..1d189a9
--- /dev/null
+++ b/build.xml
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<!-- 

+Copyright 2004 The Apache Software Foundation.

+Licensed  under the  Apache License,  Version 2.0  (the "License");

+you may not use  this file  except in  compliance with the License.

+You may obtain a copy of the License at 

+

+http://www.apache.org/licenses/LICENSE-2.0

+

+Unless required by applicable law or agreed to in writing, software

+distributed  under the  License is distributed on an "AS IS" BASIS,

+WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or

+implied.

+

+See the License for the specific language governing permissions and

+limitations under the License.

+-->

+<!--build.xml generated by maven from project.xml version 1.0

+  on date February 12 2004, time 1040 and patched absolute pathes -->

+

+<project default="jar" name="pluto" basedir=".">

+    <property name="defaulttargetdir" value="target">

+    </property>

+    <property name="libdir" value="target/lib">

+    </property>

+    <property name="classesdir" value="target/classes">

+    </property>

+    <property name="testclassesdir" value="target/test-classes">

+    </property>

+    <property name="testreportdir" value="target/test-reports">

+    </property>

+    <property name="distdir" value="dist">

+    </property>

+    <property name="javadocdir" value="dist/docs/api">

+    </property>

+    <property name="final.name" value="pluto-1.0">

+    </property>

+    <target name="init" description="o Initializes some properties">

+        <mkdir dir="${libdir}">

+        </mkdir>

+        <condition property="noget">

+            <equals arg2="only" arg1="${build.sysclasspath}">

+            </equals>

+        </condition>

+    </target>

+    <target name="compile" description="o Compile the code" depends="get-deps">

+        <mkdir dir="${classesdir}">

+        </mkdir>

+        <javac destdir="${classesdir}" deprecation="true" debug="true" optimize="false" excludes="**/package.html">

+            <src>

+                <pathelement location="src\java">

+                </pathelement>

+            </src>

+            <classpath>

+                <fileset dir="${libdir}">

+                    <include name="*.jar">

+                    </include>

+                </fileset>

+            </classpath>

+        </javac>

+    </target>

+    <target name="jar" description="o Create the jar" depends="compile,test">

+        <jar jarfile="target/${final.name}.jar" excludes="**/package.html" basedir="${classesdir}">

+        </jar>

+    </target>

+    <target name="clean" description="o Clean up the generated directories">

+        <delete dir="${defaulttargetdir}">

+        </delete>

+        <delete dir="${distdir}">

+        </delete>

+    </target>

+    <target name="dist" description="o Create a distribution" depends="jar, javadoc">

+        <mkdir dir="dist">

+        </mkdir>

+        <copy todir="dist">

+            <fileset dir="${defaulttargetdir}" includes="*.jar">

+            </fileset>

+            <fileset dir="${basedir}" includes="LICENSE*, README*">

+            </fileset>

+        </copy>

+    </target>

+    <target name="test" description="o Run the test cases" if="test.failure" depends="internal-test">

+        <fail message="There were test failures.">

+        </fail>

+    </target>

+    <target name="internal-test" depends="compile-tests">

+    </target>

+    <target name="compile-tests" depends="compile">

+    </target>

+    <target name="javadoc" description="o Generate javadoc" depends="jar">

+        <mkdir dir="${javadocdir}">

+        </mkdir>

+        <tstamp>

+            <format pattern="2003-yyyy" property="year">

+            </format>

+        </tstamp>

+        <property name="copyright" value="Copyright &amp;copy;  Apache Software Foundation. All Rights Reserved.">

+        </property>

+        <property name="title" value="Pluto Portlet Container 1.0 API">

+        </property>

+        <!--javadoc use="true" private="true" destdir="${javadocdir}" author="true" version="true" sourcepath="C:\home\Programs\cvs-1.11.5\jakarta-pluto\container\src\java" packagenames="org.apache.pluto.*"-->

+        <javadoc use="true" private="true" destdir="${javadocdir}" author="true" version="true" sourcepath="src\java" packagenames="org.apache.pluto.*">

+            <classpath>

+                <fileset dir="${libdir}">

+                    <include name="*.jar">

+                    </include>

+                </fileset>

+                <pathelement location="target/${final.name}.jar">

+                </pathelement>

+            </classpath>

+        </javadoc>

+    </target>

+    <target name="get-deps" unless="noget" depends="init">

+        <get dest="${libdir}/regexp-1.3-dev.jar" usetimestamp="true" ignoreerrors="true" src="http://www.ibiblio.org/maven/regexp/jars/regexp-1.3-dev.jar">

+        </get>

+        <get dest="${libdir}/portlet-api-1.0.jar" usetimestamp="true" ignoreerrors="true" src="file:${basedir}/../api/target/portlet-api-1.0.jar">

+        </get>

+        <get dest="${libdir}/servletapi-2.3.jar" usetimestamp="true" ignoreerrors="true" src="http://www.ibiblio.org/maven/servletapi/jars/servletapi-2.3.jar">

+        </get>

+        <get dest="${libdir}/junit-3.8.1.jar" usetimestamp="true" ignoreerrors="true" src="http://www.ibiblio.org/maven/junit/jars/junit-3.8.1.jar">

+        </get>

+        <get dest="${libdir}/ant-1.5.jar" usetimestamp="true" ignoreerrors="true" src="http://www.ibiblio.org/maven/ant/jars/ant-1.5.jar">

+        </get>

+        <get dest="${libdir}/ant-optional-1.5.jar" usetimestamp="true" ignoreerrors="true" src="http://www.ibiblio.org/maven/ant/jars/ant-optional-1.5.jar">

+        </get>

+    </target>

+    <target name="install-maven">

+        <get dest="${user.home}/maven-install-latest.jar" usetimestamp="true" src="${repo}/maven/maven-install-latest.jar">

+        </get>

+        <unjar dest="${maven.home}" src="${user.home}/maven-install-latest.jar">

+        </unjar>

+    </target>

+</project>

diff --git a/container.iml b/container.iml
new file mode 100644
index 0000000..fc992a5
--- /dev/null
+++ b/container.iml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<module version="4" relativePaths="true" type="JAVA_MODULE">

+  <component name="ModuleRootManager" />

+  <component name="NewModuleRootManager">

+    <output url="file://$MODULE_DIR$/target/classes" />

+    <exclude-output />

+    <exclude-exploded />

+    <output-test url="file://$MODULE_DIR$/target/test-classes" />

+    <content url="file://$MODULE_DIR$">

+      <sourceFolder url="file://$MODULE_DIR$/src/conf" isTestSource="false" />

+      <sourceFolder url="file://$MODULE_DIR$/src/java" isTestSource="false" />

+      <excludeFolder url="file://$MODULE_DIR$/target" />

+    </content>

+    <orderEntry type="inheritedJdk" />

+    <orderEntry type="sourceFolder" forTests="false" />

+    <orderEntry type="library" name="servlet-api-2.3" level="application" />

+    <orderEntry type="library" name="portlet-api-1.0" level="application" />

+    <orderEntry type="module" module-name="binding" />

+    <orderEntry type="library" name="commons-logging-1.0.3" level="application" />

+    <orderEntryProperties />

+  </component>

+</module>

+

diff --git a/maven.xml b/maven.xml
new file mode 100644
index 0000000..b4661a9
--- /dev/null
+++ b/maven.xml
@@ -0,0 +1,27 @@
+<!-- 

+Copyright 2004 The Apache Software Foundation.

+Licensed  under the  Apache License,  Version 2.0  (the "License");

+you may not use  this file  except in  compliance with the License.

+You may obtain a copy of the License at 

+

+http://www.apache.org/licenses/LICENSE-2.0

+

+Unless required by applicable law or agreed to in writing, software

+distributed  under the  License is distributed on an "AS IS" BASIS,

+WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or

+implied.

+

+See the License for the specific language governing permissions and

+limitations under the License.

+-->

+<project default="java:jar"

+    xmlns:j="jelly:core"

+    xmlns:maven="jelly:maven"

+    xmlns:ant="jelly:ant">

+

+    <postGoal name="dist:prepare-bin-filesystem">

+        <ant:copy todir="${maven.dist.bin.assembly.dir}">

+            <ant:fileset dir="${basedir}/.." includes="LICENSE.TXT"/>

+        </ant:copy>

+    </postGoal>

+</project>

diff --git a/project.properties b/project.properties
new file mode 100644
index 0000000..61bb1cc
--- /dev/null
+++ b/project.properties
@@ -0,0 +1,33 @@
+# 

+# Copyright 2004 The Apache Software Foundation.

+# Licensed  under the  Apache License,  Version 2.0  (the "License");

+# you may not use  this file  except in  compliance with the License.

+# You may obtain a copy of the License at 

+# 

+#   http://www.apache.org/licenses/LICENSE-2.0

+# 

+# Unless required by applicable law or agreed to in writing, software

+# distributed  under the  License is distributed on an "AS IS" BASIS,

+# WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or

+# implied.

+#  

+# See the License for the specific language governing permissions and

+# limitations under the License.

+#

+#

+# Display the date on the Maven web site

+maven.xdoc.date = left

+

+# Display the maven version the web site is documenting

+maven.xdoc.version = ${pom.currentVersion}

+

+maven.compile.deprecation=on

+

+maven.junit.fork = true

+

+maven.checkstyle.header.file = ${basedir}/../LICENSE.TXT

+maven.license.licenseFile=${basedir}/../LICENSE.TXT

+

+maven.multiproject.type = jar

+

+maven.checkstyle.format = turbine

diff --git a/project.xml b/project.xml
new file mode 100644
index 0000000..3239fb9
--- /dev/null
+++ b/project.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<!-- 

+Copyright 2004 The Apache Software Foundation.

+Licensed  under the  Apache License,  Version 2.0  (the "License");

+you may not use  this file  except in  compliance with the License.

+You may obtain a copy of the License at 

+

+http://www.apache.org/licenses/LICENSE-2.0

+

+Unless required by applicable law or agreed to in writing, software

+distributed  under the  License is distributed on an "AS IS" BASIS,

+WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or

+implied.

+

+See the License for the specific language governing permissions and

+limitations under the License.

+-->

+<project>

+    <extend>${basedir}/../project.xml</extend>

+    <name>Pluto Portlet Container</name>

+    <id>pluto</id>

+

+    <organization>

+        <logo>/../../images/apache-portals.gif</logo>

+    </organization>

+

+    <logo>/../../images/pluto.png</logo>

+

+    <shortDescription>A JSR-168 Compliant Portlet Engine.</shortDescription>

+

+    <description>

+  Pluto is the Reference Implementation of the Java 

+  Portlet Specfication.  Portlets are designed to run 

+  in the context of a portal. They are written to the 

+  Portlet API which are similar to the Servlet API.

+  A portlet container provides a runtime environment 

+  for portlets implemented according to the Portlet 

+  API. In this environment portlets can be instantiated,

+  used and finally destroyed. The portlet container is 

+  not a stand-alone container like the servlet container; 

+  instead it is implemented as a thin layer on top of 

+  the servlet container and reuses the functionality 

+  provided by the servlet container.

+    </description>

+

+    <dependencies>

+

+        <dependency>

+            <id>portlet-api</id>

+            <groupId>portlet-api</groupId>

+            <version>1.0</version>

+            <properties>

+                <war.bundle.jar>false</war.bundle.jar>

+            </properties>

+        </dependency>

+

+        <dependency>

+            <id>servletapi</id>

+            <version>2.3</version>

+            <properties>

+                <war.bundle.jar>false</war.bundle.jar>

+            </properties>

+        </dependency>

+

+        <dependency>

+            <groupId>pluto</groupId>

+            <artifactId>pluto-binding</artifactId>

+            <version>1.0.1</version>

+        </dependency>

+

+        <dependency>

+            <id>commons-logging</id>

+            <version>1.0.4</version>

+        </dependency>

+

+    </dependencies>

+

+    <build>

+

+        <nagEmailAddress>pluto-dev@jakarta.apache.org</nagEmailAddress>

+

+        <sourceDirectory>src/java</sourceDirectory>

+        <aspectSourceDirectory/>

+

+        <unitTestSourceDirectory>src/test</unitTestSourceDirectory>

+

+        <unitTest>

+            <includes>

+                <include>**/*Test.java</include>

+            </includes>

+        </unitTest>

+

+        <integrationUnitTestSourceDirectory>src/rttest</integrationUnitTestSourceDirectory>

+

+        <integrationUnitTest>

+            <includes>

+                <include>**/*Test.java</include>

+            </includes>

+        </integrationUnitTest>

+

+

+        <resources>

+            <resource>

+                <directory>src/conf</directory>

+                <includes>

+                    <include>**/*.properties</include>

+                    <include>**/*.xml</include>

+                </includes>

+            </resource>

+        </resources>

+

+        <jars/>

+

+    </build>

+

+</project>

diff --git a/src/conf/org/apache/pluto/core/LocalStrings.properties b/src/conf/org/apache/pluto/core/LocalStrings.properties
new file mode 100644
index 0000000..f1a1bb0
--- /dev/null
+++ b/src/conf/org/apache/pluto/core/LocalStrings.properties
@@ -0,0 +1 @@
+pluto.container.init=Unable to initialize portlet container {0}
\ No newline at end of file
diff --git a/src/conf/org/apache/pluto/core/impl/LocalStrings.properties b/src/conf/org/apache/pluto/core/impl/LocalStrings.properties
new file mode 100644
index 0000000..9930273
--- /dev/null
+++ b/src/conf/org/apache/pluto/core/impl/LocalStrings.properties
@@ -0,0 +1,9 @@
+

+## PortletModeException caused by Portal

+javax.portlet.PortletModeException.portlet=Portlet mode '{0}' is not supported by the portal.

+

+## PortletModeException caused by Portlet

+javax.portlet.PortletModeException.portal=Portlet mode '{0}' is not supported by the portlet.

+

+## PortletModeException caused by null mode

+javax.portlet.PortletModeException.null=Portlet mode may not be null.

diff --git a/src/conf/org/apache/pluto/environment.properties b/src/conf/org/apache/pluto/environment.properties
new file mode 100644
index 0000000..93c4984
--- /dev/null
+++ b/src/conf/org/apache/pluto/environment.properties
@@ -0,0 +1,7 @@
+pluto.container.name=Pluto

+pluto.container.version.major=1

+pluto.container.version.minor=0.1

+

+javax.portlet.version.major=1

+javax.portlet.version.minor=0

+

diff --git a/src/java/org/apache/pluto/Constants.java b/src/java/org/apache/pluto/Constants.java
new file mode 100644
index 0000000..0c74d19
--- /dev/null
+++ b/src/java/org/apache/pluto/Constants.java
@@ -0,0 +1,77 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto;

+

+/**

+ * Constant values used to bind internal portlet objects as attributes,

+ * typically to a request.

+ * @version 1.0

+ */

+public class Constants {

+

+    /**

+     * The key used to bind the <code>PortletRequest</code> to the underlying

+     * <code>HttpServletRequest</code>.

+     */

+    public final static String PORTLET_REQUEST = "javax.portlet.request";

+

+    /**

+     * The key used to bind the <code>PortletResponse</code> to the underlying

+     * <code>HttpServletRequest</code>.

+     */

+    public final static String PORTLET_RESPONSE = "javax.portlet.response";

+

+    /**

+     * The key used to bind the <code>PortletConfig</code> to the underlying

+     * PortletConfig.

+     */

+    public final static String PORTLET_CONFIG = "javax.portlet.config";

+

+    /**

+     * The key used to bind the method of processing being requested by the

+     * container to the underlying <code>PortletRquest</code>.

+     */

+    public final static String METHOD_ID = "org.apache.pluto.core.method";

+

+    /**

+     * The unique method identifier for render requests.  Render requests are

+     * requested through a call to the {@link PortletContainer#doRender(org.apache.pluto.PortletWindow,

+        * javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}

+     * method.

+     */

+    public final static Integer METHOD_RENDER = new Integer(1);

+

+    /**

+     * The unique method identifier for render requests.  Render requests are

+     * requested through a call to the {@link PortletContainer#doAction(org.apache.pluto.PortletWindow,

+        * javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}

+     * method.

+     */

+    public final static Integer METHOD_ACTION = new Integer(3);

+

+    /**

+     * The unique method identifier for render requests.  Render requests are

+     * requested through a call to the {@link PortletContainer#doLoad(org.apache.pluto.PortletWindow,

+        * javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}

+     * method.

+     */

+    public final static Integer METHOD_NOOP = new Integer(5);

+

+}

diff --git a/src/java/org/apache/pluto/PortletContainer.java b/src/java/org/apache/pluto/PortletContainer.java
new file mode 100644
index 0000000..bb76f46
--- /dev/null
+++ b/src/java/org/apache/pluto/PortletContainer.java
@@ -0,0 +1,130 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.apache.pluto;

+

+import java.io.IOException;

+

+import javax.portlet.PortletException;

+import javax.servlet.ServletContext;

+import javax.servlet.http.HttpServletRequest;

+import javax.servlet.http.HttpServletResponse;

+

+import org.apache.pluto.services.PortletContainerServices;

+

+/**

+ * The publicized entry point into Pluto. The base functionality of the portlet

+ * container can be enhanced or even modified by PortletContainerServices.

+ * <p/>

+ * <P> The methods of this class have to be called in the following order:

+ * <TABLE> <TR><TH>Method</TH><TH>Description</TH><TH>Constraints</TH></TR>

+ * <TR><TD>{@link #init(javax.servlet.ServletContext)}</TD> <TD>Initialized the

+ * portlet container.</TD> <TD>Performed only once per container

+ * lifecycle.</TD></TR>

+ * <p/>

+ * <TR><TD>{@link #doAction(org.apache.pluto.PortletWindow,

+    * javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}</TD>

+ * <TD>Perform the action for the targeted portlet</TD> <TD>Optionally performed

+ * for a single portlet per request</TD></TR>

+ * <p/>

+ * <TR><TD>{@link #doRender(org.apache.pluto.PortletWindow,

+    * javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}</TD>

+ * <TD>Render the portlet</TD> <TD>Performed once for each portlet per

+ * request.</TD></TR>

+ * <p/>

+ * <TR><TD>{@link #destroy()}</TD> <TD>Destroy and remove container from

+ * service.</TD> <TD>Performed only once per container lifecylce</TD></TR>

+ * @version $Id: PortletContainer.java 36010 2004-07-30 14:16:06Z ddewolf $

+ */

+public interface PortletContainer {

+

+    /**

+     * Initializes the portlet container.

+     * @param context the servlet configuration

+     * @throws PortletContainerException if an error occurs while initializing

+     *                                   the container

+     */

+    public void init(ServletContext context) throws PortletContainerException;

+

+    /**

+     * Shuts down the portlet container. After calling this method it is no

+     * longer valid to call any method on the portlet container.

+     * @throws PortletContainerException if an error occurs while shutting down

+     *                                   the container

+     */

+    public void destroy() throws PortletContainerException;

+

+    /**

+     * Calls the render method of the given portlet window.

+     * @param internalPortletWindow the portlet Window

+     * @param request               the servlet request

+     * @param response              the servlet response

+     * @throws PortletException          if one portlet has trouble fulfilling

+     *                                   the request

+     * @throws IOException               if the streaming causes an I/O problem

+     * @throws PortletContainerException if the portlet container implementation

+     *                                   has trouble fulfilling the request

+     */

+    public void doRender(PortletWindow internalPortletWindow,

+                         HttpServletRequest request,

+                         HttpServletResponse response)

+        throws PortletException, IOException, PortletContainerException;

+

+

+    /**

+     * Indicates that a portlet action occured in the current request and calls

+     * the processAction method of this portlet.

+     * @param internalPortletWindow the portlet Window

+     * @param request               the servlet request

+     * @param response              the servlet response

+     * @throws PortletException          if one portlet has trouble fulfilling

+     *                                   the request

+     * @throws PortletContainerException if the portlet container implementation

+     *                                   has trouble fulfilling the request

+     */

+    public void doAction(PortletWindow internalPortletWindow,

+                         HttpServletRequest request,

+                         HttpServletResponse response)

+        throws PortletException, IOException, PortletContainerException;

+

+    /**

+     * Indicates that the portlet must be initialized

+     * @param internalPortletWindow the portlet Window

+     * @param servletRequest        the servlet request

+     * @param servletResponse       the servlet response

+     * @throws PortletException          if one portlet has trouble fulfilling

+     *                                   the request

+     * @throws PortletContainerException if the portlet container implementation

+     *                                   has trouble fulfilling the request

+     */

+    public void doLoad(PortletWindow internalPortletWindow,

+                       HttpServletRequest servletRequest,

+                       HttpServletResponse servletResponse)

+        throws PortletException, PortletContainerException;

+

+    /**

+     * Returns whether the container is already initialized or not.

+     * @return <code>true</code> if the container is initialized

+     */

+    public boolean isInitialized();

+

+    /**

+     * Retrieve the unique container name

+     * @return

+     */

+    public String getName();

+

+    public PortletContainerServices getContainerServices();

+}

diff --git a/src/java/org/apache/pluto/PortletContainerException.java b/src/java/org/apache/pluto/PortletContainerException.java
new file mode 100644
index 0000000..ecc52bc
--- /dev/null
+++ b/src/java/org/apache/pluto/PortletContainerException.java
@@ -0,0 +1,82 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto;

+

+/**

+ * Thrown when an internal portlet container exception occurs within Pluto.

+ * This type of exception indicates an error from which the container is not

+ * able to recover.

+ * @version 1.0

+ */

+public class PortletContainerException extends Exception {

+

+    private Throwable cause;

+

+

+    /**

+     * Constructs a new PortletContainerException. This exception will have no

+     * message and no root cause.

+     */

+    public PortletContainerException() {

+

+    }

+

+

+    /**

+     * Constructs a new PortletContainerException with the given message.

+     * @param text the message explaining the exception occurance

+     */

+    public PortletContainerException(String text) {

+        super(text);

+    }

+

+    /**

+     * Constructs a new PortletContainerException with the given message and

+     * root cause.

+     * @param text  the message explaining the exception occurance

+     * @param cause the root cause of the is exception

+     */

+    public PortletContainerException(String text, Throwable cause) {

+        super(text);

+        this.cause = cause;

+    }

+

+    /**

+     * * Constructs a new portlet invoker exception when the portlet needs to

+     * throw an * exception. The exception's message is based on the localized

+     * message * of the underlying exception. * * @param   cause *          the

+     * root cause

+     */

+

+    public PortletContainerException(Throwable cause) {

+        super(cause.getLocalizedMessage());

+

+        this.cause = cause;

+    }

+

+    /**

+     * * Returns the exception that cause this portlet exception. * * @return

+     * the <CODE>Throwable</CODE> that caused this portlet exception.

+     */

+

+    public Throwable getRootCause() {

+        return (cause);

+    }

+}

diff --git a/src/java/org/apache/pluto/PortletContainerFactory.java b/src/java/org/apache/pluto/PortletContainerFactory.java
new file mode 100644
index 0000000..fe0f62a
--- /dev/null
+++ b/src/java/org/apache/pluto/PortletContainerFactory.java
@@ -0,0 +1,79 @@
+/*

+ * Copyright 2004 The Apache Software Foundation.

+ *

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ *

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.apache.pluto;

+

+import org.apache.commons.logging.Log;

+import org.apache.commons.logging.LogFactory;

+import org.apache.pluto.core.PortletContainerImpl;

+import org.apache.pluto.services.PortletContainerServices;

+

+/**

+ * Factory used to create new PortletContainer instances.  The factor constructs

+ * the underlying pluto container implementation by using the the given

+ * container services.

+ * @author <a href="ddewolf@apache.org">David H. DeWolf</a>

+ * @version 1.0

+ * @since Sep 18, 2004

+ */

+public class PortletContainerFactory {

+

+    private static final Log LOG =

+        LogFactory.getLog(PortletContainerFactory.class);

+

+

+    /**

+     * Singleton instance of the <code>PortletContainerFactory</code>

+     */

+    private static PortletContainerFactory factory;

+

+    /**

+     * Accessor method for the singleton instance of the

+     * <code>PortletContainerFactory</code>.

+     * @return singleton instance of the PortletContainerFactory

+     */

+    public static PortletContainerFactory getInstance() {

+        if (factory == null) {

+            factory = new PortletContainerFactory();

+        }

+        return factory;

+    }

+

+    /**

+     * Hidden constructor.

+     */

+    private PortletContainerFactory() {

+

+    }

+

+    /**

+     * Create a container with the given name, initialized from the given

+     * servlet config, and using the given container services.

+     * @param name

+     * @param env

+     * @return newly created PortletContainer

+     * @throws PortletContainerException

+     */

+    public PortletContainer createContainer(String name,

+                                            PortletContainerServices env)

+        throws PortletContainerException {

+        PortletContainer container = new PortletContainerImpl(name, env);

+        if (LOG.isInfoEnabled()) {

+            LOG.info("Portlet Container [" + name + "] created.");

+        }

+        return container;

+    }

+}

+

diff --git a/src/java/org/apache/pluto/PortletWindow.java b/src/java/org/apache/pluto/PortletWindow.java
new file mode 100644
index 0000000..b1fdbdf
--- /dev/null
+++ b/src/java/org/apache/pluto/PortletWindow.java
@@ -0,0 +1,40 @@
+/*

+ * Copyright 2004 The Apache Software Foundation.

+ *

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ *

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+

+package org.apache.pluto;

+

+import javax.portlet.PortletMode;

+import javax.portlet.WindowState;

+

+import org.apache.pluto.om.ObjectID;

+

+/**

+ * @author <a href="ddewolf@apache.org">David H. DeWolf</a>

+ * @version 1.0

+ * @since Sep 22, 2004

+ */

+public interface PortletWindow {

+

+    ObjectID getId();

+

+    String getContextPath();

+

+    String getPortletName();

+

+    WindowState getWindowState();

+

+    PortletMode getPortletMode();

+}

diff --git a/src/java/org/apache/pluto/core/InternalActionResponse.java b/src/java/org/apache/pluto/core/InternalActionResponse.java
new file mode 100644
index 0000000..f98f007
--- /dev/null
+++ b/src/java/org/apache/pluto/core/InternalActionResponse.java
@@ -0,0 +1,37 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.core;

+

+import java.util.Map;

+

+import javax.portlet.PortletMode;

+import javax.portlet.WindowState;

+

+public interface InternalActionResponse extends InternalPortletResponse {

+    public Map getRenderParameters();

+

+    public PortletMode getChangedPortletMode();

+

+    public WindowState getChangedWindowState();

+

+    public String getRedirectLocation();

+}

+

+

diff --git a/src/java/org/apache/pluto/core/InternalPortletConfig.java b/src/java/org/apache/pluto/core/InternalPortletConfig.java
new file mode 100644
index 0000000..c2173de
--- /dev/null
+++ b/src/java/org/apache/pluto/core/InternalPortletConfig.java
@@ -0,0 +1,34 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.core;

+

+import javax.portlet.PortletConfig;

+import javax.servlet.ServletConfig;

+

+import org.apache.pluto.binding.PortletDD;

+

+public interface InternalPortletConfig extends PortletConfig {

+

+    public ServletConfig getServletConfig();

+

+    public PortletDD getPortletDefinition();

+}

+

+

diff --git a/src/java/org/apache/pluto/core/InternalPortletContext.java b/src/java/org/apache/pluto/core/InternalPortletContext.java
new file mode 100644
index 0000000..4e259f7
--- /dev/null
+++ b/src/java/org/apache/pluto/core/InternalPortletContext.java
@@ -0,0 +1,34 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.core;

+

+import javax.portlet.PortletContext;

+import javax.servlet.ServletContext;

+

+import org.apache.pluto.binding.PortletAppDD;

+

+public interface InternalPortletContext extends PortletContext {

+

+    public ServletContext getServletContext();

+

+    public PortletAppDD getPortletApplicationDefinition();

+}

+

+

diff --git a/src/java/org/apache/pluto/core/InternalPortletRequest.java b/src/java/org/apache/pluto/core/InternalPortletRequest.java
new file mode 100644
index 0000000..d8bbaa1
--- /dev/null
+++ b/src/java/org/apache/pluto/core/InternalPortletRequest.java
@@ -0,0 +1,36 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.core;

+

+import javax.portlet.PortletRequest;

+

+public interface InternalPortletRequest extends PortletRequest {

+

+    public void lateInit(

+        javax.servlet.http.HttpServletRequest webModuleServletRequest);

+

+    public InternalPortletWindow getInternalPortletWindow();

+

+    public void setIncluded(boolean included);

+

+    public boolean isIncluded();

+}

+

+

diff --git a/src/java/org/apache/pluto/core/InternalPortletResponse.java b/src/java/org/apache/pluto/core/InternalPortletResponse.java
new file mode 100644
index 0000000..f92a282
--- /dev/null
+++ b/src/java/org/apache/pluto/core/InternalPortletResponse.java
@@ -0,0 +1,34 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.core;

+

+

+public interface InternalPortletResponse {

+

+    public void lateInit(

+        javax.servlet.http.HttpServletRequest webModuleServletRequest,

+        javax.servlet.http.HttpServletResponse webModuleServletResponse);

+

+    public InternalPortletWindow getInternalPortletWindow();

+

+    public void setIncluded(boolean included);

+

+    public boolean isIncluded();

+}

diff --git a/src/java/org/apache/pluto/core/InternalPortletWindow.java b/src/java/org/apache/pluto/core/InternalPortletWindow.java
new file mode 100644
index 0000000..62988f8
--- /dev/null
+++ b/src/java/org/apache/pluto/core/InternalPortletWindow.java
@@ -0,0 +1,102 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.core;

+

+import javax.portlet.PortletMode;

+import javax.portlet.WindowState;

+import javax.servlet.ServletContext;

+

+import org.apache.pluto.PortletWindow;

+import org.apache.pluto.om.ObjectID;

+

+

+/**

+ * <P> The <CODE>InternalPortletWindow</CODE> interface represents a single

+ * window of a portlet instance as it can be shown only once on a single page.

+ * There is a one-to-one relation between portlet windows and portlet entities.

+ * Adding the same portlet e.g. twice on a page results in two different

+ * windows. </P> <P> This interface defines the model as known from the MVC

+ * pattern. Its purpose is to provide read access to the data stored in the

+ * model. </P>

+ */

+public class InternalPortletWindow implements PortletWindow {

+

+    private PortletWindow window;

+    private ServletContext context;

+

+    private ObjectID id;

+    private PortletEntity entity;

+

+    /**

+     * @param ctx    the ServletContext from which this window is being

+     *               invoked.

+     * @param window the underlying window instance.

+     */

+    public InternalPortletWindow(ServletContext ctx, PortletWindow window) {

+        this.context = ctx.getContext(window.getContextPath());

+        this.window = window;

+    }

+

+    public String getContextPath() {

+        return window.getContextPath();

+    }

+

+    public String getPortletName() {

+        return window.getPortletName();

+    }

+

+    public WindowState getWindowState() {

+        return window.getWindowState();

+    }

+

+    public PortletMode getPortletMode() {

+        return window.getPortletMode();

+    }

+

+

+    /**

+     * Returns the identifier of this portlet instance window as object id. The

+     * return value cannot be NULL.

+     * @return the object identifier

+     */

+    public ObjectID getId() {

+        return window.getId();

+    }

+

+    /**

+     * The Context from which this window can be serviced.

+     * @return

+     */

+    public ServletContext getServletContext() {

+        return context;

+    }

+

+    /**

+     * Returns the portlet entity. The return value cannot be NULL.

+     * @return the portlet entity

+     */

+    public PortletEntity getPortletEntity() {

+        if (entity == null) {

+            entity = new PortletEntity(context, this);

+        }

+        return entity;

+    }

+

+}

diff --git a/src/java/org/apache/pluto/core/PortletContainerImpl.java b/src/java/org/apache/pluto/core/PortletContainerImpl.java
new file mode 100644
index 0000000..debf419
--- /dev/null
+++ b/src/java/org/apache/pluto/core/PortletContainerImpl.java
@@ -0,0 +1,263 @@
+/*

+ * Copyright 2004 The Apache Software Foundation.

+ *

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ *

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.apache.pluto.core;

+

+import java.io.IOException;

+import java.util.Map;

+

+import javax.portlet.PortletException;

+import javax.servlet.ServletContext;

+import javax.servlet.http.HttpServletRequest;

+import javax.servlet.http.HttpServletResponse;

+

+import org.apache.commons.logging.Log;

+import org.apache.commons.logging.LogFactory;

+import org.apache.pluto.PortletContainer;

+import org.apache.pluto.PortletContainerException;

+import org.apache.pluto.PortletWindow;

+import org.apache.pluto.core.impl.ActionRequestImpl;

+import org.apache.pluto.core.impl.ActionResponseImpl;

+import org.apache.pluto.core.impl.RenderRequestImpl;

+import org.apache.pluto.core.impl.RenderResponseImpl;

+import org.apache.pluto.services.PortletContainerServices;

+import org.apache.pluto.services.PortletURLProvider;

+

+/**

+ * Container implementation.

+ * @author <a href="ddewolf@apache.org">David H. DeWolf</a>

+ * @version 1.0

+ * @since Sep 18, 2004

+ */

+public class PortletContainerImpl implements PortletContainer {

+

+    private static final Log LOG =

+        LogFactory.getLog(PortletContainerImpl.class);

+

+

+    private String name;

+    private PortletContainerServices containerServices;

+    private ServletContext context;

+

+

+    private boolean initialized;

+

+    public PortletContainerImpl(String name,

+                                PortletContainerServices services) {

+        this.name = name;

+        this.containerServices = services;

+    }

+

+    /**

+     * Initialize the container for use within the given configuration scope.

+     * @param context

+     */

+    public void init(ServletContext context) {

+        this.context = context;

+        initialized = true;

+        if (LOG.isInfoEnabled()) {

+            LOG.debug("Portlet Container [" + name +

+                      "] successfully initialized.");

+        }

+    }

+

+    /**

+     * Determine whether this container has been initialized or not.

+     * @return

+     */

+    public boolean isInitialized() {

+        return initialized;

+    }

+

+    /**

+     * Destroy this container.

+     */

+    public void destroy() {

+        this.context = null;

+        initialized = false;

+    }

+

+

+    /**

+     * Render the portlet associated with the specified window.

+     * @param pWindow

+     * @param request

+     * @param response

+     * @throws PortletException

+     * @throws IOException

+     * @throws PortletContainerException

+     */

+    public void doRender(PortletWindow pWindow,

+                         HttpServletRequest request,

+                         HttpServletResponse response)

+        throws PortletException, IOException, PortletContainerException {

+

+        InternalPortletWindow window = new InternalPortletWindow(context,

+                                                                 pWindow);

+

+

+        if (LOG.isDebugEnabled()) {

+            LOG.debug("Portlet Container [" + name +

+                      "]: Render request recieved.");

+        }

+

+        RenderRequestImpl req =

+            new RenderRequestImpl(this, window, request);

+

+        RenderResponseImpl res =

+            new RenderResponseImpl(this, window, request, response);

+

+        PortletInvoker invoker = new PortletInvoker(window);

+

+        if (LOG.isDebugEnabled()) {

+            LOG.debug("Portlet Container [" + name + "]: Invoker Created.");

+        }

+

+        invoker.render(req, res);

+

+        if (LOG.isDebugEnabled()) {

+            LOG.debug("Portlet Container [" + name + "]: Portlet rendered.");

+        }

+    }

+

+    /**

+     * Process the action for the portlet associated with the given action.

+     * @param pWindow

+     * @param request

+     * @param response

+     * @throws PortletException

+     * @throws IOException

+     * @throws PortletContainerException

+     */

+    public void doAction(PortletWindow pWindow,

+                         HttpServletRequest request,

+                         HttpServletResponse response)

+        throws PortletException, IOException, PortletContainerException {

+

+        InternalPortletWindow window =

+            new InternalPortletWindow(context, pWindow);

+

+        if (LOG.isDebugEnabled()) {

+            LOG.debug("Portlet Container [" + name + "] Action request recieved");

+        }

+

+        ActionRequestImpl req =

+            new ActionRequestImpl(this, window, request);

+

+        ActionResponseImpl res =

+            new ActionResponseImpl(this, window, request, response);

+

+        PortletInvoker invoker = new PortletInvoker(window);

+

+        if (LOG.isDebugEnabled()) {

+            LOG.debug("Portlet Container [" + name + "]: Invoker Created.");

+        }

+        invoker.action(req, res);

+

+        if (LOG.isDebugEnabled()) {

+            LOG.debug(

+                "Portlet Container [" + name + "]: Portlet Action performed.");

+        }

+

+        String location = res.getRedirectLocation();

+

+        if (location == null) {

+            if (LOG.isDebugEnabled()) {

+                LOG.debug(

+                    "Portlet Container [" + name +

+                    "]:  No redirect location specified.");

+            }

+

+            PortletURLProvider redirectURL =

+                containerServices.getDynamicInformationProvider(request)

+                .getPortletURLProvider(window);

+

+            if (res.getChangedPortletMode() != null) {

+                redirectURL.setPortletMode(res.getChangedPortletMode());

+            }

+

+            if (res.getChangedWindowState() != null) {

+                redirectURL.setWindowState(res.getChangedWindowState());

+            }

+

+            Map renderParameters = res.getRenderParameters();

+            redirectURL.clearParameters();

+            redirectURL.setParameters(renderParameters);

+            redirectURL.setAction(false);

+

+            if (req.isSecure()) {

+                redirectURL.setSecure();

+            }

+            location = res.encodeRedirectURL(redirectURL.toString());

+        }

+

+        // Here we intentionally use the original response

+        // instead of the wrapped internal response.

+        response.sendRedirect(location);

+        if (LOG.isDebugEnabled()) {

+            LOG.debug("Portlet Container [" + name + "]: Redirect sent.");

+        }

+

+    }

+

+    /**

+     * Load the portlet associated with the specified window.

+     * @param pWindow

+     * @param request

+     * @param response

+     * @throws PortletException

+     * @throws PortletContainerException

+     */

+    public void doLoad(PortletWindow pWindow,

+                       HttpServletRequest request,

+                       HttpServletResponse response)

+        throws PortletException, PortletContainerException {

+

+        InternalPortletWindow window = new InternalPortletWindow(context,

+                                                                 pWindow);

+

+        if (LOG.isDebugEnabled()) {

+            LOG.debug("Portlet Container [" + name + "]: Load request recieved.");

+        }

+

+        RenderRequestImpl req =

+            new RenderRequestImpl(this, window, request);

+

+        RenderResponseImpl res =

+            new RenderResponseImpl(this, window, request, response);

+

+        PortletInvoker invoker = new PortletInvoker(window);

+

+        if (LOG.isDebugEnabled()) {

+            LOG.debug("Portlet Container [" + name + "]: Invoker Created.");

+        }

+

+        invoker.load(req, res);

+

+        if (LOG.isDebugEnabled()) {

+            LOG.debug("Portlet Container [" + name + "]: Portlet loaded.");

+        }

+

+    }

+

+    public String getName() {

+        return name;

+    }

+

+    public PortletContainerServices getContainerServices() {

+        return containerServices;

+    }

+}

+

diff --git a/src/java/org/apache/pluto/core/PortletContextManager.java b/src/java/org/apache/pluto/core/PortletContextManager.java
new file mode 100644
index 0000000..576601d
--- /dev/null
+++ b/src/java/org/apache/pluto/core/PortletContextManager.java
@@ -0,0 +1,86 @@
+/*

+ * Copyright 2004 The Apache Software Foundation.

+ *

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ *

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.apache.pluto.core;

+

+import java.io.IOException;

+import java.io.InputStream;

+import java.util.Map;

+

+import javax.portlet.PortletContext;

+import javax.servlet.ServletContext;

+

+import org.apache.pluto.PortletContainerException;

+import org.apache.pluto.binding.PortletAppDD;

+import org.apache.pluto.binding.XMLBindingFactory;

+import org.apache.pluto.core.impl.PortletContextImpl;

+

+/**

+ * @author <a href="ddewolf@apache.org">David H. DeWolf</a>

+ * @version 1.0

+ * @since Sep 20, 2004

+ */

+public class PortletContextManager {

+

+    private static final String PORTLET_XML = "/WEB-INF/portlet.xml";

+

+    private static PortletContextManager manager;

+

+    public static PortletContextManager getManager() {

+        if (manager == null) {

+            manager = new PortletContextManager();

+        }

+        return manager;

+    }

+

+    private Map contexts;

+

+    private PortletContextManager() {

+        contexts = new java.util.HashMap();

+    }

+

+    /**

+     * Retrieve the PortletContext associated with the given ServletContext.  If

+     * one does not exist, it is created.

+     * @param context

+     * @return

+     * @throws PortletContainerException

+     */

+    public InternalPortletContext getContext(ServletContext context)

+        throws PortletContainerException {

+        if (!contexts.containsKey(context)) {

+            PortletAppDD def = createDefinition(context);

+            PortletContext pc = new PortletContextImpl(context, def);

+            contexts.put(context, pc);

+        }

+        return (InternalPortletContext) contexts.get(context);

+    }

+

+    private PortletAppDD createDefinition(ServletContext ctx)

+        throws PortletContainerException {

+        PortletAppDD app = null;

+        try {

+            InputStream in = ctx.getResourceAsStream(PORTLET_XML);

+            app = XMLBindingFactory.createXMLBinding().getPortletAppDD(in);

+        } catch (IOException io) {

+            throw new PortletContainerException(

+                "Unable to open portlet.xml file. " + io.getMessage(), io);

+        }

+        return app;

+    }

+

+

+}

+

diff --git a/src/java/org/apache/pluto/core/PortletEntity.java b/src/java/org/apache/pluto/core/PortletEntity.java
new file mode 100644
index 0000000..c78e4f4
--- /dev/null
+++ b/src/java/org/apache/pluto/core/PortletEntity.java
@@ -0,0 +1,94 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.core;

+

+import java.io.IOException;

+import java.io.InputStream;

+

+import javax.servlet.ServletContext;

+

+import org.apache.pluto.PortletWindow;

+import org.apache.pluto.binding.PortletAppDD;

+import org.apache.pluto.binding.PortletDD;

+import org.apache.pluto.binding.ServletDD;

+import org.apache.pluto.binding.XMLBindingFactory;

+

+/**

+ * The PortletEntity encapsulates all data pertaining to a single portlet

+ * instance.  This instance may appear zero or more times per user. The

+ * PortletEntity consists of two primary peices of information, the Portlet

+ * Definition as defined by the {@link PortletDD} and the Wrapping Servlet

+ * information as defined by the{@link ServletDD}

+ */

+public class PortletEntity {

+    private static final String PREFIX = "/PlutoInvoker/";

+

+    private ServletContext ctx;

+    private PortletWindow window;

+

+    //  Looked up and Cached

+    private PortletDD dd;

+

+    PortletEntity(ServletContext ctx, PortletWindow window) {

+        this.ctx = ctx;

+        this.window = window;

+    }

+

+    /**

+     * Returns all preferences of this portlet The return value cannot be NULL.

+     * @return the preference set

+     */

+    public PortletPreference[] getDefaultPreferences() {

+        return null;

+    }

+

+    /**

+     * Returns the portlet description The return value cannot be NULL.

+     * @return the portlet description

+     */

+    public PortletDD getPortletDefinition() {

+        if (dd == null) {

+            load();

+        }

+        return dd;

+

+    }

+

+    private void load() {

+        ServletContext ctx = this.ctx.getContext(window.getContextPath());

+        InputStream in = ctx.getResourceAsStream(PortletAppDD.PORTLET_XML);

+        try {

+            PortletAppDD appDD = XMLBindingFactory.createXMLBinding().getPortletAppDD(in);

+            PortletDD[] dds = appDD.getPortlets();

+            for (int i = 0; i < dds.length && dd == null; i++) {

+                if (dds[i].getPortletName().equals(window.getPortletName())) {

+                    dd = dds[i];

+                }

+            }

+        } catch (IOException io) {

+            io.printStackTrace();

+        }

+    }

+

+    public String getControllerServletUri() {

+        return PREFIX + window.getPortletName();

+    }

+

+}

diff --git a/src/java/org/apache/pluto/core/PortletInvoker.java b/src/java/org/apache/pluto/core/PortletInvoker.java
new file mode 100644
index 0000000..08a26d8
--- /dev/null
+++ b/src/java/org/apache/pluto/core/PortletInvoker.java
@@ -0,0 +1,140 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.core;

+

+import java.io.IOException;

+

+import javax.portlet.PortletException;

+import javax.servlet.RequestDispatcher;

+import javax.servlet.ServletContext;

+

+import org.apache.commons.logging.Log;

+import org.apache.commons.logging.LogFactory;

+import org.apache.pluto.core.impl.ActionRequestImpl;

+import org.apache.pluto.core.impl.ActionResponseImpl;

+import org.apache.pluto.core.impl.PortletRequestImpl;

+import org.apache.pluto.core.impl.PortletResponseImpl;

+import org.apache.pluto.core.impl.RenderRequestImpl;

+import org.apache.pluto.core.impl.RenderResponseImpl;

+

+class PortletInvoker {

+    private static final Log LOG = LogFactory.getLog(PortletInvoker.class);

+

+    private InternalPortletWindow window;

+

+

+    /**

+     * Default Constructor.

+     * @param window

+     */

+    public PortletInvoker(InternalPortletWindow window) {

+        this.window = window;

+    }

+

+    public void action(ActionRequestImpl request, ActionResponseImpl response)

+        throws PortletException, IOException {

+        if (LOG.isDebugEnabled()) {

+            LOG.debug("Performing Action Invocation");

+        }

+        invoke(request, response, org.apache.pluto.Constants.METHOD_ACTION);

+    }

+

+    public void render(RenderRequestImpl request, RenderResponseImpl response)

+        throws PortletException, IOException {

+        if (LOG.isDebugEnabled()) {

+            LOG.debug("Performing Action Invocation");

+        }

+        invoke(request, response, org.apache.pluto.Constants.METHOD_RENDER);

+    }

+

+    public void load(PortletRequestImpl request, PortletResponseImpl response)

+        throws PortletException {

+        try {

+            invoke(request, response, org.apache.pluto.Constants.METHOD_NOOP);

+        } catch (IOException e) {

+            if (LOG.isErrorEnabled()) {

+                LOG.error(

+                    "PortletInvoker.load() - Error while dispatching portlet.",

+                    e);

+            }

+            throw new PortletException(e);

+        }

+    }

+

+    private void invoke(PortletRequestImpl request,

+                        PortletResponseImpl response,

+                        Integer methodID)

+        throws PortletException, IOException {

+

+

+        String uri = window.getPortletEntity().getControllerServletUri();

+        ServletContext servletContext = window.getServletContext();

+        RequestDispatcher dispatcher = servletContext.getRequestDispatcher(uri);

+

+        if (dispatcher != null) {

+            try {

+                request.setAttribute(org.apache.pluto.Constants.METHOD_ID,

+                                     methodID);

+                request.setAttribute(

+                    org.apache.pluto.Constants.PORTLET_REQUEST, request);

+                request.setAttribute(

+                    org.apache.pluto.Constants.PORTLET_RESPONSE, response);

+                dispatcher.include(request, response);

+            } catch (javax.servlet.UnavailableException e) {

+                LOG.error(

+                    "PortletInvoker.invoke() - Error while dispatching portlet.",

+                    e);

+                if (e.isPermanent()) {

+                    throw new javax.portlet.UnavailableException(

+                        e.getMessage());

+                } else {

+                    throw new javax.portlet.UnavailableException(

+                        e.getMessage(), e.getUnavailableSeconds());

+                }

+            } catch (javax.servlet.ServletException e) {

+                if (e.getRootCause() != null) {

+                    LOG.error(

+                        "PortletInvoker.render() - Error while dispatching portlet.",

+                        e.getRootCause());

+                    if (e.getRootCause() instanceof PortletException) {

+                        throw (PortletException) e.getRootCause();

+                    } else {

+                        throw new PortletException(e.getRootCause());

+                    }

+                } else {

+                    LOG.error(

+                        "PortletInvoker.invoke() - Error while dispatching portlet.",

+                        e);

+                    throw new PortletException(e);

+                }

+            } finally {

+                request.removeAttribute(org.apache.pluto.Constants.METHOD_ID);

+                request.removeAttribute(

+                    org.apache.pluto.Constants.PORTLET_REQUEST);

+                request.removeAttribute(

+                    org.apache.pluto.Constants.PORTLET_RESPONSE);

+            }

+        } else {

+            LOG.error(

+                "PortletInvoker.action() - Unable to find RequestDispatcher.");

+        }

+    }

+

+}

diff --git a/src/java/org/apache/pluto/core/PortletPreference.java b/src/java/org/apache/pluto/core/PortletPreference.java
new file mode 100644
index 0000000..9ae8c77
--- /dev/null
+++ b/src/java/org/apache/pluto/core/PortletPreference.java
@@ -0,0 +1,30 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ *

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ *

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.apache.pluto.core;

+

+/**

+ * @author <a href="ddewolf@apache.org">David H. DeWolf</a>

+ */

+public interface PortletPreference {

+

+    String getName();

+

+    String[] getValues();

+

+    void setValues(String[] values);

+

+    boolean isReadOnly();

+}

diff --git a/src/java/org/apache/pluto/core/PortletServlet.java b/src/java/org/apache/pluto/core/PortletServlet.java
new file mode 100644
index 0000000..fcd52fd
--- /dev/null
+++ b/src/java/org/apache/pluto/core/PortletServlet.java
@@ -0,0 +1,203 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.core;

+

+import java.io.IOException;

+

+import javax.portlet.Portlet;

+import javax.portlet.PortletException;

+import javax.servlet.ServletContext;

+import javax.servlet.ServletException;

+import javax.servlet.http.HttpServlet;

+import javax.servlet.http.HttpServletRequest;

+import javax.servlet.http.HttpServletResponse;

+

+import org.apache.pluto.PortletContainerException;

+import org.apache.pluto.binding.PortletAppDD;

+import org.apache.pluto.binding.PortletDD;

+import org.apache.pluto.core.impl.ActionRequestImpl;

+import org.apache.pluto.core.impl.ActionResponseImpl;

+import org.apache.pluto.core.impl.PortletConfigImpl;

+import org.apache.pluto.core.impl.RenderRequestImpl;

+import org.apache.pluto.core.impl.RenderResponseImpl;

+

+/**

+ * Portlet Invocation Servlet. This servlet recieves cross context requests from

+ * the the container and services the portlet request for the specified method.

+ * @author <a href="mailto:ddewolf@apache.org">David H. DeWolf</a>

+ * @version 1.1

+ * @since 09/22/2004

+ */

+public class PortletServlet extends HttpServlet {

+

+    private String portletName;

+

+    private Portlet portlet;

+    private InternalPortletContext portletContext;

+    private InternalPortletConfig portletConfig;

+

+    public String getServletInfo() {

+        return "Pluto PortletServlet [" + portletName + "]";

+    }

+

+    public void init() throws ServletException {

+

+        portletName = getInitParameter("portlet-name");

+

+        ServletContext context = getServletContext();

+

+        try {

+            portletContext =

+            PortletContextManager.getManager().getContext(context);

+        } catch (PortletContainerException pce) {

+            throw new ServletException(pce);

+        }

+

+        PortletAppDD appDD = portletContext.getPortletApplicationDefinition();

+        PortletDD[] dds = appDD.getPortlets();

+

+        PortletDD dd = null;

+        for (int i = 0; i < dds.length; i++) {

+            if (dds[i].getPortletName().equals(portletName)) {

+                dd = dds[i];

+                break;

+            }

+        }

+

+        if (dd == null) {

+            throw new ServletException(

+                "Unable to resolve portlet '" + portletName + "'");

+        }

+

+        portletConfig = new PortletConfigImpl(getServletConfig(),

+                                              portletContext, dd);

+

+        try {

+            ClassLoader loader = Thread.currentThread().getContextClassLoader();

+            Class pClass = loader.loadClass((dd.getPortletClass()));

+            portlet = (Portlet) pClass.newInstance();

+            portlet.init(portletConfig);

+        } catch (ClassNotFoundException cne) {

+            cne.printStackTrace();

+            throw new ServletException(cne);

+        } catch (IllegalAccessException e) {

+            e.printStackTrace();

+            throw new ServletException(e);

+        } catch (InstantiationException e) {

+            e.printStackTrace();

+            throw new ServletException(e);

+        } catch (PortletException pe) {

+            pe.printStackTrace();

+            throw new ServletException(pe);

+        }

+    }

+

+    protected void doGet(HttpServletRequest req,

+                         HttpServletResponse resp)

+        throws ServletException, IOException {

+        dispatch(req, resp);

+    }

+

+    protected void doPost(HttpServletRequest req,

+                          HttpServletResponse resp)

+        throws ServletException, IOException {

+        dispatch(req, resp);

+    }

+

+    protected void doPut(HttpServletRequest req,

+                         HttpServletResponse resp)

+        throws ServletException, IOException {

+        dispatch(req, resp);

+    }

+

+    public void destroy() {

+        if (portlet != null) {

+            portlet.destroy();

+        }

+        super.destroy();

+    }

+

+    private void dispatch(HttpServletRequest request,

+                          HttpServletResponse response)

+        throws ServletException, IOException {

+        try {

+            request.setAttribute(org.apache.pluto.Constants.PORTLET_CONFIG,

+                                 portletConfig);

+

+            Integer method_id =

+                (Integer) request.getAttribute(

+                    org.apache.pluto.Constants.METHOD_ID);

+

+            if (method_id == org.apache.pluto.Constants.METHOD_RENDER) {

+                RenderRequestImpl renderRequest = (RenderRequestImpl)

+                    request.getAttribute(

+                        org.apache.pluto.Constants.PORTLET_REQUEST);

+

+                RenderResponseImpl renderResponse = (RenderResponseImpl)

+                    request.getAttribute(

+                        org.apache.pluto.Constants.PORTLET_RESPONSE);

+

+                //renderRequest.lateInit(request);

+                //renderResponse.lateInit(request, response);

+

+                portlet.render(renderRequest, renderResponse);

+            } else if (method_id == org.apache.pluto.Constants.METHOD_ACTION) {

+                ActionRequestImpl actionRequest = (ActionRequestImpl)

+                    request.getAttribute(

+                        org.apache.pluto.Constants.PORTLET_REQUEST);

+

+                ActionResponseImpl actionResponse = (ActionResponseImpl)

+                    request.getAttribute(

+                        org.apache.pluto.Constants.PORTLET_RESPONSE);

+

+                //actionRequest.lateInit(request);

+                //actionResponse.lateInit(request, response);

+

+                portlet.processAction(actionRequest, actionResponse);

+            } else if (method_id == org.apache.pluto.Constants.METHOD_NOOP) {

+                //nothing to do

+            }

+

+        } catch (javax.portlet.UnavailableException e) {

+            e.printStackTrace();

+            /*

+            if (e.isPermanent()) {

+                throw new UnavailableException(e.getMessage());

+            } else {

+                throw new UnavailableException(e.getMessage(), e.getUnavailableSeconds());

+            }*/

+

+            // destroy isn't called by Tomcat, so we have to fix it

+            try {

+                portlet.destroy();

+            } catch (Throwable t) {

+                // don't care for Exception

+            }

+

+            // handle everything as permanently for now

+            throw new javax.servlet.UnavailableException(e.getMessage());

+        } catch (PortletException e) {

+            e.printStackTrace();

+            throw new ServletException(e);

+        } finally {

+            request.removeAttribute(org.apache.pluto.Constants.PORTLET_CONFIG);

+        }

+    }

+}

diff --git a/src/java/org/apache/pluto/core/impl/ActionRequestImpl.java b/src/java/org/apache/pluto/core/impl/ActionRequestImpl.java
new file mode 100644
index 0000000..a4d4b57
--- /dev/null
+++ b/src/java/org/apache/pluto/core/impl/ActionRequestImpl.java
@@ -0,0 +1,79 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.core.impl;

+

+import java.io.InputStream;

+

+import javax.portlet.ActionRequest;

+import javax.portlet.PortletPreferences;

+import javax.servlet.http.HttpServletRequest;

+

+import org.apache.pluto.Constants;

+import org.apache.pluto.PortletContainer;

+import org.apache.pluto.core.InternalPortletWindow;

+

+/**

+ * To change this generated comment edit the template variable "typecomment":

+ * Window>Preferences>Java>Templates. To enable and disable the creation of type

+ * comments go to Window>Preferences>Java>Code Generation.

+ */

+public class ActionRequestImpl

+    extends PortletRequestImpl implements ActionRequest {

+    /**

+     * Holds the portlet preferences

+     */

+    private PortletPreferences portletPreferences;

+

+    public ActionRequestImpl(PortletContainer container,

+                             InternalPortletWindow internalPortletWindow,

+                             HttpServletRequest servletRequest) {

+        super(container, internalPortletWindow, servletRequest);

+    }

+

+    // javax.portlet.ActionRequest implementation -------------------------------------------------

+    /* (non-Javadoc)

+     * @see org.apache.pluto.core.InternalActionResponse#getPortletInputStream()

+     */

+    public InputStream getPortletInputStream() throws java.io.IOException {

+        javax.servlet.http.HttpServletRequest servletRequest = (javax.servlet.http.HttpServletRequest) super.getRequest();

+

+        if (servletRequest.getMethod().equals("POST")) {

+            String contentType = servletRequest.getContentType();

+            if (contentType == null ||

+                contentType.equals("application/x-www-form-urlencoded")) {

+                throw new java.lang.IllegalStateException(

+                    "User request HTTP POST data is of type application/x-www-form-urlencoded. This data has been already processed by the portal/portlet-container and is available as request parameters.");

+            }

+        }

+        return servletRequest.getInputStream();

+    }

+

+    // --------------------------------------------------------------------------------------------

+    // PortletRequestImpl implementation ----------------------------------------------------------

+    public PortletPreferences getPreferences() {

+        if (this.portletPreferences == null) {

+            portletPreferences = new PortletPreferencesImpl(getContainer(),

+                                                            getWindow(), this,

+                                                            Constants.METHOD_ACTION);

+        }

+        return this.portletPreferences;

+    }

+    // --------------------------------------------------------------------------------------------

+}

diff --git a/src/java/org/apache/pluto/core/impl/ActionResponseImpl.java b/src/java/org/apache/pluto/core/impl/ActionResponseImpl.java
new file mode 100644
index 0000000..108f823
--- /dev/null
+++ b/src/java/org/apache/pluto/core/impl/ActionResponseImpl.java
@@ -0,0 +1,262 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.core.impl;

+

+import java.util.Enumeration;

+import java.util.HashMap;

+import java.util.Iterator;

+import java.util.Map;

+

+import javax.portlet.ActionResponse;

+import javax.portlet.PortalContext;

+import javax.portlet.PortletMode;

+import javax.portlet.PortletModeException;

+import javax.portlet.WindowState;

+import javax.portlet.WindowStateException;

+

+import org.apache.pluto.PortletContainer;

+import org.apache.pluto.binding.PortletDD;

+import org.apache.pluto.binding.SupportedMimeTypeDD;

+import org.apache.pluto.core.InternalActionResponse;

+import org.apache.pluto.core.InternalPortletWindow;

+import org.apache.pluto.services.DynamicInformationProvider;

+import org.apache.pluto.services.ResourceURLProvider;

+import org.apache.pluto.util.StringUtils;

+

+public class ActionResponseImpl extends PortletResponseImpl

+    implements ActionResponse, InternalActionResponse {

+

+    /**

+     * Is it still allowed to invoke the method sendRedirect() ?

+     */

+    boolean redirectAllowed = true;

+

+    private boolean redirected;

+    private String redirectLocation;

+

+    private Map renderParameters = new HashMap();

+    private WindowState windowState = null;

+    private PortletMode portletMode = null;

+

+    private DynamicInformationProvider provider;

+    private PortalContext context;

+

+

+    public ActionResponseImpl(PortletContainer container,

+                              InternalPortletWindow internalPortletWindow,

+                              javax.servlet.http.HttpServletRequest servletRequest,

+                              javax.servlet.http.HttpServletResponse servletResponse) {

+        super(container, internalPortletWindow, servletRequest,

+              servletResponse);

+        context = container.getContainerServices().getPortalContext();

+        provider =

+        container.getContainerServices().getDynamicInformationProvider(

+            servletRequest);

+    }

+

+    // javax.portlet.ActionResponse ---------------------------------------------------------------

+    public void setWindowState(WindowState windowState)

+        throws WindowStateException {

+        if (redirected) {

+            throw new IllegalStateException(

+                "it is not allowed to invoke setWindowState after sendRedirect has been called");

+        }

+

+        if (isWindowStateAllowed(windowState)) {

+            this.windowState = windowState;

+        } else {

+            throw new WindowStateException("Can't set this WindowState",

+                                           windowState);

+        }

+        redirectAllowed = false;

+    }

+

+    public void setPortletMode(PortletMode portletMode)

+        throws PortletModeException {

+        if (redirected) {

+            throw new IllegalStateException(

+                "it is not allowed to invoke setPortletMode after sendRedirect has been called");

+        }

+

+        // check if portal supports portlet mode

+        boolean supported = isPortletModeAllowed(portletMode);

+

+

+        // if porlet mode is allowed

+        if (supported) {

+            this.portletMode = portletMode;

+        } else {

+            throw new PortletModeException("Can't set this PortletMode",

+                                           portletMode);

+        }

+

+        redirectAllowed = false;

+

+    }

+

+    public void sendRedirect(String location) throws java.io.IOException {

+        if (redirectAllowed) {

+            if (location != null) {

+                javax.servlet.http.HttpServletResponse redirectResponse = _getHttpServletResponse();

+                while (redirectResponse instanceof javax.servlet.http.HttpServletResponseWrapper) {

+                    redirectResponse =

+                    (javax.servlet.http.HttpServletResponse)

+                        ((javax.servlet.http.HttpServletResponseWrapper) redirectResponse).getResponse();

+                }

+                ResourceURLProvider provider = this.provider.getResourceURLProvider(

+                    getInternalPortletWindow());

+                if (location.indexOf("://") != -1) {

+                    provider.setAbsoluteURL(location);

+                } else {

+                    provider.setFullPath(location);

+                }

+                location =

+                redirectResponse.encodeRedirectURL(provider.toString());

+                //redirectResponse.sendRedirect(location);

+                redirectLocation = location;

+                redirected = true;

+            }

+        } else {

+            throw new java.lang.IllegalStateException(

+                "Can't invoke sendRedirect() after certain methods have been called");

+        }

+

+    }

+

+    public void setRenderParameters(Map parameters) {

+        if (redirected) {

+            throw new IllegalStateException(

+                "Can't invoke setRenderParameters() after sendRedirect() has been called");

+        }

+        if (parameters == null) {

+            throw new IllegalArgumentException(

+                "Render parameters must not be null.");

+        }

+        for (Iterator iter = parameters.entrySet().iterator(); iter.hasNext();) {

+            Map.Entry entry = (Map.Entry) iter.next();

+            if (!(entry.getKey() instanceof String)) {

+                throw new IllegalArgumentException(

+                    "Key must not be null and of type java.lang.String.");

+            }

+            if (!(entry.getValue() instanceof String[])) {

+                throw new IllegalArgumentException(

+                    "Value must not be null and of type java.lang.String[].");

+            }

+        }

+

+        renderParameters = StringUtils.copyParameters(parameters);

+

+        redirectAllowed = false;

+    }

+

+    public void setRenderParameter(String key, String value) {

+        if (redirected) {

+            throw new IllegalStateException(

+                "Can't invoke setRenderParameter() after sendRedirect() has been called");

+        }

+

+        if ((key == null) || (value == null)) {

+            throw new IllegalArgumentException(

+                "Render parameter key or value must not be null.");

+        }

+

+        renderParameters.put(key, new String[]{value});

+

+        redirectAllowed = false;

+    }

+

+    public void setRenderParameter(String key, String[] values) {

+        if (redirected) {

+            throw new IllegalStateException(

+                "Can't invoke setRenderParameter() after sendRedirect() has been called");

+        }

+

+        if (key == null || values == null || values.length == 0) {

+            throw new IllegalArgumentException(

+                "Render parameter key or value must not be null or values be an empty array.");

+        }

+

+        renderParameters.put(key, StringUtils.copy(values));

+

+        redirectAllowed = false;

+    }

+    // --------------------------------------------------------------------------------------------

+    

+    // org.apache.pluto.core.InternalActionResponse implementation --------------------------------

+    public Map getRenderParameters() {

+        return renderParameters;

+    }

+

+    public PortletMode getChangedPortletMode() {

+        return this.portletMode;

+    }

+

+    public WindowState getChangedWindowState() {

+        return this.windowState;

+    }

+

+    public String getRedirectLocation() {

+        return redirectLocation;

+    }

+

+    private boolean isPortletModeAllowed(PortletMode mode) {

+        return isPortletModeAllowedByPortlet(mode)

+               && isPortletModeAllowedByPortal(mode);

+    }

+

+    private boolean isPortletModeAllowedByPortlet(PortletMode mode) {

+        PortletDD dd = internalPortletWindow.getPortletEntity()

+            .getPortletDefinition();

+

+        SupportedMimeTypeDD[] mimes = dd.getSupportedMimeTypes();

+        for (int i = 0; i < mimes.length; i++) {

+            String[] modes = mimes[i].getPortletModes();

+            for (int j = 0; j < modes.length; j++) {

+                if (modes[j].equals(mode.toString())) {

+                    return true;

+                }

+            }

+        }

+        return false;

+    }

+

+    private boolean isPortletModeAllowedByPortal(PortletMode mode) {

+        Enumeration supportedModes = context.getSupportedPortletModes();

+        while (supportedModes.hasMoreElements()) {

+            if (supportedModes.nextElement().toString().equals(

+                (mode.toString()))) {

+                return true;

+            }

+        }

+        return false;

+    }

+

+    private boolean isWindowStateAllowed(WindowState state) {

+        Enumeration supportedStates = context.getSupportedWindowStates();

+        while (supportedStates.hasMoreElements()) {

+            if (supportedStates.nextElement().toString().equals(

+                (state.toString()))) {

+                return true;

+            }

+        }

+        return false;

+    }

+

+}

diff --git a/src/java/org/apache/pluto/core/impl/Environment.java b/src/java/org/apache/pluto/core/impl/Environment.java
new file mode 100644
index 0000000..bb3384a
--- /dev/null
+++ b/src/java/org/apache/pluto/core/impl/Environment.java
@@ -0,0 +1,81 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ *

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ *

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.apache.pluto.core.impl;

+

+import java.util.ResourceBundle;

+

+/**

+ * Utility class used to retrieve environment information from the

+ * <code>environment.properties</code> file packaged with pluto.

+ * @author <a href="ddewolf@apache.org">David H. DeWolf</a>

+ */

+final class Environment {

+

+    /**

+     * Properties Resource Bundle containing pluto environment information.

+     */

+    public static final ResourceBundle PROPS;

+

+    static {

+        PROPS = ResourceBundle.getBundle("org.apache.pluto.environment");

+    }

+

+

+    public static final String getPortletContainerName() {

+        return PROPS.getString("pluto.container.name");

+    }

+

+    public static final String getPortletContainerMajorVersion() {

+        return PROPS.getString("pluto.container.version.major");

+    }

+

+    public static final String getPortletContainerMinorVersion() {

+        return PROPS.getString("pluto.container.version.minor");

+    }

+

+    /**

+     * Retrieve the major version number of the specification which this version

+     * of pluto supports.

+     * @return

+     */

+    public static final int getMajorSpecificationVersion() {

+        return Integer.parseInt(PROPS.getString("javax.portlet.version.major"));

+    }

+

+    /**

+     * Retrieve the minor version number of the specification which this version

+     * of pluto supports.

+     * @return

+     */

+    public static final int getMinorSpecificationVersion() {

+        return Integer.parseInt(PROPS.getString("javax.portlet.version.minor"));

+    }

+

+    /**

+     * Retrieve the formatted server info String required to be returned by the

+     * PortletContext.

+     * @return

+     */

+    public static final String getServerInfo() {

+        StringBuffer sb = new StringBuffer(getPortletContainerName())

+            .append("/")

+            .append(getPortletContainerMajorVersion())

+            .append(".")

+            .append(getPortletContainerMinorVersion());

+        return sb.toString();

+    }

+

+}

diff --git a/src/java/org/apache/pluto/core/impl/InternalImplConverter.java b/src/java/org/apache/pluto/core/impl/InternalImplConverter.java
new file mode 100644
index 0000000..435a38c
--- /dev/null
+++ b/src/java/org/apache/pluto/core/impl/InternalImplConverter.java
@@ -0,0 +1,72 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.core.impl;

+

+import javax.portlet.PortletRequest;

+import javax.portlet.PortletResponse;

+

+import org.apache.pluto.core.InternalPortletRequest;

+import org.apache.pluto.core.InternalPortletResponse;

+import org.apache.pluto.portlet.PortletRequestWrapper;

+import org.apache.pluto.portlet.PortletResponseWrapper;

+

+class InternalImplConverter {

+

+

+    /**

+     * The scary part about this is that there is not yet a

+     * PortletRequestWrapper defined by the spec.  Because of this, there's a

+     * chance someone might implement their own wrapper and we won't be able to

+     * get the real internal one!

+     * @param request

+     * @return

+     */

+    public static InternalPortletRequest getInternalRequest(

+        PortletRequest request) {

+        while (!(request instanceof InternalPortletRequest)) {

+            request = ((PortletRequestWrapper) request).getPortletRequest();

+            if (request == null) {

+                throw new IllegalStateException(

+                    "The internal portlet request cannot be found.");

+            }

+        }

+        return (InternalPortletRequest) request;

+    }

+

+    /**

+     * The scary part about this is that there is not yet a

+     * PortletRequestWrapper defined by the spec.  Because of this, there's a

+     * chance someone might implement their own wrapper and we won't be able to

+     * get the real internal one!

+     * @param response

+     * @return

+     */

+    public static InternalPortletResponse getInternalResponse(

+        PortletResponse response) {

+        while (!(response instanceof InternalPortletResponse)) {

+            response = ((PortletResponseWrapper) response).getPortletResponse();

+            if (response == null) {

+                throw new IllegalStateException(

+                    "The internal portlet response cannot be found.");

+            }

+        }

+        return (InternalPortletResponse) response;

+    }

+}

diff --git a/src/java/org/apache/pluto/core/impl/PortletConfigImpl.java b/src/java/org/apache/pluto/core/impl/PortletConfigImpl.java
new file mode 100644
index 0000000..c48942f
--- /dev/null
+++ b/src/java/org/apache/pluto/core/impl/PortletConfigImpl.java
@@ -0,0 +1,107 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.core.impl;

+

+import java.util.Arrays;

+import java.util.Enumeration;

+import java.util.Iterator;

+import java.util.ResourceBundle;

+

+import javax.portlet.PortletConfig;

+import javax.portlet.PortletContext;

+import javax.servlet.ServletConfig;

+

+import org.apache.pluto.binding.InitParameterDD;

+import org.apache.pluto.binding.PortletDD;

+import org.apache.pluto.core.InternalPortletConfig;

+

+public class PortletConfigImpl implements PortletConfig, InternalPortletConfig {

+    private ServletConfig servletConfig;

+    private PortletContext portletContext;

+    private PortletDD portletDD;

+

+    private ResourceBundleFactory bundles;

+

+    public PortletConfigImpl(ServletConfig servletConfig,

+                             PortletContext portletContext,

+                             PortletDD portletDD) {

+        this.servletConfig = servletConfig;

+        this.portletContext = portletContext;

+        this.portletDD = portletDD;

+    }

+

+    public String getPortletName() {

+        return portletDD.getPortletName();

+    }

+

+    public PortletContext getPortletContext() {

+        return portletContext;

+    }

+

+    public ResourceBundle getResourceBundle(java.util.Locale locale) {

+        if (bundles == null) {

+            bundles = new ResourceBundleFactory(portletDD);

+        }

+        return bundles.getResourceBundle(locale);

+    }

+

+    public String getInitParameter(String name) {

+        if (name == null) {

+            throw new IllegalArgumentException("Parameter name == null");

+        }

+

+        InitParameterDD[] parameters = portletDD.getInitParameters();

+        for (int i = 0; i < parameters.length; i++) {

+            if (parameters[i].getParameterName().equals(name)) {

+                return parameters[i].getParameterValue();

+            }

+        }

+        return null;

+    }

+

+    public Enumeration getInitParameterNames() {

+        return new java.util.Enumeration() {

+            private Iterator iterator =

+                Arrays.asList(portletDD.getInitParameters()).iterator();

+

+            public boolean hasMoreElements() {

+                return iterator.hasNext();

+            }

+

+            public Object nextElement() {

+                if (iterator.hasNext()) {

+                    return ((org.apache.pluto.binding.InitParameterDD) iterator.next()).getParameterName();

+                } else {

+                    return null;

+                }

+            }

+        };

+    }

+

+

+    public javax.servlet.ServletConfig getServletConfig() {

+        return servletConfig;

+    }

+

+    public PortletDD getPortletDefinition() {

+        return portletDD;

+    }

+    // --------------------------------------------------------------------------------------------

+}

diff --git a/src/java/org/apache/pluto/core/impl/PortletContextImpl.java b/src/java/org/apache/pluto/core/impl/PortletContextImpl.java
new file mode 100644
index 0000000..b6d7319
--- /dev/null
+++ b/src/java/org/apache/pluto/core/impl/PortletContextImpl.java
@@ -0,0 +1,161 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.core.impl;

+

+import java.net.MalformedURLException;

+

+import javax.portlet.PortletContext;

+import javax.portlet.PortletRequestDispatcher;

+import javax.servlet.RequestDispatcher;

+import javax.servlet.ServletContext;

+

+import org.apache.pluto.binding.PortletAppDD;

+import org.apache.pluto.core.InternalPortletContext;

+

+public class PortletContextImpl

+    implements PortletContext, InternalPortletContext {

+

+    private PortletAppDD portletAppDD;

+    private ServletContext servletContext;

+

+    public PortletContextImpl(ServletContext servletContext,

+                              PortletAppDD portletAppDD) {

+        this.servletContext = servletContext;

+        this.portletAppDD = portletAppDD;

+    }

+

+    public String getServerInfo() {

+        return Environment.getServerInfo();

+    }

+

+    public PortletRequestDispatcher getRequestDispatcher(String path) {

+        try {

+            RequestDispatcher rd = servletContext.getRequestDispatcher(path);

+            return new PortletRequestDispatcherImpl(rd);

+        } catch (Exception e) {

+            // need to catch exception because of tomcat 4.x bug

+            // tomcat throws an exception instead of return null

+            // if the path was not found

+            return null;

+        }

+    }

+

+    public PortletRequestDispatcher getNamedDispatcher(String name) {

+        javax.servlet.RequestDispatcher rd = servletContext.getNamedDispatcher(

+            name);

+        return rd != null ? new PortletRequestDispatcherImpl(rd)

+               : null;

+    }

+

+    public java.io.InputStream getResourceAsStream(String path) {

+        return servletContext.getResourceAsStream(path);

+    }

+

+    public int getMajorVersion() {

+        return Environment.getMajorSpecificationVersion();

+    }

+

+    public int getMinorVersion() {

+        return Environment.getMinorSpecificationVersion();

+    }

+

+    public String getMimeType(String file) {

+        return servletContext.getMimeType(file);

+    }

+

+    public String getRealPath(String path) {

+        return servletContext.getRealPath(path);

+    }

+

+    public java.util.Set getResourcePaths(String path) {

+        return servletContext.getResourcePaths(path);

+    }

+

+    public java.net.URL getResource(String path)

+        throws java.net.MalformedURLException {

+        if (path == null || !path.startsWith("/")) {

+            throw new MalformedURLException("path must start with a '/'");

+        }

+        return servletContext.getResource(path);

+    }

+

+    public java.lang.Object getAttribute(java.lang.String name) {

+        if (name == null) {

+            throw new IllegalArgumentException("Attribute name == null");

+        }

+

+        return servletContext.getAttribute(name);

+    }

+

+    public java.util.Enumeration getAttributeNames() {

+        return servletContext.getAttributeNames();

+    }

+

+    public java.lang.String getInitParameter(java.lang.String name) {

+        if (name == null) {

+            throw new IllegalArgumentException("Parameter name == null");

+        }

+

+        return servletContext.getInitParameter(name);

+    }

+

+    public java.util.Enumeration getInitParameterNames() {

+        return servletContext.getInitParameterNames();

+    }

+

+    public void log(java.lang.String msg) {

+        servletContext.log(msg);

+    }

+

+    public void log(java.lang.String message, java.lang.Throwable throwable) {

+        servletContext.log(message, throwable);

+    }

+

+    public void removeAttribute(java.lang.String name) {

+        if (name == null) {

+            throw new IllegalArgumentException("Attribute name == null");

+        }

+

+        servletContext.removeAttribute(name);

+    }

+

+    public void setAttribute(java.lang.String name, java.lang.Object object) {

+        if (name == null) {

+            throw new IllegalArgumentException("Attribute name == null");

+        }

+

+        servletContext.setAttribute(name, object);

+    }

+

+    public String getPortletContextName() {

+        return servletContext.getServletContextName();

+    }

+    // --------------------------------------------------------------------------------------------

+

+    // org.apache.pluto.core.InternalPortletContext implementation --------------------------------

+    public javax.servlet.ServletContext getServletContext() {

+        return servletContext;

+    }

+

+    public PortletAppDD getPortletApplicationDefinition() {

+        return portletAppDD;

+    }

+}

+

diff --git a/src/java/org/apache/pluto/core/impl/PortletPreferenceImpl.java b/src/java/org/apache/pluto/core/impl/PortletPreferenceImpl.java
new file mode 100644
index 0000000..9d34afc
--- /dev/null
+++ b/src/java/org/apache/pluto/core/impl/PortletPreferenceImpl.java
@@ -0,0 +1,65 @@
+/*

+ * Copyright 2004 The Apache Software Foundation.

+ *

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ *

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.apache.pluto.core.impl;

+

+import org.apache.pluto.core.PortletPreference;

+

+/**

+ * <B>TODO</B>: Document

+ * @author <a href="ddewolf@apache.org">David H. DeWolf</a>

+ * @version 1.0

+ * @since Sep 20, 2004

+ */

+public class PortletPreferenceImpl implements PortletPreference {

+

+    private String name;

+    private String[] values;

+    private boolean readOnly;

+

+    public PortletPreferenceImpl() {

+

+    }

+

+    public PortletPreferenceImpl(String name, String[] values) {

+        this.name = name;

+        this.values = values;

+    }

+

+    public String getName() {

+        return name;

+    }

+

+    public void setName(String name) {

+        this.name = name;

+    }

+

+    public String[] getValues() {

+        return values;

+    }

+

+    public void setValues(String[] values) {

+        this.values = values;

+    }

+

+    public boolean isReadOnly() {

+        return readOnly;

+    }

+

+    public void setReadOnly(boolean readOnly) {

+        this.readOnly = readOnly;

+    }

+}

+

diff --git a/src/java/org/apache/pluto/core/impl/PortletPreferencesImpl.java b/src/java/org/apache/pluto/core/impl/PortletPreferencesImpl.java
new file mode 100644
index 0000000..39a28eb
--- /dev/null
+++ b/src/java/org/apache/pluto/core/impl/PortletPreferencesImpl.java
@@ -0,0 +1,228 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.core.impl;

+

+import java.util.Collections;

+import java.util.Enumeration;

+import java.util.Iterator;

+import java.util.Map;

+import java.util.Vector;

+

+import javax.portlet.PortletPreferences;

+import javax.portlet.PreferencesValidator;

+import javax.portlet.ReadOnlyException;

+import javax.portlet.ValidatorException;

+

+import org.apache.pluto.Constants;

+import org.apache.pluto.PortletContainer;

+import org.apache.pluto.core.InternalPortletRequest;

+import org.apache.pluto.core.InternalPortletWindow;

+import org.apache.pluto.core.PortletPreference;

+import org.apache.pluto.services.PortletPreferencesFactory;

+

+

+public class PortletPreferencesImpl implements PortletPreferences {

+

+    private PortletPreferencesFactory factory;

+

+    private InternalPortletWindow window;

+

+    private InternalPortletRequest request;

+

+    private Map preferences;

+

+

+    // current method used for managing these preferences

+    private Integer methodId = null;

+

+

+    public PortletPreferencesImpl(PortletContainer container,

+                                  InternalPortletWindow window,

+                                  InternalPortletRequest request,

+                                  Integer methodId) {

+        this.factory =

+        container.getContainerServices().getPortletPreferencesFactory();

+        this.window = window;

+        this.request = request;

+        this.methodId = methodId;

+

+        this.preferences = new java.util.HashMap();

+

+        PortletPreference[] prefs

+            = window.getPortletEntity().getDefaultPreferences();

+

+        for (int i = 0; i < prefs.length; i++) {

+            preferences.put(prefs[i].getName(), prefs);

+        }

+

+        PortletPreferencesFactory factory

+            = container.getContainerServices().getPortletPreferencesFactory();

+

+        prefs = factory.getStoredPreferences(window, request);

+

+        for (int i = 0; i < prefs.length; i++) {

+            preferences.put(prefs[i].getName(), prefs);

+        }

+

+    }

+

+    public boolean isReadOnly(String key) {

+        if (key == null) {

+            throw new IllegalArgumentException("key == null");

+        }

+

+        PortletPreference pref = (PortletPreference) preferences.get(key);

+        return pref == null ? true : pref.isReadOnly();

+    }

+

+    public String getValue(String key, String def) {

+        if (key == null) {

+            throw new IllegalArgumentException("key == null");

+        }

+

+        String[] value = null;

+

+        PortletPreference pref = (PortletPreference) preferences.get(key);

+        if (pref != null) {

+            value = pref.getValues();

+        } else {

+            value = new String[]{def};

+        }

+        return value.length > 0 ? value[0] : null;

+    }

+

+    public String[] getValues(String key, String[] def) {

+        if (key == null) {

+            throw new IllegalArgumentException("key == null");

+        }

+

+        String[] values = null;

+        PortletPreference pref = (PortletPreference) preferences.get(key);

+

+        if (pref != null) {

+            values = pref.getValues();

+        } else {

+            values = def;

+        }

+        return values;

+    }

+

+    public void setValue(String key, String value) throws ReadOnlyException {

+        if (key == null) {

+            throw new IllegalArgumentException("key == null");

+        }

+

+        PortletPreference pref = (PortletPreference) preferences.get(key);

+

+        if (pref != null && pref.isReadOnly()) {

+            throw new ReadOnlyException("Preference [" + key + "] is read only");

+        } else if (pref != null) {

+            pref.setValues(new String[]{value});

+        } else {

+            pref = new PortletPreferenceImpl(key, new String[]{value});

+            preferences.put(key, pref);

+        }

+    }

+

+    public void setValues(String key, String[] values)

+        throws ReadOnlyException {

+        if (key == null) {

+            throw new IllegalArgumentException("key == null");

+        }

+

+        PortletPreference pref = (PortletPreference) preferences.get(key);

+

+        if (pref != null && pref.isReadOnly()) {

+            throw new ReadOnlyException("Preference [" + key + "] is read only");

+        } else if (pref != null) {

+            pref.setValues(values);

+        } else {

+            pref = new PortletPreferenceImpl(key, values);

+            preferences.put(key, pref);

+        }

+    }

+

+    public Enumeration getNames() {

+        return new Vector(preferences.keySet()).elements();

+    }

+

+    public Map getMap() {

+        Map map = new java.util.HashMap();

+        Iterator it = preferences.keySet().iterator();

+        while (it.hasNext()) {

+            PortletPreference pref = (PortletPreference) it.next();

+            map.put(pref.getName(), pref.getValues());

+        }

+        return Collections.unmodifiableMap(map);

+    }

+

+    public void reset(String key) throws ReadOnlyException {

+        if (key == null) {

+            throw new IllegalArgumentException("key == null");

+        }

+

+        PortletPreference pref = (PortletPreference) preferences.get(key);

+        if (pref.isReadOnly()) {

+            throw new ReadOnlyException(

+                "preference attribute called " + key + " may not be modified");

+        }

+

+        PortletPreference preference = factory.getStoredPreference(window,

+                                                                   request,

+                                                                   key);

+        preferences.put(preference.getName(), preference);

+

+    }

+

+    public void store() throws java.io.IOException, ValidatorException {

+        // not allowed when not called in action

+        if (!Constants.METHOD_ID.equals(methodId)) {

+            throw new java.lang.IllegalStateException(

+                "store is only allowed inside a processAction call");

+        }

+

+        String validatorClass =

+            window.getPortletEntity().getPortletDefinition()

+            .getPreferenceValidator();

+

+        if (validatorClass != null) {

+            try {

+                PreferencesValidator validator = (PreferencesValidator)

+                    Class.forName(validatorClass).newInstance();

+                validator.validate(this);

+            } catch (InstantiationException e) {

+                throw new ValidatorException(e, null);

+            } catch (IllegalAccessException e) {

+                throw new ValidatorException(e, null);

+            } catch (ClassNotFoundException t) {

+                throw new ValidatorException(t, null);

+            }

+        }

+

+        PortletPreference[] pref =

+            (PortletPreference[]) preferences.values().toArray(

+                new PortletPreference[preferences.size()]);

+

+        factory.store(pref);

+    }

+    // --------------------------------------------------------------------------------------------

+

+

+}

diff --git a/src/java/org/apache/pluto/core/impl/PortletRequestDispatcherImpl.java b/src/java/org/apache/pluto/core/impl/PortletRequestDispatcherImpl.java
new file mode 100644
index 0000000..041d1d8
--- /dev/null
+++ b/src/java/org/apache/pluto/core/impl/PortletRequestDispatcherImpl.java
@@ -0,0 +1,82 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.core.impl;

+

+import javax.portlet.PortletException;

+import javax.portlet.PortletRequestDispatcher;

+import javax.portlet.RenderRequest;

+import javax.portlet.RenderResponse;

+import javax.servlet.RequestDispatcher;

+

+import org.apache.pluto.core.InternalPortletRequest;

+import org.apache.pluto.core.InternalPortletResponse;

+

+public class PortletRequestDispatcherImpl implements PortletRequestDispatcher {

+

+    private javax.servlet.RequestDispatcher requestDispatcher;

+

+    public PortletRequestDispatcherImpl(RequestDispatcher requestDispatcher) {

+        this.requestDispatcher = requestDispatcher;

+    }

+

+    public void include(RenderRequest request, RenderResponse response)

+        throws PortletException, java.io.IOException {

+

+        InternalPortletRequest internalRequest =

+            InternalImplConverter.getInternalRequest(request);

+

+        InternalPortletResponse internalResponse =

+            InternalImplConverter.getInternalResponse(response);

+

+        try {

+            internalRequest.setIncluded(true);

+            internalResponse.setIncluded(true);

+

+            this.requestDispatcher.include(

+                (javax.servlet.http.HttpServletRequest) request,

+                (javax.servlet.http.HttpServletResponse) response);

+        } catch (java.io.IOException e) {

+            throw e;

+        } catch (javax.servlet.ServletException e) {

+            if (e.getRootCause() != null) {

+                throw new PortletException(e.getRootCause());

+            } else {

+                throw new PortletException(e);

+            }

+        } finally {

+            internalRequest.setIncluded(false);

+            internalResponse.setIncluded(false);

+        }

+    }

+    // --------------------------------------------------------------------------------------------

+

+    // portlet-servlet implementation

+    /*

+        public void include(javax.servlet.ServletRequest request, javax.servlet.ServletResponse response)

+        throws javax.servlet.ServletException, java.io.IOException

+        {

+        }

+    

+        public void forward(javax.servlet.ServletRequest request, javax.servlet.ServletResponse response)

+        throws javax.servlet.ServletException, java.io.IOException

+        {

+        }

+    */

+}

diff --git a/src/java/org/apache/pluto/core/impl/PortletRequestImpl.java b/src/java/org/apache/pluto/core/impl/PortletRequestImpl.java
new file mode 100644
index 0000000..3e4c1eb
--- /dev/null
+++ b/src/java/org/apache/pluto/core/impl/PortletRequestImpl.java
@@ -0,0 +1,661 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.apache.pluto.core.impl;

+

+import java.io.BufferedReader;

+import java.util.Collections;

+import java.util.Enumeration;

+import java.util.HashSet;

+import java.util.Iterator;

+import java.util.Map;

+import java.util.Set;

+import java.util.Vector;

+

+import javax.portlet.PortalContext;

+import javax.portlet.PortletContext;

+import javax.portlet.PortletMode;

+import javax.portlet.PortletPreferences;

+import javax.portlet.PortletRequest;

+import javax.portlet.PortletSession;

+import javax.portlet.WindowState;

+import javax.servlet.http.HttpServletRequestWrapper;

+

+import org.apache.pluto.PortletContainer;

+import org.apache.pluto.binding.PortletDD;

+import org.apache.pluto.binding.SecurityRoleRefDD;

+import org.apache.pluto.binding.SupportedMimeTypeDD;

+import org.apache.pluto.core.InternalPortletRequest;

+import org.apache.pluto.core.InternalPortletWindow;

+import org.apache.pluto.core.PortletEntity;

+import org.apache.pluto.services.DynamicInformationProvider;

+import org.apache.pluto.services.PropertyManagerService;

+import org.apache.pluto.util.Enumerator;

+import org.apache.pluto.util.NamespaceMapper;

+import org.apache.pluto.util.StringUtils;

+import org.apache.pluto.util.impl.NamespaceMapperImpl;

+

+/**

+ * <code>PortletRequest</code> Implementation.

+ */

+public abstract class PortletRequestImpl extends HttpServletRequestWrapper

+    implements PortletRequest, InternalPortletRequest {

+

+    /**

+     * The parent container within which this request was created.

+     */

+    private PortletContainer container;

+

+    /**

+     * The portlet window which is the target of this portlet request.

+     */

+    private InternalPortletWindow internalPortletWindow;

+

+    /**

+     * The PortletContext associated with this Request. This PortletContext must

+     * be initialized from within the <code>PortletServlet</code>.

+     */

+    private PortletContext context;

+

+    /**

+     * The PortalContext within which this request is occuring.

+     */

+    private PortalContext portalContext;

+

+    /**

+     * Holds the portlet session

+     */

+    private PortletSession portletSession;

+

+    private DynamicInformationProvider provider;

+    private NamespaceMapper mapper = new NamespaceMapperImpl();

+

+    /**

+     * true if the HTTP-Body has been accessed

+     */

+    private boolean bodyAccessed;

+

+    /**

+     * true if we are in an include call

+     */

+    private boolean included;

+

+    public PortletRequestImpl(PortletContainer container,

+                              InternalPortletWindow internalPortletWindow,

+                              javax.servlet.http.HttpServletRequest servletRequest) {

+        super(servletRequest);

+        this.container = container;

+        this.internalPortletWindow = internalPortletWindow;

+        this.provider =

+        container.getContainerServices().getDynamicInformationProvider(

+            servletRequest);

+        this.portalContext =

+        container.getContainerServices().getPortalContext();

+

+    }

+

+

+    /**

+     * Determine whether or not the specified WindowState is allowed for this

+     * portlet.

+     * @param state

+     * @return

+     */

+    public boolean isWindowStateAllowed(WindowState state) {

+        Enumeration supportedStates = portalContext.getSupportedWindowStates();

+        while (supportedStates.hasMoreElements()) {

+            if (supportedStates.nextElement().toString().equals(

+                (state.toString()))) {

+                return true;

+            }

+        }

+        return false;

+    }

+

+

+    public boolean isPortletModeAllowed(PortletMode mode) {

+        return isPortletModeAllowedByPortlet(mode)

+               && isPortletModeAllowedByPortal(mode);

+    }

+

+    public PortletMode getPortletMode() {

+        return internalPortletWindow.getPortletMode();

+    }

+

+    public WindowState getWindowState() {

+        return internalPortletWindow.getWindowState();

+    }

+

+    // needs to be implemented in each subclass

+    public abstract PortletPreferences getPreferences();

+

+    public PortletSession getPortletSession() {

+        return getPortletSession(true);

+    }

+

+    public PortletSession getPortletSession(boolean create) {

+        // check if the session was invalidated

+        javax.servlet.http.HttpSession httpSession = this.getHttpServletRequest()

+            .getSession(false);

+

+        if ((portletSession != null) && (httpSession == null)) {

+            portletSession = null;

+        } else if (httpSession != null) {

+            create = true;

+        }

+

+        if (create && portletSession == null) {

+            httpSession = this.getHttpServletRequest().getSession(create);

+            if (httpSession != null) {

+                portletSession =

+                new PortletSessionImpl(context, internalPortletWindow,

+                                       httpSession);

+            }

+        }

+

+        return portletSession;

+    }

+

+    public String getProperty(String name) {

+        if (name == null) {

+            throw new IllegalArgumentException("Attribute name == null");

+        }

+

+        // get properties from request header

+        String prop = this.getHttpServletRequest().getHeader(name);

+        if (prop == null) {

+            // get properties from PropertyManager

+            PropertyManagerService mgr = container.getContainerServices()

+                .getPropertyManagerService();

+            Map map = mgr.getRequestProperties(internalPortletWindow,

+                                               this.getHttpServletRequest());

+            if (map != null) {

+                String[] properties = (String[]) map.get(name);

+                if ((properties != null) && (properties.length > 0)) {

+                    prop = properties[0];

+                }

+            }

+        }

+

+        return prop;

+    }

+

+    public Enumeration getProperties(String name) {

+        if (name == null) {

+            throw new IllegalArgumentException("Property name == null");

+        }

+

+        Set v = new HashSet();

+

+        // get properties from request header

+        Enumeration props = this.getHttpServletRequest().getHeaders(name);

+        if (props != null) {

+            while (props.hasMoreElements()) {

+                v.add(props.nextElement());

+            }

+        }

+

+        // get properties from PropertyManager

+        PropertyManagerService mgr = container.getContainerServices()

+            .getPropertyManagerService();

+        Map map = mgr.getRequestProperties(internalPortletWindow,

+                                           this.getHttpServletRequest());

+        if (map != null) {

+            String[] properties = (String[]) map.get(name);

+

+            if (properties != null) {

+                // add properties to vector

+                for (int i = 0; i < properties.length; i++) {

+                    v.add(properties[i]);

+                }

+            }

+        }

+

+        return new Enumerator(v.iterator());

+    }

+

+    public Enumeration getPropertyNames() {

+        Set v = new HashSet();           

+

+        // get properties from PropertyManager

+        PropertyManagerService mgr = container.getContainerServices()

+            .getPropertyManagerService();

+        Map map = mgr.getRequestProperties(internalPortletWindow,

+                                           this.getHttpServletRequest());

+        if (map != null) {

+            v.addAll(map.keySet());

+        }

+

+        // get properties from request header

+        Enumeration props = this.getHttpServletRequest().getHeaderNames();

+        if (props != null) {

+            while (props.hasMoreElements()) {

+                v.add(props.nextElement());

+            }

+        }

+

+        return new Enumerator(v.iterator());

+    }

+

+    public PortalContext getPortalContext() {

+        return container.getContainerServices().getPortalContext();

+    }

+

+    public String getAuthType() {

+        return this.getHttpServletRequest().getAuthType();

+    }

+

+    public String getContextPath() {

+        return this.internalPortletWindow.getContextPath();

+        //return ((HttpServletRequest)getRequest()).getContextPath();

+    }

+

+    public String getRemoteUser() {

+        return this.getHttpServletRequest().getRemoteUser();

+    }

+

+    public java.security.Principal getUserPrincipal() {

+        return this.getHttpServletRequest().getUserPrincipal();

+    }

+

+    /**

+     * Determines whether a user is mapped to the specified role.  As specified

+     * in PLT-20-3, we must reference the &lt;security-role-ref&gt; mappings

+     * within the deployment descriptor. If no mapping is available, then, and

+     * only then, do we check use the actual role name specified against the web

+     * application deployment descriptor.

+     * @param roleName the name of the role

+     * @return true if it is determined the user has the given role.

+     */

+    public boolean isUserInRole(String roleName) {

+        PortletEntity entity = internalPortletWindow.getPortletEntity();

+        PortletDD def = entity.getPortletDefinition();

+

+        SecurityRoleRefDD ref = null;

+        SecurityRoleRefDD[] refs = def.getSecurityRoleRefs();

+        for (int i = 0; i < refs.length; i++) {

+            if (refs[i].getRoleName().equals(roleName)) {

+                ref = refs[i];

+                break;

+            }

+        }

+

+        String link = null;

+        if (ref != null && ref.getRoleLink() != null) {

+            link = ref.getRoleLink();

+        } else {

+            link = roleName;

+        }

+

+        return this.getHttpServletRequest().isUserInRole(link);

+    }

+

+    public Object getAttribute(String name) {

+        if (name == null) {

+            throw new IllegalArgumentException("Attribute name == null");

+        }

+

+        Object attribute = this.getHttpServletRequest().getAttribute(

+            mapper.encode(internalPortletWindow.getId(), name));

+

+        if (attribute == null && isNameReserved(name)) {

+            attribute = this.getHttpServletRequest().getAttribute(name);

+        }

+        return attribute;

+    }

+

+    public Enumeration getAttributeNames() {

+        Enumeration attributes = this.getHttpServletRequest()

+            .getAttributeNames();

+

+        Vector portletAttributes = new Vector();

+

+        while (attributes.hasMoreElements()) {

+            String attribute = (String) attributes.nextElement();

+

+            String portletAttribute = mapper.decode(

+                internalPortletWindow.getId(), attribute);

+

+            if (portletAttribute != null) { // it is in the portlet's namespace

+                portletAttributes.add(portletAttribute);

+            }

+        }

+

+        return portletAttributes.elements();

+    }

+

+    public String getParameter(String name) {

+        if (name == null) {

+            throw new IllegalArgumentException("Parameter name == null");

+        }

+

+        bodyAccessed = true;

+

+        Map parameters = this.getHttpServletRequest().getParameterMap();

+        String[] values = (String[]) parameters.get(name);

+        if (values != null) {

+            return values[0];

+        }

+        return null;

+    }

+

+    public java.util.Enumeration getParameterNames() {

+        bodyAccessed = true;

+

+        Map parameters = this.getHttpServletRequest().getParameterMap();

+        return Collections.enumeration(parameters.keySet());

+    }

+

+    public String[] getParameterValues(String name) {

+        if (name == null) {

+            throw new IllegalArgumentException("Parameter name == null");

+        }

+

+        bodyAccessed = true;

+

+        String[] values = (String[]) this.getHttpServletRequest()

+            .getParameterMap()

+            .get(name);

+        if (values != null) {

+            values = StringUtils.copy(values);

+        }

+        return values;

+    }

+

+    public Map getParameterMap() {

+        bodyAccessed = true;

+        Map result = StringUtils.copyParameters(

+            this.getHttpServletRequest().getParameterMap());

+        return result;

+    }

+

+    public boolean isSecure() {

+        return this.getHttpServletRequest().isSecure();

+    }

+

+    public void setAttribute(String name, Object o) {

+        if (name == null) {

+            throw new IllegalArgumentException("Attribute name == null");

+        }

+

+        if (o == null) {

+            this.removeAttribute(name);

+        } else if (isNameReserved(name)) {

+            // Reserved names go directly in the underlying request

+            getHttpServletRequest().setAttribute(name, o);

+        } else {

+            this.getHttpServletRequest().setAttribute(

+                mapper.encode(internalPortletWindow.getId(), name), o);

+        }

+    }

+

+    public void removeAttribute(String name) {

+        if (name == null) {

+            throw new IllegalArgumentException("Attribute name == null");

+        }

+        if (isNameReserved(name)) {

+            // Reserved names go directly in the underlying request

+            getHttpServletRequest().removeAttribute(name);

+        } else {

+

+            this.getHttpServletRequest().

+                removeAttribute(

+                    mapper.encode(internalPortletWindow.getId(), name));

+        }

+    }

+

+    public String getRequestedSessionId() {

+        return this.getHttpServletRequest().getRequestedSessionId();

+    }

+

+    public boolean isRequestedSessionIdValid() {

+        return this.getHttpServletRequest().isRequestedSessionIdValid();

+    }

+

+    public String getResponseContentType() {

+        // get the default response content type from the container

+        String responseContentType = provider.getResponseContentType();

+        return responseContentType;

+    }

+

+    public Enumeration getResponseContentTypes() {

+        // get the default response content types from the container

+        Iterator responseContentTypes = provider.getResponseContentTypes();

+

+        return new Enumerator(responseContentTypes);

+    }

+

+    public java.util.Locale getLocale() {

+        return this.getHttpServletRequest().getLocale();

+    }

+

+    public Enumeration getLocales() {

+        return this.getHttpServletRequest().getLocales();

+    }

+

+    public String getScheme() {

+        return this.getHttpServletRequest().getScheme();

+    }

+

+    public String getServerName() {

+        return this.getHttpServletRequest().getServerName();

+    }

+

+    public int getServerPort() {

+        return this.getHttpServletRequest().getServerPort();

+    }

+

+    // --------------------------------------------------------------------------------------------

+

+    // org.apache.pluto.core.InternalPortletRequest implementation --------------------------------

+    public void lateInit(

+        javax.servlet.http.HttpServletRequest webModuleServletRequest) {

+        super.setRequest(webModuleServletRequest);

+    }

+

+    public InternalPortletWindow getInternalPortletWindow() {

+        return internalPortletWindow;

+    }

+

+    public void setIncluded(boolean included) {

+        this.included = included;

+    }

+

+    public boolean isIncluded() {

+        return included;

+    }

+    // --------------------------------------------------------------------------------------------

+

+    // internal methods ---------------------------------------------------------------------------

+    private javax.servlet.http.HttpServletRequest getHttpServletRequest() {

+        return (javax.servlet.http.HttpServletRequest) super.getRequest();

+    }

+

+    /**

+     * Is this attribute name a reserved name (by the J2EE spec)?. Reserved

+     * names begin with "java." or "javax.".

+     */

+    private boolean isNameReserved(String name) {

+        return name.startsWith("java.") || name.startsWith("javax.");

+    }

+    // --------------------------------------------------------------------------------------------

+

+    // additional methods

+    // javax.servlet.http.HttpServletRequestWrapper

+    public java.lang.String getCharacterEncoding() {

+        return this.getHttpServletRequest().getCharacterEncoding();

+    }

+

+    public java.lang.String getContentType() {

+        if (included) {

+            return null;

+        } else {

+            return this.getHttpServletRequest().getContentType();

+        }

+    }

+

+    public int getContentLength() {

+        if (included) {

+            return 0;

+        } else {

+            return getHttpServletRequest().getContentLength();

+        }

+    }

+

+    public BufferedReader getReader()

+        throws java.io.UnsupportedEncodingException, java.io.IOException {

+        if (included) {

+            return null;

+        } else {

+            // the super class will ensure that a IllegalStateException is thrown if getInputStream() was called earlier

+            BufferedReader reader = getHttpServletRequest().getReader();

+            bodyAccessed = true;

+            return reader;

+        }

+    }

+

+

+    public String getPathInfo() {

+        String attr = (String) super.getAttribute(

+            "javax.servlet.include.path_info");

+        return (attr != null) ? attr

+               : super.getPathInfo();

+    }

+

+    public String getQueryString() {

+        String attr = (String) super.getAttribute(

+            "javax.servlet.include.query_string");

+        return (attr != null) ? attr

+               : super.getQueryString();

+    }

+

+    public String getPathTranslated() {

+        return null;

+    }

+

+    public String getRequestURI() {

+        String attr = (String) super.getAttribute(

+            "javax.servlet.include.request_uri");

+        return (attr != null) ? attr

+               : super.getRequestURI();

+    }

+

+    public StringBuffer getRequestURL() {

+        return null;

+    }

+

+    public String getServletPath() {

+        String attr = (String) super.getAttribute(

+            "javax.servlet.include.servlet_path");

+        return (attr != null) ? attr

+               : super.getServletPath();

+    }

+

+

+    //

+    //

+    // @todo WHY? Do we return null to these emthods?

+    //

+    //

+

+    public String getProtocol() {

+        return null;

+    }

+

+    public String getRemoteAddr() {

+        return null;

+    }

+

+    public String getRemoteHost() {

+        return null;

+    }

+

+    public String getRealPath(String path) {

+        return null;

+    }

+

+    public void setCharacterEncoding(String env)

+        throws java.io.UnsupportedEncodingException {

+        if (bodyAccessed) {

+            throw new IllegalStateException(

+                "This method must not be called after the HTTP-Body was accessed !");

+        }

+

+        this.getHttpServletRequest().setCharacterEncoding(env);

+        return;

+    }

+

+    public javax.servlet.ServletInputStream getInputStream()

+        throws java.io.IOException {

+        if (included) {

+            return null;

+        } else {

+            // the super class will ensure that a IllegalStateException is thrown if getReader() was called earlier

+            javax.servlet.ServletInputStream stream = getHttpServletRequest()

+                .getInputStream();

+

+            bodyAccessed = true;

+

+            return stream;

+        }

+    }

+

+    public javax.servlet.RequestDispatcher getRequestDispatcher(String path) {

+        return this.getHttpServletRequest().getRequestDispatcher(path);

+    }

+

+// Internal Implementation Detailes

+

+    public void setPortletContext(PortletContext context) {

+        this.context = context;

+    }

+

+    public PortletContainer getContainer() {

+        return container;

+    }

+

+    public InternalPortletWindow getWindow() {

+        return internalPortletWindow;

+    }

+

+    private boolean isPortletModeAllowedByPortlet(PortletMode mode) {

+        PortletDD dd = internalPortletWindow.getPortletEntity()

+            .getPortletDefinition();

+

+        SupportedMimeTypeDD[] mimes = dd.getSupportedMimeTypes();

+        for (int i = 0; i < mimes.length; i++) {

+            String[] modes = mimes[i].getPortletModes();

+            for (int j = 0; j < modes.length; j++) {

+                if (modes[j].equals(mode.toString())) {

+                    return true;

+                }

+            }

+        }

+        return false;

+    }

+

+    private boolean isPortletModeAllowedByPortal(PortletMode mode) {

+        Enumeration supportedModes = portalContext.getSupportedPortletModes();

+        while (supportedModes.hasMoreElements()) {

+            if (supportedModes.nextElement().toString().equals(

+                (mode.toString()))) {

+                return true;

+            }

+        }

+        return false;

+    }

+

+

+}

diff --git a/src/java/org/apache/pluto/core/impl/PortletResponseImpl.java b/src/java/org/apache/pluto/core/impl/PortletResponseImpl.java
new file mode 100644
index 0000000..fcbb442
--- /dev/null
+++ b/src/java/org/apache/pluto/core/impl/PortletResponseImpl.java
@@ -0,0 +1,295 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.core.impl;

+

+import java.io.IOException;

+import java.io.PrintWriter;

+import java.io.UnsupportedEncodingException;

+import java.util.HashMap;

+import java.util.Map;

+

+import javax.portlet.PortletResponse;

+import javax.servlet.ServletOutputStream;

+import javax.servlet.http.HttpServletRequest;

+

+import org.apache.pluto.PortletContainer;

+import org.apache.pluto.core.InternalPortletResponse;

+import org.apache.pluto.core.InternalPortletWindow;

+import org.apache.pluto.services.PortletContainerServices;

+import org.apache.pluto.services.PropertyManagerService;

+import org.apache.pluto.services.ResourceURLProvider;

+import org.apache.pluto.util.PrintWriterServletOutputStream;

+

+public abstract class PortletResponseImpl

+    extends javax.servlet.http.HttpServletResponseWrapper

+    implements InternalPortletResponse, PortletResponse {

+

+    PortletContainer container;

+

+    InternalPortletWindow internalPortletWindow;

+

+    /**

+     * this variable holds the servlet request of the target/portlet's web

+     * module

+     */

+    private javax.servlet.http.HttpServletRequest webModuleServletRequest;

+

+    private boolean usingWriter;

+    private boolean usingStream;

+

+    private ServletOutputStream wrappedWriter;

+    private Map properties;

+

+    /**

+     * true if we are in an include call

+     */

+    private boolean included;

+

+    public PortletResponseImpl(PortletContainer container,

+                               InternalPortletWindow internalPortletWindow,

+                               javax.servlet.http.HttpServletRequest servletRequest,

+                               javax.servlet.http.HttpServletResponse servletResponse) {

+        super(servletResponse);

+        this.container = container;

+        this.webModuleServletRequest = servletRequest;

+        this.internalPortletWindow = internalPortletWindow;

+    }

+

+    // javax.portlet.PortletResponse --------------------------------------------------------------

+    public void addProperty(String key, String value) {

+        if (key == null) {

+            throw new IllegalArgumentException("Property key == null");

+        }

+

+        Map props = getProperties();

+

+        String[] oldValues = (String[]) props.get(key);

+        String[] newValues = null;

+        if (oldValues == null) {

+            newValues = new String[]{value};

+        } else {

+            int len = oldValues.length;

+            newValues = new String[len + 1];

+            System.arraycopy(oldValues, 0, newValues, 0, len);

+            newValues[len] = value;

+        }

+        props.put(key, newValues);

+

+        PropertyManagerService service = container.getContainerServices()

+            .getPropertyManagerService();

+        service.setResponseProperties(internalPortletWindow,

+                                      this.getHttpServletRequest(),

+                                      _getHttpServletResponse(), props);

+

+    }

+

+    public void setProperty(String key, String value) {

+        if (key == null) {

+            throw new IllegalArgumentException("Property key == null");

+        }

+

+        Map props = getProperties();

+

+        String[] newValues = new String[]{value};

+        props.put(key, newValues);

+

+        PropertyManagerService service = container.getContainerServices()

+            .getPropertyManagerService();

+        service.setResponseProperties(internalPortletWindow,

+                                      this.getHttpServletRequest(),

+                                      _getHttpServletResponse(), props);

+    }

+

+    public String encodeURL(String path) {

+        if (path.indexOf("://") == -1 && !path.startsWith("/")) {

+            throw new IllegalArgumentException(

+                "only absolute URLs or full path URIs are allowed");

+        }

+

+        PortletContainerServices services = getContainer()

+            .getContainerServices();

+        ResourceURLProvider provider =

+            services.getDynamicInformationProvider(webModuleServletRequest)

+            .getResourceURLProvider(internalPortletWindow);

+        if (path.indexOf("://") != -1) {

+            provider.setAbsoluteURL(path);

+        } else {

+            provider.setFullPath(path);

+        }

+        return this._getHttpServletResponse().encodeURL(provider.toString());

+    }

+    // --------------------------------------------------------------------------------------------

+

+    // org.apache.pluto.core.InternalPortletResponse implementation -------------------------------

+    public void lateInit(

+        javax.servlet.http.HttpServletRequest webModuleServletRequest,

+        javax.servlet.http.HttpServletResponse webModuleServletResponse) {

+        this.webModuleServletRequest = webModuleServletRequest;

+        this.setResponse(webModuleServletResponse);

+    }

+    // --------------------------------------------------------------------------------------------

+

+    // internal methods ---------------------------------------------------------------------------

+    protected javax.servlet.http.HttpServletResponse _getHttpServletResponse() {

+        return (javax.servlet.http.HttpServletResponse) super.getResponse();

+    }

+

+    protected javax.servlet.http.HttpServletRequest getHttpServletRequest() {

+        return webModuleServletRequest;

+    }

+

+    private Map getProperties() {

+        if (properties == null) {

+            properties = new HashMap();

+        }

+        return properties;

+    }

+    // --------------------------------------------------------------------------------------------

+

+    // additional methods -------------------------------------------------------------------------

+    // servlet-only implementation 

+    // (inherited from HttpServletResponseWrapper)

+    public void addCookie(javax.servlet.http.Cookie cookie) {

+        this._getHttpServletResponse().addCookie(cookie);

+    }

+

+    public boolean containsHeader(String name) {

+        return this._getHttpServletResponse().containsHeader(name);

+    }

+

+    public String encodeRedirectUrl(String url) {

+        return included

+               ? null : this._getHttpServletResponse().encodeRedirectUrl(url);

+    }

+

+    public String encodeRedirectURL(String url) {

+        return included

+               ? null : this._getHttpServletResponse().encodeRedirectURL(url);

+    }

+

+    public void sendRedirect(String location) throws java.io.IOException {

+        this._getHttpServletResponse().sendRedirect(location);

+    }

+

+    public void setDateHeader(String name, long date) {

+        this._getHttpServletResponse().setDateHeader(name, date);

+    }

+

+    public void sendError(int sc, String msg) throws java.io.IOException {

+        this._getHttpServletResponse().sendError(sc, msg);

+    }

+

+    public void sendError(int sc) throws java.io.IOException {

+        this._getHttpServletResponse().sendError(sc);

+    }

+

+    public void addHeader(String name, String value) {

+        this._getHttpServletResponse().addHeader(name, value);

+    }

+

+    public void setIntHeader(String name, int value) {

+        this._getHttpServletResponse().setIntHeader(name, value);

+    }

+

+    public void addDateHeader(String name, long date) {

+        this._getHttpServletResponse().addDateHeader(name, date);

+    }

+

+    public void setHeader(String name, String value) {

+        this._getHttpServletResponse().setHeader(name, value);

+    }

+

+    public void setStatus(int sc) {

+        this._getHttpServletResponse().setStatus(sc);

+    }

+

+    public void setStatus(int sc, String sm) {

+        this._getHttpServletResponse().setStatus(sc, sm);

+    }

+

+    public void addIntHeader(String name, int value) {

+        this._getHttpServletResponse().addIntHeader(name, value);

+    }

+

+    public void setContentLength(int len) {

+        this._getHttpServletResponse().setContentLength(len);

+    }

+

+    public String encodeUrl(String url) {

+        return this.encodeURL(url);

+    }

+

+    public void setLocale(java.util.Locale loc) {

+        this._getHttpServletResponse().setLocale(loc);

+    }

+

+    public ServletOutputStream getOutputStream() throws IllegalStateException,

+                                                        IOException {

+        if (usingWriter) {

+            throw new IllegalStateException(

+                "getPortletOutputStream can't be used after getWriter was invoked");

+        }

+

+        if (wrappedWriter == null) {

+            wrappedWriter =

+            new PrintWriterServletOutputStream(

+                _getHttpServletResponse().getWriter());

+        }

+

+        usingStream = true;

+

+        return wrappedWriter;

+    }

+

+    public PrintWriter getWriter() throws UnsupportedEncodingException,

+                                          IllegalStateException, IOException {

+        if (usingStream) {

+            throw new IllegalStateException(

+                "getWriter can't be used after getOutputStream was invoked");

+        }

+

+        usingWriter = true;

+

+        return _getHttpServletResponse().getWriter();

+    }

+

+    // other

+    public InternalPortletWindow getInternalPortletWindow() {

+        return internalPortletWindow;

+    }

+    

+    // internal

+    

+    HttpServletRequest getHttpDServletRequest() {

+        return webModuleServletRequest;

+    }

+

+    public void setIncluded(boolean included) {

+        this.included = included;

+    }

+

+    public boolean isIncluded() {

+        return included;

+    }

+

+    public PortletContainer getContainer() {

+        return container;

+    }

+}

diff --git a/src/java/org/apache/pluto/core/impl/PortletSessionImpl.java b/src/java/org/apache/pluto/core/impl/PortletSessionImpl.java
new file mode 100644
index 0000000..503391d
--- /dev/null
+++ b/src/java/org/apache/pluto/core/impl/PortletSessionImpl.java
@@ -0,0 +1,211 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.core.impl;

+

+import java.util.Enumeration;

+import java.util.Vector;

+

+import javax.portlet.PortletContext;

+import javax.portlet.PortletSession;

+import javax.portlet.PortletSessionUtil;

+

+import org.apache.pluto.core.InternalPortletWindow;

+

+public class PortletSessionImpl implements PortletSession,

+                                           javax.servlet.http.HttpSession {

+    private final int DEFAULT_SCOPE = PortletSession.PORTLET_SCOPE;

+

+    private javax.servlet.http.HttpSession httpSession;

+

+    private PortletContext portletContext = null;

+

+    private InternalPortletWindow internalPortletWindow;

+

+    public PortletSessionImpl(PortletContext context,

+                              InternalPortletWindow internalPortletWindow,

+                              javax.servlet.http.HttpSession httpSession) {

+        this.portletContext = context;

+        this.internalPortletWindow = internalPortletWindow;

+        this.httpSession = httpSession;

+    }

+

+    // javax.portlet.PortletSession and javax.servlet.http.HttpSession implementation -------------

+    public Object getAttribute(String name) {

+        return this.getAttribute(name, DEFAULT_SCOPE);

+    }

+

+    public Enumeration getAttributeNames() {

+        return this.getAttributeNames(DEFAULT_SCOPE);

+    }

+

+    public long getCreationTime() throws java.lang.IllegalStateException {

+        return httpSession.getCreationTime();

+    }

+

+    public String getId() throws java.lang.IllegalStateException {

+        return httpSession.getId();

+    }

+

+    public long getLastAccessedTime() throws java.lang.IllegalStateException {

+        return httpSession.getLastAccessedTime();

+    }

+

+    public int getMaxInactiveInterval() {

+        return httpSession.getMaxInactiveInterval();

+    }

+

+    public void invalidate() throws java.lang.IllegalStateException {

+        httpSession.invalidate();

+    }

+

+    public boolean isNew() throws java.lang.IllegalStateException {

+        return httpSession.isNew();

+    }

+

+    public void removeAttribute(String name) {

+        this.removeAttribute(name, DEFAULT_SCOPE);

+    }

+

+    public void setAttribute(String name, Object value) {

+        this.setAttribute(name, value, DEFAULT_SCOPE);

+    }

+

+    public void setMaxInactiveInterval(int interval) {

+        httpSession.setMaxInactiveInterval(interval);

+    }

+    // --------------------------------------------------------------------------------------------

+

+    // javax.portlet.PortletSession implementation ------------------------------------------------

+    public java.lang.Object getAttribute(String name, int scope)

+        throws java.lang.IllegalStateException {

+        if (name == null) {

+            throw new IllegalArgumentException("name must not be null");

+        }

+        if (scope == PortletSession.APPLICATION_SCOPE) {

+            return httpSession.getAttribute(name);

+        } else {

+            Object attribute = httpSession.getAttribute(

+                "javax.portlet.p." + internalPortletWindow.getId() + "?" + name);

+            if (attribute == null) {

+                // not sure, if this should be done for all attributes or only javax.servlet.

+                attribute = httpSession.getAttribute(name);

+            }

+            return attribute;

+        }

+    }

+

+    public java.util.Enumeration getAttributeNames(int scope) {

+        if (scope == PortletSession.APPLICATION_SCOPE) {

+            return httpSession.getAttributeNames();

+        } else {

+            Enumeration attributes = httpSession.getAttributeNames();

+

+            Vector portletAttributes = new Vector();

+

+            /* Fix that ONLY attributes of PORTLET_SCOPE are returned. */

+            int prefix_length = "javax.portlet.p.".length();

+            String portletWindowId = internalPortletWindow.getId().toString();

+

+            while (attributes.hasMoreElements()) {

+                String attribute = (String) attributes.nextElement();

+

+                int attributeScope = PortletSessionUtil.decodeScope(attribute);

+

+                if (attributeScope == PortletSession.PORTLET_SCOPE &&

+                    attribute.startsWith(portletWindowId, prefix_length)) {

+                    String portletAttribute = PortletSessionUtil.decodeAttributeName(

+                        attribute);

+

+                    if (portletAttribute != null) { // it is in the portlet's namespace

+                        portletAttributes.add(portletAttribute);

+                    }

+                }

+            }

+

+            return portletAttributes.elements();

+        }

+    }

+

+    public void removeAttribute(String name, int scope)

+        throws java.lang.IllegalStateException {

+        if (name == null) {

+            throw new IllegalArgumentException("name must not be null");

+        }

+        if (scope == PortletSession.APPLICATION_SCOPE) {

+            httpSession.removeAttribute(name);

+        } else {

+            httpSession.removeAttribute(

+                "javax.portlet.p." + internalPortletWindow.getId() + "?" + name);

+        }

+    }

+

+    public void setAttribute(java.lang.String name, java.lang.Object value,

+                             int scope) throws IllegalStateException {

+        if (name == null) {

+            throw new IllegalArgumentException("name must not be null");

+        }

+        if (scope == PortletSession.APPLICATION_SCOPE) {

+            httpSession.setAttribute(name, value);

+        } else {

+            httpSession.setAttribute(

+                "javax.portlet.p." + internalPortletWindow.getId() + "?" + name,

+                value);

+        }

+    }

+

+    public PortletContext getPortletContext() {

+        return getInternalPortletContext();

+    }

+    // --------------------------------------------------------------------------------------------

+

+    // javax.servlet.http.HttpSession implementation ----------------------------------------------

+    public javax.servlet.ServletContext getServletContext() {

+        // TBD, open issue. it would be good if we could also implement the ServletContext interface at the PortletContextImpl

+        return httpSession.getServletContext();

+    }

+

+    public javax.servlet.http.HttpSessionContext getSessionContext() {

+        return httpSession.getSessionContext();

+    }

+

+    public Object getValue(String name) {

+        return this.getAttribute(name, DEFAULT_SCOPE);

+    }

+

+    public String[] getValueNames() {

+        // TBD

+        return null;

+    }

+

+    public void putValue(String name, Object value) {

+        this.setAttribute(name, value, DEFAULT_SCOPE);

+    }

+

+    public void removeValue(String name) {

+        this.removeAttribute(name, DEFAULT_SCOPE);

+    }

+    // --------------------------------------------------------------------------------------------

+

+    // internal methods ---------------------------------------------------------------------------

+    private synchronized PortletContext getInternalPortletContext() {

+        return this.portletContext;

+    }

+    // --------------------------------------------------------------------------------------------

+}

diff --git a/src/java/org/apache/pluto/core/impl/PortletURLImpl.java b/src/java/org/apache/pluto/core/impl/PortletURLImpl.java
new file mode 100644
index 0000000..a1bb973
--- /dev/null
+++ b/src/java/org/apache/pluto/core/impl/PortletURLImpl.java
@@ -0,0 +1,252 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.core.impl;

+

+import java.util.Enumeration;

+import java.util.HashMap;

+import java.util.Iterator;

+import java.util.Map;

+

+import javax.portlet.PortalContext;

+import javax.portlet.PortletMode;

+import javax.portlet.PortletModeException;

+import javax.portlet.PortletSecurityException;

+import javax.portlet.PortletURL;

+import javax.portlet.WindowState;

+import javax.portlet.WindowStateException;

+

+import org.apache.pluto.PortletContainer;

+import org.apache.pluto.binding.PortletDD;

+import org.apache.pluto.binding.SupportedMimeTypeDD;

+import org.apache.pluto.core.InternalPortletWindow;

+import org.apache.pluto.services.PortletURLProvider;

+import org.apache.pluto.util.StringManager;

+import org.apache.pluto.util.StringUtils;

+

+public class PortletURLImpl implements PortletURL {

+

+    private static final StringManager EXCEPTIONS =

+        StringManager.getManager(PortletURLImpl.class.getPackage().getName());

+

+

+    private PortletContainer container;

+    protected PortletMode mode = null;

+

+    protected Map parameters = new HashMap();

+

+    protected InternalPortletWindow internalPortletWindow;

+

+    protected boolean secure;

+    protected javax.servlet.http.HttpServletRequest servletRequest;

+    protected javax.servlet.http.HttpServletResponse servletResponse;

+    protected WindowState state;

+    protected boolean isAction;

+

+    private PortalContext context;

+

+    public PortletURLImpl(PortletContainer container,

+                          InternalPortletWindow internalPortletWindow,

+                          javax.servlet.http.HttpServletRequest servletRequest,

+                          javax.servlet.http.HttpServletResponse servletResponse,

+                          boolean isAction) {

+        this.container = container;

+        this.internalPortletWindow = internalPortletWindow;

+        this.servletRequest = servletRequest;

+        this.servletResponse = servletResponse;

+        secure = servletRequest.isSecure();

+        this.isAction = isAction;

+        this.context = container.getContainerServices().getPortalContext();

+    }

+

+    // javax.portlet.PortletURL -------------------------------------------------------------------

+    public void setWindowState(WindowState windowState)

+        throws WindowStateException {

+        if (windowState != null && isWindowStateAllowed(windowState)) {

+            state = windowState;

+            return;

+        }

+

+        throw new WindowStateException(

+            "unsupported Window State used: " + windowState, windowState);

+    }

+

+    public void setPortletMode(PortletMode portletMode)

+        throws PortletModeException {

+        // Test and throw exception if not allowed.

+        isPortletModeAllowed(portletMode);

+        mode = portletMode;

+    }

+

+    public void setParameter(String name, String value) {

+        if (name == null || value == null) {

+            throw new IllegalArgumentException(

+                "name and value must not be null");

+        }

+

+        parameters.put(name, new String[]{value});

+    }

+

+    public void setParameter(String name, String[] values) {

+        if (name == null || values == null || values.length == 0) {

+            throw new IllegalArgumentException(

+                "name and values must not be null or values be an empty array");

+        }

+

+        parameters.put(name, StringUtils.copy(values));

+    }

+

+    /* (non-Javadoc)

+     * @see javax.portlet.PortletURL#setParameters(Map)

+     */

+    public void setParameters(Map parameters) {

+        if (parameters == null) {

+            throw new IllegalArgumentException("Parameters must not be null.");

+        }

+        for (Iterator iter = parameters.entrySet().iterator(); iter.hasNext();) {

+            Map.Entry entry = (Map.Entry) iter.next();

+            if (!(entry.getKey() instanceof String)) {

+                throw new IllegalArgumentException(

+                    "Key must not be null and of type java.lang.String.");

+            }

+            if (!(entry.getValue() instanceof String[])) {

+                throw new IllegalArgumentException(

+                    "Value must not be null and of type java.lang.String[].");

+            }

+        }

+

+        this.parameters = StringUtils.copyParameters(parameters);

+    }

+

+    public void setSecure(boolean secure) throws PortletSecurityException {

+        this.secure = secure;

+    }

+

+    public String toString() {

+        StringBuffer url = new StringBuffer(200);

+

+        PortletURLProvider urlProvider = container.getContainerServices()

+            .getDynamicInformationProvider(servletRequest)

+            .getPortletURLProvider(internalPortletWindow);

+

+        if (mode != null) {

+            urlProvider.setPortletMode(mode);

+        }

+        if (state != null) {

+            urlProvider.setWindowState(state);

+        }

+        if (isAction) {

+            urlProvider.setAction(true);

+        }

+        if (secure) {

+            urlProvider.setSecure();

+        }

+        urlProvider.clearParameters();

+        urlProvider.setParameters(parameters);

+

+        url.append(urlProvider.toString());

+

+        return url.toString();

+    }

+    // --------------------------------------------------------------------------------------------

+

+

+    // additional methods -------------------------------------------------------------------------

+    public String getParameter(String name) {

+        return (String) parameters.get(name);

+    }

+

+    public String[] getParameters(String name) {

+        return (String[]) parameters.get(name);

+    }

+

+    public PortletMode getPortletMode() {

+        return mode;

+    }

+

+    public WindowState getWindowState() {

+        return state;

+    }

+    // --------------------------------------------------------------------------------------------

+

+

+    private boolean isPortletModeAllowed(PortletMode mode)

+        throws PortletModeException {

+        if (mode == null) {

+            throw new PortletModeException(

+                EXCEPTIONS.getString("javax.portlet.PortletModeException.null"),

+                null);

+        }

+

+        return isPortletModeAllowedByPortlet(mode)

+               && isPortletModeAllowedByPortal(mode);

+    }

+

+    private boolean isPortletModeAllowedByPortlet(PortletMode mode)

+        throws PortletModeException {

+        // PLT 8.1: View Portlet Mode should always be

+        // supported by a portlet, even if not defined in the descriptor

+        if (mode.equals(PortletMode.VIEW)) {

+            return true;

+        }

+

+        PortletDD dd = internalPortletWindow.getPortletEntity()

+            .getPortletDefinition();

+        SupportedMimeTypeDD[] mimes = dd.getSupportedMimeTypes();

+        for (int i = 0; i < mimes.length; i++) {

+            String[] modes = mimes[i].getPortletModes();

+            for (int j = 0; j < modes.length; j++) {

+                if (modes[j].toUpperCase().equals(

+                    mode.toString().toUpperCase())) {

+                    return true;

+                }

+            }

+        }

+        String message = EXCEPTIONS.getString(

+            "javax.portlet.PortletModeException.portlet", mode.toString());

+

+        throw new PortletModeException(message, mode);

+    }

+

+    private boolean isPortletModeAllowedByPortal(PortletMode mode)

+        throws PortletModeException {

+        Enumeration supportedModes = context.getSupportedPortletModes();

+        while (supportedModes.hasMoreElements()) {

+            if (supportedModes.nextElement().toString().toUpperCase().equals(

+                (mode.toString().toUpperCase()))) {

+                return true;

+            }

+        }

+        String message = EXCEPTIONS.getString(

+            "javax.portlet.PortletModeException.portal", mode.toString());

+

+        throw new PortletModeException(message, mode);

+    }

+

+    private boolean isWindowStateAllowed(WindowState state) {

+        Enumeration supportedStates = context.getSupportedWindowStates();

+        while (supportedStates.hasMoreElements()) {

+            if (supportedStates.nextElement().toString().toUpperCase().equals(

+                (state.toString().toUpperCase()))) {

+                return true;

+            }

+        }

+        return false;

+    }

+}

diff --git a/src/java/org/apache/pluto/core/impl/RenderRequestImpl.java b/src/java/org/apache/pluto/core/impl/RenderRequestImpl.java
new file mode 100644
index 0000000..b494699
--- /dev/null
+++ b/src/java/org/apache/pluto/core/impl/RenderRequestImpl.java
@@ -0,0 +1,84 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.core.impl;

+

+import java.io.BufferedReader;

+import java.io.IOException;

+import java.util.Enumeration;

+

+import javax.portlet.PortletPreferences;

+import javax.portlet.RenderRequest;

+

+import org.apache.commons.logging.Log;

+import org.apache.commons.logging.LogFactory;

+import org.apache.pluto.Constants;

+import org.apache.pluto.PortletContainer;

+import org.apache.pluto.core.InternalPortletWindow;

+

+/**

+ * To change this generated comment edit the template variable "typecomment":

+ * Window>Preferences>Java>Templates. To enable and disable the creation of type

+ * comments go to Window>Preferences>Java>Code Generation.

+ */

+public class RenderRequestImpl extends PortletRequestImpl

+    implements RenderRequest {

+    private static final Log LOG = LogFactory.getLog(RenderRequestImpl.class);

+    /**

+     * Holds the portlet preferences

+     */

+    private PortletPreferences portletPreferences = null;

+

+    public RenderRequestImpl(PortletContainer container,

+                             InternalPortletWindow internalPortletWindow,

+                             javax.servlet.http.HttpServletRequest servletRequest) {

+        super(container, internalPortletWindow, servletRequest);

+    }

+

+    // additional methods -------------------------------------------------------------------------

+    /**

+     * @see javax.servlet.ServletRequest#getReader()

+     */

+    public BufferedReader getReader() throws IOException {

+        return super.getReader();

+    }

+

+    public PortletPreferences getPreferences() {

+        if (LOG.isDebugEnabled()) {

+            LOG.debug("Getting Preferences: " + portletPreferences);

+        }

+

+        if (portletPreferences == null) {

+            portletPreferences = new PortletPreferencesImpl(getContainer(),

+                                                            getWindow(), this,

+                                                            Constants.METHOD_ACTION);

+        }

+        if (LOG.isDebugEnabled()) {

+            LOG.debug("Returning Preferences: " + portletPreferences);

+            Enumeration e = portletPreferences.getNames();

+            while (e.hasMoreElements()) {

+                String name = (String) e.nextElement();

+                LOG.debug(" - Preference: name = " + name);

+            }

+        }

+

+        return portletPreferences;

+    }

+    // --------------------------------------------------------------------------------------------

+}

diff --git a/src/java/org/apache/pluto/core/impl/RenderResponseImpl.java b/src/java/org/apache/pluto/core/impl/RenderResponseImpl.java
new file mode 100644
index 0000000..66b1ce8
--- /dev/null
+++ b/src/java/org/apache/pluto/core/impl/RenderResponseImpl.java
@@ -0,0 +1,194 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.core.impl;

+

+import java.io.IOException;

+import java.io.OutputStream;

+import java.io.PrintWriter;

+

+import javax.portlet.PortletURL;

+import javax.portlet.RenderResponse;

+

+import org.apache.pluto.PortletContainer;

+import org.apache.pluto.binding.PortletDD;

+import org.apache.pluto.binding.SupportedMimeTypeDD;

+import org.apache.pluto.core.InternalPortletWindow;

+import org.apache.pluto.core.PortletEntity;

+import org.apache.pluto.services.PortalCallbackProvider;

+import org.apache.pluto.util.NamespaceMapper;

+import org.apache.pluto.util.impl.NamespaceMapperImpl;

+

+public class RenderResponseImpl extends PortletResponseImpl

+    implements RenderResponse {

+    private static final String illegalStateExceptionText = "No content type set.";

+

+    private String currentContentType = null;   // needed as servlet 2.3 does not have a response.getContentType

+

+    private NamespaceMapper mapper = new NamespaceMapperImpl();

+

+    public RenderResponseImpl(PortletContainer container,

+                              InternalPortletWindow internalPortletWindow,

+                              javax.servlet.http.HttpServletRequest servletRequest,

+                              javax.servlet.http.HttpServletResponse servletResponse) {

+        super(container, internalPortletWindow, servletRequest,

+              servletResponse);

+    }

+

+    // javax.portlet.RenderResponse ---------------------------------------------------------------

+    public String getContentType() {

+        // in servlet 2.4 we could simply use this:

+        // return this._getHttpServletResponse().getContentType();

+        return currentContentType;

+    }

+

+    public PortletURL createRenderURL() {

+        PortletURL url = createURL(false);

+        return url;

+    }

+

+    public PortletURL createActionURL() {

+        PortletURL url = createURL(true);

+        return url;

+    }

+

+    public String getNamespace() {

+        return mapper.encode(getInternalPortletWindow().getId(), "");

+    }

+

+    public void setTitle(String title) {

+        PortalCallbackProvider callback =

+            container.getContainerServices().getPortalCallbackProvider();

+

+        callback.setTitle(this.getHttpServletRequest(),

+                          getInternalPortletWindow(),

+                          title);

+    }

+

+    public void setContentType(String type) {

+        String mimeType = stripCharacterEncoding(type);

+        if (!isValidContentType(mimeType)) {

+            throw new IllegalArgumentException(mimeType);

+        }

+        this._getHttpServletResponse().setContentType(mimeType);

+        currentContentType = mimeType;

+    }

+

+    public String getCharacterEncoding() {

+        return this._getHttpServletResponse().getCharacterEncoding();

+    }

+

+    public PrintWriter getWriter() throws IOException, IllegalStateException {

+        if (currentContentType == null) {

+            throw new java.lang.IllegalStateException(

+                illegalStateExceptionText);

+        }

+

+        return super.getWriter();

+    }

+

+    public java.util.Locale getLocale() {

+        return this.getHttpServletRequest().getLocale();

+    }

+

+    public void setBufferSize(int size) {

+        throw new IllegalStateException(

+            "portlet container does not support buffering");

+    }

+

+    public int getBufferSize() {

+        //return this._getHttpServletResponse().getBufferSize();

+        return 0;

+    }

+

+    public void flushBuffer() throws java.io.IOException {

+        this._getHttpServletResponse().flushBuffer();

+    }

+

+    public void resetBuffer() {

+        this._getHttpServletResponse().resetBuffer();

+    }

+

+    public boolean isCommitted() {

+        return this._getHttpServletResponse().isCommitted();

+    }

+

+    public void reset() {

+        this._getHttpServletResponse().reset();

+    }

+

+    public OutputStream getPortletOutputStream() throws java.io.IOException,

+                                                        java.lang.IllegalStateException {

+        if (currentContentType == null) {

+            throw new java.lang.IllegalStateException(

+                illegalStateExceptionText);

+        }

+        return getOutputStream();

+    }

+    // --------------------------------------------------------------------------------------------

+

+    // internal methods ---------------------------------------------------------------------------

+    /**

+     * @param isAction

+     * @return

+     * @todo make dynamic? as service?

+     */

+    private PortletURL createURL(boolean isAction) {

+        return new PortletURLImpl(container,

+                                  getInternalPortletWindow(),

+                                  getHttpServletRequest(),

+                                  _getHttpServletResponse(),

+                                  isAction);

+

+    }

+

+    private boolean isValidContentType(String type) {

+        type = stripCharacterEncoding(type);

+        String wildcard = null;

+        int index = type.indexOf("/");

+        if (index > -1) {

+            wildcard = type.substring(0, index);

+        }

+

+        PortletEntity entity = internalPortletWindow.getPortletEntity();

+        PortletDD def = entity.getPortletDefinition();

+        SupportedMimeTypeDD[] mimes = def.getSupportedMimeTypes();

+        for (int i = 0; i < mimes.length; i++) {

+            String mt = mimes[i].getMimeType();

+            if (mt.equals(type)) {

+                return true;

+            } else if (mt.startsWith(wildcard)) {

+                return true;

+            }

+        }

+        return false;

+    }

+

+    private String stripCharacterEncoding(String type) {

+        int xs = type.indexOf(';');

+        String strippedType;

+        if (xs == -1) {

+            strippedType = type;

+        } else {

+            strippedType = type.substring(0, xs);

+        }

+        return strippedType.trim();

+    }

+    // --------------------------------------------------------------------------------------------

+}

diff --git a/src/java/org/apache/pluto/core/impl/ResourceBundleFactory.java b/src/java/org/apache/pluto/core/impl/ResourceBundleFactory.java
new file mode 100644
index 0000000..150f9fd
--- /dev/null
+++ b/src/java/org/apache/pluto/core/impl/ResourceBundleFactory.java
@@ -0,0 +1,76 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ *

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ *

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.apache.pluto.core.impl;

+

+import java.util.ListResourceBundle;

+import java.util.Locale;

+import java.util.Map;

+import java.util.MissingResourceException;

+import java.util.ResourceBundle;

+

+import org.apache.pluto.binding.PortletDD;

+import org.apache.pluto.binding.PortletInfoDD;

+

+/**

+ * @author <a href="ddewolf@apache.org">David H. DeWolf</a>

+ */

+class ResourceBundleFactory {

+

+    private ResourceBundle defaultBundle;

+    private Map bundles = new java.util.HashMap();

+    private String bundleName;

+

+    public ResourceBundleFactory(PortletDD dd) {

+        PortletInfoDD info = dd.getPortletInfo();

+        final String[] title = new String[]{"javax.portlet.title",

+                                            info.getTitle()};

+        final String[] shrtt = new String[]{"javax.portlet.short-title",

+                                            info.getShortTitle()};

+        final String[] keys = new String[]{"javax.portlet.keywords",

+                                           info.getKeywords()};

+        defaultBundle = new ListResourceBundle() {

+            public Object[][] getContents() {

+                return new String[][]{title, shrtt, keys};

+            }

+        };

+

+        bundleName = dd.getResourceBundle();

+    }

+

+    public ResourceBundle getResourceBundle(Locale locale) {

+        if (bundles.containsKey(locale)) {

+            return (ResourceBundle) bundles.get(locale);

+        }

+

+        try {

+            if (bundleName != null) {

+                ClassLoader loader = Thread.currentThread()

+                    .getContextClassLoader();

+                ResourceBundle bundle = ResourceBundle.getBundle(bundleName,

+                                                                 locale,

+                                                                 loader);

+                if (bundle != null) {

+                    bundles.put(locale, bundle);

+                    return bundle;

+                }

+            }

+        } catch (MissingResourceException mre) {

+            bundles.put(locale, defaultBundle);

+        }

+

+        return defaultBundle;

+    }

+}

diff --git a/src/java/org/apache/pluto/om/ObjectID.java b/src/java/org/apache/pluto/om/ObjectID.java
new file mode 100644
index 0000000..3556081
--- /dev/null
+++ b/src/java/org/apache/pluto/om/ObjectID.java
@@ -0,0 +1,30 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.om;

+

+

+/**

+ * * Wraps around the Object IDs.

+ */

+

+public interface ObjectID {

+

+

+}

diff --git a/src/java/org/apache/pluto/package.html b/src/java/org/apache/pluto/package.html
new file mode 100644
index 0000000..6babaf9
--- /dev/null
+++ b/src/java/org/apache/pluto/package.html
@@ -0,0 +1,42 @@
+<HTML>

+<HEAD><TITLE>Apache Pluto</TITLE></HEAD>

+<BODY>

+<P>The root package of the Pluto Portlet Container.</P>

+

+<P>Portals embedding Pluto must implement the 

+   {@link org.apache.pluto.services.PortletContainerServices}

+   interfac and then retrieve an instance of the container from

+   the {@link org.apache.pluto.PortletContainerFactory}.</P>

+<H3>Initialization of the container</H3>   

+<P>

+<xmp>

+PortletContainerServices services = // your implementation!

+PortletContainer container =

+   PortletContainerFactory.createContainer("MyContainer", services);

+

+ServletContext context = // the servlet context within which the portal is executing

+container.init(servletContext);

+</xmp>

+</P>

+

+<H3>Processing of Requests</H3>   

+<P>

+<xmp>

+if(isActionRequest) {

+    container.doAction(request, response);

+}

+else if(isRenderRequest) {

+    container.doRender(request, response);

+}

+</xmp>

+</P>

+

+<H3>Shutting Down the Container</H3>

+<P>

+<xmp>

+container.destroy();

+</xmp>

+</P>

+

+</BODY>

+</HTML>
\ No newline at end of file
diff --git a/src/java/org/apache/pluto/portlet/ActionRequestWrapper.java b/src/java/org/apache/pluto/portlet/ActionRequestWrapper.java
new file mode 100644
index 0000000..38cb476
--- /dev/null
+++ b/src/java/org/apache/pluto/portlet/ActionRequestWrapper.java
@@ -0,0 +1,80 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.portlet;

+

+import javax.portlet.ActionRequest;

+

+public class ActionRequestWrapper extends PortletRequestWrapper

+    implements ActionRequest {

+

+    /**

+     * Creates a ServletRequest adaptor wrapping the given request object.

+     * @throws java.lang.IllegalArgumentException

+     *          if the request is null.

+     */

+    public ActionRequestWrapper(ActionRequest actionRequest) {

+        super(actionRequest);

+

+        if (actionRequest == null) {

+            throw new IllegalArgumentException("Request cannot be null");

+        }

+    }

+

+    // javax.portlet.ActionRequest implementation -------------------------------------------------    

+    public java.io.InputStream getPortletInputStream()

+        throws java.io.IOException {

+        return this.getActionRequest().getPortletInputStream();

+    }

+

+    public void setCharacterEncoding(String enc)

+        throws java.io.UnsupportedEncodingException {

+        this.getActionRequest().setCharacterEncoding(enc);

+    }

+

+    public java.io.BufferedReader getReader()

+        throws java.io.UnsupportedEncodingException, java.io.IOException {

+        return this.getActionRequest().getReader();

+    }

+

+    public java.lang.String getCharacterEncoding() {

+        return this.getActionRequest().getCharacterEncoding();

+    }

+

+    public java.lang.String getContentType() {

+        return this.getActionRequest().getContentType();

+    }

+

+    public int getContentLength() {

+        return this.getActionRequest().getContentLength();

+    }

+    

+    // --------------------------------------------------------------------------------------------

+    

+    // additional methods -------------------------------------------------------------------------

+    /**

+     * Return the wrapped ServletRequest object.

+     */

+    public ActionRequest getActionRequest() {

+        return (ActionRequest) getPortletRequest();

+    }

+

+    // --------------------------------------------------------------------------------------------

+}

+

diff --git a/src/java/org/apache/pluto/portlet/ActionResponseWrapper.java b/src/java/org/apache/pluto/portlet/ActionResponseWrapper.java
new file mode 100644
index 0000000..df465b6
--- /dev/null
+++ b/src/java/org/apache/pluto/portlet/ActionResponseWrapper.java
@@ -0,0 +1,85 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.portlet;

+

+import java.util.Map;

+

+import javax.portlet.ActionResponse;

+import javax.portlet.PortletMode;

+import javax.portlet.PortletModeException;

+import javax.portlet.WindowState;

+import javax.portlet.WindowStateException;

+

+public class ActionResponseWrapper extends PortletResponseWrapper

+    implements ActionResponse {

+

+    /**

+     * Creates a ServletResponse adaptor wrapping the given response object.

+     * @throws java.lang.IllegalArgumentException

+     *          if the response is null.

+     */

+    public ActionResponseWrapper(ActionResponse actionResponse) {

+        super(actionResponse);

+

+        if (actionResponse == null) {

+            throw new IllegalArgumentException("Response cannot be null");

+        }

+    }

+

+    // javax.portlet.ActionResponse implementation ------------------------------------------------

+    public void setWindowState(WindowState windowState)

+        throws WindowStateException {

+        this.getActionResponse().setWindowState(windowState);

+    }

+

+    public void setPortletMode(PortletMode portletMode)

+        throws PortletModeException {

+        this.getActionResponse().setPortletMode(portletMode);

+    }

+

+    public void sendRedirect(String location) throws java.io.IOException {

+        this.getActionResponse().sendRedirect(location);

+    }

+

+    public void setRenderParameters(Map parameters) {

+        this.getActionResponse().setRenderParameters(parameters);

+    }

+

+    public void setRenderParameter(String key, String value) {

+        this.getActionResponse().setRenderParameter(key, value);

+    }

+

+    public void setRenderParameter(String key, String[] values) {

+        this.getActionResponse().setRenderParameter(key, values);

+    }

+

+    // --------------------------------------------------------------------------------------------

+

+    // additional methods -------------------------------------------------------------------------

+    /**

+     * Return the wrapped ServletResponse object.

+     */

+    public ActionResponse getActionResponse() {

+        return (ActionResponse) getPortletResponse();

+    }

+

+    // --------------------------------------------------------------------------------------------

+}

+

diff --git a/src/java/org/apache/pluto/portlet/PortletRequestWrapper.java b/src/java/org/apache/pluto/portlet/PortletRequestWrapper.java
new file mode 100644
index 0000000..8dfd1e9
--- /dev/null
+++ b/src/java/org/apache/pluto/portlet/PortletRequestWrapper.java
@@ -0,0 +1,208 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.portlet;

+

+import java.util.Enumeration;

+

+import javax.portlet.PortalContext;

+import javax.portlet.PortletMode;

+import javax.portlet.PortletPreferences;

+import javax.portlet.PortletRequest;

+import javax.portlet.PortletSession;

+import javax.portlet.WindowState;

+

+public class PortletRequestWrapper

+    extends javax.servlet.http.HttpServletRequestWrapper

+    implements PortletRequest {

+

+    /**

+     * Creates a ServletRequest adaptor wrapping the given request object.

+     * @throws java.lang.IllegalArgumentException

+     *          if the request is null.

+     */

+    public PortletRequestWrapper(PortletRequest portletRequest) {

+        super((javax.servlet.http.HttpServletRequest) portletRequest);

+

+        if (portletRequest == null) {

+            throw new IllegalArgumentException("Request cannot be null");

+        }

+    }

+

+    // javax.portlet.PortletRequest implementation -------------------------------------------------

+    public boolean isWindowStateAllowed(WindowState state) {

+        return this.getPortletRequest().isWindowStateAllowed(state);

+    }

+

+    public boolean isPortletModeAllowed(PortletMode mode) {

+        return this.getPortletRequest().isPortletModeAllowed(mode);

+    }

+

+    public PortletMode getPortletMode() {

+        return this.getPortletRequest().getPortletMode();

+    }

+

+    public WindowState getWindowState() {

+        return this.getPortletRequest().getWindowState();

+    }

+

+    public PortletPreferences getPreferences() {

+        return this.getPortletRequest().getPreferences();

+    }

+

+    public PortletSession getPortletSession() {

+        return this.getPortletRequest().getPortletSession();

+    }

+

+    public PortletSession getPortletSession(boolean create) {

+        return this.getPortletRequest().getPortletSession(create);

+    }

+

+    public String getProperty(String name) {

+        return this.getPortletRequest().getProperty(name);

+    }

+

+    public Enumeration getProperties(String name) {

+        return this.getPortletRequest().getProperties(name);

+    }

+

+    public Enumeration getPropertyNames() {

+        return this.getPortletRequest().getPropertyNames();

+    }

+

+    public PortalContext getPortalContext() {

+        return this.getPortletRequest().getPortalContext();

+    }

+

+    public java.lang.String getAuthType() {

+        return this.getPortletRequest().getAuthType();

+    }

+

+    public String getContextPath() {

+        return this.getPortletRequest().getContextPath();

+    }

+

+    public java.lang.String getRemoteUser() {

+        return this.getPortletRequest().getRemoteUser();

+    }

+

+    public java.security.Principal getUserPrincipal() {

+        return this.getPortletRequest().getUserPrincipal();

+    }

+

+    public boolean isUserInRole(java.lang.String role) {

+        return this.getPortletRequest().isUserInRole(role);

+    }

+

+    public Object getAttribute(String name) {

+        return this.getPortletRequest().getAttribute(name);

+    }

+

+    public java.util.Enumeration getAttributeNames() {

+        return this.getPortletRequest().getAttributeNames();

+    }

+

+    public String getParameter(String name) {

+        return this.getPortletRequest().getParameter(name);

+    }

+

+    public java.util.Enumeration getParameterNames() {

+        return this.getPortletRequest().getParameterNames();

+    }

+

+    public String[] getParameterValues(String name) {

+        return this.getPortletRequest().getParameterValues(name);

+    }

+

+    public java.util.Map getParameterMap() {

+        return this.getPortletRequest().getParameterMap();

+    }

+

+    public boolean isSecure() {

+        return this.getPortletRequest().isSecure();

+    }

+

+    public void setAttribute(String name, Object o) {

+        this.getPortletRequest().setAttribute(name, o);

+    }

+

+    public void removeAttribute(String name) {

+        this.getPortletRequest().removeAttribute(name);

+    }

+

+    public String getRequestedSessionId() {

+        return this.getPortletRequest().getRequestedSessionId();

+    }

+

+    public boolean isRequestedSessionIdValid() {

+        return this.getPortletRequest().isRequestedSessionIdValid();

+    }

+

+    public String getResponseContentType() {

+        return this.getPortletRequest().getResponseContentType();

+    }

+

+    public java.util.Enumeration getResponseContentTypes() {

+        return this.getPortletRequest().getResponseContentTypes();

+    }

+

+    public java.util.Locale getLocale() {

+        return this.getPortletRequest().getLocale();

+    }

+

+    public java.util.Enumeration getLocales() {

+        return this.getPortletRequest().getLocales();

+    }

+

+    public String getScheme() {

+        return this.getPortletRequest().getScheme();

+    }

+

+    public String getServerName() {

+        return this.getPortletRequest().getServerName();

+    }

+

+    public int getServerPort() {

+        return this.getPortletRequest().getServerPort();

+    }

+

+    // --------------------------------------------------------------------------------------------

+    

+    // additional methods -------------------------------------------------------------------------

+    /**

+     * Return the wrapped ServletRequest object.

+     */

+    public PortletRequest getPortletRequest() {

+        return (PortletRequest) super.getRequest();

+    }

+

+    /**

+     * Sets the request being wrapped.

+     * @throws java.lang.IllegalArgumentException

+     *          if the request is null.

+     */

+    public void setRequest(PortletRequest request) {

+        if (request == null) {

+            throw new IllegalArgumentException("Request cannot be null");

+        }

+        setRequest((javax.servlet.http.HttpServletRequest) request);

+    }

+    // --------------------------------------------------------------------------------------------

+}

+

diff --git a/src/java/org/apache/pluto/portlet/PortletResponseWrapper.java b/src/java/org/apache/pluto/portlet/PortletResponseWrapper.java
new file mode 100644
index 0000000..a6a647d
--- /dev/null
+++ b/src/java/org/apache/pluto/portlet/PortletResponseWrapper.java
@@ -0,0 +1,76 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.portlet;

+

+import javax.portlet.PortletResponse;

+

+public class PortletResponseWrapper

+    extends javax.servlet.http.HttpServletResponseWrapper

+    implements PortletResponse {

+

+    /**

+     * Creates a ServletResponse adaptor wrapping the given response object.

+     * @throws java.lang.IllegalArgumentException

+     *          if the response is null.

+     */

+    public PortletResponseWrapper(PortletResponse portletResponse) {

+        super((javax.servlet.http.HttpServletResponse) portletResponse);

+

+        if (portletResponse == null) {

+            throw new IllegalArgumentException("Response cannot be null");

+        }

+    }

+

+    // javax.portlet.PortletResponse implementation ------------------------------------------------

+    public void addProperty(String key, String value) {

+        this.getPortletResponse().addProperty(key, value);

+    }

+

+    public void setProperty(String key, String value) {

+        this.getPortletResponse().setProperty(key, value);

+    }

+

+    public String encodeURL(String path) {

+        return this.getPortletResponse().encodeURL(path);

+    }

+    // --------------------------------------------------------------------------------------------

+

+    // additional methods -------------------------------------------------------------------------

+    /**

+     * Return the wrapped ServletResponse object.

+     */

+    public PortletResponse getPortletResponse() {

+        return (PortletResponse) super.getResponse();

+    }

+

+    /**

+     * Sets the response being wrapped.

+     * @throws java.lang.IllegalArgumentException

+     *          if the response is null.

+     */

+    public void setResponse(PortletResponse response) {

+        if (response == null) {

+            throw new IllegalArgumentException("Response cannot be null");

+        }

+        setResponse((javax.servlet.http.HttpServletResponse) response);

+    }

+    // --------------------------------------------------------------------------------------------

+}

+

diff --git a/src/java/org/apache/pluto/portlet/RenderRequestWrapper.java b/src/java/org/apache/pluto/portlet/RenderRequestWrapper.java
new file mode 100644
index 0000000..f1195ad
--- /dev/null
+++ b/src/java/org/apache/pluto/portlet/RenderRequestWrapper.java
@@ -0,0 +1,54 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.portlet;

+

+import javax.portlet.RenderRequest;

+

+public class RenderRequestWrapper extends PortletRequestWrapper

+    implements RenderRequest {

+

+    /**

+     * Creates a ServletRequest adaptor wrapping the given request object.

+     * @throws java.lang.IllegalArgumentException

+     *          if the request is null.

+     */

+    public RenderRequestWrapper(RenderRequest renderRequest) {

+        super(renderRequest);

+

+        if (renderRequest == null) {

+            throw new IllegalArgumentException("Request cannot be null");

+        }

+    }

+

+    // javax.portlet.RenderRequest implementation -------------------------------------------------

+

+    // --------------------------------------------------------------------------------------------

+    

+    // additional methods -------------------------------------------------------------------------

+    /**

+     * Return the wrapped ServletRequest object.

+     */

+    public RenderRequest getRenderRequest() {

+        return (RenderRequest) getPortletRequest();

+    }

+

+    // --------------------------------------------------------------------------------------------

+}

+

diff --git a/src/java/org/apache/pluto/portlet/RenderResponseWrapper.java b/src/java/org/apache/pluto/portlet/RenderResponseWrapper.java
new file mode 100644
index 0000000..835796d
--- /dev/null
+++ b/src/java/org/apache/pluto/portlet/RenderResponseWrapper.java
@@ -0,0 +1,119 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.portlet;

+

+import java.io.IOException;

+import java.io.OutputStream;

+

+import javax.portlet.PortletURL;

+import javax.portlet.RenderResponse;

+

+public class RenderResponseWrapper extends PortletResponseWrapper

+    implements RenderResponse {

+    /**

+     * Creates a ServletResponse adaptor wrapping the given response object.

+     * @throws java.lang.IllegalArgumentException

+     *          if the response is null.

+     */

+    public RenderResponseWrapper(RenderResponse renderResponse) {

+        super(renderResponse);

+

+        if (renderResponse == null) {

+            throw new IllegalArgumentException("Response cannot be null");

+        }

+    }

+

+    // javax.portlet.RenderResponse implementation ------------------------------------------------

+    public String getContentType() {

+        return this.getRenderResponse().getContentType();

+    }

+

+    public PortletURL createRenderURL() {

+        return this.getRenderResponse().createRenderURL();

+    }

+

+    public PortletURL createActionURL() {

+        return this.getRenderResponse().createActionURL();

+    }

+

+    public String getNamespace() {

+        return this.getRenderResponse().getNamespace();

+    }

+

+    public void setTitle(String title) {

+        this.getRenderResponse().setTitle(title);

+    }

+

+    public void setContentType(String type) {

+        this.getRenderResponse().setContentType(type);

+    }

+

+    public String getCharacterEncoding() {

+        return this.getRenderResponse().getCharacterEncoding();

+    }

+

+    public java.io.PrintWriter getWriter() throws java.io.IOException {

+        return this.getRenderResponse().getWriter();

+    }

+

+    public java.util.Locale getLocale() {

+        return this.getRenderResponse().getLocale();

+    }

+

+    public void setBufferSize(int size) {

+        this.getRenderResponse().setBufferSize(size);

+    }

+

+    public int getBufferSize() {

+        return this.getRenderResponse().getBufferSize();

+    }

+

+    public void flushBuffer() throws java.io.IOException {

+        this.getRenderResponse().flushBuffer();

+    }

+

+    public void resetBuffer() {

+        this.getRenderResponse().resetBuffer();

+    }

+

+    public boolean isCommitted() {

+        return this.getRenderResponse().isCommitted();

+    }

+

+    public void reset() {

+        this.getRenderResponse().reset();

+    }

+

+    public OutputStream getPortletOutputStream() throws IOException {

+        return this.getRenderResponse().getPortletOutputStream();

+    }

+    // --------------------------------------------------------------------------------------------

+

+    // additional methods -------------------------------------------------------------------------

+    /**

+     * Return the wrapped ServletResponse object.

+     */

+    public RenderResponse getRenderResponse() {

+        return (RenderResponse) getPortletResponse();

+    }

+    // --------------------------------------------------------------------------------------------

+

+}

+

diff --git a/src/java/org/apache/pluto/services/ContainerService.java b/src/java/org/apache/pluto/services/ContainerService.java
new file mode 100644
index 0000000..1f82816
--- /dev/null
+++ b/src/java/org/apache/pluto/services/ContainerService.java
@@ -0,0 +1,25 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+package org.apache.pluto.services;

+

+/**

+ * Defines a service and needs to be implemented by all

+ * PortletContainerServices

+ */

+public interface ContainerService {

+

+

+}

diff --git a/src/java/org/apache/pluto/services/DynamicInformationProvider.java b/src/java/org/apache/pluto/services/DynamicInformationProvider.java
new file mode 100644
index 0000000..f0aa031
--- /dev/null
+++ b/src/java/org/apache/pluto/services/DynamicInformationProvider.java
@@ -0,0 +1,64 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.services;

+

+import org.apache.pluto.PortletWindow;

+

+/**

+ * Provide information from the portal to portlet container that are request

+ * dependend.

+ */

+public interface DynamicInformationProvider {

+

+

+    /**

+     * Returns the content type the portlet should use in its response The

+     * content type only includes the content type, not the character set.

+     * @return the content type to use for the response

+     */

+    public String getResponseContentType();

+

+    /**

+     * Gets a list of mime types which the portal accepts for the response. This

+     * list is ordered with the most preferable types listed first.

+     * <p/>

+     * The content type only includes the content type, not the character set.

+     * @return an java.util.Iterator of content types for the response

+     */

+    public java.util.Iterator getResponseContentTypes();

+

+    /**

+     * Returns an URL pointing to the given portlet window

+     * @param portletWindow the portlet Window

+     * @return the URL to the given portlet

+     */

+    public PortletURLProvider getPortletURLProvider(

+        PortletWindow portletWindow);

+

+    /**

+     * Returns the ResourceURLProvider to create URLs pointing to a resource in

+     * a web application.

+     * @param portletWindow the portlet Window

+     * @return the URL to a resource

+     */

+    public ResourceURLProvider getResourceURLProvider(

+        PortletWindow portletWindow);

+

+}

diff --git a/src/java/org/apache/pluto/services/PortalCallbackProvider.java b/src/java/org/apache/pluto/services/PortalCallbackProvider.java
new file mode 100644
index 0000000..835ac37
--- /dev/null
+++ b/src/java/org/apache/pluto/services/PortalCallbackProvider.java
@@ -0,0 +1,33 @@
+/*

+ * Copyright 2004 The Apache Software Foundation.

+ *

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ *

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+

+package org.apache.pluto.services;

+

+import javax.servlet.http.HttpServletRequest;

+

+import org.apache.pluto.PortletWindow;

+

+/**

+ * @author <a href="ddewolf@apache.org">David H. DeWolf</a>

+ * @version 1.0

+ * @since Sep 21, 2004

+ */

+public interface PortalCallbackProvider {

+

+    public void setTitle(HttpServletRequest request,

+                         PortletWindow window,

+                         String title);

+}

diff --git a/src/java/org/apache/pluto/services/PortalContextProvider.java b/src/java/org/apache/pluto/services/PortalContextProvider.java
new file mode 100644
index 0000000..bcf749d
--- /dev/null
+++ b/src/java/org/apache/pluto/services/PortalContextProvider.java
@@ -0,0 +1,83 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.services;

+

+

+/**

+ * Provide information about the calling portal.

+ */

+public interface PortalContextProvider {

+

+    /**

+     * Returns the portal property with the given name, or a <code>null</code>

+     * if there is no property by that name.

+     * @param name property name

+     * @return portal property with key <code>name</code>

+     * @exception	java.lang.IllegalArgumentException if name is

+     * <code>null</code>.

+     */

+

+    public java.lang.String getProperty(java.lang.String name);

+

+

+    /**

+     * Returns all portal property names as strings, or an empty

+     * <code>Collection</code> if there are no property names.

+     * @return portal property names

+     */

+    public java.util.Collection getPropertyNames();

+

+

+    /**

+     * Returns the portlet modes that the portal supports as

+     * <code>javax.portlet.PortletMode</code> objects.

+     * <p/>

+     * The portlet modes must at least include the standard portlet modes

+     * <code>EDIT, HELP, VIEW</code>.

+     * @return list of supported portlet modes

+     */

+

+    public java.util.Collection getSupportedPortletModes();

+

+

+    /**

+     * Returns the window states that the portal supports as

+     * <code>javax.portlet.WindowState</code> objects.

+     * <p/>

+     * The window states must at least include the standard window states <code>

+     * MINIMIZED, NORMAL, MAXIMIZED</code>.

+     * @return list of supported window states

+     */

+

+    public java.util.Collection getSupportedWindowStates();

+

+

+    /**

+     * Returns information about the portal like vendor, version, etc.

+     * <p/>

+     * The returned string starts with <br> <I>servername/versionnumber</I>

+     * Other optional information follow the primary string in parentheses.

+     * @return a <CODE>String</CODE> containing at least the portal name and

+     *         version number

+     */

+

+    public java.lang.String getPortalInfo();

+

+}

diff --git a/src/java/org/apache/pluto/services/PortletContainerServices.java b/src/java/org/apache/pluto/services/PortletContainerServices.java
new file mode 100644
index 0000000..a9f3635
--- /dev/null
+++ b/src/java/org/apache/pluto/services/PortletContainerServices.java
@@ -0,0 +1,43 @@
+package org.apache.pluto.services;

+

+import javax.portlet.PortalContext;

+import javax.servlet.http.HttpServletRequest;

+

+/**

+ * Defines the services necessary for integration between the Pluto Container

+ * and a Portal.

+ * @author <a href="ddewolf@apache.org">David H. DeWolf</a>

+ */

+public interface PortletContainerServices {

+

+    /**

+     * Provider used to retrieve request-time services.

+     * @param req

+     * @return a DynamicInformationProvider implementation.

+     */

+    DynamicInformationProvider getDynamicInformationProvider(

+        HttpServletRequest req);

+

+    /**

+     * Return the PortletPreferencesFactory implementation.

+     * @return a PortletPreferencesFactory implementation.

+     */

+    PortletPreferencesFactory getPortletPreferencesFactory();

+

+    /**

+     * Retrieve the PortalContext associated with this group of container

+     * services.

+     * @return a PortalContext implementation.

+     */

+    PortalContext getPortalContext();

+

+    /**

+     * @return a PortalCallbackProvider implementation.

+     */

+    PortalCallbackProvider getPortalCallbackProvider();

+

+    /**

+     * @return a PropertyManagerService implementation.

+     */

+    PropertyManagerService getPropertyManagerService();

+}

diff --git a/src/java/org/apache/pluto/services/PortletPreferencesFactory.java b/src/java/org/apache/pluto/services/PortletPreferencesFactory.java
new file mode 100644
index 0000000..251dd93
--- /dev/null
+++ b/src/java/org/apache/pluto/services/PortletPreferencesFactory.java
@@ -0,0 +1,40 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.services;

+

+import java.io.IOException;

+

+import javax.portlet.PortletRequest;

+

+import org.apache.pluto.PortletWindow;

+import org.apache.pluto.core.PortletPreference;

+

+public interface PortletPreferencesFactory {

+

+    PortletPreference[] getStoredPreferences(PortletWindow window,

+                                             PortletRequest req);

+

+    PortletPreference getStoredPreference(PortletWindow window,

+                                          PortletRequest req,

+                                          String preferenceName);

+

+    void store(PortletPreference[] preferences) throws IOException;

+

+}

diff --git a/src/java/org/apache/pluto/services/PortletURLProvider.java b/src/java/org/apache/pluto/services/PortletURLProvider.java
new file mode 100644
index 0000000..b7389b3
--- /dev/null
+++ b/src/java/org/apache/pluto/services/PortletURLProvider.java
@@ -0,0 +1,81 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.services;

+

+import java.util.Map;

+

+import javax.portlet.PortletMode;

+import javax.portlet.WindowState;

+

+/**

+ * Defines the interface used by the portlet container to create Portal URLs.

+ * This provider must be implemented by the Portal and provided via the

+ * container services upon initialization of the container.

+ */

+public interface PortletURLProvider {

+

+

+    /**

+     * Sets the new portlet mode at the URL. If no mode is set at the URL the

+     * currently active mode is used.

+     * @param mode the new portlet mode

+     */

+    public void setPortletMode(PortletMode mode);

+

+    /**

+     * Sets the new window state at the URL. If no state is set at the URL the

+     * currently active state is used.

+     * @param state the new window state

+     */

+    public void setWindowState(WindowState state);

+

+    /**

+     * Specifies whether or not this request should be considered an action

+     * request. If the value specified is false, a render request will be

+     * assumed.

+     */

+    public void setAction(boolean action);

+

+    /**

+     * By calling this method the URL is defined as a secure URL.

+     */

+    public void setSecure();

+

+    /**

+     * Removes all pre-existing parameters in this URL

+     */

+    public void clearParameters();

+

+    /**

+     * Sets the given parameters as parameters into the URL, Removes all

+     * previously set parameters.

+     * @param parameters a map containing the name [java.lang.String] and value

+     *                   [java.lang.String[]] of the parameters.

+     */

+    public void setParameters(Map parameters);

+

+

+    /**

+     * Returns the URL in string format. This method should only be called

+     * once.

+     * @return the URL

+     */

+    public String toString();

+}

diff --git a/src/java/org/apache/pluto/services/PropertyManagerService.java b/src/java/org/apache/pluto/services/PropertyManagerService.java
new file mode 100644
index 0000000..147a532
--- /dev/null
+++ b/src/java/org/apache/pluto/services/PropertyManagerService.java
@@ -0,0 +1,71 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+

+package org.apache.pluto.services;

+

+import java.util.Map;

+

+import javax.servlet.http.HttpServletRequest;

+import javax.servlet.http.HttpServletResponse;

+

+import org.apache.pluto.PortletWindow;

+

+/**

+ * The <code>PropertyManagerService</code> interface is a container service

+ * providing the portlet container with external defined properties. This

+ * interface allows to associate properties with the portlet request and portlet

+ * response. <br> This service represents an abstract layer to make the property

+ * management independent of the portlet container and to allow diverse special

+ * implementations.

+ * <p/>

+ * <p>This SPI interface can be implemented by the portal.</p>

+ */

+public interface PropertyManagerService extends ContainerService {

+

+    /**

+     * Sets the given property map defined by the portlet window in its

+     * response. <br> The purpose of this method is to provide the portal

+     * framework with a new map of properties set by the portlet. The map can be

+     * empty, but not NULL <br> This method can be called multiple times during

+     * one request by the portlet container

+     * @param window     the portlet window of this property

+     * @param request    the servlet request

+     * @param response   the servlet response

+     * @param properties the String/String array map containing the properties

+     *                   to be set.

+     */

+    public void setResponseProperties(PortletWindow window,

+                                      HttpServletRequest request,

+                                      HttpServletResponse response,

+                                      Map properties);

+

+    /**

+     * Returns all properties for the given portlet window defined in the portal

+     * as String/String array map. They will be made available to the portlet

+     * through the portlet request. <br> The purpose of this method is to allow

+     * the portal framework to create a map of properties and make it available

+     * to the portlet container. <br> This method can be called multiple times

+     * during one request by the portlet container <br> The return value cannot

+     * be null.

+     * @param window  the portlet window of this property

+     * @param request the servlet request

+     * @return		a <code>Map</code> containing all properties. If there are no

+     * properties of that name returns an empty <code>Map</code>.

+     */

+    public Map getRequestProperties(PortletWindow window,

+                                    HttpServletRequest request);

+

+}

diff --git a/src/java/org/apache/pluto/services/ResourceURLProvider.java b/src/java/org/apache/pluto/services/ResourceURLProvider.java
new file mode 100644
index 0000000..bb12149
--- /dev/null
+++ b/src/java/org/apache/pluto/services/ResourceURLProvider.java
@@ -0,0 +1,42 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+

+package org.apache.pluto.services;

+

+public interface ResourceURLProvider {

+

+

+    /**

+     * Sets the absolute URL to be returned by the provider. E.g.

+     * http://host/wps/portal/hello.gif

+     * @param path the new absolute url

+     */

+    public void setAbsoluteURL(String path);

+

+    /**

+     * Sets a full path URI including the context root. E.g.

+     * /wps/portal/hello.gif

+     * @param path the new absolute url

+     */

+    public void setFullPath(String path);

+

+    /**

+     * Returns a url to a resource as absolute URL starting with protocol so

+     * that it can be accessed by a browser.

+     * @return the URL as string

+     */

+    public String toString();

+}

diff --git a/src/java/org/apache/pluto/tags/ActionURLTag.java b/src/java/org/apache/pluto/tags/ActionURLTag.java
new file mode 100644
index 0000000..02562a0
--- /dev/null
+++ b/src/java/org/apache/pluto/tags/ActionURLTag.java
@@ -0,0 +1,85 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+/*

+ * Created on Feb 21, 2003

+ *

+ * To change this generated comment go to 

+ * Window>Preferences>Java>Code Generation>Code Template

+ */

+package org.apache.pluto.tags;

+

+import javax.portlet.PortletMode;

+import javax.portlet.PortletModeException;

+import javax.portlet.PortletSecurityException;

+import javax.portlet.RenderResponse;

+import javax.portlet.WindowState;

+import javax.portlet.WindowStateException;

+import javax.servlet.jsp.JspException;

+import javax.servlet.jsp.PageContext;

+

+/**

+ * Supporting class for the <CODE>actionURL</CODE> tag. Creates a url that

+ * points to the current Portlet and triggers an action request with the

+ * supplied parameters.

+ */

+public class ActionURLTag extends BasicURLTag {

+

+    /* (non-Javadoc)

+     * @see javax.servlet.jsp.tagext.Tag#doStartTag()

+     */

+    public int doStartTag() throws JspException {

+        if (var != null) {

+            pageContext.removeAttribute(var, PageContext.PAGE_SCOPE);

+        }

+        RenderResponse renderResponse = (RenderResponse) pageContext.getRequest()

+            .getAttribute("javax.portlet.response");

+

+        if (renderResponse != null) {

+            setUrl(renderResponse.createActionURL());

+            if (portletMode != null) {

+                try {

+                    url.setPortletMode(

+                        (PortletMode) TEI.portletModes.get(

+                            portletMode.toUpperCase()));

+                } catch (PortletModeException e) {

+                    throw new JspException(e);

+                }

+            }

+            if (windowState != null) {

+                try {

+                    url.setWindowState(

+                        (WindowState) TEI.definedWindowStates.get(

+                            windowState.toUpperCase()));

+                } catch (WindowStateException e) {

+                    throw new JspException(e);

+                }

+            }

+            if (secure != null) {

+                try {

+                    url.setSecure(getSecureBoolean());

+                } catch (PortletSecurityException e) {

+                    throw new JspException(e);

+                }

+            }

+        }

+        return EVAL_PAGE;

+    }

+}

+

diff --git a/src/java/org/apache/pluto/tags/BasicURLTag.java b/src/java/org/apache/pluto/tags/BasicURLTag.java
new file mode 100644
index 0000000..e1aa7e5
--- /dev/null
+++ b/src/java/org/apache/pluto/tags/BasicURLTag.java
@@ -0,0 +1,228 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.tags;

+

+import java.io.IOException;

+import java.lang.reflect.Field;

+import java.util.Hashtable;

+

+import javax.portlet.PortletMode;

+import javax.portlet.PortletURL;

+import javax.portlet.WindowState;

+import javax.servlet.jsp.JspException;

+import javax.servlet.jsp.JspWriter;

+import javax.servlet.jsp.PageContext;

+import javax.servlet.jsp.tagext.TagData;

+import javax.servlet.jsp.tagext.TagExtraInfo;

+import javax.servlet.jsp.tagext.TagSupport;

+import javax.servlet.jsp.tagext.VariableInfo;

+

+/**

+ * Supporting class for the <CODE>actionURL</CODE> and <CODE>renderURL</CODE>

+ * tag. Creates a url that points to the current Portlet and triggers an action

+ * request with the supplied parameters.

+ */

+public abstract class BasicURLTag extends TagSupport {

+

+    public static class TEI extends TagExtraInfo {

+        public final static Hashtable definedWindowStates = getDefinedWindowStates();

+        public final static Hashtable portletModes = getDefinedPortletModes();

+

+        /**

+         * Provides a list of all static PortletMode available in the

+         * specifications by using introspection

+         * @return Hashtable

+         */

+        private static Hashtable getDefinedPortletModes() {

+            Hashtable portletModes = new Hashtable();

+            Field[] f = PortletMode.class.getDeclaredFields();

+

+            for (int i = 0; i < f.length; i++) {

+                if (f[i].getType().isAssignableFrom(

+                    javax.portlet.PortletMode.class)) {

+                    try {

+                        portletModes.put(

+                            f[i].get(f[i]).toString().toUpperCase(),

+                            f[i].get(f[i]));

+                    } catch (IllegalAccessException e) {

+                    }

+                }

+            }

+

+            return portletModes;

+        }

+

+        /**

+         * Provides a list of all static WindowsStates available in the

+         * specifications by using introspection

+         * @return Hashtable

+         */

+        private static Hashtable getDefinedWindowStates() {

+            Hashtable definedWindowStates = new Hashtable();

+            Field[] f = WindowState.class.getDeclaredFields();

+

+            for (int i = 0; i < f.length; i++) {

+                if (f[i].getType().isAssignableFrom(

+                    javax.portlet.WindowState.class)) {

+                    try {

+                        definedWindowStates.put(

+                            f[i].get(f[i]).toString().toUpperCase(),

+                            f[i].get(f[i]));

+                    } catch (IllegalAccessException e) {

+

+                    }

+                }

+            }

+            return definedWindowStates;

+        }

+

+        public VariableInfo[] getVariableInfo(TagData tagData) {

+            VariableInfo vi[] = null;

+            String var = tagData.getAttributeString("var");

+            if (var != null) {

+                vi = new VariableInfo[1];

+                vi[0] =

+                new VariableInfo(var, "java.lang.String", true,

+                                 VariableInfo.AT_BEGIN);

+            }

+            return vi;

+        }

+

+    }

+

+    protected String portletMode;

+    protected String secure;

+    protected Boolean secureBoolean;

+    protected String windowState;

+    protected PortletURL url;

+    protected String var;

+

+    /**

+     * Processes the <CODE>actionURL</CODE> or <CODE>renderURL</CODE> tag.

+     * @return int

+     */

+    public abstract int doStartTag() throws JspException;

+

+    /**

+     * @return int

+     */

+    public int doEndTag() throws JspException {

+        if (var == null) {

+            try {

+                JspWriter writer = pageContext.getOut();

+                writer.print(url);

+                writer.flush();

+            } catch (IOException ioe) {

+                throw new JspException(

+                    "actionURL/renderURL Tag Exception: cannot write to the output writer.");

+            }

+        } else {

+            pageContext.setAttribute(var, url.toString(),

+                                     PageContext.PAGE_SCOPE);

+        }

+        return EVAL_PAGE;

+    }

+

+    /**

+     * Returns the portletMode.

+     * @return String

+     */

+    public String getPortletMode() {

+        return portletMode;

+    }

+

+    /**

+     * @return secure as String

+     */

+    public String getSecure() {

+        return secure;

+    }

+

+    /**

+     * @return secure as Boolean

+     */

+    public boolean getSecureBoolean() {

+        return this.secureBoolean.booleanValue();

+    }

+

+    /**

+     * Returns the windowState.

+     * @return String

+     */

+    public String getWindowState() {

+        return windowState;

+    }

+

+    /**

+     * @return PortletURL

+     */

+    public PortletURL getUrl() {

+        return url;

+    }

+

+    /**

+     * Returns the var.

+     * @return String

+     */

+    public String getVar() {

+        return var;

+    }

+

+    /**

+     * Sets the portletMode.

+     * @param portletMode The portletMode to set

+     */

+    public void setPortletMode(String portletMode) {

+        this.portletMode = portletMode;

+    }

+

+    /**

+     * Sets secure to boolean value of the string

+     * @param secure

+     */

+    public void setSecure(String secure) {

+        this.secure = secure;

+        this.secureBoolean = new Boolean(secure);

+    }

+

+    /**

+     * Sets the windowState.

+     * @param windowState The windowState to set

+     */

+    public void setWindowState(String windowState) {

+        this.windowState = windowState;

+    }

+

+    /**

+     * Sets the url.

+     * @param url The url to set

+     */

+    public void setUrl(PortletURL url) {

+        this.url = url;

+    }

+

+    /**

+     * Sets the var.

+     * @param var The var to set

+     */

+    public void setVar(String var) {

+        this.var = var;

+    }

+}

diff --git a/src/java/org/apache/pluto/tags/DefineObjectsTag.java b/src/java/org/apache/pluto/tags/DefineObjectsTag.java
new file mode 100644
index 0000000..f6fd6f4
--- /dev/null
+++ b/src/java/org/apache/pluto/tags/DefineObjectsTag.java
@@ -0,0 +1,100 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.tags;

+

+import javax.portlet.PortletConfig;

+import javax.portlet.PortletRequest;

+import javax.portlet.RenderResponse;

+import javax.servlet.jsp.JspException;

+import javax.servlet.jsp.PageContext;

+import javax.servlet.jsp.tagext.TagData;

+import javax.servlet.jsp.tagext.TagExtraInfo;

+import javax.servlet.jsp.tagext.TagSupport;

+import javax.servlet.jsp.tagext.VariableInfo;

+

+import org.apache.pluto.Constants;

+

+

+/**

+ * Supporting class for the <CODE>defineObjects</CODE> tag. Creates the

+ * following variables to be used in the JSP: <UL> <LI><CODE>renderRequest</CODE>

+ * <LI><CODE>renderResponse</CODE> <LI><CODE>portletConfig</CODE> </UL>

+ * @see javax.portlet.PortletRequest

+ * @see javax.portlet.RenderResponse

+ * @see javax.portlet.PortletConfig

+ */

+public class DefineObjectsTag extends TagSupport {

+

+    /**

+     * Processes the <CODE>defineObjects</CODE> tag.

+     * @return <CODE>SKIP_BODY</CODE>

+     */

+    public int doStartTag() throws JspException {

+        PortletRequest renderRequest = (PortletRequest) pageContext.getRequest()

+            .getAttribute(Constants.PORTLET_REQUEST);

+        RenderResponse renderResponse = (RenderResponse) pageContext.getRequest()

+            .getAttribute(Constants.PORTLET_RESPONSE);

+        PortletConfig portletConfig = (PortletConfig) pageContext.getRequest()

+            .getAttribute(Constants.PORTLET_CONFIG);

+

+        if (pageContext.getAttribute("renderRequest") == null)   //Set attributes only once

+        {

+            pageContext.setAttribute("renderRequest",

+                                     renderRequest,

+                                     PageContext.PAGE_SCOPE);

+        }

+

+        if (pageContext.getAttribute("renderResponse") == null) {

+            pageContext.setAttribute("renderResponse",

+                                     renderResponse,

+                                     PageContext.PAGE_SCOPE);

+        }

+

+        if (pageContext.getAttribute("portletConfig") == null) {

+            pageContext.setAttribute("portletConfig",

+                                     portletConfig,

+                                     PageContext.PAGE_SCOPE);

+        }

+

+        return SKIP_BODY;

+    }

+

+    public static class TEI extends TagExtraInfo {

+

+        public VariableInfo[] getVariableInfo(TagData tagData) {

+            VariableInfo[] info = new VariableInfo[]{

+                new VariableInfo("renderRequest",

+                                 "javax.portlet.PortletRequest",

+                                 true,

+                                 VariableInfo.AT_BEGIN),

+                new VariableInfo("renderResponse",

+                                 "javax.portlet.RenderResponse",

+                                 true,

+                                 VariableInfo.AT_BEGIN),

+                new VariableInfo("portletConfig",

+                                 "javax.portlet.PortletConfig",

+                                 true,

+                                 VariableInfo.AT_BEGIN)

+            };

+

+            return info;

+        }

+    }

+}

diff --git a/src/java/org/apache/pluto/tags/NamespaceTag.java b/src/java/org/apache/pluto/tags/NamespaceTag.java
new file mode 100644
index 0000000..b84ead9
--- /dev/null
+++ b/src/java/org/apache/pluto/tags/NamespaceTag.java
@@ -0,0 +1,55 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.tags;

+

+import java.io.IOException;

+

+import javax.portlet.RenderResponse;

+import javax.servlet.jsp.JspException;

+import javax.servlet.jsp.JspWriter;

+import javax.servlet.jsp.tagext.TagSupport;

+

+/**

+ * This tag produces a unique value for the current portlet.

+ * <p/>

+ * <p/>

+ * Supporting class for the <CODE>namespace</CODE> tag. writes a unique value

+ * for the current portlet <BR>This tag has no attributes

+ */

+public class NamespaceTag extends TagSupport {

+

+    /* (non-Javadoc)

+     * @see javax.servlet.jsp.tagext.Tag#doStartTag()

+     */

+    public int doStartTag() throws JspException {

+        RenderResponse renderResponse = (RenderResponse) pageContext.getRequest()

+            .getAttribute("javax.portlet.response");

+        String namespace = renderResponse.getNamespace();

+        JspWriter writer = pageContext.getOut();

+        try {

+            writer.print(namespace);

+            writer.flush();

+        } catch (IOException ioe) {

+            throw new JspException(

+                "namespace Tag Exception: cannot write to the output writer.");

+        }

+        return SKIP_BODY;

+    }

+}

diff --git a/src/java/org/apache/pluto/tags/ParamTag.java b/src/java/org/apache/pluto/tags/ParamTag.java
new file mode 100644
index 0000000..c19e8f2
--- /dev/null
+++ b/src/java/org/apache/pluto/tags/ParamTag.java
@@ -0,0 +1,93 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.tags;

+

+import javax.portlet.PortletURL;

+import javax.servlet.jsp.JspException;

+import javax.servlet.jsp.tagext.TagSupport;

+

+

+/**

+ * * Supporting class for the <CODE>param</CODE> tag. * defines a parameter that

+ * can be added to a <CODE>actionURL</CODE> or * a <CODE>renderURL</CODE> *

+ * <BR>The following attributes are mandatory * <UL> * <LI><CODE>name</CODE> *

+ * <LI><CODE>value</CODE> * </UL>

+ */

+public class ParamTag extends TagSupport {

+

+    private String name;

+    private String value;

+

+    /**

+     * Processes the <CODE>param</CODE> tag.

+     * @return <CODE>SKIP_BODY</CODE>

+     */

+    public int doStartTag() throws JspException {

+        BasicURLTag urlTag = (BasicURLTag) findAncestorWithClass(this,

+                                                                 BasicURLTag.class);

+        if (urlTag == null) {

+            throw new JspException(

+                "the 'param' Tag must have actionURL or renderURL as a parent");

+        }

+        PortletURL url = urlTag.getUrl();

+

+        if (getName() != null) {

+            url.setParameter(getName(), getValue());

+        }

+

+        return SKIP_BODY;

+    }

+

+    /**

+     * Returns the name.

+     * @return String

+     */

+    public String getName() {

+        return name;

+    }

+

+    /**

+     * Returns the value.

+     * @return String

+     */

+    public String getValue() {

+        if (value == null) {

+            value = "";

+        }

+        return value;

+    }

+

+    /**

+     * Sets the name.

+     * @param name The name to set

+     */

+    public void setName(String name) {

+        this.name = name;

+    }

+

+    /**

+     * Sets the value.

+     * @param value The value to set

+     */

+    public void setValue(String value) {

+        this.value = value;

+    }

+

+}

diff --git a/src/java/org/apache/pluto/tags/RenderURLTag.java b/src/java/org/apache/pluto/tags/RenderURLTag.java
new file mode 100644
index 0000000..0c8c261
--- /dev/null
+++ b/src/java/org/apache/pluto/tags/RenderURLTag.java
@@ -0,0 +1,86 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+/*

+ * Created on Feb 21, 2003

+ *

+ * To change this generated comment go to 

+ * Window>Preferences>Java>Code Generation>Code Template

+ */

+package org.apache.pluto.tags;

+

+import javax.portlet.PortletMode;

+import javax.portlet.PortletModeException;

+import javax.portlet.PortletSecurityException;

+import javax.portlet.RenderResponse;

+import javax.portlet.WindowState;

+import javax.portlet.WindowStateException;

+import javax.servlet.jsp.JspException;

+import javax.servlet.jsp.PageContext;

+

+/**

+ * * Supporting class for the <CODE>renderURL</CODE> tag. * Creates a url that

+ * points to the current Portlet and triggers an render request * with the

+ * supplied parameters. *

+ */

+public class RenderURLTag extends BasicURLTag {

+

+

+    /* (non-Javadoc)

+         * @see javax.servlet.jsp.tagext.Tag#doStartTag()

+         */

+    public int doStartTag() throws JspException {

+        if (var != null) {

+            pageContext.removeAttribute(var, PageContext.PAGE_SCOPE);

+        }

+        RenderResponse renderResponse = (RenderResponse) pageContext.getRequest()

+            .getAttribute("javax.portlet.response");

+

+        if (renderResponse != null) {

+            setUrl(renderResponse.createRenderURL());

+            if (portletMode != null) {

+                try {

+                    url.setPortletMode(

+                        (PortletMode) TEI.portletModes.get(

+                            portletMode.toUpperCase()));

+                } catch (PortletModeException e) {

+                    throw new JspException(e);

+                }

+            }

+            if (windowState != null) {

+                try {

+                    url.setWindowState(

+                        (WindowState) TEI.definedWindowStates.get(

+                            windowState.toUpperCase()));

+                } catch (WindowStateException e) {

+                    throw new JspException(e);

+                }

+            }

+            if (secure != null) {

+                try {

+                    url.setSecure(getSecureBoolean());

+                } catch (PortletSecurityException e) {

+                    throw new JspException(e);

+                }

+            }

+        }

+        return EVAL_PAGE;

+    }

+}

+

diff --git a/src/java/org/apache/pluto/util/Enumerator.java b/src/java/org/apache/pluto/util/Enumerator.java
new file mode 100644
index 0000000..762c832
--- /dev/null
+++ b/src/java/org/apache/pluto/util/Enumerator.java
@@ -0,0 +1,89 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.util;

+

+import java.util.Collection;

+import java.util.Enumeration;

+import java.util.Iterator;

+import java.util.Map;

+import java.util.NoSuchElementException;

+

+

+/**

+ * Uitlity class to wraps an <code>Enumeration</code> around a Collection, i.e.

+ * <code>Iterator</code> classes.

+ */

+

+public final class Enumerator implements Enumeration {

+

+

+    // Iterator over which the Enumeration takes place

+    private Iterator iterator = null;

+

+

+    /**

+     * Returns an Enumeration over the specified Collection.

+     * @param collection Collection with values that should be enumerated

+     */

+    public Enumerator(Collection collection) {

+        this(collection.iterator());

+    }

+

+

+    /**

+     * Returns an Enumeration over the values of the specified Iterator.

+     * @param iterator Iterator to be wrapped

+     */

+    public Enumerator(Iterator iterator) {

+        super();

+        this.iterator = iterator;

+    }

+

+

+    /**

+     * Returns an Enumeration over the values of the specified Map.

+     * @param map Map with values that should be enumerated

+     */

+    public Enumerator(Map map) {

+        this(map.values().iterator());

+    }

+

+

+    /**

+     * Tests if this enumeration contains more elements.

+     * @return <code>true</code> if this enumeration contains at least one more

+     *         element to provide, <code>false</code> otherwise.

+     */

+    public boolean hasMoreElements() {

+        return (iterator.hasNext());

+    }

+

+

+    /**

+     * Returns the next element of this enumeration.

+     * @return the next element of this enumeration

+     * @throws NoSuchElementException if no more elements exist

+     */

+    public Object nextElement() throws NoSuchElementException {

+        return (iterator.next());

+    }

+

+

+}

diff --git a/src/java/org/apache/pluto/util/NamespaceMapper.java b/src/java/org/apache/pluto/util/NamespaceMapper.java
new file mode 100644
index 0000000..9bdc4f0
--- /dev/null
+++ b/src/java/org/apache/pluto/util/NamespaceMapper.java
@@ -0,0 +1,36 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.util;

+

+import org.apache.pluto.om.ObjectID;

+

+/**

+ **/

+

+public interface NamespaceMapper {

+

+

+    public String encode(ObjectID namespace, String name);

+

+    public String encode(ObjectID ns1, ObjectID ns2, String name);

+

+    public String decode(ObjectID ns, String name);

+

+}

diff --git a/src/java/org/apache/pluto/util/PrintWriterServletOutputStream.java b/src/java/org/apache/pluto/util/PrintWriterServletOutputStream.java
new file mode 100644
index 0000000..043bc0a
--- /dev/null
+++ b/src/java/org/apache/pluto/util/PrintWriterServletOutputStream.java
@@ -0,0 +1,128 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.util;

+

+import java.io.IOException;

+import java.io.PrintWriter;

+

+import javax.servlet.ServletOutputStream;

+

+/**

+ * This is a specialized class implementing a ServletOutputStream that works in

+ * conjunction with a PrintWriter to send data to the browser. It is used when a

+ * J2EE server throws an IllegalStateException when you call getOutputStream on

+ * a response which someone has previously called getWriter on.

+ */

+public class PrintWriterServletOutputStream extends ServletOutputStream {

+

+    /**

+     * The PrintWriter that is wrapped on top of the base input stream

+     */

+    PrintWriter mPrintWriter;

+

+    /**

+     * Construct a ServletOutputStream that coordinates output using a base

+     * ServletOutputStream and a PrintWriter that is wrapped on top of that

+     * OutputStream.

+     */

+    public PrintWriterServletOutputStream(PrintWriter pO) {

+        super();

+        mPrintWriter = pO;

+    }

+

+    /**

+     * Writes an array of bytes

+     * @param pBuf the array to be written

+     * @throws IOException if an I/O error occurred

+     */

+    public void write(byte[] pBuf) throws IOException {

+        char[] cbuf = new char[pBuf.length];

+        for (int i = 0; i < cbuf.length; i++) {

+            cbuf[i] = (char) (pBuf[i] & 0xff);

+        }

+        mPrintWriter.write(cbuf, 0, pBuf.length);

+    }

+

+    /**

+     * Writes a single byte to the output stream

+     */

+    public void write(int pVal) throws IOException {

+        mPrintWriter.write(pVal);

+    }

+

+    /**

+     * Writes a subarray of bytes

+     * @param pBuf    the array to be written

+     * @param pOffset the offset into the array

+     * @param pLength the number of bytes to write

+     * @throws IOException if an I/O error occurred

+     */

+    public void write(byte[] pBuf, int pOffset, int pLength)

+        throws IOException {

+        char[] cbuf = new char[pLength];

+        for (int i = 0; i < pLength; i++) {

+            cbuf[i] = (char) (pBuf[i + pOffset] & 0xff);

+        }

+        mPrintWriter.write(cbuf, 0, pLength);

+    }

+

+    /**

+     * Flushes the stream, writing any buffered output bytes

+     * @throws IOException if an I/O error occurred

+     */

+    public void flush() throws IOException {

+        mPrintWriter.flush();

+    }

+

+    /**

+     * Closes the stream

+     * @throws IOException if an I/O error occurred

+     */

+    public void close() throws IOException {

+        mPrintWriter.close();

+    }

+

+    /**

+     * Prints a string.

+     * @param pVal the String to be printed

+     * @throws IOException if an I/O error has occurred

+     */

+    public void print(String pVal) throws IOException {

+        mPrintWriter.print(pVal);

+    }

+

+    /**

+     * Prints an string followed by a CRLF.

+     * @param pVal the String to be printed

+     * @throws IOException if an I/O error has occurred

+     */

+    public void println(String pVal) throws IOException {

+        mPrintWriter.println(pVal);

+    }

+

+    /**

+     * Prints a CRLF

+     * @throws IOException if an I/O error has occurred

+     */

+    public void println() throws IOException {

+        mPrintWriter.println();

+    }

+

+}

diff --git a/src/java/org/apache/pluto/util/StringManager.java b/src/java/org/apache/pluto/util/StringManager.java
new file mode 100644
index 0000000..ff1e541
--- /dev/null
+++ b/src/java/org/apache/pluto/util/StringManager.java
@@ -0,0 +1,237 @@
+/*

+ * Copyright 1999,2004 The Apache Software Foundation.

+ *

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ *

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+

+

+package org.apache.pluto.util;

+

+import java.net.URLClassLoader;

+import java.text.MessageFormat;

+import java.util.Hashtable;

+import java.util.Locale;

+import java.util.MissingResourceException;

+import java.util.ResourceBundle;

+

+/**

+ * An internationalization / localization helper class which reduces the bother

+ * of handling ResourceBundles and takes care of the common cases of message

+ * formating which otherwise require the creation of Object arrays and such.

+ * <p/>

+ * <p>The StringManager operates on a package basis. One StringManager per

+ * package can be created and accessed via the getManager method call.

+ * <p/>

+ * <p>The StringManager will look for a ResourceBundle named by the package name

+ * given plus the suffix of "LocalStrings". In practice, this means that the

+ * localized information will be contained in a LocalStrings.properties file

+ * located in the package directory of the classpath.

+ * <p/>

+ * <p>Please see the documentation for java.util.ResourceBundle for more

+ * information.

+ * @author James Duncan Davidson [duncan@eng.sun.com]

+ * @author James Todd [gonzo@eng.sun.com]

+ */

+

+public class StringManager {

+

+    /**

+     * The ResourceBundle for this StringManager.

+     */

+

+    private ResourceBundle bundle;

+

+    /**

+     * Creates a new StringManager for a given package. This is a private method

+     * and all access to it is arbitrated by the static getManager method call

+     * so that only one StringManager per package will be created.

+     * @param packageName Name of package to create StringManager for.

+     */

+

+    private StringManager(String packageName) {

+        String bundleName = packageName + ".LocalStrings";

+        try {

+            bundle = ResourceBundle.getBundle(bundleName);

+            return;

+        } catch (MissingResourceException ex) {

+            // Try from the current loader ( that's the case for trusted apps )

+            ClassLoader cl = Thread.currentThread().getContextClassLoader();

+            if (cl != null) {

+                try {

+                    bundle =

+                    ResourceBundle.getBundle(bundleName, Locale.getDefault(),

+                                             cl);

+                    return;

+                } catch (MissingResourceException ex2) {

+                }

+            }

+            if (cl == null) {

+                cl = this.getClass().getClassLoader();

+            }

+

+            System.out.println("Can't find resource " + bundleName +

+                               " " + cl);

+            if (cl instanceof URLClassLoader) {

+                System.out.println(((URLClassLoader) cl).getURLs());

+            }

+        }

+    }

+

+    /**

+     * Get a string from the underlying resource bundle.

+     * @param key The resource name

+     */

+    public String getString(String key) {

+        return MessageFormat.format(getStringInternal(key), null);

+    }

+

+

+    protected String getStringInternal(String key) {

+        if (key == null) {

+            String msg = "key is null";

+

+            throw new NullPointerException(msg);

+        }

+

+        String str = null;

+

+        if (bundle == null) {

+            return key;

+        }

+        try {

+            str = bundle.getString(key);

+        } catch (MissingResourceException mre) {

+            str = "Cannot find message associated with key '" + key + "'";

+        }

+

+        return str;

+    }

+

+    /**

+     * Get a string from the underlying resource bundle and format it with the

+     * given set of arguments.

+     * @param key  The resource name

+     * @param args Formatting directives

+     */

+

+    public String getString(String key, Object[] args) {

+        String iString = null;

+        String value = getStringInternal(key);

+

+        // this check for the runtime exception is some pre 1.1.6

+        // VM's don't do an automatic toString() on the passed in

+        // objects and barf out

+

+        try {

+            // ensure the arguments are not null so pre 1.2 VM's don't barf

+            Object nonNullArgs[] = args;

+            for (int i = 0; i < args.length; i++) {

+                if (args[i] == null) {

+                    if (nonNullArgs == args) {

+                        nonNullArgs =

+                        (Object[]) args.clone();

+                    }

+                    nonNullArgs[i] = "null";

+                }

+            }

+

+            iString = MessageFormat.format(value, nonNullArgs);

+        } catch (IllegalArgumentException iae) {

+            StringBuffer buf = new StringBuffer();

+            buf.append(value);

+            for (int i = 0; i < args.length; i++) {

+                buf.append(" arg[" + i + "]=" + args[i]);

+            }

+            iString = buf.toString();

+        }

+        return iString;

+    }

+

+    /**

+     * Get a string from the underlying resource bundle and format it with the

+     * given object argument. This argument can of course be a String object.

+     * @param key The resource name

+     * @param arg Formatting directive

+     */

+

+    public String getString(String key, Object arg) {

+        Object[] args = new Object[]{arg};

+        return getString(key, args);

+    }

+

+    /**

+     * Get a string from the underlying resource bundle and format it with the

+     * given object arguments. These arguments can of course be String objects.

+     * @param key  The resource name

+     * @param arg1 Formatting directive

+     * @param arg2 Formatting directive

+     */

+

+    public String getString(String key, Object arg1, Object arg2) {

+        Object[] args = new Object[]{arg1, arg2};

+        return getString(key, args);

+    }

+

+    /**

+     * Get a string from the underlying resource bundle and format it with the

+     * given object arguments. These arguments can of course be String objects.

+     * @param key  The resource name

+     * @param arg1 Formatting directive

+     * @param arg2 Formatting directive

+     * @param arg3 Formatting directive

+     */

+

+    public String getString(String key, Object arg1, Object arg2,

+                            Object arg3) {

+        Object[] args = new Object[]{arg1, arg2, arg3};

+        return getString(key, args);

+    }

+

+    /**

+     * Get a string from the underlying resource bundle and format it with the

+     * given object arguments. These arguments can of course be String objects.

+     * @param key  The resource name

+     * @param arg1 Formatting directive

+     * @param arg2 Formatting directive

+     * @param arg3 Formatting directive

+     * @param arg4 Formatting directive

+     */

+

+    public String getString(String key, Object arg1, Object arg2,

+                            Object arg3, Object arg4) {

+        Object[] args = new Object[]{arg1, arg2, arg3, arg4};

+        return getString(key, args);

+    }

+    // --------------------------------------------------------------

+    // STATIC SUPPORT METHODS

+    // --------------------------------------------------------------

+

+    private static Hashtable managers = new Hashtable();

+

+    /**

+     * Get the StringManager for a particular package. If a manager for a

+     * package already exists, it will be reused, else a new StringManager will

+     * be created and returned.

+     * @param packageName The package name

+     */

+

+    public synchronized static StringManager getManager(String packageName) {

+        StringManager mgr = (StringManager) managers.get(packageName);

+

+        if (mgr == null) {

+            mgr = new StringManager(packageName);

+            managers.put(packageName, mgr);

+        }

+        return mgr;

+    }

+}

diff --git a/src/java/org/apache/pluto/util/StringUtils.java b/src/java/org/apache/pluto/util/StringUtils.java
new file mode 100644
index 0000000..67a7a83
--- /dev/null
+++ b/src/java/org/apache/pluto/util/StringUtils.java
@@ -0,0 +1,337 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.util;

+

+import java.util.HashMap;

+import java.util.Iterator;

+import java.util.Map;

+

+/**

+ * * <CODE>StringUtils</CODE> hosts a couple of utility methods around *

+ * strings.

+ */

+

+public class StringUtils {

+

+    static java.util.BitSet dontNeedEncoding;

+    static final int caseDiff = ('a' - 'A');

+

+    /* The list of characters that are not encoded have been determined by

+       referencing O'Reilly's "HTML: The Definitive Guide" (page 164). */

+

+    static {

+        dontNeedEncoding = new java.util.BitSet(256);

+        int i;

+        for (i = 'a'; i <= 'z'; i++) {

+            dontNeedEncoding.set(i);

+        }

+        for (i = 'A'; i <= 'Z'; i++) {

+            dontNeedEncoding.set(i);

+        }

+        for (i = '0'; i <= '9'; i++) {

+            dontNeedEncoding.set(i);

+        }

+        dontNeedEncoding.set('-');

+        dontNeedEncoding.set('_');

+        dontNeedEncoding.set('.');

+        dontNeedEncoding.set('*');

+    }

+

+    /**

+     * * The operating system's line separator ('\n' on UNIX, '\r\n' on

+     * Windows)

+     */

+

+    public static final String lineSeparator = System.getProperty(

+        "line.separator");

+

+    /**

+     * * Returns the name of the package of the specified class. * The package

+     * will not include the common (short) name of the * class or the file

+     * extension. * * @param   aClass *          a class object * * @return

+     * its package

+     */

+

+    public static String packageOf(Class aClass) {

+        if (aClass == null) {

+            throw (new IllegalArgumentException(

+                "StringUtils: Argument \"aClass\" cannot be null."));

+        }

+

+        String result = "";

+

+        int index = aClass.getName().lastIndexOf(".");

+

+        if (index >= 0) {

+            result = aClass.getName().substring(0, index);

+        }

+

+        return (result);

+    }

+

+    /**

+     * Returns the short name of the specified class. The name will not include

+     * the package name or file extension.

+     * @param aClass a class object

+     * @return its name

+     */

+

+    public static String nameOf(Class aClass) {

+        if (aClass == null) {

+            throw new IllegalArgumentException(

+                "StringUtils: Argument \"aClass\" cannot be null.");

+        }

+

+        String className = aClass.getName();

+

+        int index = className.lastIndexOf(".");

+

+        if (index >= 0) {

+            className = className.substring(index + 1);

+        }

+

+        return (className);

+    }

+

+    /**

+     * Returns a combination of two paths, inserting slashes as appropriate.

+     * @param aRoot a root path

+     * @param aPath a path

+     * @return the path

+     */

+

+    public static String pathOf(String aRoot, String aPath) {

+        if (aPath == null) {

+            throw new IllegalArgumentException(

+                "StringUtils: Argument \"aPath\" cannot be null.");

+        }

+

+        String result = null;

+

+        if (aPath.startsWith("/") ||

+            aPath.startsWith("\\") ||

+            (aPath.length() >= 2 && aPath.charAt(1) == ':')) {

+            result = aPath;

+        } else {

+            if (aRoot == null) {

+                throw new IllegalArgumentException(

+                    "StringUtils: Argument \"aRoot\" cannot be null.");

+            }

+

+            StringBuffer temp = new StringBuffer(aRoot);

+

+            if (!aRoot.endsWith("/") &&

+                !aRoot.endsWith("\\")) {

+                temp.append('/');

+            }

+

+            temp.append(aPath);

+

+            result = temp.toString();

+        }

+

+        return result.toString();

+    }

+

+    /**

+     * Returns a <CODE>Boolean</CODE> object that corresponds the given value. A

+     * value of <CODE>true</CODE> or <CODE>yes</CODE> corresponds to

+     * <CODE>Boolean.TRUE</CODE> and a value of <CODE>false</CODE> or

+     * <CODE>no</CODE> corresponds to <CODE>Boolean.FALSE</CODE>. The comparions

+     * is case-insensitive, but for performance reasons, lower-case values of

+     * <CODE>true</CODE> and <CODE>false</CODE> should be used.

+     * @param aValue to value to convert

+     * @return the boolean value

+     */

+    public static Boolean booleanOf(String aValue) {

+        Boolean result = null;

+

+        if (aValue != null) {

+            if (aValue == "true" ||

+                aValue == "yes" ||

+                aValue.equalsIgnoreCase("true") ||

+                aValue.equalsIgnoreCase("yes")) {

+                result = Boolean.TRUE;

+            } else if (aValue == "false" ||

+                       aValue == "no" ||

+                       aValue.equalsIgnoreCase("false") ||

+                       aValue.equalsIgnoreCase("no")) {

+                result = Boolean.FALSE;

+            }

+        }

+

+        return (result);

+    }

+

+    /**

+     * Replace all occurrences of a pattern within a string by a replacement

+     * @param source  The string that should be searched

+     * @param pattern The pattern that should be replaced

+     * @param replace The replacement that should be inserted instead of the

+     *                pattern

+     * @return The updated source string

+     */

+    public static String replace(String source, String pattern, String replace) {

+        if (source == null || source.length() == 0 ||

+            pattern == null || pattern.length() == 0) {

+            return source;

+        }

+

+        int k = source.indexOf(pattern);

+

+        if (k == -1) {

+            return source;

+        }

+

+        StringBuffer out = new StringBuffer();

+        int i = 0, l = pattern.length();

+

+        while (k != -1) {

+            out.append(source.substring(i, k));

+

+            if (replace != null) {

+                out.append(replace);

+            }

+

+            i = k + l;

+            k = source.indexOf(pattern, i);

+        }

+        out.append(source.substring(i));

+        return out.toString();

+    }

+

+    public static void newLine(StringBuffer buffer, int indent) {

+        buffer.append(StringUtils.lineSeparator);

+        indent(buffer, indent);

+    }

+

+    public static void indent(StringBuffer buffer, int indent) {

+        for (int i = 0; i < indent; i++) {

+            buffer.append(' ');

+        }

+    }

+

+    public static String encode(String s) {

+        int maxBytesPerChar = 10;

+        StringBuffer out = new StringBuffer(s.length());

+        java.io.ByteArrayOutputStream buf = new java.io.ByteArrayOutputStream(

+            maxBytesPerChar);

+        java.io.OutputStreamWriter writer = new java.io.OutputStreamWriter(buf);

+

+        for (int i = 0; i < s.length(); i++) {

+            int c = (int) s.charAt(i);

+            if (dontNeedEncoding.get(c)) {

+                out.append((char) c);

+            } else {

+                // convert to external encoding before hex conversion

+                try {

+                    writer.write(c);

+                    writer.flush();

+                } catch (java.io.IOException e) {

+                    buf.reset();

+                    continue;

+                }

+                byte[] ba = buf.toByteArray();

+                for (int j = 0; j < ba.length; j++) {

+                    out.append('x');

+                    char ch = Character.forDigit((ba[j] >> 4) & 0xF, 16);

+                    // converting to use uppercase letter as part of

+                    // the hex value if ch is a letter.

+                    if (Character.isLetter(ch)) {

+                        ch -= caseDiff;

+                    }

+                    out.append(ch);

+                    ch = Character.forDigit(ba[j] & 0xF, 16);

+                    if (Character.isLetter(ch)) {

+                        ch -= caseDiff;

+                    }

+                    out.append(ch);

+                }

+                buf.reset();

+            }

+        }

+

+        return out.toString();

+    }

+

+    public static String decode(String s) {

+        StringBuffer sb = new StringBuffer();

+        for (int i = 0; i < s.length(); i++) {

+            char c = s.charAt(i);

+            switch (c) {

+                case '%':

+                    if (((s.charAt(i + 1) >= '0') && (s.charAt(i + 1) <= '9')) &&

+                        ((s.charAt(i + 2) >= '0') && (s.charAt(i + 2) <= '9'))) {

+                        try {

+                            sb.append(

+                                (char) Integer.parseInt(s.substring(i + 1, i +

+                                                                           3),

+                                                        16));

+                        } catch (java.lang.NumberFormatException e) {

+                            throw new java.lang.IllegalArgumentException();

+                        }

+                        i += 2;

+                        break;

+                    }

+                default:

+                    sb.append(c);

+                    break;

+            }

+        }

+        // Undo conversion to external encoding

+        String result = sb.toString();

+        try {

+            byte[] inputBytes = result.getBytes("8859_1");

+            result = new String(inputBytes);

+        } catch (java.io.UnsupportedEncodingException e) {

+            // The system should always have 8859_1

+        }

+        return result;

+    }

+

+    public static String[] copy(String[] source) {

+        if (source == null) {

+            return null;

+        }

+        int length = source.length;

+        String[] result = new String[length];

+        System.arraycopy(source, 0, result, 0, length);

+        return result;

+    }

+

+    public static Map copyParameters(Map parameters) {

+        Map result = new HashMap(parameters);

+        for (Iterator iter = result.entrySet().iterator(); iter.hasNext();) {

+            Map.Entry entry = (Map.Entry) iter.next();

+            if (!(entry.getKey() instanceof String)) {

+                throw new IllegalArgumentException(

+                    "Parameter map keys must not be null and of type java.lang.String.");

+            }

+            try {

+                entry.setValue(copy((String[]) entry.getValue()));

+            } catch (ClassCastException ex) {

+                throw new IllegalArgumentException(

+                    "Parameter map values must not be null and of type java.lang.String[].");

+            }

+        }

+        return result;

+    }

+

+}

diff --git a/src/java/org/apache/pluto/util/WriterOutputStream.java b/src/java/org/apache/pluto/util/WriterOutputStream.java
new file mode 100644
index 0000000..61afbce
--- /dev/null
+++ b/src/java/org/apache/pluto/util/WriterOutputStream.java
@@ -0,0 +1,39 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.util;

+

+import java.io.IOException;

+import java.io.OutputStream;

+import java.io.Writer;

+

+public class WriterOutputStream extends OutputStream {

+    private Writer writer;

+    private String encoding;

+

+    public WriterOutputStream(Writer writer, String encoding) {

+        this.writer = writer;

+        this.encoding = encoding;

+    }

+

+    public void write(int b) throws IOException {

+        // this is slow but it works for now

+        writer.write(new String(new byte[]{(byte) b}, encoding));

+    }

+}

diff --git a/src/java/org/apache/pluto/util/impl/NamespaceMapperImpl.java b/src/java/org/apache/pluto/util/impl/NamespaceMapperImpl.java
new file mode 100644
index 0000000..ace90be
--- /dev/null
+++ b/src/java/org/apache/pluto/util/impl/NamespaceMapperImpl.java
@@ -0,0 +1,67 @@
+/*

+ * Copyright 2003,2004 The Apache Software Foundation.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ * 

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+/* 

+

+ */

+

+package org.apache.pluto.util.impl;

+

+import org.apache.pluto.om.ObjectID;

+import org.apache.pluto.util.NamespaceMapper;

+

+/**

+ **/

+

+public class NamespaceMapperImpl implements NamespaceMapper {

+    public NamespaceMapperImpl() {

+    }

+

+    // org.apache.pluto.util.NamespaceMapper implementation ---------------------------------------

+    public String encode(ObjectID ns, String name) {

+        StringBuffer buffer = new StringBuffer(50);

+        buffer.append("Pluto_");

+        buffer.append(ns);

+        buffer.append('_');

+        buffer.append(name);

+        return buffer.toString();

+    }

+

+    public String encode(ObjectID ns1, ObjectID ns2, String name) {

+        StringBuffer buffer = new StringBuffer(50);

+        buffer.append("Pluto_");

+        buffer.append(ns1);

+        buffer.append('_');

+        buffer.append(ns2);

+        buffer.append('_');

+        buffer.append(name);

+        return buffer.toString();

+    }

+

+    public String decode(ObjectID ns, String name) {

+        if (!name.startsWith("Pluto_")) {

+            return null;

+        }

+        StringBuffer buffer = new StringBuffer(50);

+        buffer.append("Pluto_");

+        buffer.append(ns);

+        buffer.append('_');

+        if (!name.startsWith(buffer.toString())) {

+            return null;

+        }

+        return name.substring(buffer.length());

+    }

+    // --------------------------------------------------------------------------------------------

+}