001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.jetspeed.portlet;
018:
019: import java.lang.reflect.InvocationHandler;
020: import java.lang.reflect.InvocationTargetException;
021: import java.lang.reflect.Method;
022: import java.lang.reflect.Proxy;
023: import java.lang.reflect.Modifier;
024:
025: import java.io.IOException;
026:
027: import javax.portlet.Portlet;
028: import javax.portlet.GenericPortlet;
029: import javax.portlet.PortletConfig;
030: import javax.portlet.PortletException;
031: import javax.portlet.PortletMode;
032: import javax.portlet.WindowState;
033: import javax.portlet.ActionRequest;
034: import javax.portlet.ActionResponse;
035: import javax.portlet.RenderRequest;
036: import javax.portlet.RenderResponse;
037:
038: import org.apache.pluto.om.portlet.PortletDefinition;
039: import org.apache.pluto.om.portlet.ContentTypeSet;
040:
041: import org.apache.jetspeed.JetspeedActions;
042: import org.apache.jetspeed.portlet.SupportsHeaderPhase;
043: import org.apache.jetspeed.util.BaseObjectProxy;
044: import org.apache.jetspeed.container.JetspeedPortletConfig;
045:
046: import javax.servlet.ServletConfig;
047: import javax.servlet.ServletContext;
048: import javax.portlet.UnavailableException;
049: import org.apache.jetspeed.Jetspeed;
050: import org.apache.jetspeed.components.portletregistry.PortletRegistry;
051: import org.apache.jetspeed.om.common.portlet.PortletDefinitionComposite;
052: import org.apache.jetspeed.om.common.portlet.MutablePortletApplication;
053: import org.apache.pluto.om.servlet.WebApplicationDefinition;
054: import org.apache.jetspeed.factory.PortletFactory;
055: import org.apache.jetspeed.factory.PortletInstance;
056:
057: /**
058: * PortletObjectProxy
059: *
060: * @author <a href="mailto:woonsan@apache.org">Woonsan Ko</a>
061: * @version $Id: PortletObjectProxy.java 516448 2007-03-09 16:25:47Z ate $
062: */
063: public class PortletObjectProxy extends BaseObjectProxy {
064:
065: private static ThreadLocal tlPortletObjectProxied = new ThreadLocal() {
066: protected synchronized Object initialValue() {
067: return new boolean[] { false };
068: }
069: };
070:
071: public static void setPortletObjectProxied(
072: boolean portletObjectProxied) {
073: ((boolean[]) tlPortletObjectProxied.get())[0] = portletObjectProxied;
074: }
075:
076: public static boolean isPortletObjectProxied() {
077: return ((boolean[]) tlPortletObjectProxied.get())[0];
078: }
079:
080: private static Method renderMethod;
081: private static Method processActionMethod;
082:
083: static {
084: try {
085: renderMethod = Portlet.class.getMethod("render",
086: new Class[] { RenderRequest.class,
087: RenderResponse.class });
088: processActionMethod = Portlet.class.getMethod(
089: "processAction", new Class[] { ActionRequest.class,
090: ActionResponse.class });
091: } catch (NoSuchMethodException e) {
092: throw new NoSuchMethodError(e.getMessage());
093: }
094: }
095:
096: private Object portletObject;
097: private PortletInstance customConfigModePortletInstance;
098: private boolean genericPortletInvocable;
099: private Method portletDoEditMethod;
100: private ContentTypeSet portletContentTypeSet;
101: private boolean autoSwitchEditDefaultsModeToEditMode;
102: private boolean autoSwitchConfigMode;
103: private String customConfigModePortletUniqueName;
104:
105: public static Object createProxy(Object proxiedObject,
106: boolean autoSwitchEditDefaultsModeToEditMode,
107: boolean autoSwitchConfigMode,
108: String customConfigModePortletUniqueName) {
109: Class proxiedClass = proxiedObject.getClass();
110: ClassLoader classLoader = proxiedClass.getClassLoader();
111: Class[] proxyInterfaces = null;
112:
113: if (proxiedObject instanceof SupportsHeaderPhase) {
114: proxyInterfaces = new Class[] { Portlet.class,
115: SupportsHeaderPhase.class };
116: } else {
117: proxyInterfaces = new Class[] { Portlet.class };
118: }
119:
120: InvocationHandler handler = new PortletObjectProxy(
121: proxiedObject, autoSwitchEditDefaultsModeToEditMode,
122: autoSwitchConfigMode, customConfigModePortletUniqueName);
123: return Proxy.newProxyInstance(classLoader, proxyInterfaces,
124: handler);
125: }
126:
127: private PortletObjectProxy(Object portletObject,
128: boolean autoSwitchEditDefaultsModeToEditMode,
129: boolean autoSwitchConfigMode,
130: String customConfigModePortletUniqueName) {
131: this .portletObject = portletObject;
132: this .autoSwitchEditDefaultsModeToEditMode = autoSwitchEditDefaultsModeToEditMode;
133: this .autoSwitchConfigMode = autoSwitchConfigMode;
134: this .customConfigModePortletUniqueName = customConfigModePortletUniqueName;
135:
136: if (portletObject instanceof GenericPortlet) {
137: try {
138: this .portletDoEditMethod = this .portletObject
139: .getClass().getMethod(
140: "doEdit",
141: new Class[] { RenderRequest.class,
142: RenderResponse.class });
143:
144: if (Modifier.isPublic(this .portletDoEditMethod
145: .getModifiers())) {
146: this .genericPortletInvocable = true;
147: }
148: } catch (NoSuchMethodException e) {
149: }
150: }
151: }
152:
153: public Object invoke(Object proxy, Method method, Object[] args)
154: throws Throwable {
155: Object result = null;
156: boolean handledHere = false;
157: Class declaringClass = method.getDeclaringClass();
158:
159: if (declaringClass == Portlet.class) {
160: if (renderMethod.equals(method)) {
161: proxyRender((RenderRequest) args[0],
162: (RenderResponse) args[1]);
163: return null;
164: } else if (processActionMethod.equals(method)) {
165: proxyProcessAction((ActionRequest) args[0],
166: (ActionResponse) args[1]);
167: } else {
168: result = method.invoke(this .portletObject, args);
169: }
170: } else if (declaringClass == SupportsHeaderPhase.class) {
171: result = method.invoke(this .portletObject, args);
172: } else {
173: result = super .invoke(proxy, method, args);
174: }
175:
176: return result;
177: }
178:
179: protected void proxyRender(RenderRequest request,
180: RenderResponse response) throws PortletException,
181: IOException, Exception {
182: PortletMode mode = request.getPortletMode();
183:
184: boolean autoSwitchConfigMode = false;
185: boolean autoSwitchToEditMode = false;
186:
187: if (this .autoSwitchConfigMode
188: && JetspeedActions.CONFIG_MODE.equals(mode)) {
189: autoSwitchConfigMode = true;
190: }
191:
192: if (this .autoSwitchEditDefaultsModeToEditMode
193: && this .genericPortletInvocable) {
194: if (JetspeedActions.EDIT_DEFAULTS_MODE.equals(mode)) {
195: if (!isSupportingEditDefaultsMode((GenericPortlet) this .portletObject)) {
196: autoSwitchToEditMode = true;
197: }
198: }
199: }
200:
201: if (autoSwitchConfigMode) {
202: try {
203: if (this .customConfigModePortletInstance == null) {
204: refreshCustomConfigModePortletInstance();
205: }
206:
207: this .customConfigModePortletInstance.render(request,
208: response);
209: } catch (UnavailableException e) {
210: refreshCustomConfigModePortletInstance();
211: this .customConfigModePortletInstance.render(request,
212: response);
213: }
214: } else if (autoSwitchToEditMode) {
215: GenericPortlet genericPortlet = (GenericPortlet) this .portletObject;
216:
217: // Override GenericPortlet#render....
218: WindowState state = request.getWindowState();
219:
220: if (!WindowState.MINIMIZED.equals(state)) {
221: String title = genericPortlet.getPortletConfig()
222: .getResourceBundle(request.getLocale())
223: .getString("javax.portlet.title");
224: response.setTitle(title);
225:
226: this .portletDoEditMethod.invoke(genericPortlet,
227: new Object[] { request, response });
228: }
229: } else {
230: ((Portlet) this .portletObject).render(request, response);
231: }
232: }
233:
234: protected void proxyProcessAction(ActionRequest request,
235: ActionResponse response) throws PortletException,
236: IOException, Exception {
237: PortletMode mode = request.getPortletMode();
238:
239: boolean autoSwitchConfigMode = false;
240:
241: if (this .autoSwitchConfigMode
242: && JetspeedActions.CONFIG_MODE.equals(mode)) {
243: autoSwitchConfigMode = true;
244: }
245:
246: if (autoSwitchConfigMode) {
247: try {
248: if (this .customConfigModePortletInstance == null) {
249: refreshCustomConfigModePortletInstance();
250: }
251:
252: this .customConfigModePortletInstance.processAction(
253: request, response);
254: } catch (UnavailableException e) {
255: refreshCustomConfigModePortletInstance();
256: this .customConfigModePortletInstance.processAction(
257: request, response);
258: }
259: } else {
260: ((Portlet) this .portletObject).processAction(request,
261: response);
262: }
263: }
264:
265: private boolean isSupportingEditDefaultsMode(GenericPortlet portlet) {
266: if (this .portletContentTypeSet == null) {
267: try {
268: JetspeedPortletConfig config = (JetspeedPortletConfig) portlet
269: .getPortletConfig();
270: PortletDefinition portletDef = config
271: .getPortletDefinition();
272: this .portletContentTypeSet = portletDef
273: .getContentTypeSet();
274: } catch (Exception e) {
275: }
276: }
277:
278: if (this .portletContentTypeSet != null) {
279: return this .portletContentTypeSet
280: .supportsPortletMode(JetspeedActions.EDIT_DEFAULTS_MODE);
281: }
282:
283: return false;
284: }
285:
286: private void refreshCustomConfigModePortletInstance() {
287: try {
288: PortletRegistry registry = (PortletRegistry) Jetspeed
289: .getComponentManager().getComponent(
290: "portletRegistry");
291: PortletFactory portletFactory = (PortletFactory) Jetspeed
292: .getComponentManager().getComponent(
293: "portletFactory");
294: ServletContext portalAppContext = ((ServletConfig) Jetspeed
295: .getComponentManager()
296: .getComponent("ServletConfig")).getServletContext();
297:
298: PortletDefinitionComposite portletDef = (PortletDefinitionComposite) registry
299: .getPortletDefinitionByUniqueName(this .customConfigModePortletUniqueName);
300: MutablePortletApplication portletApp = (MutablePortletApplication) portletDef
301: .getPortletApplicationDefinition();
302: WebApplicationDefinition webAppDef = portletApp
303: .getWebApplicationDefinition();
304: String portletAppName = webAppDef.getContextRoot();
305: ServletContext portletAppContext = portalAppContext
306: .getContext(portletAppName);
307:
308: setPortletObjectProxied(true);
309: this .customConfigModePortletInstance = portletFactory
310: .getPortletInstance(portletAppContext, portletDef);
311: } catch (Exception e) {
312: } finally {
313: setPortletObjectProxied(false);
314: }
315: }
316:
317: }
|