View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.jetspeed.portlet;
18  
19  import java.lang.reflect.InvocationHandler;
20  import java.lang.reflect.InvocationTargetException;
21  import java.lang.reflect.Method;
22  import java.lang.reflect.Proxy;
23  import java.lang.reflect.Modifier;
24  
25  import java.io.IOException;
26  
27  import javax.portlet.Portlet;
28  import javax.portlet.GenericPortlet;
29  import javax.portlet.PortletConfig;
30  import javax.portlet.PortletException;
31  import javax.portlet.PortletMode;
32  import javax.portlet.WindowState;
33  import javax.portlet.ActionRequest;
34  import javax.portlet.ActionResponse;
35  import javax.portlet.RenderRequest;
36  import javax.portlet.RenderResponse;
37  
38  import org.apache.pluto.om.portlet.PortletDefinition;
39  import org.apache.pluto.om.portlet.ContentTypeSet;
40  
41  import org.apache.jetspeed.JetspeedActions;
42  import org.apache.jetspeed.portlet.SupportsHeaderPhase;
43  import org.apache.jetspeed.util.BaseObjectProxy;
44  import org.apache.jetspeed.container.JetspeedPortletConfig;
45  
46  import javax.servlet.ServletConfig;
47  import javax.servlet.ServletContext;
48  import javax.portlet.UnavailableException;
49  import org.apache.jetspeed.Jetspeed;
50  import org.apache.jetspeed.components.portletregistry.PortletRegistry;
51  import org.apache.jetspeed.om.common.portlet.PortletDefinitionComposite;
52  import org.apache.jetspeed.om.common.portlet.MutablePortletApplication;
53  import org.apache.pluto.om.servlet.WebApplicationDefinition;
54  import org.apache.jetspeed.factory.PortletFactory;
55  import org.apache.jetspeed.factory.PortletInstance;
56  
57  /***
58   * PortletObjectProxy
59   * 
60   * @author <a href="mailto:woonsan@apache.org">Woonsan Ko</a>
61   * @version $Id: PortletObjectProxy.java 516448 2007-03-09 16:25:47Z ate $
62   */
63  public class PortletObjectProxy extends BaseObjectProxy
64  {
65      
66      private static ThreadLocal tlPortletObjectProxied =
67          new ThreadLocal() {
68              protected synchronized Object initialValue() {
69                  return new boolean [] { false };
70              }
71          };
72      
73      public static void setPortletObjectProxied(boolean portletObjectProxied)
74      {
75          ((boolean []) tlPortletObjectProxied.get())[0] = portletObjectProxied;
76      }
77          
78      public static boolean isPortletObjectProxied()
79      {
80          return ((boolean []) tlPortletObjectProxied.get())[0];
81      }
82      
83      private static Method renderMethod;
84      private static Method processActionMethod;
85      
86      static 
87      {
88      	try 
89          {
90              renderMethod = Portlet.class.getMethod("render", new Class [] { RenderRequest.class, RenderResponse.class });
91              processActionMethod = Portlet.class.getMethod("processAction", new Class [] { ActionRequest.class, ActionResponse.class });
92          } 
93          catch (NoSuchMethodException e) 
94          {
95      	    throw new NoSuchMethodError(e.getMessage());
96      	}
97      }
98      
99      private Object portletObject;
100     private PortletInstance customConfigModePortletInstance;
101     private boolean genericPortletInvocable;
102     private Method portletDoEditMethod;
103     private ContentTypeSet portletContentTypeSet;
104     private boolean autoSwitchEditDefaultsModeToEditMode;
105     private boolean autoSwitchConfigMode;
106     private String customConfigModePortletUniqueName;
107     
108     public static Object createProxy(Object proxiedObject, boolean autoSwitchEditDefaultsModeToEditMode, boolean autoSwitchConfigMode, String customConfigModePortletUniqueName)
109     {
110         Class proxiedClass = proxiedObject.getClass();
111         ClassLoader classLoader = proxiedClass.getClassLoader();
112         Class [] proxyInterfaces = null;
113         
114         if (proxiedObject instanceof SupportsHeaderPhase)
115         {
116             proxyInterfaces = new Class [] { Portlet.class, SupportsHeaderPhase.class };
117         }
118         else
119         {
120             proxyInterfaces = new Class [] { Portlet.class };
121         }
122         
123         InvocationHandler handler = new PortletObjectProxy(proxiedObject, autoSwitchEditDefaultsModeToEditMode, autoSwitchConfigMode, customConfigModePortletUniqueName);
124         return Proxy.newProxyInstance(classLoader, proxyInterfaces, handler);
125     }
126 
127     private PortletObjectProxy(Object portletObject, boolean autoSwitchEditDefaultsModeToEditMode, boolean autoSwitchConfigMode, String customConfigModePortletUniqueName)
128     {
129         this.portletObject = portletObject;
130         this.autoSwitchEditDefaultsModeToEditMode = autoSwitchEditDefaultsModeToEditMode;
131         this.autoSwitchConfigMode = autoSwitchConfigMode;
132         this.customConfigModePortletUniqueName = customConfigModePortletUniqueName;
133         
134         if (portletObject instanceof GenericPortlet)
135         {
136             try
137             {
138                 this.portletDoEditMethod = this.portletObject.getClass().getMethod("doEdit", new Class [] { RenderRequest.class, RenderResponse.class });
139                 
140                 if (Modifier.isPublic(this.portletDoEditMethod.getModifiers()))
141                 {
142                     this.genericPortletInvocable = true;
143                 }
144             }
145             catch (NoSuchMethodException e)
146             {
147             }
148         }
149     }
150 
151     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
152     {
153         Object result = null;
154         boolean handledHere = false;
155         Class declaringClass = method.getDeclaringClass();
156         
157         if (declaringClass == Portlet.class)
158         {
159             if (renderMethod.equals(method))
160             {
161                 proxyRender((RenderRequest) args[0], (RenderResponse) args[1]);
162                 return null;
163             }
164             else if (processActionMethod.equals(method))
165             {
166                 proxyProcessAction((ActionRequest) args[0], (ActionResponse) args[1]);
167             }
168             else
169             {
170                 result = method.invoke(this.portletObject, args);
171             }
172         }
173         else if (declaringClass == SupportsHeaderPhase.class)
174         {
175             result = method.invoke(this.portletObject, args);
176         }
177         else
178         {
179             result = super.invoke(proxy, method, args);
180         }
181         
182         return result;
183     }
184 
185     protected void proxyRender(RenderRequest request, RenderResponse response) throws PortletException, IOException, Exception
186     {
187         PortletMode mode = request.getPortletMode();
188         
189         boolean autoSwitchConfigMode = false;
190         boolean autoSwitchToEditMode = false;
191         
192         if (this.autoSwitchConfigMode && JetspeedActions.CONFIG_MODE.equals(mode))
193         {
194             autoSwitchConfigMode = true;
195         }
196         
197         if (this.autoSwitchEditDefaultsModeToEditMode && this.genericPortletInvocable)
198         {
199             if (JetspeedActions.EDIT_DEFAULTS_MODE.equals(mode))
200             {
201                 if (!isSupportingEditDefaultsMode((GenericPortlet) this.portletObject))
202                 {
203                     autoSwitchToEditMode = true;
204                 }
205             }
206         }
207         
208         if (autoSwitchConfigMode)
209         {
210             try
211             {
212                 if (this.customConfigModePortletInstance == null)
213                 {
214                     refreshCustomConfigModePortletInstance();
215                 }
216                 
217                 this.customConfigModePortletInstance.render(request, response);
218             }
219             catch (UnavailableException e)
220             {
221                 refreshCustomConfigModePortletInstance();
222                 this.customConfigModePortletInstance.render(request, response);
223             }
224         }
225         else if (autoSwitchToEditMode)
226         {
227             GenericPortlet genericPortlet = (GenericPortlet) this.portletObject;
228             
229             // Override GenericPortlet#render....
230             WindowState state = request.getWindowState();
231             
232             if (!WindowState.MINIMIZED.equals(state))
233             {
234                 String title = genericPortlet.getPortletConfig().getResourceBundle(request.getLocale()).getString("javax.portlet.title");
235                 response.setTitle(title);
236                 
237                 this.portletDoEditMethod.invoke(genericPortlet, new Object [] { request, response });
238             }
239         }
240         else
241         {
242             ((Portlet) this.portletObject).render(request, response);
243         }
244     }
245 
246     protected void proxyProcessAction(ActionRequest request, ActionResponse response) throws PortletException, IOException, Exception
247     {
248         PortletMode mode = request.getPortletMode();
249         
250         boolean autoSwitchConfigMode = false;
251         
252         if (this.autoSwitchConfigMode && JetspeedActions.CONFIG_MODE.equals(mode))
253         {
254             autoSwitchConfigMode = true;
255         }
256         
257         if (autoSwitchConfigMode)
258         {
259             try
260             {
261                 if (this.customConfigModePortletInstance == null)
262                 {
263                     refreshCustomConfigModePortletInstance();
264                 }
265                 
266                 this.customConfigModePortletInstance.processAction(request, response);
267             }
268             catch (UnavailableException e)
269             {
270                 refreshCustomConfigModePortletInstance();
271                 this.customConfigModePortletInstance.processAction(request, response);
272             }
273         }
274         else
275         {
276             ((Portlet) this.portletObject).processAction(request, response);
277         }
278     }
279     
280     private boolean isSupportingEditDefaultsMode(GenericPortlet portlet)
281     {
282         if (this.portletContentTypeSet == null)
283         {
284             try
285             {
286                 JetspeedPortletConfig config = (JetspeedPortletConfig) portlet.getPortletConfig();
287                 PortletDefinition portletDef = config.getPortletDefinition();
288                 this.portletContentTypeSet = portletDef.getContentTypeSet();
289             }
290             catch (Exception e)
291             {
292             }
293         }
294         
295         if (this.portletContentTypeSet != null)
296         {
297             return this.portletContentTypeSet.supportsPortletMode(JetspeedActions.EDIT_DEFAULTS_MODE);
298         }
299         
300         return false;
301     }
302        
303     private void refreshCustomConfigModePortletInstance()
304     {
305         try
306         {
307             PortletRegistry registry = (PortletRegistry) Jetspeed.getComponentManager().getComponent("portletRegistry");
308             PortletFactory portletFactory = (PortletFactory) Jetspeed.getComponentManager().getComponent("portletFactory");
309             ServletContext portalAppContext = ((ServletConfig) Jetspeed.getComponentManager().getComponent("ServletConfig")).getServletContext();
310             
311             PortletDefinitionComposite portletDef = (PortletDefinitionComposite) registry.getPortletDefinitionByUniqueName(this.customConfigModePortletUniqueName);
312             MutablePortletApplication portletApp = (MutablePortletApplication) portletDef.getPortletApplicationDefinition();
313             WebApplicationDefinition webAppDef = portletApp.getWebApplicationDefinition();
314             String portletAppName = webAppDef.getContextRoot();
315             ServletContext portletAppContext = portalAppContext.getContext(portletAppName);
316             
317             setPortletObjectProxied(true);
318             this.customConfigModePortletInstance = portletFactory.getPortletInstance(portletAppContext, portletDef);
319         }
320         catch (Exception e)
321         {
322         }
323         finally
324         {
325             setPortletObjectProxied(false);
326         }
327     }
328     
329 }