001: /*
002: * @author <a href="mailto:novotny@gridsphere.org">Jason Novotny</a>
003: * @version $Id: ApplicationPortletImpl.java 6409 2008-01-25 13:46:13Z docentt $
004: */
005: package org.gridsphere.portletcontainer.impl;
006:
007: import org.apache.commons.logging.Log;
008: import org.apache.commons.logging.LogFactory;
009: import org.gridsphere.portlet.impl.PortalContextImpl;
010: import org.gridsphere.portlet.impl.SportletProperties;
011: import org.gridsphere.portletcontainer.ApplicationPortlet;
012: import org.gridsphere.portletcontainer.PortletDispatcher;
013: import org.gridsphere.portletcontainer.PortletPreferencesManager;
014: import org.gridsphere.portletcontainer.PortletStatus;
015: import org.gridsphere.portletcontainer.impl.descriptor.*;
016: import org.gridsphere.services.core.persistence.PersistenceManagerException;
017:
018: import javax.portlet.PortalContext;
019: import javax.portlet.Portlet;
020: import javax.servlet.RequestDispatcher;
021: import javax.servlet.ServletContext;
022: import javax.servlet.http.HttpServletRequest;
023: import javax.servlet.http.HttpServletResponse;
024: import java.io.IOException;
025: import java.io.UnsupportedEncodingException;
026: import java.net.URLEncoder;
027: import java.util.*;
028:
029: /**
030: * The <code>ApplicationPortletImpl</code> is an implementation of the <code>ApplicationPortlet</code> interface
031: * that uses Castor for XML to Java data bindings.
032: * <p/>
033: * The <code>ApplicationPortlet</code> represents the portlet application instance
034: * defined in the portlet descriptor file.
035: */
036: public class ApplicationPortletImpl implements ApplicationPortlet,
037: Comparable {
038:
039: private Log log = LogFactory.getLog(ApplicationPortletImpl.class);
040: private PortletDefinition portletDef = null;
041:
042: private String portletClassName = null;
043: private String webAppName = null;
044:
045: private Locale compareLocale = null;
046:
047: private Portlet portletInstance = null;
048:
049: private ServletContext context = null;
050: private PortalContext portalContext = null;
051: private javax.portlet.PreferencesValidator prefsValidator = null;
052:
053: private int expiration = 0;
054:
055: private Map<String, Set<String>> markupModes = new HashMap<String, Set<String>>();
056: private List<javax.portlet.WindowState> states = new ArrayList<javax.portlet.WindowState>();
057:
058: private PortletDeploymentDescriptor portletDD = null;
059: private String concreteID = null;
060: private String portletName = null;
061:
062: private Locale[] supportedLocales = null;
063: private Map<String, String> descsMap = null;
064: private Map<String, String> dispsMap = null;
065: private String requiredRole = "";
066:
067: protected PortletStatus status = PortletStatus.SUCCESS;
068: protected String statusMessage = "JSR Portlet loaded successfully";
069:
070: protected PortletPreferencesManager prefsManager = null;
071:
072: /**
073: * Default constructor is private
074: */
075: protected ApplicationPortletImpl() {
076: }
077:
078: /**
079: * Constructs an instance of ApplicationPortletImpl
080: *
081: * @param pdd the <code>PortletDeploymentDescriptor</code>
082: * @param portletDef the portlet definition
083: * @param webApplication the ui application name for this application portlet
084: * @param context the <code>ServletContext</code> containing this application portlet
085: */
086: public ApplicationPortletImpl(PortletDeploymentDescriptor pdd,
087: PortletDefinition portletDef, String webApplication,
088: ServletContext context) {
089: this .portletDef = portletDef;
090: this .webAppName = webApplication;
091: this .portletClassName = portletDef.getPortletClass()
092: .getContent();
093: this .portletName = portletDef.getPortletName().getContent();
094: this .context = context;
095: PortletApp portletApp = pdd.getPortletWebApplication();
096:
097: SupportedLocale[] locales = portletDef.getSupportedLocale();
098: supportedLocales = new Locale[locales.length];
099: for (int i = 0; i < locales.length; i++) {
100: supportedLocales[i] = new Locale(locales[i].getContent());
101: }
102:
103: // create portal context
104: portalContext = new PortalContextImpl(pdd
105: .getPortletWebApplication());
106:
107: portletName = portletDef.getPortletName().getContent();
108: concreteID = webAppName + "#" + portletName;
109:
110: // supported locales
111: supportedLocales = new Locale[portletDef
112: .getSupportedLocaleCount()];
113: SupportedLocale[] suppLocs = portletDef.getSupportedLocale();
114: for (int i = 0; i < suppLocs.length; i++) {
115: supportedLocales[i] = new Locale(suppLocs[i].getContent(),
116: "", "");
117: }
118:
119: // portlet descriptions
120: Description[] descs = portletDef.getDescription();
121: descsMap = new HashMap<String, String>();
122: for (int i = 0; i < descs.length; i++) {
123: descsMap.put(descs[i].getLang(), descs[i].getContent());
124: }
125:
126: // portlet display names
127: DisplayName[] disps = portletDef.getDisplayName();
128: dispsMap = new HashMap<String, String>();
129: for (int i = 0; i < disps.length; i++) {
130: dispsMap.put(disps[i].getLang(), disps[i].getContent());
131: }
132:
133: // get required role
134: SecurityRoleRef[] secRoleRef = portletDef.getSecurityRoleRef();
135: for (int i = 0; i < secRoleRef.length; i++) {
136: requiredRole = secRoleRef[i].getRoleName().getContent();
137: }
138:
139: //String id = portletDef.getPortletClass().getContent();
140: this .portletName = portletDef.getPortletName().getContent();
141: if (portletDef.getExpirationCache() != null) {
142: expiration = portletDef.getExpirationCache().getContent();
143: }
144:
145: Supports[] supports = portletDef.getSupports();
146: // defined portlet modes
147: for (int i = 0; i < supports.length; i++) {
148: Set<String> modesAllowed = new HashSet<String>();
149: Supports s = (Supports) supports[i];
150: org.gridsphere.portletcontainer.impl.descriptor.PortletMode[] modes = (org.gridsphere.portletcontainer.impl.descriptor.PortletMode[]) s
151: .getPortletMode();
152: for (int j = 0; j < modes.length; j++) {
153: org.gridsphere.portletcontainer.impl.descriptor.PortletMode m = modes[j];
154: modesAllowed.add(m.getContent());
155: }
156: modesAllowed.add(javax.portlet.PortletMode.VIEW.toString());
157: String mimeType = (String) s.getMimeType().getContent();
158:
159: markupModes.put(mimeType, modesAllowed);
160:
161: }
162:
163: List<String> customStatesList = new ArrayList<String>();
164: CustomWindowState[] customStates = portletApp
165: .getCustomWindowState();
166: if (customStates != null) {
167: for (int i = 0; i < customStates.length; i++) {
168: customStatesList.add(customStates[i].getWindowState()
169: .getContent());
170: }
171: }
172:
173: // defined window states
174: if (!customStatesList.isEmpty()) {
175: for (int i = 0; i < supports.length; i++) {
176: Supports s = (Supports) supports[i];
177: org.gridsphere.portletcontainer.impl.descriptor.WindowState[] statesAllowed = (org.gridsphere.portletcontainer.impl.descriptor.WindowState[]) s
178: .getWindowState();
179: if (statesAllowed != null) {
180: for (int j = 0; j < statesAllowed.length; j++) {
181: org.gridsphere.portletcontainer.impl.descriptor.WindowState w = statesAllowed[j];
182: if (customStatesList.contains(w.getContent()))
183: states.add(new javax.portlet.WindowState(w
184: .getContent()));
185: }
186: }
187: }
188: }
189: states.add(javax.portlet.WindowState.MAXIMIZED);
190: states.add(javax.portlet.WindowState.MINIMIZED);
191: states.add(javax.portlet.WindowState.NORMAL);
192:
193: org.gridsphere.portletcontainer.impl.descriptor.PortletPreferences prefDesc = portletDef
194: .getPortletPreferences();
195: if (prefDesc != null) {
196: org.gridsphere.portletcontainer.impl.descriptor.PreferencesValidator validator = prefDesc
197: .getPreferencesValidator();
198: if (validator != null) {
199: String validatorClass = validator.getContent();
200: if (validatorClass != null) {
201: try {
202: prefsValidator = (javax.portlet.PreferencesValidator) Class
203: .forName(validatorClass).newInstance();
204: } catch (Exception e) {
205: log.error("Unable to create validator: "
206: + validatorClass + "! ", e);
207: }
208: }
209: }
210: }
211:
212: prefsManager = new PortletPreferencesManagerImpl(prefDesc,
213: prefsValidator);
214:
215: }
216:
217: /**
218: * Return the web application name associated with this application portlet
219: *
220: * @return the web application name
221: */
222: public String getWebApplicationName() {
223: return webAppName;
224: }
225:
226: /**
227: * Returns the id of a PortletApplication
228: *
229: * @return the id of the PortletApplication
230: */
231: public String getApplicationPortletID() {
232: return webAppName + "#" + portletName;
233: }
234:
235: /**
236: * Returns a PortletDispatcher for this ApplicationPortlet
237: *
238: * @return PortletDispatcher the proxy portlet for this ApplicationPortlet
239: */
240: public PortletDispatcher getPortletDispatcher(
241: HttpServletRequest req, HttpServletResponse res) {
242:
243: //System.err.println("in getPortletDispatcher: cid=" + req.getAttribute(SportletProperties.COMPONENT_ID));
244: String cid = (String) req
245: .getAttribute(SportletProperties.COMPONENT_ID);
246: String pid = (String) req
247: .getAttribute(SportletProperties.PORTLETID);
248: // TODO fix my hack to get any render params and pass them as queryInfo to the portlet
249: Map params = (Map) req
250: .getAttribute(SportletProperties.RENDER_PARAM_PREFIX
251: + pid + "_" + cid);
252: StringBuffer extraInfo = new StringBuffer();
253:
254: //System.err.println("Dispatching: Looking for render params for " + SportletProperties.RENDER_PARAM_PREFIX + pid + "_" + cid);
255: if (params == null) {
256: params = new HashMap();
257: }
258:
259: //params.put(SportletProperties.COMPONENT_ID, cid);
260: boolean firstParam = true;
261:
262: Iterator it = params.keySet().iterator();
263: try {
264: while (it.hasNext()) {
265: if (!firstParam) {
266: extraInfo.append("&");
267: } else {
268: extraInfo.append("?");
269: }
270: String name = (String) it.next();
271:
272: // Render parameters that are passed on from the portlet frame are persistent across client requests
273: // They are render param names already prefixed. We prefix them again so are can be selectively retrieved
274: // in the nasty request parameter filter GridSphereParameters
275:
276: String encname = URLEncoder.encode("pr_" + name,
277: "UTF-8");
278: //String encname = URLEncoder.encode(name, "UTF-8");
279:
280: Object val = params.get(name);
281: if (val instanceof String[]) {
282: String[] vals = (String[]) val;
283: for (int j = 0; j < vals.length - 1; j++) {
284: String encvalue = URLEncoder.encode(vals[j],
285: "UTF-8");
286: extraInfo.append(encname);
287: extraInfo.append("=");
288: extraInfo.append(encvalue);
289: extraInfo.append("&");
290: }
291: String encvalue = URLEncoder.encode(
292: vals[vals.length - 1], "UTF-8");
293: extraInfo.append(encname);
294: extraInfo.append("=");
295: extraInfo.append(encvalue);
296: } else if (val instanceof String) {
297: String aval = (String) params.get(name);
298: if ((aval != null) && (!aval.equals(""))) {
299: String encvalue = URLEncoder.encode(aval,
300: "UTF-8");
301: extraInfo.append(encname);
302: extraInfo.append("=");
303: extraInfo.append(encvalue);
304: } else {
305: extraInfo.append(encname);
306: }
307: }
308: firstParam = false;
309: }
310: } catch (UnsupportedEncodingException e) {
311: log.error("Unsupported encoding!", e);
312: }
313:
314: // before it adds ".1" to real webappName
315: //String realWebAppName = webAppName.substring(0, webAppName.length() - 2);
316:
317: //System.err.println("in getPortletDispatcher of jsr query string " + "/jsr/" + webAppName + extraInfo);
318: // TODO change dangerously hardcoded value!!!
319: RequestDispatcher rd = context.getRequestDispatcher("/jsr/"
320: + webAppName + extraInfo.toString());
321: //RequestDispatcher rd = context.getNamedDispatcher(servletName);
322:
323: if (rd == null) {
324: String msg = "Unable to create a dispatcher for portlet: "
325: + portletName + "\n";
326: msg += "Make sure the servlet mapping: /jsr/" + webAppName
327: + " is defined in web.xml";
328: log.error(msg);
329: }
330: return new PortletDispatcherImpl(rd);
331: }
332:
333: /**
334: * Returns the name of a PortletApplication
335: *
336: * @return name of the PortletApplication
337: */
338: public String getApplicationPortletName() {
339: return portletName;
340: }
341:
342: public String getApplicationPortletClassName() {
343: return portletClassName;
344: }
345:
346: public PortalContext getPortalContext() {
347: return portalContext;
348: }
349:
350: public String getPortletDescription(Locale locale) {
351: if (locale == null)
352: throw new IllegalArgumentException(
353: "supplied locale cannot be null!");
354: Description[] descs = portletDef.getDescription();
355: for (int i = 0; i < descs.length; i++) {
356: if (descs[i].getLang().equals(locale.getLanguage())) {
357: return descs[i].getContent();
358: }
359: }
360: return "Unknown portlet description";
361: }
362:
363: public String getPortletDisplayName(Locale locale) {
364: if (locale == null)
365: throw new IllegalArgumentException(
366: "supplied locale cannot be null!");
367: DisplayName[] dispNames = portletDef.getDisplayName();
368: for (int i = 0; i < dispNames.length; i++) {
369: if (dispNames[i].getLang().equals(locale.getLanguage())) {
370: return dispNames[i].getContent();
371: }
372: }
373: return "Unknown portlet display name";
374: }
375:
376: public int getExpirationCache() {
377: return portletDef.getExpirationCache().getContent();
378: }
379:
380: public Locale[] getSupportedLocales() {
381: return supportedLocales;
382: }
383:
384: public SecurityRoleRef[] getSecurityRoleRefs() {
385: return portletDef.getSecurityRoleRef();
386: }
387:
388: public PortletPreferencesManager getPortletPreferencesManager(
389: String portletId, String userId, boolean isRender) {
390: prefsManager.setPortletId(portletId);
391: prefsManager.setUserId(userId);
392: prefsManager.setRender(isRender);
393: return prefsManager;
394: }
395:
396: public Portlet getPortletInstance() {
397: return portletInstance;
398: }
399:
400: public void setApplicationPortletStatus(PortletStatus status) {
401: this .status = status;
402: }
403:
404: public void setApplicationPortletStatusMessage(String statusMessage) {
405: this .statusMessage = statusMessage;
406: }
407:
408: public PortletStatus getApplicationPortletStatus() {
409: return status;
410: }
411:
412: public String getApplicationPortletStatusMessage() {
413: return statusMessage;
414: }
415:
416: /**
417: * Returns the portlet application name
418: *
419: * @return the portlet application name
420: */
421: public String getPortletName() {
422: return portletName;
423: }
424:
425: /**
426: * Sets the name of a PortletApplication
427: *
428: * @param portletName name of a PortletApplication
429: */
430: public void setPortletName(String portletName) {
431: this .portletName = portletName;
432: }
433:
434: /**
435: * Returns the allowed window states supported by this portlet
436: *
437: * @return the <code>List</code> of
438: * <code>WindowState</code> elements allowed for this portlet
439: */
440: public List<javax.portlet.WindowState> getAllowedWindowStates() {
441: return Collections.unmodifiableList(states);
442: }
443:
444: /**
445: * Returns the supported modes for this portlet
446: *
447: * @return the supported modes for this portlet
448: */
449: public Set<String> getSupportedModes(String markup) {
450: if (markup == null)
451: throw new IllegalArgumentException(
452: "Supplied markup cannot be null!");
453: for (String mimeType : markupModes.keySet()) {
454: int idx1 = mimeType.indexOf(markup);
455: int idx2 = markup.indexOf(mimeType);
456: if ((idx1 > 0) || (idx2 > 0)
457: || (mimeType.equalsIgnoreCase(markup))) {
458: return markupModes.get(mimeType);
459: }
460: }
461: return new TreeSet<String>();
462: }
463:
464: public SortedSet<String> getSupportedMimeTypes(
465: javax.portlet.PortletMode mode) {
466: if (mode == null)
467: throw new IllegalArgumentException(
468: "Supplied mode cannot be null!");
469: SortedSet<String> mimeTypes = new TreeSet<String>();
470: for (String mimeType : markupModes.keySet()) {
471: Set modes = markupModes.get(mimeType);
472: if (modes.contains(mode.toString())) {
473: mimeTypes.add(mimeType);
474: }
475: }
476: return mimeTypes;
477: }
478:
479: /**
480: * returns the amount of time in seconds that a portlet's content should be cached
481: *
482: * @return the amount of time in seconds that a portlet's content should be cached
483: */
484: public long getCacheExpires() {
485: return expiration;
486: }
487:
488: /**
489: * Returns the concrete portlet id
490: *
491: * @return the concrete portlet id
492: */
493: public String getConcretePortletID() {
494: return concreteID;
495: }
496:
497: /**
498: * Returns the default/supported locale of a portlet
499: *
500: * @return the default locale of the portlet
501: */
502: public String getDefaultLocale() {
503: return supportedLocales[0].getLanguage();
504: }
505:
506: public String getDescription(Locale loc) {
507: String desc = (String) descsMap.get(loc.getLanguage());
508: if (desc == null) {
509: desc = portletName;
510: }
511: return desc;
512: }
513:
514: public String getDisplayName(Locale loc) {
515: String disp = (String) dispsMap.get(loc.getLanguage());
516: if (disp == null) {
517: disp = portletName;
518: }
519: return disp;
520: }
521:
522: /**
523: * Returns the required portlet role necessary to access this portlet
524: *
525: * @return the required portlet role necessary to access this portlet
526: */
527: public String getRequiredRole() {
528: return requiredRole;
529: }
530:
531: /**
532: * Sets the required portlet role necessary to access this portlet
533: *
534: * @param role the required portlet role necessary to access this portlet
535: */
536: public void setRequiredRole(String role) {
537: this .requiredRole = role;
538: }
539:
540: /**
541: * Saves any concrete portlet changes to the descriptor
542: *
543: * @throws java.io.IOException if an I/O error occurs
544: */
545: public void save() throws IOException {
546: try {
547: portletDD.save();
548: } catch (PersistenceManagerException e) {
549: throw new IOException(
550: "Unable to save JSR concrete portlet: "
551: + e.getMessage());
552: }
553: }
554:
555: public String toString() {
556: StringBuffer sb = new StringBuffer();
557: sb.append("\t JSR Application Portlet:\n");
558: sb.append("\t JSR Portlet Name: ").append(portletName).append(
559: "\n");
560: sb.append("\t Web app name: ").append(webAppName).append("\n");
561: sb.append("\t concrete ID: ").append(concreteID).append("\n");
562: sb.append("\t Status: ").append(status).append("\n");
563: sb.append("\t Status message: ").append(statusMessage).append(
564: "\n");
565: /*
566: if (portletDispatcher == null) {
567: sb.append("\t Portlet dispatcher: NULL");
568: } else {
569: sb.append("\t Portlet dispatcher: OK");
570: }
571: */
572: return sb.toString();
573: }
574:
575: public void setCompareLocale(Locale loc) {
576: compareLocale = loc;
577: }
578:
579: public int compareTo(Object o) {
580: ApplicationPortletImpl otherApplicationPortlet = (ApplicationPortletImpl) o;
581: if (compareLocale == null)
582: return (this .getWebApplicationName() + " - " + getDisplayName(new Locale(
583: getDefaultLocale())))
584: .compareToIgnoreCase(otherApplicationPortlet
585: .getWebApplicationName()
586: + " - "
587: + otherApplicationPortlet
588: .getDisplayName(new Locale(
589: getDefaultLocale())));
590: else
591: return (this .getWebApplicationName() + " - " + getDisplayName(compareLocale))
592: .compareToIgnoreCase(otherApplicationPortlet
593: .getWebApplicationName()
594: + " - "
595: + (otherApplicationPortlet
596: .getDisplayName(compareLocale)));
597: }
598: }
|