[gatein-commits] gatein SVN: r5356 - in portal/branches/wci: component/application-registry/src/main/java/org/exoplatform/application/gadget and 43 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Mon Nov 29 11:47:42 EST 2010


Author: alain_defrance
Date: 2010-11-29 11:47:37 -0500 (Mon, 29 Nov 2010)
New Revision: 5356

Added:
   portal/branches/wci/component/application-registry/src/main/java/org/exoplatform/application/gadget/GadgetImporter.java
   portal/branches/wci/component/application-registry/src/main/java/org/exoplatform/application/gadget/RemoteImporter.java
   portal/branches/wci/component/identity/src/main/java/org/exoplatform/services/organization/idm/Tools.java
   portal/branches/wci/component/portal/src/main/java/org/exoplatform/portal/pom/config/cache/PortalNamesCache.java
   portal/branches/wci/component/portal/src/test/java/org/exoplatform/portal/config/TestConcurrencyDataStorage.java
   portal/branches/wci/component/web/security/src/main/java/org/exoplatform/web/security/security/AbstractCodec.java
   portal/branches/wci/component/web/security/src/main/java/org/exoplatform/web/security/security/ToThrowAwayCodec.java
   portal/branches/wci/docs/reference-guide/en/modules/PortalDevelopment/LocalizationConfiguration.xml
Removed:
   portal/branches/wci/component/application-registry/src/main/java/org/exoplatform/application/gadget/LocalImporter.java
Modified:
   portal/branches/wci/component/application-registry/src/main/java/org/exoplatform/application/gadget/GadgetDeployer.java
   portal/branches/wci/component/application-registry/src/main/java/org/exoplatform/application/gadget/GadgetRegistryService.java
   portal/branches/wci/component/application-registry/src/main/java/org/exoplatform/application/gadget/ServletLocalImporter.java
   portal/branches/wci/component/application-registry/src/main/java/org/exoplatform/application/gadget/impl/GadgetRegistryServiceImpl.java
   portal/branches/wci/component/identity/src/main/java/org/exoplatform/services/organization/idm/GroupDAOImpl.java
   portal/branches/wci/component/identity/src/main/java/org/exoplatform/services/organization/idm/IDMUserListAccess.java
   portal/branches/wci/component/identity/src/main/java/org/exoplatform/services/organization/idm/IntegrationCache.java
   portal/branches/wci/component/identity/src/main/java/org/exoplatform/services/organization/idm/MembershipDAOImpl.java
   portal/branches/wci/component/identity/src/main/java/org/exoplatform/services/organization/idm/MembershipImpl.java
   portal/branches/wci/component/identity/src/main/java/org/exoplatform/services/organization/idm/MembershipTypeDAOImpl.java
   portal/branches/wci/component/identity/src/main/java/org/exoplatform/services/organization/idm/UserDAOImpl.java
   portal/branches/wci/component/portal/src/main/java/org/exoplatform/portal/config/model/Page.java
   portal/branches/wci/component/portal/src/main/java/org/exoplatform/portal/config/model/PortalConfig.java
   portal/branches/wci/component/portal/src/main/java/org/exoplatform/portal/pom/config/GlobalKey.java
   portal/branches/wci/component/portal/src/main/java/org/exoplatform/portal/pom/config/POMSession.java
   portal/branches/wci/component/portal/src/main/java/org/exoplatform/portal/pom/config/POMSessionManager.java
   portal/branches/wci/component/portal/src/test/java/org/exoplatform/portal/config/TestCache.java
   portal/branches/wci/component/portal/src/test/java/org/exoplatform/portal/config/TestDataStorage.java
   portal/branches/wci/component/scripting/src/main/java/org/exoplatform/groovyscript/GroovyTemplate.java
   portal/branches/wci/component/web/controller/src/main/java/org/exoplatform/web/WebAppController.java
   portal/branches/wci/component/web/resources/src/main/java/org/exoplatform/portal/application/Image.java
   portal/branches/wci/component/web/resources/src/main/java/org/exoplatform/portal/application/ResourceRequestFilter.java
   portal/branches/wci/component/web/resources/src/main/java/org/exoplatform/portal/resource/CachedStylesheet.java
   portal/branches/wci/component/web/resources/src/main/java/org/exoplatform/portal/resource/SkinService.java
   portal/branches/wci/component/web/resources/src/main/java/org/exoplatform/web/application/javascript/JavascriptConfigService.java
   portal/branches/wci/component/web/security/src/main/java/org/exoplatform/web/security/security/CookieTokenService.java
   portal/branches/wci/component/web/security/src/main/java/org/exoplatform/web/security/security/TokenContainer.java
   portal/branches/wci/component/web/server/src/main/java/org/exoplatform/upload/UploadService.java
   portal/branches/wci/docs/reference-guide/en/modules/PortalDevelopment.xml
   portal/branches/wci/examples/portal/war/src/main/webapp/WEB-INF/web.xml
   portal/branches/wci/gadgets/core/src/main/java/org/exoplatform/portal/gadget/core/ProxyServletFilter.java
   portal/branches/wci/gadgets/eXoGadgets/src/main/webapp/gadgets/rssAggregator/script.js
   portal/branches/wci/packaging/tomcat/integration/
   portal/branches/wci/pom.xml
   portal/branches/wci/portlet/dashboard/src/main/java/org/exoplatform/gadget/webui/component/UIGadgetPortlet.java
   portal/branches/wci/portlet/exoadmin/src/main/java/org/exoplatform/toolbar/webui/component/UIUserToolBarGroupPortlet.java
   portal/branches/wci/portlet/exoadmin/src/main/java/org/exoplatform/toolbar/webui/component/UIUserToolBarSitePortlet.java
   portal/branches/wci/portlet/exoadmin/src/main/webapp/groovy/applicationregistry/webui/component/UIGadgetInfo.gtmpl
   portal/branches/wci/portlet/exoadmin/src/main/webapp/skin/organization/webui/component/UIOrganizationPortlet/DefaultStylesheet.css
   portal/branches/wci/portlet/web/src/main/webapp/groovy/portal/webui/component/UIPortalNavigation.gtmpl
   portal/branches/wci/testsuite/selenium-snifftests/src/suite/org/exoplatform/portal/selenium/NewSnifftest/Test_SNF_PRL_37_ManageNavigationOfGroup.html
   portal/branches/wci/testsuite/selenium-snifftests/src/suite/org/exoplatform/portal/selenium/NewSnifftest/Test_SNF_PRL_49_ChangeApplicationWhenEditPagePropertiesOfNode.html
   portal/branches/wci/testsuite/selenium-snifftests/src/suite/org/exoplatform/portal/selenium/Test_PRL_03_01_001_CheckShowingGroupManagementForm.html
   portal/branches/wci/testsuite/selenium-snifftests/src/suite/org/exoplatform/portal/selenium/Test_PRL_03_05_012_AddSomeUsersIntoGroupInCaseAfterCommaHasSpace.html
   portal/branches/wci/testsuite/testdefinitions/GateIn_v3.2.x_MainFunctions_TestDefinition.ods
   portal/branches/wci/web/eXoResources/src/main/webapp/skin/DefaultSkin/portal/webui/component/customization/UIPageBrowser/Stylesheet.css
   portal/branches/wci/web/portal/src/main/webapp/WEB-INF/conf/organization/picketlink-idm/jboss-cache-cluster.xml
   portal/branches/wci/web/portal/src/main/webapp/WEB-INF/web.xml
   portal/branches/wci/web/portal/src/main/webapp/groovy/portal/webui/workspace/UIPortalApplication.gtmpl
   portal/branches/wci/web/portal/src/main/webapp/index.jsp
   portal/branches/wci/web/rest/src/main/webapp/WEB-INF/web.xml
   portal/branches/wci/webui/eXo/src/main/java/org/exoplatform/webui/organization/account/UIUserSelector.java
   portal/branches/wci/webui/framework/src/main/java/org/exoplatform/webui/core/UIComponentDecorator.java
   portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/application/localization/LocalizationFilter.java
   portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/application/UIPortletActionListener.java
   portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/container/UIContainerActionListener.java
   portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/container/UIContainerForm.java
   portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/javascript/JavascriptServlet.java
   portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/navigation/PageNavigationUtils.java
   portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/navigation/UINavigationNodeSelector.java
   portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/navigation/UIPortalNavigation.java
   portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/page/UIPageActionListener.java
   portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/page/UIPageBrowser.java
   portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/page/UIPageForm.java
   portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/workspace/UIMaskWorkspace.java
   portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/workspace/UIPortalApplicationLifecycle.java
   portal/branches/wci/webui/portlet/src/main/java/org/exoplatform/webui/application/portlet/PortletApplicationController.java
Log:
merged from trunk 5342

Modified: portal/branches/wci/component/application-registry/src/main/java/org/exoplatform/application/gadget/GadgetDeployer.java
===================================================================
--- portal/branches/wci/component/application-registry/src/main/java/org/exoplatform/application/gadget/GadgetDeployer.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/component/application-registry/src/main/java/org/exoplatform/application/gadget/GadgetDeployer.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -19,8 +19,6 @@
 package org.exoplatform.application.gadget;
 
 import org.exoplatform.application.gadget.impl.GadgetRegistryServiceImpl;
-import org.exoplatform.commons.chromattic.ChromatticLifeCycle;
-import org.exoplatform.commons.chromattic.SessionContext;
 import org.exoplatform.commons.xml.DocumentSource;
 import org.exoplatform.commons.xml.XMLValidator;
 import org.exoplatform.container.ExoContainerContext;
@@ -40,11 +38,10 @@
 import org.w3c.dom.NodeList;
 
 import javax.servlet.ServletContext;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import java.io.InputStream;
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * @author <a href="mailto:julien.viet at exoplatform.com">Julien Viet</a>
@@ -115,28 +112,27 @@
 
    private void handle(ServletContext scontext, URL gadgetsURL)
    {
-      ChromatticLifeCycle lifeCycle = gadgetRegistryService.getChromatticLifeCycle();
-      lifeCycle.openContext();
       try
       {
+         List<GadgetImporter> importers = new ArrayList<GadgetImporter>();
          Document docXML = validator.validate(DocumentSource.create(gadgetsURL));
          NodeList nodeList = docXML.getElementsByTagName("gadget");
          for (int i = 0; i < nodeList.getLength(); i++)
          {
             Element gadgetElement = (Element)nodeList.item(i);
             String gadgetName = gadgetElement.getAttribute("name");
-            log.debug("About to import gadget " + gadgetName);
+
+            //
+            log.debug("About to parse gadget " + gadgetName);
             Element pathElt = XMLTools.getUniqueChild(gadgetElement, "path", false);
+            GadgetImporter importer = null;
             if (pathElt != null)
             {
                String path = XMLTools.asString(pathElt, true);
-               ServletLocalImporter importer = new ServletLocalImporter(
+               importer = new ServletLocalImporter(
                   gadgetName,
-                  gadgetRegistryService.getRegistry(),
                   path,
-                  scontext,
-                  true);
-               importer.doImport();
+                  scontext);
             }
             else
             {
@@ -144,24 +140,26 @@
                if (urlElt != null)
                {
                   String url = XMLTools.asString(urlElt, true);
-                  ServletLocalImporter importer = new ServletLocalImporter(
+                  importer = new RemoteImporter(
                      gadgetName,
-                     gadgetRegistryService.getRegistry(),
-                     url, 
-                     scontext,
-                     false);
-                  importer.doImport();
+                     url);
                }
             }
+
+            //
+            if (importer != null)
+            {
+               importers.add(importer);
+               log.debug("Add gadget " + gadgetName + " to gadget imports");
+            }
          }
+
+         // Import everything
+         gadgetRegistryService.deploy(importers);
       }
       catch (Exception e)
       {
          log.error("Could not process gadget file " + gadgetsURL, e);
       }
-      finally
-      {
-         lifeCycle.closeContext(true);
-      }
    }
 }

Copied: portal/branches/wci/component/application-registry/src/main/java/org/exoplatform/application/gadget/GadgetImporter.java (from rev 5342, portal/trunk/component/application-registry/src/main/java/org/exoplatform/application/gadget/GadgetImporter.java)
===================================================================
--- portal/branches/wci/component/application-registry/src/main/java/org/exoplatform/application/gadget/GadgetImporter.java	                        (rev 0)
+++ portal/branches/wci/component/application-registry/src/main/java/org/exoplatform/application/gadget/GadgetImporter.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -0,0 +1,133 @@
+/*
+ * 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.
+ */
+
+package org.exoplatform.application.gadget;
+
+import org.apache.shindig.common.uri.Uri;
+import org.apache.shindig.gadgets.spec.GadgetSpec;
+import org.apache.shindig.gadgets.spec.ModulePrefs;
+import org.exoplatform.application.gadget.impl.GadgetDefinition;
+import org.gatein.common.logging.Logger;
+import org.gatein.common.logging.LoggerFactory;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+/**
+ * @author <a href="mailto:julien.viet at exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+public abstract class GadgetImporter
+{
+
+   /** . */
+   private static final Logger log = LoggerFactory.getLogger(GadgetImporter.class);
+
+   /** The gadget name as seen by GateIn. */
+   private String gadgetName;
+
+   /** The gadget uri. */
+   private String gadgetURI;
+
+   protected GadgetImporter(
+      String gadgetName,
+      String gadgetURI)
+   {
+      this.gadgetName = gadgetName;
+      this.gadgetURI = gadgetURI;
+   }
+
+   public String getGadgetName()
+   {
+      return gadgetName;
+   }
+
+   public String getGadgetURI()
+   {
+      return gadgetURI;
+   }
+
+   protected abstract byte[] getGadgetBytes(String gadgetURI) throws IOException;
+
+   protected abstract String getGadgetURL(String gadgetURI) throws Exception;
+
+   protected abstract void process(String gadgetURI, GadgetDefinition def) throws Exception;
+
+   private String getGadgetTitle(ModulePrefs prefs, String defaultValue)
+   {
+      String title = prefs.getDirectoryTitle();
+      if (title == null || title.trim().length() < 1)
+      {
+         title = prefs.getTitle();
+      }
+      if (title == null || title.trim().length() < 1)
+      {
+         return defaultValue;
+      }
+      return title;
+   }
+
+   public void doImport(GadgetDefinition def) throws Exception
+   {
+      // Get bytes
+      byte[] bytes = getGadgetBytes(gadgetURI);
+      if (bytes == null)
+      {
+         log.error("Cannot import gadget " + gadgetURI + " because its data could not be found");
+         return;
+      }
+
+      // Get encoding
+      String encoding = EncodingDetector.detect(new ByteArrayInputStream(bytes));
+
+      //
+      String gadget = new String(bytes, encoding);
+
+      //
+      String gadgetURL = getGadgetURL(gadgetURI);
+      GadgetSpec spec = new GadgetSpec(Uri.parse(gadgetURL), gadget);
+      ModulePrefs prefs = spec.getModulePrefs();
+
+
+      //
+      String description = prefs.getDescription();
+      String thumbnail = prefs.getThumbnail().toString();
+      String title = getGadgetTitle(prefs, gadgetName);
+      String referenceURL = prefs.getTitleUrl().toString();
+
+      //
+      log.info("Importing gadget name=" + gadgetName + " description=" + description + " thumbnail=" + thumbnail + " title=" +
+               thumbnail + " title=" + title);
+
+      //
+      def.setDescription(description);
+      def.setThumbnail(thumbnail); // Do something better than that
+      def.setTitle(title);
+      def.setReferenceURL(referenceURL);
+
+      //
+      process(gadgetURI, def);
+   }
+
+   @Override
+   public String toString()
+   {
+      return getClass().getSimpleName() + "[name=" + getGadgetName() + ",path=" + getGadgetURI() + "]";
+   }
+}

Modified: portal/branches/wci/component/application-registry/src/main/java/org/exoplatform/application/gadget/GadgetRegistryService.java
===================================================================
--- portal/branches/wci/component/application-registry/src/main/java/org/exoplatform/application/gadget/GadgetRegistryService.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/component/application-registry/src/main/java/org/exoplatform/application/gadget/GadgetRegistryService.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -33,6 +33,13 @@
 {
 
    /**
+    * Deploy a set of gadgets.
+    *
+    * @param gadgets the gadgets to deploy
+    */
+   public void deploy(Iterable<GadgetImporter> gadgets);
+
+   /**
     * Return Gadget object retrieved from database by its name.
     * 
     * @param name the name of gadget

Deleted: portal/branches/wci/component/application-registry/src/main/java/org/exoplatform/application/gadget/LocalImporter.java
===================================================================
--- portal/branches/wci/component/application-registry/src/main/java/org/exoplatform/application/gadget/LocalImporter.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/component/application-registry/src/main/java/org/exoplatform/application/gadget/LocalImporter.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -1,247 +0,0 @@
-/*
- * 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.
- */
-
-package org.exoplatform.application.gadget;
-
-import org.apache.shindig.common.uri.Uri;
-import org.apache.shindig.gadgets.spec.GadgetSpec;
-import org.apache.shindig.gadgets.spec.ModulePrefs;
-import org.chromattic.ext.ntdef.NTFolder;
-import org.chromattic.ext.ntdef.Resource;
-import org.exoplatform.application.gadget.impl.GadgetDefinition;
-import org.exoplatform.application.gadget.impl.GadgetRegistry;
-import org.exoplatform.application.gadget.impl.LocalGadgetData;
-import org.exoplatform.application.gadget.impl.RemoteGadgetData;
-import org.gatein.common.logging.Logger;
-import org.gatein.common.logging.LoggerFactory;
-import org.gatein.common.net.URLTools;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.net.URL;
-
-/**
- * @author <a href="mailto:julien.viet at exoplatform.com">Julien Viet</a>
- * @version $Revision$
- */
-public abstract class LocalImporter
-{
-
-   /** . */
-   private static final Logger log = LoggerFactory.getLogger(LocalImporter.class);
-
-   /** The gadget name as seen by GateIn. */
-   private String name;
-
-   /** The gadget registry. */
-   private GadgetRegistry registry;
-
-   /** The gadget path. */
-   private String gadgetPath;
-
-   /** . */
-   private boolean local;
-
-   /** Used temporarily when importing resources. */
-   private NTFolder folder;
-
-   protected LocalImporter(
-      String name,
-      GadgetRegistry registry,
-      String gadgetPath,
-      boolean local)
-   {
-      this.name = name;
-      this.registry = registry;
-      this.gadgetPath = gadgetPath;
-      this.local = local;
-   }
-
-   private byte[] getGadgetBytes() throws IOException
-   {
-      if (local)
-      {
-         return getContent(gadgetPath);
-      }
-      else
-      {
-         URL url = new URL(gadgetPath);
-         return URLTools.getContent(url, 5000, 5000);
-      }
-   }
-
-   private String getGadgetURL() throws Exception
-   {
-      if (local)
-      {
-         return "http://www.gatein.org";
-      }
-      else
-      {
-         return gadgetPath;
-      }
-   }
-
-   private String getGadgetTitle(ModulePrefs prefs, String defaultValue)
-   {
-      String title = prefs.getDirectoryTitle();
-      if (title == null || title.trim().length() < 1)
-      {
-         title = prefs.getTitle();
-      }
-      if (title == null || title.trim().length() < 1)
-      {
-         return defaultValue;
-      }
-      return title;
-   }
-
-   public void doImport() throws Exception
-   {
-      if (registry.getGadget(name) != null)
-      {
-         log.debug("Will not import existing gagdet " + name);
-         return;
-      }
-
-      // Get bytes
-      byte[] bytes = getGadgetBytes();
-      if (bytes == null)
-      {
-         log.error("Cannot import gadget " + gadgetPath + " because its data could not be found");
-         return;
-      }
-
-      // Get encoding
-      String encoding = EncodingDetector.detect(new ByteArrayInputStream(bytes));
-
-      //
-      String gadget = new String(bytes, encoding);
-
-      //
-      String gadgetURL = getGadgetURL();
-      GadgetSpec spec = new GadgetSpec(Uri.parse(gadgetURL), gadget);
-      ModulePrefs prefs = spec.getModulePrefs();
-
-      //
-      GadgetDefinition def = registry.addGadget(name);
-
-      //
-      String description = prefs.getDescription();
-      String thumbnail = prefs.getThumbnail().toString();
-      String title = getGadgetTitle(prefs, name);
-      String referenceURL = prefs.getTitleUrl().toString();
-
-      //
-      log.info("Importing gadget name=" + name + " description=" + description + " thumbnail=" + thumbnail + " title=" +
-               thumbnail + " title=" + title);
-
-      //
-      def.setDescription(description);
-      def.setThumbnail(thumbnail); // Do something better than that
-      def.setTitle(title);
-      def.setReferenceURL(referenceURL);
-      def.setLocal(local);
-
-      //
-      if (local)
-      {
-         LocalGadgetData data = (LocalGadgetData)def.getData();
-
-         //
-         String fileName = getName(gadgetPath);
-         data.setFileName(fileName);
-
-         // Import resource
-         folder = data.getResources();
-         String folderPath = getParent(gadgetPath);
-         visitChildren(folderPath);
-         folder = null;
-      }
-      else
-      {
-         RemoteGadgetData data = (RemoteGadgetData)def.getData();
-
-         // Set remote URL
-         data.setURL(gadgetPath);
-      }
-   }
-
-   private void visit(String resourcePath) throws Exception
-   {
-      String name = getName(resourcePath);
-      if (isFile(resourcePath))
-      {
-         byte[] content = getContent(resourcePath);
-
-         //
-         if (content != null)
-         {
-            String mimeType = getMimeType(name);
-
-            //
-            if (mimeType == null)
-            {
-               mimeType = "application/octet-stream";
-            }
-
-            // We can detect encoding for XML files
-            String encoding = null;
-            if ("application/xml".equals(mimeType))
-            {
-               encoding = EncodingDetector.detect(new ByteArrayInputStream(content));
-            }
-
-            // Correct mime type for gadgets
-            if (resourcePath.equals(gadgetPath)) {
-               mimeType = LocalGadgetData.GADGET_MIME_TYPE;
-            }
-
-            //
-            folder.createFile(name, new Resource(mimeType, encoding, content));
-         }
-      }
-      else
-      {
-         folder = folder.createFolder(name);
-         visitChildren(resourcePath);
-         folder = folder.getParent();
-      }
-   }
-
-   private void visitChildren(String folderPath) throws Exception
-   {
-      for (String childPath : getChildren(folderPath))
-      {
-         visit(childPath);
-      }
-   }
-
-   public abstract String getName(String resourcePath) throws IOException;
-
-   public abstract String getParent(String resourcePath) throws IOException;
-
-   public abstract byte[] getContent(String filePath) throws IOException;
-
-   public abstract Iterable<String> getChildren(String folderPath) throws IOException;
-
-   public abstract boolean isFile(String resourcePath) throws IOException;
-
-   public abstract String getMimeType(String fileName);
-}

Copied: portal/branches/wci/component/application-registry/src/main/java/org/exoplatform/application/gadget/RemoteImporter.java (from rev 5342, portal/trunk/component/application-registry/src/main/java/org/exoplatform/application/gadget/RemoteImporter.java)
===================================================================
--- portal/branches/wci/component/application-registry/src/main/java/org/exoplatform/application/gadget/RemoteImporter.java	                        (rev 0)
+++ portal/branches/wci/component/application-registry/src/main/java/org/exoplatform/application/gadget/RemoteImporter.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+package org.exoplatform.application.gadget;
+
+import org.exoplatform.application.gadget.impl.GadgetDefinition;
+import org.exoplatform.application.gadget.impl.RemoteGadgetData;
+import org.gatein.common.net.URLTools;
+
+import java.io.IOException;
+import java.net.URL;
+
+/**
+ * @author <a href="mailto:julien.viet at exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+public class RemoteImporter extends GadgetImporter
+{
+
+   public RemoteImporter(String name, String gadgetPath)
+   {
+      super(name, gadgetPath);
+   }
+
+   @Override
+   protected byte[] getGadgetBytes(String gadgetURI) throws IOException
+   {
+      URL url = new URL(gadgetURI);
+      return URLTools.getContent(url, 5000, 5000);
+   }
+
+   @Override
+   protected String getGadgetURL(String gadgetURI) throws Exception
+   {
+      return "http://www.gatein.org";
+   }
+
+   @Override
+   protected void process(String gadgetURI, GadgetDefinition def) throws Exception
+   {
+      def.setLocal(false);
+
+      //
+      RemoteGadgetData data = (RemoteGadgetData)def.getData();
+
+      // Set remote URL
+      data.setURL(gadgetURI);
+   }
+}

Modified: portal/branches/wci/component/application-registry/src/main/java/org/exoplatform/application/gadget/ServletLocalImporter.java
===================================================================
--- portal/branches/wci/component/application-registry/src/main/java/org/exoplatform/application/gadget/ServletLocalImporter.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/component/application-registry/src/main/java/org/exoplatform/application/gadget/ServletLocalImporter.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -18,12 +18,16 @@
  */
 package org.exoplatform.application.gadget;
 
-import org.exoplatform.application.gadget.impl.GadgetRegistry;
+import org.chromattic.ext.ntdef.NTFolder;
+import org.chromattic.ext.ntdef.Resource;
+import org.exoplatform.application.gadget.impl.GadgetDefinition;
+import org.exoplatform.application.gadget.impl.LocalGadgetData;
 import org.gatein.common.io.IOTools;
 import org.gatein.common.logging.Logger;
 import org.gatein.common.logging.LoggerFactory;
 
 import javax.servlet.ServletContext;
+import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Set;
@@ -32,7 +36,7 @@
  * @author <a href="mailto:julien.viet at exoplatform.com">Julien Viet</a>
  * @version $Revision$
  */
-public class ServletLocalImporter extends LocalImporter
+public class ServletLocalImporter extends GadgetImporter
 {
 
    /** . */
@@ -41,22 +45,103 @@
    /** . */
    private final ServletContext servletContext;
 
+   /** Used temporarily when importing resources. */
+   private NTFolder folder;
+
    public ServletLocalImporter(
       String name,
-      GadgetRegistry registry,
       String gadgetPath,
-      ServletContext servletContext,
-      boolean local)
+      ServletContext servletContext)
    {
-      super(name, registry, gadgetPath, local);
+      super(name, gadgetPath);
 
       //
       this.servletContext = servletContext;
    }
 
    @Override
-   public String getName(String resourcePath) throws IOException
+   protected byte[] getGadgetBytes(String gadgetURI) throws IOException
    {
+      return getContent(gadgetURI);
+   }
+
+   @Override
+   protected String getGadgetURL(String gadgetURI) throws Exception
+   {
+      return gadgetURI;
+   }
+
+   @Override
+   protected void process(String gadgetURI, GadgetDefinition def) throws Exception
+   {
+      def.setLocal(true);
+
+      //
+      LocalGadgetData data = (LocalGadgetData)def.getData();
+
+      //
+      String fileName = getName(gadgetURI);
+      data.setFileName(fileName);
+
+      // Import resource
+      folder = data.getResources();
+      String folderPath = getParent(gadgetURI);
+      visitChildren(gadgetURI, folderPath);
+      folder = null;
+   }
+
+   private void visit(String uri, String resourcePath) throws Exception
+   {
+      String name = getName(resourcePath);
+      if (isFile(resourcePath))
+      {
+         byte[] content = getContent(resourcePath);
+
+         //
+         if (content != null)
+         {
+            String mimeType = getMimeType(name);
+
+            //
+            if (mimeType == null)
+            {
+               mimeType = "application/octet-stream";
+            }
+
+            // We can detect encoding for XML files
+            String encoding = null;
+            if ("application/xml".equals(mimeType))
+            {
+               encoding = EncodingDetector.detect(new ByteArrayInputStream(content));
+            }
+
+            // Correct mime type for gadgets
+            if (resourcePath.equals(uri)) {
+               mimeType = LocalGadgetData.GADGET_MIME_TYPE;
+            }
+
+            //
+            folder.createFile(name, new Resource(mimeType, encoding, content));
+         }
+      }
+      else
+      {
+         folder = folder.createFolder(name);
+         visitChildren(uri, resourcePath);
+         folder = folder.getParent();
+      }
+   }
+
+   private void visitChildren(String gadgetURI, String folderPath) throws Exception
+   {
+      for (String childPath : getChildren(folderPath))
+      {
+         visit(gadgetURI, childPath);
+      }
+   }
+
+   private String getName(String resourcePath) throws IOException
+   {
       // It's a directory, remove the trailing '/'
       if (resourcePath.endsWith("/"))
       {
@@ -70,8 +155,7 @@
       return resourcePath.substring(index + 1);
    }
 
-   @Override
-   public String getParent(String resourcePath) throws IOException
+   private String getParent(String resourcePath) throws IOException
    {
       // It's a directory, remove the trailing '/'
       if (resourcePath.endsWith("/"))
@@ -86,8 +170,7 @@
       return resourcePath.substring(0, index + 1);
    }
 
-   @Override
-   public byte[] getContent(String filePath) throws IOException
+   private byte[] getContent(String filePath) throws IOException
    {
       InputStream in = servletContext.getResourceAsStream(filePath);
       if (in == null)
@@ -101,21 +184,18 @@
       }
    }
 
-   @Override
-   public Iterable<String> getChildren(String folderPath) throws IOException
+   private Iterable<String> getChildren(String folderPath) throws IOException
    {
-      @SuppressWarnings("unchecked") Set resourcePaths = servletContext.getResourcePaths(folderPath);
+      @SuppressWarnings("unchecked") Set<String> resourcePaths = servletContext.getResourcePaths(folderPath);
       return resourcePaths;
    }
 
-   @Override
-   public boolean isFile(String resourcePath) throws IOException
+   private boolean isFile(String resourcePath) throws IOException
    {
       return !resourcePath.endsWith("/");
    }
 
-   @Override
-   public String getMimeType(String fileName)
+   private String getMimeType(String fileName)
    {
       return servletContext.getMimeType(fileName);
    }

Modified: portal/branches/wci/component/application-registry/src/main/java/org/exoplatform/application/gadget/impl/GadgetRegistryServiceImpl.java
===================================================================
--- portal/branches/wci/component/application-registry/src/main/java/org/exoplatform/application/gadget/impl/GadgetRegistryServiceImpl.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/component/application-registry/src/main/java/org/exoplatform/application/gadget/impl/GadgetRegistryServiceImpl.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -23,6 +23,7 @@
 import org.chromattic.ext.ntdef.Resource;
 import org.exoplatform.application.gadget.Gadget;
 import org.exoplatform.application.gadget.GadgetRegistryService;
+import org.exoplatform.application.gadget.GadgetImporter;
 import org.exoplatform.application.registry.impl.ApplicationRegistryChromatticLifeCycle;
 import org.exoplatform.commons.chromattic.ChromatticLifeCycle;
 import org.exoplatform.commons.chromattic.ChromatticManager;
@@ -30,11 +31,14 @@
 import org.exoplatform.container.xml.InitParams;
 import org.exoplatform.container.xml.PropertiesParam;
 import org.exoplatform.container.xml.ValueParam;
+import org.gatein.common.logging.Logger;
+import org.gatein.common.logging.LoggerFactory;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
+import java.util.concurrent.Callable;
 
 /**
  * @author <a href="mailto:julien.viet at exoplatform.com">Julien Viet</a>
@@ -44,6 +48,9 @@
 {
 
    /** . */
+   private final Logger log = LoggerFactory.getLogger(GadgetRegistryServiceImpl.class);
+
+   /** . */
    private static final String DEFAULT_DEVELOPER_GROUP = "/platform/administrators";
 
    /** . */
@@ -120,13 +127,23 @@
       return registry;
    }
 
-   public ChromatticLifeCycle getChromatticLifeCycle()
+   // ***************
+
+   public void deploy(Iterable<GadgetImporter> gadgets)
    {
-      return chromatticLifeCycle;
+      for (GadgetImporter importer : gadgets)
+      {
+         try
+         {
+            new DeployTask(importer).call();
+         }
+         catch (Exception e)
+         {
+            log.error("Could not process gadget file " + importer, e);
+         }
+      }
    }
 
-   // ***************
-
    public Gadget getGadget(String name) throws Exception
    {
       GadgetRegistry registry = getRegistry();
@@ -285,4 +302,40 @@
    {
       return hostName;
    }
+
+   private class DeployTask implements Callable<Boolean>
+   {
+
+      /** . */
+      private final GadgetImporter importer;
+
+      private DeployTask(GadgetImporter importer)
+      {
+         this.importer = importer;
+      }
+
+      public Boolean call() throws Exception
+      {
+         chromatticLifeCycle.openContext();
+         try
+         {
+            boolean done = false;
+            if (getRegistry().getGadget(importer.getGadgetName()) == null)
+            {
+               GadgetDefinition def = getRegistry().addGadget(importer.getGadgetName());
+               importer.doImport(def);
+               done = true;
+            }
+            else
+            {
+               log.debug("Will not import existing gagdet " + importer.getGadgetName());
+            }
+            return done;
+         }
+         finally
+         {
+            chromatticLifeCycle.closeContext(true);
+         }
+      }
+   }
 }

Modified: portal/branches/wci/component/identity/src/main/java/org/exoplatform/services/organization/idm/GroupDAOImpl.java
===================================================================
--- portal/branches/wci/component/identity/src/main/java/org/exoplatform/services/organization/idm/GroupDAOImpl.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/component/identity/src/main/java/org/exoplatform/services/organization/idm/GroupDAOImpl.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -22,6 +22,9 @@
 import org.exoplatform.services.organization.Group;
 import org.exoplatform.services.organization.GroupEventListener;
 import org.exoplatform.services.organization.GroupHandler;
+import org.gatein.common.logging.LogLevel;
+import org.gatein.common.logging.Logger;
+import org.gatein.common.logging.LoggerFactory;
 import org.picketlink.idm.api.Attribute;
 import org.picketlink.idm.api.IdentitySession;
 import org.picketlink.idm.impl.api.SimpleAttribute;
@@ -35,10 +38,10 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 
+
+
 /*
  * @author <a href="mailto:boleslaw.dawidowicz at redhat.com">Boleslaw Dawidowicz</a>
  */
@@ -73,16 +76,50 @@
 
    final public Group createGroupInstance()
    {
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "createGroupInstance",
+            null
+         );
+      }
       return new ExtGroup();
    }
 
    public void createGroup(Group group, boolean broadcast) throws Exception
    {
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "createGroup",
+            new Object[]{
+               "broadcast", broadcast
+            }
+         );
+      }
       addChild(null, group, broadcast);
    }
 
    public void addChild(Group parent, Group child, boolean broadcast) throws Exception
    {
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "addChild",
+            new Object[]{
+               "parent", parent,
+               "child", child,
+               "broadcast", broadcast
+            }
+         );
+      }
+
       org.picketlink.idm.api.Group parentGroup = null;
 
       String childPLGroupName = getPLIDMGroupName(child.getGroupName());
@@ -148,6 +185,19 @@
 
    public void saveGroup(Group group, boolean broadcast) throws Exception
    {
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "saveGroup",
+            new Object[]{
+               "group", group,
+               "broadcast", broadcast
+            }
+         );
+      }
+
       if (broadcast)
       {
          preSave(group, false);
@@ -161,6 +211,19 @@
 
    public Group removeGroup(Group group, boolean broadcast) throws Exception
    {
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "removeGroup",
+            new Object[]{
+               "group", group,
+               "broadcast", broadcast
+            }
+         );
+      }
+
       if (broadcast)
       {
          preDelete(group);
@@ -228,6 +291,19 @@
 
    public Collection findGroupByMembership(String userName, String membershipType) throws Exception
    {
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "findGroupsByMembership",
+            new Object[]{
+               "userName", membershipType
+            }
+         );
+      }
+
+
       Collection<org.picketlink.idm.api.Role> allRoles = new HashSet();
 
       try
@@ -272,25 +348,84 @@
       }
 
       // UI has hardcoded casts to List
-      return new LinkedList<Group>(exoGroups);
+      Collection result = new LinkedList<Group>(exoGroups);
+
+      if (log.isTraceEnabled())
+      {
+        Tools.logMethodOut(
+            log,
+            LogLevel.TRACE,
+            "findGroupByMembership",
+            result
+         );
+      }
+      
+      return result;
    }
 
    //
    public Group findGroupById(String groupId) throws Exception
    {
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "findGroupById",
+            new Object[]{
+               "groupId", groupId
+            }
+         );
+      }
 
+
       org.picketlink.idm.api.Group jbidGroup = orgService.getJBIDMGroup(groupId);
 
       if (jbidGroup == null)
       {
+         if (log.isTraceEnabled())
+         {
+            Tools.logMethodOut(
+               log,
+               LogLevel.TRACE,
+               "findGroupById",
+               null
+            );
+      }
+
          return null;
       }
 
-      return convertGroup(jbidGroup);
+      Group result = convertGroup(jbidGroup);
+
+      if (log.isTraceEnabled())
+      {
+        Tools.logMethodOut(
+            log,
+            LogLevel.TRACE,
+            "findGroupById",
+            result
+         );
+      }
+
+      return result;
+
    }
 
    public Collection findGroups(Group parent) throws Exception
    {
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "findGroups",
+            new Object[]{
+               "parent", parent
+            }
+         );
+      }
+
       org.picketlink.idm.api.Group jbidGroup = null;
 
       if (parent == null)
@@ -396,6 +531,16 @@
          Collections.sort(results);
       }
 
+      if (log.isTraceEnabled())
+      {
+        Tools.logMethodOut(
+            log,
+            LogLevel.TRACE,
+            "findGroups",
+            results
+         );
+      }
+
       return results;
 
    }
@@ -403,6 +548,19 @@
    public Collection findGroupsOfUser(String user) throws Exception
    {
 
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "findGroupsOfUser",
+            new Object[]{
+               "user", user
+            }
+         );
+      }
+
+
       if (user == null)
       {
          // julien : integration bug
@@ -415,6 +573,17 @@
          // at org.exoplatform.organization.webui.component.GroupManagement.isMemberOfGroup(GroupManagement.java:72)
          // at org.exoplatform.organization.webui.component.GroupManagement.isAdministrator(GroupManagement.java:125)
          // at org.exoplatform.organization.webui.component.UIGroupExplorer.<init>(UIGroupExplorer.java:57)
+
+         if (log.isTraceEnabled())
+         {
+            Tools.logMethodOut(
+               log,
+               LogLevel.TRACE,
+               "findGroupsOfUser",
+               Collections.emptyList()
+            );
+      }
+
          return Collections.emptyList();
       }
 
@@ -439,12 +608,32 @@
 
       }
 
+      if (log.isTraceEnabled())
+      {
+        Tools.logMethodOut(
+            log,
+            LogLevel.TRACE,
+            "findGroupsOfUser",
+            exoGroups
+         );
+      }
+
       return exoGroups;
    }
 
    public Collection getAllGroups() throws Exception
    {
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "getAllGroups",
+            null
+         );
+      }
 
+
       Set<org.picketlink.idm.api.Group> plGroups = new HashSet<org.picketlink.idm.api.Group>();
 
       try
@@ -490,7 +679,19 @@
       }
 
       // UI has hardcoded casts to List
-      return new LinkedList<Group>(exoGroups);
+      Collection result = new LinkedList<Group>(exoGroups);
+
+      if (log.isTraceEnabled())
+      {
+        Tools.logMethodOut(
+            log,
+            LogLevel.TRACE,
+            "getAllGroups",
+            result
+         );
+      }
+
+      return result;
       
    }
 
@@ -529,6 +730,18 @@
 
    protected Group convertGroup(org.picketlink.idm.api.Group jbidGroup) throws Exception
    {
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "convertGroup",
+            new Object[]{
+               "jbidGroup", jbidGroup
+            }
+         );
+      }
+
       Map<String, Attribute> attrs = new HashMap();
 
       try
@@ -562,6 +775,16 @@
       // Resolve full ID
       String id = getGroupId(jbidGroup, null);
 
+      if (log.isTraceEnabled())
+      {
+        Tools.logMethodOut(
+            log,
+            LogLevel.TRACE,
+            "getGroupId",
+            id
+         );
+      }
+
       exoGroup.setId(id);
 
       // child of root
@@ -575,6 +798,16 @@
          exoGroup.setParentId(id.substring(0, id.lastIndexOf("/")));
       }
 
+      if (log.isTraceEnabled())
+      {
+        Tools.logMethodOut(
+            log,
+            LogLevel.TRACE,
+            "convertGroup",
+            exoGroup
+         );
+      }
+
       return exoGroup;
    }
 
@@ -589,6 +822,20 @@
    private String getGroupId(org.picketlink.idm.api.Group jbidGroup,
                              List<org.picketlink.idm.api.Group> processed) throws Exception
    {
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "getGroupId",
+            new Object[]{
+               "jbidGroup", jbidGroup,
+               "processed", processed
+            }
+         );
+      }
+
+
       // Check in cache
       if (getIntegrationCache() != null)
       {
@@ -633,6 +880,10 @@
       // Check if there is cross reference so we ended in a loop and break the process.
       if (parents.size() > 0 && processed.contains(parents.iterator().next()))
       {
+         if (log.isTraceEnabled())
+         {
+            log.trace("Detected looped relationship between groups!!!");
+         }
          processed.remove(processed.size() - 1);
          return CYCLIC_ID;
       }

Modified: portal/branches/wci/component/identity/src/main/java/org/exoplatform/services/organization/idm/IDMUserListAccess.java
===================================================================
--- portal/branches/wci/component/identity/src/main/java/org/exoplatform/services/organization/idm/IDMUserListAccess.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/component/identity/src/main/java/org/exoplatform/services/organization/idm/IDMUserListAccess.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -21,10 +21,14 @@
 
 import org.exoplatform.commons.utils.ListAccess;
 import org.exoplatform.services.organization.User;
+import org.gatein.common.logging.LogLevel;
+import org.gatein.common.logging.Logger;
+import org.gatein.common.logging.LoggerFactory;
 import org.picketlink.idm.api.SortOrder;
 import org.picketlink.idm.api.query.UserQuery;
 import org.picketlink.idm.api.query.UserQueryBuilder;
 
+
 import java.util.List;
 
 /*
@@ -32,6 +36,8 @@
  */
 public class IDMUserListAccess implements ListAccess<User>
 {
+   private static Logger log = LoggerFactory.getLogger(IDMUserListAccess.class);
+
    private final UserDAOImpl userDAO;
 
    private final PicketLinkIDMService idmService;
@@ -54,6 +60,19 @@
 
    public User[] load(int index, int length) throws Exception, IllegalArgumentException
    {
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "load",
+            new Object[]{
+               "index", index,
+               "length", length
+            }
+         );
+      }
+
       userQueryBuilder.page(index, length);
       UserQuery query = userQueryBuilder.sort(SortOrder.ASCENDING).createQuery();
       List<org.picketlink.idm.api.User> users = idmService.getIdentitySession().list(query);
@@ -67,21 +86,55 @@
          exoUsers[i] = UserDAOImpl.getPopulatedUser(user.getId(), idmService.getIdentitySession());
       }
 
+      if (log.isTraceEnabled())
+      {
+        Tools.logMethodOut(
+            log,
+            LogLevel.TRACE,
+            "load",
+            exoUsers
+         );
+      }
+
       return exoUsers;
    }
 
    public int getSize() throws Exception
    {
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "getSize",
+            null
+         );
+      }
+
+      int result;
+
       if (countAll)
       {
-         return idmService.getIdentitySession().getPersistenceManager().getUserCount();
+         result = idmService.getIdentitySession().getPersistenceManager().getUserCount();
       }
       else
       {
          userQueryBuilder.page(0, 0);
          UserQuery query = userQueryBuilder.sort(SortOrder.ASCENDING).createQuery();
-         return idmService.getIdentitySession().execute(query).size();
+         result = idmService.getIdentitySession().execute(query).size();
       }
 
+      if (log.isTraceEnabled())
+      {
+        Tools.logMethodOut(
+            log,
+            LogLevel.TRACE,
+            "getSize",
+            result
+         );
+      }
+
+      return result;
+
    }
 }

Modified: portal/branches/wci/component/identity/src/main/java/org/exoplatform/services/organization/idm/IntegrationCache.java
===================================================================
--- portal/branches/wci/component/identity/src/main/java/org/exoplatform/services/organization/idm/IntegrationCache.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/component/identity/src/main/java/org/exoplatform/services/organization/idm/IntegrationCache.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -149,15 +149,17 @@
 
       Node ioNode = getCache().getRoot().addChild(nodeFqn);
 
-      ioNode.put(NODE_OBJECT_KEY, id);
-
-      if (log.isLoggable(Level.FINER))
+      if (ioNode != null)
       {
+         ioNode.put(NODE_OBJECT_KEY, id);
 
-         log.finer(this.toString() + "GateIn group id cached. PLIDM group id: " + pLIDMId +
-            "GateIn group id: " + id + ";namespace=" + ns);
+         if (log.isLoggable(Level.FINER))
+         {
+
+            log.finer(this.toString() + "GateIn group id cached. PLIDM group id: " + pLIDMId +
+               "GateIn group id: " + id + ";namespace=" + ns);
+         }
       }
-
    }
 
    /**
@@ -201,14 +203,16 @@
 
       Node ioNode = getCache().getRoot().addChild(nodeFqn);
 
-      ioNode.put(NODE_OBJECT_KEY, rootGroup);
-
-      if (log.isLoggable(Level.FINER))
+      if (ioNode != null)
       {
+         ioNode.put(NODE_OBJECT_KEY, rootGroup);
 
-         log.finer(this.toString() + "GateIn root group stored in cache" + ";namespace=" + ns);
+         if (log.isLoggable(Level.FINER))
+         {
+
+            log.finer(this.toString() + "GateIn root group stored in cache" + ";namespace=" + ns);
+         }
       }
-
    }
 
    /**

Modified: portal/branches/wci/component/identity/src/main/java/org/exoplatform/services/organization/idm/MembershipDAOImpl.java
===================================================================
--- portal/branches/wci/component/identity/src/main/java/org/exoplatform/services/organization/idm/MembershipDAOImpl.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/component/identity/src/main/java/org/exoplatform/services/organization/idm/MembershipDAOImpl.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -26,12 +26,14 @@
 import org.exoplatform.services.organization.MembershipHandler;
 import org.exoplatform.services.organization.MembershipType;
 import org.exoplatform.services.organization.User;
+import org.gatein.common.logging.LogLevel;
+import org.gatein.common.logging.Logger;
+import org.gatein.common.logging.LoggerFactory;
 import org.picketlink.idm.api.IdentitySession;
 import org.picketlink.idm.api.Role;
 import org.picketlink.idm.api.RoleType;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
+
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
@@ -74,6 +76,19 @@
    public void createMembership(Membership m, boolean broadcast) throws Exception
    {
 
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "createMembership",
+            new Object[]{
+               "membership", m,
+               "broadcast", broadcast,
+            }
+         );
+      }
+
       if (broadcast)
       {
          preSave(m, true);
@@ -90,6 +105,21 @@
 
    public void linkMembership(User user, Group g, MembershipType mt, boolean broadcast) throws Exception
    {
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "linkMembership",
+            new Object[]{
+               "user", user,
+               "group", g,
+               "membershipType", mt,
+               "broadcast", broadcast
+            }
+         );
+      }
+
       if (g == null)
       {
          throw new InvalidNameException("Can not create membership record for " + user.getUserName()
@@ -154,7 +184,20 @@
 
    public void saveMembership(Membership m, boolean broadcast) throws Exception
    {
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "saveMembership",
+            new Object[]{
+               "membership", m,
+               "broadcast", broadcast
+            }
+         );
+      }
 
+
       String plGroupName = getPLIDMGroupName(getGroupNameFromId(m.getGroupId()));
 
       String groupId =
@@ -222,7 +265,20 @@
 
    public Membership removeMembership(String id, boolean broadcast) throws Exception
    {
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "removeMembership",
+            new Object[]{
+               "id", id,
+               "broadcast", broadcast
+            }
+         );
+      }
 
+
       Membership m = new MembershipImpl(id);
 
       String plGroupName = getPLIDMGroupName(getGroupNameFromId(m.getGroupId()));
@@ -308,6 +364,20 @@
    public Collection removeMembershipByUser(String userName, boolean broadcast) throws Exception
    {
 
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "removeMembershipByUser",
+            new Object[]{
+               "userName", userName,
+               "broadcast", broadcast
+            }
+         );
+      }
+
+
       Collection<Role> roles = new HashSet();
 
       try
@@ -388,6 +458,22 @@
 
    public Membership findMembershipByUserGroupAndType(String userName, String groupId, String type) throws Exception
    {
+
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "findMembershipByUserAndType",
+            new Object[]{
+               "userName", userName,
+               "groupId", groupId,
+               "type", type,
+            }
+         );
+      }
+
+
       String plGroupName = getPLIDMGroupName(getGroupNameFromId(groupId));
 
       String gid =
@@ -437,6 +523,8 @@
          hasMembership = true;
       }
 
+      Membership result = null;
+
       if (hasMembership)
       {
 
@@ -446,16 +534,51 @@
          m.setUserName(userName);
          m.setMembershipType(type);
 
-         return m;
+         result = m;
       }
-      return null;
+
+      if (log.isTraceEnabled())
+      {
+        Tools.logMethodOut(
+            log,
+            LogLevel.TRACE,
+            "findMembershipByUserGroupAndType",
+            result
+         );
+      }
+
+      return result;
    }
 
    public Collection findMembershipsByUserAndGroup(String userName, String groupId) throws Exception
    {
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "findMembershipByUserAndGroup",
+            new Object[]{
+               "userName", userName,
+               "groupId", groupId,
+            }
+         );
+      }
+
       if (userName == null)
       {
          // julien fix : if user name is null, need to check if we do need to return a special group
+
+         if (log.isTraceEnabled())
+         {
+            Tools.logMethodOut(
+               log,
+               LogLevel.TRACE,
+               "findMembershipByUserAndGroup",
+               Collections.emptyList()
+            );
+      }
+
          return Collections.emptyList();
       }
 
@@ -515,11 +638,36 @@
       }
 
       //TODO: Exo UI has hardcoded casts to List
-      return new LinkedList(memberships);
+      Collection result = new LinkedList(memberships);
+
+      if (log.isTraceEnabled())
+      {
+        Tools.logMethodOut(
+            log,
+            LogLevel.TRACE,
+            "findMembershipByUserAndGroup",
+            result
+         );
+      }
+
+      return result;
    }
 
    public Collection findMembershipsByUser(String userName) throws Exception
    {
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "findMembershipsByUser",
+            new Object[]{
+               "userName", userName
+            }
+         );
+      }
+
+
       Collection<Role> roles = new HashSet();
 
       try
@@ -577,7 +725,19 @@
       }
 
 
-      return new LinkedList(memberships);
+      Collection result = new LinkedList(memberships);
+
+      if (log.isTraceEnabled())
+      {
+        Tools.logMethodOut(
+            log,
+            LogLevel.TRACE,
+            "findMembershipsByUser",
+            result
+         );
+      }
+
+      return result;
    }
 
    public Collection findMembershipsByGroup(Group group) throws Exception
@@ -587,6 +747,18 @@
 
    public Collection findMembershipsByGroupId(String groupId) throws Exception
    {
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "findMembershipsByGroup",
+            new Object[]{
+               "groupId", groupId
+            }
+         );
+      }
+
       String plGroupName = getPLIDMGroupName(getGroupNameFromId(groupId));
 
       String gid =
@@ -656,11 +828,34 @@
          Collections.sort(results);
       }
 
+
+      if (log.isTraceEnabled())
+      {
+        Tools.logMethodOut(
+            log,
+            LogLevel.TRACE,
+            "findMembershipsByGroupId",
+            results
+         );
+      }
+
       return results;
    }
 
    public Membership findMembership(String id) throws Exception
    {
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "findMembership",
+            new Object[]{
+               "id", id
+            }
+         );
+      }
+
       Membership m = new MembershipImpl(id);
 
       String plGroupName = getPLIDMGroupName(getGroupNameFromId(m.getGroupId()));
@@ -675,6 +870,15 @@
          if (isCreateMembership(m.getMembershipType()) &&
              getIdentitySession().getRoleManager().hasRole(m.getUserName(), groupId, m.getMembershipType()))
          {
+            if (log.isTraceEnabled())
+            {
+               Tools.logMethodOut(
+                  log,
+                  LogLevel.TRACE,
+                  "findMembership",
+                  m
+               );
+            }
             return m;
          }
       }
@@ -690,6 +894,16 @@
          if (isAssociationMapped() && getAssociationMapping().equals(m.getMembershipType()) &&
              getIdentitySession().getRelationshipManager().isAssociatedByKeys(groupId, m.getUserName()))
          {
+            if (log.isTraceEnabled())
+            {
+               Tools.logMethodOut(
+                  log,
+                  LogLevel.TRACE,
+                  "findMembership",
+                  m
+               );
+            }
+
             return m;
          }
       }
@@ -700,6 +914,15 @@
 
       }
 
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodOut(
+            log,
+            LogLevel.TRACE,
+            "findMembership",
+            null
+         );
+      }
 
       return null;
    }

Modified: portal/branches/wci/component/identity/src/main/java/org/exoplatform/services/organization/idm/MembershipImpl.java
===================================================================
--- portal/branches/wci/component/identity/src/main/java/org/exoplatform/services/organization/idm/MembershipImpl.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/component/identity/src/main/java/org/exoplatform/services/organization/idm/MembershipImpl.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -157,4 +157,14 @@
 
       return userName.compareTo(m.getUserName());  
    }
+
+   @Override
+   public String toString()
+   {
+      return "MembershipImpl{" +
+         "membershipType='" + membershipType + '\'' +
+         ", userName='" + userName + '\'' +
+         ", groupId='" + groupId + '\'' +
+         '}';
+   }
 }

Modified: portal/branches/wci/component/identity/src/main/java/org/exoplatform/services/organization/idm/MembershipTypeDAOImpl.java
===================================================================
--- portal/branches/wci/component/identity/src/main/java/org/exoplatform/services/organization/idm/MembershipTypeDAOImpl.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/component/identity/src/main/java/org/exoplatform/services/organization/idm/MembershipTypeDAOImpl.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -22,6 +22,7 @@
 import org.exoplatform.services.organization.MembershipType;
 import org.exoplatform.services.organization.MembershipTypeHandler;
 import org.exoplatform.services.organization.impl.MembershipTypeImpl;
+import org.gatein.common.logging.LogLevel;
 import org.gatein.common.logging.Logger;
 import org.gatein.common.logging.LoggerFactory;
 import org.picketlink.idm.api.IdentitySession;
@@ -71,6 +72,20 @@
 
    public MembershipType createMembershipType(MembershipType mt, boolean broadcast) throws Exception
    {
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "createMembershipType",
+            new Object[]{
+               "membershipType", mt,
+               "broadcast", broadcast
+            }
+         );
+      }
+
+
       Date now = new Date();
       mt.setCreatedDate(now);
       mt.setModifiedDate(now);
@@ -83,6 +98,18 @@
 
    public MembershipType saveMembershipType(MembershipType mt, boolean broadcast) throws Exception
    {
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "saveMembershipType",
+            new Object[]{
+               "membershipType", mt,
+               "broadcast", broadcast
+            }
+         );
+      }
       Date now = new Date();
       mt.setModifiedDate(now);
       updateMembershipType(mt);
@@ -91,6 +118,18 @@
 
    public MembershipType findMembershipType(String name) throws Exception
    {
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "findMembershipType",
+            new Object[]{
+               "name", name
+            }
+         );
+      }
+
       RoleType rt = getIdentitySession().getRoleManager().getRoleType(name);
 
       MembershipType mt = null;
@@ -101,11 +140,35 @@
          populateMembershipType(mt);
       }
 
+      if (log.isTraceEnabled())
+      {
+        Tools.logMethodOut(
+            log,
+            LogLevel.TRACE,
+            "findMembershipType",
+            mt
+         );
+      }
+
       return mt;
    }
 
    public MembershipType removeMembershipType(String name, boolean broadcast) throws Exception
    {
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "removeMembershipType",
+            new Object[]{
+               "name", name,
+               "broadcast", broadcast
+            }
+         );
+      }
+
+
       MembershipType mt = findMembershipType(name);
 
       if (mt != null)
@@ -119,6 +182,15 @@
 
    public Collection findMembershipTypes() throws Exception
    {
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "findMembershipTypes",
+            null
+         );
+      }
 
       Collection<RoleType> rts = getIdentitySession().getRoleManager().findRoleTypes();
 
@@ -131,6 +203,16 @@
          mts.add(mt);
       }
 
+      if (log.isTraceEnabled())
+      {
+        Tools.logMethodOut(
+            log,
+            LogLevel.TRACE,
+            "findMembershipTypes",
+            mts
+         );
+      }
+
       return mts;
    }
 

Copied: portal/branches/wci/component/identity/src/main/java/org/exoplatform/services/organization/idm/Tools.java (from rev 5342, portal/trunk/component/identity/src/main/java/org/exoplatform/services/organization/idm/Tools.java)
===================================================================
--- portal/branches/wci/component/identity/src/main/java/org/exoplatform/services/organization/idm/Tools.java	                        (rev 0)
+++ portal/branches/wci/component/identity/src/main/java/org/exoplatform/services/organization/idm/Tools.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -0,0 +1,106 @@
+package org.exoplatform.services.organization.idm;
+
+import org.gatein.common.logging.LogLevel;
+import org.gatein.common.logging.Logger;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+/*
+* JBoss, a division of Red Hat
+* Copyright 2010, Red Hat Middleware, LLC, and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* 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.
+*/
+
+/**
+ * Some helper methods
+ */
+public class Tools
+{
+   public static void logMethodIn(Logger log, LogLevel level, String methodName, Object[] args)
+   {
+      try
+      {
+         StringBuilder sb = new StringBuilder();
+         sb.append("Method '")
+            .append(methodName)
+            .append("' called with arguments: ");
+
+         if (args != null)
+         {
+            for (Object arg : args)
+            {
+               if (arg != null && arg instanceof Object[])
+               {
+                  sb.append(Arrays.toString((Object[])arg))
+                     .append("; ");
+               }
+               else
+               {
+                  sb.append(arg)
+                     .append("; ");
+               }
+            }
+         }
+         else
+         {
+            sb.append(args);
+         }
+
+         log.log(level, sb.toString());
+      }
+      catch (Throwable t)
+      {
+         log.log(level, "Error in logging code block (not related to application code): ", t);
+      }
+
+   }
+
+   public static void logMethodOut(Logger log, LogLevel level, String methodName, Object result)
+   {
+      try
+      {
+         StringBuilder sb = new StringBuilder();
+         sb.append("Method '")
+            .append(methodName)
+            .append("' returning object: ");
+
+         if (result != null && result instanceof Collection)
+         {
+            sb.append("Collection of size: ").append(((Collection)result).size());
+         }
+         else
+         {
+            if (result != null)
+            {
+               sb.append("[").append(result.getClass().getCanonicalName()).append("]");
+            }
+            sb.append(result);
+         }
+
+         log.log(level, sb.toString());
+
+      }
+      catch (Throwable t)
+      {
+         log.log(level, "Error in logging code block (not related to application code): ", t);
+      }
+   }
+
+}

Modified: portal/branches/wci/component/identity/src/main/java/org/exoplatform/services/organization/idm/UserDAOImpl.java
===================================================================
--- portal/branches/wci/component/identity/src/main/java/org/exoplatform/services/organization/idm/UserDAOImpl.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/component/identity/src/main/java/org/exoplatform/services/organization/idm/UserDAOImpl.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -28,6 +28,7 @@
 import org.exoplatform.services.organization.UserEventListener;
 import org.exoplatform.services.organization.UserHandler;
 import org.exoplatform.services.organization.impl.UserImpl;
+import org.gatein.common.logging.LogLevel;
 import org.gatein.common.logging.Logger;
 import org.gatein.common.logging.LoggerFactory;
 import org.picketlink.idm.api.Attribute;
@@ -122,6 +123,20 @@
 
    public void createUser(User user, boolean broadcast) throws Exception
    {
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "createUser",
+            new Object[]{
+               "user", user,
+               "broadcast", broadcast
+            }
+         );
+      }
+
+
       IdentitySession session = service_.getIdentitySession();
       if (broadcast)
       {
@@ -149,6 +164,20 @@
 
    public void saveUser(User user, boolean broadcast) throws Exception
    {
+
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "saveUser",
+            new Object[]{
+               "user", user,
+               "broadcast", broadcast
+            }
+         );
+      }
+
       IdentitySession session = service_.getIdentitySession();
       if (broadcast)
       {
@@ -165,6 +194,20 @@
 
    public User removeUser(String userName, boolean broadcast) throws Exception
    {
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "removeUser",
+            new Object[]{
+               "userName", userName,
+               "broadcast", broadcast
+            }
+         );
+      }
+
+
       IdentitySession session = service_.getIdentitySession();
 
       org.picketlink.idm.api.User foundUser = null;
@@ -223,15 +266,49 @@
    //
    public User findUserByName(String userName) throws Exception
    {
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "findUserByName",
+            new Object[]{
+               "userName", userName,
+            }
+         );
+      }
+
       IdentitySession session = service_.getIdentitySession();
 
       User user = getPopulatedUser(userName, session);
 
+      if (log.isTraceEnabled())
+      {
+        Tools.logMethodOut(
+            log,
+            LogLevel.TRACE,
+            "findUserByName",
+            user
+         );
+      }
+
       return user;
    }
 
    public LazyPageList getUserPageList(int pageSize) throws Exception
    {
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "getUserPagetList",
+            new Object[]{
+               "pageSize", pageSize
+            }
+         );
+      }
+
       UserQueryBuilder qb = service_.getIdentitySession().createUserQueryBuilder();
 
       return new LazyPageList(new IDMUserListAccess(this, service_, qb, pageSize, true), pageSize);
@@ -245,9 +322,32 @@
 //
    public boolean authenticate(String username, String password) throws Exception
    {
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "authenticate",
+            new Object[]{
+               "userName", username,
+               "password", "****"
+            }
+         );
+      }
+
       User user = findUserByName(username);
       if (user == null)
       {
+         if (log.isTraceEnabled())
+         {
+            Tools.logMethodOut(
+               log,
+               LogLevel.TRACE,
+               "authenticate",
+               false
+            );
+         }
+
          return false;
       }
 
@@ -279,12 +379,35 @@
          userImpl.setLastLoginTime(Calendar.getInstance().getTime());
          saveUser(userImpl, false);
       }
+
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodOut(
+            log,
+            LogLevel.TRACE,
+            "authenticate",
+            authenticated
+         );
+      }
+
       return authenticated;
    }
 
    public LazyPageList findUsers(Query q) throws Exception
    {
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "findUsers",
+            new Object[]{
+               "q", q
+            }
+         );
+      }
 
+
       UserQueryBuilder qb = service_.getIdentitySession().createUserQueryBuilder();
 
       if (q.getUserName() != null)
@@ -319,6 +442,19 @@
 
    public LazyPageList findUsersByGroup(String groupId) throws Exception
    {
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "findUsersByGroup",
+            new Object[]{
+               "groupId", groupId
+            }
+         );
+      }
+
+
       UserQueryBuilder qb = service_.getIdentitySession().createUserQueryBuilder();
 
       org.picketlink.idm.api.Group jbidGroup = null;
@@ -339,6 +475,18 @@
 
    public User findUserByEmail(String email) throws Exception
    {
+      if (log.isTraceEnabled())
+      {
+         Tools.logMethodIn(
+            log,
+            LogLevel.TRACE,
+            "findUserByEmail",
+            new Object[]{
+               "findUserByEmail", email
+            }
+         );
+      }
+
       IdentitySession session = service_.getIdentitySession();
 
 
@@ -363,6 +511,16 @@
 
       }
 
+      if (log.isTraceEnabled())
+      {
+        Tools.logMethodOut(
+            log,
+            LogLevel.TRACE,
+            "findUserByEmail",
+            user
+         );
+      }
+
       return user;
    }
 

Modified: portal/branches/wci/component/portal/src/main/java/org/exoplatform/portal/config/model/Page.java
===================================================================
--- portal/branches/wci/component/portal/src/main/java/org/exoplatform/portal/config/model/Page.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/component/portal/src/main/java/org/exoplatform/portal/config/model/Page.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -50,6 +50,13 @@
    {
    }
 
+   public Page(String ownerType, String ownerId, String name)
+   {
+      this.ownerType = ownerType;
+      this.ownerId = ownerId;
+      this.name = name;
+   }
+
    public Page(PageData data)
    {
       super(data);

Modified: portal/branches/wci/component/portal/src/main/java/org/exoplatform/portal/config/model/PortalConfig.java
===================================================================
--- portal/branches/wci/component/portal/src/main/java/org/exoplatform/portal/config/model/PortalConfig.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/component/portal/src/main/java/org/exoplatform/portal/config/model/PortalConfig.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -67,6 +67,16 @@
       this(PORTAL_TYPE);
    }
 
+   public PortalConfig(String type)
+   {
+      this(type, null);
+   }
+
+   public PortalConfig(String type, String ownerId)
+   {
+      this(type, ownerId, null);
+   }
+
    public PortalConfig(String type, String ownerId, String storageId)
    {
       super(storageId);
@@ -74,16 +84,9 @@
       //
       this.type = type;
       this.name = ownerId;
+      this.portalLayout = new Container();
    }
 
-   public PortalConfig(String type)
-   {
-      this.type = type;
-
-      //
-      setPortalLayout(new Container());
-   }
-
    public PortalConfig(PortalData data)
    {
       super(data.getStorageId());
@@ -99,14 +102,6 @@
       this.portalLayout = new Container(data.getPortalLayout());
    }
 
-   PortalConfig(String storageId, String type)
-   {
-      super(storageId);
-
-      //
-      this.type = type;
-   }
-
    public String getType()
    {
       return type;

Modified: portal/branches/wci/component/portal/src/main/java/org/exoplatform/portal/pom/config/GlobalKey.java
===================================================================
--- portal/branches/wci/component/portal/src/main/java/org/exoplatform/portal/pom/config/GlobalKey.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/component/portal/src/main/java/org/exoplatform/portal/pom/config/GlobalKey.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -55,6 +55,16 @@
       this.localKey = localKey;
    }
 
+   public String getRepositoryId()
+   {
+      return repositoryId;
+   }
+
+   public Serializable getLocalKey()
+   {
+      return localKey;
+   }
+
    @Override
    public int hashCode()
    {

Modified: portal/branches/wci/component/portal/src/main/java/org/exoplatform/portal/pom/config/POMSession.java
===================================================================
--- portal/branches/wci/component/portal/src/main/java/org/exoplatform/portal/pom/config/POMSession.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/component/portal/src/main/java/org/exoplatform/portal/pom/config/POMSession.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -55,7 +55,7 @@
  * @author <a href="mailto:julien.viet at exoplatform.com">Julien Viet</a>
  * @version $Revision$
  */
-public class POMSession
+public final class POMSession
 {
 
    /** . */
@@ -361,20 +361,40 @@
       }
       public void afterSynchronization(SynchronizationStatus status)
       {
-         if (status == SynchronizationStatus.SAVED && staleKeys != null)
+         if (status == SynchronizationStatus.SAVED)
          {
-            if (log.isTraceEnabled())
-            {
-               log.trace("Session commit about to evict entries " + staleKeys);
-            }
-            for (Serializable key : staleKeys)
-            {
-               mgr.cacheRemove(key);
-            }
+            reset();
          }
       }
    };
 
+   /**
+    * Reset the session and set its state like it was a newly created session.
+    */
+   private void reset()
+   {
+      // Evict entries from the shared cache if any
+      if (staleKeys != null && staleKeys.size() > 0)
+      {
+         if (log.isTraceEnabled())
+         {
+            log.trace("About to evict entries " + staleKeys);
+         }
+         for (Serializable key : staleKeys)
+         {
+            mgr.cacheRemove(key);
+         }
+         staleKeys.clear();
+      }
+
+      // Reset modified flag
+      if (log.isTraceEnabled())
+      {
+         log.trace("Setting modified flag to false");
+      }
+      modified = false;
+   }
+
    public <V> V execute(POMTask<V> task) throws Exception
    {
       if (isInTask)
@@ -404,7 +424,11 @@
       {
          if (!markedForRollback)
          {
+            // Trigger persistent save
             model.save();
+
+            // Reset modified state
+            reset();
          }
          else
          {

Modified: portal/branches/wci/component/portal/src/main/java/org/exoplatform/portal/pom/config/POMSessionManager.java
===================================================================
--- portal/branches/wci/component/portal/src/main/java/org/exoplatform/portal/pom/config/POMSessionManager.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/component/portal/src/main/java/org/exoplatform/portal/pom/config/POMSessionManager.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -23,8 +23,13 @@
 import org.exoplatform.commons.chromattic.ChromatticManager;
 import org.exoplatform.commons.chromattic.SessionContext;
 import org.exoplatform.portal.pom.config.cache.DataCache;
+import org.exoplatform.portal.pom.config.cache.PortalNamesCache;
+import org.exoplatform.portal.pom.data.OwnerKey;
+import org.exoplatform.portal.pom.data.PortalKey;
 import org.exoplatform.services.cache.CacheService;
+import org.exoplatform.services.cache.CachedObjectSelector;
 import org.exoplatform.services.cache.ExoCache;
+import org.exoplatform.services.cache.ObjectCacheInfo;
 import org.exoplatform.services.jcr.RepositoryService;
 import org.gatein.common.logging.Logger;
 import org.gatein.common.logging.LoggerFactory;
@@ -69,7 +74,7 @@
       this.manager = manager;
       this.cache = cacheService.getCacheInstance("MOPSessionManager");
       this.pomService = null;
-      this.executor = new DataCache(new ExecutorDispatcher());
+      this.executor = new PortalNamesCache(new DataCache(new ExecutorDispatcher()));
    }
 
    public void cachePut(Serializable key, Object value)
@@ -105,7 +110,7 @@
 
    public void cacheRemove(Serializable key)
    {
-      GlobalKey globalKey = GlobalKey.wrap(configurator.getRepositoryName(), key);
+      final GlobalKey globalKey = GlobalKey.wrap(configurator.getRepositoryName(), key);
 
       //
       if (log.isTraceEnabled())
@@ -114,7 +119,47 @@
       }
 
       //
-      cache.remove(globalKey);
+      if (key instanceof PortalKey)
+      {
+         // This code seems complex but actually it tries to find all objects in cache that have the same
+         // owner key than the portal key, for instance if we remove (portal,classic) then all pages
+         // related to (portal,classic) are also evicted
+         final PortalKey portalKey = (PortalKey)key;
+         try
+         {
+            cache.select(new CachedObjectSelector<GlobalKey, Object>()
+            {
+               public boolean select(GlobalKey selectedGlobalKey, ObjectCacheInfo<?> ocinfo)
+               {
+                  if (globalKey.getRepositoryId().equals(selectedGlobalKey.getRepositoryId()))
+                  {
+                     Serializable selectedLocalKey = selectedGlobalKey.getLocalKey();
+                     if (selectedLocalKey instanceof OwnerKey)
+                     {
+                        OwnerKey selectedOwnerKey = (OwnerKey)selectedLocalKey;
+                        if (selectedOwnerKey.getType().equals(portalKey.getType()) && selectedOwnerKey.getId().equals(portalKey.getId()))
+                        {
+                           return true;
+                        }
+                     }
+                  }
+                  return false;
+               }
+               public void onSelect(ExoCache<? extends GlobalKey, ?> exoCache, GlobalKey key, ObjectCacheInfo<?> ocinfo) throws Exception
+               {
+                  cache.remove(key);
+               }
+            });
+         }
+         catch (Exception e)
+         {
+            log.error("Unexpected error when clearing pom cache", e);
+         }
+      }
+      else
+      {
+         cache.remove(globalKey);
+      }
    }
 
    public void start()

Copied: portal/branches/wci/component/portal/src/main/java/org/exoplatform/portal/pom/config/cache/PortalNamesCache.java (from rev 5342, portal/trunk/component/portal/src/main/java/org/exoplatform/portal/pom/config/cache/PortalNamesCache.java)
===================================================================
--- portal/branches/wci/component/portal/src/main/java/org/exoplatform/portal/pom/config/cache/PortalNamesCache.java	                        (rev 0)
+++ portal/branches/wci/component/portal/src/main/java/org/exoplatform/portal/pom/config/cache/PortalNamesCache.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+package org.exoplatform.portal.pom.config.cache;
+
+import org.exoplatform.commons.utils.LazyPageList;
+import org.exoplatform.commons.utils.ListAccessImpl;
+import org.exoplatform.portal.pom.config.POMSession;
+import org.exoplatform.portal.pom.config.POMTask;
+import org.exoplatform.portal.pom.config.TaskExecutionDecorator;
+import org.exoplatform.portal.pom.config.TaskExecutor;
+import org.exoplatform.portal.pom.config.tasks.PortalConfigTask;
+import org.exoplatform.portal.pom.config.tasks.SearchTask;
+import org.exoplatform.portal.pom.data.PortalKey;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:julien.viet at exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+public class PortalNamesCache extends TaskExecutionDecorator
+{
+
+   public PortalNamesCache(TaskExecutor next)
+   {
+      super(next);
+   }
+
+   @Override
+   public <V> V execute(POMSession session, POMTask<V> task) throws Exception
+   {
+      if (!session.isModified())
+      {
+         if (task instanceof SearchTask.FindSiteKey)
+         {
+            List<PortalKey> data = (List<PortalKey>)session.getFromCache(SearchTask.FindSiteKey.class);
+            if (data == null)
+            {
+               V result = super.execute(session, task);
+               LazyPageList<PortalKey> list = (LazyPageList<PortalKey>)result;
+               session.putInCache(SearchTask.FindSiteKey.class, Collections.unmodifiableList(new ArrayList<PortalKey>(list.getAll())));
+               return result;
+            }
+            else
+            {
+               return (V)new LazyPageList<PortalKey>(new ListAccessImpl<PortalKey>(PortalKey.class, data), 10);
+            }
+         }
+         else if (task instanceof PortalConfigTask.Save || task instanceof PortalConfigTask.Remove)
+         {
+            V result = super.execute(session, task);
+            session.scheduleForEviction(SearchTask.FindSiteKey.class);
+            return result;
+         }
+      }
+
+      //
+      return super.execute(session, task);
+   }
+}

Modified: portal/branches/wci/component/portal/src/test/java/org/exoplatform/portal/config/TestCache.java
===================================================================
--- portal/branches/wci/component/portal/src/test/java/org/exoplatform/portal/config/TestCache.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/component/portal/src/test/java/org/exoplatform/portal/config/TestCache.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -20,9 +20,9 @@
 
 import org.exoplatform.container.PortalContainer;
 import org.exoplatform.portal.config.model.Page;
+import org.exoplatform.portal.config.model.PortalConfig;
 import org.exoplatform.portal.pom.config.POMSession;
 import org.exoplatform.portal.pom.config.POMSessionManager;
-
 import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
@@ -128,4 +128,48 @@
       //
       end();
    }
+
+   public void testGetPageFromRemovedPortal() throws Exception
+   {
+      // Create what we need for the test
+      begin();
+      session = mgr.openSession();
+      PortalConfig portalConfig = new PortalConfig("portal", "testGetPageFromRemovedPortal");
+      storage_.create(portalConfig);
+      storage_.create(new Page("portal", "testGetPageFromRemovedPortal", "home"));
+      end(true);
+
+      // Clear cache
+      mgr.clearCache();
+
+      // The first transaction
+      begin();
+      session = mgr.openSession();
+
+      // Get page from JCR and it should be stored in cache
+      Page page = storage_.getPage("portal::testGetPageFromRemovedPortal::home");
+      assertNotNull(page);
+
+      // Now remove the portal
+      PortalConfig portal = storage_.getPortalConfig("portal", "testGetPageFromRemovedPortal");
+      storage_.remove(portal);
+
+      // Terminate the first transaction
+      end(true);
+
+      // The second transaction
+      begin();
+      session = mgr.openSession();
+
+      // The portal should be null
+      portal = storage_.getPortalConfig("portal", "testGetPageFromRemovedPortal");
+      assertNull(portal);
+
+      // The portal home page should also be null
+      page = storage_.getPage("portal::testGetPageFromRemovedPortal::home");
+      assertNull(page);
+
+      // End second transaction
+      end(true);
+   }
 }

Copied: portal/branches/wci/component/portal/src/test/java/org/exoplatform/portal/config/TestConcurrencyDataStorage.java (from rev 5342, portal/trunk/component/portal/src/test/java/org/exoplatform/portal/config/TestConcurrencyDataStorage.java)
===================================================================
--- portal/branches/wci/component/portal/src/test/java/org/exoplatform/portal/config/TestConcurrencyDataStorage.java	                        (rev 0)
+++ portal/branches/wci/component/portal/src/test/java/org/exoplatform/portal/config/TestConcurrencyDataStorage.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ */
+package org.exoplatform.portal.config;
+
+import java.util.concurrent.CountDownLatch;
+
+import org.exoplatform.container.PortalContainer;
+import org.exoplatform.portal.config.model.Page;
+import org.exoplatform.portal.config.model.PortalConfig;
+import org.exoplatform.portal.pom.config.POMSessionManager;
+
+/**
+ * @author <a href="mailto:hoang281283 at gmail.com">Minh Hoang TO</a>
+ * Nov 10, 2010
+ */
+
+public class TestConcurrencyDataStorage extends AbstractPortalTest
+{
+
+   private DataStorage storage_;
+
+   private POMSessionManager mgr;
+
+   public TestConcurrencyDataStorage(String name)
+   {
+      super(name);
+   }
+
+   public void setUp() throws Exception
+   {
+      super.setUp();
+      begin();
+      PortalContainer container = PortalContainer.getInstance();
+      storage_ = (DataStorage)container.getComponentInstanceOfType(DataStorage.class);
+      mgr = (POMSessionManager)container.getComponentInstanceOfType(POMSessionManager.class);
+      
+   }
+   
+   public void testCreatePageConcurrently() throws Exception
+   {
+      CountDownLatch startSignal = new CountDownLatch(1);
+      
+      for (int i = 0; i < 5; i++)
+      {
+         Thread thread = new Thread(new CreatePageTask(mgr, storage_, startSignal, "test" + i, "foo" + i)); 
+         thread.start();
+      }
+      
+      startSignal.countDown();
+   }
+   
+   public void testCreatePageSequentially() throws Exception
+   {
+      for (int i = 5; i < 10; i++)
+      {
+         Thread thread = new Thread(new CreatePageTask(mgr, storage_, null, "test" + i, "foo" + i)); 
+         thread.start();
+         thread.join();
+      }
+   }
+
+   protected void tearDown() throws Exception
+   {
+      end();
+      super.tearDown();
+   }
+   
+   public class CreatePageTask implements Runnable
+   {
+      private DataStorage dataStorage;
+      
+      private POMSessionManager sessionManager;
+      
+      private String pageName;
+      
+      private String pageTitle;
+      
+      private CountDownLatch startSignal;
+      
+      public CreatePageTask(POMSessionManager _sessionManager, DataStorage _dataStorage, CountDownLatch _startSignal, String _pageName, String _pageTitle)
+      {
+         dataStorage = _dataStorage;
+         pageName = _pageName;
+         pageTitle = _pageTitle;
+         sessionManager = _sessionManager;
+         startSignal = _startSignal;
+      }
+      
+      @Override
+      public void run()
+      {
+         try
+         {
+            if(startSignal != null)
+               startSignal.await();
+
+            sessionManager.openSession();
+
+            Page page = new Page();
+            page.setOwnerType(PortalConfig.PORTAL_TYPE);
+            page.setOwnerId("test");
+            page.setTitle(pageTitle);
+            page.setName(pageName);
+
+            dataStorage.create(page);
+
+            Page createdPage = dataStorage.getPage(page.getPageId());
+            assertNotNull(createdPage);
+            assertEquals(pageName, createdPage.getName());
+            assertEquals(pageTitle, createdPage.getTitle());
+
+            System.out.println("Current POMSession: " + sessionManager.getSession().toString());
+         }
+         catch (Exception ex)
+         {
+            ex.printStackTrace();
+            System.out.println("Could not create the page: " + pageName + " , " + pageTitle);
+         }
+      }
+   }
+
+}

Modified: portal/branches/wci/component/portal/src/test/java/org/exoplatform/portal/config/TestDataStorage.java
===================================================================
--- portal/branches/wci/component/portal/src/test/java/org/exoplatform/portal/config/TestDataStorage.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/component/portal/src/test/java/org/exoplatform/portal/config/TestDataStorage.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -21,6 +21,7 @@
 
 import static org.exoplatform.portal.pom.config.Utils.split;
 
+import org.exoplatform.commons.utils.LazyPageList;
 import org.exoplatform.container.PortalContainer;
 import org.exoplatform.portal.application.PortletPreferences;
 import org.exoplatform.portal.application.Preference;
@@ -36,7 +37,11 @@
 import org.exoplatform.services.listener.ListenerService;
 
 import java.util.*;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicReference;
 
+import junit.framework.AssertionFailedError;
+
 /**
  * Created by The eXo Platform SARL Author : Tung Pham thanhtungty at gmail.com Nov
  * 13, 2007
@@ -45,9 +50,12 @@
 {
 
    /** . */
-   private final String testPage = "portal::classic::testPage";
+   private static final String CLASSIC_HOME = "portal::classic::homepage";
 
    /** . */
+   private static final String CLASSIC_TEST = "portal::classic::testPage";
+
+   /** . */
    private final String testPortletPreferences = "portal#classic:/web/BannerPortlet/testPortletPreferences";
 
    /** . */
@@ -297,7 +305,7 @@
       assertEquals(1, events.size());
       
       //
-      page = storage_.getPage(testPage);
+      page = storage_.getPage(CLASSIC_TEST);
       assertNull(page);
    }
 
@@ -868,7 +876,137 @@
       gadgetApp = (Application<Gadget>)row0.getChildren().get(0);
       assertEquals("foo", storage_.getId(gadgetApp.getState()));
    }
+   
+   public void testRemoveAndFindPage() throws Exception
+   {
+      Page page = storage_.getPage(CLASSIC_HOME);
+      assertNotNull(page);
+      storage_.remove(page);
 
+      // This will trigger a save
+      Query<Page> query = new Query<Page>(null, null, null, null, Page.class);
+      LazyPageList<Page> list = storage_.find(query);
+      assertNotNull(list);
+
+      // We check is now seen as removed
+      assertNull(storage_.getPage(CLASSIC_HOME));
+   }
+
+   public void testGetAllPortalNames() throws Exception
+   {
+      final List<String> names = storage_.getAllPortalNames();
+
+      // Create new portal
+      storage_.create(new PortalConfig("portal", "testGetAllPortalNames"));
+
+      // Test during tx we see the good names
+      List<String> transientNames = storage_.getAllPortalNames();
+      assertTrue(transientNames.containsAll(names));
+      transientNames.removeAll(names);
+      assertEquals(Collections.singletonList("testGetAllPortalNames"), transientNames);
+
+      // Test we have not seen anything yet outside of tx
+      final CountDownLatch addSync = new CountDownLatch(1);
+      final AtomicReference<Throwable> error = new AtomicReference<Throwable>();
+      new Thread()
+      {
+         @Override
+         public void run()
+         {
+            begin();
+            try
+            {
+               List<String> isolatedNames = storage_.getAllPortalNames();
+               assertEquals(new HashSet<String>(names), new HashSet<String>(isolatedNames));
+            }
+            catch (Throwable t)
+            {
+               error.set(t);
+            }
+            finally
+            {
+               addSync.countDown();
+               end();
+            }
+         }
+      }.start();
+
+      //
+      addSync.await();
+      if (error.get() != null)
+      {
+         AssertionFailedError afe = new AssertionFailedError();
+         afe.initCause(error.get());
+         throw afe;
+      }
+
+      // Now commit tx
+      session.close(true);
+      end(true);
+
+      // We test we observe the change
+      begin();
+      session = mgr.openSession();
+      List<String> afterNames = storage_.getAllPortalNames();
+      assertTrue(afterNames.containsAll(names));
+      afterNames.removeAll(names);
+      assertEquals(Collections.singletonList("testGetAllPortalNames"), afterNames);
+
+      // Then we remove the newly created portal
+      storage_.remove(new PortalConfig("portal", "testGetAllPortalNames"));
+
+      // Test we are syeing the transient change
+      transientNames.clear();
+      transientNames = storage_.getAllPortalNames();
+      assertEquals(names, transientNames);
+
+      // Test we have not seen anything yet outside of tx
+      error.set(null);
+      final CountDownLatch removeSync = new CountDownLatch(1);
+      new Thread()
+      {
+         public void run()
+         {
+            begin();
+            try
+            {
+               List<String> isolatedNames = storage_.getAllPortalNames();
+               assertTrue(isolatedNames.containsAll(names));
+               isolatedNames.removeAll(names);
+               assertEquals(Collections.singletonList("testGetAllPortalNames"), isolatedNames);
+            }
+            catch (Throwable t)
+            {
+               error.set(t);
+            }
+            finally
+            {
+               removeSync.countDown();
+               end();
+            }
+         }
+      }.start();
+
+      //
+      removeSync.await();
+      if (error.get() != null)
+      {
+         AssertionFailedError afe = new AssertionFailedError();
+         afe.initCause(error.get());
+         throw afe;
+      }
+
+      //
+      session.close(true);
+      end(true);
+
+      // Now test it is still removed
+      begin();
+      session = mgr.openSession();
+      afterNames = storage_.getAllPortalNames();
+      assertEquals(new HashSet<String>(names), new HashSet<String>(afterNames));
+   }
+
    private Application<Portlet> create(String instanceId)
    {
       int i0 = instanceId.indexOf("#");

Modified: portal/branches/wci/component/scripting/src/main/java/org/exoplatform/groovyscript/GroovyTemplate.java
===================================================================
--- portal/branches/wci/component/scripting/src/main/java/org/exoplatform/groovyscript/GroovyTemplate.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/component/scripting/src/main/java/org/exoplatform/groovyscript/GroovyTemplate.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -34,6 +34,7 @@
 public class GroovyTemplate
 {
 
+   // todo : move that to {@link org.gatein.common.io.IOTools}
    private static String read(Reader reader) throws IOException
    {
       StringBuilder builder = new StringBuilder();

Modified: portal/branches/wci/component/web/controller/src/main/java/org/exoplatform/web/WebAppController.java
===================================================================
--- portal/branches/wci/component/web/controller/src/main/java/org/exoplatform/web/WebAppController.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/component/web/controller/src/main/java/org/exoplatform/web/WebAppController.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -49,7 +49,7 @@
 
    private HashMap<String, Object> attributes_;
 
-   private HashMap<String, Application> applications_;
+   private volatile HashMap<String, Application> applications_;
 
    private HashMap<String, WebRequestHandler> handlers_;
 
@@ -89,16 +89,42 @@
       return applications;
    }
 
-   public void removeApplication(String appId)
+   public synchronized void removeApplication(String appId)
    {
       applications_.remove(appId);
    }
 
-   public void addApplication(Application app)
+   /**
+    *   Add application (portlet, gadget) to the global application map if and only if it has
+    * not been registered yet.
+    * 
+    * @param <T>
+    * @param app
+    * @return
+    */
+   public <T extends Application> T addApplication(T app)
    {
-      applications_.put(app.getApplicationId(), app);
+      Application result = getApplication(app.getApplicationId());
+      
+      //Double-check block
+      if(result == null)
+      {
+         synchronized(this)
+         {
+            result = getApplication(app.getApplicationId());
+            if(result == null)
+            {
+               HashMap<String, Application> temporalApplicationsMap = new HashMap<String, Application>(applications_);
+               temporalApplicationsMap.put(app.getApplicationId(), app);
+               this.applications_ = temporalApplicationsMap;
+               result = app;
+            }
+         }
+      }
+      
+      return (T)result;
    }
-
+   
    public void register(WebRequestHandler handler) throws Exception
    {
       for (String path : handler.getPath())

Modified: portal/branches/wci/component/web/resources/src/main/java/org/exoplatform/portal/application/Image.java
===================================================================
--- portal/branches/wci/component/web/resources/src/main/java/org/exoplatform/portal/application/Image.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/component/web/resources/src/main/java/org/exoplatform/portal/application/Image.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -19,6 +19,8 @@
 
 package org.exoplatform.portal.application;
 
+import java.util.Date;
+
 /**
  * @author <a href="mailto:julien.viet at exoplatform.com">Julien Viet</a>
  * @version $Revision$
@@ -29,10 +31,19 @@
    final ImageType type;
 
    final byte[] bytes;
+   
+   final long lastModified;
 
    public Image(ImageType type, byte[] bytes)
    {
       this.type = type;
       this.bytes = bytes;
+//  Remove miliseconds because string of date retrieve from Http header doesn't have miliseconds
+      lastModified = (new Date().getTime() / 1000) * 1000;
    }
+   
+   public long getLastModified() 
+   {
+      return lastModified;
+   }
 }

Modified: portal/branches/wci/component/web/resources/src/main/java/org/exoplatform/portal/application/ResourceRequestFilter.java
===================================================================
--- portal/branches/wci/component/web/resources/src/main/java/org/exoplatform/portal/application/ResourceRequestFilter.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/component/web/resources/src/main/java/org/exoplatform/portal/application/ResourceRequestFilter.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -36,6 +36,7 @@
 import java.io.OutputStream;
 import java.net.URLDecoder;
 import java.nio.charset.Charset;
+import java.util.Date;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
@@ -64,6 +65,10 @@
 
    private ConcurrentMap<String, FutureTask<Image>> mirroredImageCache = new ConcurrentHashMap<String, FutureTask<Image>>();
 
+   public static final String IF_MODIFIED_SINCE     = "If-Modified-Since";
+ 
+   public static final String LAST_MODIFIED     = "Last-Modified";    
+   
    public void afterInit(FilterConfig filterConfig)
    {
       cfg = filterConfig;
@@ -77,11 +82,19 @@
       final String uri = URLDecoder.decode(httpRequest.getRequestURI(), "UTF-8");
       final HttpServletResponse httpResponse = (HttpServletResponse)response;
       ExoContainer portalContainer = getContainer();
-      SkinService skinService = (SkinService)portalContainer.getComponentInstanceOfType(SkinService.class);
+      final SkinService skinService = (SkinService) portalContainer.getComponentInstanceOfType(SkinService.class);
+      long ifModifiedSince = httpRequest.getDateHeader(IF_MODIFIED_SINCE);
 
       //
       if (uri.endsWith(".css"))
       {
+//     Check if cached resource has not been modifed, return 304 code      
+         long cssLastModified = skinService.getLastModified(uri);
+         if (isNotModified(ifModifiedSince, cssLastModified)) {
+            httpResponse.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
+            return;
+         }
+
          final OutputStream out = response.getOutputStream();
          final BinaryOutput output = new BinaryOutput()
          {
@@ -118,6 +131,9 @@
                {
                   httpResponse.setHeader("Cache-Control", "no-cache");
                }
+
+               long lastModified = skinService.getLastModified(uri);
+               processIfModified(lastModified, httpResponse);
             }
          };
 
@@ -192,8 +208,16 @@
                      Image img = futureImg.get();
                      if (img != null)
                      {
+                        //Check if cached resource has not been modifed, return 304 code      
+                        long imgLastModified = img.getLastModified();
+                        if (isNotModified(ifModifiedSince, imgLastModified)) {
+                           httpResponse.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
+                           return;
+                        }
                         httpResponse.setContentType(img.type.getMimeType());
                         httpResponse.setContentLength(img.bytes.length);
+                        processIfModified(imgLastModified, httpResponse);
+                        
                         OutputStream out = httpResponse.getOutputStream();
                         out.write(img.bytes);
                         out.close();
@@ -238,6 +262,30 @@
       }
    }
 
+   /**
+    * Add Last-Modified Http header to HttpServetResponse
+    */
+   public void processIfModified(long lastModified, HttpServletResponse httpResponse) {
+      httpResponse.setDateHeader(ResourceRequestFilter.LAST_MODIFIED, lastModified);
+   }
+
+   /**
+    * If cached resource has not changed since date in http header (If_Modified_Since), return true
+    * Else return false;
+    * @param ifModifedSince - String, and HttpHeader element
+    * @param lastModified
+    * @param httpResponse
+    * @return
+    */
+   public boolean isNotModified(long ifModifedSince, long lastModified) {
+      if (!PropertyManager.isDevelopping()) {
+         if (ifModifedSince >= lastModified) {
+            return true;
+         }
+      }
+      return false;
+   }
+   
    public void destroy()
    {
    }

Modified: portal/branches/wci/component/web/resources/src/main/java/org/exoplatform/portal/resource/CachedStylesheet.java
===================================================================
--- portal/branches/wci/component/web/resources/src/main/java/org/exoplatform/portal/resource/CachedStylesheet.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/component/web/resources/src/main/java/org/exoplatform/portal/resource/CachedStylesheet.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -24,6 +24,7 @@
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.lang.reflect.UndeclaredThrowableException;
+import java.util.Date;
 
 /**
  * @author <a href="mailto:julien.viet at exoplatform.com">Julien Viet</a>
@@ -40,6 +41,8 @@
 
    /** . */
    private final byte[] bytes;
+   
+   private long lastModified;
 
    public CachedStylesheet(String text)
    {
@@ -59,11 +62,18 @@
       //
       this.text = text;
       this.bytes = bytes;
+//  Remove miliseconds because string of date retrieve from Http header doesn't have miliseconds 
+      lastModified = (new Date().getTime() / 1000) * 1000;
    }
 
    public String getText()
    {
       return text;
+   }   
+
+   public long getLastModified()
+   {
+      return lastModified;
    }
 
    public void writeTo(BinaryOutput output) throws IOException

Modified: portal/branches/wci/component/web/resources/src/main/java/org/exoplatform/portal/resource/SkinService.java
===================================================================
--- portal/branches/wci/component/web/resources/src/main/java/org/exoplatform/portal/resource/SkinService.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/component/web/resources/src/main/java/org/exoplatform/portal/resource/SkinService.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -51,6 +51,7 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Date;
 import java.util.EnumMap;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -455,6 +456,9 @@
       // Try cache first
       if (!PropertyManager.isDevelopping())
       {
+         //
+         FutureExoCache<String, CachedStylesheet, Orientation> cache = orientation == Orientation.LT ? ltCache : rtCache;
+         CachedStylesheet cachedCss = cache.get(orientation, path);
 
          if (path.startsWith("/" + portalContainerName + "/resource"))
          {
@@ -464,11 +468,7 @@
          {
             renderer.setExpiration(ONE_HOUR);
          }
-
-         //
-         FutureExoCache<String, CachedStylesheet, Orientation> cache = orientation == Orientation.LT ? ltCache : rtCache;
-         CachedStylesheet cachedCss = cache.get(orientation, path);
-
+         
          cachedCss.writeTo(renderer.getOutput());
       }
       else
@@ -546,6 +546,41 @@
    }
 
    /**
+    * Return last modifed date of cached css
+    * Return null if cached css can not be found
+    * @param path - path must not be null
+    */
+   public long getLastModified(String path)
+   {
+      if (path == null)
+      {
+         throw new IllegalArgumentException("path must not be null");
+      }
+
+      FutureExoCache<String, CachedStylesheet, Orientation> cache = ltCache;
+      Orientation orientation = Orientation.LT;
+      if (path.endsWith("-lt.css"))
+      {
+         path = path.substring(0, path.length() - "-lt.css".length()) + ".css";
+      }
+      else if (path.endsWith("-rt.css"))
+      {
+         path = path.substring(0, path.length() - "-rt.css".length()) + ".css";
+         orientation = Orientation.RT;
+      }
+
+      CachedStylesheet cachedCSS = cache.get(orientation, path);
+      if (cachedCSS == null)
+      {
+         return Long.MAX_VALUE;
+      }
+      else
+      {
+         return cachedCSS.getLastModified();
+      }
+   }
+
+   /**
     * Remove SkinConfig from Portal Skin Configs  by module and skin name
     * @param module
     * @param skinName

Modified: portal/branches/wci/component/web/resources/src/main/java/org/exoplatform/web/application/javascript/JavascriptConfigService.java
===================================================================
--- portal/branches/wci/component/web/resources/src/main/java/org/exoplatform/web/application/javascript/JavascriptConfigService.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/component/web/resources/src/main/java/org/exoplatform/web/application/javascript/JavascriptConfigService.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -40,6 +40,7 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -64,6 +65,8 @@
    private HashMap<String, String> extendedJavascripts;
 
    private byte[] jsBytes = null;
+   
+   private long lastModified = Long.MAX_VALUE;
 
    /** . */
    private JavascriptDeployer deployer;
@@ -278,6 +281,18 @@
     */
    public void writeMergedJavascript(OutputStream out) throws IOException
    {
+      jsBytes = getMergedJavascript();
+
+      //
+      out.write(jsBytes);
+   }
+   
+   /**
+    * Return merged javascript in byte array
+    * @return byte[]
+    */
+   public byte[] getMergedJavascript()
+   {
       if (jsBytes == null)
       {
          // Generate javascript in a buffer
@@ -314,10 +329,15 @@
             log.error("Error when generating minified javascript, will use normal javascript instead", e);
             jsBytes = bytes;
          }
+//         Remove miliseconds because string of date retrieve from Http header doesn't have miliseconds
+         lastModified = (new Date().getTime() / 1000) * 1000;
       }
+      return jsBytes;
+   }
 
-      //
-      out.write(jsBytes);
+   public long getLastModified() 
+   {
+      return lastModified;
    }
 
    /**
@@ -374,4 +394,4 @@
       DefaultServletContainerFactory.getInstance().getServletContainer().removeWebAppListener(removal);
    }
 
-}
\ No newline at end of file
+}

Copied: portal/branches/wci/component/web/security/src/main/java/org/exoplatform/web/security/security/AbstractCodec.java (from rev 5342, portal/trunk/component/web/security/src/main/java/org/exoplatform/web/security/security/AbstractCodec.java)
===================================================================
--- portal/branches/wci/component/web/security/src/main/java/org/exoplatform/web/security/security/AbstractCodec.java	                        (rev 0)
+++ portal/branches/wci/component/web/security/src/main/java/org/exoplatform/web/security/security/AbstractCodec.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+package org.exoplatform.web.security.security;
+
+import org.exoplatform.container.component.BaseComponentPlugin;
+
+/**
+ * Abstract codec used to encode/decode password stored/loaded on/from token entry
+ * 
+ * @author <a href="mailto:hoang281283 at gmail.com">Minh Hoang TO</a>
+ * Nov 19, 2010
+ */
+
+public abstract class AbstractCodec extends BaseComponentPlugin
+{
+
+   public String getName()
+   {
+      return this.getClass().toString();
+   }
+   
+   public abstract String encode(String plainInput);
+   
+   public abstract String decode(String encodedInput);
+   
+}

Modified: portal/branches/wci/component/web/security/src/main/java/org/exoplatform/web/security/security/CookieTokenService.java
===================================================================
--- portal/branches/wci/component/web/security/src/main/java/org/exoplatform/web/security/security/CookieTokenService.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/component/web/security/src/main/java/org/exoplatform/web/security/security/CookieTokenService.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -24,6 +24,7 @@
 import org.exoplatform.commons.chromattic.ChromatticManager;
 import org.exoplatform.commons.chromattic.ContextualTask;
 import org.exoplatform.commons.chromattic.SessionContext;
+import org.exoplatform.container.component.ComponentPlugin;
 import org.exoplatform.container.xml.InitParams;
 import org.exoplatform.web.security.GateInToken;
 import org.gatein.wci.security.Credentials;
@@ -47,6 +48,9 @@
    /** . */
    private String lifecycleName="autologin";
 
+   //TODO: Introduce the concept of priority and store the plugins in a map structure
+   private AbstractCodec codec;
+   
    public CookieTokenService(InitParams initParams, ChromatticManager chromatticManager)
    {
       super(initParams);
@@ -56,8 +60,19 @@
     	  lifecycleName = (String)initParams.getValuesParam(SERVICE_CONFIG).getValues().get(3);
       }
       this.chromatticLifeCycle = chromatticManager.getLifeCycle(lifecycleName);
+      
+      //Set the default codec
+      this.codec = new ToThrowAwayCodec();
    }
 
+   public final void setupCodec(ComponentPlugin codecPlugin)
+   {
+      if(codecPlugin instanceof AbstractCodec)
+      {
+         this.codec = (AbstractCodec)codecPlugin;
+      }
+   }
+   
    public String createToken(final Credentials credentials)
    {
       if (validityMillis < 0)
@@ -76,7 +91,9 @@
             long expirationTimeMillis = System.currentTimeMillis() + validityMillis;
             GateInToken token = new GateInToken(expirationTimeMillis, credentials);
             TokenContainer container = getTokenContainer();
-            container.saveToken(tokenId, token.getPayload(), new Date(token.getExpirationTimeMillis()));
+            
+            //Save the token, password is encoded thanks to the codec
+            container.encodeAndSaveToken(tokenId, token.getPayload(), new Date(expirationTimeMillis), codec);
             return tokenId;
          }
       }.executeWith(chromatticLifeCycle);
@@ -89,7 +106,8 @@
          @Override
          protected GateInToken execute()
          {
-            return getTokenContainer().getToken((String)id);
+            //Get the token, encoded password is decoded thanks to codec
+            return getTokenContainer().getTokenAndDecode(id, codec);
          }
       }.executeWith(chromatticLifeCycle);
    }

Copied: portal/branches/wci/component/web/security/src/main/java/org/exoplatform/web/security/security/ToThrowAwayCodec.java (from rev 5342, portal/trunk/component/web/security/src/main/java/org/exoplatform/web/security/security/ToThrowAwayCodec.java)
===================================================================
--- portal/branches/wci/component/web/security/src/main/java/org/exoplatform/web/security/security/ToThrowAwayCodec.java	                        (rev 0)
+++ portal/branches/wci/component/web/security/src/main/java/org/exoplatform/web/security/security/ToThrowAwayCodec.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+package org.exoplatform.web.security.security;
+
+/**
+ * @author <a href="mailto:hoang281283 at gmail.com">Minh Hoang TO</a>
+ * Nov 19, 2010
+ */
+
+public class ToThrowAwayCodec extends AbstractCodec
+{
+
+   @Override
+   public String decode(String encodedInput)
+   {
+      return encodedInput;
+   }
+
+   @Override
+   public String encode(String plainInput)
+   {
+      return plainInput;
+   }
+
+}

Modified: portal/branches/wci/component/web/security/src/main/java/org/exoplatform/web/security/security/TokenContainer.java
===================================================================
--- portal/branches/wci/component/web/security/src/main/java/org/exoplatform/web/security/security/TokenContainer.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/component/web/security/src/main/java/org/exoplatform/web/security/security/TokenContainer.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -84,5 +84,37 @@
       entry.setExpirationTime(expirationTime);
       return entry.getToken();
    }
+   
+   public GateInToken encodeAndSaveToken(String tokenId, Credentials credentials, Date expirationTime, AbstractCodec codec)
+   {
+      Map<String, TokenEntry> tokens = getTokens();
+      TokenEntry entry = tokens.get(tokenId);
+      if (entry == null)
+      {
+         entry = createToken();
+         tokens.put(tokenId, entry);
+         entry.setUserName(credentials.getUsername());
+         entry.setPassword(codec.encode(credentials.getPassword()));
+      }
+      entry.setExpirationTime(expirationTime);
+      return entry.getToken();
+   }
+   
+   public GateInToken getTokenAndDecode(String tokenId, AbstractCodec codec)
+   {
+      Map<String, TokenEntry> tokens = getTokens();
+      TokenEntry entry = tokens.get(tokenId);
+      if(entry != null)
+      {
+         GateInToken gateInToken = entry.getToken();
+         Credentials payload = gateInToken.getPayload();
+         
+         //Return a cloned GateInToken
+         return new GateInToken(gateInToken.getExpirationTimeMillis(), new Credentials(payload.getUsername(), codec
+               .decode(payload.getPassword())));
 
+      }
+      return null;
+   }
+
 }

Modified: portal/branches/wci/component/web/server/src/main/java/org/exoplatform/upload/UploadService.java
===================================================================
--- portal/branches/wci/component/web/server/src/main/java/org/exoplatform/upload/UploadService.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/component/web/server/src/main/java/org/exoplatform/upload/UploadService.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -109,6 +109,9 @@
 
       DiskFileItem fileItem = (DiskFileItem)itemList.get(0);
       String fileName = fileItem.getName();
+      if (fileName == null)
+         fileName = uploadId;
+      fileName = fileName.substring(fileName.lastIndexOf('\\') + 1);
       String storeLocation = uploadLocation_ + "/" + uploadId + "." + fileName;
 
       // commons-fileupload will store the temp file with name *.tmp

Copied: portal/branches/wci/docs/reference-guide/en/modules/PortalDevelopment/LocalizationConfiguration.xml (from rev 5342, portal/trunk/docs/reference-guide/en/modules/PortalDevelopment/LocalizationConfiguration.xml)
===================================================================
--- portal/branches/wci/docs/reference-guide/en/modules/PortalDevelopment/LocalizationConfiguration.xml	                        (rev 0)
+++ portal/branches/wci/docs/reference-guide/en/modules/PortalDevelopment/LocalizationConfiguration.xml	2010-11-29 16:47:37 UTC (rev 5356)
@@ -0,0 +1,274 @@
+<?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;
+]>
+
+<section id="sect-Reference_Guide-Localization_Configuration-Pluggable_Locale_Policy">
+   <title>Pluggable Locale Policy</title>
+
+   <para>Every request processed by every portlet is invoked within a context of current <literal>Locale</literal>.
+      Current <literal>Locale</literal> can be retrieved by calling <literal>getLocale()</literal> method of
+      <literal>javax.portlet.PortletRequest</literal> interface.
+   </para>
+   <para>The exact algorithm for determining the current <literal>Locale</literal> is not specified by Portlet Specification,
+      and is left to portlet containers to implement the way they deem most appropriate.
+   </para>
+   <para>In &PRODUCT; each portal instance has a default language which can be used to present content for new users.
+      Another option is to use each user’s browser language preference, provided it matches one of the available
+      localizations that &PRODUCT; supports, and only fallback to portal default language if no match is found.
+      Every user, while visiting a portal, has an option to change the language of the user interface by using a Language chooser.
+      The choice can be remembered for the duration of the session, or it can be remembered for a longer period using a browser cookie,
+      or - for registered and logged-in users - it can be saved into user’s profile.
+   </para>
+   <para>So, we can see that there is more than one way to determine the <literal>Locale</literal> to be used for displaying a portal page
+      to the user. For this reason the mechanism for determining the current <literal>Locale</literal> of the request
+      is pluggable in &PRODUCT;, so the exact algorithm can be customized.
+   </para>
+
+      <section id="sect-Reference_Guide-Localization_Configuration-Pluggable_Locale_Policy-Locale_Policy_API">
+         <title>LocalePolicy API</title>
+
+         <para>Customization is achieved by using LocalePolicy API, which is a simple API consisting of one interface,
+            and one class:
+         </para>
+         <itemizedlist>
+            <listitem>
+               <para><literal>org.exoplatform.services.resources.LocalePolicy</literal> interface</para>
+            </listitem>
+            <listitem>
+               <para><literal>org.exoplatform.services.resources.LocaleContextInfo</literal> class</para>
+            </listitem>
+         </itemizedlist>
+
+         <para><literal>LocalePolicy</literal> interface defines a single method that’s invoked on the installed
+            <literal>LocalePolicy</literal> service implementation:
+         </para>
+
+         <programlisting><![CDATA[public interface LocalePolicy
+{
+   public Locale determineLocale(LocaleContextInfo localeContext);
+}]]>
+         </programlisting>
+         <para><literal>Locale</literal> returned by determineLocale() method is the <literal>Locale</literal>
+            that will be returned to portlets when they call <literal>javax.portlet.PortletRequest.getLocale()</literal> method.
+         </para>
+         <para>The returned <literal>Locale</literal> has to be one of the locales supported by portal,
+            otherwise it will fallback to portal-default <literal>Locale</literal>.
+         </para>
+
+         <para>The supported locales are listed in <filename>gatein.ear/02portal.war/WEB-INF/conf/common/locales-config.xml</filename> file
+            as described in <xref linkend="sect-Reference_Guide-Internationalization_Configuration-Locales_configuration"/> .
+         </para>
+
+         <para>The <literal>determineLocale()</literal> method takes a parameter of type <literal>LocaleContextInfo</literal>,
+            which represents a compilation of preferred locales from different sources - user’s profile, portal default,
+            browser language settings, current session, browser cookie … All these different sources of <literal>Locale</literal>
+            configuration or preference are used as input to <literal>LocalePolicy</literal> implementation
+            that decides which <literal>Locale</literal> should be used.
+         </para>
+
+      </section>
+      <section id="sect-Reference_Guide-Localization_Configuration-Pluggable_Locale_Policy-Default_LocalePolicy">
+         <title>Default <literal>LocalePolicy</literal></title>
+         <para>By default, <literal>org.exoplatform.portal.application.localization.DefaultLocalePolicyService</literal> - an implementation
+               of <literal>LocalePolicy</literal> - is installed to provide the default behaviour.
+               This, however, can easily be extended and overriden. A completely new implementation can also be written from scratch.
+         </para>
+         <para><literal>DefaultLocalePolicyService</literal> treats logged-in users slightly differently than anonymous users.
+            Logged-in users have a profile that can contain language preference, while anonymous users don't.
+         </para>
+         <para>Here is an algorithm used for anonymous users.</para>
+         <procedure>
+            <title>An algorithm for anonymous users</title>
+            <step>
+               <para>
+                  Iterate over <literal>LocaleContextInfo</literal> properties in the following order:
+               </para>
+               <itemizedlist>
+                  <listitem>
+                     <para><literal>cookieLocales</literal></para>
+                  </listitem>
+                  <listitem>
+                     <para><literal>sessionLocale</literal></para>
+                  </listitem>
+                  <listitem>
+                     <para><literal>browserLocales</literal></para>
+                  </listitem>
+                  <listitem>
+                     <para><literal>portalLocale</literal></para>
+                  </listitem>
+               </itemizedlist>
+            </step>
+            <step>
+               <para>Get each property's value - if it's a collection, get the first value.
+               </para>
+            </step>
+            <step>
+               <para>If value is one of the supported locales return it as a result.
+               </para>
+            </step>
+            <step>
+               <para>If value is not in the supported locales set, try to remove country information,
+                  and check if a language matching locale is in the list of supported locales.
+                  If so, return it as a result.
+               </para>
+            </step>
+            <step>
+               <para>Otherwise, continue with the next property.
+               </para>
+            </step>
+         </procedure>
+         <para>If no supported locale is found the return locale eventually defaults to <literal>portalLocale</literal>.
+         </para>
+         <para>The algorithm for logged-in users is virtually the same except that the first <literal>Locale</literal>
+            source checked is user's profile.</para>
+         <procedure>
+            <title>An algorithm for logged-in users</title>
+            <step>
+               <para>
+                  Iterate over <literal>LocaleContextInfo</literal> properties in the following order:
+               </para>
+               <itemizedlist>
+                  <listitem>
+                     <para><literal>userProfile</literal></para>
+                  </listitem>
+                  <listitem>
+                     <para><literal>cookieLocales</literal></para>
+                  </listitem>
+                  <listitem>
+                     <para><literal>sessionLocale</literal></para>
+                  </listitem>
+                  <listitem>
+                     <para><literal>browserLocales</literal></para>
+                  </listitem>
+                  <listitem>
+                     <para><literal>portalLocale</literal></para>
+                  </listitem>
+               </itemizedlist>
+            </step>
+            <step>
+               <para>The rest is the same as for anonymous users ...</para>
+            </step>
+         </procedure>
+
+      </section>
+      <section id="sect-Reference_Guide-Localization_Configuration-Pluggable_Locale_Policy-Custom_LocalePolicy">
+         <title>Custom <literal>LocalePolicy</literal></title>
+         <para>The easiest way to customize the <literal>LocalePolicy</literal> is to extend <literal>DefaultLocalePolicyService</literal>.
+            The study of its source code will be required. There is ample JavaDoc that provides thorough information.
+            Most customizations will involve simply overriding one or more of its protected methods.
+         </para>
+         <para>
+            An example of a customization is an already provided <literal>NoBrowserLocalePolicyService</literal>.
+            By overriding just one method, it skips any use of browser language preference.
+         </para>
+         <programlisting><![CDATA[public class NoBrowserLocalePolicyService extends DefaultLocalePolicyService
+{
+   /**
+    * Override super method with no-op.
+    *
+    * @param context locale context info available to implementations in order to determine appropriate Locale
+    * @return null
+    */
+   @Override
+   protected Locale getLocaleConfigFromBrowser(LocaleContextInfo context)
+   {
+      return null;
+   }
+}]]>
+         </programlisting>
+      </section>
+
+      <section id="sect-Reference_Guide-Localization_Configuration-Pluggable_Locale_Policy-Configuration">
+         <title>LocalePolicy Configuration</title>
+
+         <para>The <literal>LocalePolicy</literal> framework is enabled for portlets by configuring LocalizationLifecycle class in portal's webui configuration file:
+         <filename>gatein.ear/02portal.war/WEB-INF/webui-configuration.xml</filename>:</para>
+
+         <programlisting role="XML"><![CDATA[    <application-lifecycle-listeners>
+      ...
+      <listener>org.exoplatform.portal.application.localization.LocalizationLifecycle</listener>
+    </application-lifecycle-listeners>]]>
+         </programlisting>
+
+         <para>The default <literal>LocalePolicy</literal> implementation is installed as GateIn Kernel portal service via
+            <filename>gatein.ear/lib/exo.portal.webui.portal-VERSION.jar/conf/portal/configuration.xml</filename>.
+         </para>
+         <para>The following fragment is responsible for installing the service:
+         </para>
+         <programlisting role="XML"><![CDATA[    <component>
+       <key>org.exoplatform.services.resources.LocalePolicy</key>
+       <type>org.exoplatform.portal.application.localization.DefaultLocalePolicyService</type>
+   </component>]]>
+         </programlisting>
+         <para>Besides implementing <literal>LocalePolicy</literal>, the service class also needs to implement
+            <literal>org.picocontainer.Startable</literal> interface in order to get installed.
+         </para>
+         <para>This configuration file should not be changed. The configuration in it can be overriden by placing it into portal's .war file:
+            <filename>gatein.ear/02portal.war/WEB-INF/conf/configuration.xml</filename> (usually as another file included into this one).
+         </para>
+      </section>
+
+      <section id="sect-Reference_Guide-Localization_Configuration-Pluggable_Locale_Policy-Non_bridged">
+         <title>Keeping non-bridged resources in sync with current Locale</title>
+         <para>In portals all the resources that are not portlets themselves but are accessed through portlets - reading
+            data through <literal>PortletRequest</literal>, and writing to <literal>PortletResponse</literal> - are
+            referred to as 'bridged'. Any resources that are accessed directly, bypassing portal filters and servlets,
+            are referred to as 'non-bridged'.
+         </para>
+         <para>Non-bridged servlets, and .jsps have no access to <literal>PortalRequest</literal>. They don't use
+            <literal>PortletRequest.getLocale()</literal> to determine current <literal>Locale</literal>.
+            Instead, they use <literal>ServletRequest.getLocale()</literal> which is subject to precise semantics
+            defined by Servlet specification - it reflects browser's language preference.
+         </para>
+         <para>In other words, non-bridged resources don't have a notion of current <literal>Locale</literal>
+            in the same sense that portlets do. The result is that when mixing portlets and non-bridged resources there
+            may be a localization mismatch - an inconsistency in the language used by different resources composing your portal
+            page.
+         </para>
+         <para>This problem is addressed by <literal>LocalizationFilter</literal>. This is a filter that changes the behaviour
+            of <literal>ServletRequest.getLocale()</literal> method so that it behaves the same way as
+            <literal>PortletRequest.getLocale()</literal>. That way even localization of servlets, and .jsps
+            accessed in a non-bridged manner can stay in sync with portlet localization.
+         </para>
+         <para><literal>LocalizationFilter</literal> is installed through portal's web.xml file: <filename>gatein.ear/02portal.war/WEB-INF/web.xml</filename>
+         </para>
+         <programlisting role="XML"><![CDATA[   <filter>
+		<filter-name>LocalizationFilter</filter-name>
+		<filter-class>org.exoplatform.portal.application.localization.LocalizationFilter</filter-class>
+	</filter>
+
+	...
+
+	<filter-mapping>
+       <filter-name>LocalizationFilter</filter-name>
+       <url-pattern>/*</url-pattern>
+       <dispatcher>INCLUDE</dispatcher>
+       <dispatcher>FORWARD</dispatcher>
+       <dispatcher>REQUEST</dispatcher>
+       <dispatcher>ERROR</dispatcher>
+   </filter-mapping>]]>
+         </programlisting>
+         <para>There is a tiny limitation with this mechanism in that it is unable to determine the current portal,
+            and consequently its default language. As a result the portalLocale defaults to <literal>English</literal>, but can be configured
+            to something else by using filter's <literal>PortalLocale</literal> init param. For example:
+         </para>
+         <programlisting role="XML"><![CDATA[   <filter>
+		<filter-name>LocalizationFilter</filter-name>
+		<filter-class>org.exoplatform.portal.application.localization.LocalizationFilter</filter-class>
+		<init-param>
+		   <param-name>PortalLocale</param-name>
+		   <param-value>fr_FR</param-value>
+		</init-param>
+	</filter> ]]>
+         </programlisting>
+         <para>By default, <literal>LocalizationFilter</literal> is applied very broadly to cover all the resources automatically.
+            &PRODUCT; uses some non-bridged .jsps that require <literal>LocalizationFilter</literal>, so narrowing
+            the mapping to *.jsp is enough for &PRODUCT; to still function correctly. Additionally deployed portlets,
+            and portal applications, however, may require broader mapping to cover their non-bridged resources.
+         </para>
+         <para>Narrowing the mapping might improve performance. This is something to consider, when optimizing for speed.
+         </para>
+      </section>
+   </section>
\ No newline at end of file

Modified: portal/branches/wci/docs/reference-guide/en/modules/PortalDevelopment.xml
===================================================================
--- portal/branches/wci/docs/reference-guide/en/modules/PortalDevelopment.xml	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/docs/reference-guide/en/modules/PortalDevelopment.xml	2010-11-29 16:47:37 UTC (rev 5356)
@@ -11,6 +11,7 @@
 	<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" />
+	<xi:include href="PortalDevelopment/LocalizationConfiguration.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" />

Modified: portal/branches/wci/examples/portal/war/src/main/webapp/WEB-INF/web.xml
===================================================================
--- portal/branches/wci/examples/portal/war/src/main/webapp/WEB-INF/web.xml	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/examples/portal/war/src/main/webapp/WEB-INF/web.xml	2010-11-29 16:47:37 UTC (rev 5356)
@@ -252,10 +252,6 @@
 		<url-pattern>/gateinservlet</url-pattern>
 	</servlet-mapping>
 
-	<session-config>
-		<session-timeout>30</session-timeout>
-	</session-config>
-
 	<!-- The Welcome File List for IBM WebSphere -->
 
 	<welcome-file-list>

Modified: portal/branches/wci/gadgets/core/src/main/java/org/exoplatform/portal/gadget/core/ProxyServletFilter.java
===================================================================
--- portal/branches/wci/gadgets/core/src/main/java/org/exoplatform/portal/gadget/core/ProxyServletFilter.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/gadgets/core/src/main/java/org/exoplatform/portal/gadget/core/ProxyServletFilter.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -22,6 +22,9 @@
 import org.exoplatform.container.PortalContainer;
 import org.exoplatform.web.security.proxy.ProxyFilterService;
 
+import org.gatein.common.logging.LoggerFactory;
+import org.gatein.common.logging.Logger;
+
 import javax.servlet.Filter;
 import javax.servlet.FilterChain;
 import javax.servlet.FilterConfig;
@@ -57,6 +60,9 @@
    /** . */
    private ServletContext ctx;
 
+   /** . */
+   private static final Logger logger = LoggerFactory.getLogger(ProxyServletFilter.class);
+
    public void init(FilterConfig cfg) throws ServletException
    {
       this.ctx = cfg.getServletContext();
@@ -90,14 +96,23 @@
             }
             else
             {
-               URI uri = URI.create(url);
-               if (!service.accept(hreq, container, uri))
+               try
                {
-                  hresp.sendError(HttpServletResponse.SC_FORBIDDEN, "Gadget " + url + " is blacklisted");
+                  URI uri = URI.create(url);
+                  if (!service.accept(hreq, container, uri))
+                  {
+                     hresp.sendError(HttpServletResponse.SC_FORBIDDEN, "Gadget " + url + " is blacklisted");
+                  }
+                  else
+                  {
+                     chain.doFilter(req, resp);
+                  }
+
                }
-               else
+               catch (java.lang.IllegalArgumentException e)
                {
-                  chain.doFilter(req, resp);
+                  // It happens that some URLs can be wrong, I've seen this with "http://" as URL in one of the Google Gadgets
+                  logger.debug("Invalid URL: " + url);
                }
             }
          }

Modified: portal/branches/wci/gadgets/eXoGadgets/src/main/webapp/gadgets/rssAggregator/script.js
===================================================================
--- portal/branches/wci/gadgets/eXoGadgets/src/main/webapp/gadgets/rssAggregator/script.js	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/gadgets/eXoGadgets/src/main/webapp/gadgets/rssAggregator/script.js	2010-11-29 16:47:37 UTC (rev 5356)
@@ -43,7 +43,7 @@
     if (isNaN(B)) {
         return "an indeterminate amount of time ago"
     }
-    time = (new Date().getTime() 1000 - B) / 1000;
+    time = (new Date().getTime()*1000 - B) / 1000;
     if (time < 60) {
         return "less than a minute ago"
     } else {


Property changes on: portal/branches/wci/packaging/tomcat/integration
___________________________________________________________________
Name: svn:ignore
   + target


Modified: portal/branches/wci/pom.xml
===================================================================
--- portal/branches/wci/pom.xml	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/pom.xml	2010-11-29 16:47:37 UTC (rev 5356)
@@ -47,8 +47,8 @@
       <org.gatein.common.version>2.0.3-GA</org.gatein.common.version>
       <org.gatein.wci.version>2.1.0-Alpha01-SNAPSHOT</org.gatein.wci.version>
       <org.gatein.pc.version>2.2.0-GA</org.gatein.pc.version>
-      <org.picketlink.idm>1.1.7.CR01</org.picketlink.idm>
-      <org.gatein.wsrp.version>2.0.0-CR02</org.gatein.wsrp.version>
+      <org.picketlink.idm>1.1.7.GA</org.picketlink.idm>
+      <org.gatein.wsrp.version>2.0.0-CR03</org.gatein.wsrp.version>
       <org.gatein.mop.version>1.0.3-GA</org.gatein.mop.version>
       <org.slf4j.version>1.5.6</org.slf4j.version>
       <rhino.version>1.6R5</rhino.version>
@@ -1346,6 +1346,12 @@
           <version>5.1.6</version>
           <scope>test</scope>
         </dependency>
+        <dependency>
+           <groupId>log4j</groupId>
+           <artifactId>log4j</artifactId>
+           <version>1.2.14</version>
+           <scope>test</scope>
+        </dependency>
       </dependencies>
       <build>
         <plugins>

Modified: portal/branches/wci/portlet/dashboard/src/main/java/org/exoplatform/gadget/webui/component/UIGadgetPortlet.java
===================================================================
--- portal/branches/wci/portlet/dashboard/src/main/java/org/exoplatform/gadget/webui/component/UIGadgetPortlet.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/portlet/dashboard/src/main/java/org/exoplatform/gadget/webui/component/UIGadgetPortlet.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -20,8 +20,8 @@
 package org.exoplatform.gadget.webui.component;
 
 import org.exoplatform.application.gadget.Gadget;
+import org.exoplatform.application.gadget.GadgetImporter;
 import org.exoplatform.application.gadget.GadgetRegistryService;
-import org.exoplatform.application.gadget.LocalImporter;
 import org.exoplatform.container.ExoContainer;
 import org.exoplatform.container.ExoContainerContext;
 import org.exoplatform.portal.webui.application.GadgetUtil;
@@ -50,7 +50,7 @@
 {
    final static public String LOCAL_STRING = "local://";
 
-   private static final Logger log = LoggerFactory.getLogger(LocalImporter.class);
+   private static final Logger log = LoggerFactory.getLogger(GadgetImporter.class);
 
    public UIGadgetPortlet() throws Exception
    {

Modified: portal/branches/wci/portlet/exoadmin/src/main/java/org/exoplatform/toolbar/webui/component/UIUserToolBarGroupPortlet.java
===================================================================
--- portal/branches/wci/portlet/exoadmin/src/main/java/org/exoplatform/toolbar/webui/component/UIUserToolBarGroupPortlet.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/portlet/exoadmin/src/main/java/org/exoplatform/toolbar/webui/component/UIUserToolBarGroupPortlet.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -55,7 +55,7 @@
       {
          if (navigation.getOwnerType().equals(PortalConfig.GROUP_TYPE))
          {
-            navigations.add(PageNavigationUtils.filter(navigation, remoteUser));
+            navigations.add(PageNavigationUtils.filterNavigation(navigation, remoteUser, false, true));
          }
       }
       return navigations;

Modified: portal/branches/wci/portlet/exoadmin/src/main/java/org/exoplatform/toolbar/webui/component/UIUserToolBarSitePortlet.java
===================================================================
--- portal/branches/wci/portlet/exoadmin/src/main/java/org/exoplatform/toolbar/webui/component/UIUserToolBarSitePortlet.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/portlet/exoadmin/src/main/java/org/exoplatform/toolbar/webui/component/UIUserToolBarSitePortlet.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -68,7 +68,7 @@
    {
       PageNavigation navi = getPageNavigation(PortalConfig.PORTAL_TYPE + "::" + getCurrentPortal());
       String remoteUser = Util.getPortalRequestContext().getRemoteUser();
-      return PageNavigationUtils.filter(navi, remoteUser);
+      return PageNavigationUtils.filterNavigation(navi, remoteUser, false, true);
    }
 
    private PageNavigation getPageNavigation(String owner) throws Exception

Modified: portal/branches/wci/portlet/exoadmin/src/main/webapp/groovy/applicationregistry/webui/component/UIGadgetInfo.gtmpl
===================================================================
--- portal/branches/wci/portlet/exoadmin/src/main/webapp/groovy/applicationregistry/webui/component/UIGadgetInfo.gtmpl	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/portlet/exoadmin/src/main/webapp/groovy/applicationregistry/webui/component/UIGadgetInfo.gtmpl	2010-11-29 16:47:37 UTC (rev 5356)
@@ -11,6 +11,9 @@
 	if(gadgetThumbnail == null || gadgetThumbnail.length() == 0){
 		gadgetThumbnail = srcBGError ;
 	}
+        def viewURL = uicomponent.getViewUrl();
+        def editURL = uicomponent.getEditUrl();
+        def refURL = gadget.getReferenceUrl();
 %>
 <div class="UIGadgetInfo" id="$uicomponent.id">
 	<div class="UIBreadcumb">
@@ -21,7 +24,7 @@
 		<div class="Refresh16x16Icon ControlIcon" title="<%=_ctx.appRes("UIGadgetInfo.title.refresh")%>" onclick="<%= uicomponent.event("Refresh") %>"><span></span></div>
 		<div class="ClearBoth"><span></span></div>
 	</div>
- 	<div class="Application ClearFix">
+ 	<div class="Application">
  		<div class="PortletIcons">
 				<img src="$gadgetThumbnail" onError="src='$srcBGError'" alt=""/>
 		</div>
@@ -41,12 +44,12 @@
 				<table>
 					<tr>
 						<td class="LeftLabel"><%=_ctx.appRes("UIGadgetInfo.label.viewUrl")%></td>
-						<td class="RightLabel" title=" <%= uicomponent.getViewUrl() %> "><%= uicomponent.getViewUrl() %></td>
+						<td class="RightLabel" title=" <%=viewURL %> "><a href="<%=viewURL %>" target="_blank">$viewURL</a></td>
 					</tr>						
 					<% if(gadget.isLocal()) {%>
 					<tr>
 						<td class="LeftLabel"><%=_ctx.appRes("UIGadgetInfo.label.editUrl")%></td>
-						<td class="RightLabel"><%= uicomponent.getEditUrl() %></td>
+						<td class="RightLabel"><a href="<%=editURL %>" target="_blank">$editURL</a></td>
 					</tr>						
 					<% } %>
 				</table>
@@ -54,7 +57,7 @@
 					<tr>
 						<td class="LeftLabel"><%=_ctx.appRes("UIGadgetInfo.label.reference")%></td>
 						<td class="RightLabel">						
-							<%= gadget.getReferenceUrl() %>
+							<a href="<%=refURL %>" target="_blank">$refURL</a>
 						</td>
 					</tr>
 				</table>

Modified: portal/branches/wci/portlet/exoadmin/src/main/webapp/skin/organization/webui/component/UIOrganizationPortlet/DefaultStylesheet.css
===================================================================
--- portal/branches/wci/portlet/exoadmin/src/main/webapp/skin/organization/webui/component/UIOrganizationPortlet/DefaultStylesheet.css	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/portlet/exoadmin/src/main/webapp/skin/organization/webui/component/UIOrganizationPortlet/DefaultStylesheet.css	2010-11-29 16:47:37 UTC (rev 5356)
@@ -168,6 +168,7 @@
 	float: left; /* orientation=lt */
 	float: right; /* orientation=rt */
 	height: auto;
+	width: 100%;
 }
 
 .UIOrganizationPortlet .UISearch .UISearchForm .QuickSet {

Modified: portal/branches/wci/portlet/web/src/main/webapp/groovy/portal/webui/component/UIPortalNavigation.gtmpl
===================================================================
--- portal/branches/wci/portlet/web/src/main/webapp/groovy/portal/webui/component/UIPortalNavigation.gtmpl	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/portlet/web/src/main/webapp/groovy/portal/webui/component/UIPortalNavigation.gtmpl	2010-11-29 16:47:37 UTC (rev 5356)
@@ -95,7 +95,7 @@
 					<div class="MenuItem $tabStyleNavigation">
 						<div class="$arrowIcon" title="$title">
 							<div class="ItemIcon $icon">
-								<a href="$pageURI">$label</a>
+								<a href="#">$label</a>
 							</div>
 						</div>
 			""";

Modified: portal/branches/wci/testsuite/selenium-snifftests/src/suite/org/exoplatform/portal/selenium/NewSnifftest/Test_SNF_PRL_37_ManageNavigationOfGroup.html
===================================================================
--- portal/branches/wci/testsuite/selenium-snifftests/src/suite/org/exoplatform/portal/selenium/NewSnifftest/Test_SNF_PRL_37_ManageNavigationOfGroup.html	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/testsuite/selenium-snifftests/src/suite/org/exoplatform/portal/selenium/NewSnifftest/Test_SNF_PRL_37_ManageNavigationOfGroup.html	2010-11-29 16:47:37 UTC (rev 5356)
@@ -118,12 +118,12 @@
 </tr>
 <tr>
 	<td>waitForElementPresent</td>
-	<td>//div[@id='UIAddGroupNavigationGrid']/table[1]/tbody/tr/td[2]/a</td>
+	<td>//div[@id='UIAddGroupNavigationGrid']/table[2]/tbody/tr/td[2]/a</td>
 	<td></td>
 </tr>
 <tr>
 	<td>click</td>
-	<td>//div[@id='UIAddGroupNavigationGrid']/table[1]/tbody/tr/td[2]/a</td>
+	<td>//div[@id='UIAddGroupNavigationGrid']/table[2]/tbody/tr/td[2]/a</td>
 	<td></td>
 </tr>
 <tr>
@@ -138,12 +138,12 @@
 </tr>
 <tr>
 	<td>waitForTextPresent</td>
-	<td>Operations</td>
+	<td>Organization</td>
 	<td></td>
 </tr>
 <tr>
 	<td>verifyTextPresent</td>
-	<td>Operations</td>
+	<td>Organization</td>
 	<td></td>
 </tr>
 <tr>
@@ -153,12 +153,12 @@
 </tr>
 <tr>
 	<td>waitForElementPresent</td>
-	<td>//div[@id='UIGroupNavigationGrid']/table[2]/tbody/tr/td[3]/a[3]</td>
+	<td>link=Delete Navigation</td>
 	<td></td>
 </tr>
 <tr>
 	<td>click</td>
-	<td>//div[@id='UIGroupNavigationGrid']/table[2]/tbody/tr/td[3]/a[3]</td>
+	<td>link=Delete Navigation</td>
 	<td></td>
 </tr>
 <tr>
@@ -173,12 +173,12 @@
 </tr>
 <tr>
 	<td>waitForTextNotPresent</td>
-	<td>Operations</td>
+	<td>Organization</td>
 	<td></td>
 </tr>
 <tr>
 	<td>verifyTextNotPresent</td>
-	<td>Operations</td>
+	<td>Organization</td>
 	<td></td>
 </tr>
 <tr>

Modified: portal/branches/wci/testsuite/selenium-snifftests/src/suite/org/exoplatform/portal/selenium/NewSnifftest/Test_SNF_PRL_49_ChangeApplicationWhenEditPagePropertiesOfNode.html
===================================================================
--- portal/branches/wci/testsuite/selenium-snifftests/src/suite/org/exoplatform/portal/selenium/NewSnifftest/Test_SNF_PRL_49_ChangeApplicationWhenEditPagePropertiesOfNode.html	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/testsuite/selenium-snifftests/src/suite/org/exoplatform/portal/selenium/NewSnifftest/Test_SNF_PRL_49_ChangeApplicationWhenEditPagePropertiesOfNode.html	2010-11-29 16:47:37 UTC (rev 5356)
@@ -503,7 +503,7 @@
 </tr>
 <tr>
 	<td>mouseOver</td>
-	<td>//div[2]/div/div[2]/div/div/div[2]/div/div/div/div/div/div/div[2]</td>
+	<td>//div/div/div[2]/div/div/div/div/div/div/div[2]</td>
 	<td>Test_SNF_PRL_49</td>
 </tr>
 <tr>
@@ -538,17 +538,17 @@
 </tr>
 <tr>
 	<td>mouseOver</td>
-	<td>//div[2]/div/div[2]/div/div/div[2]/div/div/div/div/div/div/div[2]</td>
+	<td>//div/div/div[2]/div/div/div/div/div/div/div[2]</td>
 	<td>Test_SNF_PRL_49</td>
 </tr>
 <tr>
 	<td>waitForElementPresent</td>
-	<td>//div[2]/div/div[2]/div/div/div[2]/div/div/div/div/div/div/a[2]</td>
+	<td>//div/div/div[2]/div/div/div/div/div/div/a[2]</td>
 	<td></td>
 </tr>
 <tr>
 	<td>click</td>
-	<td>//div[2]/div/div[2]/div/div/div[2]/div/div/div/div/div/div/a[2]</td>
+	<td>//div/div/div[2]/div/div/div/div/div/div/a[2]</td>
 	<td></td>
 </tr>
 <tr>

Modified: portal/branches/wci/testsuite/selenium-snifftests/src/suite/org/exoplatform/portal/selenium/Test_PRL_03_01_001_CheckShowingGroupManagementForm.html
===================================================================
--- portal/branches/wci/testsuite/selenium-snifftests/src/suite/org/exoplatform/portal/selenium/Test_PRL_03_01_001_CheckShowingGroupManagementForm.html	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/testsuite/selenium-snifftests/src/suite/org/exoplatform/portal/selenium/Test_PRL_03_01_001_CheckShowingGroupManagementForm.html	2010-11-29 16:47:37 UTC (rev 5356)
@@ -123,13 +123,13 @@
 </tr>
 <tr>
 	<td>waitForTextPresent</td>
-	<td>//div[@id='UIOrganizationPortlet']/div[2]/div[2]/div[1]/div[2]/div[1]/div[2]/div/div/div/div[3]/div[1]/a</td>
+	<td>Organization</td>
 	<td></td>
 </tr>
 <tr>
-	<td>verifyText</td>
-	<td>//div[@id='UIOrganizationPortlet']/div[2]/div[2]/div[1]/div[2]/div[1]/div[2]/div/div/div/div[3]/div[1]/a</td>
+	<td>verifyTextPresent</td>
 	<td>Organization</td>
+	<td></td>
 </tr>
 <tr>
 	<td>echo</td>
@@ -183,12 +183,12 @@
 </tr>
 <tr>
 	<td>waitForTextPresent</td>
-	<td>link=Customers</td>
+	<td>Customers</td>
 	<td></td>
 </tr>
 <tr>
 	<td>verifyTextPresent</td>
-	<td>link=Customers</td>
+	<td>Customers</td>
 	<td></td>
 </tr>
 <tr>
@@ -207,12 +207,12 @@
 	<td></td>
 </tr>
 <tr>
-	<td>waitForTextPresent</td>
+	<td>waitForElementPresent</td>
 	<td>//div[1]/div[2]/div/div/div/div[1]/a</td>
 	<td></td>
 </tr>
 <tr>
-	<td>verifyTextPresent</td>
+	<td>verifyElementPresent</td>
 	<td>//div[1]/div[2]/div/div/div/div[1]/a</td>
 	<td></td>
 </tr>

Modified: portal/branches/wci/testsuite/selenium-snifftests/src/suite/org/exoplatform/portal/selenium/Test_PRL_03_05_012_AddSomeUsersIntoGroupInCaseAfterCommaHasSpace.html
===================================================================
--- portal/branches/wci/testsuite/selenium-snifftests/src/suite/org/exoplatform/portal/selenium/Test_PRL_03_05_012_AddSomeUsersIntoGroupInCaseAfterCommaHasSpace.html	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/testsuite/selenium-snifftests/src/suite/org/exoplatform/portal/selenium/Test_PRL_03_05_012_AddSomeUsersIntoGroupInCaseAfterCommaHasSpace.html	2010-11-29 16:47:37 UTC (rev 5356)
@@ -102,6 +102,11 @@
 	<td>root, john,&nbsp;&nbsp;demo</td>
 </tr>
 <tr>
+	<td>echo</td>
+	<td>-- http://jira.exoplatform.org/browse/SELEGEN-37 --</td>
+	<td></td>
+</tr>
+<tr>
 	<td>waitForElementPresent</td>
 	<td>membership</td>
 	<td></td>

Modified: portal/branches/wci/testsuite/testdefinitions/GateIn_v3.2.x_MainFunctions_TestDefinition.ods
===================================================================
(Binary files differ)

Modified: portal/branches/wci/web/eXoResources/src/main/webapp/skin/DefaultSkin/portal/webui/component/customization/UIPageBrowser/Stylesheet.css
===================================================================
--- portal/branches/wci/web/eXoResources/src/main/webapp/skin/DefaultSkin/portal/webui/component/customization/UIPageBrowser/Stylesheet.css	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/web/eXoResources/src/main/webapp/skin/DefaultSkin/portal/webui/component/customization/UIPageBrowser/Stylesheet.css	2010-11-29 16:47:37 UTC (rev 5356)
@@ -29,7 +29,7 @@
 .UIPageBrowser .UIGrid {	
 	width: 99.7%;
 	!width: 98%;
-	margin: auto;
+	margin: 0px;
 }
 
 .UIPageBrowser .UIGrid .Text {	

Modified: portal/branches/wci/web/portal/src/main/webapp/WEB-INF/conf/organization/picketlink-idm/jboss-cache-cluster.xml
===================================================================
--- portal/branches/wci/web/portal/src/main/webapp/WEB-INF/conf/organization/picketlink-idm/jboss-cache-cluster.xml	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/web/portal/src/main/webapp/WEB-INF/conf/organization/picketlink-idm/jboss-cache-cluster.xml	2010-11-29 16:47:37 UTC (rev 5356)
@@ -8,10 +8,11 @@
 
   <!-- Eviction configuration -->
   <eviction wakeUpInterval="5000">
-    <default algorithmClass="org.jboss.cache.eviction.LRUAlgorithm"
+    <default algorithmClass="org.jboss.cache.eviction.ExpirationAlgorithm"
       eventQueueSize="1000000">
-      <property name="maxNodes" value="1000000" />
+      <property name="maxNodes" value="100000" />
       <property name="timeToLive" value="120000" />
+      <property name="warnNoExpirationKey" value="false" />
     </default>
   </eviction>
 

Modified: portal/branches/wci/web/portal/src/main/webapp/WEB-INF/web.xml
===================================================================
--- portal/branches/wci/web/portal/src/main/webapp/WEB-INF/web.xml	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/web/portal/src/main/webapp/WEB-INF/web.xml	2010-11-29 16:47:37 UTC (rev 5356)
@@ -292,10 +292,6 @@
     <url-pattern>/gateinservlet</url-pattern>
   </servlet-mapping>
 
-	<session-config>
-	  <session-timeout>30</session-timeout>
-	</session-config>
-
   <!-- The Welcome File List for IBM WebSphere -->
 
 	<welcome-file-list>

Modified: portal/branches/wci/web/portal/src/main/webapp/groovy/portal/webui/workspace/UIPortalApplication.gtmpl
===================================================================
--- portal/branches/wci/web/portal/src/main/webapp/groovy/portal/webui/workspace/UIPortalApplication.gtmpl	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/web/portal/src/main/webapp/groovy/portal/webui/workspace/UIPortalApplication.gtmpl	2010-11-29 16:47:37 UTC (rev 5356)
@@ -47,10 +47,12 @@
       <link id="${portletSkin.id}" rel="stylesheet" type="text/css" href= "$url" />
     <%}%>
      <script type="text/javascript">
+     <%
      // This variable must be used only to initialize other variables otherwise
      // please use eXo.env.portal.context or eXo.env.portal.context instead
      // Those 2 last variables cannot be used to initialize variables because 
      // we cannot be sure that they will be initialized before initializing your script
+     %>
       var currentContext = '<%=docBase%>' ;
     </script>   
     <%if(org.exoplatform.commons.utils.PropertyManager.isDevelopping()) {

Modified: portal/branches/wci/web/portal/src/main/webapp/index.jsp
===================================================================
--- portal/branches/wci/web/portal/src/main/webapp/index.jsp	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/web/portal/src/main/webapp/index.jsp	2010-11-29 16:47:37 UTC (rev 5356)
@@ -22,8 +22,14 @@
 <%@ page import="org.exoplatform.container.PortalContainer"%>
 <%@ page import="org.exoplatform.portal.config.UserPortalConfigService"%>
 <%
-	PortalContainer manager = PortalContainer.getCurrentInstance(session.getServletContext()) ;
-  UserPortalConfigService userPortalConfigService = (UserPortalConfigService) manager.getComponentInstanceOfType(UserPortalConfigService.class) ;
-	response.sendRedirect(request.getContextPath() + "/public/"+userPortalConfigService.getDefaultPortal()+"/");
+   PortalContainer manager = PortalContainer.getCurrentInstance(session.getServletContext());
+   UserPortalConfigService userPortalConfigService = (UserPortalConfigService)manager.getComponentInstanceOfType(UserPortalConfigService.class);
+   String remoteUser = request.getRemoteUser();
+   String accessMode = "public";
+   if (remoteUser != null && remoteUser.trim().length() > 0)
+   {
+      accessMode = "private";
+   }
+   response.sendRedirect(request.getContextPath() + "/" + accessMode + "/" + userPortalConfigService.getDefaultPortal() + "/");
 %>
 

Modified: portal/branches/wci/web/rest/src/main/webapp/WEB-INF/web.xml
===================================================================
--- portal/branches/wci/web/rest/src/main/webapp/WEB-INF/web.xml	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/web/rest/src/main/webapp/WEB-INF/web.xml	2010-11-29 16:47:37 UTC (rev 5356)
@@ -84,10 +84,6 @@
     <url-pattern>/*</url-pattern>
   </servlet-mapping>
 
-	<session-config>
-	  <session-timeout>30</session-timeout> 
-	</session-config>
-	
   <security-constraint>
     <web-resource-collection>
       <web-resource-name>rest</web-resource-name>

Modified: portal/branches/wci/webui/eXo/src/main/java/org/exoplatform/webui/organization/account/UIUserSelector.java
===================================================================
--- portal/branches/wci/webui/eXo/src/main/java/org/exoplatform/webui/organization/account/UIUserSelector.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/webui/eXo/src/main/java/org/exoplatform/webui/organization/account/UIUserSelector.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -412,7 +412,9 @@
          uiSelectUserForm.setSelectedGroup(groupId);
          OrganizationService service = uiSelectGroupForm.getApplicationComponent(OrganizationService.class);
          PageList users = uiSelectUserForm.removeDuplicate(service.getUserHandler().findUsersByGroup(groupId));
+         users.setPageSize(10);
          uiSelectUserForm.uiIterator_.setPageList(users);
+         uiSelectUserForm.setKeyword(null);
          event.getRequestContext().addUIComponentToUpdateByAjax(uiSelectUserForm);
       }
    }
@@ -423,17 +425,23 @@
       {
          UIUserSelector uiSelectUserForm = event.getSource();
          String groupId = uiSelectUserForm.getSelectedGroup();
-         uiSelectUserForm.setSelectedGroup(groupId);
          OrganizationService service = uiSelectUserForm.getApplicationComponent(OrganizationService.class);
+
+         PageList users = PageList.EMPTY_LIST;
          if (groupId != null && groupId.trim().length() != 0)
          {
-            PageList users = uiSelectUserForm.removeDuplicate(service.getUserHandler().findUsersByGroup(groupId));
-            uiSelectUserForm.uiIterator_.setPageList(users);
+            if (service.getGroupHandler().findGroupById(groupId) != null)
+            {
+               users = uiSelectUserForm.removeDuplicate(service.getUserHandler().findUsersByGroup(groupId));
+            }                                                            
          }
          else
          {
-            uiSelectUserForm.uiIterator_.setPageList(service.getUserHandler().findUsers(new Query()));
+            users = service.getUserHandler().findUsers(new Query());
          }
+         users.setPageSize(10);
+         uiSelectUserForm.uiIterator_.setPageList(users);
+         uiSelectUserForm.setKeyword(null);
          event.getRequestContext().addUIComponentToUpdateByAjax(uiSelectUserForm);
       }
    }

Modified: portal/branches/wci/webui/framework/src/main/java/org/exoplatform/webui/core/UIComponentDecorator.java
===================================================================
--- portal/branches/wci/webui/framework/src/main/java/org/exoplatform/webui/core/UIComponentDecorator.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/webui/framework/src/main/java/org/exoplatform/webui/core/UIComponentDecorator.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -48,14 +48,22 @@
       return uicomponent_;
    }
 
-   public void setUIComponent(UIComponent uicomponent)
+   public UIComponent setUIComponent(UIComponent uicomponent)
    {
+      UIComponent oldOne = uicomponent_;
       if (uicomponent_ != null)
-         uicomponent_.setRendered(false);
+         uicomponent_.setParent(null);
       uicomponent_ = uicomponent;
-      if (uicomponent_ == null)
-         return;
-      uicomponent_.setParent(this);
+      if (uicomponent_ != null)
+      {
+         UIComponent oldParent = uicomponent_.getParent();
+         if (oldParent != null && oldParent != this && oldParent instanceof UIComponentDecorator)
+         {
+            ((UIComponentDecorator)oldParent).setUIComponent(null);
+         }
+         uicomponent_.setParent(this);
+      }
+      return oldOne;
    }
 
    @SuppressWarnings("unchecked")

Modified: portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/application/localization/LocalizationFilter.java
===================================================================
--- portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/application/localization/LocalizationFilter.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/application/localization/LocalizationFilter.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -56,15 +56,27 @@
  * override for extra-portlet requests (i.e. unbridged .jsp). Thanks to it dynamic resources can be localized
  * to keep in sync with the rest of the portal. This filter is re-entrant, and can safely be installed for
  * INCLUDE, FORWARD, and ERROR dispatch methods.
- *
+ * <p>
  * A concrete example of re-entrant use is login/jsp/login.jsp used when authentication fails at portal login.
- *
+ * <p>
  * By default {@link HttpServletRequest#getLocale()} and {@link HttpServletRequest#getLocales()} reflect
  * browser language preference. When using this filter these two calls employ the same Locale determination algorithm
- * as LocalizationLifecycle does.
- *
+ * as {@link LocalizationLifecycle} does.
+ * <p>
  * This filter can be activated / deactivated via portal module's web.xml
- *
+ * <p>
+ * If default portal language is other than English, it can be configured for the filter by using PortalLocale init param:
+ * <p>
+ * <pre>&lt;filter&gt; 
+ *   &lt;filter-name&gt;LocalizationFilter&lt;/filter-name&gt;
+ *   &lt;filter-class&gt;org.exoplatform.portal.application.localization.LocalizationFilter&lt;/filter-class&gt;
+ *   &lt;init-param&gt;
+ *     &lt;param-name>PortalLocale&lt;/param-name&gt;
+ *     &lt;param-value>fr_FR&lt;/param-value&gt;
+ *   &lt;/init-param&gt;
+ * &lt;/filter&gt;
+ * </pre>
+ * 
  * @author <a href="mailto:mstrukel at redhat.com">Marko Strukelj</a>
  */
 public class LocalizationFilter implements Filter
@@ -73,8 +85,14 @@
 
    private static ThreadLocal<Locale> currentLocale = new ThreadLocal<Locale>();
 
+   private Locale portalLocale = Locale.ENGLISH;
+
    public void init(FilterConfig filterConfig) throws ServletException
    {
+      String locale = filterConfig.getInitParameter("PortalLocale");
+      locale = locale != null ? locale.trim() : null;
+      if (locale != null && locale.length() > 0)
+         portalLocale = LocaleContextInfo.getLocale(locale);
    }
 
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
@@ -141,7 +159,7 @@
          localeCtx.setUserProfileLocale(getUserProfileLocale(container, req.getRemoteUser()));
          localeCtx.setRemoteUser(req.getRemoteUser());
 
-         localeCtx.setPortalLocale(Locale.ENGLISH);
+         localeCtx.setPortalLocale(checkPortalLocaleSupported(portalLocale, supportedLocales));
          Locale locale = localePolicy.determineLocale(localeCtx);
          boolean supported = supportedLocales.contains(locale);
 
@@ -170,6 +188,27 @@
       }
    }
 
+   private Locale checkPortalLocaleSupported(Locale portalLocale, Set<Locale> supportedLocales)
+   {
+      if (supportedLocales.contains(portalLocale))
+         return portalLocale;
+      if ("".equals(portalLocale.getCountry()) == false)
+      {
+         Locale loc = new Locale(portalLocale.getLanguage());
+         if (supportedLocales.contains(loc))
+         {
+            log.warn("portalLocale not supported: " + LocaleContextInfo.getLocaleAsString(portalLocale)
+                  + ". Falling back to '" + portalLocale.getLanguage()+ "'.");
+            this.portalLocale = loc;
+            return loc;
+         }
+      }
+
+      log.warn("portalLocale not supported: " + LocaleContextInfo.getLocaleAsString(portalLocale) + ". Falling back to Locale.ENGLISH.");
+      this.portalLocale = Locale.ENGLISH;
+      return portalLocale;
+   }
+
    private Locale getUserProfileLocale(ExoContainer container, String user)
    {
       UserProfile userProfile = null;

Modified: portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/application/UIPortletActionListener.java
===================================================================
--- portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/application/UIPortletActionListener.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/application/UIPortletActionListener.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -854,8 +854,7 @@
    {
       public void execute(Event<UIPortlet> event) throws Exception
       {
-         UIPortal uiPortal = Util.getUIPortal();
-         UIPortalApplication uiApp = uiPortal.getAncestorOfType(UIPortalApplication.class);
+         UIPortalApplication uiApp = Util.getUIPortalApplication();
          UIMaskWorkspace uiMaskWS = uiApp.getChildById(UIPortalApplication.UI_MASK_WS_ID);
          uiMaskWS.setUpdated(true);
          UIPortlet uiPortlet = event.getSource();

Modified: portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/container/UIContainerActionListener.java
===================================================================
--- portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/container/UIContainerActionListener.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/container/UIContainerActionListener.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -39,8 +39,7 @@
       {
 
          UIContainer uiContainer = event.getSource();
-         UIPortal uiPortal = Util.getUIPortal();
-         UIPortalApplication uiApp = uiPortal.getAncestorOfType(UIPortalApplication.class);
+         UIPortalApplication uiApp = Util.getUIPortalApplication();
          UIMaskWorkspace uiMaskWS = uiApp.getChildById(UIPortalApplication.UI_MASK_WS_ID);
          UIContainerForm containerForm = uiMaskWS.createUIComponent(UIContainerForm.class, null, null);
          containerForm.setValues(uiContainer);

Modified: portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/container/UIContainerForm.java
===================================================================
--- portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/container/UIContainerForm.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/container/UIContainerForm.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -141,7 +141,7 @@
 
          event.getRequestContext().addUIComponentToUpdateByAjax(uiMaskWorkspace);
 
-         UIPortalApplication uiPortalApp = uiForm.getAncestorOfType(UIPortalApplication.class);
+         UIPortalApplication uiPortalApp = Util.getUIPortalApplication();
          UIWorkingWorkspace uiWorkingWS = uiPortalApp.getChildById(UIPortalApplication.UI_WORKING_WS_ID);
          pcontext.getJavascriptManager().addJavascript("eXo.portal.UIPortal.changeComposerSaveButton();");
          pcontext.addUIComponentToUpdateByAjax(uiWorkingWS);

Modified: portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/javascript/JavascriptServlet.java
===================================================================
--- portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/javascript/JavascriptServlet.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/javascript/JavascriptServlet.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -19,10 +19,14 @@
 
 package org.exoplatform.portal.webui.javascript;
 
+import org.exoplatform.commons.utils.PropertyManager;
 import org.exoplatform.container.ExoContainerContext;
+import org.exoplatform.portal.application.ResourceRequestFilter;
 import org.exoplatform.web.application.javascript.JavascriptConfigService;
 
 import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Date;
 
 import javax.servlet.ServletConfig;
 import javax.servlet.ServletException;
@@ -55,14 +59,23 @@
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException,
       IOException
    {
-      JavascriptConfigService service =
+      final JavascriptConfigService service =
          (JavascriptConfigService)ExoContainerContext.getCurrentContainer().getComponentInstanceOfType(
             JavascriptConfigService.class);
-
+      long lastModified = service.getLastModified();
+      long ifModifiedSince = request.getDateHeader(ResourceRequestFilter.IF_MODIFIED_SINCE);
+      
       // Julien: should we also set charset along with the content type ?
       response.setContentType("application/x-javascript");
-      ServletOutputStream stream = response.getOutputStream();
-      service.writeMergedJavascript(stream);
+      if (!PropertyManager.isDevelopping()) {
+         if (ifModifiedSince >= lastModified) {
+            response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
+            return;
+         }
+      }
+      
+      byte[] jsBytes = service.getMergedJavascript();
+      response.setDateHeader(ResourceRequestFilter.LAST_MODIFIED, lastModified);
+      response.getOutputStream().write(jsBytes);      
    }
-
 }

Modified: portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/navigation/PageNavigationUtils.java
===================================================================
--- portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/navigation/PageNavigationUtils.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/navigation/PageNavigationUtils.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -367,6 +367,12 @@
       }
 
       PageNode cloneStartNode = startNode.clone();
+
+      // Check if page reference isn't existing, page reference value of node is setted null too.
+      if (pageReference != null && userService.getPage(pageReference) == null)
+      {
+         cloneStartNode.setPageReference(null);         
+      }
       ArrayList<PageNode> filteredChildren = new ArrayList<PageNode>();
 
       List<PageNode> children = startNode.getChildren();

Modified: portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/navigation/UINavigationNodeSelector.java
===================================================================
--- portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/navigation/UINavigationNodeSelector.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/navigation/UINavigationNodeSelector.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -26,7 +26,6 @@
 import org.exoplatform.portal.config.model.PageNode;
 import org.exoplatform.portal.config.model.PortalConfig;
 import org.exoplatform.portal.mop.Visibility;
-import org.exoplatform.portal.webui.navigation.ParentChildPair;
 import org.exoplatform.portal.webui.page.UIPage;
 import org.exoplatform.portal.webui.page.UIPageNodeForm;
 import org.exoplatform.portal.webui.portal.UIPortalComposer;
@@ -447,7 +446,6 @@
             uiToolPanel.setWorkingComponent(UIPage.class, null);
             UIPage uiPage = (UIPage)uiToolPanel.getUIComponent();
 
-            WebuiRequestContext context = WebuiRequestContext.getCurrentInstance();
             if(selectPage.getTitle() == null)
                selectPage.setTitle(selectedPageNode.getLabel());
 
@@ -535,46 +533,48 @@
    {
       public void execute(Event<UIRightClickPopupMenu> event) throws Exception
       {
-    	  String uri = event.getRequestContext().getRequestParameter(UIComponent.OBJECTID);
-    	  WebuiRequestContext pcontext = event.getRequestContext();
-          UIApplication uiApp = pcontext.getUIApplication();
-          UINavigationNodeSelector uiNodeSelector = event.getSource().getAncestorOfType(UINavigationNodeSelector.class);
-          UINavigationManagement uiManagement = uiNodeSelector.getParent();
-          Class<?>[] childrenToRender = new Class<?>[]{UINavigationNodeSelector.class};
-          uiManagement.setRenderedChildrenOfTypes(childrenToRender);
-          event.getRequestContext().addUIComponentToUpdateByAjax(uiManagement);
+         String uri = event.getRequestContext().getRequestParameter(UIComponent.OBJECTID);
+         WebuiRequestContext pcontext = event.getRequestContext();
+         UIApplication uiApp = pcontext.getUIApplication();
+         UINavigationNodeSelector uiNodeSelector = event.getSource().getAncestorOfType(UINavigationNodeSelector.class);
+         UINavigationManagement uiManagement = uiNodeSelector.getParent();
+         Class<?>[] childrenToRender = new Class<?>[]{UINavigationNodeSelector.class};
+         uiManagement.setRenderedChildrenOfTypes(childrenToRender);
+         event.getRequestContext().addUIComponentToUpdateByAjax(uiManagement);
 
-          PageNavigation nav = uiNodeSelector.getEdittedNavigation();
-          if (nav == null)
-          {
-             return;
-          }
-          
-          PageNode[] pageNodes = PageNavigationUtils.searchPageNodesByUri(nav, uri);
-          if (pageNodes == null)
-          {
-             return;
-          }
-          
-          for (PageNode pageNode : pageNodes) {
-  			 if(pageNode != null && pageNode.isSystem()) {
-  				 uiApp.addMessage(new ApplicationMessage("UINavigationNodeSelector.msg.systemnode-move", null));
-  				 return;
-  			 }
-          }
-          
-          TreeNodeData selectedNode = new TreeNodeData(nav, pageNodes[0], pageNodes[1]);
-          selectedNode.setDeleteNode(false);
-          uiNodeSelector.setCopyNode(selectedNode);
-          event.getSource().setActions(
-             new String[]{"AddNode", "EditPageNode", "EditSelectedNode", "CopyNode", "CloneNode", "CutNode",
-                "PasteNode", "DeleteNode", "MoveUp", "MoveDown"});         
+         PageNavigation nav = uiNodeSelector.getEdittedNavigation();
+         if (nav == null)
+         {
+            return;
+         }
 
-          if (uiNodeSelector.getCopyNode() == null)
-          {
-             return;
-          }
-          uiNodeSelector.getCopyNode().setDeleteNode(true);
+         ParentChildPair parentChildPair = PageNavigationUtils.searchParentChildPairByUri(nav, uri);
+         if (parentChildPair == null)
+         {
+            return;
+         }
+
+         PageNode parentNode = parentChildPair.getParentNode();
+         PageNode childNode = parentChildPair.getChildNode();
+
+         if (childNode != null && childNode.isSystem())
+         {
+            uiApp.addMessage(new ApplicationMessage("UINavigationNodeSelector.msg.systemnode-move", null));
+            return;
+         }
+
+         TreeNodeData selectedNode = new TreeNodeData(nav, parentNode, childNode);
+         selectedNode.setDeleteNode(false);
+         uiNodeSelector.setCopyNode(selectedNode);
+         event.getSource().setActions(
+            new String[]{"AddNode", "EditPageNode", "EditSelectedNode", "CopyNode", "CloneNode", "CutNode",
+               "PasteNode", "DeleteNode", "MoveUp", "MoveDown"});
+
+         if (uiNodeSelector.getCopyNode() == null)
+         {
+            return;
+         }
+         uiNodeSelector.getCopyNode().setDeleteNode(true);
       }
    }
 

Modified: portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/navigation/UIPortalNavigation.java
===================================================================
--- portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/navigation/UIPortalNavigation.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/navigation/UIPortalNavigation.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -113,7 +113,7 @@
 
       if (context.getRemoteUser() != null)
       {
-         result.add(PageNavigationUtils.filter(getSelectedNavigation(), context.getRemoteUser()));
+         result.add(PageNavigationUtils.filterNavigation(getSelectedNavigation(), context.getRemoteUser(), false, true));
       }
       else
       {
@@ -121,7 +121,7 @@
          {
             if (!showUserNavigation && nav.getOwnerType().equals("user"))
                continue;
-            result.add(PageNavigationUtils.filter(nav, null));
+            result.add(PageNavigationUtils.filterNavigation(nav, null, false, true));
          }
       }
       return result;

Modified: portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/page/UIPageActionListener.java
===================================================================
--- portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/page/UIPageActionListener.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/page/UIPageActionListener.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -59,7 +59,7 @@
       public void execute(Event<UIPortal> event) throws Exception
       {
          UIPortal showedUIPortal = event.getSource();
-         UIPortalApplication uiPortalApp = showedUIPortal.getAncestorOfType(UIPortalApplication.class);
+         UIPortalApplication uiPortalApp = Util.getUIPortalApplication();
          
          //This code snippet is to make sure that Javascript/Skin is fully loaded at the first request
          UIWorkingWorkspace uiWorkingWS = uiPortalApp.getChildById(UIPortalApplication.UI_WORKING_WS_ID);

Modified: portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/page/UIPageBrowser.java
===================================================================
--- portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/page/UIPageBrowser.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/page/UIPageBrowser.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -309,6 +309,12 @@
          if(page.getOwnerType().equals(PortalConfig.USER_TYPE)){
             removePageNode(page, event);
          }
+
+         UIWorkingWorkspace uiWorkingWorkspace = uiPortalApp.getChild(UIWorkingWorkspace.class);
+         uiWorkingWorkspace.updatePortletsByName("UserToolbarSitePortlet");
+         uiWorkingWorkspace.updatePortletsByName("UserToolbarGroupPortlet");
+         uiWorkingWorkspace.updatePortletsByName("UserToolbarDashboardPortlet");
+         uiWorkingWorkspace.updatePortletsByName("NavigationPortlet");
       }
       
       /**

Modified: portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/page/UIPageForm.java
===================================================================
--- portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/page/UIPageForm.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/page/UIPageForm.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -125,12 +125,12 @@
       addUIFormInput(uiSettingSet);
       setSelectedTab(uiSettingSet.getId());
 
-      WebuiRequestContext context = WebuiRequestContext.getCurrentInstance();
-      Param param = initParams.getParam("PageTemplate");
-      List<SelectItemCategory> itemCategories = (List<SelectItemCategory>)param.getMapGroovyObject(context);
-      UIFormInputItemSelector uiTemplate = new UIFormInputItemSelector("Template", "template");
-      uiTemplate.setItemCategories(itemCategories);
-      addUIFormInput(uiTemplate);
+      //WebuiRequestContext context = WebuiRequestContext.getCurrentInstance();
+      //Param param = initParams.getParam("PageTemplate");
+      //List<SelectItemCategory> itemCategories = (List<SelectItemCategory>)param.getMapGroovyObject(context);
+      //UIFormInputItemSelector uiTemplate = new UIFormInputItemSelector("Template", "template");
+      //uiTemplate.setItemCategories(itemCategories);
+      //addUIFormInput(uiTemplate);
   
       uiPermissionSetting = createUIComponent(UIFormInputSet.class, "PermissionSetting", null);
       UIListPermissionSelector uiListPermissionSelector = createUIComponent(UIListPermissionSelector.class, null, null);

Modified: portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/workspace/UIMaskWorkspace.java
===================================================================
--- portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/workspace/UIMaskWorkspace.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/workspace/UIMaskWorkspace.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -93,10 +93,11 @@
       return createUIComponent(clazz, null, null);
    }
 
-   public void setUIComponent(UIComponent uicomponent)
+   public UIComponent setUIComponent(UIComponent uicomponent)
    {
-      super.setUIComponent(uicomponent);
+      UIComponent oldOne = super.setUIComponent(uicomponent);
       setShow(uicomponent != null);
+      return oldOne;
    }
 
    static public class CloseActionListener extends EventListener<UIComponent>

Modified: portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/workspace/UIPortalApplicationLifecycle.java
===================================================================
--- portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/workspace/UIPortalApplicationLifecycle.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/webui/portal/src/main/java/org/exoplatform/portal/webui/workspace/UIPortalApplicationLifecycle.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -44,7 +44,12 @@
          return;
       UIComponent uiTarget = uicomponent.findComponentById(componentId);
       if (uiTarget == null)
+      {
+         context.addUIComponentToUpdateByAjax(uicomponent.<UIComponent>getChildById(UIPortalApplication.UI_WORKING_WS_ID));
+         context.addUIComponentToUpdateByAjax(uicomponent.getChild(UIMaskWorkspace.class));
+         ((PortalRequestContext)context).setFullRender(true);
          return;
+      }
       if (uiTarget == uicomponent)
          super.processDecode(uicomponent, context);
       uiTarget.processDecode(context);

Modified: portal/branches/wci/webui/portlet/src/main/java/org/exoplatform/webui/application/portlet/PortletApplicationController.java
===================================================================
--- portal/branches/wci/webui/portlet/src/main/java/org/exoplatform/webui/application/portlet/PortletApplicationController.java	2010-11-29 15:35:58 UTC (rev 5355)
+++ portal/branches/wci/webui/portlet/src/main/java/org/exoplatform/webui/application/portlet/PortletApplicationController.java	2010-11-29 16:47:37 UTC (rev 5356)
@@ -133,7 +133,7 @@
       {
          application = new PortletApplication(getPortletConfig());
          application.onInit();
-         controller.addApplication(application);
+         application = controller.addApplication(application);
       }
       return application;
    }



More information about the gatein-commits mailing list