You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jetspeed-dev@portals.apache.org by ta...@apache.org on 2011/02/25 08:45:04 UTC

svn commit: r1074422 - in /portals/jetspeed-2/portal/trunk: ./ components/jetspeed-portal/src/main/java/org/apache/jetspeed/tools/pamanager/ components/jetspeed-portal/src/test/java/org/apache/jetspeed/ components/jetspeed-rdbms/src/main/java/org/apach...

Author: taylor
Date: Fri Feb 25 07:45:03 2011
New Revision: 1074422

URL: http://svn.apache.org/viewvc?rev=1074422&view=rev
Log:
https://issues.apache.org/jira/browse/JS2-1232
Portlet Instances feature implemented with tests. Note I had to rename this feature Portlet Clones since the concept of Portlet Instances is used (albeit at a low level) all over the codebase. This commit is considered Phase 1 of 2, and includes the core implementation, as well as basic integration into j2-admin PAM, and the Jetspeed Toolbox search. Phase II will encompass improving the PAM and Toolbox to further support administration of clones. This commit introduces an new column CLONE_PARENT to the PORTLET_DEFINITION table. Schema change requirements will be documented in release notes and migration docs.


Added:
    portals/jetspeed-2/portal/trunk/components/jetspeed-rdbms/src/main/java/org/apache/jetspeed/util/ojb/PortletCloneQueryCustomizer.java   (with props)
Modified:
    portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/tools/pamanager/PortletApplicationManager.java
    portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/AbstractRequestContextTestCase.java
    portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/JETSPEED-INF/ojb/registry_repository.xml
    portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletregistry/PersistenceBrokerPortletRegistry.java
    portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletregistry/PortletRegistryHelper.java
    portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletregistry/RegistryPortletCache.java
    portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/om/portlet/impl/PortletApplicationDefinitionImpl.java
    portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/om/portlet/impl/PortletDefinitionImpl.java
    portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/serializer/JetspeedRegistrySerializer.java
    portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/test/java/org/apache/jetspeed/components/portletregistry/TestPortletRegistryDAO.java
    portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/test/resources/registry-test.xml
    portals/jetspeed-2/portal/trunk/etc/registration/assembly/registry.xml
    portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/components/portletregistry/PortletRegistry.java
    portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/om/portlet/PortletApplication.java
    portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/om/portlet/PortletDefinition.java
    portals/jetspeed-2/portal/trunk/jetspeed-archetype/src/main/resources/archetype-resources/pom.xml
    portals/jetspeed-2/portal/trunk/jetspeed-portal-resources/src/main/ddl-schema/registry-schema.xml
    portals/jetspeed-2/portal/trunk/jetspeed-portal-resources/src/main/resources/assembly/registry.xml
    portals/jetspeed-2/portal/trunk/pom.xml

Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/tools/pamanager/PortletApplicationManager.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/tools/pamanager/PortletApplicationManager.java?rev=1074422&r1=1074421&r2=1074422&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/tools/pamanager/PortletApplicationManager.java (original)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/tools/pamanager/PortletApplicationManager.java Fri Feb 25 07:45:03 2011
@@ -750,11 +750,12 @@ public class PortletApplicationManager i
         if (searchEngine != null)
         {
             List<PortletDefinition> portletDefList = pa.getPortlets();
-            List<Object> list = new ArrayList<Object>(portletDefList.size() + 1);
-            
+            List<PortletDefinition> cloneDefList = pa.getClones();
+            List<Object> list = new ArrayList<Object>(portletDefList.size() + cloneDefList.size() + 1);
             if (remove)
             {
                 list.addAll(portletDefList);
+                list.addAll(cloneDefList);
                 list.add(pa);
                 searchEngine.remove(list);
                 log.info("Un-Registered the portlet application in the search engine... " + pa.getName());
@@ -763,6 +764,7 @@ public class PortletApplicationManager i
             {
                 list.add(pa);
                 list.addAll(portletDefList);
+                list.addAll(cloneDefList);
                 searchEngine.add(list);
                 log.info("Registered the portlet application in the search engine... " + pa.getName());
             }

Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/AbstractRequestContextTestCase.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/AbstractRequestContextTestCase.java?rev=1074422&r1=1074421&r2=1074422&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/AbstractRequestContextTestCase.java (original)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/AbstractRequestContextTestCase.java Fri Feb 25 07:45:03 2011
@@ -42,6 +42,7 @@ public class AbstractRequestContextTestC
         confList.add("jetspeed-properties.xml");
         confList.add("page-manager.xml");
         confList.add("registry.xml");
+        confList.add("search.xml");
         confList.add("JETSPEED-INF/spring/RequestDispatcherService.xml");        
         confList.add("rc2.xml");
         confList.add("static-bean-references.xml");
@@ -51,7 +52,7 @@ public class AbstractRequestContextTestC
         confList.add("security-atn.xml");
         confList.add("security-spi-atn.xml");
         confList.add("security-atz.xml");
-        confList.add("JETSPEED-INF/spring/JetspeedPrincipalManagerProviderOverride.xml");        
+        confList.add("JETSPEED-INF/spring/JetspeedPrincipalManagerProviderOverride.xml");
         return confList.toArray(new String[confList.size()]);
     }
 

Added: portals/jetspeed-2/portal/trunk/components/jetspeed-rdbms/src/main/java/org/apache/jetspeed/util/ojb/PortletCloneQueryCustomizer.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-rdbms/src/main/java/org/apache/jetspeed/util/ojb/PortletCloneQueryCustomizer.java?rev=1074422&view=auto
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-rdbms/src/main/java/org/apache/jetspeed/util/ojb/PortletCloneQueryCustomizer.java (added)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-rdbms/src/main/java/org/apache/jetspeed/util/ojb/PortletCloneQueryCustomizer.java Fri Feb 25 07:45:03 2011
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jetspeed.util.ojb;
+
+import org.apache.ojb.broker.PersistenceBroker;
+import org.apache.ojb.broker.accesslayer.QueryCustomizerDefaultImpl;
+import org.apache.ojb.broker.metadata.CollectionDescriptor;
+import org.apache.ojb.broker.query.Query;
+import org.apache.ojb.broker.query.QueryByCriteria;
+
+public class PortletCloneQueryCustomizer extends QueryCustomizerDefaultImpl {
+
+    private static final long serialVersionUID = -1933868940330442307L;
+    private static final String CLONE_FIELD = "isClone";
+
+    public Query customizeQuery(Object owner, PersistenceBroker broker, CollectionDescriptor collDescriptor, QueryByCriteria query)
+    {
+        String isClone = this.getAttribute(CLONE_FIELD, "false");
+        if (isClone.equals("false"))
+        {
+            query.getCriteria().addIsNull("cloneParent");
+        }
+        else
+        {
+            query.getCriteria().addNotNull("cloneParent");
+        }
+        return query;
+    }
+}

Propchange: portals/jetspeed-2/portal/trunk/components/jetspeed-rdbms/src/main/java/org/apache/jetspeed/util/ojb/PortletCloneQueryCustomizer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: portals/jetspeed-2/portal/trunk/components/jetspeed-rdbms/src/main/java/org/apache/jetspeed/util/ojb/PortletCloneQueryCustomizer.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/JETSPEED-INF/ojb/registry_repository.xml
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/JETSPEED-INF/ojb/registry_repository.xml?rev=1074422&r1=1074421&r2=1074422&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/JETSPEED-INF/ojb/registry_repository.xml (original)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/JETSPEED-INF/ojb/registry_repository.xml Fri Feb 25 07:45:03 2011
@@ -191,6 +191,12 @@
 
       >
          <inverse-foreignkey field-ref="appId"/>
+         <query-customizer class="org.apache.jetspeed.util.ojb.PortletCloneQueryCustomizer">
+            <attribute
+              attribute-name="isClone"
+              attribute-value="false"
+            />
+         </query-customizer>
       </collection-descriptor>
 
       <collection-descriptor
@@ -366,6 +372,23 @@
          <inverse-foreignkey field-ref="applicationId"/>
       </collection-descriptor>
 
+      <collection-descriptor
+         name="clones"
+         element-class-ref="org.apache.jetspeed.om.portlet.impl.PortletDefinitionImpl"
+         auto-delete="false"
+         auto-update = "true"
+         auto-retrieve = "true"
+
+      >
+         <inverse-foreignkey field-ref="appId"/>
+         <query-customizer class="org.apache.jetspeed.util.ojb.PortletCloneQueryCustomizer">
+            <attribute
+              attribute-name="isClone"
+              attribute-value="true"
+            />
+         </query-customizer>
+      </collection-descriptor>
+
    </class-descriptor>
 
 <!--
@@ -417,7 +440,12 @@
          column="CACHE_SCOPE"
          jdbc-type="VARCHAR"
       />
-
+      <field-descriptor
+          name="cloneParent"
+          column="CLONE_PARENT"
+          jdbc-type="VARCHAR"
+          nullable="true"
+      />
       <field-descriptor
          name="resourceBundle"
          column="RESOURCE_BUNDLE"

Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletregistry/PersistenceBrokerPortletRegistry.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletregistry/PersistenceBrokerPortletRegistry.java?rev=1074422&r1=1074421&r2=1074422&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletregistry/PersistenceBrokerPortletRegistry.java (original)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletregistry/PersistenceBrokerPortletRegistry.java Fri Feb 25 07:45:03 2011
@@ -42,6 +42,7 @@ import org.apache.jetspeed.om.portlet.Se
 import org.apache.jetspeed.om.portlet.Supports;
 import org.apache.jetspeed.om.portlet.impl.PortletApplicationDefinitionImpl;
 import org.apache.jetspeed.om.portlet.impl.PortletDefinitionImpl;
+import org.apache.jetspeed.search.SearchEngine;
 import org.apache.jetspeed.util.JetspeedLocale;
 import org.apache.ojb.broker.query.Criteria;
 import org.apache.ojb.broker.query.QueryFactory;
@@ -67,27 +68,35 @@ public class PersistenceBrokerPortletReg
      * The separator used to create a unique portlet name as
      * {portletApplication}::{portlet}
      */
-    static final String PORTLET_UNIQUE_NAME_SEPARATOR = "::";
+    static public final String PORTLET_UNIQUE_NAME_SEPARATOR = "::";
 
-    private JetspeedCache applicationOidCache = null;
-    private JetspeedCache portletOidCache = null;
-    private JetspeedCache applicationNameCache = null;
-    private JetspeedCache portletNameCache = null;
-    private List<RegistryEventListener> listeners = new ArrayList<RegistryEventListener>();
-    private PortletPreferencesProvider preferenceService;
+    protected JetspeedCache applicationOidCache = null;
+    protected JetspeedCache portletOidCache = null;
+    protected JetspeedCache applicationNameCache = null;
+    protected JetspeedCache portletNameCache = null;
+    protected List<RegistryEventListener> listeners = new ArrayList<RegistryEventListener>();
+    protected PortletPreferencesProvider preferenceService;
+    protected SearchEngine searchEngine;
     
     // for testing purposes only: no need for the portletFactory then
     public PersistenceBrokerPortletRegistry(String repositoryPath, PortletPreferencesProvider preferenceService)
     {
-        this(repositoryPath, null, null, null, null, preferenceService);
+        this(repositoryPath, null, null, null, null, preferenceService, null);
+    }
+
+    public PersistenceBrokerPortletRegistry(String repositoryPath,
+            JetspeedCache applicationOidCache, JetspeedCache portletOidCache,
+            JetspeedCache applicationNameCache, JetspeedCache portletNameCache,
+            PortletPreferencesProvider preferenceService)
+    {
+        this(repositoryPath, applicationOidCache, portletOidCache, applicationNameCache, portletNameCache, preferenceService, null);
     }
     
-    /**
-     *  
-     */
     public PersistenceBrokerPortletRegistry(String repositoryPath,
             JetspeedCache applicationOidCache, JetspeedCache portletOidCache, 
-            JetspeedCache applicationNameCache, JetspeedCache portletNameCache, PortletPreferencesProvider preferenceService)
+            JetspeedCache applicationNameCache, JetspeedCache portletNameCache, 
+            PortletPreferencesProvider preferenceService,
+            SearchEngine search)
     {
         super(repositoryPath);
         this.applicationOidCache = applicationOidCache;
@@ -100,12 +109,35 @@ public class PersistenceBrokerPortletReg
         this.applicationNameCache.addEventListener(this, false);
         this.portletNameCache.addEventListener(this, false);        
         this.preferenceService = preferenceService;
+        this.searchEngine = search;
     }
     
     @SuppressWarnings("unchecked")
     public Collection<PortletDefinition> getAllPortletDefinitions()
     {
         Criteria c = new Criteria();
+        c.addIsNull("cloneParent");
+        Collection<PortletDefinition> list = getPersistenceBrokerTemplate().getCollectionByQuery(
+                QueryFactory.newQuery(PortletDefinitionImpl.class, c));
+        postLoadColl(list);
+        return list;
+    }
+
+    @SuppressWarnings("unchecked")
+    public Collection<PortletDefinition> getAllDefinitions()
+    {
+        Criteria c = new Criteria();
+        Collection<PortletDefinition> list = getPersistenceBrokerTemplate().getCollectionByQuery(
+                QueryFactory.newQuery(PortletDefinitionImpl.class, c));
+        postLoadColl(list);
+        return list;
+    }
+
+    @SuppressWarnings("unchecked")
+    public Collection<PortletDefinition> getAllCloneDefinitions()
+    {
+        Criteria c = new Criteria();
+        c.addNotNull("cloneParent");
         Collection<PortletDefinition> list = getPersistenceBrokerTemplate().getCollectionByQuery(
                 QueryFactory.newQuery(PortletDefinitionImpl.class, c));
         postLoadColl(list);
@@ -200,6 +232,7 @@ public class PersistenceBrokerPortletReg
     {
         getPersistenceBrokerTemplate().store(newApp);
         this.preferenceService.storeDefaults(newApp);
+        this.restoreClones(newApp);
     }
 
     public void removeApplication(PortletApplication app) throws RegistryException
@@ -350,36 +383,36 @@ public class PersistenceBrokerPortletReg
         this.listeners.remove(listener);
     }
  
-    public void clonePortletDefinition(PortletDefinition source, String newPortletName) throws FailedToStorePortletDefinitionException
+    public PortletDefinition clonePortletDefinition(PortletDefinition source, String newPortletName) throws FailedToStorePortletDefinitionException
     {
         if (this.portletDefinitionExists(newPortletName, source.getApplication()))
         {
-            throw new FailedToStorePortletDefinitionException("Cannot clone to portlet named " + newPortletName + ", name already exists"); 
+            throw new FailedToStorePortletDefinitionException("Cannot clone to portlet named " + newPortletName + ", name already exists");
         }
-
         // create new portlet in source portlet application
-        PortletDefinition copy = source.getApplication().addPortlet(newPortletName);
-        
+        PortletDefinition copy = source.getApplication().addClone(newPortletName);
+        PortletApplication destApp = source.getApplication();
+
         // First set display name
-        
+
         DisplayName displayName = copy.addDisplayName(JetspeedLocale.getDefaultLocale().getLanguage());
         displayName.setDisplayName(newPortletName);
-        
+
         // And, then, copy all attributes
-        
+
         copy.setPortletClass(source.getPortletClass());
         copy.setResourceBundle(source.getResourceBundle());
         copy.setPreferenceValidatorClassname(source.getPreferenceValidatorClassname());
         copy.setExpirationCache(source.getExpirationCache());
         copy.setCacheScope(source.getCacheScope());
-        
+
         for (LocalizedField field : source.getMetadata().getFields())
         {
             copy.getMetadata().addField(field.getLocale(), field.getName(), field.getValue());
         }
-        
+
         copy.setJetspeedSecurityConstraint(source.getJetspeedSecurityConstraint());
-        
+
         for (Description desc : source.getDescriptions())
         {
             Description copyDesc = copy.addDescription(desc.getLang());
@@ -390,14 +423,16 @@ public class PersistenceBrokerPortletReg
         {
             InitParam copyInitParam = copy.addInitParam(initParam.getParamName());
             copyInitParam.setParamValue(initParam.getParamValue());
-            
+
             for (Description desc : initParam.getDescriptions())
             {
                 Description copyDesc = copyInitParam.addDescription(desc.getLang());
                 copyDesc.setDescription(desc.getDescription());
             }
         }
-        
+        InitParam parentPortlet = copy.addInitParam(PortletDefinition.CLONE_PARENT_INIT_PARAM);
+        parentPortlet.setParamValue(source.getPortletName());
+
         for (EventDefinitionReference eventDefRef : source.getSupportedProcessingEvents())
         {
             copy.addSupportedProcessingEvent(eventDefRef.getQName());
@@ -407,34 +442,34 @@ public class PersistenceBrokerPortletReg
         {
             copy.addSupportedPublishingEvent(eventDefRef.getQName());
         }
-        
+
         for (SecurityRoleRef secRoleRef : source.getSecurityRoleRefs())
         {
             SecurityRoleRef copySecRoleRef = copy.addSecurityRoleRef(secRoleRef.getRoleName());
             copySecRoleRef.setRoleLink(secRoleRef.getRoleLink());
-            
+
             for (Description desc : secRoleRef.getDescriptions())
             {
                 Description copyDesc = copySecRoleRef.addDescription(desc.getLang());
                 copyDesc.setDescription(desc.getDescription());
             }
         }
-        
+
         for (Supports supports : source.getSupports())
         {
             Supports copySupports = copy.addSupports(supports.getMimeType());
-            
+
             for (String portletMode : supports.getPortletModes())
             {
                 copySupports.addPortletMode(portletMode);
             }
-            
+
             for (String windowState : supports.getWindowStates())
             {
                 copySupports.addWindowState(windowState);
             }
         }
-        
+
         for (Language language : source.getLanguages())
         {
             Language copyLanguage = copy.addLanguage(language.getLocale());
@@ -443,23 +478,23 @@ public class PersistenceBrokerPortletReg
             copyLanguage.setKeywords(language.getKeywords());
             copyLanguage.setSupportedLocale(language.isSupportedLocale());
         }
-        
+
         for (ContainerRuntimeOption runtimeOption : source.getContainerRuntimeOptions())
         {
             ContainerRuntimeOption copyRuntimeOption = copy.addContainerRuntimeOption(runtimeOption.getName());
-            
+
             for (String value : runtimeOption.getValues())
             {
                 copyRuntimeOption.addValue(value);
             }
         }
-        
+
         copy.getSupportedPublicRenderParameters().addAll(source.getSupportedPublicRenderParameters());
-        
+
         //savePortletDefinition(copy);
         try
         {
-            updatePortletApplication(source.getApplication());
+            updatePortletApplication(destApp);
         }
         catch (RegistryException e)
         {
@@ -469,11 +504,11 @@ public class PersistenceBrokerPortletReg
         {
             Preference copyPref = copy.addDescriptorPreference(pref.getName());
             copyPref.setReadOnly(pref.isReadOnly());
-            
+
             for (String value : pref.getValues())
             {
                 copyPref.addValue(value);
-            }            
+            }
         }
         try
         {
@@ -481,8 +516,60 @@ public class PersistenceBrokerPortletReg
         }
         catch (Throwable e)
         {
-            source.getApplication().getPortlets().remove(copy);
-            throw new FailedToStorePortletDefinitionException(e);            
+            destApp.getClones().remove(copy);
+            throw new FailedToStorePortletDefinitionException(e);
+        }
+        PortletDefinition pd = getPortletDefinitionByUniqueName(PortletRegistryHelper.makeUniqueName(source.getApplication().getName(), newPortletName));
+        PortletApplication pa = pd.getApplication();
+        // reindex
+        if (searchEngine != null)
+        {
+            searchEngine.remove(pa);
+            searchEngine.remove(pa.getPortlets());
+            searchEngine.remove(pa.getClones());
+            searchEngine.add(pa);
+            searchEngine.add(pa.getPortlets());
+            searchEngine.add(pa.getClones());
+        }
+        return pd;
+    }
+
+    public int restoreClones(PortletApplication pa)
+            throws RegistryException
+    {
+        int count = 0;
+        Criteria criteria = new Criteria();
+        criteria.addEqualTo("cloneParent", pa.getName());
+        Collection<PortletDefinitionImpl> clones = getPersistenceBrokerTemplate().getCollectionByQuery(
+                QueryFactory.newQuery(PortletDefinitionImpl.class, criteria));
+        for (PortletDefinitionImpl pd : clones)
+        {
+            if (pd.isClone())
+            {
+                if (pa.getName().equals(pd.getCloneParent()))
+                {
+                    // Restore Clone
+                    pd.setApplication(pa);
+                    pa.getClones().add(pd);
+                    count++;
+                }
+            }
+        }
+        if (count > 0)
+        {
+            updatePortletApplication(pa);
         }
-    }       
+        return count;
+    }
+
+    public void removeAllClones(PortletApplication pa)
+            throws RegistryException
+    {
+        Criteria c = new Criteria();
+        c.addEqualTo("cloneParent", pa.getName());
+        getPersistenceBrokerTemplate().deleteByQuery(QueryFactory.newQuery(PortletDefinitionImpl.class, c));
+        pa.getClones().clear();
+        this.updatePortletApplication(pa);
+    }
+
 }
\ No newline at end of file

Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletregistry/PortletRegistryHelper.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletregistry/PortletRegistryHelper.java?rev=1074422&r1=1074421&r2=1074422&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletregistry/PortletRegistryHelper.java (original)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletregistry/PortletRegistryHelper.java Fri Feb 25 07:45:03 2011
@@ -71,4 +71,10 @@ public class PortletRegistryHelper
         return split;
     }
 
+    public static String makeUniqueName(String appName, String portletName)
+    {
+        return appName + PersistenceBrokerPortletRegistry.PORTLET_UNIQUE_NAME_SEPARATOR + portletName;
+    }
+
+
 }

Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletregistry/RegistryPortletCache.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletregistry/RegistryPortletCache.java?rev=1074422&r1=1074421&r2=1074422&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletregistry/RegistryPortletCache.java (original)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletregistry/RegistryPortletCache.java Fri Feb 25 07:45:03 2011
@@ -77,10 +77,14 @@ public class RegistryPortletCache implem
     public synchronized static void cacheAdd(Identity oid, Object obj)
     {
         oidCache.remove(oid);
+        PortletDefinition pd = (PortletDefinition)obj;
+        if (pd.getApplication() == null)
+        {
+            return;
+        }
         CacheElement entry = new EhCacheElementImpl(oid, obj);
         oidCache.put(entry);
         
-        PortletDefinition pd = (PortletDefinition)obj;
         DistributedCacheObject wrapper = new RegistryCacheObjectWrapper(oid, pd.getUniqueName());
         nameCache.remove(pd.getUniqueName());
         CacheElement nameEntry = nameCache.createElement(pd.getUniqueName(), wrapper);

Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/om/portlet/impl/PortletApplicationDefinitionImpl.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/om/portlet/impl/PortletApplicationDefinitionImpl.java?rev=1074422&r1=1074421&r2=1074422&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/om/portlet/impl/PortletApplicationDefinitionImpl.java (original)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/om/portlet/impl/PortletApplicationDefinitionImpl.java Fri Feb 25 07:45:03 2011
@@ -41,6 +41,7 @@ import org.apache.jetspeed.om.portlet.Ev
 import org.apache.jetspeed.om.portlet.Filter;
 import org.apache.jetspeed.om.portlet.FilterMapping;
 import org.apache.jetspeed.om.portlet.GenericMetadata;
+import org.apache.jetspeed.om.portlet.InitParam;
 import org.apache.jetspeed.om.portlet.JetspeedServiceReference;
 import org.apache.jetspeed.om.portlet.Listener;
 import org.apache.jetspeed.om.portlet.LocaleEncodingMapping;
@@ -96,6 +97,7 @@ public class PortletApplicationDefinitio
     private List<DisplayName> displayNames;
     private List<SecurityRole> roles;
     private List<PortletDefinition> portlets;
+    private List<PortletDefinition> clones;
     private List<EventDefinition> eventDefinitions;
     private List<PublicRenderParameter> publicRenderParameters;
     private List<CustomPortletMode> customPortletModes;
@@ -359,6 +361,18 @@ public class PortletApplicationDefinitio
         return null;
     }
 
+    public PortletDefinition getClone(String cloneName)
+    {
+        for (PortletDefinition clone : getClones())
+        {
+            if (clone.getPortletName().equals(cloneName))
+            {
+                return clone;
+            }
+        }
+        return null;
+    }
+
     @SuppressWarnings("unchecked")
     public List<PortletDefinition> getPortlets()
     {
@@ -369,6 +383,17 @@ public class PortletApplicationDefinitio
         return portlets;
     }
 
+    @SuppressWarnings("unchecked")
+    public List<PortletDefinition> getClones()
+    {
+        if (clones == null)
+        {
+            clones = CollectionUtils.createList();
+        }
+        return clones;
+    }
+
+
     public PortletDefinition addPortlet(String name)
     {
         if (getPortlet(name) != null)
@@ -382,6 +407,19 @@ public class PortletApplicationDefinitio
         return portlet;
     }
 
+    public PortletDefinition addClone(String name)
+    {
+        if (getClone(name) != null)
+        {
+            throw new IllegalArgumentException("Portlet/Clone with name: "+name+" already defined");
+        }
+        PortletDefinitionImpl clone = new PortletDefinitionImpl(this.getName());
+        clone.setPortletName(name);
+        clone.setApplication(this);       
+        getClones().add(clone);
+        return clone;
+    }
+
     @SuppressWarnings("unchecked")
     public List<EventDefinition> getEventDefinitions()
     {
@@ -981,6 +1019,11 @@ public class PortletApplicationDefinitio
         {
             ((Support)pd).postLoad(this);
         }
+        for (PortletDefinition clone : clones)
+        {
+            ((Support)clone).postLoad(this);
+        }
+
     }
 
     /// PersistenceBrokerAware interface implementation

Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/om/portlet/impl/PortletDefinitionImpl.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/om/portlet/impl/PortletDefinitionImpl.java?rev=1074422&r1=1074421&r2=1074422&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/om/portlet/impl/PortletDefinitionImpl.java (original)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/om/portlet/impl/PortletDefinitionImpl.java Fri Feb 25 07:45:03 2011
@@ -73,7 +73,8 @@ public class PortletDefinitionImpl imple
     protected String preferenceValidatorClassname;
     private Integer expirationCache;
     private String cacheScope;
-
+    private String cloneParent = null;
+    
     /** Metadata property */    
     private Collection<LocalizedField> metadataFields = null;
 
@@ -100,6 +101,11 @@ public class PortletDefinitionImpl imple
     {
     }
 
+    public PortletDefinitionImpl(String cloneParent)
+    {
+        this.cloneParent = cloneParent;
+    }
+
     public PortletApplication getApplication()
     {
         return app;
@@ -757,4 +763,13 @@ public class PortletDefinitionImpl imple
         return this.addSupportedPublishingEvent(qname);
     }
 
+    public boolean isClone()
+    {
+        return (cloneParent != null);
+    }
+
+    public String getCloneParent()
+    {
+        return this.cloneParent;
+    }
 }

Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/serializer/JetspeedRegistrySerializer.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/serializer/JetspeedRegistrySerializer.java?rev=1074422&r1=1074421&r2=1074422&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/serializer/JetspeedRegistrySerializer.java (original)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/serializer/JetspeedRegistrySerializer.java Fri Feb 25 07:45:03 2011
@@ -107,11 +107,13 @@ public class JetspeedRegistrySerializer 
                 for (PortletApplication pa : registry.getPortletApplications())
                 {
                     List<PortletDefinition> portlets = pa.getPortlets();
+                    List<PortletDefinition> clones = pa.getClones();
                     if (searchEngine != null)
                     {
-                        List<Object> list = new ArrayList<Object>(portlets.size() + 1);
+                        List<Object> list = new ArrayList<Object>(portlets.size() + clones.size() + 1);
                         list.add(pa);
                         list.addAll(portlets);
+                        list.addAll(clones);
                         searchEngine.remove(list);
                     }
                     registry.removeApplication(pa);

Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/test/java/org/apache/jetspeed/components/portletregistry/TestPortletRegistryDAO.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/test/java/org/apache/jetspeed/components/portletregistry/TestPortletRegistryDAO.java?rev=1074422&r1=1074421&r2=1074422&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/test/java/org/apache/jetspeed/components/portletregistry/TestPortletRegistryDAO.java (original)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/test/java/org/apache/jetspeed/components/portletregistry/TestPortletRegistryDAO.java Fri Feb 25 07:45:03 2011
@@ -133,7 +133,7 @@ public class TestPortletRegistryDAO exte
         final String appName = "App_1";
         final String sourcePortletName = "Portlet 1";
         final String clonedPortletName = "ClonedPortlet 1";
-        
+
         PortletApplication app = portletRegistry.getPortletApplication(appName);
         assertNotNull("Portlet application, " + appName + ", is not found.", app);
         
@@ -148,9 +148,12 @@ public class TestPortletRegistryDAO exte
         {
             Collection<LocalizedField> sourceFields = sourcePortlet.getMetadata().getFields();
             portletRegistry.clonePortletDefinition(sourcePortlet, clonedPortletName);
-            clonedPortlet = app.getPortlet(clonedPortletName);
+            clonedPortlet = app.getClone(clonedPortletName);
             assertNotNull("Cloned portlet is not found after invoking cloning method.", clonedPortlet);
 
+            assertTrue("Portlet should've been a clone", clonedPortlet.isClone());
+            assertEquals("Portlet clone parent not matching parent app", clonedPortlet.getCloneParent(), app.getName());
+            
             Collection<LocalizedField> clonedFields = clonedPortlet.getMetadata().getFields();
             
             assertEquals("The metadata fields count is not equals.", sourceFields.size(), clonedFields.size());
@@ -179,10 +182,52 @@ public class TestPortletRegistryDAO exte
         {
             if (clonedPortlet != null)
             {
-                app.getPortlets().remove(clonedPortlet);
+                List<PortletDefinition> clones = app.getClones();
+                assertEquals("count of clones off", 1, clones.size());
+                clones.remove(clonedPortlet);
                 portletRegistry.updatePortletApplication(app);
+                PortletApplication testApp = portletRegistry.getPortletApplication("App_1");
+                clones = testApp.getClones();
+                assertEquals("count of clones should be zero", 0, clones.size());
             }
         }
+        // test restoring clones
+        try
+        {
+            createApplicationAndPortlet("cloneTest", "/cloneTest", "SourcePortlet", "Title Source Portlet", false);
+            PortletApplication testApp = portletRegistry.getPortletApplication("cloneTest");
+            assertNotNull("test app is null", testApp);
+            assertEquals("test App name not what expected", "cloneTest", testApp.getName());
+            PortletDefinition srcPortlet = testApp.getPortlet("SourcePortlet");
+            assertNotNull("src portlet is null", srcPortlet);
+            assertEquals("src portlet title is not what expected", "Title Source Portlet", srcPortlet.getPortletInfo().getTitle() );
+
+            PortletDefinition myClone = portletRegistry.clonePortletDefinition(srcPortlet, "restorePortlet");
+            assertNotNull("myClone portlet is null", myClone);
+            assertEquals("myClone portlet name is not what expected", myClone.getPortletName(), "restorePortlet");
+            assertEquals("expecting one clone ", 1,  testApp.getClones().size());
+
+            portletRegistry.removeApplication(testApp);
+            testApp = portletRegistry.getPortletApplication("cloneTest");
+            assertNull("test app should be null", testApp);
+
+            createApplicationAndPortlet("cloneTest", "/cloneTest", "SourcePortlet", "Title Source Portlet", false);
+            PortletApplication recreated = portletRegistry.getPortletApplication("cloneTest");
+            assertNotNull("recreated test app is null", recreated);
+            int count = portletRegistry.restoreClones(recreated);
+            assertEquals("Expected to restore one clone", 1, count);
+            PortletDefinition cpd = recreated.getClone("restorePortlet");
+            assertEquals("Expected clone to be named 'restorePortlet' ", cpd.getPortletName(), "restorePortlet");
+        }
+        finally
+        {
+            PortletApplication cleanup = portletRegistry.getPortletApplication("cloneTest");
+            assertNotNull("cleanup app is null", cleanup);
+            assertEquals("expecting one clone ", 1, cleanup.getClones().size());
+            portletRegistry.removeAllClones(cleanup);
+            assertEquals("expecting zero clones ", 0, cleanup.getClones().size());
+            portletRegistry.removeApplication(cleanup);
+        }
     }
     
     private static List<LocalizedField> findLocalizedFieldsByNameAndLocale(final Collection<LocalizedField> sourceFields, final String name, final Locale locale)
@@ -245,6 +290,12 @@ public class TestPortletRegistryDAO exte
      */
     private void buildTestData() throws RegistryException, LockFailedException
     {
+        createApplicationAndPortlet("App_1", "/app1", "Portlet 1", "Portlet 1", true);
+    }
+
+    private void createApplicationAndPortlet(String appName, String appContextPath, String portletName, String title, boolean create20Data)
+            throws RegistryException, LockFailedException
+    {
         String lang = Locale.getDefault().toString();
         
         // start clean
@@ -257,8 +308,8 @@ public class TestPortletRegistryDAO exte
         // Create an Application and a Web app
 
         PortletApplicationDefinitionImpl app = new PortletApplicationDefinitionImpl();
-        app.setName("App_1");
-        app.setContextPath("/app1");
+        app.setName(appName);
+        app.setContextPath(appContextPath);
 
         app.addDescription(Locale.FRENCH.toString()).setDescription("Description: Le fromage est dans mon pantalon!");
         app.addDisplayName(Locale.FRENCH.toString()).setDisplayName("Display Name: Le fromage est dans mon pantalon!");
@@ -274,7 +325,7 @@ public class TestPortletRegistryDAO exte
         
         addDublinCore(app.getMetadata());
 
-        PortletDefinition portlet = app.addPortlet("Portlet 1");
+        PortletDefinition portlet = app.addPortlet(portletName);
         portlet.setPortletClass("org.apache.Portlet");
         portlet.addDescription(lang).setDescription("Portlet description.");
         portlet.addDisplayName(lang).setDisplayName("Portlet display Name.");
@@ -291,8 +342,8 @@ public class TestPortletRegistryDAO exte
         pref.addValue("value 2");
         
         Language language = portlet.addLanguage(Locale.getDefault());
-        language.setTitle("Portlet 1");
-        language.setShortTitle("Portlet 1");
+        language.setTitle(title);
+        language.setShortTitle(title);
 
         Supports supports = portlet.addSupports("html/text");
         supports.addPortletMode(MODE_EDIT);
@@ -302,12 +353,15 @@ public class TestPortletRegistryDAO exte
         supports = portlet.addSupports("wml");
         supports.addPortletMode(MODE_HELP);
         supports.addPortletMode(MODE_VIEW);
-        
-        build20TestData(app, portlet);
+
+        if (create20Data)
+        {
+            build20TestData(app, portlet);
+        }
         portletRegistry.updatePortletApplication(app);        
     }
      
-    
+
     protected void verifyData(boolean afterUpdates) throws Exception
     {
         PortletApplication app;

Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/test/resources/registry-test.xml
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/test/resources/registry-test.xml?rev=1074422&r1=1074421&r2=1074422&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/test/resources/registry-test.xml (original)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/test/resources/registry-test.xml Fri Feb 25 07:45:03 2011
@@ -46,29 +46,40 @@
         </constructor-arg>        
         <constructor-arg index="5">
             <ref bean="PortletPreferencesProviderImpl" />
-        </constructor-arg>    
+        </constructor-arg>
     </bean>
 
     <bean id="org.apache.jetspeed.request.RequestContextComponent" class="org.apache.jetspeed.request.MockRequestContextComponent"/>
-    
-    <bean id="org.apache.jetspeed.components.portletregistry.PortletRegistry" name="portletRegistry" parent="baseTransactionProxy">
-        <property name="proxyInterfaces">
-            <value>org.apache.jetspeed.components.portletregistry.PortletRegistry</value>
-        </property>
 
-        <property name="target">
-            <ref bean="portletRegistryImpl" />
-        </property>
-        <property name="transactionAttributes">
-            <props>
-                <prop key="register*">PROPAGATION_REQUIRED,-org.apache.jetspeed.components.portletregistry.RegistryException</prop>
-                <prop key="remove*">PROPAGATION_REQUIRED,-org.apache.jetspeed.components.portletregistry.RegistryException</prop>
-                <prop key="update*">PROPAGATION_REQUIRED,-org.apache.jetspeed.components.portletregistry.RegistryException</prop>
-                <prop key="save*">PROPAGATION_REQUIRED,-org.apache.jetspeed.components.portletregistry.RegistryException</prop>
-                <prop key="*">PROPAGATION_SUPPORTS</prop>
-            </props>
-        </property>
-    </bean>
+
+  <bean id="org.apache.jetspeed.components.portletregistry.PortletRegistry" name="portletRegistry"
+    parent="baseTransactionProxy">
+    <property name="proxyInterfaces">
+      <value>org.apache.jetspeed.components.portletregistry.PortletRegistry</value>
+    </property>
+
+    <property name="target">
+      <ref bean="portletRegistryImpl" />
+    </property>
+    <property name="transactionAttributes">
+      <props>
+        <prop key="register*">
+          PROPAGATION_REQUIRED,-org.apache.jetspeed.components.portletregistry.RegistryException
+        </prop>
+        <prop key="remove*">
+          PROPAGATION_REQUIRED,-org.apache.jetspeed.components.portletregistry.RegistryException
+        </prop>
+        <prop key="update*">
+          PROPAGATION_REQUIRED,-org.apache.jetspeed.components.portletregistry.RegistryException
+        </prop>
+        <prop key="save*">PROPAGATION_REQUIRED,-org.apache.jetspeed.components.portletregistry.RegistryException</prop>
+        <prop key="clone*">PROPAGATION_REQUIRED,-org.apache.jetspeed.components.portletregistry.RegistryException</prop>
+        <prop key="restore*">PROPAGATION_REQUIRED,-org.apache.jetspeed.components.portletregistry.RegistryException</prop>
+        <prop key="*">PROPAGATION_SUPPORTS</prop>
+      </props>
+    </property>
+  </bean>
+
 
   <!-- register JetspeedPortletFactory as RegistryEventLister on the PortletRegistry -->
   <bean id="registerPortletFactoryPortletRegistyEventListener" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">

Modified: portals/jetspeed-2/portal/trunk/etc/registration/assembly/registry.xml
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/etc/registration/assembly/registry.xml?rev=1074422&r1=1074421&r2=1074422&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/etc/registration/assembly/registry.xml (original)
+++ portals/jetspeed-2/portal/trunk/etc/registration/assembly/registry.xml Fri Feb 25 07:45:03 2011
@@ -42,7 +42,10 @@
         </constructor-arg>
         <constructor-arg index="5">
             <ref bean="portletDefinitionNameCache" />
-        </constructor-arg>        
+        </constructor-arg>
+        <constructor-arg index="6">
+          <ref bean="org.apache.jetspeed.search.SearchEngine" />
+        </constructor-arg>
     </bean>
 
     <bean id="org.apache.jetspeed.components.portletregistry.PortletRegistry" name="portletRegistry" parent="baseTransactionProxy">

Modified: portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/components/portletregistry/PortletRegistry.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/components/portletregistry/PortletRegistry.java?rev=1074422&r1=1074421&r2=1074422&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/components/portletregistry/PortletRegistry.java (original)
+++ portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/components/portletregistry/PortletRegistry.java Fri Feb 25 07:45:03 2011
@@ -34,9 +34,27 @@ import org.apache.jetspeed.om.portlet.Po
  */
 public interface PortletRegistry
 {
+    /**
+     * Retrieves all portlet definitions for this deployment
+     * including both clones and portlet definitions
+     * @return a collection of portlet definitions from all portlet apps
+     */
+    Collection<PortletDefinition> getAllDefinitions();
+
+    /**
+     * Retrieve all portlet definitions system wide
+     * The collection does not include clones
+     * @return a collection of portlet definitions from all portlet apps
+     */
     Collection<PortletDefinition> getAllPortletDefinitions();
 
     /**
+     * Retrieve all clone definitions system wide 
+     * @return a collection of portlet definitions from all portlet apps
+     */
+    Collection<PortletDefinition> getAllCloneDefinitions();
+
+    /**
      * Retrieves a PortletApplication by it's unique name.  We use
      * PortletApplication interface which extends the Pluto PortletApplicationDefinition
      * and adds additional functionallity to it.
@@ -153,11 +171,31 @@ public interface PortletRegistry
     void removeRegistryEventListener(RegistryEventListener listener);
 
     /**
-     * Given a portlet definition, create a clone of it, with a new name
-     * @param source the portlet definition to be cloned
-     * @param newPortletName the unique name of the new portlet definition
+     * Create a portlet instance
+     *
+     * @param source create an instance from this given portlet definition
+     * @param newPortletName a unique portlet name
      * @throws FailedToStorePortletDefinitionException
      */
-    void clonePortletDefinition(PortletDefinition source, String newPortletName) throws FailedToStorePortletDefinitionException;
-    
+    PortletDefinition clonePortletDefinition(PortletDefinition source, String newPortletName) throws FailedToStorePortletDefinitionException;
+
+    /**
+     * Restores all orphaned clones to a re-registered portlet application
+     * @param pa
+     * @return
+     * @throws RegistryException
+     */
+    public int restoreClones(PortletApplication pa)
+            throws RegistryException;
+
+
+    /**
+     * Remove all clones from a given portlet application
+     * 
+     * @param pa the portlet application
+     * @throws RegistryException
+     */
+    void removeAllClones(PortletApplication pa)
+            throws RegistryException;
+
 }

Modified: portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/om/portlet/PortletApplication.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/om/portlet/PortletApplication.java?rev=1074422&r1=1074421&r2=1074422&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/om/portlet/PortletApplication.java (original)
+++ portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/om/portlet/PortletApplication.java Fri Feb 25 07:45:03 2011
@@ -139,8 +139,11 @@ public interface PortletApplication exte
     public GenericMetadata getMetadata();
 
     PortletDefinition getPortlet(String name);
+    PortletDefinition getClone(String name);
     List<PortletDefinition> getPortlets();
+    List<PortletDefinition> getClones();
     PortletDefinition addPortlet(String name);
+    PortletDefinition addClone(String name);
 
     List<EventDefinition> getEventDefinitions();
     EventDefinition addEventDefinition(String name);

Modified: portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/om/portlet/PortletDefinition.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/om/portlet/PortletDefinition.java?rev=1074422&r1=1074421&r2=1074422&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/om/portlet/PortletDefinition.java (original)
+++ portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/om/portlet/PortletDefinition.java Fri Feb 25 07:45:03 2011
@@ -19,7 +19,6 @@ package org.apache.jetspeed.om.portlet;
 import java.io.Serializable;
 import java.util.List;
 import java.util.Locale;
-import java.util.ResourceBundle;
 
 import javax.xml.namespace.QName;
 
@@ -33,6 +32,7 @@ import javax.xml.namespace.QName;
  */
 public interface PortletDefinition extends org.apache.pluto.container.om.portlet.PortletDefinition, Serializable
 {
+    final String CLONE_PARENT_INIT_PARAM = "cloneParentPortlet";
     PortletApplication getApplication();
     InitParam getInitParam(String paramName);
     List<InitParam> getInitParams();
@@ -171,4 +171,18 @@ public interface PortletDefinition exten
      * @return true only if the internal identities are the same
      */
     boolean isSameIdentity(PortletDefinition other);
+
+    /**
+     * Determine if this portlet defintion is a clon
+     */
+    boolean isClone();
+
+    /**
+      * returns the parent portlet definition name from which this
+      * portlet clone was cloned from. If not defined, returns null
+     *
+      * @return the parent application name or null if not a clone
+      */
+     String getCloneParent();
 }
+ 

Modified: portals/jetspeed-2/portal/trunk/jetspeed-archetype/src/main/resources/archetype-resources/pom.xml
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/jetspeed-archetype/src/main/resources/archetype-resources/pom.xml?rev=1074422&r1=1074421&r2=1074422&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/jetspeed-archetype/src/main/resources/archetype-resources/pom.xml (original)
+++ portals/jetspeed-2/portal/trunk/jetspeed-archetype/src/main/resources/archetype-resources/pom.xml Fri Feb 25 07:45:03 2011
@@ -32,7 +32,7 @@
 
   <properties>
     <org.apache.portals.jetspeed.version>2.2.2-SNAPSHOT</org.apache.portals.jetspeed.version>
-    <org.apache.pluto.version>2.0.0</org.apache.pluto.version>
+    <org.apache.pluto.version>2.0.3-SNAPSHOT</org.apache.pluto.version>
     <org.apache.portals.applications.apa-logging.version>1.0</org.apache.portals.applications.apa-logging.version>
     <ccpp.version>1.0</ccpp.version>
     <org.apache.portals.bridges.common.version>2.0</org.apache.portals.bridges.common.version>

Modified: portals/jetspeed-2/portal/trunk/jetspeed-portal-resources/src/main/ddl-schema/registry-schema.xml
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/jetspeed-portal-resources/src/main/ddl-schema/registry-schema.xml?rev=1074422&r1=1074421&r2=1074422&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/jetspeed-portal-resources/src/main/ddl-schema/registry-schema.xml (original)
+++ portals/jetspeed-2/portal/trunk/jetspeed-portal-resources/src/main/ddl-schema/registry-schema.xml Fri Feb 25 07:45:03 2011
@@ -41,7 +41,8 @@ limitations under the License.
         <column name="RESOURCE_BUNDLE" size="255" type="VARCHAR"/>
         <column name="PREFERENCE_VALIDATOR" size="255" type="VARCHAR"/>
         <column name="SECURITY_REF" size="40" type="VARCHAR"/>      
-        <column name="CACHE_SCOPE" size="30" type="VARCHAR"/>  
+        <column name="CACHE_SCOPE" size="30" type="VARCHAR"/>
+        <column name="CLONE_PARENT" required="fals" size="80" type="VARCHAR"/>
     </table>
 
     <!--

Modified: portals/jetspeed-2/portal/trunk/jetspeed-portal-resources/src/main/resources/assembly/registry.xml
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/jetspeed-portal-resources/src/main/resources/assembly/registry.xml?rev=1074422&r1=1074421&r2=1074422&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/jetspeed-portal-resources/src/main/resources/assembly/registry.xml (original)
+++ portals/jetspeed-2/portal/trunk/jetspeed-portal-resources/src/main/resources/assembly/registry.xml Fri Feb 25 07:45:03 2011
@@ -71,7 +71,10 @@
     </constructor-arg>
     <constructor-arg index="5">
       <ref bean="org.apache.jetspeed.components.portletpreferences.PortletPreferencesProvider" />
-    </constructor-arg>    
+    </constructor-arg>
+    <constructor-arg index="6">
+      <ref bean="org.apache.jetspeed.search.SearchEngine" />
+    </constructor-arg>
   </bean>
 
   <bean id="org.apache.jetspeed.components.portletregistry.PortletRegistry" name="portletRegistry"
@@ -97,6 +100,7 @@
         </prop>
         <prop key="save*">PROPAGATION_REQUIRED,-org.apache.jetspeed.components.portletregistry.RegistryException</prop>
         <prop key="clone*">PROPAGATION_REQUIRED,-org.apache.jetspeed.components.portletregistry.RegistryException</prop>
+        <prop key="restore*">PROPAGATION_REQUIRED,-org.apache.jetspeed.components.portletregistry.RegistryException</prop>
         <prop key="*">PROPAGATION_SUPPORTS</prop>
       </props>
     </property>

Modified: portals/jetspeed-2/portal/trunk/pom.xml
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/pom.xml?rev=1074422&r1=1074421&r2=1074422&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/pom.xml (original)
+++ portals/jetspeed-2/portal/trunk/pom.xml Fri Feb 25 07:45:03 2011
@@ -277,7 +277,7 @@
     <myfaces.version>1.1.5</myfaces.version>
     <ojb.version>1.0.3</ojb.version>
     <org.apache.derby.version>10.3.2.1</org.apache.derby.version>
-    <org.apache.pluto.version>2.0.3-SNAPSHOT</org.apache.pluto.version>
+        <org.apache.pluto.version>2.0.3-SNAPSHOT</org.apache.pluto.version>
     <org.apache.portals.bridges.common.version>2.0</org.apache.portals.bridges.common.version>
     <org.apache.portals.bridges.frameworks.version>1.0.4</org.apache.portals.bridges.frameworks.version>
     <org.apache.portals.bridges.velocity.version>2.0</org.apache.portals.bridges.velocity.version>



---------------------------------------------------------------------
To unsubscribe, e-mail: jetspeed-dev-unsubscribe@portals.apache.org
For additional commands, e-mail: jetspeed-dev-help@portals.apache.org


Re: svn commit: r1074422 - in /portals/jetspeed-2/portal/trunk: ./ components/jetspeed-portal/src/main/java/org/apache/jetspeed/tools/pamanager/ components/jetspeed-portal/src/test/java/org/apache/jetspeed/ components/jetspeed-rdbms/src/main/java/org/apach...

Posted by Ron Wheeler <rw...@artifact-software.com>.
The Roadmap advances!
Congratulations.

Ron

On 25/02/2011 2:45 AM, taylor@apache.org wrote:
> Author: taylor
> Date: Fri Feb 25 07:45:03 2011
> New Revision: 1074422
>
> URL: http://svn.apache.org/viewvc?rev=1074422&view=rev
> Log:
> https://issues.apache.org/jira/browse/JS2-1232
> Portlet Instances feature implemented with tests. Note I had to rename this feature Portlet Clones since the concept of Portlet Instances is used (albeit at a low level) all over the codebase. This commit is considered Phase 1 of 2, and includes the core implementation, as well as basic integration into j2-admin PAM, and the Jetspeed Toolbox search. Phase II will encompass improving the PAM and Toolbox to further support administration of clones. This commit introduces an new column CLONE_PARENT to the PORTLET_DEFINITION table. Schema change requirements will be documented in release notes and migration docs.
>
>
> Added:
>      portals/jetspeed-2/portal/trunk/components/jetspeed-rdbms/src/main/java/org/apache/jetspeed/util/ojb/PortletCloneQueryCustomizer.java   (with props)
> Modified:
>      portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/tools/pamanager/PortletApplicationManager.java
>      portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/AbstractRequestContextTestCase.java
>      portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/JETSPEED-INF/ojb/registry_repository.xml
>      portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletregistry/PersistenceBrokerPortletRegistry.java
>      portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletregistry/PortletRegistryHelper.java
>      portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletregistry/RegistryPortletCache.java
>      portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/om/portlet/impl/PortletApplicationDefinitionImpl.java
>      portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/om/portlet/impl/PortletDefinitionImpl.java
>      portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/serializer/JetspeedRegistrySerializer.java
>      portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/test/java/org/apache/jetspeed/components/portletregistry/TestPortletRegistryDAO.java
>      portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/test/resources/registry-test.xml
>      portals/jetspeed-2/portal/trunk/etc/registration/assembly/registry.xml
>      portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/components/portletregistry/PortletRegistry.java
>      portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/om/portlet/PortletApplication.java
>      portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/om/portlet/PortletDefinition.java
>      portals/jetspeed-2/portal/trunk/jetspeed-archetype/src/main/resources/archetype-resources/pom.xml
>      portals/jetspeed-2/portal/trunk/jetspeed-portal-resources/src/main/ddl-schema/registry-schema.xml
>      portals/jetspeed-2/portal/trunk/jetspeed-portal-resources/src/main/resources/assembly/registry.xml
>      portals/jetspeed-2/portal/trunk/pom.xml
>
> Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/tools/pamanager/PortletApplicationManager.java
> URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/tools/pamanager/PortletApplicationManager.java?rev=1074422&r1=1074421&r2=1074422&view=diff
> ==============================================================================
> --- portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/tools/pamanager/PortletApplicationManager.java (original)
> +++ portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/tools/pamanager/PortletApplicationManager.java Fri Feb 25 07:45:03 2011
> @@ -750,11 +750,12 @@ public class PortletApplicationManager i
>           if (searchEngine != null)
>           {
>               List<PortletDefinition>  portletDefList = pa.getPortlets();
> -            List<Object>  list = new ArrayList<Object>(portletDefList.size() + 1);
> -
> +            List<PortletDefinition>  cloneDefList = pa.getClones();
> +            List<Object>  list = new ArrayList<Object>(portletDefList.size() + cloneDefList.size() + 1);
>               if (remove)
>               {
>                   list.addAll(portletDefList);
> +                list.addAll(cloneDefList);
>                   list.add(pa);
>                   searchEngine.remove(list);
>                   log.info("Un-Registered the portlet application in the search engine... " + pa.getName());
> @@ -763,6 +764,7 @@ public class PortletApplicationManager i
>               {
>                   list.add(pa);
>                   list.addAll(portletDefList);
> +                list.addAll(cloneDefList);
>                   searchEngine.add(list);
>                   log.info("Registered the portlet application in the search engine... " + pa.getName());
>               }
>
> Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/AbstractRequestContextTestCase.java
> URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/AbstractRequestContextTestCase.java?rev=1074422&r1=1074421&r2=1074422&view=diff
> ==============================================================================
> --- portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/AbstractRequestContextTestCase.java (original)
> +++ portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/AbstractRequestContextTestCase.java Fri Feb 25 07:45:03 2011
> @@ -42,6 +42,7 @@ public class AbstractRequestContextTestC
>           confList.add("jetspeed-properties.xml");
>           confList.add("page-manager.xml");
>           confList.add("registry.xml");
> +        confList.add("search.xml");
>           confList.add("JETSPEED-INF/spring/RequestDispatcherService.xml");
>           confList.add("rc2.xml");
>           confList.add("static-bean-references.xml");
> @@ -51,7 +52,7 @@ public class AbstractRequestContextTestC
>           confList.add("security-atn.xml");
>           confList.add("security-spi-atn.xml");
>           confList.add("security-atz.xml");
> -        confList.add("JETSPEED-INF/spring/JetspeedPrincipalManagerProviderOverride.xml");
> +        confList.add("JETSPEED-INF/spring/JetspeedPrincipalManagerProviderOverride.xml");
>           return confList.toArray(new String[confList.size()]);
>       }
>
>
> Added: portals/jetspeed-2/portal/trunk/components/jetspeed-rdbms/src/main/java/org/apache/jetspeed/util/ojb/PortletCloneQueryCustomizer.java
> URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-rdbms/src/main/java/org/apache/jetspeed/util/ojb/PortletCloneQueryCustomizer.java?rev=1074422&view=auto
> ==============================================================================
> --- portals/jetspeed-2/portal/trunk/components/jetspeed-rdbms/src/main/java/org/apache/jetspeed/util/ojb/PortletCloneQueryCustomizer.java (added)
> +++ portals/jetspeed-2/portal/trunk/components/jetspeed-rdbms/src/main/java/org/apache/jetspeed/util/ojb/PortletCloneQueryCustomizer.java Fri Feb 25 07:45:03 2011
> @@ -0,0 +1,43 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one or more
> + * contributor license agreements.  See the NOTICE file distributed with
> + * this work for additional information regarding copyright ownership.
> + * The ASF licenses this file to You under the Apache License, Version 2.0
> + * (the "License"); you may not use this file except in compliance with
> + * the License.  You may obtain a copy of the License at
> + *
> + *      http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +package org.apache.jetspeed.util.ojb;
> +
> +import org.apache.ojb.broker.PersistenceBroker;
> +import org.apache.ojb.broker.accesslayer.QueryCustomizerDefaultImpl;
> +import org.apache.ojb.broker.metadata.CollectionDescriptor;
> +import org.apache.ojb.broker.query.Query;
> +import org.apache.ojb.broker.query.QueryByCriteria;
> +
> +public class PortletCloneQueryCustomizer extends QueryCustomizerDefaultImpl {
> +
> +    private static final long serialVersionUID = -1933868940330442307L;
> +    private static final String CLONE_FIELD = "isClone";
> +
> +    public Query customizeQuery(Object owner, PersistenceBroker broker, CollectionDescriptor collDescriptor, QueryByCriteria query)
> +    {
> +        String isClone = this.getAttribute(CLONE_FIELD, "false");
> +        if (isClone.equals("false"))
> +        {
> +            query.getCriteria().addIsNull("cloneParent");
> +        }
> +        else
> +        {
> +            query.getCriteria().addNotNull("cloneParent");
> +        }
> +        return query;
> +    }
> +}
>
> Propchange: portals/jetspeed-2/portal/trunk/components/jetspeed-rdbms/src/main/java/org/apache/jetspeed/util/ojb/PortletCloneQueryCustomizer.java
> ------------------------------------------------------------------------------
>      svn:eol-style = native
>
> Propchange: portals/jetspeed-2/portal/trunk/components/jetspeed-rdbms/src/main/java/org/apache/jetspeed/util/ojb/PortletCloneQueryCustomizer.java
> ------------------------------------------------------------------------------
>      svn:keywords = Id
>
> Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/JETSPEED-INF/ojb/registry_repository.xml
> URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/JETSPEED-INF/ojb/registry_repository.xml?rev=1074422&r1=1074421&r2=1074422&view=diff
> ==============================================================================
> --- portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/JETSPEED-INF/ojb/registry_repository.xml (original)
> +++ portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/JETSPEED-INF/ojb/registry_repository.xml Fri Feb 25 07:45:03 2011
> @@ -191,6 +191,12 @@
>
>         >
>            <inverse-foreignkey field-ref="appId"/>
> +<query-customizer class="org.apache.jetspeed.util.ojb.PortletCloneQueryCustomizer">
> +<attribute
> +              attribute-name="isClone"
> +              attribute-value="false"
> +            />
> +</query-customizer>
>         </collection-descriptor>
>
>         <collection-descriptor
> @@ -366,6 +372,23 @@
>            <inverse-foreignkey field-ref="applicationId"/>
>         </collection-descriptor>
>
> +<collection-descriptor
> +         name="clones"
> +         element-class-ref="org.apache.jetspeed.om.portlet.impl.PortletDefinitionImpl"
> +         auto-delete="false"
> +         auto-update = "true"
> +         auto-retrieve = "true"
> +
> +>
> +<inverse-foreignkey field-ref="appId"/>
> +<query-customizer class="org.apache.jetspeed.util.ojb.PortletCloneQueryCustomizer">
> +<attribute
> +              attribute-name="isClone"
> +              attribute-value="true"
> +            />
> +</query-customizer>
> +</collection-descriptor>
> +
>      </class-descriptor>
>
>   <!--
> @@ -417,7 +440,12 @@
>            column="CACHE_SCOPE"
>            jdbc-type="VARCHAR"
>         />
> -
> +<field-descriptor
> +          name="cloneParent"
> +          column="CLONE_PARENT"
> +          jdbc-type="VARCHAR"
> +          nullable="true"
> +      />
>         <field-descriptor
>            name="resourceBundle"
>            column="RESOURCE_BUNDLE"
>
> Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletregistry/PersistenceBrokerPortletRegistry.java
> URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletregistry/PersistenceBrokerPortletRegistry.java?rev=1074422&r1=1074421&r2=1074422&view=diff
> ==============================================================================
> --- portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletregistry/PersistenceBrokerPortletRegistry.java (original)
> +++ portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletregistry/PersistenceBrokerPortletRegistry.java Fri Feb 25 07:45:03 2011
> @@ -42,6 +42,7 @@ import org.apache.jetspeed.om.portlet.Se
>   import org.apache.jetspeed.om.portlet.Supports;
>   import org.apache.jetspeed.om.portlet.impl.PortletApplicationDefinitionImpl;
>   import org.apache.jetspeed.om.portlet.impl.PortletDefinitionImpl;
> +import org.apache.jetspeed.search.SearchEngine;
>   import org.apache.jetspeed.util.JetspeedLocale;
>   import org.apache.ojb.broker.query.Criteria;
>   import org.apache.ojb.broker.query.QueryFactory;
> @@ -67,27 +68,35 @@ public class PersistenceBrokerPortletReg
>        * The separator used to create a unique portlet name as
>        * {portletApplication}::{portlet}
>        */
> -    static final String PORTLET_UNIQUE_NAME_SEPARATOR = "::";
> +    static public final String PORTLET_UNIQUE_NAME_SEPARATOR = "::";
>
> -    private JetspeedCache applicationOidCache = null;
> -    private JetspeedCache portletOidCache = null;
> -    private JetspeedCache applicationNameCache = null;
> -    private JetspeedCache portletNameCache = null;
> -    private List<RegistryEventListener>  listeners = new ArrayList<RegistryEventListener>();
> -    private PortletPreferencesProvider preferenceService;
> +    protected JetspeedCache applicationOidCache = null;
> +    protected JetspeedCache portletOidCache = null;
> +    protected JetspeedCache applicationNameCache = null;
> +    protected JetspeedCache portletNameCache = null;
> +    protected List<RegistryEventListener>  listeners = new ArrayList<RegistryEventListener>();
> +    protected PortletPreferencesProvider preferenceService;
> +    protected SearchEngine searchEngine;
>
>       // for testing purposes only: no need for the portletFactory then
>       public PersistenceBrokerPortletRegistry(String repositoryPath, PortletPreferencesProvider preferenceService)
>       {
> -        this(repositoryPath, null, null, null, null, preferenceService);
> +        this(repositoryPath, null, null, null, null, preferenceService, null);
> +    }
> +
> +    public PersistenceBrokerPortletRegistry(String repositoryPath,
> +            JetspeedCache applicationOidCache, JetspeedCache portletOidCache,
> +            JetspeedCache applicationNameCache, JetspeedCache portletNameCache,
> +            PortletPreferencesProvider preferenceService)
> +    {
> +        this(repositoryPath, applicationOidCache, portletOidCache, applicationNameCache, portletNameCache, preferenceService, null);
>       }
>
> -    /**
> -     *
> -     */
>       public PersistenceBrokerPortletRegistry(String repositoryPath,
>               JetspeedCache applicationOidCache, JetspeedCache portletOidCache,
> -            JetspeedCache applicationNameCache, JetspeedCache portletNameCache, PortletPreferencesProvider preferenceService)
> +            JetspeedCache applicationNameCache, JetspeedCache portletNameCache,
> +            PortletPreferencesProvider preferenceService,
> +            SearchEngine search)
>       {
>           super(repositoryPath);
>           this.applicationOidCache = applicationOidCache;
> @@ -100,12 +109,35 @@ public class PersistenceBrokerPortletReg
>           this.applicationNameCache.addEventListener(this, false);
>           this.portletNameCache.addEventListener(this, false);
>           this.preferenceService = preferenceService;
> +        this.searchEngine = search;
>       }
>
>       @SuppressWarnings("unchecked")
>       public Collection<PortletDefinition>  getAllPortletDefinitions()
>       {
>           Criteria c = new Criteria();
> +        c.addIsNull("cloneParent");
> +        Collection<PortletDefinition>  list = getPersistenceBrokerTemplate().getCollectionByQuery(
> +                QueryFactory.newQuery(PortletDefinitionImpl.class, c));
> +        postLoadColl(list);
> +        return list;
> +    }
> +
> +    @SuppressWarnings("unchecked")
> +    public Collection<PortletDefinition>  getAllDefinitions()
> +    {
> +        Criteria c = new Criteria();
> +        Collection<PortletDefinition>  list = getPersistenceBrokerTemplate().getCollectionByQuery(
> +                QueryFactory.newQuery(PortletDefinitionImpl.class, c));
> +        postLoadColl(list);
> +        return list;
> +    }
> +
> +    @SuppressWarnings("unchecked")
> +    public Collection<PortletDefinition>  getAllCloneDefinitions()
> +    {
> +        Criteria c = new Criteria();
> +        c.addNotNull("cloneParent");
>           Collection<PortletDefinition>  list = getPersistenceBrokerTemplate().getCollectionByQuery(
>                   QueryFactory.newQuery(PortletDefinitionImpl.class, c));
>           postLoadColl(list);
> @@ -200,6 +232,7 @@ public class PersistenceBrokerPortletReg
>       {
>           getPersistenceBrokerTemplate().store(newApp);
>           this.preferenceService.storeDefaults(newApp);
> +        this.restoreClones(newApp);
>       }
>
>       public void removeApplication(PortletApplication app) throws RegistryException
> @@ -350,36 +383,36 @@ public class PersistenceBrokerPortletReg
>           this.listeners.remove(listener);
>       }
>
> -    public void clonePortletDefinition(PortletDefinition source, String newPortletName) throws FailedToStorePortletDefinitionException
> +    public PortletDefinition clonePortletDefinition(PortletDefinition source, String newPortletName) throws FailedToStorePortletDefinitionException
>       {
>           if (this.portletDefinitionExists(newPortletName, source.getApplication()))
>           {
> -            throw new FailedToStorePortletDefinitionException("Cannot clone to portlet named " + newPortletName + ", name already exists");
> +            throw new FailedToStorePortletDefinitionException("Cannot clone to portlet named " + newPortletName + ", name already exists");
>           }
> -
>           // create new portlet in source portlet application
> -        PortletDefinition copy = source.getApplication().addPortlet(newPortletName);
> -
> +        PortletDefinition copy = source.getApplication().addClone(newPortletName);
> +        PortletApplication destApp = source.getApplication();
> +
>           // First set display name
> -
> +
>           DisplayName displayName = copy.addDisplayName(JetspeedLocale.getDefaultLocale().getLanguage());
>           displayName.setDisplayName(newPortletName);
> -
> +
>           // And, then, copy all attributes
> -
> +
>           copy.setPortletClass(source.getPortletClass());
>           copy.setResourceBundle(source.getResourceBundle());
>           copy.setPreferenceValidatorClassname(source.getPreferenceValidatorClassname());
>           copy.setExpirationCache(source.getExpirationCache());
>           copy.setCacheScope(source.getCacheScope());
> -
> +
>           for (LocalizedField field : source.getMetadata().getFields())
>           {
>               copy.getMetadata().addField(field.getLocale(), field.getName(), field.getValue());
>           }
> -
> +
>           copy.setJetspeedSecurityConstraint(source.getJetspeedSecurityConstraint());
> -
> +
>           for (Description desc : source.getDescriptions())
>           {
>               Description copyDesc = copy.addDescription(desc.getLang());
> @@ -390,14 +423,16 @@ public class PersistenceBrokerPortletReg
>           {
>               InitParam copyInitParam = copy.addInitParam(initParam.getParamName());
>               copyInitParam.setParamValue(initParam.getParamValue());
> -
> +
>               for (Description desc : initParam.getDescriptions())
>               {
>                   Description copyDesc = copyInitParam.addDescription(desc.getLang());
>                   copyDesc.setDescription(desc.getDescription());
>               }
>           }
> -
> +        InitParam parentPortlet = copy.addInitParam(PortletDefinition.CLONE_PARENT_INIT_PARAM);
> +        parentPortlet.setParamValue(source.getPortletName());
> +
>           for (EventDefinitionReference eventDefRef : source.getSupportedProcessingEvents())
>           {
>               copy.addSupportedProcessingEvent(eventDefRef.getQName());
> @@ -407,34 +442,34 @@ public class PersistenceBrokerPortletReg
>           {
>               copy.addSupportedPublishingEvent(eventDefRef.getQName());
>           }
> -
> +
>           for (SecurityRoleRef secRoleRef : source.getSecurityRoleRefs())
>           {
>               SecurityRoleRef copySecRoleRef = copy.addSecurityRoleRef(secRoleRef.getRoleName());
>               copySecRoleRef.setRoleLink(secRoleRef.getRoleLink());
> -
> +
>               for (Description desc : secRoleRef.getDescriptions())
>               {
>                   Description copyDesc = copySecRoleRef.addDescription(desc.getLang());
>                   copyDesc.setDescription(desc.getDescription());
>               }
>           }
> -
> +
>           for (Supports supports : source.getSupports())
>           {
>               Supports copySupports = copy.addSupports(supports.getMimeType());
> -
> +
>               for (String portletMode : supports.getPortletModes())
>               {
>                   copySupports.addPortletMode(portletMode);
>               }
> -
> +
>               for (String windowState : supports.getWindowStates())
>               {
>                   copySupports.addWindowState(windowState);
>               }
>           }
> -
> +
>           for (Language language : source.getLanguages())
>           {
>               Language copyLanguage = copy.addLanguage(language.getLocale());
> @@ -443,23 +478,23 @@ public class PersistenceBrokerPortletReg
>               copyLanguage.setKeywords(language.getKeywords());
>               copyLanguage.setSupportedLocale(language.isSupportedLocale());
>           }
> -
> +
>           for (ContainerRuntimeOption runtimeOption : source.getContainerRuntimeOptions())
>           {
>               ContainerRuntimeOption copyRuntimeOption = copy.addContainerRuntimeOption(runtimeOption.getName());
> -
> +
>               for (String value : runtimeOption.getValues())
>               {
>                   copyRuntimeOption.addValue(value);
>               }
>           }
> -
> +
>           copy.getSupportedPublicRenderParameters().addAll(source.getSupportedPublicRenderParameters());
> -
> +
>           //savePortletDefinition(copy);
>           try
>           {
> -            updatePortletApplication(source.getApplication());
> +            updatePortletApplication(destApp);
>           }
>           catch (RegistryException e)
>           {
> @@ -469,11 +504,11 @@ public class PersistenceBrokerPortletReg
>           {
>               Preference copyPref = copy.addDescriptorPreference(pref.getName());
>               copyPref.setReadOnly(pref.isReadOnly());
> -
> +
>               for (String value : pref.getValues())
>               {
>                   copyPref.addValue(value);
> -            }
> +            }
>           }
>           try
>           {
> @@ -481,8 +516,60 @@ public class PersistenceBrokerPortletReg
>           }
>           catch (Throwable e)
>           {
> -            source.getApplication().getPortlets().remove(copy);
> -            throw new FailedToStorePortletDefinitionException(e);
> +            destApp.getClones().remove(copy);
> +            throw new FailedToStorePortletDefinitionException(e);
> +        }
> +        PortletDefinition pd = getPortletDefinitionByUniqueName(PortletRegistryHelper.makeUniqueName(source.getApplication().getName(), newPortletName));
> +        PortletApplication pa = pd.getApplication();
> +        // reindex
> +        if (searchEngine != null)
> +        {
> +            searchEngine.remove(pa);
> +            searchEngine.remove(pa.getPortlets());
> +            searchEngine.remove(pa.getClones());
> +            searchEngine.add(pa);
> +            searchEngine.add(pa.getPortlets());
> +            searchEngine.add(pa.getClones());
> +        }
> +        return pd;
> +    }
> +
> +    public int restoreClones(PortletApplication pa)
> +            throws RegistryException
> +    {
> +        int count = 0;
> +        Criteria criteria = new Criteria();
> +        criteria.addEqualTo("cloneParent", pa.getName());
> +        Collection<PortletDefinitionImpl>  clones = getPersistenceBrokerTemplate().getCollectionByQuery(
> +                QueryFactory.newQuery(PortletDefinitionImpl.class, criteria));
> +        for (PortletDefinitionImpl pd : clones)
> +        {
> +            if (pd.isClone())
> +            {
> +                if (pa.getName().equals(pd.getCloneParent()))
> +                {
> +                    // Restore Clone
> +                    pd.setApplication(pa);
> +                    pa.getClones().add(pd);
> +                    count++;
> +                }
> +            }
> +        }
> +        if (count>  0)
> +        {
> +            updatePortletApplication(pa);
>           }
> -    }
> +        return count;
> +    }
> +
> +    public void removeAllClones(PortletApplication pa)
> +            throws RegistryException
> +    {
> +        Criteria c = new Criteria();
> +        c.addEqualTo("cloneParent", pa.getName());
> +        getPersistenceBrokerTemplate().deleteByQuery(QueryFactory.newQuery(PortletDefinitionImpl.class, c));
> +        pa.getClones().clear();
> +        this.updatePortletApplication(pa);
> +    }
> +
>   }
> \ No newline at end of file
>
> Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletregistry/PortletRegistryHelper.java
> URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletregistry/PortletRegistryHelper.java?rev=1074422&r1=1074421&r2=1074422&view=diff
> ==============================================================================
> --- portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletregistry/PortletRegistryHelper.java (original)
> +++ portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletregistry/PortletRegistryHelper.java Fri Feb 25 07:45:03 2011
> @@ -71,4 +71,10 @@ public class PortletRegistryHelper
>           return split;
>       }
>
> +    public static String makeUniqueName(String appName, String portletName)
> +    {
> +        return appName + PersistenceBrokerPortletRegistry.PORTLET_UNIQUE_NAME_SEPARATOR + portletName;
> +    }
> +
> +
>   }
>
> Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletregistry/RegistryPortletCache.java
> URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletregistry/RegistryPortletCache.java?rev=1074422&r1=1074421&r2=1074422&view=diff
> ==============================================================================
> --- portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletregistry/RegistryPortletCache.java (original)
> +++ portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/components/portletregistry/RegistryPortletCache.java Fri Feb 25 07:45:03 2011
> @@ -77,10 +77,14 @@ public class RegistryPortletCache implem
>       public synchronized static void cacheAdd(Identity oid, Object obj)
>       {
>           oidCache.remove(oid);
> +        PortletDefinition pd = (PortletDefinition)obj;
> +        if (pd.getApplication() == null)
> +        {
> +            return;
> +        }
>           CacheElement entry = new EhCacheElementImpl(oid, obj);
>           oidCache.put(entry);
>
> -        PortletDefinition pd = (PortletDefinition)obj;
>           DistributedCacheObject wrapper = new RegistryCacheObjectWrapper(oid, pd.getUniqueName());
>           nameCache.remove(pd.getUniqueName());
>           CacheElement nameEntry = nameCache.createElement(pd.getUniqueName(), wrapper);
>
> Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/om/portlet/impl/PortletApplicationDefinitionImpl.java
> URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/om/portlet/impl/PortletApplicationDefinitionImpl.java?rev=1074422&r1=1074421&r2=1074422&view=diff
> ==============================================================================
> --- portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/om/portlet/impl/PortletApplicationDefinitionImpl.java (original)
> +++ portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/om/portlet/impl/PortletApplicationDefinitionImpl.java Fri Feb 25 07:45:03 2011
> @@ -41,6 +41,7 @@ import org.apache.jetspeed.om.portlet.Ev
>   import org.apache.jetspeed.om.portlet.Filter;
>   import org.apache.jetspeed.om.portlet.FilterMapping;
>   import org.apache.jetspeed.om.portlet.GenericMetadata;
> +import org.apache.jetspeed.om.portlet.InitParam;
>   import org.apache.jetspeed.om.portlet.JetspeedServiceReference;
>   import org.apache.jetspeed.om.portlet.Listener;
>   import org.apache.jetspeed.om.portlet.LocaleEncodingMapping;
> @@ -96,6 +97,7 @@ public class PortletApplicationDefinitio
>       private List<DisplayName>  displayNames;
>       private List<SecurityRole>  roles;
>       private List<PortletDefinition>  portlets;
> +    private List<PortletDefinition>  clones;
>       private List<EventDefinition>  eventDefinitions;
>       private List<PublicRenderParameter>  publicRenderParameters;
>       private List<CustomPortletMode>  customPortletModes;
> @@ -359,6 +361,18 @@ public class PortletApplicationDefinitio
>           return null;
>       }
>
> +    public PortletDefinition getClone(String cloneName)
> +    {
> +        for (PortletDefinition clone : getClones())
> +        {
> +            if (clone.getPortletName().equals(cloneName))
> +            {
> +                return clone;
> +            }
> +        }
> +        return null;
> +    }
> +
>       @SuppressWarnings("unchecked")
>       public List<PortletDefinition>  getPortlets()
>       {
> @@ -369,6 +383,17 @@ public class PortletApplicationDefinitio
>           return portlets;
>       }
>
> +    @SuppressWarnings("unchecked")
> +    public List<PortletDefinition>  getClones()
> +    {
> +        if (clones == null)
> +        {
> +            clones = CollectionUtils.createList();
> +        }
> +        return clones;
> +    }
> +
> +
>       public PortletDefinition addPortlet(String name)
>       {
>           if (getPortlet(name) != null)
> @@ -382,6 +407,19 @@ public class PortletApplicationDefinitio
>           return portlet;
>       }
>
> +    public PortletDefinition addClone(String name)
> +    {
> +        if (getClone(name) != null)
> +        {
> +            throw new IllegalArgumentException("Portlet/Clone with name: "+name+" already defined");
> +        }
> +        PortletDefinitionImpl clone = new PortletDefinitionImpl(this.getName());
> +        clone.setPortletName(name);
> +        clone.setApplication(this);
> +        getClones().add(clone);
> +        return clone;
> +    }
> +
>       @SuppressWarnings("unchecked")
>       public List<EventDefinition>  getEventDefinitions()
>       {
> @@ -981,6 +1019,11 @@ public class PortletApplicationDefinitio
>           {
>               ((Support)pd).postLoad(this);
>           }
> +        for (PortletDefinition clone : clones)
> +        {
> +            ((Support)clone).postLoad(this);
> +        }
> +
>       }
>
>       /// PersistenceBrokerAware interface implementation
>
> Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/om/portlet/impl/PortletDefinitionImpl.java
> URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/om/portlet/impl/PortletDefinitionImpl.java?rev=1074422&r1=1074421&r2=1074422&view=diff
> ==============================================================================
> --- portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/om/portlet/impl/PortletDefinitionImpl.java (original)
> +++ portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/om/portlet/impl/PortletDefinitionImpl.java Fri Feb 25 07:45:03 2011
> @@ -73,7 +73,8 @@ public class PortletDefinitionImpl imple
>       protected String preferenceValidatorClassname;
>       private Integer expirationCache;
>       private String cacheScope;
> -
> +    private String cloneParent = null;
> +
>       /** Metadata property */
>       private Collection<LocalizedField>  metadataFields = null;
>
> @@ -100,6 +101,11 @@ public class PortletDefinitionImpl imple
>       {
>       }
>
> +    public PortletDefinitionImpl(String cloneParent)
> +    {
> +        this.cloneParent = cloneParent;
> +    }
> +
>       public PortletApplication getApplication()
>       {
>           return app;
> @@ -757,4 +763,13 @@ public class PortletDefinitionImpl imple
>           return this.addSupportedPublishingEvent(qname);
>       }
>
> +    public boolean isClone()
> +    {
> +        return (cloneParent != null);
> +    }
> +
> +    public String getCloneParent()
> +    {
> +        return this.cloneParent;
> +    }
>   }
>
> Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/serializer/JetspeedRegistrySerializer.java
> URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/serializer/JetspeedRegistrySerializer.java?rev=1074422&r1=1074421&r2=1074422&view=diff
> ==============================================================================
> --- portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/serializer/JetspeedRegistrySerializer.java (original)
> +++ portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/serializer/JetspeedRegistrySerializer.java Fri Feb 25 07:45:03 2011
> @@ -107,11 +107,13 @@ public class JetspeedRegistrySerializer
>                   for (PortletApplication pa : registry.getPortletApplications())
>                   {
>                       List<PortletDefinition>  portlets = pa.getPortlets();
> +                    List<PortletDefinition>  clones = pa.getClones();
>                       if (searchEngine != null)
>                       {
> -                        List<Object>  list = new ArrayList<Object>(portlets.size() + 1);
> +                        List<Object>  list = new ArrayList<Object>(portlets.size() + clones.size() + 1);
>                           list.add(pa);
>                           list.addAll(portlets);
> +                        list.addAll(clones);
>                           searchEngine.remove(list);
>                       }
>                       registry.removeApplication(pa);
>
> Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/test/java/org/apache/jetspeed/components/portletregistry/TestPortletRegistryDAO.java
> URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/test/java/org/apache/jetspeed/components/portletregistry/TestPortletRegistryDAO.java?rev=1074422&r1=1074421&r2=1074422&view=diff
> ==============================================================================
> --- portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/test/java/org/apache/jetspeed/components/portletregistry/TestPortletRegistryDAO.java (original)
> +++ portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/test/java/org/apache/jetspeed/components/portletregistry/TestPortletRegistryDAO.java Fri Feb 25 07:45:03 2011
> @@ -133,7 +133,7 @@ public class TestPortletRegistryDAO exte
>           final String appName = "App_1";
>           final String sourcePortletName = "Portlet 1";
>           final String clonedPortletName = "ClonedPortlet 1";
> -
> +
>           PortletApplication app = portletRegistry.getPortletApplication(appName);
>           assertNotNull("Portlet application, " + appName + ", is not found.", app);
>
> @@ -148,9 +148,12 @@ public class TestPortletRegistryDAO exte
>           {
>               Collection<LocalizedField>  sourceFields = sourcePortlet.getMetadata().getFields();
>               portletRegistry.clonePortletDefinition(sourcePortlet, clonedPortletName);
> -            clonedPortlet = app.getPortlet(clonedPortletName);
> +            clonedPortlet = app.getClone(clonedPortletName);
>               assertNotNull("Cloned portlet is not found after invoking cloning method.", clonedPortlet);
>
> +            assertTrue("Portlet should've been a clone", clonedPortlet.isClone());
> +            assertEquals("Portlet clone parent not matching parent app", clonedPortlet.getCloneParent(), app.getName());
> +
>               Collection<LocalizedField>  clonedFields = clonedPortlet.getMetadata().getFields();
>
>               assertEquals("The metadata fields count is not equals.", sourceFields.size(), clonedFields.size());
> @@ -179,10 +182,52 @@ public class TestPortletRegistryDAO exte
>           {
>               if (clonedPortlet != null)
>               {
> -                app.getPortlets().remove(clonedPortlet);
> +                List<PortletDefinition>  clones = app.getClones();
> +                assertEquals("count of clones off", 1, clones.size());
> +                clones.remove(clonedPortlet);
>                   portletRegistry.updatePortletApplication(app);
> +                PortletApplication testApp = portletRegistry.getPortletApplication("App_1");
> +                clones = testApp.getClones();
> +                assertEquals("count of clones should be zero", 0, clones.size());
>               }
>           }
> +        // test restoring clones
> +        try
> +        {
> +            createApplicationAndPortlet("cloneTest", "/cloneTest", "SourcePortlet", "Title Source Portlet", false);
> +            PortletApplication testApp = portletRegistry.getPortletApplication("cloneTest");
> +            assertNotNull("test app is null", testApp);
> +            assertEquals("test App name not what expected", "cloneTest", testApp.getName());
> +            PortletDefinition srcPortlet = testApp.getPortlet("SourcePortlet");
> +            assertNotNull("src portlet is null", srcPortlet);
> +            assertEquals("src portlet title is not what expected", "Title Source Portlet", srcPortlet.getPortletInfo().getTitle() );
> +
> +            PortletDefinition myClone = portletRegistry.clonePortletDefinition(srcPortlet, "restorePortlet");
> +            assertNotNull("myClone portlet is null", myClone);
> +            assertEquals("myClone portlet name is not what expected", myClone.getPortletName(), "restorePortlet");
> +            assertEquals("expecting one clone ", 1,  testApp.getClones().size());
> +
> +            portletRegistry.removeApplication(testApp);
> +            testApp = portletRegistry.getPortletApplication("cloneTest");
> +            assertNull("test app should be null", testApp);
> +
> +            createApplicationAndPortlet("cloneTest", "/cloneTest", "SourcePortlet", "Title Source Portlet", false);
> +            PortletApplication recreated = portletRegistry.getPortletApplication("cloneTest");
> +            assertNotNull("recreated test app is null", recreated);
> +            int count = portletRegistry.restoreClones(recreated);
> +            assertEquals("Expected to restore one clone", 1, count);
> +            PortletDefinition cpd = recreated.getClone("restorePortlet");
> +            assertEquals("Expected clone to be named 'restorePortlet' ", cpd.getPortletName(), "restorePortlet");
> +        }
> +        finally
> +        {
> +            PortletApplication cleanup = portletRegistry.getPortletApplication("cloneTest");
> +            assertNotNull("cleanup app is null", cleanup);
> +            assertEquals("expecting one clone ", 1, cleanup.getClones().size());
> +            portletRegistry.removeAllClones(cleanup);
> +            assertEquals("expecting zero clones ", 0, cleanup.getClones().size());
> +            portletRegistry.removeApplication(cleanup);
> +        }
>       }
>
>       private static List<LocalizedField>  findLocalizedFieldsByNameAndLocale(final Collection<LocalizedField>  sourceFields, final String name, final Locale locale)
> @@ -245,6 +290,12 @@ public class TestPortletRegistryDAO exte
>        */
>       private void buildTestData() throws RegistryException, LockFailedException
>       {
> +        createApplicationAndPortlet("App_1", "/app1", "Portlet 1", "Portlet 1", true);
> +    }
> +
> +    private void createApplicationAndPortlet(String appName, String appContextPath, String portletName, String title, boolean create20Data)
> +            throws RegistryException, LockFailedException
> +    {
>           String lang = Locale.getDefault().toString();
>
>           // start clean
> @@ -257,8 +308,8 @@ public class TestPortletRegistryDAO exte
>           // Create an Application and a Web app
>
>           PortletApplicationDefinitionImpl app = new PortletApplicationDefinitionImpl();
> -        app.setName("App_1");
> -        app.setContextPath("/app1");
> +        app.setName(appName);
> +        app.setContextPath(appContextPath);
>
>           app.addDescription(Locale.FRENCH.toString()).setDescription("Description: Le fromage est dans mon pantalon!");
>           app.addDisplayName(Locale.FRENCH.toString()).setDisplayName("Display Name: Le fromage est dans mon pantalon!");
> @@ -274,7 +325,7 @@ public class TestPortletRegistryDAO exte
>
>           addDublinCore(app.getMetadata());
>
> -        PortletDefinition portlet = app.addPortlet("Portlet 1");
> +        PortletDefinition portlet = app.addPortlet(portletName);
>           portlet.setPortletClass("org.apache.Portlet");
>           portlet.addDescription(lang).setDescription("Portlet description.");
>           portlet.addDisplayName(lang).setDisplayName("Portlet display Name.");
> @@ -291,8 +342,8 @@ public class TestPortletRegistryDAO exte
>           pref.addValue("value 2");
>
>           Language language = portlet.addLanguage(Locale.getDefault());
> -        language.setTitle("Portlet 1");
> -        language.setShortTitle("Portlet 1");
> +        language.setTitle(title);
> +        language.setShortTitle(title);
>
>           Supports supports = portlet.addSupports("html/text");
>           supports.addPortletMode(MODE_EDIT);
> @@ -302,12 +353,15 @@ public class TestPortletRegistryDAO exte
>           supports = portlet.addSupports("wml");
>           supports.addPortletMode(MODE_HELP);
>           supports.addPortletMode(MODE_VIEW);
> -
> -        build20TestData(app, portlet);
> +
> +        if (create20Data)
> +        {
> +            build20TestData(app, portlet);
> +        }
>           portletRegistry.updatePortletApplication(app);
>       }
>
> -
> +
>       protected void verifyData(boolean afterUpdates) throws Exception
>       {
>           PortletApplication app;
>
> Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/test/resources/registry-test.xml
> URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/test/resources/registry-test.xml?rev=1074422&r1=1074421&r2=1074422&view=diff
> ==============================================================================
> --- portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/test/resources/registry-test.xml (original)
> +++ portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/test/resources/registry-test.xml Fri Feb 25 07:45:03 2011
> @@ -46,29 +46,40 @@
>           </constructor-arg>
>           <constructor-arg index="5">
>               <ref bean="PortletPreferencesProviderImpl" />
> -</constructor-arg>
> +</constructor-arg>
>       </bean>
>
>       <bean id="org.apache.jetspeed.request.RequestContextComponent" class="org.apache.jetspeed.request.MockRequestContextComponent"/>
> -
> -<bean id="org.apache.jetspeed.components.portletregistry.PortletRegistry" name="portletRegistry" parent="baseTransactionProxy">
> -<property name="proxyInterfaces">
> -<value>org.apache.jetspeed.components.portletregistry.PortletRegistry</value>
> -</property>
>
> -<property name="target">
> -<ref bean="portletRegistryImpl" />
> -</property>
> -<property name="transactionAttributes">
> -<props>
> -<prop key="register*">PROPAGATION_REQUIRED,-org.apache.jetspeed.components.portletregistry.RegistryException</prop>
> -<prop key="remove*">PROPAGATION_REQUIRED,-org.apache.jetspeed.components.portletregistry.RegistryException</prop>
> -<prop key="update*">PROPAGATION_REQUIRED,-org.apache.jetspeed.components.portletregistry.RegistryException</prop>
> -<prop key="save*">PROPAGATION_REQUIRED,-org.apache.jetspeed.components.portletregistry.RegistryException</prop>
> -<prop key="*">PROPAGATION_SUPPORTS</prop>
> -</props>
> -</property>
> -</bean>
> +
> +<bean id="org.apache.jetspeed.components.portletregistry.PortletRegistry" name="portletRegistry"
> +    parent="baseTransactionProxy">
> +<property name="proxyInterfaces">
> +<value>org.apache.jetspeed.components.portletregistry.PortletRegistry</value>
> +</property>
> +
> +<property name="target">
> +<ref bean="portletRegistryImpl" />
> +</property>
> +<property name="transactionAttributes">
> +<props>
> +<prop key="register*">
> +          PROPAGATION_REQUIRED,-org.apache.jetspeed.components.portletregistry.RegistryException
> +</prop>
> +<prop key="remove*">
> +          PROPAGATION_REQUIRED,-org.apache.jetspeed.components.portletregistry.RegistryException
> +</prop>
> +<prop key="update*">
> +          PROPAGATION_REQUIRED,-org.apache.jetspeed.components.portletregistry.RegistryException
> +</prop>
> +<prop key="save*">PROPAGATION_REQUIRED,-org.apache.jetspeed.components.portletregistry.RegistryException</prop>
> +<prop key="clone*">PROPAGATION_REQUIRED,-org.apache.jetspeed.components.portletregistry.RegistryException</prop>
> +<prop key="restore*">PROPAGATION_REQUIRED,-org.apache.jetspeed.components.portletregistry.RegistryException</prop>
> +<prop key="*">PROPAGATION_SUPPORTS</prop>
> +</props>
> +</property>
> +</bean>
> +
>
>     <!-- register JetspeedPortletFactory as RegistryEventLister on the PortletRegistry -->
>     <bean id="registerPortletFactoryPortletRegistyEventListener" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
>
> Modified: portals/jetspeed-2/portal/trunk/etc/registration/assembly/registry.xml
> URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/etc/registration/assembly/registry.xml?rev=1074422&r1=1074421&r2=1074422&view=diff
> ==============================================================================
> --- portals/jetspeed-2/portal/trunk/etc/registration/assembly/registry.xml (original)
> +++ portals/jetspeed-2/portal/trunk/etc/registration/assembly/registry.xml Fri Feb 25 07:45:03 2011
> @@ -42,7 +42,10 @@
>           </constructor-arg>
>           <constructor-arg index="5">
>               <ref bean="portletDefinitionNameCache" />
> -</constructor-arg>
> +</constructor-arg>
> +<constructor-arg index="6">
> +<ref bean="org.apache.jetspeed.search.SearchEngine" />
> +</constructor-arg>
>       </bean>
>
>       <bean id="org.apache.jetspeed.components.portletregistry.PortletRegistry" name="portletRegistry" parent="baseTransactionProxy">
>
> Modified: portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/components/portletregistry/PortletRegistry.java
> URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/components/portletregistry/PortletRegistry.java?rev=1074422&r1=1074421&r2=1074422&view=diff
> ==============================================================================
> --- portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/components/portletregistry/PortletRegistry.java (original)
> +++ portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/components/portletregistry/PortletRegistry.java Fri Feb 25 07:45:03 2011
> @@ -34,9 +34,27 @@ import org.apache.jetspeed.om.portlet.Po
>    */
>   public interface PortletRegistry
>   {
> +    /**
> +     * Retrieves all portlet definitions for this deployment
> +     * including both clones and portlet definitions
> +     * @return a collection of portlet definitions from all portlet apps
> +     */
> +    Collection<PortletDefinition>  getAllDefinitions();
> +
> +    /**
> +     * Retrieve all portlet definitions system wide
> +     * The collection does not include clones
> +     * @return a collection of portlet definitions from all portlet apps
> +     */
>       Collection<PortletDefinition>  getAllPortletDefinitions();
>
>       /**
> +     * Retrieve all clone definitions system wide
> +     * @return a collection of portlet definitions from all portlet apps
> +     */
> +    Collection<PortletDefinition>  getAllCloneDefinitions();
> +
> +    /**
>        * Retrieves a PortletApplication by it's unique name.  We use
>        * PortletApplication interface which extends the Pluto PortletApplicationDefinition
>        * and adds additional functionallity to it.
> @@ -153,11 +171,31 @@ public interface PortletRegistry
>       void removeRegistryEventListener(RegistryEventListener listener);
>
>       /**
> -     * Given a portlet definition, create a clone of it, with a new name
> -     * @param source the portlet definition to be cloned
> -     * @param newPortletName the unique name of the new portlet definition
> +     * Create a portlet instance
> +     *
> +     * @param source create an instance from this given portlet definition
> +     * @param newPortletName a unique portlet name
>        * @throws FailedToStorePortletDefinitionException
>        */
> -    void clonePortletDefinition(PortletDefinition source, String newPortletName) throws FailedToStorePortletDefinitionException;
> -
> +    PortletDefinition clonePortletDefinition(PortletDefinition source, String newPortletName) throws FailedToStorePortletDefinitionException;
> +
> +    /**
> +     * Restores all orphaned clones to a re-registered portlet application
> +     * @param pa
> +     * @return
> +     * @throws RegistryException
> +     */
> +    public int restoreClones(PortletApplication pa)
> +            throws RegistryException;
> +
> +
> +    /**
> +     * Remove all clones from a given portlet application
> +     *
> +     * @param pa the portlet application
> +     * @throws RegistryException
> +     */
> +    void removeAllClones(PortletApplication pa)
> +            throws RegistryException;
> +
>   }
>
> Modified: portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/om/portlet/PortletApplication.java
> URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/om/portlet/PortletApplication.java?rev=1074422&r1=1074421&r2=1074422&view=diff
> ==============================================================================
> --- portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/om/portlet/PortletApplication.java (original)
> +++ portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/om/portlet/PortletApplication.java Fri Feb 25 07:45:03 2011
> @@ -139,8 +139,11 @@ public interface PortletApplication exte
>       public GenericMetadata getMetadata();
>
>       PortletDefinition getPortlet(String name);
> +    PortletDefinition getClone(String name);
>       List<PortletDefinition>  getPortlets();
> +    List<PortletDefinition>  getClones();
>       PortletDefinition addPortlet(String name);
> +    PortletDefinition addClone(String name);
>
>       List<EventDefinition>  getEventDefinitions();
>       EventDefinition addEventDefinition(String name);
>
> Modified: portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/om/portlet/PortletDefinition.java
> URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/om/portlet/PortletDefinition.java?rev=1074422&r1=1074421&r2=1074422&view=diff
> ==============================================================================
> --- portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/om/portlet/PortletDefinition.java (original)
> +++ portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/om/portlet/PortletDefinition.java Fri Feb 25 07:45:03 2011
> @@ -19,7 +19,6 @@ package org.apache.jetspeed.om.portlet;
>   import java.io.Serializable;
>   import java.util.List;
>   import java.util.Locale;
> -import java.util.ResourceBundle;
>
>   import javax.xml.namespace.QName;
>
> @@ -33,6 +32,7 @@ import javax.xml.namespace.QName;
>    */
>   public interface PortletDefinition extends org.apache.pluto.container.om.portlet.PortletDefinition, Serializable
>   {
> +    final String CLONE_PARENT_INIT_PARAM = "cloneParentPortlet";
>       PortletApplication getApplication();
>       InitParam getInitParam(String paramName);
>       List<InitParam>  getInitParams();
> @@ -171,4 +171,18 @@ public interface PortletDefinition exten
>        * @return true only if the internal identities are the same
>        */
>       boolean isSameIdentity(PortletDefinition other);
> +
> +    /**
> +     * Determine if this portlet defintion is a clon
> +     */
> +    boolean isClone();
> +
> +    /**
> +      * returns the parent portlet definition name from which this
> +      * portlet clone was cloned from. If not defined, returns null
> +     *
> +      * @return the parent application name or null if not a clone
> +      */
> +     String getCloneParent();
>   }
> +
>
> Modified: portals/jetspeed-2/portal/trunk/jetspeed-archetype/src/main/resources/archetype-resources/pom.xml
> URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/jetspeed-archetype/src/main/resources/archetype-resources/pom.xml?rev=1074422&r1=1074421&r2=1074422&view=diff
> ==============================================================================
> --- portals/jetspeed-2/portal/trunk/jetspeed-archetype/src/main/resources/archetype-resources/pom.xml (original)
> +++ portals/jetspeed-2/portal/trunk/jetspeed-archetype/src/main/resources/archetype-resources/pom.xml Fri Feb 25 07:45:03 2011
> @@ -32,7 +32,7 @@
>
>     <properties>
>       <org.apache.portals.jetspeed.version>2.2.2-SNAPSHOT</org.apache.portals.jetspeed.version>
> -<org.apache.pluto.version>2.0.0</org.apache.pluto.version>
> +<org.apache.pluto.version>2.0.3-SNAPSHOT</org.apache.pluto.version>
>       <org.apache.portals.applications.apa-logging.version>1.0</org.apache.portals.applications.apa-logging.version>
>       <ccpp.version>1.0</ccpp.version>
>       <org.apache.portals.bridges.common.version>2.0</org.apache.portals.bridges.common.version>
>
> Modified: portals/jetspeed-2/portal/trunk/jetspeed-portal-resources/src/main/ddl-schema/registry-schema.xml
> URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/jetspeed-portal-resources/src/main/ddl-schema/registry-schema.xml?rev=1074422&r1=1074421&r2=1074422&view=diff
> ==============================================================================
> --- portals/jetspeed-2/portal/trunk/jetspeed-portal-resources/src/main/ddl-schema/registry-schema.xml (original)
> +++ portals/jetspeed-2/portal/trunk/jetspeed-portal-resources/src/main/ddl-schema/registry-schema.xml Fri Feb 25 07:45:03 2011
> @@ -41,7 +41,8 @@ limitations under the License.
>           <column name="RESOURCE_BUNDLE" size="255" type="VARCHAR"/>
>           <column name="PREFERENCE_VALIDATOR" size="255" type="VARCHAR"/>
>           <column name="SECURITY_REF" size="40" type="VARCHAR"/>
> -<column name="CACHE_SCOPE" size="30" type="VARCHAR"/>
> +<column name="CACHE_SCOPE" size="30" type="VARCHAR"/>
> +<column name="CLONE_PARENT" required="fals" size="80" type="VARCHAR"/>
>       </table>
>
>       <!--
>
> Modified: portals/jetspeed-2/portal/trunk/jetspeed-portal-resources/src/main/resources/assembly/registry.xml
> URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/jetspeed-portal-resources/src/main/resources/assembly/registry.xml?rev=1074422&r1=1074421&r2=1074422&view=diff
> ==============================================================================
> --- portals/jetspeed-2/portal/trunk/jetspeed-portal-resources/src/main/resources/assembly/registry.xml (original)
> +++ portals/jetspeed-2/portal/trunk/jetspeed-portal-resources/src/main/resources/assembly/registry.xml Fri Feb 25 07:45:03 2011
> @@ -71,7 +71,10 @@
>       </constructor-arg>
>       <constructor-arg index="5">
>         <ref bean="org.apache.jetspeed.components.portletpreferences.PortletPreferencesProvider" />
> -</constructor-arg>
> +</constructor-arg>
> +<constructor-arg index="6">
> +<ref bean="org.apache.jetspeed.search.SearchEngine" />
> +</constructor-arg>
>     </bean>
>
>     <bean id="org.apache.jetspeed.components.portletregistry.PortletRegistry" name="portletRegistry"
> @@ -97,6 +100,7 @@
>           </prop>
>           <prop key="save*">PROPAGATION_REQUIRED,-org.apache.jetspeed.components.portletregistry.RegistryException</prop>
>           <prop key="clone*">PROPAGATION_REQUIRED,-org.apache.jetspeed.components.portletregistry.RegistryException</prop>
> +<prop key="restore*">PROPAGATION_REQUIRED,-org.apache.jetspeed.components.portletregistry.RegistryException</prop>
>           <prop key="*">PROPAGATION_SUPPORTS</prop>
>         </props>
>       </property>
>
> Modified: portals/jetspeed-2/portal/trunk/pom.xml
> URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/pom.xml?rev=1074422&r1=1074421&r2=1074422&view=diff
> ==============================================================================
> --- portals/jetspeed-2/portal/trunk/pom.xml (original)
> +++ portals/jetspeed-2/portal/trunk/pom.xml Fri Feb 25 07:45:03 2011
> @@ -277,7 +277,7 @@
>       <myfaces.version>1.1.5</myfaces.version>
>       <ojb.version>1.0.3</ojb.version>
>       <org.apache.derby.version>10.3.2.1</org.apache.derby.version>
> -<org.apache.pluto.version>2.0.3-SNAPSHOT</org.apache.pluto.version>
> +<org.apache.pluto.version>2.0.3-SNAPSHOT</org.apache.pluto.version>
>       <org.apache.portals.bridges.common.version>2.0</org.apache.portals.bridges.common.version>
>       <org.apache.portals.bridges.frameworks.version>1.0.4</org.apache.portals.bridges.frameworks.version>
>       <org.apache.portals.bridges.velocity.version>2.0</org.apache.portals.bridges.velocity.version>
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: jetspeed-dev-unsubscribe@portals.apache.org
> For additional commands, e-mail: jetspeed-dev-help@portals.apache.org
>
>


---------------------------------------------------------------------
To unsubscribe, e-mail: jetspeed-dev-unsubscribe@portals.apache.org
For additional commands, e-mail: jetspeed-dev-help@portals.apache.org