gatein SVN: r7783 - components/wci/tags.
by do-not-reply@jboss.org
Author: bdaw
Date: 2011-10-19 03:14:46 -0400 (Wed, 19 Oct 2011)
New Revision: 7783
Added:
components/wci/tags/2.1.0-GA/
Log:
[maven-release-plugin] copy for tag 2.1.0-GA
13 years, 2 months
gatein SVN: r7782 - in components/wci/trunk: exo and 19 other directories.
by do-not-reply@jboss.org
Author: bdaw
Date: 2011-10-19 03:14:34 -0400 (Wed, 19 Oct 2011)
New Revision: 7782
Modified:
components/wci/trunk/exo/pom.xml
components/wci/trunk/jboss/jboss6/pom.xml
components/wci/trunk/jboss/pom.xml
components/wci/trunk/jetty/pom.xml
components/wci/trunk/pom.xml
components/wci/trunk/test/core/pom.xml
components/wci/trunk/test/pom.xml
components/wci/trunk/test/portlets/exo-portlet/pom.xml
components/wci/trunk/test/portlets/gatein-portlet/pom.xml
components/wci/trunk/test/portlets/native-portlet/pom.xml
components/wci/trunk/test/portlets/pom.xml
components/wci/trunk/test/servers/jboss51/pom.xml
components/wci/trunk/test/servers/jboss6/pom.xml
components/wci/trunk/test/servers/jetty6/pom.xml
components/wci/trunk/test/servers/pom.xml
components/wci/trunk/test/servers/tomcat6/pom.xml
components/wci/trunk/test/servers/tomcat7/pom.xml
components/wci/trunk/tomcat/pom.xml
components/wci/trunk/tomcat/tomcat6/pom.xml
components/wci/trunk/tomcat/tomcat7/pom.xml
components/wci/trunk/wci/pom.xml
Log:
[maven-release-plugin] prepare release 2.1.0-GA
Modified: components/wci/trunk/exo/pom.xml
===================================================================
--- components/wci/trunk/exo/pom.xml 2011-10-19 07:01:46 UTC (rev 7781)
+++ components/wci/trunk/exo/pom.xml 2011-10-19 07:14:34 UTC (rev 7782)
@@ -2,7 +2,7 @@
<parent>
<groupId>org.gatein.wci</groupId>
<artifactId>wci-parent</artifactId>
- <version>2.1.0-Beta07-SNAPSHOT</version>
+ <version>2.1.0-GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>wci-exo</artifactId>
Modified: components/wci/trunk/jboss/jboss6/pom.xml
===================================================================
--- components/wci/trunk/jboss/jboss6/pom.xml 2011-10-19 07:01:46 UTC (rev 7781)
+++ components/wci/trunk/jboss/jboss6/pom.xml 2011-10-19 07:14:34 UTC (rev 7782)
@@ -2,11 +2,11 @@
<parent>
<groupId>org.gatein.wci</groupId>
<artifactId>wci-jboss</artifactId>
- <version>2.1.0-Beta07-SNAPSHOT</version>
+ <version>2.1.0-GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>wci-jboss6</artifactId>
- <version>2.1.0-Beta07-SNAPSHOT</version>
+ <version>2.1.0-GA</version>
<packaging>jar</packaging>
<name>GateIn - WCI JBoss 6 compatibility component</name>
Modified: components/wci/trunk/jboss/pom.xml
===================================================================
--- components/wci/trunk/jboss/pom.xml 2011-10-19 07:01:46 UTC (rev 7781)
+++ components/wci/trunk/jboss/pom.xml 2011-10-19 07:14:34 UTC (rev 7782)
@@ -2,7 +2,7 @@
<parent>
<groupId>org.gatein.wci</groupId>
<artifactId>wci-parent</artifactId>
- <version>2.1.0-Beta07-SNAPSHOT</version>
+ <version>2.1.0-GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>wci-jboss</artifactId>
Modified: components/wci/trunk/jetty/pom.xml
===================================================================
--- components/wci/trunk/jetty/pom.xml 2011-10-19 07:01:46 UTC (rev 7781)
+++ components/wci/trunk/jetty/pom.xml 2011-10-19 07:14:34 UTC (rev 7782)
@@ -2,7 +2,7 @@
<parent>
<groupId>org.gatein.wci</groupId>
<artifactId>wci-parent</artifactId>
- <version>2.1.0-Beta07-SNAPSHOT</version>
+ <version>2.1.0-GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>wci-jetty</artifactId>
Modified: components/wci/trunk/pom.xml
===================================================================
--- components/wci/trunk/pom.xml 2011-10-19 07:01:46 UTC (rev 7781)
+++ components/wci/trunk/pom.xml 2011-10-19 07:14:34 UTC (rev 7782)
@@ -6,7 +6,7 @@
<groupId>org.gatein.wci</groupId>
<artifactId>wci-parent</artifactId>
- <version>2.1.0-Beta07-SNAPSHOT</version>
+ <version>2.1.0-GA</version>
<packaging>pom</packaging>
<parent>
@@ -16,9 +16,9 @@
</parent>
<scm>
- <connection>scm:svn:http://anonsvn.jboss.org/repos/gatein/components/wci/trunk/</connection>
- <developerConnection>scm:svn:https://svn.jboss.org/repos/gatein/components/wci/trunk/</developerConnection>
- <url>http://fisheye.jboss.org/browse/gatein/components/wci/trunk/</url>
+ <connection>scm:svn:http://anonsvn.jboss.org/repos/gatein/components/wci/tags/2.1.0-GA</connection>
+ <developerConnection>scm:svn:https://svn.jboss.org/repos/gatein/components/wci/tags/2.1.0-GA</developerConnection>
+ <url>http://fisheye.jboss.org/browse/gatein/components/wci/tags/2.1.0-GA</url>
</scm>
<properties>
Modified: components/wci/trunk/test/core/pom.xml
===================================================================
--- components/wci/trunk/test/core/pom.xml 2011-10-19 07:01:46 UTC (rev 7781)
+++ components/wci/trunk/test/core/pom.xml 2011-10-19 07:14:34 UTC (rev 7782)
@@ -2,7 +2,7 @@
<parent>
<groupId>org.gatein.wci</groupId>
<artifactId>wci-test-parent</artifactId>
- <version>2.1.0-Beta07-SNAPSHOT</version>
+ <version>2.1.0-GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>wci-test-core</artifactId>
Modified: components/wci/trunk/test/pom.xml
===================================================================
--- components/wci/trunk/test/pom.xml 2011-10-19 07:01:46 UTC (rev 7781)
+++ components/wci/trunk/test/pom.xml 2011-10-19 07:14:34 UTC (rev 7782)
@@ -2,7 +2,7 @@
<parent>
<groupId>org.gatein.wci</groupId>
<artifactId>wci-parent</artifactId>
- <version>2.1.0-Beta07-SNAPSHOT</version>
+ <version>2.1.0-GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>wci-test-parent</artifactId>
Modified: components/wci/trunk/test/portlets/exo-portlet/pom.xml
===================================================================
--- components/wci/trunk/test/portlets/exo-portlet/pom.xml 2011-10-19 07:01:46 UTC (rev 7781)
+++ components/wci/trunk/test/portlets/exo-portlet/pom.xml 2011-10-19 07:14:34 UTC (rev 7782)
@@ -2,11 +2,11 @@
<parent>
<groupId>org.gatein.wci</groupId>
<artifactId>wci-test-portlets</artifactId>
- <version>2.1.0-Beta07-SNAPSHOT</version>
+ <version>2.1.0-GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>wci-test-exo-portlet</artifactId>
- <version>2.1.0-Beta07-SNAPSHOT</version>
+ <version>2.1.0-GA</version>
<packaging>war</packaging>
<name>GateIn - WCI eXo Backwards Compatibility Test Portlet</name>
</project>
Modified: components/wci/trunk/test/portlets/gatein-portlet/pom.xml
===================================================================
--- components/wci/trunk/test/portlets/gatein-portlet/pom.xml 2011-10-19 07:01:46 UTC (rev 7781)
+++ components/wci/trunk/test/portlets/gatein-portlet/pom.xml 2011-10-19 07:14:34 UTC (rev 7782)
@@ -2,11 +2,11 @@
<parent>
<groupId>org.gatein.wci</groupId>
<artifactId>wci-test-portlets</artifactId>
- <version>2.1.0-Beta07-SNAPSHOT</version>
+ <version>2.1.0-GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>wci-test-gatein-portlet</artifactId>
- <version>2.1.0-Beta07-SNAPSHOT</version>
+ <version>2.1.0-GA</version>
<packaging>war</packaging>
<name>GateIn - WCI Gatein Test Portlet</name>
</project>
Modified: components/wci/trunk/test/portlets/native-portlet/pom.xml
===================================================================
--- components/wci/trunk/test/portlets/native-portlet/pom.xml 2011-10-19 07:01:46 UTC (rev 7781)
+++ components/wci/trunk/test/portlets/native-portlet/pom.xml 2011-10-19 07:14:34 UTC (rev 7782)
@@ -2,11 +2,11 @@
<parent>
<groupId>org.gatein.wci</groupId>
<artifactId>wci-test-portlets</artifactId>
- <version>2.1.0-Beta07-SNAPSHOT</version>
+ <version>2.1.0-GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>wci-test-native-portlet</artifactId>
- <version>2.1.0-Beta07-SNAPSHOT</version>
+ <version>2.1.0-GA</version>
<packaging>war</packaging>
<name>GateIn - WCI Native Test Portlet</name>
</project>
Modified: components/wci/trunk/test/portlets/pom.xml
===================================================================
--- components/wci/trunk/test/portlets/pom.xml 2011-10-19 07:01:46 UTC (rev 7781)
+++ components/wci/trunk/test/portlets/pom.xml 2011-10-19 07:14:34 UTC (rev 7782)
@@ -2,7 +2,7 @@
<parent>
<groupId>org.gatein.wci</groupId>
<artifactId>wci-test-parent</artifactId>
- <version>2.1.0-Beta07-SNAPSHOT</version>
+ <version>2.1.0-GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>wci-test-portlets</artifactId>
Modified: components/wci/trunk/test/servers/jboss51/pom.xml
===================================================================
--- components/wci/trunk/test/servers/jboss51/pom.xml 2011-10-19 07:01:46 UTC (rev 7781)
+++ components/wci/trunk/test/servers/jboss51/pom.xml 2011-10-19 07:14:34 UTC (rev 7782)
@@ -2,7 +2,7 @@
<parent>
<groupId>org.gatein.wci</groupId>
<artifactId>wci-test-server-parent</artifactId>
- <version>2.1.0-Beta07-SNAPSHOT</version>
+ <version>2.1.0-GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>wci-test-jboss51</artifactId>
Modified: components/wci/trunk/test/servers/jboss6/pom.xml
===================================================================
--- components/wci/trunk/test/servers/jboss6/pom.xml 2011-10-19 07:01:46 UTC (rev 7781)
+++ components/wci/trunk/test/servers/jboss6/pom.xml 2011-10-19 07:14:34 UTC (rev 7782)
@@ -2,7 +2,7 @@
<parent>
<groupId>org.gatein.wci</groupId>
<artifactId>wci-test-server-parent</artifactId>
- <version>2.1.0-Beta07-SNAPSHOT</version>
+ <version>2.1.0-GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>wci-test-jboss6</artifactId>
Modified: components/wci/trunk/test/servers/jetty6/pom.xml
===================================================================
--- components/wci/trunk/test/servers/jetty6/pom.xml 2011-10-19 07:01:46 UTC (rev 7781)
+++ components/wci/trunk/test/servers/jetty6/pom.xml 2011-10-19 07:14:34 UTC (rev 7782)
@@ -2,7 +2,7 @@
<parent>
<groupId>org.gatein.wci</groupId>
<artifactId>wci-test-server-parent</artifactId>
- <version>2.1.0-Beta07-SNAPSHOT</version>
+ <version>2.1.0-GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>wci-test-jetty6</artifactId>
Modified: components/wci/trunk/test/servers/pom.xml
===================================================================
--- components/wci/trunk/test/servers/pom.xml 2011-10-19 07:01:46 UTC (rev 7781)
+++ components/wci/trunk/test/servers/pom.xml 2011-10-19 07:14:34 UTC (rev 7782)
@@ -2,7 +2,7 @@
<parent>
<groupId>org.gatein.wci</groupId>
<artifactId>wci-test-parent</artifactId>
- <version>2.1.0-Beta07-SNAPSHOT</version>
+ <version>2.1.0-GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>wci-test-server-parent</artifactId>
Modified: components/wci/trunk/test/servers/tomcat6/pom.xml
===================================================================
--- components/wci/trunk/test/servers/tomcat6/pom.xml 2011-10-19 07:01:46 UTC (rev 7781)
+++ components/wci/trunk/test/servers/tomcat6/pom.xml 2011-10-19 07:14:34 UTC (rev 7782)
@@ -2,7 +2,7 @@
<parent>
<groupId>org.gatein.wci</groupId>
<artifactId>wci-test-server-parent</artifactId>
- <version>2.1.0-Beta07-SNAPSHOT</version>
+ <version>2.1.0-GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>wci-test-tomcat6</artifactId>
Modified: components/wci/trunk/test/servers/tomcat7/pom.xml
===================================================================
--- components/wci/trunk/test/servers/tomcat7/pom.xml 2011-10-19 07:01:46 UTC (rev 7781)
+++ components/wci/trunk/test/servers/tomcat7/pom.xml 2011-10-19 07:14:34 UTC (rev 7782)
@@ -2,7 +2,7 @@
<parent>
<groupId>org.gatein.wci</groupId>
<artifactId>wci-test-server-parent</artifactId>
- <version>2.1.0-Beta07-SNAPSHOT</version>
+ <version>2.1.0-GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>wci-test-tomcat7</artifactId>
Modified: components/wci/trunk/tomcat/pom.xml
===================================================================
--- components/wci/trunk/tomcat/pom.xml 2011-10-19 07:01:46 UTC (rev 7781)
+++ components/wci/trunk/tomcat/pom.xml 2011-10-19 07:14:34 UTC (rev 7782)
@@ -2,7 +2,7 @@
<parent>
<groupId>org.gatein.wci</groupId>
<artifactId>wci-parent</artifactId>
- <version>2.1.0-Beta07-SNAPSHOT</version>
+ <version>2.1.0-GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>wci-tomcat</artifactId>
Modified: components/wci/trunk/tomcat/tomcat6/pom.xml
===================================================================
--- components/wci/trunk/tomcat/tomcat6/pom.xml 2011-10-19 07:01:46 UTC (rev 7781)
+++ components/wci/trunk/tomcat/tomcat6/pom.xml 2011-10-19 07:14:34 UTC (rev 7782)
@@ -2,11 +2,11 @@
<parent>
<groupId>org.gatein.wci</groupId>
<artifactId>wci-tomcat</artifactId>
- <version>2.1.0-Beta07-SNAPSHOT</version>
+ <version>2.1.0-GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>wci-tomcat6</artifactId>
- <version>2.1.0-Beta07-SNAPSHOT</version>
+ <version>2.1.0-GA</version>
<packaging>jar</packaging>
<name>GateIn - WCI Tomcat 6 compatibility component</name>
Modified: components/wci/trunk/tomcat/tomcat7/pom.xml
===================================================================
--- components/wci/trunk/tomcat/tomcat7/pom.xml 2011-10-19 07:01:46 UTC (rev 7781)
+++ components/wci/trunk/tomcat/tomcat7/pom.xml 2011-10-19 07:14:34 UTC (rev 7782)
@@ -2,11 +2,11 @@
<parent>
<groupId>org.gatein.wci</groupId>
<artifactId>wci-tomcat</artifactId>
- <version>2.1.0-Beta07-SNAPSHOT</version>
+ <version>2.1.0-GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>wci-tomcat7</artifactId>
- <version>2.1.0-Beta07-SNAPSHOT</version>
+ <version>2.1.0-GA</version>
<packaging>jar</packaging>
<name>GateIn - WCI Tomcat 7 compatibility component</name>
Modified: components/wci/trunk/wci/pom.xml
===================================================================
--- components/wci/trunk/wci/pom.xml 2011-10-19 07:01:46 UTC (rev 7781)
+++ components/wci/trunk/wci/pom.xml 2011-10-19 07:14:34 UTC (rev 7782)
@@ -2,7 +2,7 @@
<parent>
<groupId>org.gatein.wci</groupId>
<artifactId>wci-parent</artifactId>
- <version>2.1.0-Beta07-SNAPSHOT</version>
+ <version>2.1.0-GA</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>wci-wci</artifactId>
13 years, 2 months
gatein SVN: r7781 - in portal/trunk/web/portal/src/main/webapp/WEB-INF/conf: portal and 1 other directory.
by do-not-reply@jboss.org
Author: haint
Date: 2011-10-19 03:01:46 -0400 (Wed, 19 Oct 2011)
New Revision: 7781
Modified:
portal/trunk/web/portal/src/main/webapp/WEB-INF/conf/common/common-configuration.xml
portal/trunk/web/portal/src/main/webapp/WEB-INF/conf/portal/portal-configuration.xml
Log:
GTNPORTAL-2174 Use the new ExoCache config instead of adding a new creator
Modified: portal/trunk/web/portal/src/main/webapp/WEB-INF/conf/common/common-configuration.xml
===================================================================
--- portal/trunk/web/portal/src/main/webapp/WEB-INF/conf/common/common-configuration.xml 2011-10-19 06:48:45 UTC (rev 7780)
+++ portal/trunk/web/portal/src/main/webapp/WEB-INF/conf/common/common-configuration.xml 2011-10-19 07:01:46 UTC (rev 7781)
@@ -203,11 +203,6 @@
<description>The EA cache creator</description>
<object type="org.exoplatform.services.cache.impl.jboss.ea.EAExoCacheCreator"></object>
</object-param>
- <object-param>
- <name>simple</name>
- <description>The Simple cache creator</description>
- <object type="org.exoplatform.commons.cache.SimpleExoCacheCreator"></object>
- </object-param>
</init-params>
</component-plugin>
</external-component-plugins>
Modified: portal/trunk/web/portal/src/main/webapp/WEB-INF/conf/portal/portal-configuration.xml
===================================================================
--- portal/trunk/web/portal/src/main/webapp/WEB-INF/conf/portal/portal-configuration.xml 2011-10-19 06:48:45 UTC (rev 7780)
+++ portal/trunk/web/portal/src/main/webapp/WEB-INF/conf/portal/portal-configuration.xml 2011-10-19 07:01:46 UTC (rev 7781)
@@ -339,6 +339,9 @@
<field name="liveTime">
<long>600</long>
</field>
+ <field name="implementation">
+ <string>org.exoplatform.services.cache.concurrent.ConcurrentFIFOExoCache</string>
+ </field>
</object>
</object-param>
</init-params>
@@ -387,6 +390,9 @@
<field name="liveTime">
<long>600</long>
</field>
+ <field name="implementation">
+ <string>org.exoplatform.services.cache.concurrent.ConcurrentFIFOExoCache</string>
+ </field>
</object>
</object-param>
</init-params>
@@ -438,6 +444,9 @@
<field name="liveTime">
<long>600</long>
</field>
+ <field name="implementation">
+ <string>org.exoplatform.services.cache.concurrent.ConcurrentFIFOExoCache</string>
+ </field>
</object>
</object-param>
</init-params>
13 years, 2 months
gatein SVN: r7780 - portal/trunk/webui/dashboard/src/main/java/org/exoplatform/dashboard/webui/component.
by do-not-reply@jboss.org
Author: kien_nguyen
Date: 2011-10-19 02:48:45 -0400 (Wed, 19 Oct 2011)
New Revision: 7780
Modified:
portal/trunk/webui/dashboard/src/main/java/org/exoplatform/dashboard/webui/component/UIDashboardSelectContainer.java
Log:
GTNPORTAL-1008 Gadget permissions are not working correctly (gagdet with restricted access in the AppReg are visible)
Modified: portal/trunk/webui/dashboard/src/main/java/org/exoplatform/dashboard/webui/component/UIDashboardSelectContainer.java
===================================================================
--- portal/trunk/webui/dashboard/src/main/java/org/exoplatform/dashboard/webui/component/UIDashboardSelectContainer.java 2011-10-19 05:50:10 UTC (rev 7779)
+++ portal/trunk/webui/dashboard/src/main/java/org/exoplatform/dashboard/webui/component/UIDashboardSelectContainer.java 2011-10-19 06:48:45 UTC (rev 7780)
@@ -22,12 +22,15 @@
import org.exoplatform.application.registry.Application;
import org.exoplatform.application.registry.ApplicationCategory;
import org.exoplatform.application.registry.ApplicationRegistryService;
+import org.exoplatform.portal.config.UserACL;
import org.exoplatform.portal.config.model.ApplicationType;
+import org.exoplatform.portal.webui.util.Util;
import org.exoplatform.webui.application.WebuiRequestContext;
import org.exoplatform.webui.config.annotation.ComponentConfig;
import org.exoplatform.webui.core.UIContainer;
import org.exoplatform.webui.core.lifecycle.UIFormLifecycle;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
@@ -59,21 +62,28 @@
public final List<ApplicationCategory> getCategories() throws Exception
{
ApplicationRegistryService service = getApplicationComponent(ApplicationRegistryService.class);
+ UserACL acl = Util.getUIPortalApplication().getApplicationComponent(UserACL.class);
String remoteUser = ((WebuiRequestContext)WebuiRequestContext.getCurrentInstance()).getRemoteUser();
- List<ApplicationCategory> listCategories =
- service.getApplicationCategories(remoteUser, ApplicationType.GADGET);
+ List<ApplicationCategory> listCategories = new ArrayList<ApplicationCategory>();
- Iterator<ApplicationCategory> appCateIte = listCategories.iterator();
+ Iterator<ApplicationCategory> appCateIte = service.getApplicationCategories(remoteUser, ApplicationType.GADGET).iterator();
while (appCateIte.hasNext())
{
ApplicationCategory cate = appCateIte.next();
- List<Application> listGadgets = cate.getApplications();
- if (listGadgets == null || listGadgets.size() == 0)
+ for(String p : cate.getAccessPermissions())
{
- appCateIte.remove();
- continue;
+ if(acl.hasPermission(p))
+ {
+ List<Application> listGadgets = cate.getApplications();
+ if (listGadgets != null && listGadgets.size() > 0)
+ {
+ listCategories.add(cate);
+ break;
+ }
+ }
}
+
}
Collections.sort(listCategories, new Comparator<ApplicationCategory>()
{
@@ -93,7 +103,21 @@
public List<Application> getGadgetsOfCategory(final ApplicationCategory appCategory) throws Exception
{
- List<Application> listGadgets = appCategory.getApplications();
+ UserACL acl = Util.getUIPortalApplication().getApplicationComponent(UserACL.class);
+ List<Application> listGadgets = new ArrayList<Application>();
+ Iterator<Application> gadgetIterator = appCategory.getApplications().iterator();
+ while(gadgetIterator.hasNext())
+ {
+ Application app = gadgetIterator.next();
+ for(String p : app.getAccessPermissions())
+ {
+ if(acl.hasPermission(p))
+ {
+ listGadgets.add(app);
+ break;
+ }
+ }
+ }
Collections.sort(listGadgets, new Comparator<Application>()
{
public int compare(Application app1, Application app2)
13 years, 2 months
gatein SVN: r7779 - in portal/trunk: webui/core/src/main/java/org/exoplatform/webui/form and 1 other directory.
by do-not-reply@jboss.org
Author: ndkhoiits
Date: 2011-10-19 01:50:10 -0400 (Wed, 19 Oct 2011)
New Revision: 7779
Modified:
portal/trunk/portlet/exoadmin/src/main/java/org/exoplatform/navigation/webui/component/UIPageNodeForm.java
portal/trunk/webui/core/src/main/java/org/exoplatform/webui/form/UIFormCheckBoxInput.java
Log:
GTNPORTAL-2181 Still check Extended label mode after add new node with uncheck Extended label mode
Modified: portal/trunk/portlet/exoadmin/src/main/java/org/exoplatform/navigation/webui/component/UIPageNodeForm.java
===================================================================
--- portal/trunk/portlet/exoadmin/src/main/java/org/exoplatform/navigation/webui/component/UIPageNodeForm.java 2011-10-19 05:46:34 UTC (rev 7778)
+++ portal/trunk/portlet/exoadmin/src/main/java/org/exoplatform/navigation/webui/component/UIPageNodeForm.java 2011-10-19 05:50:10 UTC (rev 7779)
@@ -174,7 +174,7 @@
getUIStringInput("name").setEditable(UIFormStringInput.ENABLE);
getChild(UIFormInputIconSelector.class).setSelectedIcon("Default");
setShowPublicationDate(false);
- switchLabelMode(false);
+ switchLabelMode(true);
return;
}
getUIStringInput("name").setEditable(UIFormStringInput.DISABLE);
@@ -392,9 +392,11 @@
}
node.setI18nizedLabels(labels);
-
+
if (getUIFormCheckBoxInput(SWITCH_MODE).getValue().toString().equals("true"))
node.setLabel(null);
+ else if (node.getLabel() == null)
+ node.setLabel(node.getName());
}
public void setShowCheckPublicationDate(boolean show)
Modified: portal/trunk/webui/core/src/main/java/org/exoplatform/webui/form/UIFormCheckBoxInput.java
===================================================================
--- portal/trunk/webui/core/src/main/java/org/exoplatform/webui/form/UIFormCheckBoxInput.java 2011-10-19 05:46:34 UTC (rev 7778)
+++ portal/trunk/webui/core/src/main/java/org/exoplatform/webui/form/UIFormCheckBoxInput.java 2011-10-19 05:50:10 UTC (rev 7779)
@@ -56,7 +56,7 @@
super(name, bindingExpression, null);
if (value != null)
typeValue_ = (Class<T>)value.getClass();
- value_ = value;
+ setValue(value);
setId(name);
}
@@ -120,7 +120,6 @@
{
if (!isEnable())
return;
-
if (input != null) {
if(input.equals("true"))
checked = true;
13 years, 2 months
gatein SVN: r7778 - in epp/docs/branches/5.2/Reference_Guide-eXoJCR-1.14/en-US/images: DataImportStrategy and 1 other directory.
by do-not-reply@jboss.org
Author: smumford
Date: 2011-10-19 01:46:34 -0400 (Wed, 19 Oct 2011)
New Revision: 7778
Added:
epp/docs/branches/5.2/Reference_Guide-eXoJCR-1.14/en-US/images/DataImportStrategy/
epp/docs/branches/5.2/Reference_Guide-eXoJCR-1.14/en-US/images/DataImportStrategy/navigation1.png
epp/docs/branches/5.2/Reference_Guide-eXoJCR-1.14/en-US/images/DataImportStrategy/navigation2.png
epp/docs/branches/5.2/Reference_Guide-eXoJCR-1.14/en-US/images/DataImportStrategy/navigation_insert.png
epp/docs/branches/5.2/Reference_Guide-eXoJCR-1.14/en-US/images/DataImportStrategy/navigation_merge.png
Log:
Porting revs 7738,7666,7658 to EPP
Added: epp/docs/branches/5.2/Reference_Guide-eXoJCR-1.14/en-US/images/DataImportStrategy/navigation1.png
===================================================================
(Binary files differ)
Property changes on: epp/docs/branches/5.2/Reference_Guide-eXoJCR-1.14/en-US/images/DataImportStrategy/navigation1.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added: epp/docs/branches/5.2/Reference_Guide-eXoJCR-1.14/en-US/images/DataImportStrategy/navigation2.png
===================================================================
(Binary files differ)
Property changes on: epp/docs/branches/5.2/Reference_Guide-eXoJCR-1.14/en-US/images/DataImportStrategy/navigation2.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added: epp/docs/branches/5.2/Reference_Guide-eXoJCR-1.14/en-US/images/DataImportStrategy/navigation_insert.png
===================================================================
(Binary files differ)
Property changes on: epp/docs/branches/5.2/Reference_Guide-eXoJCR-1.14/en-US/images/DataImportStrategy/navigation_insert.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added: epp/docs/branches/5.2/Reference_Guide-eXoJCR-1.14/en-US/images/DataImportStrategy/navigation_merge.png
===================================================================
(Binary files differ)
Property changes on: epp/docs/branches/5.2/Reference_Guide-eXoJCR-1.14/en-US/images/DataImportStrategy/navigation_merge.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
13 years, 2 months
gatein SVN: r7776 - epp/docs/branches/5.2/Reference_Guide-eXoJCR-1.14/en-US/modules/PortalDevelopment.
by do-not-reply@jboss.org
Author: smumford
Date: 2011-10-19 01:45:35 -0400 (Wed, 19 Oct 2011)
New Revision: 7776
Added:
epp/docs/branches/5.2/Reference_Guide-eXoJCR-1.14/en-US/modules/PortalDevelopment/DataImportStrategy.xml
epp/docs/branches/5.2/Reference_Guide-eXoJCR-1.14/en-US/modules/PortalDevelopment/NavigationController.xml
Log:
Porting revs 7738,7666,7658 to EPP
Added: epp/docs/branches/5.2/Reference_Guide-eXoJCR-1.14/en-US/modules/PortalDevelopment/DataImportStrategy.xml
===================================================================
--- epp/docs/branches/5.2/Reference_Guide-eXoJCR-1.14/en-US/modules/PortalDevelopment/DataImportStrategy.xml (rev 0)
+++ epp/docs/branches/5.2/Reference_Guide-eXoJCR-1.14/en-US/modules/PortalDevelopment/DataImportStrategy.xml 2011-10-19 05:45:35 UTC (rev 7776)
@@ -0,0 +1,290 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % BOOK_ENTITIES SYSTEM "../../Reference_Guide.ent">
+%BOOK_ENTITIES;
+]>
+<chapter id="chap-Reference_Guide-Data_Import_Strategy">
+ <title>Data Import Strategy</title>
+ <section id="sect-Reference_Guide-Data_Import_Strategy-Introduction">
+ <title>Introduction</title>
+ <para>
+ In the Portal extension mechanism, developers can define an extension
+ that Portal data can be customized by configurations in the extension. There
+ are several cases which an extension developer wants to define how to customize the Portal data,
+ for example modifying, overwriting or just inserting a bit into the data defined by the portal.
+ Therefore, GateIn also defines several modes for each case and the only thing which a developer has to do is to clarify the
+ usecase and reasonably configure extensions.
+ </para>
+ <para>
+ This section shows you how data are changes in each mode.
+ </para>
+ </section>
+
+ <section id="sect-Reference_Guide-Data_Import_Strategy-Import_Mode">
+ <title>Import Mode</title>
+ <para>
+ In this section, the following modes for the import strategy are introduced:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>CONSERVE</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>MERGE</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>INSERT</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>OVERWRITE</literal>
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Each mode indicates how the Portal data are imported. The import mode value is
+ set whenever <literal>NewPortalConfigListener</literal> is initiated. If the mode is not set,
+ the default value will be used in this case. The default value is configurable as
+ a UserPortalConfigService initial param. For example, the bellow configuration
+ means that default value is <literal>MERGE</literal>.
+ </para>
+ <programlisting language="XML" role="XML"><![CDATA[
+<component>
+ <key>org.exoplatform.portal.config.UserPortalConfigService</key>
+ <type>org.exoplatform.portal.config.UserPortalConfigService</type>
+ <component-plugins>
+ ............
+ </component-plugins>
+ <init-params>
+ <value-param>
+ <name>default.import.mode</name>
+ <value>merge</value>
+ </value-param>
+ </init-params>
+</component>
+ ]]>
+ </programlisting>
+ <para>
+ The way that the import strategy works with the import mode will be clearly demonstrated in next sections for each type of data.
+ </para>
+ </section>
+ <section id="sect-Reference_Guide-Data_Import_Strategy-Data_Import_Strategy">
+ <title>Data Import Strategy</title>
+ <para>
+ The 'Portal Data' term which has been referred in the previous sections can be
+ classified into three types of object data: Portal Config, Page Data and
+ Navigation Data; each of which has some differences in the import strategy.
+ </para>
+ <section id="sect-Reference_Guide-Data_Import_Strategy-Data_Import_Strategy-Navigation_Data">
+ <title>Navigation Data</title>
+ <para>
+ The navigation data import strategy will be processed to the import mode level as the followings:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>CONSERVE</literal>: If the navigation exists, leave it untouched. Otherwise, import data.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>INSERT</literal>: Insert the missing description data, but add only new nodes. Other modifications remains untouched.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>MERGE</literal>: Merge the description data, add missing nodes and update same name nodes.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>OVERWRITE</literal>: Always destroy the previous data and recreate it.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ In the GateIn navigation structure, each navigation can be referred
+ to a tree which each node links to a page content. Each node contains some
+ description data, such as label, icon, page reference, and more. Therefore, GateIn
+ provides a way to insert or merge new data to the initiated navigation tree or a
+ sub-tree.
+ </para>
+ <para>
+ The merge strategy performs the recursive comparison of child nodes between the
+ existing persistent nodes of a navigation and the transient nodes provided by
+ a descriptor:
+ </para>
+ <procedure id="proc-Reference_Guide-Merge_Strategy">
+ <step>
+ <para>
+ Start with the root nodes (which is the effective root node or another node if the parent URI is specified).
+ </para>
+ </step>
+ <step>
+ <para>
+ Compare the set of child nodes and insert the missing nodes in the persistent nodes.
+ </para>
+ </step>
+ <step>
+ <para>
+ Proceed recursively for each child having the same name.
+ </para>
+ </step>
+ </procedure>
+ <para>
+ Let's see the example with two navigation nodes in each import mode. In this case, there are 2 navigation definitions:
+ </para>
+<programlisting language="XML" role="XML"><![CDATA[<node-navigation>
+ <page-nodes>
+ <node>
+ <name>foo</name>
+ <icon>foo_icon_1</icon>
+ <node>
+ <name>juu</name>
+ <icon>juu_icon</icon>
+ </node>
+ </node>
+ <node>
+ <name>daa</name>
+ <icon>daa_icon</icon>
+ </node>
+ </page-nodes>
+</node-navigation>]]></programlisting>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/DataImportStrategy/navigation1.png" format="PNG" align="center"/>
+ </imageobject>
+ </mediaobject>
+<programlisting language="XML" role="XML"><![CDATA[<node-navigation>
+ <page-nodes>
+ <node>
+ <name>foo</name>
+ <icon>foo_icon_2</icon>
+ </node>
+ <node>
+ <name>bar</name>
+ <icon>bar_icon</icon>
+ </node>
+ </page-nodes>
+</node-navigation>]]></programlisting>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/DataImportStrategy/navigation2.png" format="PNG" align="center"/>
+ </imageobject>
+ </mediaobject>
+ <para>
+ For example, the <emphasis>navigation1</emphasis> is loaded before <emphasis>navigation2</emphasis>. The Navigation
+ Importer processes on two navigation definitions, depending on the Import Mode defined in portal configuration.
+ </para>
+ <variablelist>
+ <title>Import Mode Cases</title>
+ <varlistentry>
+ <term>Case 1: <literal>CONSERVE</literal></term>
+ <listitem>
+ <para>
+ With the <literal>CONSERVE</literal> mode, data are only imported when they do not exist. So, if
+ the navigation has been created by the <emphasis>navigation1</emphasis> definition, the <emphasis>navigation2</emphasis> definition
+ does not affect anything on it. We have the result as following
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/DataImportStrategy/navigation1.png" format="PNG" align="center"/>
+ </imageobject>
+ </mediaobject>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Case 2: <literal>INSERT</literal></term>
+ <listitem>
+ <para>
+ If a node does not exist, the importer will add new nodes to the navigation tree. You will see the following result:
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/DataImportStrategy/navigation_insert.png" format="PNG" align="center"/>
+ </imageobject>
+ </mediaobject>
+ <para>
+ Hereafter, the node 'bar' is added to the navigation tree, because it does not exist in the initiated data.
+ Other nodes are kept in the import process.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Case 3: <literal>MERGE</literal></term>
+ <listitem>
+ <para>
+ The <literal>MERGE</literal> mode indicates that a new node is added to the navigation tree, and
+ updates the node data (such node label and node icon in the example) if it exists.
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/DataImportStrategy/navigation_merge.png" format="PNG" align="center"/>
+ </imageobject>
+ </mediaobject>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Case 4: <literal>OVERWRITE</literal></term>
+ <listitem>
+ <para>
+ Everything will be destroyed and replaced with new data if the <literal>OVERWRITE</literal> mode is used.
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/DataImportStrategy/navigation2.png" format="PNG" align="center"/>
+ </imageobject>
+ </mediaobject>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+
+ <section id="sect-Reference_Guide-Data_Import_Strategy-Data_Import_Strategy-Portal_Config">
+ <title>Portal Config</title>
+ <para>
+ PortalConfig defines the portal name, permission, layout and some properties
+ of a site. These information are configured in the <emphasis>portal.xml</emphasis>, <emphasis>group.xml</emphasis> or
+ <emphasis>user.xml</emphasis>, depending on the site type. The PortalConfig importer performs a strategy
+ that is based on the mode defined in NewPortalConfigListener, including <literal>CONSERVE</literal>,
+ <literal>INSERT</literal>, <literal>MERGE</literal> or <literal>OVERWRITE</literal>. Let's see how the import mode affects in the process of
+ portal data performance:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>CONSERVE</literal>: There is nothing to be imported. The existing data will be kept without any changes.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>INSERT</literal>: When the portal config does not exist, create the new portal defined by the portal config definition. Otherwise, do nothing.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>MERGE</literal> and <literal>OVERWRITE</literal> have the same behavior. The new portal config will be created if it does not exist or update portal properties defined by the portal config definition.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section id="sect-Reference_Guide-Data_Import_Strategy-Data_Import_Strategy-Page_Data">
+ <title>Page Data</title>
+ <para>
+ The import mode affects the page data import as the same as Portal Config.
+ </para>
+ <note>
+ <para>
+ If the Import mode is <literal>CONSERVE</literal> or <literal>INSERT</literal>, the data import strategy always performs
+ as the <literal>MERGE</literal> mode in the first data initialization of the Portal.
+ </para>
+ </note>
+ </section>
+ </section>
+</chapter>
Added: epp/docs/branches/5.2/Reference_Guide-eXoJCR-1.14/en-US/modules/PortalDevelopment/NavigationController.xml
===================================================================
--- epp/docs/branches/5.2/Reference_Guide-eXoJCR-1.14/en-US/modules/PortalDevelopment/NavigationController.xml (rev 0)
+++ epp/docs/branches/5.2/Reference_Guide-eXoJCR-1.14/en-US/modules/PortalDevelopment/NavigationController.xml 2011-10-19 05:45:35 UTC (rev 7776)
@@ -0,0 +1,676 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "<literal>http</literal>://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % BOOK_ENTITIES SYSTEM "../../Reference_Guide.ent">
+%BOOK_ENTITIES;
+]>
+<chapter id="chap-Reference_Guide-Navigation_Controller">
+ <title>Navigation Controller </title>
+ <section id="sect-Reference_Guide-Navigation_Controller-Description">
+ <title>Description</title>
+ <para>The navigation controller is a major enhancement of JBoss Enterprise Portal Platform that has several goals:</para>
+ <itemizedlist>
+ <listitem>
+ <para>Provide non ambiguous URLs for portal managed resources such as navigation. Previously different resources were possible for a single URL, even worse, the set of resources available for an URL was depending on one's private navigation (groups and dashboard)</para>
+ </listitem>
+ <listitem>
+ <para>Decouple the <literal>http</literal> request from the portal request. Previously both were tightly coupled, for instance the URL for a site had to begin with <uri>/public/{sitename}</uri> or <uri>/private/{sitename}</uri>. The navigation controller provides a flexible and configurable mapping.</para>
+ </listitem>
+ <listitem>
+ <para>Provide more friendly URL and give a degree of freedom for portal administrators by letting them configure how <literal>http</literal> request should look.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section id="sect-Reference_Guide-Navigation_Controller-Controller_in_Action">
+ <title>Controller in Action</title>
+ <section id="sect-Reference_Guide-Navigation_Controller-Controller_in_Action-Controller">
+ <title>Controller</title>
+ <para>The <application>WebAppController</application> is the component of JBoss Enterprise Portal Platform that process <literal>http</literal> invocations and transforms them into a portal request. It has been improved with the addition of a request mapping engine (<emphasis role="bold">controller</emphasis>) whose role is to make the decoupling of the <literal>http</literal> request and create a portal request.
+ </para>
+ <para>
+ The mapping engine makes two essential tasks:</para>
+ <itemizedlist>
+ <listitem>
+ <para>Create a Map<QualifiedName, String> from an incoming <literal>http</literal> request</para>
+ </listitem>
+ <listitem>
+ <para>Render a Map<QualifiedName, String> as an <literal>http</literal> URL</para>
+ </listitem>
+ </itemizedlist>
+ <para>The goal of the controller (mapping engine) is to <emphasis role="bold">decouple</emphasis> the request processed by JBoss Enterprise Portal Platform from the incoming <literal>HTTP</literal> request.
+ </para>
+ <para>
+ Indeed a request contain data that determines how the request will be processed and such data can be encoded in various places in the request such as the request path or a query parameter. The controller allows JBoss Enterprise Portal Platform route a request according to a set of parameters (a map) instead of the servlet request.</para>
+ <para>
+ The controller configuration is declarative in an XML file, allowing easy reconfiguration of the routing table and it is processed into an internal data structure that is used to perform resolution (routing or rendering)</para>
+ </section>
+ <section id="sect-Reference_Guide-Navigation_Controller-Controller_in_Action-Building_Controller">
+ <title>Building Controller</title>
+ <para>The controller configuration that contains the routing rules is loaded from a file named <filename>controller.xml</filename> that is retrieved in the JBoss Enterprise Portal Platform configuration directory. Its location is determined by the <parameter>gatein.controller.config</parameter> property.</para>
+ <para>
+ <application>WebAppController</application> loads and initializes the mapping engine</para>
+
+<programlisting language="XML"><![CDATA[
+<!-- conf/portal/controller-configuration.xml of portal.war -->
+<component>
+ <type>org.exoplatform.web.WebAppController</type>
+ <init-params>
+ <value-param>
+ <name>controller.config</name>
+ <value>${gatein.portal.controller.config}</value>
+ </value-param>
+ </init-params>
+</component>
+]]></programlisting>
+
+ <para>JBoss Enterprise Portal Platform's extension project can define their own routing table, because of the extension mechanism.</para>
+ <para>The <filename>controller.xml</filename> can be changed and reloaded at runtime, this helps the testing of different configurations easily (configuration loading operations) and provide more insight into the routing engine (the <literal>findRoutes</literal> operation). see <emphasis role="bold">Rebuiding controller</emphasis> for more detail</para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="bold">ReBuilding controller</emphasis>
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>The <application>WebAppController</application> is annotated with <code>@Managed</code> annotations and is bound under the <code>view=portal,service=controller</code> JMX name and under the "portalcontroller" REST name.</para>
+ <para>It provides the following attributes and operations</para>
+ <itemizedlist>
+ <listitem>
+ <para>Attribute configurationPath : the read only the configuration path of the controller xml file</para>
+ </listitem>
+ <listitem>
+ <para>Operation loadConfiguration : load a new configuration file from a specified xml path</para>
+ </listitem>
+ <listitem>
+ <para>Operation reloadConfiguration : reload the configuration file</para>
+ </listitem>
+ <listitem>
+ <para>Operation findRoutes : route the request argument through the controller and returns a list of all parameter map resolution. The argument is a request uri such as "/groups/:platform:administrators/administration/registry". It returns a string representation (<code>List<Map></code>) of the matched routes.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section>
+ <title>Controller Configuration (controller.xml)</title>
+ <para>Most of the controller configuration cares about defining rules (Routing table - contains routes object) that will drive the resolution. Routes are processed during the controller initialization to give a tree of node. Each node</para>
+ <itemizedlist>
+ <listitem>
+ <para>is related to its parent with a matching rule that can either be an <emphasis role="bold">exact string matching</emphasis> or a <emphasis role="bold">regular expression matching</emphasis>
+ </para>
+ </listitem>
+ <listitem>
+ <para>is associated with a set of parameters</para>
+ </listitem>
+ </itemizedlist>
+ <para>A parameter is defined by a qualified name and there are three kind of parameters</para>
+ <section>
+ <title>
+ <emphasis role="bold">Route parameters</emphasis>
+ </title>
+ <para>Route parameters defines a fixed value associate with a qualified name.</para>
+ <itemizedlist>
+ <listitem>
+ <para>Routing: route parameters allow the controller to distinguish branches easily and route the request accordingly.</para>
+ </listitem>
+ <listitem>
+ <para>Rendering: selection occurs when always.</para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ <emphasis role="bold">Example:</emphasis>
+ </para>
+<programlisting language="XML"><![CDATA[
+<route path="/foo">
+ <route-param qname="gtn:handler">
+ <value>portal</value>
+ </route-param>
+</route>
+]]></programlisting>
+ <para>This configuration matches the request path "/foo" to the map (gtn:handler=portal). Conversely it renders the (gtn:handler=portal) map as the "/foo" URL. In this example we see two concepts</para>
+ <itemizedlist>
+ <listitem>
+ <para>exact path matching ("/foo")</para>
+ </listitem>
+ <listitem>
+ <para>route parameters ("gtn:handler")</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section>
+ <title>
+ <emphasis role="bold">Path parameters - <emphasis role="italic">Regular expression support</emphasis>
+ </emphasis>
+ </title>
+ <para>Path parameters allow to associate a portion of the request path with a parameter. Such parameter will match any non empty portion of text except the <emphasis role="bold">/</emphasis> character (that is the [^/]+ regular expression) otherwise they can be associated with a regular expression for matching specific patterns. Path parameters are mandatory for matching since they are part of the request path, however it is allowed to write regular expression matching an empty value.</para>
+ <itemizedlist>
+ <listitem>
+ <para>Routing: route is accepted if the regular expression is matched.</para>
+ </listitem>
+ <listitem>
+ <para>Rendering: selection occurs when the regular expression matches the parameter.</para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ <emphasis role="bold">Encoding</emphasis>
+ </para>
+ <para>Path parameters may contain '/' character which is a reserved char for URI path. This case is specially handled by the navigation controller by using a special character to replace '/' literals. By default the character is the semi colon <emphasis role="bold">:</emphasis> and can be changed to other possible values (see controller XML schema for possible values) to give a greater amount of flexibility.</para>
+ <para>This encoding is applied only when the encoding performed for parameter having a mode set to the <code>default-form</code> value, for instance it does not happen for navigation node URI (for which <emphasis role="bold">/</emphasis> are encoded literally). The separator escape char can still be used but under it's percent escaped form, so by default a path parameter value containing <emphasis role="bold">:</emphasis> would be encoded as <code>%3A</code> and conversely the <code>%3A</code> value will be decoded as <emphasis role="bold">:</emphasis>.</para>
+ <para>
+ <emphasis role="bold">Example:</emphasis>
+ </para>
+<programlisting language="XML"><![CDATA[
+<route path="/{gtn:path}">
+</route>
+]]></programlisting>
+ <para>No pattern defined, used the default one [^/]+</para>
+<programlisting><![CDATA[
+Routing and Rendering
+Path "/foo" <--> the map (gtn:path=foo)
+
+Path "/foo:bar" <--> the map (gtn:path=foo/bar)
+]]></programlisting>
+ <para>If the request path contains another "/" char it will not work,default encoding mode is : <emphasis role="bold">default-form</emphasis>. For example:"/foo/bar" --> not matched, return empty parameter map</para>
+ <para>However this could be solved with the following configuration:</para>
+<programlisting language="XML"><![CDATA[
+<route path="/{gtn:path}">
+ <path-param encoding="preserve-path" qname="gtn:path">
+ <pattern>.*</pattern>
+ </path-param>
+</route>
+]]></programlisting>
+ <orderedlist>
+ <listitem>
+ <para>The .* declaration allows to match any char sequence.</para>
+ </listitem>
+ <listitem>
+ <para>The <emphasis role="italic">preserve-path</emphasis> <emphasis role="bold">encoding</emphasis> tells the engine that the "/" chars should be handled by the path parameter itself as they have a special meaning for the router. Without this special encoding, "/" would be rendered as the ":<emphasis role="italic">" character and conversely the ":</emphasis>" character would be matched as the "/" character.</para>
+ </listitem>
+ </orderedlist>
+ </section>
+ <section>
+ <title>Request parameters</title>
+ <para>Request parameters are matched from the request parameters (GET or POST). The match can be optional as their representation in the request allows it.</para>
+ <itemizedlist>
+ <listitem>
+ <para>Routing</para>
+ <itemizedlist>
+ <listitem>
+ <para>route is accepted when a required parameter is present and matched in the request.</para>
+ </listitem>
+ <listitem>
+ <para>route is accepted when an optional parameter is absent or matched in the request.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ <listitem>
+ <para>Rendering:</para>
+ <itemizedlist>
+ <listitem>
+ <para>selection occurs for required parameters when is the parameter is present and matched in the map.</para>
+ </listitem>
+ <listitem>
+ <para>selection occurs for optional parameters when is the parameter is absent or matched in the map.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+ <para>
+ <emphasis role="bold">Example:</emphasis>
+ </para>
+<programlisting language="XML"><![CDATA[
+<route path="/">
+ <request-param name="path" qname="gtn:path"/>
+</route>
+]]></programlisting>
+ <para>Request parameters are declared by a <code>request-param</code> element and by default will match any value. A request like "/?path=foo" is mapped to the (gtn:path=foo) map. The <code>name</code> attribute of the <code>request-param</code> tag defines the request parameter value. This element accepts more configuration</para>
+ <itemizedlist>
+ <listitem>
+ <para>a <code>value</code> or a <code>pattern</code> element a child element to match a constant or a pattern</para>
+ </listitem>
+ <listitem>
+ <para>a <code>control-mode</code> attribute with the value <code>optional</code> or <code>required</code> to indicate if matching is mandatory or not</para>
+ </listitem>
+ <listitem>
+ <para>a <code>value-mapping</code> attribute with the possible values <code>canonical</code>, <code>never-empty</code>, <code>never-null</code> can be used to filter filter values after matching is done. For instance a parameter configured with <code>value-mapping="never-empty"</code> and matching the empty string value will not put the empty string in the map.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section>
+ <title>Route precedence</title>
+ <para>The order of route declaration is important as it influence how rules are matched. Sometimes the same request could be matched by several routes and the routing table is ambiguous.</para>
+<programlisting language="XML"><![CDATA[
+<route path="/foo">
+ <route-param qname="gtn:handler">
+ <value>portal</value>
+ </route-param>
+</route>
+<route path="/{gtn:path}">
+ <path-param encoding="preserve-path" qname="gtn:path">
+ <pattern>.*</pattern>
+ </path-param>
+</route>
+]]></programlisting>
+ <para>In that case, the request path "/foo" will always be matched by the first rule before the second rule. This can be misleading since the map (gtn:path=foo) would be rendered as "/foo" as well and would not be matched by the first rule. Such ambiguit can happen, it can be desirable or not.</para>
+ </section>
+ <section>
+ <title>Route nesting</title>
+ <para>Route nesting is possible and often desirable as it helps to</para>
+ <itemizedlist>
+ <listitem>
+ <para>factor common parameters in a common rule</para>
+ </listitem>
+ <listitem>
+ <para>perform more efficient matching as the match of the common rule is done once for all the sub routes</para>
+ </listitem>
+ </itemizedlist>
+<programlisting language="XML"><![CDATA[
+<route path="/foo">
+ <route-param qname="gtn:handler">
+ <value>portal</value>
+ </route-param>
+ <route path="/bar">
+ <route-param qname="gtn:path">
+ <value>bar</value>
+ </route-param>
+ </route>
+ <route path="/juu">
+ <route-param qname="gtn:path">
+ <value>juu</value>
+ </route-param>
+ </route>
+</route>
+]]></programlisting>
+ <itemizedlist>
+ <listitem>
+ <para>The request path "/foo/bar" is mapped to the (gtn:handler=portal,gtn:path=bar) map</para>
+ </listitem>
+ <listitem>
+ <para>The request path "/foo/juu" is mapped to the (gtn:handler=portal,gtn:path=juu) map</para>
+ </listitem>
+ <listitem>
+ <para>The request path "/foo" is not mapped as non leaf routes do not perform matches.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ </section>
+ </section>
+ <section>
+ <title>Integrate to JBoss Enterprise Portal Platform WebUI framework</title>
+ <section>
+ <title>Routing</title>
+ <para>JBoss Enterprise Portal Platform defines a set of parameters in its routing table, for each client request, the mapping engine processes the request path and return the defined parameters with their values as a Map<QualifiedName, String></para>
+ <para>
+ <emphasis role="bold">gtn:handler</emphasis>
+ </para>
+ <para>The gtn:handler names is one of the most important qualified name as it determines which handler will take care of the request processing just after the controller has determined the parameter map. The handler value is used to make a lookup in the handler map of the controller. An handler is a class that extends the <code>WebRequestHandler</code> class and implements the <code>execute(ControllerContext)</code> method. Several handlers are available by default:</para>
+ <itemizedlist>
+ <listitem>
+ <para>portal : process aggregated portal requests</para>
+ </listitem>
+ <listitem>
+ <para>upload / download : process file upload and file download</para>
+ </listitem>
+ <listitem>
+ <para>legacy : handle legacy URL redirection (see <emphasis role="bold">Legacy handler</emphasis> section)</para>
+ </listitem>
+ <listitem>
+ <para>default : <literal>http</literal> redirection to the default portal of the container</para>
+ </listitem>
+ <listitem>
+ <para>staticResource: serve static resources like image, css or javascript... files in portal.war (see <emphasis role="bold">Static Resource Handler</emphasis> section)</para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ <emphasis role="bold">gtn:sitetype / gtn:sitename / gtn:path</emphasis>
+ </para>
+ <para>Those qualified names drives a request for the portal handler. They are used to determine which site to show and which path to resolve against a navigation. For instance the (gtn:sitetype=portal,gtn:sitename=classic,gtn:path=home) instruct the portal handler to show the home page of the classic portal site.</para>
+ <para>
+ <emphasis role="bold">gtn:lang</emphasis>
+ </para>
+ <para>The language in the URL for the portal handler. This is a new feature offered, now language can be specified on URL. that mean user can bookmark that URL (with the information about language) or he can changed language simply by modifying the URL address</para>
+ <para>
+ <emphasis role="bold">gtn:componentid / gtn:action / gtn:objectid</emphasis>
+ </para>
+ <para>The webui parameters used by the portal handler for managing webui component URLs for portal applications (and not for portlet applications).</para>
+ </section>
+ <section>
+ <title>Rendering</title>
+ <para>The <emphasis role="bold">controller</emphasis> is designed to render a Map<QualifiedName, String> as an <literal>http</literal> URL according to its routing table. But to integrate it for using easily in WebUI Framework of JBoss Enterprise Portal Platform, we need some more components</para>
+ <section>
+ <title>
+ <emphasis role="bold">PortalURL</emphasis>
+ </title>
+ <para>
+ <code>PortalURL</code> play a similar role at the portal level, its main role is to abstract the creation of an URL for a resource managed by the portal.</para>
+<programlisting language="Java"><![CDATA[
+public abstract class PortalURL<R, U extends PortalURL<U>>
+{
+ ...
+}
+]]></programlisting>
+ <para>The <code>PortalURL</code> declaration may seem a bit strange at first sight with two generic types <code>U</code> and <code>R</code> and the circular recursion of the <code>U</code> generic parameter, but it's because most of the time you will not use the <code>PortalURL</code> object but instead subclasses.</para>
+ <itemizedlist>
+ <listitem>
+ <para>The <code>R</code> generic type represents the type of the resource managed by the portal</para>
+ </listitem>
+ <listitem>
+ <para>The <code>U</code> generic type is also described as <emphasis role="bold">self bound generic type</emphasis>. This design pattern allows a class to return subtypes of itself in the class declaring the generic type. Java Enums are based on this principle (<code>class Enum<E extends Enum<E>></code>)</para>
+ </listitem>
+ </itemizedlist>
+ <para>A portal URL has various methods but certainly the most important method is the <code>toString()</code> method that generates an URL representing that will target the resource associated with the URL. The remaining methods are getter and setter for mutating the URL configuration, those options will affect the URL representation when it is generated.</para>
+ <itemizedlist>
+ <listitem>
+ <para>resource : the mandatory resource associated with the URL</para>
+ </listitem>
+ <listitem>
+ <para>locale : the optional locale used in the URL allowing the creation of bookmarkable URL containing a language</para>
+ </listitem>
+ <listitem>
+ <para>confirm : the optional confirm message displayed by the portal in the context of the portal UI</para>
+ </listitem>
+ <listitem>
+ <para>ajax : the optional ajax option allowing an ajax invocation of the URL</para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ <emphasis role="bold">Obtaining a PortalURL</emphasis>
+ </para>
+ <para>
+ <code>PortalURL</code> objects are obtained from <code>RequestContext</code> instance such as the <code>PortalRequestContext</code> or the PortletRequestContext. Usually those are obtained thanks to <code>getCurrentInstance</code> method of the <code>RequestContext</code> class:</para>
+<programlisting language="Java"><![CDATA[
+RequestContext ctx = RequestContext.getCurrentInstance();
+]]></programlisting>
+ <para>
+ <code>PortalURL</code> are created via to the <code>createURL</code> method that takes as input a resource type. A resource type is usually a constant and is a type safe object that allow to retrieve <code>PortalURL</code> subclasses:</para>
+<programlisting language="Java"><![CDATA[
+RequestContext ctx = RequestContext.getCurrentInstance();
+PortalURL<R, U> URL = ctx.createURL(type);
+]]></programlisting>
+ <para>In reality you will use a concrete type constant and have instead more concrete code like:</para>
+<programlisting language="Java"><![CDATA[
+RequestContext ctx = RequestContext.getCurrentInstance();
+NodeURL URL = ctx.createURL(NodeURL.TYPE);
+]]></programlisting>
+ <note>
+ <para>The <code>NodeURL.TYPE</code> is actually declared as <code>new ResourceType<NavigationResource, NodeURL>()</code> that can be described as a <emphasis role="bold">type literal</emphasis> object emulated by a Java anonymous inner class. Such literal were introduced by Neil Gafter as Super Type Token and popularized by Google Guice as Type Literal. It's an interesting way to create a literal representing a kind of Java type.</para>
+ </note>
+ </section>
+ <section>
+ <title>
+ <emphasis role="bold">Node URL</emphasis>
+ </title>
+ <para>The class <code>NodeURL</code> is one of the subclass of <code>PortalURL</code> that is specialized for navigation node resources:</para>
+<programlisting language="Java"><![CDATA[
+public class NodeURL extends PortalURL<NavigationResource, NodeURL>
+{
+ ...
+}
+]]></programlisting>
+ <para>The good news is that the NodeURL does not carry any generic type of its super class, which means that a NodeURL is type safe and one does not have to worry about generic types.</para>
+ <para>Using a NodeURL is pretty straightforward:</para>
+<programlisting language="Java"><![CDATA[
+NodeURL URL = RequestContext.getCurrentInstance().createURL(NodeURL.TYPE);
+URL.setResource(new NavigationResource("portal", "classic, "home"));
+String s = URL.toString();
+]]></programlisting>
+ <para>The <code>NodeURL</code> subclass contains specialized setter to make its usage even easier:</para>
+<programlisting language="Java"><![CDATA[
+UserNode node = ...;
+NodeURL URL = RequestContext.getCurrentInstance().createURL(NodeURL.TYPE);
+URL.setNode(node);
+String s = URL.toString();
+]]></programlisting>
+ </section>
+ <section>
+ <title>
+ <emphasis role="bold">Component URL</emphasis>
+ </title>
+ <para>The <code>ComponentURL</code> subclass is another specialization of <code>PortalURL</code> that allows the creation of WebUI components URLs. <code>ComponentURL</code> is commonly used to trigger WebUI events from client side:</para>
+<programlisting><![CDATA[
+<% def componentURL = uicomponent.event(...); /*or uicomponent.URL(...) */ %>
+ <a href=$componentURL>Click me</a>
+]]></programlisting>
+ <para>Normally you should not have to deal with it as the WebUI framework has already an abstraction for managing URL known as <code>URLBuilder</code>. The <code>URLBuilder</code> implementation delegates URL creation to <code>ComponentURL</code> objects.</para>
+ </section>
+ <section>
+ <title>Portlet URLs</title>
+ <para>Portlet URLs API implementation delegates to the portal <code>ComponentURL</code> (via the portlet container SPI). It is possible to control the language in the URL from a <code>PortletURL</code> object by setting a property named <code>gtn:lang</code>:</para>
+ <itemizedlist>
+ <listitem>
+ <para>when the property value is set to a value returned by <code>Locale#toString()</code> method for locale objects having a non null language value and a null variant value, the URL generated by the <code>PortletURL#toString()</code> method will contain the locale in the URL.</para>
+ </listitem>
+ <listitem>
+ <para>when the property value is set to an empty string, the generated URL will not contain a language. If the incoming URL was carrying a language, this language will be erased.</para>
+ </listitem>
+ <listitem>
+ <para>when the property value is not set, it will not affect the generated URL.</para>
+ </listitem>
+ </itemizedlist>
+<programlisting language="Java"><![CDATA[
+PortletURL URL = resp.createRenderURL();
+URL.setProperty("gtn:lang", "fr");
+writer.print("<a href='" + URL + "'>French</a>");
+]]></programlisting>
+ </section>
+ <section>
+ <title>Webui <code>URLBuilder</code>
+ </title>
+ <para>This internal API for creating URL works as before and delegates to the <code>PortletURL</code> API when the framework is executed in a portlet and to a <code>ComponentURL</code> API when the framework is executed in the portal context. The API has been modified to take in account the language in URL with two properties on the builder:</para>
+ <itemizedlist>
+ <listitem>
+ <para>locale : a locale for setting on the URL</para>
+ </listitem>
+ <listitem>
+ <para>removeLocale : a boolean for removing the locale present on the URL</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section>
+ <title>Groovy Templates</title>
+ <para>Within a Groovy template the mechanism is the same, however a splash of integration has been done to make creation of NodeURL simpler. A closure is bound under the <code>nodeurl</code> name and is available for invocation anytime. It will simply create a NodeURL object and return it:</para>
+<programlisting language="Java"><![CDATA[
+UserNode node = ...;
+NodeURL URL = nodeurl();
+URL.setNode(node);
+String s = URL.toString();
+]]></programlisting>
+ <para>The closure <code>nodeurl</code> is bound to Groovy template in <code>WebuiBindingContext</code>
+ </para>
+<programlisting language="Java"><![CDATA[
+// Closure nodeurl()
+put("nodeurl", new Closure(this)
+{
+ @Override
+ public Object call(Object[] args)
+ {
+ return context.createURL(NodeURL.TYPE);
+ }
+});
+]]></programlisting>
+ </section>
+ </section>
+ </section>
+ <section>
+ <title>Changes and migration from JBoss Enterprise Portal Platform 3.1.x</title>
+ <para>The navigation controller implies a migration of the client code that is coupled to several internal APIs of JBoss Enterprise Portal Platform. As far as we know the major impact is related to anything dealing with URL:</para>
+ <itemizedlist>
+ <listitem>
+ <para>Creation of an URL representing a resource managed by the portal: navigation node or ui component.</para>
+ </listitem>
+ <listitem>
+ <para>Using <literal>http</literal> request related information</para>
+ </listitem>
+ </itemizedlist>
+ <para>There are also changes in the configuration, because there is a change of how things are internally.</para>
+ <section>
+ <title>Migration of navigation node URL</title>
+ <para>
+ <emphasis role="bold">Using free form node</emphasis>
+ </para>
+ <para>Previously code for creating navigation node was like:</para>
+<programlisting language="Java"><![CDATA[
+String uri = Util.getPortalRequestContext().getPortalURI() + "home";
+]]></programlisting>
+ <para>The new code will look like</para>
+<programlisting language="Java"><![CDATA[
+PortalURL nodeURL = nodeurl();
+NavigationResource resource = new NavigationResource(SiteType.PORTAL, pcontext.getPortalOwner(), "home");
+String uri = nodeURL.setResource(resource).toString();
+]]></programlisting>
+ <para>
+ <emphasis role="bold">Using UserNode object</emphasis>
+ </para>
+<programlisting language="Java"><![CDATA[
+UserNode node = ...;
+String uri = Util.getPortalRequestContext().getPortalURI() + node.getURI()";
+]]></programlisting>
+ <para>The new code will look like</para>
+
+<programlisting language="Java"><![CDATA[
+UserNode node = ...;
+PortalURL nodeURL = nodeurl();
+String uri = nodeURL.setNode(node).toString();
+]]></programlisting>
+ </section>
+ <section>
+ <title>Security changes</title>
+ <para>Security configuration change in order to keep with the flexibility added by the navigation controller. In particular the authentication does not depend anymore on path specified in <code>web.xml</code> but instead rely on the security mandated by the underlying resource. Here are the noticeable changes for security</para>
+ <itemizedlist>
+ <listitem>
+ <para>Authentication is now triggered on the /login URL when it does not have a username or a password specified. Therefore the URL <code>/login?initialURI=/classic/home</code> is (more or less) equivalent to <code>/private/classic/home</code>
+ </para>
+ </listitem>
+ <listitem>
+ <para>When a resource cannot be viewed due to security constraint</para>
+ <itemizedlist>
+ <listitem>
+ <para>If the user is not logged, the authentication will be triggered</para>
+ </listitem>
+ <listitem>
+ <para>Otherwise a special page (the usual one) will be displayed instead</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section>
+ <title>Default handler</title>
+ <para>Redirection to the default portal used to be done by the <code>index.jsp</code> JSP page. This is not the case anymore, the index.jsp has been removed and the welcome file in <code>web.xml</code> was removed too. Instead a specific handler in the routing table has been configured, the sole role of this handler is to redirect the request to default portal when no other request has been matched previously:</para>
+
+<programlisting language="XML"><![CDATA[
+<controller>
+ ...
+ <route path="/">
+ <route-param qname="gtn:handler">
+ <value>default</value>
+ </route-param>
+ </route>
+</controller>
+]]></programlisting>
+ </section>
+ <section>
+ <title>Legacy handler</title>
+ <para>Legacy URLs such as <code>/public/...</code> and <code>/private/...</code> are now emulated to determine the best resource with the same resolution algorithm than before but instead of displaying the page, will make an <literal>http</literal> 302 redirection to the correct URL. This handler is present in the controller configuration. There is a noticeable difference between the two routes</para>
+ <itemizedlist>
+ <listitem>
+ <para>The public redirection attempt to find a node with the legacy resolution algorithm without authentication, which means that secured nodes will not be resolved and the redirection of a secured node will likely redirect to another page. For instance resolving the URL /public/classic/administration/registry path will likely resolve to another node if the user is not authenticated and is not part of the platform administrator group.</para>
+ </listitem>
+ <listitem>
+ <para>The private redirection performs first an authentication before doing the redirection. In that case the /private/classic/administration/registry path will resolve be redirected to the /portal/groups/:platform:administrators/administration/registry page if the user has the sufficient security rights.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section>
+ <title>Static resource handler</title>
+ <para>The "/" mapping for "default" servlet is now replaced by mapping for org.exoplatform.portal.application.PortalController servlet, that mean we need a handler (<emphasis role="bold">org.exoplatform.portal.application.StaticResourceRequestHandler</emphasis>) to serve static resources like image, css or javascript... files in portal.war. And it should be configured, and extended easily. Thanks to the controller.xml. This file can be overridden and can be changed and reloaded at runtime (WebAppController is MBean with some operations such as : reloadConfiguration() ...)</para>
+ <para>Declare StaticResourceHandler in controller.xml</para>
+<programlisting language="XML"><![CDATA[
+<route path="/{gtn:path}">
+ <route-param qname="gtn:handler">
+ <value>staticResource</value>
+ </route-param>
+ <path-param encoding="preserve-path" qname="gtn:path">
+ <pattern>.*\.(jpg|png|gif|ico|css)</pattern>
+ </path-param>
+</route>
+]]></programlisting>
+ <para>And we don't need these kind of following mapping in portal.war's web.xml anymore :</para>
+
+<programlisting language="XML"><![CDATA[
+<servlet-mapping>
+ <servlet-name>default</servlet-name>
+ <URL-pattern>*.jpg</URL-pattern>
+</servlet-mapping>
+...
+]]></programlisting>
+ </section>
+ <section>
+ <title>portal.war's web.xml changes</title>
+ <para>DoLoginServlet declaration</para>
+
+<programlisting language="XML"><![CDATA[
+<servlet>
+ <servlet-name>DoLoginServlet</servlet-name>
+ <servlet-class>org.exoplatform.web.login.DoLoginServlet</servlet-class>
+</servlet>
+<servlet-mapping>
+ <servlet-name>DoLoginServlet</servlet-name>
+ <URL-pattern>/dologin</URL-pattern>
+</servlet-mapping>
+]]></programlisting>
+ <para>Delare <emphasis role="bold">portal servlet</emphasis> as default servlet</para>
+
+<programlisting language="XML"><![CDATA[
+<servlet-mapping>
+ <servlet-name>portal</servlet-name>
+ <URL-pattern>/</URL-pattern>
+</servlet-mapping>
+]]></programlisting>
+ <para>So there are some mapping declaration for portal servlet are unused, we should also remove them: <emphasis role="bold">
+ <emphasis role="italic">/private/* /public/* /admin/* /upload/* /download/*</emphasis>
+ </emphasis>
+ </para>
+ <para>Add some security constraints</para>
+
+<programlisting language="XML"><![CDATA[
+<security-constraint>
+ <web-resource-collection>
+ <web-resource-name>user authentication</web-resource-name>
+ <URL-pattern>/dologin</URL-pattern>
+ <URL-pattern>/groups/*</URL-pattern>
+ <URL-pattern>/users/*</URL-pattern>
+...
+ </web-resource-collection>
+</security-constraint>
+]]></programlisting>
+ <para>We can remove the index.jsp, and its declaration in web.xml now, thank to the Default request handler</para>
+
+<programlisting language="XML"><![CDATA[
+<welcome-file-list>
+ <welcome-file>/index.jsp</welcome-file>
+</welcome-file-list>
+]]></programlisting>
+ </section>
+ <section>
+ <title>Dashboard changes</title>
+ <para>There are several important changes to take in account</para>
+ <itemizedlist>
+ <listitem>
+ <para>dashboard are now bound to a single URL (/users/root by default) and dashboard pages are leaf of this path</para>
+ </listitem>
+ <listitem>
+ <para>dashboard life cycle can be decoupled (create / destroy) from the identity creation in a configurable manner in <code>UserPortalConfigService</code> and exposed in configuration.properties under <code>gatein.portal.idm.createuserportal</code> and <code>gatein.portal.idm.destroyuserportal</code>.</para>
+ </listitem>
+ <listitem>
+ <para>by default dashboard are not created when a user is registered</para>
+ </listitem>
+ <listitem>
+ <para>a dashboard is created when the user access his dashboard URL</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section>
+ <title>Remove unused files</title>
+ <para>1/ portal-unavailable.jsp: this file was presented before if user goes to a non-available portal. Now the server sends a 404 status code instead.</para>
+ <para>2/ portal-warning.jsp: this file is not used in any place</para>
+ </section>
+ </section>
+</chapter>
13 years, 2 months
gatein SVN: r7775 - in epp/docs/branches/5.2/Reference_Guide/en-US: images/DataImportStrategy and 2 other directories.
by do-not-reply@jboss.org
Author: smumford
Date: 2011-10-19 01:44:02 -0400 (Wed, 19 Oct 2011)
New Revision: 7775
Added:
epp/docs/branches/5.2/Reference_Guide/en-US/images/DataImportStrategy/
epp/docs/branches/5.2/Reference_Guide/en-US/images/DataImportStrategy/navigation1.png
epp/docs/branches/5.2/Reference_Guide/en-US/images/DataImportStrategy/navigation2.png
epp/docs/branches/5.2/Reference_Guide/en-US/images/DataImportStrategy/navigation_insert.png
epp/docs/branches/5.2/Reference_Guide/en-US/images/DataImportStrategy/navigation_merge.png
epp/docs/branches/5.2/Reference_Guide/en-US/modules/PortalDevelopment/DataImportStrategy.xml
epp/docs/branches/5.2/Reference_Guide/en-US/modules/PortalDevelopment/NavigationController.xml
Modified:
epp/docs/branches/5.2/Reference_Guide/en-US/modules/PortalDevelopment.xml
Log:
Porting revs 7738,7666,7658 to EPP
Added: epp/docs/branches/5.2/Reference_Guide/en-US/images/DataImportStrategy/navigation1.png
===================================================================
(Binary files differ)
Property changes on: epp/docs/branches/5.2/Reference_Guide/en-US/images/DataImportStrategy/navigation1.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added: epp/docs/branches/5.2/Reference_Guide/en-US/images/DataImportStrategy/navigation2.png
===================================================================
(Binary files differ)
Property changes on: epp/docs/branches/5.2/Reference_Guide/en-US/images/DataImportStrategy/navigation2.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added: epp/docs/branches/5.2/Reference_Guide/en-US/images/DataImportStrategy/navigation_insert.png
===================================================================
(Binary files differ)
Property changes on: epp/docs/branches/5.2/Reference_Guide/en-US/images/DataImportStrategy/navigation_insert.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added: epp/docs/branches/5.2/Reference_Guide/en-US/images/DataImportStrategy/navigation_merge.png
===================================================================
(Binary files differ)
Property changes on: epp/docs/branches/5.2/Reference_Guide/en-US/images/DataImportStrategy/navigation_merge.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added: epp/docs/branches/5.2/Reference_Guide/en-US/modules/PortalDevelopment/DataImportStrategy.xml
===================================================================
--- epp/docs/branches/5.2/Reference_Guide/en-US/modules/PortalDevelopment/DataImportStrategy.xml (rev 0)
+++ epp/docs/branches/5.2/Reference_Guide/en-US/modules/PortalDevelopment/DataImportStrategy.xml 2011-10-19 05:44:02 UTC (rev 7775)
@@ -0,0 +1,290 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % BOOK_ENTITIES SYSTEM "../../Reference_Guide.ent">
+%BOOK_ENTITIES;
+]>
+<chapter id="chap-Reference_Guide-Data_Import_Strategy">
+ <title>Data Import Strategy</title>
+ <section id="sect-Reference_Guide-Data_Import_Strategy-Introduction">
+ <title>Introduction</title>
+ <para>
+ In the Portal extension mechanism, developers can define an extension
+ that Portal data can be customized by configurations in the extension. There
+ are several cases which an extension developer wants to define how to customize the Portal data,
+ for example modifying, overwriting or just inserting a bit into the data defined by the portal.
+ Therefore, GateIn also defines several modes for each case and the only thing which a developer has to do is to clarify the
+ usecase and reasonably configure extensions.
+ </para>
+ <para>
+ This section shows you how data are changes in each mode.
+ </para>
+ </section>
+
+ <section id="sect-Reference_Guide-Data_Import_Strategy-Import_Mode">
+ <title>Import Mode</title>
+ <para>
+ In this section, the following modes for the import strategy are introduced:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>CONSERVE</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>MERGE</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>INSERT</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>OVERWRITE</literal>
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Each mode indicates how the Portal data are imported. The import mode value is
+ set whenever <literal>NewPortalConfigListener</literal> is initiated. If the mode is not set,
+ the default value will be used in this case. The default value is configurable as
+ a UserPortalConfigService initial param. For example, the bellow configuration
+ means that default value is <literal>MERGE</literal>.
+ </para>
+ <programlisting language="XML" role="XML"><![CDATA[
+<component>
+ <key>org.exoplatform.portal.config.UserPortalConfigService</key>
+ <type>org.exoplatform.portal.config.UserPortalConfigService</type>
+ <component-plugins>
+ ............
+ </component-plugins>
+ <init-params>
+ <value-param>
+ <name>default.import.mode</name>
+ <value>merge</value>
+ </value-param>
+ </init-params>
+</component>
+ ]]>
+ </programlisting>
+ <para>
+ The way that the import strategy works with the import mode will be clearly demonstrated in next sections for each type of data.
+ </para>
+ </section>
+ <section id="sect-Reference_Guide-Data_Import_Strategy-Data_Import_Strategy">
+ <title>Data Import Strategy</title>
+ <para>
+ The 'Portal Data' term which has been referred in the previous sections can be
+ classified into three types of object data: Portal Config, Page Data and
+ Navigation Data; each of which has some differences in the import strategy.
+ </para>
+ <section id="sect-Reference_Guide-Data_Import_Strategy-Data_Import_Strategy-Navigation_Data">
+ <title>Navigation Data</title>
+ <para>
+ The navigation data import strategy will be processed to the import mode level as the followings:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>CONSERVE</literal>: If the navigation exists, leave it untouched. Otherwise, import data.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>INSERT</literal>: Insert the missing description data, but add only new nodes. Other modifications remains untouched.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>MERGE</literal>: Merge the description data, add missing nodes and update same name nodes.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>OVERWRITE</literal>: Always destroy the previous data and recreate it.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ In the GateIn navigation structure, each navigation can be referred
+ to a tree which each node links to a page content. Each node contains some
+ description data, such as label, icon, page reference, and more. Therefore, GateIn
+ provides a way to insert or merge new data to the initiated navigation tree or a
+ sub-tree.
+ </para>
+ <para>
+ The merge strategy performs the recursive comparison of child nodes between the
+ existing persistent nodes of a navigation and the transient nodes provided by
+ a descriptor:
+ </para>
+ <procedure id="proc-Reference_Guide-Merge_Strategy">
+ <step>
+ <para>
+ Start with the root nodes (which is the effective root node or another node if the parent URI is specified).
+ </para>
+ </step>
+ <step>
+ <para>
+ Compare the set of child nodes and insert the missing nodes in the persistent nodes.
+ </para>
+ </step>
+ <step>
+ <para>
+ Proceed recursively for each child having the same name.
+ </para>
+ </step>
+ </procedure>
+ <para>
+ Let's see the example with two navigation nodes in each import mode. In this case, there are 2 navigation definitions:
+ </para>
+<programlisting language="XML" role="XML"><![CDATA[<node-navigation>
+ <page-nodes>
+ <node>
+ <name>foo</name>
+ <icon>foo_icon_1</icon>
+ <node>
+ <name>juu</name>
+ <icon>juu_icon</icon>
+ </node>
+ </node>
+ <node>
+ <name>daa</name>
+ <icon>daa_icon</icon>
+ </node>
+ </page-nodes>
+</node-navigation>]]></programlisting>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/DataImportStrategy/navigation1.png" format="PNG" align="center"/>
+ </imageobject>
+ </mediaobject>
+<programlisting language="XML" role="XML"><![CDATA[<node-navigation>
+ <page-nodes>
+ <node>
+ <name>foo</name>
+ <icon>foo_icon_2</icon>
+ </node>
+ <node>
+ <name>bar</name>
+ <icon>bar_icon</icon>
+ </node>
+ </page-nodes>
+</node-navigation>]]></programlisting>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/DataImportStrategy/navigation2.png" format="PNG" align="center"/>
+ </imageobject>
+ </mediaobject>
+ <para>
+ For example, the <emphasis>navigation1</emphasis> is loaded before <emphasis>navigation2</emphasis>. The Navigation
+ Importer processes on two navigation definitions, depending on the Import Mode defined in portal configuration.
+ </para>
+ <variablelist>
+ <title>Import Mode Cases</title>
+ <varlistentry>
+ <term>Case 1: <literal>CONSERVE</literal></term>
+ <listitem>
+ <para>
+ With the <literal>CONSERVE</literal> mode, data are only imported when they do not exist. So, if
+ the navigation has been created by the <emphasis>navigation1</emphasis> definition, the <emphasis>navigation2</emphasis> definition
+ does not affect anything on it. We have the result as following
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/DataImportStrategy/navigation1.png" format="PNG" align="center"/>
+ </imageobject>
+ </mediaobject>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Case 2: <literal>INSERT</literal></term>
+ <listitem>
+ <para>
+ If a node does not exist, the importer will add new nodes to the navigation tree. You will see the following result:
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/DataImportStrategy/navigation_insert.png" format="PNG" align="center"/>
+ </imageobject>
+ </mediaobject>
+ <para>
+ Hereafter, the node 'bar' is added to the navigation tree, because it does not exist in the initiated data.
+ Other nodes are kept in the import process.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Case 3: <literal>MERGE</literal></term>
+ <listitem>
+ <para>
+ The <literal>MERGE</literal> mode indicates that a new node is added to the navigation tree, and
+ updates the node data (such node label and node icon in the example) if it exists.
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/DataImportStrategy/navigation_merge.png" format="PNG" align="center"/>
+ </imageobject>
+ </mediaobject>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Case 4: <literal>OVERWRITE</literal></term>
+ <listitem>
+ <para>
+ Everything will be destroyed and replaced with new data if the <literal>OVERWRITE</literal> mode is used.
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/DataImportStrategy/navigation2.png" format="PNG" align="center"/>
+ </imageobject>
+ </mediaobject>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+
+ <section id="sect-Reference_Guide-Data_Import_Strategy-Data_Import_Strategy-Portal_Config">
+ <title>Portal Config</title>
+ <para>
+ PortalConfig defines the portal name, permission, layout and some properties
+ of a site. These information are configured in the <emphasis>portal.xml</emphasis>, <emphasis>group.xml</emphasis> or
+ <emphasis>user.xml</emphasis>, depending on the site type. The PortalConfig importer performs a strategy
+ that is based on the mode defined in NewPortalConfigListener, including <literal>CONSERVE</literal>,
+ <literal>INSERT</literal>, <literal>MERGE</literal> or <literal>OVERWRITE</literal>. Let's see how the import mode affects in the process of
+ portal data performance:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>CONSERVE</literal>: There is nothing to be imported. The existing data will be kept without any changes.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>INSERT</literal>: When the portal config does not exist, create the new portal defined by the portal config definition. Otherwise, do nothing.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>MERGE</literal> and <literal>OVERWRITE</literal> have the same behavior. The new portal config will be created if it does not exist or update portal properties defined by the portal config definition.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section id="sect-Reference_Guide-Data_Import_Strategy-Data_Import_Strategy-Page_Data">
+ <title>Page Data</title>
+ <para>
+ The import mode affects the page data import as the same as Portal Config.
+ </para>
+ <note>
+ <para>
+ If the Import mode is <literal>CONSERVE</literal> or <literal>INSERT</literal>, the data import strategy always performs
+ as the <literal>MERGE</literal> mode in the first data initialization of the Portal.
+ </para>
+ </note>
+ </section>
+ </section>
+</chapter>
Added: epp/docs/branches/5.2/Reference_Guide/en-US/modules/PortalDevelopment/NavigationController.xml
===================================================================
--- epp/docs/branches/5.2/Reference_Guide/en-US/modules/PortalDevelopment/NavigationController.xml (rev 0)
+++ epp/docs/branches/5.2/Reference_Guide/en-US/modules/PortalDevelopment/NavigationController.xml 2011-10-19 05:44:02 UTC (rev 7775)
@@ -0,0 +1,676 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "<literal>http</literal>://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % BOOK_ENTITIES SYSTEM "../../Reference_Guide.ent">
+%BOOK_ENTITIES;
+]>
+<chapter id="chap-Reference_Guide-Navigation_Controller">
+ <title>Navigation Controller </title>
+ <section id="sect-Reference_Guide-Navigation_Controller-Description">
+ <title>Description</title>
+ <para>The navigation controller is a major enhancement of JBoss Enterprise Portal Platform that has several goals:</para>
+ <itemizedlist>
+ <listitem>
+ <para>Provide non ambiguous URLs for portal managed resources such as navigation. Previously different resources were possible for a single URL, even worse, the set of resources available for an URL was depending on one's private navigation (groups and dashboard)</para>
+ </listitem>
+ <listitem>
+ <para>Decouple the <literal>http</literal> request from the portal request. Previously both were tightly coupled, for instance the URL for a site had to begin with <uri>/public/{sitename}</uri> or <uri>/private/{sitename}</uri>. The navigation controller provides a flexible and configurable mapping.</para>
+ </listitem>
+ <listitem>
+ <para>Provide more friendly URL and give a degree of freedom for portal administrators by letting them configure how <literal>http</literal> request should look.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section id="sect-Reference_Guide-Navigation_Controller-Controller_in_Action">
+ <title>Controller in Action</title>
+ <section id="sect-Reference_Guide-Navigation_Controller-Controller_in_Action-Controller">
+ <title>Controller</title>
+ <para>The <application>WebAppController</application> is the component of JBoss Enterprise Portal Platform that process <literal>http</literal> invocations and transforms them into a portal request. It has been improved with the addition of a request mapping engine (<emphasis role="bold">controller</emphasis>) whose role is to make the decoupling of the <literal>http</literal> request and create a portal request.
+ </para>
+ <para>
+ The mapping engine makes two essential tasks:</para>
+ <itemizedlist>
+ <listitem>
+ <para>Create a Map<QualifiedName, String> from an incoming <literal>http</literal> request</para>
+ </listitem>
+ <listitem>
+ <para>Render a Map<QualifiedName, String> as an <literal>http</literal> URL</para>
+ </listitem>
+ </itemizedlist>
+ <para>The goal of the controller (mapping engine) is to <emphasis role="bold">decouple</emphasis> the request processed by JBoss Enterprise Portal Platform from the incoming <literal>HTTP</literal> request.
+ </para>
+ <para>
+ Indeed a request contain data that determines how the request will be processed and such data can be encoded in various places in the request such as the request path or a query parameter. The controller allows JBoss Enterprise Portal Platform route a request according to a set of parameters (a map) instead of the servlet request.</para>
+ <para>
+ The controller configuration is declarative in an XML file, allowing easy reconfiguration of the routing table and it is processed into an internal data structure that is used to perform resolution (routing or rendering)</para>
+ </section>
+ <section id="sect-Reference_Guide-Navigation_Controller-Controller_in_Action-Building_Controller">
+ <title>Building Controller</title>
+ <para>The controller configuration that contains the routing rules is loaded from a file named <filename>controller.xml</filename> that is retrieved in the JBoss Enterprise Portal Platform configuration directory. Its location is determined by the <parameter>gatein.controller.config</parameter> property.</para>
+ <para>
+ <application>WebAppController</application> loads and initializes the mapping engine</para>
+
+<programlisting language="XML"><![CDATA[
+<!-- conf/portal/controller-configuration.xml of portal.war -->
+<component>
+ <type>org.exoplatform.web.WebAppController</type>
+ <init-params>
+ <value-param>
+ <name>controller.config</name>
+ <value>${gatein.portal.controller.config}</value>
+ </value-param>
+ </init-params>
+</component>
+]]></programlisting>
+
+ <para>JBoss Enterprise Portal Platform's extension project can define their own routing table, because of the extension mechanism.</para>
+ <para>The <filename>controller.xml</filename> can be changed and reloaded at runtime, this helps the testing of different configurations easily (configuration loading operations) and provide more insight into the routing engine (the <literal>findRoutes</literal> operation). see <emphasis role="bold">Rebuiding controller</emphasis> for more detail</para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="bold">ReBuilding controller</emphasis>
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>The <application>WebAppController</application> is annotated with <code>@Managed</code> annotations and is bound under the <code>view=portal,service=controller</code> JMX name and under the "portalcontroller" REST name.</para>
+ <para>It provides the following attributes and operations</para>
+ <itemizedlist>
+ <listitem>
+ <para>Attribute configurationPath : the read only the configuration path of the controller xml file</para>
+ </listitem>
+ <listitem>
+ <para>Operation loadConfiguration : load a new configuration file from a specified xml path</para>
+ </listitem>
+ <listitem>
+ <para>Operation reloadConfiguration : reload the configuration file</para>
+ </listitem>
+ <listitem>
+ <para>Operation findRoutes : route the request argument through the controller and returns a list of all parameter map resolution. The argument is a request uri such as "/groups/:platform:administrators/administration/registry". It returns a string representation (<code>List<Map></code>) of the matched routes.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section>
+ <title>Controller Configuration (controller.xml)</title>
+ <para>Most of the controller configuration cares about defining rules (Routing table - contains routes object) that will drive the resolution. Routes are processed during the controller initialization to give a tree of node. Each node</para>
+ <itemizedlist>
+ <listitem>
+ <para>is related to its parent with a matching rule that can either be an <emphasis role="bold">exact string matching</emphasis> or a <emphasis role="bold">regular expression matching</emphasis>
+ </para>
+ </listitem>
+ <listitem>
+ <para>is associated with a set of parameters</para>
+ </listitem>
+ </itemizedlist>
+ <para>A parameter is defined by a qualified name and there are three kind of parameters</para>
+ <section>
+ <title>
+ <emphasis role="bold">Route parameters</emphasis>
+ </title>
+ <para>Route parameters defines a fixed value associate with a qualified name.</para>
+ <itemizedlist>
+ <listitem>
+ <para>Routing: route parameters allow the controller to distinguish branches easily and route the request accordingly.</para>
+ </listitem>
+ <listitem>
+ <para>Rendering: selection occurs when always.</para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ <emphasis role="bold">Example:</emphasis>
+ </para>
+<programlisting language="XML"><![CDATA[
+<route path="/foo">
+ <route-param qname="gtn:handler">
+ <value>portal</value>
+ </route-param>
+</route>
+]]></programlisting>
+ <para>This configuration matches the request path "/foo" to the map (gtn:handler=portal). Conversely it renders the (gtn:handler=portal) map as the "/foo" URL. In this example we see two concepts</para>
+ <itemizedlist>
+ <listitem>
+ <para>exact path matching ("/foo")</para>
+ </listitem>
+ <listitem>
+ <para>route parameters ("gtn:handler")</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section>
+ <title>
+ <emphasis role="bold">Path parameters - <emphasis role="italic">Regular expression support</emphasis>
+ </emphasis>
+ </title>
+ <para>Path parameters allow to associate a portion of the request path with a parameter. Such parameter will match any non empty portion of text except the <emphasis role="bold">/</emphasis> character (that is the [^/]+ regular expression) otherwise they can be associated with a regular expression for matching specific patterns. Path parameters are mandatory for matching since they are part of the request path, however it is allowed to write regular expression matching an empty value.</para>
+ <itemizedlist>
+ <listitem>
+ <para>Routing: route is accepted if the regular expression is matched.</para>
+ </listitem>
+ <listitem>
+ <para>Rendering: selection occurs when the regular expression matches the parameter.</para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ <emphasis role="bold">Encoding</emphasis>
+ </para>
+ <para>Path parameters may contain '/' character which is a reserved char for URI path. This case is specially handled by the navigation controller by using a special character to replace '/' literals. By default the character is the semi colon <emphasis role="bold">:</emphasis> and can be changed to other possible values (see controller XML schema for possible values) to give a greater amount of flexibility.</para>
+ <para>This encoding is applied only when the encoding performed for parameter having a mode set to the <code>default-form</code> value, for instance it does not happen for navigation node URI (for which <emphasis role="bold">/</emphasis> are encoded literally). The separator escape char can still be used but under it's percent escaped form, so by default a path parameter value containing <emphasis role="bold">:</emphasis> would be encoded as <code>%3A</code> and conversely the <code>%3A</code> value will be decoded as <emphasis role="bold">:</emphasis>.</para>
+ <para>
+ <emphasis role="bold">Example:</emphasis>
+ </para>
+<programlisting language="XML"><![CDATA[
+<route path="/{gtn:path}">
+</route>
+]]></programlisting>
+ <para>No pattern defined, used the default one [^/]+</para>
+<programlisting><![CDATA[
+Routing and Rendering
+Path "/foo" <--> the map (gtn:path=foo)
+
+Path "/foo:bar" <--> the map (gtn:path=foo/bar)
+]]></programlisting>
+ <para>If the request path contains another "/" char it will not work,default encoding mode is : <emphasis role="bold">default-form</emphasis>. For example:"/foo/bar" --> not matched, return empty parameter map</para>
+ <para>However this could be solved with the following configuration:</para>
+<programlisting language="XML"><![CDATA[
+<route path="/{gtn:path}">
+ <path-param encoding="preserve-path" qname="gtn:path">
+ <pattern>.*</pattern>
+ </path-param>
+</route>
+]]></programlisting>
+ <orderedlist>
+ <listitem>
+ <para>The .* declaration allows to match any char sequence.</para>
+ </listitem>
+ <listitem>
+ <para>The <emphasis role="italic">preserve-path</emphasis> <emphasis role="bold">encoding</emphasis> tells the engine that the "/" chars should be handled by the path parameter itself as they have a special meaning for the router. Without this special encoding, "/" would be rendered as the ":<emphasis role="italic">" character and conversely the ":</emphasis>" character would be matched as the "/" character.</para>
+ </listitem>
+ </orderedlist>
+ </section>
+ <section>
+ <title>Request parameters</title>
+ <para>Request parameters are matched from the request parameters (GET or POST). The match can be optional as their representation in the request allows it.</para>
+ <itemizedlist>
+ <listitem>
+ <para>Routing</para>
+ <itemizedlist>
+ <listitem>
+ <para>route is accepted when a required parameter is present and matched in the request.</para>
+ </listitem>
+ <listitem>
+ <para>route is accepted when an optional parameter is absent or matched in the request.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ <listitem>
+ <para>Rendering:</para>
+ <itemizedlist>
+ <listitem>
+ <para>selection occurs for required parameters when is the parameter is present and matched in the map.</para>
+ </listitem>
+ <listitem>
+ <para>selection occurs for optional parameters when is the parameter is absent or matched in the map.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+ <para>
+ <emphasis role="bold">Example:</emphasis>
+ </para>
+<programlisting language="XML"><![CDATA[
+<route path="/">
+ <request-param name="path" qname="gtn:path"/>
+</route>
+]]></programlisting>
+ <para>Request parameters are declared by a <code>request-param</code> element and by default will match any value. A request like "/?path=foo" is mapped to the (gtn:path=foo) map. The <code>name</code> attribute of the <code>request-param</code> tag defines the request parameter value. This element accepts more configuration</para>
+ <itemizedlist>
+ <listitem>
+ <para>a <code>value</code> or a <code>pattern</code> element a child element to match a constant or a pattern</para>
+ </listitem>
+ <listitem>
+ <para>a <code>control-mode</code> attribute with the value <code>optional</code> or <code>required</code> to indicate if matching is mandatory or not</para>
+ </listitem>
+ <listitem>
+ <para>a <code>value-mapping</code> attribute with the possible values <code>canonical</code>, <code>never-empty</code>, <code>never-null</code> can be used to filter filter values after matching is done. For instance a parameter configured with <code>value-mapping="never-empty"</code> and matching the empty string value will not put the empty string in the map.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section>
+ <title>Route precedence</title>
+ <para>The order of route declaration is important as it influence how rules are matched. Sometimes the same request could be matched by several routes and the routing table is ambiguous.</para>
+<programlisting language="XML"><![CDATA[
+<route path="/foo">
+ <route-param qname="gtn:handler">
+ <value>portal</value>
+ </route-param>
+</route>
+<route path="/{gtn:path}">
+ <path-param encoding="preserve-path" qname="gtn:path">
+ <pattern>.*</pattern>
+ </path-param>
+</route>
+]]></programlisting>
+ <para>In that case, the request path "/foo" will always be matched by the first rule before the second rule. This can be misleading since the map (gtn:path=foo) would be rendered as "/foo" as well and would not be matched by the first rule. Such ambiguit can happen, it can be desirable or not.</para>
+ </section>
+ <section>
+ <title>Route nesting</title>
+ <para>Route nesting is possible and often desirable as it helps to</para>
+ <itemizedlist>
+ <listitem>
+ <para>factor common parameters in a common rule</para>
+ </listitem>
+ <listitem>
+ <para>perform more efficient matching as the match of the common rule is done once for all the sub routes</para>
+ </listitem>
+ </itemizedlist>
+<programlisting language="XML"><![CDATA[
+<route path="/foo">
+ <route-param qname="gtn:handler">
+ <value>portal</value>
+ </route-param>
+ <route path="/bar">
+ <route-param qname="gtn:path">
+ <value>bar</value>
+ </route-param>
+ </route>
+ <route path="/juu">
+ <route-param qname="gtn:path">
+ <value>juu</value>
+ </route-param>
+ </route>
+</route>
+]]></programlisting>
+ <itemizedlist>
+ <listitem>
+ <para>The request path "/foo/bar" is mapped to the (gtn:handler=portal,gtn:path=bar) map</para>
+ </listitem>
+ <listitem>
+ <para>The request path "/foo/juu" is mapped to the (gtn:handler=portal,gtn:path=juu) map</para>
+ </listitem>
+ <listitem>
+ <para>The request path "/foo" is not mapped as non leaf routes do not perform matches.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ </section>
+ </section>
+ <section>
+ <title>Integrate to JBoss Enterprise Portal Platform WebUI framework</title>
+ <section>
+ <title>Routing</title>
+ <para>JBoss Enterprise Portal Platform defines a set of parameters in its routing table, for each client request, the mapping engine processes the request path and return the defined parameters with their values as a Map<QualifiedName, String></para>
+ <para>
+ <emphasis role="bold">gtn:handler</emphasis>
+ </para>
+ <para>The gtn:handler names is one of the most important qualified name as it determines which handler will take care of the request processing just after the controller has determined the parameter map. The handler value is used to make a lookup in the handler map of the controller. An handler is a class that extends the <code>WebRequestHandler</code> class and implements the <code>execute(ControllerContext)</code> method. Several handlers are available by default:</para>
+ <itemizedlist>
+ <listitem>
+ <para>portal : process aggregated portal requests</para>
+ </listitem>
+ <listitem>
+ <para>upload / download : process file upload and file download</para>
+ </listitem>
+ <listitem>
+ <para>legacy : handle legacy URL redirection (see <emphasis role="bold">Legacy handler</emphasis> section)</para>
+ </listitem>
+ <listitem>
+ <para>default : <literal>http</literal> redirection to the default portal of the container</para>
+ </listitem>
+ <listitem>
+ <para>staticResource: serve static resources like image, css or javascript... files in portal.war (see <emphasis role="bold">Static Resource Handler</emphasis> section)</para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ <emphasis role="bold">gtn:sitetype / gtn:sitename / gtn:path</emphasis>
+ </para>
+ <para>Those qualified names drives a request for the portal handler. They are used to determine which site to show and which path to resolve against a navigation. For instance the (gtn:sitetype=portal,gtn:sitename=classic,gtn:path=home) instruct the portal handler to show the home page of the classic portal site.</para>
+ <para>
+ <emphasis role="bold">gtn:lang</emphasis>
+ </para>
+ <para>The language in the URL for the portal handler. This is a new feature offered, now language can be specified on URL. that mean user can bookmark that URL (with the information about language) or he can changed language simply by modifying the URL address</para>
+ <para>
+ <emphasis role="bold">gtn:componentid / gtn:action / gtn:objectid</emphasis>
+ </para>
+ <para>The webui parameters used by the portal handler for managing webui component URLs for portal applications (and not for portlet applications).</para>
+ </section>
+ <section>
+ <title>Rendering</title>
+ <para>The <emphasis role="bold">controller</emphasis> is designed to render a Map<QualifiedName, String> as an <literal>http</literal> URL according to its routing table. But to integrate it for using easily in WebUI Framework of JBoss Enterprise Portal Platform, we need some more components</para>
+ <section>
+ <title>
+ <emphasis role="bold">PortalURL</emphasis>
+ </title>
+ <para>
+ <code>PortalURL</code> play a similar role at the portal level, its main role is to abstract the creation of an URL for a resource managed by the portal.</para>
+<programlisting language="Java"><![CDATA[
+public abstract class PortalURL<R, U extends PortalURL<U>>
+{
+ ...
+}
+]]></programlisting>
+ <para>The <code>PortalURL</code> declaration may seem a bit strange at first sight with two generic types <code>U</code> and <code>R</code> and the circular recursion of the <code>U</code> generic parameter, but it's because most of the time you will not use the <code>PortalURL</code> object but instead subclasses.</para>
+ <itemizedlist>
+ <listitem>
+ <para>The <code>R</code> generic type represents the type of the resource managed by the portal</para>
+ </listitem>
+ <listitem>
+ <para>The <code>U</code> generic type is also described as <emphasis role="bold">self bound generic type</emphasis>. This design pattern allows a class to return subtypes of itself in the class declaring the generic type. Java Enums are based on this principle (<code>class Enum<E extends Enum<E>></code>)</para>
+ </listitem>
+ </itemizedlist>
+ <para>A portal URL has various methods but certainly the most important method is the <code>toString()</code> method that generates an URL representing that will target the resource associated with the URL. The remaining methods are getter and setter for mutating the URL configuration, those options will affect the URL representation when it is generated.</para>
+ <itemizedlist>
+ <listitem>
+ <para>resource : the mandatory resource associated with the URL</para>
+ </listitem>
+ <listitem>
+ <para>locale : the optional locale used in the URL allowing the creation of bookmarkable URL containing a language</para>
+ </listitem>
+ <listitem>
+ <para>confirm : the optional confirm message displayed by the portal in the context of the portal UI</para>
+ </listitem>
+ <listitem>
+ <para>ajax : the optional ajax option allowing an ajax invocation of the URL</para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ <emphasis role="bold">Obtaining a PortalURL</emphasis>
+ </para>
+ <para>
+ <code>PortalURL</code> objects are obtained from <code>RequestContext</code> instance such as the <code>PortalRequestContext</code> or the PortletRequestContext. Usually those are obtained thanks to <code>getCurrentInstance</code> method of the <code>RequestContext</code> class:</para>
+<programlisting language="Java"><![CDATA[
+RequestContext ctx = RequestContext.getCurrentInstance();
+]]></programlisting>
+ <para>
+ <code>PortalURL</code> are created via to the <code>createURL</code> method that takes as input a resource type. A resource type is usually a constant and is a type safe object that allow to retrieve <code>PortalURL</code> subclasses:</para>
+<programlisting language="Java"><![CDATA[
+RequestContext ctx = RequestContext.getCurrentInstance();
+PortalURL<R, U> URL = ctx.createURL(type);
+]]></programlisting>
+ <para>In reality you will use a concrete type constant and have instead more concrete code like:</para>
+<programlisting language="Java"><![CDATA[
+RequestContext ctx = RequestContext.getCurrentInstance();
+NodeURL URL = ctx.createURL(NodeURL.TYPE);
+]]></programlisting>
+ <note>
+ <para>The <code>NodeURL.TYPE</code> is actually declared as <code>new ResourceType<NavigationResource, NodeURL>()</code> that can be described as a <emphasis role="bold">type literal</emphasis> object emulated by a Java anonymous inner class. Such literal were introduced by Neil Gafter as Super Type Token and popularized by Google Guice as Type Literal. It's an interesting way to create a literal representing a kind of Java type.</para>
+ </note>
+ </section>
+ <section>
+ <title>
+ <emphasis role="bold">Node URL</emphasis>
+ </title>
+ <para>The class <code>NodeURL</code> is one of the subclass of <code>PortalURL</code> that is specialized for navigation node resources:</para>
+<programlisting language="Java"><![CDATA[
+public class NodeURL extends PortalURL<NavigationResource, NodeURL>
+{
+ ...
+}
+]]></programlisting>
+ <para>The good news is that the NodeURL does not carry any generic type of its super class, which means that a NodeURL is type safe and one does not have to worry about generic types.</para>
+ <para>Using a NodeURL is pretty straightforward:</para>
+<programlisting language="Java"><![CDATA[
+NodeURL URL = RequestContext.getCurrentInstance().createURL(NodeURL.TYPE);
+URL.setResource(new NavigationResource("portal", "classic, "home"));
+String s = URL.toString();
+]]></programlisting>
+ <para>The <code>NodeURL</code> subclass contains specialized setter to make its usage even easier:</para>
+<programlisting language="Java"><![CDATA[
+UserNode node = ...;
+NodeURL URL = RequestContext.getCurrentInstance().createURL(NodeURL.TYPE);
+URL.setNode(node);
+String s = URL.toString();
+]]></programlisting>
+ </section>
+ <section>
+ <title>
+ <emphasis role="bold">Component URL</emphasis>
+ </title>
+ <para>The <code>ComponentURL</code> subclass is another specialization of <code>PortalURL</code> that allows the creation of WebUI components URLs. <code>ComponentURL</code> is commonly used to trigger WebUI events from client side:</para>
+<programlisting><![CDATA[
+<% def componentURL = uicomponent.event(...); /*or uicomponent.URL(...) */ %>
+ <a href=$componentURL>Click me</a>
+]]></programlisting>
+ <para>Normally you should not have to deal with it as the WebUI framework has already an abstraction for managing URL known as <code>URLBuilder</code>. The <code>URLBuilder</code> implementation delegates URL creation to <code>ComponentURL</code> objects.</para>
+ </section>
+ <section>
+ <title>Portlet URLs</title>
+ <para>Portlet URLs API implementation delegates to the portal <code>ComponentURL</code> (via the portlet container SPI). It is possible to control the language in the URL from a <code>PortletURL</code> object by setting a property named <code>gtn:lang</code>:</para>
+ <itemizedlist>
+ <listitem>
+ <para>when the property value is set to a value returned by <code>Locale#toString()</code> method for locale objects having a non null language value and a null variant value, the URL generated by the <code>PortletURL#toString()</code> method will contain the locale in the URL.</para>
+ </listitem>
+ <listitem>
+ <para>when the property value is set to an empty string, the generated URL will not contain a language. If the incoming URL was carrying a language, this language will be erased.</para>
+ </listitem>
+ <listitem>
+ <para>when the property value is not set, it will not affect the generated URL.</para>
+ </listitem>
+ </itemizedlist>
+<programlisting language="Java"><![CDATA[
+PortletURL URL = resp.createRenderURL();
+URL.setProperty("gtn:lang", "fr");
+writer.print("<a href='" + URL + "'>French</a>");
+]]></programlisting>
+ </section>
+ <section>
+ <title>Webui <code>URLBuilder</code>
+ </title>
+ <para>This internal API for creating URL works as before and delegates to the <code>PortletURL</code> API when the framework is executed in a portlet and to a <code>ComponentURL</code> API when the framework is executed in the portal context. The API has been modified to take in account the language in URL with two properties on the builder:</para>
+ <itemizedlist>
+ <listitem>
+ <para>locale : a locale for setting on the URL</para>
+ </listitem>
+ <listitem>
+ <para>removeLocale : a boolean for removing the locale present on the URL</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section>
+ <title>Groovy Templates</title>
+ <para>Within a Groovy template the mechanism is the same, however a splash of integration has been done to make creation of NodeURL simpler. A closure is bound under the <code>nodeurl</code> name and is available for invocation anytime. It will simply create a NodeURL object and return it:</para>
+<programlisting language="Java"><![CDATA[
+UserNode node = ...;
+NodeURL URL = nodeurl();
+URL.setNode(node);
+String s = URL.toString();
+]]></programlisting>
+ <para>The closure <code>nodeurl</code> is bound to Groovy template in <code>WebuiBindingContext</code>
+ </para>
+<programlisting language="Java"><![CDATA[
+// Closure nodeurl()
+put("nodeurl", new Closure(this)
+{
+ @Override
+ public Object call(Object[] args)
+ {
+ return context.createURL(NodeURL.TYPE);
+ }
+});
+]]></programlisting>
+ </section>
+ </section>
+ </section>
+ <section>
+ <title>Changes and migration from JBoss Enterprise Portal Platform 3.1.x</title>
+ <para>The navigation controller implies a migration of the client code that is coupled to several internal APIs of JBoss Enterprise Portal Platform. As far as we know the major impact is related to anything dealing with URL:</para>
+ <itemizedlist>
+ <listitem>
+ <para>Creation of an URL representing a resource managed by the portal: navigation node or ui component.</para>
+ </listitem>
+ <listitem>
+ <para>Using <literal>http</literal> request related information</para>
+ </listitem>
+ </itemizedlist>
+ <para>There are also changes in the configuration, because there is a change of how things are internally.</para>
+ <section>
+ <title>Migration of navigation node URL</title>
+ <para>
+ <emphasis role="bold">Using free form node</emphasis>
+ </para>
+ <para>Previously code for creating navigation node was like:</para>
+<programlisting language="Java"><![CDATA[
+String uri = Util.getPortalRequestContext().getPortalURI() + "home";
+]]></programlisting>
+ <para>The new code will look like</para>
+<programlisting language="Java"><![CDATA[
+PortalURL nodeURL = nodeurl();
+NavigationResource resource = new NavigationResource(SiteType.PORTAL, pcontext.getPortalOwner(), "home");
+String uri = nodeURL.setResource(resource).toString();
+]]></programlisting>
+ <para>
+ <emphasis role="bold">Using UserNode object</emphasis>
+ </para>
+<programlisting language="Java"><![CDATA[
+UserNode node = ...;
+String uri = Util.getPortalRequestContext().getPortalURI() + node.getURI()";
+]]></programlisting>
+ <para>The new code will look like</para>
+
+<programlisting language="Java"><![CDATA[
+UserNode node = ...;
+PortalURL nodeURL = nodeurl();
+String uri = nodeURL.setNode(node).toString();
+]]></programlisting>
+ </section>
+ <section>
+ <title>Security changes</title>
+ <para>Security configuration change in order to keep with the flexibility added by the navigation controller. In particular the authentication does not depend anymore on path specified in <code>web.xml</code> but instead rely on the security mandated by the underlying resource. Here are the noticeable changes for security</para>
+ <itemizedlist>
+ <listitem>
+ <para>Authentication is now triggered on the /login URL when it does not have a username or a password specified. Therefore the URL <code>/login?initialURI=/classic/home</code> is (more or less) equivalent to <code>/private/classic/home</code>
+ </para>
+ </listitem>
+ <listitem>
+ <para>When a resource cannot be viewed due to security constraint</para>
+ <itemizedlist>
+ <listitem>
+ <para>If the user is not logged, the authentication will be triggered</para>
+ </listitem>
+ <listitem>
+ <para>Otherwise a special page (the usual one) will be displayed instead</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section>
+ <title>Default handler</title>
+ <para>Redirection to the default portal used to be done by the <code>index.jsp</code> JSP page. This is not the case anymore, the index.jsp has been removed and the welcome file in <code>web.xml</code> was removed too. Instead a specific handler in the routing table has been configured, the sole role of this handler is to redirect the request to default portal when no other request has been matched previously:</para>
+
+<programlisting language="XML"><![CDATA[
+<controller>
+ ...
+ <route path="/">
+ <route-param qname="gtn:handler">
+ <value>default</value>
+ </route-param>
+ </route>
+</controller>
+]]></programlisting>
+ </section>
+ <section>
+ <title>Legacy handler</title>
+ <para>Legacy URLs such as <code>/public/...</code> and <code>/private/...</code> are now emulated to determine the best resource with the same resolution algorithm than before but instead of displaying the page, will make an <literal>http</literal> 302 redirection to the correct URL. This handler is present in the controller configuration. There is a noticeable difference between the two routes</para>
+ <itemizedlist>
+ <listitem>
+ <para>The public redirection attempt to find a node with the legacy resolution algorithm without authentication, which means that secured nodes will not be resolved and the redirection of a secured node will likely redirect to another page. For instance resolving the URL /public/classic/administration/registry path will likely resolve to another node if the user is not authenticated and is not part of the platform administrator group.</para>
+ </listitem>
+ <listitem>
+ <para>The private redirection performs first an authentication before doing the redirection. In that case the /private/classic/administration/registry path will resolve be redirected to the /portal/groups/:platform:administrators/administration/registry page if the user has the sufficient security rights.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section>
+ <title>Static resource handler</title>
+ <para>The "/" mapping for "default" servlet is now replaced by mapping for org.exoplatform.portal.application.PortalController servlet, that mean we need a handler (<emphasis role="bold">org.exoplatform.portal.application.StaticResourceRequestHandler</emphasis>) to serve static resources like image, css or javascript... files in portal.war. And it should be configured, and extended easily. Thanks to the controller.xml. This file can be overridden and can be changed and reloaded at runtime (WebAppController is MBean with some operations such as : reloadConfiguration() ...)</para>
+ <para>Declare StaticResourceHandler in controller.xml</para>
+<programlisting language="XML"><![CDATA[
+<route path="/{gtn:path}">
+ <route-param qname="gtn:handler">
+ <value>staticResource</value>
+ </route-param>
+ <path-param encoding="preserve-path" qname="gtn:path">
+ <pattern>.*\.(jpg|png|gif|ico|css)</pattern>
+ </path-param>
+</route>
+]]></programlisting>
+ <para>And we don't need these kind of following mapping in portal.war's web.xml anymore :</para>
+
+<programlisting language="XML"><![CDATA[
+<servlet-mapping>
+ <servlet-name>default</servlet-name>
+ <URL-pattern>*.jpg</URL-pattern>
+</servlet-mapping>
+...
+]]></programlisting>
+ </section>
+ <section>
+ <title>portal.war's web.xml changes</title>
+ <para>DoLoginServlet declaration</para>
+
+<programlisting language="XML"><![CDATA[
+<servlet>
+ <servlet-name>DoLoginServlet</servlet-name>
+ <servlet-class>org.exoplatform.web.login.DoLoginServlet</servlet-class>
+</servlet>
+<servlet-mapping>
+ <servlet-name>DoLoginServlet</servlet-name>
+ <URL-pattern>/dologin</URL-pattern>
+</servlet-mapping>
+]]></programlisting>
+ <para>Delare <emphasis role="bold">portal servlet</emphasis> as default servlet</para>
+
+<programlisting language="XML"><![CDATA[
+<servlet-mapping>
+ <servlet-name>portal</servlet-name>
+ <URL-pattern>/</URL-pattern>
+</servlet-mapping>
+]]></programlisting>
+ <para>So there are some mapping declaration for portal servlet are unused, we should also remove them: <emphasis role="bold">
+ <emphasis role="italic">/private/* /public/* /admin/* /upload/* /download/*</emphasis>
+ </emphasis>
+ </para>
+ <para>Add some security constraints</para>
+
+<programlisting language="XML"><![CDATA[
+<security-constraint>
+ <web-resource-collection>
+ <web-resource-name>user authentication</web-resource-name>
+ <URL-pattern>/dologin</URL-pattern>
+ <URL-pattern>/groups/*</URL-pattern>
+ <URL-pattern>/users/*</URL-pattern>
+...
+ </web-resource-collection>
+</security-constraint>
+]]></programlisting>
+ <para>We can remove the index.jsp, and its declaration in web.xml now, thank to the Default request handler</para>
+
+<programlisting language="XML"><![CDATA[
+<welcome-file-list>
+ <welcome-file>/index.jsp</welcome-file>
+</welcome-file-list>
+]]></programlisting>
+ </section>
+ <section>
+ <title>Dashboard changes</title>
+ <para>There are several important changes to take in account</para>
+ <itemizedlist>
+ <listitem>
+ <para>dashboard are now bound to a single URL (/users/root by default) and dashboard pages are leaf of this path</para>
+ </listitem>
+ <listitem>
+ <para>dashboard life cycle can be decoupled (create / destroy) from the identity creation in a configurable manner in <code>UserPortalConfigService</code> and exposed in configuration.properties under <code>gatein.portal.idm.createuserportal</code> and <code>gatein.portal.idm.destroyuserportal</code>.</para>
+ </listitem>
+ <listitem>
+ <para>by default dashboard are not created when a user is registered</para>
+ </listitem>
+ <listitem>
+ <para>a dashboard is created when the user access his dashboard URL</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section>
+ <title>Remove unused files</title>
+ <para>1/ portal-unavailable.jsp: this file was presented before if user goes to a non-available portal. Now the server sends a 404 status code instead.</para>
+ <para>2/ portal-warning.jsp: this file is not used in any place</para>
+ </section>
+ </section>
+</chapter>
Modified: epp/docs/branches/5.2/Reference_Guide/en-US/modules/PortalDevelopment.xml
===================================================================
--- epp/docs/branches/5.2/Reference_Guide/en-US/modules/PortalDevelopment.xml 2011-10-19 05:02:16 UTC (rev 7774)
+++ epp/docs/branches/5.2/Reference_Guide/en-US/modules/PortalDevelopment.xml 2011-10-19 05:44:02 UTC (rev 7775)
@@ -4,18 +4,19 @@
%BOOK_ENTITIES;
]>
<part id="part-Reference_Guide-Portal_Development">
- <title>Portal Development</title>
- <xi:include href="PortalDevelopment/Skinning.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
- <xi:include href="PortalDevelopment/PortalLifecycle.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
- <xi:include href="PortalDevelopment/DefaultPortalConfiguration.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
- <xi:include href="PortalDevelopment/DefaultPortalPermissionConfiguration.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
- <xi:include href="PortalDevelopment/DefaultPortalNavigationConfiguration.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
- <xi:include href="PortalDevelopment/InternationalizationConfiguration.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <title>Portal Development</title>
+ <xi:include href="PortalDevelopment/Skinning.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="PortalDevelopment/PortalLifecycle.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="PortalDevelopment/DefaultPortalConfiguration.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="PortalDevelopment/DefaultPortalPermissionConfiguration.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="PortalDevelopment/DefaultPortalNavigationConfiguration.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="PortalDevelopment/DataImportStrategy.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="PortalDevelopment/InternationalizationConfiguration.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="PortalDevelopment/LocalizationConfiguration.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
- <!--DOC NOTE: LocalizationConfiguration.xml added to satisfy JBEPP-685/GTNPORTAL-1694 -->
- <xi:include href="PortalDevelopment/RTLFramework.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
- <xi:include href="PortalDevelopment/XMLResourceBundles.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
- <xi:include href="PortalDevelopment/JavascriptInterApplicationCommunication.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="PortalDevelopment/RTLFramework.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="PortalDevelopment/XMLResourceBundles.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="PortalDevelopment/JavascriptInterApplicationCommunication.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<!--<xi:include href="PortalDevelopment/JavascriptConfiguration.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />-->
<!-- DOC NOTE: JavaScript Configuration section removed as per instruction from Thomas Heute-->
+ <xi:include href="PortalDevelopment/NavigationController.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
</part>
13 years, 2 months
gatein SVN: r7774 - in portal/trunk: component/web/server/src/main/java/org/exoplatform/web/handler and 5 other directories.
by do-not-reply@jboss.org
Author: haint
Date: 2011-10-19 01:02:16 -0400 (Wed, 19 Oct 2011)
New Revision: 7774
Added:
portal/trunk/web/eXoResources/src/main/webapp/javascript/eXo/webui/UIUploadInput.js
portal/trunk/web/portal/src/main/webapp/groovy/webui/form/UIUploadInput.gtmpl
portal/trunk/webui/core/src/main/java/org/exoplatform/webui/form/input/UIUploadInput.java
Modified:
portal/trunk/component/web/server/src/main/java/org/exoplatform/upload/UploadService.java
portal/trunk/component/web/server/src/main/java/org/exoplatform/web/handler/UploadHandler.java
portal/trunk/testsuite/webuibasedsamples/src/main/java/org/exoplatform/sample/webui/component/UISampleDownloadUpload.java
portal/trunk/web/eXoResources/src/main/webapp/javascript/eXo/webui/UIUpload.js
portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_cs.properties
portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_de.properties
portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_en.properties
portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_es.properties
portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_fr.properties
portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_it.properties
portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_ja.properties
portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_ne.properties
portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_nl.properties
portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_pt_BR.properties
portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_ru.properties
portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_uk.properties
portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_vi.properties
Log:
GTNPORTAL-2183 Build a new UIFormUploadInput component and difine limit size unit for UploadService
Modified: portal/trunk/component/web/server/src/main/java/org/exoplatform/upload/UploadService.java
===================================================================
--- portal/trunk/component/web/server/src/main/java/org/exoplatform/upload/UploadService.java 2011-10-19 04:41:43 UTC (rev 7773)
+++ portal/trunk/component/web/server/src/main/java/org/exoplatform/upload/UploadService.java 2011-10-19 05:02:16 UTC (rev 7774)
@@ -32,6 +32,9 @@
import org.gatein.common.text.EntityEncoder;
import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
@@ -53,19 +56,24 @@
private String uploadLocation_;
- private int defaultUploadLimitMB_;
+ private UploadLimit defaultUploadLimitMB_;
- private Map<String, Integer> uploadLimitsMB_ = new LinkedHashMap<String, Integer>();
+ private Map<String, UploadLimit> uploadLimits = new LinkedHashMap<String, UploadLimit>();
public static String UPLOAD_RESOURCES_STACK = "uploadResourcesStack";
-
+
+ public static enum UploadUnit
+ {
+ KB, MB, GB
+ };
+
public UploadService(PortalContainerInfo pinfo, InitParams params) throws Exception
{
String tmpDir = System.getProperty("java.io.tmpdir");
if (params == null || params.getValueParam("upload.limit.size") == null)
- defaultUploadLimitMB_ = 0; // 0 means unlimited
+ defaultUploadLimitMB_ = new UploadLimit(0, UploadUnit.MB); // 0 means unlimited
else
- defaultUploadLimitMB_ = Integer.parseInt(params.getValueParam("upload.limit.size").getValue());
+ defaultUploadLimitMB_ = new UploadLimit(Integer.parseInt(params.getValueParam("upload.limit.size").getValue()), UploadUnit.MB);
uploadLocation_ = tmpDir + "/" + pinfo.getContainerName() + "/eXoUpload";
File uploadDir = new File(uploadLocation_);
if (!uploadDir.exists())
@@ -112,6 +120,7 @@
if (itemList == null || itemList.size() != 1 || itemList.get(0).isFormField())
{
log.debug("Please upload 1 file per request");
+ removeUploadResource(uploadId);
return;
}
@@ -120,13 +129,23 @@
if (fileName == null)
fileName = uploadId;
fileName = fileName.substring(fileName.lastIndexOf('\\') + 1);
- fileName = EntityEncoder.FULL.encode(fileName);
String storeLocation = uploadLocation_ + "/" + uploadId + "." + fileName;
// commons-fileupload will store the temp file with name *.tmp
// we need to rename it to our desired name
fileItem.getStoreLocation().renameTo(new File(storeLocation));
+ File fileStore = new File(storeLocation);
+ if (!fileStore.exists())
+ try
+ {
+ fileStore.createNewFile();
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+
upResource.setFileName(fileName);
upResource.setMimeType(fileItem.getContentType());
@@ -140,6 +159,49 @@
upResource.setStatus(UploadResource.UPLOADED_STATUS);
}
+ /**
+ * @deprecated use {@link #createUploadResource(String, javax.servlet.http.HttpServletRequest)} instead
+ *
+ */
+ public void createUploadResource(String uploadId, String encoding, String contentType, double contentLength,
+ InputStream inputStream) throws Exception
+ {
+ UploadResource upResource = new UploadResource(uploadId);
+ RequestStreamReader reader = new RequestStreamReader(upResource);
+ uploadResources.put(upResource.getUploadId(), upResource);
+ if (isLimited(upResource, contentLength))
+ {
+ upResource.setStatus(UploadResource.FAILED_STATUS);
+ return;
+ }
+
+ Map<String, String> headers = reader.parseHeaders(inputStream, encoding);
+
+ String fileName = reader.getFileName(headers);
+ if (fileName == null)
+ fileName = uploadId;
+ fileName = fileName.substring(fileName.lastIndexOf('\\') + 1);
+
+ upResource.setFileName(fileName);
+ upResource.setMimeType(headers.get(RequestStreamReader.CONTENT_TYPE));
+ upResource.setStoreLocation(uploadLocation_ + "/" + uploadId + "." + fileName);
+ upResource.setEstimatedSize(contentLength);
+ File fileStore = new File(upResource.getStoreLocation());
+ if (!fileStore.exists())
+ fileStore.createNewFile();
+ FileOutputStream output = new FileOutputStream(fileStore);
+ reader.readBodyData(inputStream, contentType, output);
+
+ if (upResource.getStatus() == UploadResource.UPLOADING_STATUS)
+ {
+ upResource.setStatus(UploadResource.UPLOADED_STATUS);
+ return;
+ }
+
+ uploadResources.remove(uploadId);
+ fileStore.delete();
+ }
+
@SuppressWarnings("unchecked")
private void putToStackInSession(HttpSession session, String uploadId)
{
@@ -178,7 +240,7 @@
for (String id : uploadIds)
{
removeUploadResource(id);
- uploadLimitsMB_.remove(id);
+ uploadLimits.remove(id);
}
}
}
@@ -229,10 +291,23 @@
*/
public void addUploadLimit(String uploadId, Integer limitMB)
{
- if (limitMB == null)
- uploadLimitsMB_.put(uploadId, Integer.valueOf(defaultUploadLimitMB_));
+ addUploadLimit(uploadId, limitMB, UploadUnit.MB);
+ }
+
+ public void addUploadLimit(String uploadId, Integer limit, UploadUnit unit)
+ {
+ if (limit == null)
+ {
+ uploadLimits.put(uploadId, defaultUploadLimitMB_);
+ }
+ else if(unit == null)
+ {
+ uploadLimits.put(uploadId, new UploadLimit(limit, UploadUnit.MB));
+ }
else
- uploadLimitsMB_.put(uploadId, limitMB);
+ {
+ uploadLimits.put(uploadId, new UploadLimit(limit, unit));
+ }
}
/**
@@ -240,9 +315,9 @@
*
* @return all upload limit sizes
*/
- public Map<String, Integer> getUploadLimitsMB()
+ public Map<String, UploadLimit> getUploadLimits()
{
- return uploadLimitsMB_;
+ return uploadLimits;
}
private ServletFileUpload makeServletFileUpload(final UploadResource upResource)
@@ -273,26 +348,61 @@
private boolean isLimited(UploadResource upResource, double contentLength)
{
// by default, use the limit set in the service
- int limitMB = defaultUploadLimitMB_;
+ UploadLimit limit = defaultUploadLimitMB_;
// if the limit is set in the request (specific for this upload) then use
// this value instead of the default one
- if (uploadLimitsMB_.containsKey(upResource.getUploadId()))
+ if (uploadLimits.containsKey(upResource.getUploadId()))
{
- limitMB = uploadLimitsMB_.get(upResource.getUploadId()).intValue();
+ limit = uploadLimits.get(upResource.getUploadId());
}
- int estimatedSizeMB = (int)((contentLength / 1024) / 1024);
- if (limitMB > 0 && estimatedSizeMB > limitMB)
+ double estimatedSize = contentLength / limit.division;
+ if (limit.getLimit() > 0 && estimatedSize > limit.getLimit())
{ // a limit set to 0 means unlimited
if (log.isDebugEnabled())
{
- log.debug("Upload cancelled because file bigger than size limit : " + estimatedSizeMB + " MB > " + limitMB
- + " MB");
+ log.debug("Upload cancelled because file bigger than size limit : " + estimatedSize + " " + limit.unit + " > " + limit.getLimit()
+ + " " + limit.unit);
}
return true;
}
return false;
}
-
+ public static class UploadLimit
+ {
+ private int limit;
+
+ private int division;
+
+ private UploadUnit unit;
+
+ public UploadLimit(int limit, UploadUnit unit)
+ {
+ this.limit = limit;
+ this.unit = unit;
+ if(unit == UploadUnit.KB)
+ {
+ division = 1024;
+ }
+ else if(unit == UploadUnit.MB)
+ {
+ division = 1024 * 1024;
+ }
+ else if(unit == UploadUnit.GB)
+ {
+ division = 1024 * 1024 * 1024;
+ }
+ }
+
+ public int getLimit()
+ {
+ return limit;
+ }
+
+ public String getUnit()
+ {
+ return unit.toString();
+ }
+ }
}
Modified: portal/trunk/component/web/server/src/main/java/org/exoplatform/web/handler/UploadHandler.java
===================================================================
--- portal/trunk/component/web/server/src/main/java/org/exoplatform/web/handler/UploadHandler.java 2011-10-19 04:41:43 UTC (rev 7773)
+++ portal/trunk/component/web/server/src/main/java/org/exoplatform/web/handler/UploadHandler.java 2011-10-19 05:02:16 UTC (rev 7774)
@@ -24,6 +24,7 @@
import org.exoplatform.container.ExoContainerContext;
import org.exoplatform.upload.UploadResource;
import org.exoplatform.upload.UploadService;
+import org.exoplatform.upload.UploadService.UploadLimit;
import org.exoplatform.web.ControllerContext;
import org.exoplatform.web.WebAppController;
import org.exoplatform.web.WebRequestHandler;
@@ -66,7 +67,7 @@
String[] uploadIds = req.getParameterValues("uploadId");
res.setHeader("Cache-Control", "no-cache");
-
+
ExoContainer container = ExoContainerContext.getCurrentContainer();
UploadService service = (UploadService)container.getComponentInstanceOfType(UploadService.class);
if (action == null || action.length() < 1)
@@ -87,10 +88,11 @@
continue;
if (upResource.getStatus() == UploadResource.FAILED_STATUS)
{
- int limitMB = service.getUploadLimitsMB().get(uploadIds[i]).intValue();
+ UploadLimit limit = service.getUploadLimits().get(uploadIds[i]);
value.append("\n \"").append(uploadIds[i]).append("\": {");
value.append("\n \"status\":").append('\"').append("failed").append("\",");
- value.append("\n \"size\":").append('\"').append(limitMB).append("\"");
+ value.append("\n \"size\":").append('\"').append(limit.getLimit()).append("\",");
+ value.append("\n \"unit\":").append('\"').append(limit.getUnit()).append("\"");
value.append("\n }");
continue;
}
@@ -101,7 +103,8 @@
}
value.append("\n \"").append(uploadIds[i]).append("\": {");
value.append("\n \"percent\":").append('\"').append((int)percent).append("\",");
- value.append("\n \"fileName\":").append('\"').append(encodeName(upResource.getFileName()))
+ String fileName = EntityEncoder.FULL.encode(upResource.getFileName());
+ value.append("\n \"fileName\":").append('\"').append(encodeName(fileName))
.append("\"");
value.append("\n }");
if (i < uploadIds.length - 1)
Modified: portal/trunk/testsuite/webuibasedsamples/src/main/java/org/exoplatform/sample/webui/component/UISampleDownloadUpload.java
===================================================================
--- portal/trunk/testsuite/webuibasedsamples/src/main/java/org/exoplatform/sample/webui/component/UISampleDownloadUpload.java 2011-10-19 04:41:43 UTC (rev 7773)
+++ portal/trunk/testsuite/webuibasedsamples/src/main/java/org/exoplatform/sample/webui/component/UISampleDownloadUpload.java 2011-10-19 05:02:16 UTC (rev 7774)
@@ -1,12 +1,17 @@
package org.exoplatform.sample.webui.component;
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import org.exoplatform.download.DownloadResource;
import org.exoplatform.download.DownloadService;
import org.exoplatform.download.InputStreamDownloadResource;
import org.exoplatform.upload.UploadResource;
+import org.exoplatform.upload.UploadService.UploadUnit;
import org.exoplatform.webui.config.annotation.ComponentConfig;
import org.exoplatform.webui.config.annotation.EventConfig;
import org.exoplatform.webui.core.lifecycle.UIFormLifecycle;
@@ -14,6 +19,7 @@
import org.exoplatform.webui.event.EventListener;
import org.exoplatform.webui.form.UIForm;
import org.exoplatform.webui.form.UIFormUploadInput;
+import org.exoplatform.webui.form.input.UIUploadInput;
@ComponentConfig(lifecycle = UIFormLifecycle.class, template = "app:/groovy/webui/component/UISampleDownloadUpload.gtmpl", events = {@EventConfig(listeners = UISampleDownloadUpload.SubmitActionListener.class)})
public class UISampleDownloadUpload extends UIForm
@@ -30,8 +36,13 @@
public UISampleDownloadUpload() throws Exception
{
addUIFormInput(new UIFormUploadInput("name0", "value0"));
- addUIFormInput(new UIFormUploadInput("name1", "value1", 100));
+ addUIFormInput(new UIFormUploadInput("name1", "value1", 1));
addUIFormInput(new UIFormUploadInput("name2", "value2", 200));
+
+ addUIFormInput(new UIUploadInput("name3", "name3", 2, 300, UploadUnit.KB));
+ UIUploadInput input = new UIUploadInput("name4", "name4", 2, 300);
+ input.setAutoUpload(false);
+ addUIFormInput(input);
}
public void setDownloadLink(String[] downloadLink)
@@ -71,9 +82,9 @@
{
UISampleDownloadUpload uiForm = event.getSource();
DownloadService dservice = uiForm.getApplicationComponent(DownloadService.class);
- String[] downloadLink = new String[3];
- String[] fileName = new String[3];
- String[] inputName = new String[3];
+ List<String> downloadLink = new ArrayList<String>();
+ List<String> fileName = new ArrayList<String>();
+ List<String> inputName = new ArrayList<String>();
for (int index = 0; index <= 2; index++)
{
UIFormUploadInput input = uiForm.getChildById("name" + index);
@@ -83,15 +94,28 @@
DownloadResource dresource =
new InputStreamDownloadResource(input.getUploadDataAsStream(), uploadResource.getMimeType());
dresource.setDownloadName(uploadResource.getFileName());
- downloadLink[index] = dservice.getDownloadLink(dservice.addDownloadResource(dresource));
- fileName[index] = uploadResource.getFileName();
- inputName[index] = "name" + index;
+ downloadLink.add(dservice.getDownloadLink(dservice.addDownloadResource(dresource)));
+ fileName.add(uploadResource.getFileName());
+ inputName.add("name" + index);
}
}
- uiForm.setDownloadLink(downloadLink);
- uiForm.setFileName(fileName);
- uiForm.setInputName(inputName);
+ for(int index = 3; index < 5; index++) {
+ UIUploadInput input = uiForm.getChildById("name" + index);
+ UploadResource[] uploadResources = input.getUploadResources();
+ for(UploadResource uploadResource : uploadResources) {
+ DownloadResource dresource =
+ new InputStreamDownloadResource(new FileInputStream(new File(uploadResource.getStoreLocation())), uploadResource.getMimeType());
+ dresource.setDownloadName(uploadResource.getFileName());
+ downloadLink.add(dservice.getDownloadLink(dservice.addDownloadResource(dresource)));
+ fileName.add(uploadResource.getFileName());
+ inputName.add("name" + index);
+ }
+ }
+
+ uiForm.setDownloadLink(downloadLink.toArray(new String[downloadLink.size()]));
+ uiForm.setFileName(fileName.toArray(new String[fileName.size()]));
+ uiForm.setInputName(inputName.toArray(new String[inputName.size()]));
event.getRequestContext().addUIComponentToUpdateByAjax(uiForm.getParent());
}
Modified: portal/trunk/web/eXoResources/src/main/webapp/javascript/eXo/webui/UIUpload.js
===================================================================
--- portal/trunk/web/eXoResources/src/main/webapp/javascript/eXo/webui/UIUpload.js 2011-10-19 04:41:43 UTC (rev 7773)
+++ portal/trunk/web/eXoResources/src/main/webapp/javascript/eXo/webui/UIUpload.js 2011-10-19 05:02:16 UTC (rev 7774)
@@ -92,7 +92,7 @@
* Refresh progress bar to update state of upload progress
* @param {String} elementId identifier of upload bar frame
*/
-UIUpload.prototype.refeshProgress = function(elementId) {
+UIUpload.prototype.refreshProgress = function(elementId) {
var list = eXo.webui.UIUpload.listUpload;
if(list.length < 1) return;
var url = eXo.env.server.context + "/upload?" ;
@@ -103,7 +103,7 @@
}
var responseText = ajaxAsyncGetRequest(url, false);
if(list.length > 0) {
- setTimeout("eXo.webui.UIUpload.refeshProgress('" + elementId + "');", 1000);
+ setTimeout("eXo.webui.UIUpload.refreshProgress('" + elementId + "');", 1000);
}
var response;
@@ -119,6 +119,9 @@
if (response.upload[id].status == "failed") {
this.abortUpload(id);
var message = eXo.core.DOMUtil.findFirstChildByClass(container, "div", "LimitMessage").innerHTML ;
+ message = message.replace("{0}", response.upload[id].size);
+ message = message.replace("{1}", response.upload[id].unit);
+ alert(message);
continue;
}
var element = document.getElementById(id+"ProgressIframe");
@@ -271,7 +274,7 @@
var list = eXo.webui.UIUpload.listUpload;
if(list.length == 0) {
eXo.webui.UIUpload.listUpload.push(form.id);
- setTimeout("eXo.webui.UIUpload.refeshProgress('" + id + "');", 1000);
+ setTimeout("eXo.webui.UIUpload.refreshProgress('" + id + "');", 1000);
} else {
eXo.webui.UIUpload.listUpload.push(form.id);
}
Added: portal/trunk/web/eXoResources/src/main/webapp/javascript/eXo/webui/UIUploadInput.js
===================================================================
--- portal/trunk/web/eXoResources/src/main/webapp/javascript/eXo/webui/UIUploadInput.js (rev 0)
+++ portal/trunk/web/eXoResources/src/main/webapp/javascript/eXo/webui/UIUploadInput.js 2011-10-19 05:02:16 UTC (rev 7774)
@@ -0,0 +1,249 @@
+/**
+ * Copyright (C) 2009 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+function UIUploadInput() {
+ this.listUpload = new Array();
+ this.refreshTime = 1000;
+ this.delayTime = 5000;
+ this.progressURL = eXo.env.server.context + "/upload?action=progress&uploadId=";
+ this.uploadURL = eXo.env.server.context + "/upload?action=upload&uploadId=" ;
+ this.abortURL = eXo.env.server.context + "/upload?action=abort&uploadId=" ;
+ this.deleteURL = eXo.env.server.context + "/upload?action=delete&uploadId=" ;
+};
+
+/**
+ * Initialize upload and create a upload request to server
+ * @param {String} uploadId identifier upload
+ * @param {boolean} isAutoUpload auto upload or none
+ */
+UIUploadInput.prototype.initUploadEntry = function(uploadId, isAutoUpload) {
+ for(var i = 0; i < uploadId.length; i++) {
+ var url = this.progressURL + uploadId[i] ;
+ var responseText = ajaxAsyncGetRequest(url, false);
+
+ var response;
+ try {
+ eval("response = "+responseText);
+ } catch(err) {
+ return;
+ }
+
+ if(response.upload[uploadId[i]] == undefined || response.upload[uploadId[i]].percent == undefined) {
+ this.createEntryUpload(uploadId[i], isAutoUpload);
+ } else if(response.upload[uploadId[i]].percent == 100) {
+ this.showUploaded(uploadId[i], response.upload[uploadId[i]].fileName);
+ }
+ }
+};
+
+UIUploadInput.prototype.createEntryUpload = function(id, isAutoUpload) {
+ var div = document.getElementById('UploadInput' + id);
+
+ var inputHTML = "<input id='file" +id+ "' class='file' name='file' type='file' onkeypress='return false;'";
+
+ if(isAutoUpload) {
+ inputHTML += " onchange='eXo.webui.UIUploadInput.upload(\"" +id+ "\", " +isAutoUpload+ ");' >";
+ } else {
+ inputHTML += " >"
+ }
+
+ div.style.display = 'block';
+ div.innerHTML = inputHTML;
+
+ if(!isAutoUpload) {
+ var prefixId = id.substring(0, id.indexOf('-'));
+ var img = document.getElementById('IconUpload' + prefixId + '-0');
+ img.style.display = 'block';
+ }
+};
+
+UIUploadInput.prototype.displayUploadButton = function(id) {
+ var flag = true;
+ if(id instanceof Array) {
+ var img = document.getElementById('IconUpload' + id[0]);
+ for(var i = 0; i < id.length; i++) {
+ var input = document.getElementById('file' + id[i]);
+ if(input == null) flag = true;
+ else if(input.value == null || input.value == '') flag = false;
+ }
+ if(flag) img.style.display = 'none';
+ } else return;
+};
+
+UIUploadInput.prototype.showUploaded = function(id, fileName) {
+ this.listUpload.remove(id);
+ var container = parent.document.getElementById('UploadInputContainer' + id);
+ var element = document.getElementById('ProgressIframe' + id);
+ element.innerHTML = "<span></span>";
+
+ var UploadInput = eXo.core.DOMUtil.findDescendantById(container, 'UploadInput' + id);
+ UploadInput.style.display = "none";
+
+ var progressIframe = eXo.core.DOMUtil.findDescendantById(container, 'ProgressIframe' + id);
+ progressIframe.style.display = "none";
+
+ var selectFileFrame = eXo.core.DOMUtil.findFirstDescendantByClass(container, "div", "SelectFileFrame") ;
+ selectFileFrame.style.display = "block" ;
+
+ var fileNameLabel = eXo.core.DOMUtil.findFirstDescendantByClass(selectFileFrame, "div", "FileNameLabel") ;
+ if(fileName != null) fileNameLabel.innerHTML = decodeURIComponent(fileName);
+
+ var progressBarFrame = eXo.core.DOMUtil.findFirstDescendantByClass(container, "div", "ProgressBarFrame") ;
+ progressBarFrame.style.display = "none" ;
+};
+
+UIUploadInput.prototype.refreshProgress = function(uploadId, isAutoUpload) {
+ var list = this.listUpload;
+ if(list.length < 1) return;
+ var url = this.progressURL;
+
+ for(var i = 0; i < list.length; i++){
+ url = url + "&uploadId=" + list[i];
+ }
+ var responseText = ajaxAsyncGetRequest(url, false);
+ if(this.listUpload.length > 0) {
+ setTimeout("eXo.webui.UIUploadInput.refreshProgress('" +uploadId+ "', " +isAutoUpload+ ");", this.refreshTime);
+ }
+
+ var response;
+ try {
+ eval("response = "+responseText);
+ } catch(err) {
+ return;
+ }
+
+ for(id in response.upload) {
+ var container = parent.document.getElementById('UploadInputContainer' + id);
+ if (response.upload[id].status == "failed") {
+ this.abortUpload(id, isAutoUpload);
+ var message = eXo.core.DOMUtil.findFirstChildByClass(container, "div", "LimitMessage").innerHTML ;
+ message = message.replace("{0}", response.upload[id].size);
+ message = message.replace("{1}", response.upload[id].unit);
+ alert(message);
+ continue;
+ }
+ var element = document.getElementById('ProgressIframe' + id);
+ var percent = response.upload[id].percent;
+ var progressBarMiddle = eXo.core.DOMUtil.findFirstDescendantByClass(container, "div", "ProgressBarMiddle") ;
+ var blueProgressBar = eXo.core.DOMUtil.findFirstChildByClass(progressBarMiddle, "div", "BlueProgressBar") ;
+ var progressBarLabel = eXo.core.DOMUtil.findFirstChildByClass(blueProgressBar, "div", "ProgressBarLabel") ;
+ blueProgressBar.style.width = percent + "%" ;
+ progressBarLabel.innerHTML = percent + "%" ;
+
+ if(percent == 100) {
+ this.showUploaded(id, response.upload[id].fileName);
+ }
+ }
+
+ if(this.listUpload.length < 1) return;
+
+ if (element) {
+ element.innerHTML = "Uploaded "+ percent + "% " +
+ "<span onclick='parent.eXo.webui.UIUploadInput.abortUpload("+uploadId+", "+isAutoUpload+")'>Abort</span>";
+ }
+};
+
+UIUploadInput.prototype.deleteUpload = function(id, isAutoUpload) {
+ var url = this.deleteURL + id;
+ var request = eXo.core.Browser.createHttpRequest();
+ request.open('GET', url, false);
+ request.setRequestHeader("Cache-Control", "max-age=86400");
+ request.send(null);
+
+ var container = parent.document.getElementById('UploadInputContainer' + id);
+ var selectFileFrame = eXo.core.DOMUtil.findFirstDescendantByClass(container, "div", "SelectFileFrame") ;
+ selectFileFrame.style.display = "none" ;
+
+ this.createEntryUpload(id, isAutoUpload);
+};
+
+UIUploadInput.prototype.abortUpload = function(id, isAutoUpload) {
+ this.listUpload.remove(id);
+ var url = this.abortURL + id;
+ var request = eXo.core.Browser.createHttpRequest();
+ request.open('GET', url, false);
+ request.setRequestHeader("Cache-Control", "max-age=86400");
+ request.send(null);
+
+ var container = parent.document.getElementById('UploadInputContainer' + id);
+ var progressIframe = eXo.core.DOMUtil.findDescendantById(container, 'ProgressIframe' + id);
+ progressIframe.style.display = "none";
+
+ var progressBarFrame = eXo.core.DOMUtil.findFirstDescendantByClass(container, "div", "ProgressBarFrame") ;
+ progressBarFrame.style.display = "none" ;
+
+ this.createEntryUpload(id, isAutoUpload);
+};
+
+/**
+ * Start upload file
+ * @param {Object} clickEle
+ * @param {String} id
+ */
+
+UIUploadInput.prototype.doUpload = function(id, isAutoUpload) {
+ var DOMUtil = eXo.core.DOMUtil;
+ var container = parent.document.getElementById('UploadInputContainer' + id);
+ this.displayUploadButton(id);
+ if(id instanceof Array) {
+ for(var i = 0; i < id.length; i++) {
+ this.doUpload(id[i], isAutoUpload);
+ }
+ } else {
+ var file = document.getElementById('file' + id);
+ if (file == null || file == undefined) return;
+ if (file.value == null || file.value == '') return;
+ var temp = file.value;
+
+ var progressBarFrame = DOMUtil.findFirstDescendantByClass(container, "div", "ProgressBarFrame");
+ progressBarFrame.style.display = "block";
+
+ var progressBarMiddle = DOMUtil.findFirstDescendantByClass(container, "div", "ProgressBarMiddle");
+ var blueProgressBar = DOMUtil.findFirstChildByClass(progressBarMiddle, "div", "BlueProgressBar");
+ var progressBarLabel = DOMUtil.findFirstChildByClass(blueProgressBar, "div", "ProgressBarLabel");
+ blueProgressBar.style.width = "0%";
+ progressBarLabel.innerHTML = "0%";
+
+ var uploadAction = this.uploadURL + id;
+ var formHTML = "<form id='form" +id+ "' class='UIUploadForm' style='margin: 0px; padding: 0px' action='"
+ + uploadAction + "' enctype='multipart/form-data' target='UploadIFrame" + id + "' method='post'></form>";
+ var div = document.createElement("div");
+ div.innerHTML = formHTML;
+ var form = div.firstChild;
+
+ form.appendChild(file);
+ document.body.appendChild(div);
+ form.submit();
+ document.body.removeChild(div);
+
+ if(this.listUpload.length == 0) {
+ this.listUpload.push(id);
+ setTimeout("eXo.webui.UIUploadInput.refreshProgress('" + id + "', " + isAutoUpload + ");", this.refreshTime);
+ } else {
+ this.listUpload.push(id);
+ }
+ }
+};
+
+UIUploadInput.prototype.upload = function(id, isAutoUpload) {
+ if(isAutoUpload) setTimeout("eXo.webui.UIUploadInput.doUpload('" + id + "', " + isAutoUpload + ")", this.delayTime);
+ else this.doUpload(id, isAutoUpload);
+};
+
+eXo.webui.UIUploadInput = new UIUploadInput();
Modified: portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_cs.properties
===================================================================
--- portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_cs.properties 2011-10-19 04:41:43 UTC (rev 7773)
+++ portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_cs.properties 2011-10-19 05:02:16 UTC (rev 7774)
@@ -446,7 +446,7 @@
UIFormUploadInput.label.Cancel=Zru\u0161it
UIFormUploadInput.label.Uploaded=Nahr\u00E1no
UIFormUploadInput.label.remove=Odstranit nahran\u00E9
-UIFormUploadInput.msg.limit=Soubor mus\u00ED b\u00FDt men\u0161\u00ED ne\u017E {0} MB.
+UIFormUploadInput.msg.limit=Soubor mus\u00ED b\u00FDt men\u0161\u00ED ne\u017E {0} {1}.
UIGadget.tooltip.Maximize=Maximalizovat
UIGadget.tooltip.Minimize=Minimalizovat
@@ -1526,7 +1526,7 @@
UIFormUploadInput.label.Cancel=Zru\u0161it
UIFormUploadInput.label.Uploaded=Nahr\u00e1no
UIFormUploadInput.label.remove=Odstranit nahran\u00e9
-UIFormUploadInput.msg.limit=Soubor mus\u00ed b\u00fdt men\u0161\u00ed ne\u017e {0} MB.
+UIFormUploadInput.msg.limit=Soubor mus\u00ed b\u00fdt men\u0161\u00ed ne\u017e {0} {1}.
UIGadget.tooltip.Maximize=Maximalizovat
UIGadget.tooltip.Minimize=Minimalizovat
Modified: portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_de.properties
===================================================================
--- portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_de.properties 2011-10-19 04:41:43 UTC (rev 7773)
+++ portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_de.properties 2011-10-19 05:02:16 UTC (rev 7774)
@@ -989,7 +989,7 @@
UIFormUploadInput.label.Uploaded=Hochgeladen
UIFormUploadInput.label.remove=L\u00f6schen
UIFormUploadInput.label.Cancel=#{word.cancel}
-UIFormUploadInput.msg.limit=Die Datei muss weniger als {0} MB gro\u00df sein.
+UIFormUploadInput.msg.limit=Die Datei muss weniger als {0} {1} gro\u00df sein.
###############################################################################
# org.exoplatform.portal.webui.component.customization.UIPageNodeSelector #
Modified: portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_en.properties
===================================================================
--- portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_en.properties 2011-10-19 04:41:43 UTC (rev 7773)
+++ portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_en.properties 2011-10-19 05:02:16 UTC (rev 7774)
@@ -1080,7 +1080,7 @@
UIFormUploadInput.label.Uploaded=Uploaded
UIFormUploadInput.label.remove=Remove Uploaded
UIFormUploadInput.label.Cancel=Cancel
-UIFormUploadInput.msg.limit=The file must be less than {0} MB.
+UIFormUploadInput.msg.limit=The file must be less than {0} {1}.
###############################################################################
# org.exoplatform.portal.webui.component.customization.UIPageNodeSelector #
Modified: portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_es.properties
===================================================================
--- portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_es.properties 2011-10-19 04:41:43 UTC (rev 7773)
+++ portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_es.properties 2011-10-19 05:02:16 UTC (rev 7774)
@@ -966,7 +966,7 @@
UIFormUploadInput.label.Uploaded=Subida
UIFormUploadInput.label.remove=Elinimar Subida
UIFormUploadInput.label.Cancel=Cancelar
-UIFormUploadInput.msg.limit=El tama\u00f1o del fichero debe ser inferior a {0} MB.
+UIFormUploadInput.msg.limit=El tama\u00f1o del fichero debe ser inferior a {0} {1}.
###############################################################################
# org.exoplatform.portal.webui.component.customization.UIPageNodeSelector #
Modified: portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_fr.properties
===================================================================
--- portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_fr.properties 2011-10-19 04:41:43 UTC (rev 7773)
+++ portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_fr.properties 2011-10-19 05:02:16 UTC (rev 7774)
@@ -985,7 +985,7 @@
UIFormUploadInput.label.Uploaded=Envoyé
UIFormUploadInput.label.remove=Supprimer
UIFormUploadInput.label.Cancel=#{word.cancel}
-UIFormUploadInput.msg.limit=Le fichier doit faire moins de {0} MB.
+UIFormUploadInput.msg.limit=Le fichier doit faire moins de {0} {1}.
###############################################################################
Modified: portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_it.properties
===================================================================
--- portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_it.properties 2011-10-19 04:41:43 UTC (rev 7773)
+++ portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_it.properties 2011-10-19 05:02:16 UTC (rev 7774)
@@ -1028,7 +1028,7 @@
UIFormUploadInput.label.Uploaded=Aggiornato
UIFormUploadInput.label.remove=Rimuovi l'Aggiornamento
UIFormUploadInput.label.Cancel=Annulla
-UIFormUploadInput.msg.limit=Il file deve essere minore di {0} MB.
+UIFormUploadInput.msg.limit=Il file deve essere minore di {0} {1}.
###############################################################################
# org.exoplatform.portal.webui.component.customization.UIPageNodeSelector #
Modified: portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_ja.properties
===================================================================
--- portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_ja.properties 2011-10-19 04:41:43 UTC (rev 7773)
+++ portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_ja.properties 2011-10-19 05:02:16 UTC (rev 7774)
@@ -994,7 +994,7 @@
UIFormUploadInput.label.Uploaded=\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9
UIFormUploadInput.label.remove=\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u3092\u9664\u53bb
UIFormUploadInput.label.Cancel=\u30ad\u30e3\u30f3\u30bb\u30eb
-UIFormUploadInput.msg.limit=\u30d5\u30a1\u30a4\u30eb\u30b5\u30a4\u30ba\u306f {0} MB\u4ee5\u4e0b\u3067\u3042\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002
+UIFormUploadInput.msg.limit=\u30d5\u30a1\u30a4\u30eb\u30b5\u30a4\u30ba\u306f {0} {1}\u4ee5\u4e0b\u3067\u3042\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002
###############################################################################
# org.exoplatform.portal.webui.component.customization.UIPageNodeSelector #
Modified: portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_ne.properties
===================================================================
--- portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_ne.properties 2011-10-19 04:41:43 UTC (rev 7773)
+++ portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_ne.properties 2011-10-19 05:02:16 UTC (rev 7774)
@@ -992,7 +992,7 @@
UIFormUploadInput.label.Uploaded=\u0905\u092a\u094d\u0932\u094b\u0921 \u0917\u0930\u0947\u0915\u094b
UIFormUploadInput.label.remove=\u0905\u092a\u094d\u0932\u094b\u0921 \u0917\u0930\u0947\u0915\u094b \u0939\u091f\u093e\u0909\u0928\u0941\u0939\u094b\u0938\u094d
UIFormUploadInput.label.Cancel=\u0930\u0926\u094d\u0926 \u0917\u0930\u094d\u0928\u0941\u0939\u094b\u0938\u094d
-UIFormUploadInput.msg.limit=\u092b\u093e\u0907\u0932 {0} MB \u092d\u0928\u094d\u0926\u093e \u0938\u093e\u0928\u094b \u0939\u0941\u0928\u0941\u092a\u0930\u094d\u091b\u0964
+UIFormUploadInput.msg.limit=\u092b\u093e\u0907\u0932 {0} {1} \u092d\u0928\u094d\u0926\u093e \u0938\u093e\u0928\u094b \u0939\u0941\u0928\u0941\u092a\u0930\u094d\u091b\u0964
###############################################################################
# org.exoplatform.portal.webui.component.customization.UIPageNodeSelector #
Modified: portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_nl.properties
===================================================================
--- portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_nl.properties 2011-10-19 04:41:43 UTC (rev 7773)
+++ portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_nl.properties 2011-10-19 05:02:16 UTC (rev 7774)
@@ -967,7 +967,7 @@
UIFormUploadInput.label.Uploaded=Ge\u00FCpload
UIFormUploadInput.label.remove=#{word.remove}
UIFormUploadInput.label.Cancel=#{word.cancel}
-UIFormUploadInput.msg.limit=Het bestand moet kleiner zijn dan {0} MB.
+UIFormUploadInput.msg.limit=Het bestand moet kleiner zijn dan {0} {1}.
###############################################################################
# org.exoplatform.portal.webui.component.customization.UIPageNodeSelector #
Modified: portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_pt_BR.properties
===================================================================
--- portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_pt_BR.properties 2011-10-19 04:41:43 UTC (rev 7773)
+++ portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_pt_BR.properties 2011-10-19 05:02:16 UTC (rev 7774)
@@ -986,7 +986,7 @@
UIFormUploadInput.label.Uploaded=Enviado
UIFormUploadInput.label.remove=Remover Arquivo
UIFormUploadInput.label.Cancel=Cancelar
-UIFormUploadInput.msg.limit=Arquivo deve possuir menos de {0} MB.
+UIFormUploadInput.msg.limit=Arquivo deve possuir menos de {0} {1}.
###############################################################################
# org.exoplatform.portal.webui.component.customization.UIPageNodeSelector #
Modified: portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_ru.properties
===================================================================
--- portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_ru.properties 2011-10-19 04:41:43 UTC (rev 7773)
+++ portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_ru.properties 2011-10-19 05:02:16 UTC (rev 7774)
@@ -951,7 +951,7 @@
UIFormUploadInput.label.Uploaded=Загружено
UIFormUploadInput.label.remove=Удалить загрузки
UIFormUploadInput.label.Cancel=Отменить
-UIFormUploadInput.msg.limit=Максимальный размер файла {0} MiB.
+UIFormUploadInput.msg.limit=Максимальный размер файла {0} {1}.
###############################################################################
Modified: portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_uk.properties
===================================================================
--- portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_uk.properties 2011-10-19 04:41:43 UTC (rev 7773)
+++ portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_uk.properties 2011-10-19 05:02:16 UTC (rev 7774)
@@ -942,7 +942,7 @@
UIFormUploadInput.label.Uploaded=Завантажено
UIFormUploadInput.label.remove=Вилучити завантажене
UIFormUploadInput.label.Cancel=Скасувати
-UIFormUploadInput.msg.limit=Файл повинен бути меншим, ніж {0} MB.
+UIFormUploadInput.msg.limit=Файл повинен бути меншим, ніж {0} {1}.
###############################################################################
Modified: portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_vi.properties
===================================================================
--- portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_vi.properties 2011-10-19 04:41:43 UTC (rev 7773)
+++ portal/trunk/web/portal/src/main/webapp/WEB-INF/classes/locale/portal/webui_vi.properties 2011-10-19 05:02:16 UTC (rev 7774)
@@ -1020,7 +1020,7 @@
UIFormUploadInput.label.Uploaded=Tải tệp tin
UIFormUploadInput.label.remove=Xóa tệp tin đã tải
UIFormUploadInput.label.Cancel=Loại bỏ
-UIFormUploadInput.msg.limit=Dung lượng tệp tin không được lớn hơn {0} MB.
+UIFormUploadInput.msg.limit=Dung lượng tệp tin không được lớn hơn {0} {1}.
###############################################################################
# org.exoplatform.portal.webui.component.customization.UIPageNodeSelector #
Added: portal/trunk/web/portal/src/main/webapp/groovy/webui/form/UIUploadInput.gtmpl
===================================================================
--- portal/trunk/web/portal/src/main/webapp/groovy/webui/form/UIUploadInput.gtmpl (rev 0)
+++ portal/trunk/web/portal/src/main/webapp/groovy/webui/form/UIUploadInput.gtmpl 2011-10-19 05:02:16 UTC (rev 7774)
@@ -0,0 +1,53 @@
+<%
+ String[] uploadId = uicomponent.getUploadId();
+ boolean isAutoUpload = uicomponent.isAutoUpload();
+ int limitFile = uicomponent.getLimitFile();
+ def rcontext = _ctx.getRequestContext();
+ rcontext.getJavascriptManager().importJavascript('eXo.webui.UIUploadInput');
+ StringBuilder b = new StringBuilder();
+ b.append("[") ;
+ for(int i = 0; i < uploadId.length; i++) {
+ b.append("\'").append(uploadId[i]).append("\'") ;
+ if(i < uploadId.length - 1) b.append(",");
+ }
+ b.append("]");
+ rcontext.getJavascriptManager().addCustomizedOnLoadScript("eXo.webui.UIUploadInput.initUploadEntry("+b.toString()+","+isAutoUpload+");");
+%>
+<%for(int i = 0; i < uploadId.length; i++) {%>
+<div class="UIUploadInput" id="UploadInputContainer<%=uploadId[i];%>">
+ <div class="LimitMessage" style="display: none;"><%= _ctx.appRes("UIFormUploadInput.msg.limit"); %></div>
+ <div id="UploadInput<%=uploadId[i];%>" class="UploadInput">
+ </div>
+ <div id="ProgressIframe<%=uploadId[i];%>" class="ProgressIframe" style="display: none;"></div>
+ <div class="ProgressBarFrame" style="display: none;">
+ <div class="ProgressBar">
+ <div class="ProgressBarLeft">
+ <div class="ProgressBarMiddle">
+ <div class="BlueProgressBar">
+ <div class="ProgressBarLabel">0%</div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="DeleteFileFrame">
+ <div class="DeleteFileLable" onclick="eXo.webui.UIUploadInput.abortUpload('<%=uploadId[i];%>', <%=isAutoUpload;%>);"><%=_ctx.appRes("UIFormUploadInput.label.Cancel")%></div>
+ </div>
+ </div>
+ <div class="SelectFileFrame" style="display: none;">
+ <div class="FileName">
+ <div class="FileNameLabel"><span></span></div>
+ </div>
+ <div class="RemoveFile" title="<%= _ctx.appRes("UIFormUploadInput.label.remove"); %>" onclick="eXo.webui.UIUploadInput.deleteUpload('<%=uploadId[i];%>', <%=isAutoUpload;%>);"></div>
+ </div>
+ <iframe height="0" width="0" name="UploadIFrame<%=uploadId[i];%>" id="UploadIFrame<%=uploadId[i];%>" style="display: none;">
+ <!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
+ <html xmlns='http://www.w3.org/1999/xhtml'>
+ <head></head>
+ <body></body>
+ </html>
+ </iframe>
+</div>
+<%}%>
+<%if(!isAutoUpload) {%>
+<img id="IconUpload<%=uploadId[0]%>" class="UploadButton" style="width : 20px; height: 20px; float: left; cursor: pointer; vertical-align: bottom; background: url('/eXoResources/skin/DefaultSkin/webui/component/UIUpload/background/UpArrow16x16.gif') no-repeat left;" onclick="eXo.webui.UIUploadInput.upload(<%=b.toString();%>, <%=isAutoUpload;%>)" alt='' src='/eXoResources/skin/sharedImages/Blank.gif'/>
+<%}%>
Added: portal/trunk/webui/core/src/main/java/org/exoplatform/webui/form/input/UIUploadInput.java
===================================================================
--- portal/trunk/webui/core/src/main/java/org/exoplatform/webui/form/input/UIUploadInput.java (rev 0)
+++ portal/trunk/webui/core/src/main/java/org/exoplatform/webui/form/input/UIUploadInput.java 2011-10-19 05:02:16 UTC (rev 7774)
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2003-2011 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.webui.form.input;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.exoplatform.upload.UploadResource;
+import org.exoplatform.upload.UploadService;
+import org.exoplatform.upload.UploadService.UploadUnit;
+import org.exoplatform.webui.application.WebuiRequestContext;
+import org.exoplatform.webui.config.annotation.ComponentConfig;
+import org.exoplatform.webui.form.UIFormInputBase;
+
+
+
+/**
+ * @author <a href="mailto:haint@exoplatform.com">Nguyen Thanh Hai</a>
+ *
+ * @datJul 19, 2011
+ */
+
+@ComponentConfig(template = "system:/groovy/webui/form/UIUploadInput.gtmpl")
+public class UIUploadInput extends UIFormInputBase<String>
+{
+ private String[] uploadId;
+
+ private boolean isAutoUpload = true;
+
+ private int limitFile = 1;
+
+ public UIUploadInput(String name, String bindingExpression, int limitFile)
+ {
+ super(name, bindingExpression, String.class);
+ if(limitFile > 1) this.limitFile = limitFile ;
+ uploadId = new String[this.limitFile] ;
+ for(int i = 0; i < uploadId.length; i++)
+ {
+ uploadId[i] = new StringBuffer().append(Math.abs(hashCode())).append('-').append(i).toString();
+ }
+ UploadService service = getApplicationComponent(UploadService.class);
+ for(int i = 0; i < uploadId.length; i++)
+ {
+ service.addUploadLimit(uploadId[i], null); // Use the limit set by the service. Warning, the service can allow no size limit (value to 0)
+ }
+ setComponentConfig(UIUploadInput.class, null);
+ }
+
+ public UIUploadInput(String name, String bindingExpression,int limitFile, int limitSize)
+ {
+ this(name, bindingExpression, limitFile, limitSize, UploadUnit.MB);
+ }
+
+ public UIUploadInput(String name, String bindingExpression, int limitFile, int limitSize, UploadUnit unit)
+ {
+ super(name, bindingExpression, String.class);
+ if(limitFile > 1) this.limitFile = limitFile ;
+ uploadId = new String[this.limitFile] ;
+ for(int i = 0; i < uploadId.length; i++)
+ {
+ uploadId[i] = new StringBuffer().append(Math.abs(hashCode())).append('-').append(i).toString();
+ }
+ UploadService service = getApplicationComponent(UploadService.class);
+ for(int i = 0; i < uploadId.length; i++)
+ {
+ service.addUploadLimit(uploadId[i], Integer.valueOf(limitSize), unit);
+ }
+ setComponentConfig(UIUploadInput.class, null);
+ }
+
+ public String[] getUploadId()
+ {
+ return uploadId;
+ }
+
+ public void setAutoUpload(boolean isAutoUpload)
+ {
+ this.isAutoUpload = isAutoUpload;
+ }
+
+ public boolean isAutoUpload()
+ {
+ return isAutoUpload;
+ }
+
+ public int getLimitFile()
+ {
+ return limitFile;
+ }
+
+ public UploadResource[] getUploadResources() {
+ List<UploadResource> holder = new ArrayList<UploadResource>();
+ UploadService service = getApplicationComponent(UploadService.class);
+ for(int i = 0; i < uploadId.length; i++)
+ {
+ UploadResource uploadResource = service.getUploadResource(uploadId[i]);
+ if(uploadResource == null) continue;
+ holder.add(uploadResource) ;
+ }
+ return holder.toArray(new UploadResource[holder.size()]);
+ }
+
+ public UploadResource getUploadResource(String uploadId) {
+ UploadService service = getApplicationComponent(UploadService.class);
+ return service.getUploadResource(uploadId);
+ }
+
+ public InputStream[] getUploadDataAsStreams() throws FileNotFoundException
+ {
+ List<InputStream> holder = new ArrayList<InputStream>();
+ UploadService service = getApplicationComponent(UploadService.class);
+ for(int i = 0; i < uploadId.length; i++)
+ {
+ UploadResource uploadResource = service.getUploadResource(uploadId[i]);
+ if(uploadResource == null) continue;
+ File file = new File(uploadResource.getStoreLocation());
+ holder.add(new FileInputStream(file));
+ }
+ return holder.toArray(new InputStream[holder.size()]);
+ }
+
+ public InputStream getUploadDataAsStream(String uploadId) throws FileNotFoundException
+ {
+ UploadService service = getApplicationComponent(UploadService.class);
+ UploadResource uploadResource = service.getUploadResource(uploadId);
+ if(uploadResource == null) return null;
+ else return new FileInputStream(new File(uploadResource.getStoreLocation()));
+ }
+
+ public void decode(Object input, WebuiRequestContext context) throws Exception
+ {
+ }
+}
13 years, 2 months