001: /******************************************************************************
002: * JBoss, a division of Red Hat *
003: * Copyright 2006, Red Hat Middleware, LLC, and individual *
004: * contributors as indicated by the @authors tag. See the *
005: * copyright.txt in the distribution for a full listing of *
006: * individual contributors. *
007: * *
008: * This is free software; you can redistribute it and/or modify it *
009: * under the terms of the GNU Lesser General Public License as *
010: * published by the Free Software Foundation; either version 2.1 of *
011: * the License, or (at your option) any later version. *
012: * *
013: * This software is distributed in the hope that it will be useful, *
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of *
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
016: * Lesser General Public License for more details. *
017: * *
018: * You should have received a copy of the GNU Lesser General Public *
019: * License along with this software; if not, write to the Free *
020: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
021: * 02110-1301 USA, or see the FSF site: http://www.fsf.org. *
022: ******************************************************************************/package org.jboss.portlet;
023:
024: import org.jboss.portal.format.util.EntityTable;
025:
026: import javax.portlet.ActionRequest;
027: import javax.portlet.ActionResponse;
028: import javax.portlet.Portlet;
029: import javax.portlet.PortletConfig;
030: import javax.portlet.PortletContext;
031: import javax.portlet.PortletException;
032: import javax.portlet.PortletMode;
033: import javax.portlet.PortletPreferences;
034: import javax.portlet.PortletSecurityException;
035: import javax.portlet.PortletURL;
036: import javax.portlet.RenderRequest;
037: import javax.portlet.RenderResponse;
038: import javax.portlet.WindowState;
039: import java.io.IOException;
040: import java.io.PrintWriter;
041: import java.lang.reflect.InvocationTargetException;
042: import java.lang.reflect.Method;
043: import java.lang.reflect.Modifier;
044: import java.util.Enumeration;
045: import java.util.Iterator;
046: import java.util.Locale;
047: import java.util.Map;
048: import java.util.ResourceBundle;
049:
050: /**
051: * The JBossPortlet.
052: *
053: * @author <a href="mailto:julien@jboss.org">Julien Viet</a>
054: * @version $Revision: 8786 $
055: */
056: public class JBossPortlet implements Portlet {
057:
058: /** . */
059: private static final Class[] ACTION_LOOKUP = new Class[] {
060: JBossActionRequest.class, JBossActionResponse.class };
061:
062: /** . */
063: private static final PortletMode ADMIN = new PortletMode("admin");
064:
065: /** . */
066: private PortletConfig config;
067:
068: public JBossPortlet() {
069: }
070:
071: /** Return the string <i>main</i>, it can be overriden to return another value by subclasses. */
072: public String getDefaultOperation() {
073: return "main";
074: }
075:
076: /** Return the string <i>op</i>, it can be overriden to return another value by subclasses. */
077: public String getOperationName() {
078: return "op";
079: }
080:
081: public void init() throws PortletException {
082: }
083:
084: public PortletConfig getPortletConfig() {
085: return config;
086: }
087:
088: public String getPortletName() {
089: return config.getPortletName();
090: }
091:
092: public PortletContext getPortletContext() {
093: return config.getPortletContext();
094: }
095:
096: /** Calls <code>doDispatch(JBossActionRequest,JBossActionResponse)</code>. */
097: protected void processAction(JBossActionRequest req,
098: JBossActionResponse resp) throws PortletException,
099: PortletSecurityException, IOException {
100: processDispatch(req, resp);
101: }
102:
103: /**
104: * <p>This method looks up the method corresponding to the action. It uses the action parameter using the parameter
105: * name defines by the <code>operationName</code> field of this class. If not method is found it uses the method
106: * defined by the return of the method <code>getDefaultOperation()</code> of this class. In order to be found a
107: * method must use <code>JBossActionRequest</code> and <JBossActionResponse> in the signature.</p> <p/> <p>If not
108: * valid dispatcher is found it throws a PortletException, otherwise it invokes the method by reflection. The invoked
109: * method may declare exceptions in the throws clause of the method. Whenever an exception is raised during the
110: * invocation of the method, a decision is taken depending on the nature of the exception :</p>
111: * <p/>
112: * <ul> <li>If the exception is an instanceof <code>PortletException</code>, <code>IOException</code> then this
113: * exception is rethrown as is since this method declares them in its throws clause</li> <li>If the exception is an
114: * instance of <code>RuntimeException</code> or <code>Error>/code>, it is rethrown as is</li> <li>Otherwise a
115: * <code>PortletException</code> is created with the caught exception as cause and thrown</li> </ul>
116: */
117: protected void processDispatch(JBossActionRequest req,
118: JBossActionResponse resp) throws PortletException,
119: PortletSecurityException, IOException {
120: PortletMode portletMode = req.getPortletMode();
121: if (PortletMode.VIEW.equals(portletMode)) {
122: processView(req, resp);
123: } else if (PortletMode.HELP.equals(portletMode)) {
124: processHelp(req, resp);
125: } else if (PortletMode.EDIT.equals(portletMode)) {
126: processEdit(req, resp);
127: } else if (ADMIN.equals(portletMode)) {
128: processAdmin(req, resp);
129: }
130: }
131:
132: /** Default doEdit method that works in coordination with doEdit(JBossRenderRequest,JBossRenderResponse). */
133: public void processEdit(JBossActionRequest req,
134: JBossActionResponse resp) throws PortletException,
135: PortletSecurityException, IOException {
136: PortletPreferences prefs = req.getPreferences();
137: Map map = prefs.getMap();
138: for (Iterator i = req.getParameterMap().entrySet().iterator(); i
139: .hasNext();) {
140: Map.Entry entry = (Map.Entry) i.next();
141: String name = (String) entry.getKey();
142: String[] values = (String[]) entry.getValue();
143: if (map.containsKey(name)) {
144: prefs.setValues(name, values);
145: }
146: }
147: prefs.store();
148: }
149:
150: /**
151: *
152: */
153: public void processHelp(JBossActionRequest req,
154: JBossActionResponse resp) throws PortletException,
155: PortletSecurityException, IOException {
156: throw new PortletException();
157: }
158:
159: /**
160: *
161: */
162: public void processAdmin(JBossActionRequest req,
163: JBossActionResponse resp) throws PortletException,
164: PortletSecurityException, IOException {
165: throw new PortletException();
166: }
167:
168: /**
169: *
170: */
171: public void processView(JBossActionRequest req,
172: JBossActionResponse resp) throws PortletException,
173: PortletSecurityException, IOException {
174: // Try to locate specific operation
175: Method dispatcher = null;
176: String operation = req.getParameter(getOperationName());
177: if (operation != null) {
178: dispatcher = lookupMethod(operation, ACTION_LOOKUP);
179: }
180:
181: // If it null try to getPortalObjectContext the default operation
182: if (dispatcher == null) {
183: dispatcher = lookupMethod(getDefaultOperation(),
184: ACTION_LOOKUP);
185: }
186:
187: // Invoke the operation
188: if (dispatcher != null) {
189: try {
190: dispatcher.invoke(this , new Object[] { req, resp });
191: } catch (IllegalAccessException e) {
192: throw new PortletException(e);
193: } catch (InvocationTargetException e) {
194: Throwable t = e.getCause();
195: if (t instanceof PortletException) {
196: throw (PortletException) t;
197: } else if (t instanceof IOException) {
198: throw (IOException) t;
199: } else if (t instanceof RuntimeException) {
200: throw (RuntimeException) t;
201: } else if (t instanceof Error) {
202: throw (Error) t;
203: } else {
204: throw new PortletException(
205: "Unexpected exception when dispatching the operation",
206: e);
207: }
208: }
209: } else {
210: throw new PortletException("Nothing to invoke");
211: }
212: }
213:
214: /** Calls <code>doDispatch(JBossRenderRequest,JBossRenderResponse)</code>. */
215: protected void render(JBossRenderRequest req,
216: JBossRenderResponse resp) throws PortletException,
217: PortletSecurityException, IOException {
218: resp.setTitle(getTitle(req));
219: doDispatch(req, resp);
220: }
221:
222: /**
223: *
224: */
225: protected void doDispatch(JBossRenderRequest request,
226: JBossRenderResponse response) throws PortletException,
227: PortletSecurityException, IOException {
228: if (!WindowState.MINIMIZED.equals(request.getWindowState())) {
229: PortletMode portletMode = request.getPortletMode();
230: if (PortletMode.VIEW.equals(portletMode)) {
231: doView(request, response);
232: } else if (PortletMode.HELP.equals(portletMode)) {
233: doHelp(request, response);
234: } else if (PortletMode.EDIT.equals(portletMode)) {
235: doEdit(request, response);
236: } else if (ADMIN.equals(portletMode)) {
237: doAdmin(request, response);
238: }
239: }
240: }
241:
242: /** Throw a <code>PortletException</code>. */
243: protected void doView(JBossRenderRequest request,
244: JBossRenderResponse response) throws PortletException,
245: PortletSecurityException, IOException {
246: throw new PortletException();
247: }
248:
249: /** Throw a <code>PortletException</code>. */
250: protected void doHelp(JBossRenderRequest request,
251: JBossRenderResponse response) throws PortletException,
252: PortletSecurityException, IOException {
253: throw new PortletException();
254: }
255:
256: /** Provide a default generic editor for preferences that produce HTML markup. */
257: protected void doEdit(JBossRenderRequest request,
258: JBossRenderResponse response) throws PortletException,
259: PortletSecurityException, IOException {
260: response.setContentType("text/html");
261: PrintWriter writer = response.getWriter();
262:
263: //
264: PortletURL url = response.createActionURL();
265:
266: //
267: writer.print("<table> "
268: + "<tr><td class=\"portlet-section-alternate\">"
269: + "Name"
270: + "</td><td class=\"portlet-section-alternate\">"
271: + "Value" + "</td></tr>" + "<form action=\"");
272: writer.print(url.toString());
273: writer.print("\" method=\"post\">");
274:
275: //
276: PortletPreferences prefs = request.getPreferences();
277: for (Iterator i = prefs.getMap().entrySet().iterator(); i
278: .hasNext();) {
279: Map.Entry entry = (Map.Entry) i.next();
280: String name = (String) entry.getKey();
281: String[] values = (String[]) entry.getValue();
282:
283: // Perform HTML entity replacement
284: name = EntityTable.FULL.convertEntities(name);
285: for (int j = 0; j < values.length; j++) {
286: String value = values[j];
287: if (value != null) {
288: values[j] = EntityTable.FULL.convertEntities(value);
289: }
290: }
291:
292: //
293: writer.print("<tr><td class=\"portlet-section-body\">");
294: writer.print(name);
295: writer.print("</td><td class=\"portlet-section-body\">");
296: if (prefs.isReadOnly(name)) {
297: writer.print(name);
298: } else {
299: writer
300: .print("<input class=\"portlet-form-input-field\" type=\"text\" name=\"");
301: writer.print(name);
302: writer.print("\" value=\"");
303: writer.print(values.length >= 1 ? values[0] : "");
304: writer.print("\"/>");
305: }
306: writer.print("</td></tr>");
307: }
308:
309: writer
310: .print("<tr><td colspan=\"2\" class=\"portlet-section-alternate\">"
311: + "<input class=\"portlet-form-button\" type=\"submit\" value=\"Save\"/>"
312: + "</td></tr>" + "</form></table>");
313: }
314:
315: /** Throw a <code>PortletException</code>. */
316: protected void doAdmin(JBossRenderRequest request,
317: JBossRenderResponse response) throws PortletException,
318: PortletSecurityException, IOException {
319: throw new PortletException();
320: }
321:
322: public ResourceBundle getResourceBundle(Locale locale) {
323: return getPortletConfig().getResourceBundle(locale);
324: }
325:
326: protected String getTitle(RenderRequest request) {
327: ResourceBundle bundle = getResourceBundle(request.getLocale());
328: return bundle.getString("javax.portlet.title");
329: }
330:
331: public String getInitParameter(String name)
332: throws IllegalArgumentException {
333: return getPortletConfig().getInitParameter(name);
334: }
335:
336: public Enumeration getInitParameterNames() {
337: return getPortletConfig().getInitParameterNames();
338: }
339:
340: // javax.portlet.Portlet implementation *****************************************************************************
341:
342: public void init(PortletConfig config) throws PortletException {
343: this .config = config;
344: init();
345: }
346:
347: public void processAction(ActionRequest request,
348: ActionResponse response) throws PortletException,
349: PortletSecurityException, IOException {
350: processAction((JBossActionRequest) request,
351: (JBossActionResponse) response);
352: }
353:
354: public void render(RenderRequest req, RenderResponse resp)
355: throws PortletException, PortletSecurityException,
356: IOException {
357: render((JBossRenderRequest) req, (JBossRenderResponse) resp);
358: }
359:
360: public void destroy() {
361: }
362:
363: // Private **********************************************************************************************************
364:
365: /** Locate a method. */
366: private Method lookupMethod(String operation, Class[] parameterTypes) {
367: try {
368: Method m = getClass().getMethod(operation, parameterTypes);
369: if (m.getReturnType() == void.class
370: && Modifier.isPublic(m.getModifiers())) {
371: return m;
372: }
373: } catch (NoSuchMethodException e) {
374: // Does not exist
375: }
376: return null;
377: }
378: }
|