1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
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 }