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 wo...@apache.org on 2007/10/02 17:49:53 UTC

svn commit: r581285 - in /portals/jetspeed-2/branches/JETSPEED-2.1.3: commons/src/java/org/apache/jetspeed/portlet/ commons/src/java/org/apache/jetspeed/util/ components/portal/src/java/org/apache/jetspeed/decoration/ components/portlet-factory/src/jav...

Author: woonsan
Date: Tue Oct  2 08:49:52 2007
New Revision: 581285

URL: http://svn.apache.org/viewvc?rev=581285&view=rev
Log:
[JS2-634] More advanced feature added:
If a portlet does not support edit_defaults mode, but it supports edit mode, then Jetspeed can optionally provide automatic dispatching to doEdit() when the current portlet mode is edit_defaults.

To enable this option:

 a) Set *autoSwitchingToEditDefaultsModes* to true for decorationValve in pipelines.xml like the following:

     <property name="autoSwitchingToEditDefaultsModes"><value>true</value></property>

 b) Set the first constructor arg to true for portletFactory bean in registry.xml like the following:

    <bean id="portletFactory" class="org.apache.jetspeed.factory.JetspeedPortletFactory">
        <!--
        If the following argument is true, then this factory will create proxy instances for actual portlet instances. 
        Proxy instances will switch edit_defaults mode to edit mode automatically for portlets not supporting edit_defaults mode.
        -->
        <constructor-arg index="0">
            <value>false</value>
        </constructor-arg>
    </bean>

Limitations or Assumptions:
 a) If the doEdit() method of a portlet is not public, then the system will not provide auto-dispatching for the portlet with no error.
 b) If a portlet provide edit_defaults mode, then the system will not provide auto-dispatching. Instead, it will hand over rendering to the portlet.

Added:
    portals/jetspeed-2/branches/JETSPEED-2.1.3/commons/src/java/org/apache/jetspeed/portlet/PortletObjectProxy.java
    portals/jetspeed-2/branches/JETSPEED-2.1.3/commons/src/java/org/apache/jetspeed/util/BaseObjectProxy.java
    portals/jetspeed-2/branches/JETSPEED-2.1.3/components/portlet-factory/src/java/org/apache/jetspeed/factory/JetspeedPortletProxyInstance.java
Modified:
    portals/jetspeed-2/branches/JETSPEED-2.1.3/components/portal/src/java/org/apache/jetspeed/decoration/DecorationValve.java
    portals/jetspeed-2/branches/JETSPEED-2.1.3/components/portlet-factory/src/java/org/apache/jetspeed/factory/JetspeedPortletFactory.java
    portals/jetspeed-2/branches/JETSPEED-2.1.3/src/webapp/WEB-INF/assembly/pipelines.xml
    portals/jetspeed-2/branches/JETSPEED-2.1.3/src/webapp/WEB-INF/assembly/registry.xml

Added: portals/jetspeed-2/branches/JETSPEED-2.1.3/commons/src/java/org/apache/jetspeed/portlet/PortletObjectProxy.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/branches/JETSPEED-2.1.3/commons/src/java/org/apache/jetspeed/portlet/PortletObjectProxy.java?rev=581285&view=auto
==============================================================================
--- portals/jetspeed-2/branches/JETSPEED-2.1.3/commons/src/java/org/apache/jetspeed/portlet/PortletObjectProxy.java (added)
+++ portals/jetspeed-2/branches/JETSPEED-2.1.3/commons/src/java/org/apache/jetspeed/portlet/PortletObjectProxy.java Tue Oct  2 08:49:52 2007
@@ -0,0 +1,193 @@
+/*
+ * 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.portlet;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.Modifier;
+
+import java.io.IOException;
+
+import javax.portlet.Portlet;
+import javax.portlet.GenericPortlet;
+import javax.portlet.PortletConfig;
+import javax.portlet.PortletException;
+import javax.portlet.PortletMode;
+import javax.portlet.WindowState;
+import javax.portlet.ActionRequest;
+import javax.portlet.ActionResponse;
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+
+import org.apache.pluto.om.portlet.PortletDefinition;
+import org.apache.pluto.om.portlet.ContentTypeSet;
+
+import org.apache.jetspeed.JetspeedActions;
+import org.apache.jetspeed.util.BaseObjectProxy;
+import org.apache.jetspeed.container.JetspeedPortletConfig;
+
+/**
+ * PortletObjectProxy
+ * 
+ * @author <a href="mailto:woonsan@apache.org">Woonsan Ko</a>
+ * @version $Id: PortletObjectProxy.java 516448 2007-03-09 16:25:47Z ate $
+ */
+public class PortletObjectProxy extends BaseObjectProxy
+{
+
+    private static Method renderMethod;
+    
+    static 
+    {
+    	try 
+        {
+            renderMethod = Portlet.class.getMethod("render", new Class [] { RenderRequest.class, RenderResponse.class });
+        } 
+        catch (NoSuchMethodException e) 
+        {
+    	    throw new NoSuchMethodError(e.getMessage());
+    	}
+    }
+    
+    private Object portletObject;
+    private boolean genericPortletInvocable;
+    private Method portletDoEditMethod;
+    private ContentTypeSet portletContentTypeSet;
+    
+    public static Object createProxy(Object proxiedObject)
+    {
+        Class proxiedClass = proxiedObject.getClass();
+        ClassLoader classLoader = proxiedClass.getClassLoader();
+        Class [] proxyInterfaces = new Class [] { Portlet.class };
+        InvocationHandler handler = new PortletObjectProxy(proxiedObject);
+        return Proxy.newProxyInstance(classLoader, proxyInterfaces, handler);
+    }
+
+    private PortletObjectProxy(Object portletObject)
+    {
+        this.portletObject = portletObject;
+        
+        if (portletObject instanceof GenericPortlet)
+        {
+            try
+            {
+                this.portletDoEditMethod = this.portletObject.getClass().getMethod("doEdit", new Class [] { RenderRequest.class, RenderResponse.class });
+                
+                if (Modifier.isPublic(this.portletDoEditMethod.getModifiers()))
+                {
+                    this.genericPortletInvocable = true;
+                }
+            }
+            catch (NoSuchMethodException e)
+            {
+            }
+        }
+        else
+        {
+            System.out.println("!!!!! not generic portlet: " + this.portletObject);
+        }
+    }
+
+    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
+    {
+        Object result = null;
+        boolean handledHere = false;
+        Class declaringClass = method.getDeclaringClass();
+        
+        if (declaringClass == Portlet.class)
+        {
+            if (renderMethod.equals(method))
+            {
+                proxyRender((RenderRequest) args[0], (RenderResponse) args[1]);
+                return null;
+            }
+            else
+            {
+                result = method.invoke(this.portletObject, args);
+            }
+        }
+        else
+        {
+            result = super.invoke(proxy, method, args);
+        }
+        
+        return result;
+    }
+
+    protected void proxyRender(RenderRequest request, RenderResponse response) throws PortletException, IOException, Exception
+    {
+        boolean autoSwitchToEditMode = false;
+        
+        if (this.genericPortletInvocable)
+        {
+            PortletMode mode = request.getPortletMode();
+            
+            if (JetspeedActions.EDIT_DEFAULTS_MODE.equals(mode))
+            {
+                if (!isSupportingEditDefaultsMode((GenericPortlet) this.portletObject))
+                {
+                    autoSwitchToEditMode = true;
+                }
+            }
+        }
+        
+        if (autoSwitchToEditMode)
+        {
+            GenericPortlet genericPortlet = (GenericPortlet) this.portletObject;
+            
+            // Override GenericPortlet#render....
+            WindowState state = request.getWindowState();
+            
+            if (!WindowState.MINIMIZED.equals(state))
+            {
+                String title = genericPortlet.getPortletConfig().getResourceBundle(request.getLocale()).getString("javax.portlet.title");
+                response.setTitle(title);
+                
+                this.portletDoEditMethod.invoke(genericPortlet, new Object [] { request, response });
+            }
+        }
+        else
+        {
+            ((Portlet) this.portletObject).render(request, response);
+        }
+    }
+    
+    private boolean isSupportingEditDefaultsMode(GenericPortlet portlet)
+    {
+        if (this.portletContentTypeSet == null)
+        {
+            try
+            {
+                JetspeedPortletConfig config = (JetspeedPortletConfig) portlet.getPortletConfig();
+                PortletDefinition portletDef = config.getPortletDefinition();
+                this.portletContentTypeSet = portletDef.getContentTypeSet();
+            }
+            catch (Exception e)
+            {
+            }
+        }
+        
+        if (this.portletContentTypeSet != null)
+        {
+            return this.portletContentTypeSet.supportsPortletMode(JetspeedActions.EDIT_DEFAULTS_MODE);
+        }
+        
+        return false;
+    }
+}

Added: portals/jetspeed-2/branches/JETSPEED-2.1.3/commons/src/java/org/apache/jetspeed/util/BaseObjectProxy.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/branches/JETSPEED-2.1.3/commons/src/java/org/apache/jetspeed/util/BaseObjectProxy.java?rev=581285&view=auto
==============================================================================
--- portals/jetspeed-2/branches/JETSPEED-2.1.3/commons/src/java/org/apache/jetspeed/util/BaseObjectProxy.java (added)
+++ portals/jetspeed-2/branches/JETSPEED-2.1.3/commons/src/java/org/apache/jetspeed/util/BaseObjectProxy.java Tue Oct  2 08:49:52 2007
@@ -0,0 +1,96 @@
+/*
+ * 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;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+/**
+ * BaseObjectProxy
+ * 
+ * @author <a href="mailto:woonsan@apache.org">Woonsan Ko</a>
+ * @version $Id: BaseObjectProxy.java 516448 2007-03-09 16:25:47Z ate $
+ */
+public class BaseObjectProxy implements InvocationHandler 
+{
+
+    protected static Method hashCodeMethod;
+    protected static Method equalsMethod;
+    protected static Method toStringMethod;
+    
+    static 
+    {
+    	try 
+        {
+    	    hashCodeMethod = Object.class.getMethod("hashCode", null);
+    	    equalsMethod = Object.class.getMethod("equals", new Class [] { Object.class });
+    	    toStringMethod = Object.class.getMethod("toString", null);
+        } 
+        catch (NoSuchMethodException e) 
+        {
+    	    throw new NoSuchMethodError(e.getMessage());
+    	}
+    }
+    
+    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
+    {
+        Object result = null;
+    	Class declaringClass = method.getDeclaringClass();
+
+    	if (declaringClass == Object.class) 
+        {
+    	    if (hashCodeMethod.equals(method)) 
+            {
+                result = proxyHashCode(proxy);
+    	    } 
+            else if (equalsMethod.equals(method)) 
+            {
+                result = proxyEquals(proxy, args[0]);
+    	    } 
+            else if (toStringMethod.equals(method)) 
+            {
+                result = proxyToString(proxy);
+    	    } 
+            else 
+            {
+                throw new InternalError("unexpected Object method dispatched: " + method);
+    	    }
+    	}
+        else
+        {
+            throw new InternalError("unexpected Object method dispatched: " + method);
+        }
+        
+        return result;
+    }
+    
+    protected Integer proxyHashCode(Object proxy) 
+    {
+    	return new Integer(System.identityHashCode(proxy));
+    }
+
+    protected Boolean proxyEquals(Object proxy, Object other) 
+    {
+    	return (proxy == other ? Boolean.TRUE : Boolean.FALSE);
+    }
+
+    protected String proxyToString(Object proxy) 
+    {
+    	return proxy.getClass().getName() + '@' + Integer.toHexString(proxy.hashCode());
+    }
+
+}

Modified: portals/jetspeed-2/branches/JETSPEED-2.1.3/components/portal/src/java/org/apache/jetspeed/decoration/DecorationValve.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/branches/JETSPEED-2.1.3/components/portal/src/java/org/apache/jetspeed/decoration/DecorationValve.java?rev=581285&r1=581284&r2=581285&view=diff
==============================================================================
--- portals/jetspeed-2/branches/JETSPEED-2.1.3/components/portal/src/java/org/apache/jetspeed/decoration/DecorationValve.java (original)
+++ portals/jetspeed-2/branches/JETSPEED-2.1.3/components/portal/src/java/org/apache/jetspeed/decoration/DecorationValve.java Tue Oct  2 08:49:52 2007
@@ -88,6 +88,8 @@
     private boolean useSessionForThemeCaching = false;
     
     private boolean maxOnEdit = false;
+    
+    private boolean autoSwitchingToEditDefaultsModes = true;
          
      /**
       * For security constraint checks
@@ -386,7 +388,7 @@
                         }
                         if ( ! equalsCurrentMode || isAjaxRequest )
                         {
-                            if ( content.supportsPortletMode(customMode) 
+                            if ( (content.supportsPortletMode(customMode) || isAutoSwitchableCustomMode(customMode))
                                  && (!PortletMode.EDIT.equals(customMode) || pageActionAccess.isEditAllowed())
                                  && pageActionAccess.checkPortletMode(fragmentId, portletName, mappedMode)
                                  )
@@ -632,5 +634,28 @@
     public boolean getMaximizeOnEdit()
     {
         return this.maxOnEdit;
+    }
+    
+    public void setAutoSwitchingToEditDefaultsModes(boolean autoSwitchingToEditDefaultsModes)
+    {
+        this.autoSwitchingToEditDefaultsModes = autoSwitchingToEditDefaultsModes;
+    }
+    
+    public boolean getAutoSwitchingToEditDefaultsModes()
+    {
+        return this.autoSwitchingToEditDefaultsModes;
+    }
+    
+    private boolean isAutoSwitchableCustomMode(PortletMode customMode)
+    {
+        if (this.autoSwitchingToEditDefaultsModes)
+        {
+            if (JetspeedActions.EDIT_DEFAULTS_MODE.equals(customMode))
+            {
+                return true;
+            }
+        }
+        
+        return false;
     }
 }

Modified: portals/jetspeed-2/branches/JETSPEED-2.1.3/components/portlet-factory/src/java/org/apache/jetspeed/factory/JetspeedPortletFactory.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/branches/JETSPEED-2.1.3/components/portlet-factory/src/java/org/apache/jetspeed/factory/JetspeedPortletFactory.java?rev=581285&r1=581284&r2=581285&view=diff
==============================================================================
--- portals/jetspeed-2/branches/JETSPEED-2.1.3/components/portlet-factory/src/java/org/apache/jetspeed/factory/JetspeedPortletFactory.java (original)
+++ portals/jetspeed-2/branches/JETSPEED-2.1.3/components/portlet-factory/src/java/org/apache/jetspeed/factory/JetspeedPortletFactory.java Tue Oct  2 08:49:52 2007
@@ -56,15 +56,24 @@
     
     private static final Log log = LogFactory.getLog(JetspeedPortletFactory.class);
     private final Map classLoaderMap;
+    
+    private boolean portletProxyUsed = false;
 
     /**
      * 
      */
     public JetspeedPortletFactory()
     {
+        this(false);
+    }
+    
+    public JetspeedPortletFactory(boolean portletProxyUsed)
+    {
         this.portletCache =  Collections.synchronizedMap(new HashMap());
         this.validatorCache = Collections.synchronizedMap(new HashMap());
         classLoaderMap = Collections.synchronizedMap(new HashMap());
+        
+        this.portletProxyUsed = portletProxyUsed;
     }
 
     public void registerPortletApplication(PortletApplication pa, ClassLoader cl)
@@ -205,7 +214,15 @@
                 // wrap new Portlet inside PortletInstance which ensures the destroy
                 // method will wait for all its invocation threads to complete
                 // and thereby releasing all its ClassLoader locks as needed for local portlets.
-                portlet = new JetspeedPortletInstance(pd.getName(), (Portlet)clazz.newInstance());
+                
+                if (this.portletProxyUsed)
+                {
+                    portlet = new JetspeedPortletProxyInstance(pd.getName(), (Portlet)clazz.newInstance());
+                }
+                else
+                {
+                    portlet = new JetspeedPortletInstance(pd.getName(), (Portlet)clazz.newInstance());
+                }
             }
               finally
             {

Added: portals/jetspeed-2/branches/JETSPEED-2.1.3/components/portlet-factory/src/java/org/apache/jetspeed/factory/JetspeedPortletProxyInstance.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/branches/JETSPEED-2.1.3/components/portlet-factory/src/java/org/apache/jetspeed/factory/JetspeedPortletProxyInstance.java?rev=581285&view=auto
==============================================================================
--- portals/jetspeed-2/branches/JETSPEED-2.1.3/components/portlet-factory/src/java/org/apache/jetspeed/factory/JetspeedPortletProxyInstance.java (added)
+++ portals/jetspeed-2/branches/JETSPEED-2.1.3/components/portlet-factory/src/java/org/apache/jetspeed/factory/JetspeedPortletProxyInstance.java Tue Oct  2 08:49:52 2007
@@ -0,0 +1,36 @@
+/*
+ * 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.factory;
+
+import javax.portlet.Portlet;
+
+import org.apache.jetspeed.portlet.PortletObjectProxy;
+
+/**
+ * JetspeedPortletProxyInstance
+ * 
+ * @author <a href="mailto:woonsan@apache.org">Woonsan Ko</a>
+ * @version $Id: JetspeedPortletProxyInstance.java 516448 2007-03-09 16:25:47Z ate $
+ *
+ */
+public class JetspeedPortletProxyInstance extends JetspeedPortletInstance
+{
+    public JetspeedPortletProxyInstance(String portletName, Portlet portlet)
+    {
+        super(portletName, (Portlet) PortletObjectProxy.createProxy(portlet));
+    }
+}

Modified: portals/jetspeed-2/branches/JETSPEED-2.1.3/src/webapp/WEB-INF/assembly/pipelines.xml
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/branches/JETSPEED-2.1.3/src/webapp/WEB-INF/assembly/pipelines.xml?rev=581285&r1=581284&r2=581285&view=diff
==============================================================================
--- portals/jetspeed-2/branches/JETSPEED-2.1.3/src/webapp/WEB-INF/assembly/pipelines.xml (original)
+++ portals/jetspeed-2/branches/JETSPEED-2.1.3/src/webapp/WEB-INF/assembly/pipelines.xml Tue Oct  2 08:49:52 2007
@@ -323,6 +323,7 @@
          -->
          <!-- When clicking on Edit Mode, also switch to Maximize -->
         <property name="maximizeOnEdit"><value>false</value></property>         
+        <property name="autoSwitchingToEditDefaultsModes"><value>false</value></property>
   </bean>
 
   <bean id="loginViewValve"

Modified: portals/jetspeed-2/branches/JETSPEED-2.1.3/src/webapp/WEB-INF/assembly/registry.xml
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/branches/JETSPEED-2.1.3/src/webapp/WEB-INF/assembly/registry.xml?rev=581285&r1=581284&r2=581285&view=diff
==============================================================================
--- portals/jetspeed-2/branches/JETSPEED-2.1.3/src/webapp/WEB-INF/assembly/registry.xml (original)
+++ portals/jetspeed-2/branches/JETSPEED-2.1.3/src/webapp/WEB-INF/assembly/registry.xml Tue Oct  2 08:49:52 2007
@@ -19,7 +19,15 @@
 <beans>
 
     <!-- Portlet Factory -->
-    <bean id="portletFactory" class="org.apache.jetspeed.factory.JetspeedPortletFactory"></bean>
+    <bean id="portletFactory" class="org.apache.jetspeed.factory.JetspeedPortletFactory">
+        <!--
+        If the following argument is true, then this factory will create proxy instances for actual portlet instances. 
+        Proxy instances will switch edit_defaults mode to edit mode automatically for portlets not supporting edit_defaults mode.
+        -->
+        <constructor-arg index="0">
+            <value>false</value>
+        </constructor-arg>
+    </bean>
 
     <!-- Portlet Registry DAO-->
     <bean id="portletRegistryImpl" class="org.apache.jetspeed.components.portletregistry.PersistenceBrokerPortletRegistry" init-method="init">



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