0001: /*
0002: * (C) Copyright 2000 - 2003 Nabh Information Systems, Inc.
0003: *
0004: * This program is free software; you can redistribute it and/or
0005: * modify it under the terms of the GNU General Public License
0006: * as published by the Free Software Foundation; either version 2
0007: * of the License, or (at your option) any later version.
0008: *
0009: * This program is distributed in the hope that it will be useful,
0010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0012: * GNU General Public License for more details.
0013: *
0014: * You should have received a copy of the GNU General Public License
0015: * along with this program; if not, write to the Free Software
0016: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
0017: *
0018: */
0019:
0020: package com.nabhinc.portal.core;
0021:
0022: import java.io.IOException;
0023: import java.io.InputStream;
0024: import java.util.HashMap;
0025: import java.util.Hashtable;
0026: import java.util.Iterator;
0027: import java.util.List;
0028: import java.util.Locale;
0029: import java.util.TreeMap;
0030: import java.util.Vector;
0031:
0032: import javax.portlet.Portlet;
0033: import javax.portlet.PreferencesValidator;
0034: import javax.servlet.RequestDispatcher;
0035: import javax.servlet.ServletConfig;
0036: import javax.servlet.ServletContext;
0037: import javax.servlet.ServletException;
0038: import javax.servlet.http.HttpServletRequest;
0039: import javax.servlet.http.HttpServletResponse;
0040: import javax.xml.bind.JAXBContext;
0041: import javax.xml.bind.JAXBException;
0042: import javax.xml.bind.Unmarshaller;
0043:
0044: import com.nabhinc.core.AbstractServlet;
0045: import com.nabhinc.core.MimeTypes;
0046: import com.nabhinc.portal.config.CustomPortletModeType;
0047: import com.nabhinc.portal.config.CustomWindowStateType;
0048: import com.nabhinc.portal.config.DescriptionType;
0049: import com.nabhinc.portal.config.DisplayNameType;
0050: import com.nabhinc.portal.config.ExpirationCacheType;
0051: import com.nabhinc.portal.config.InitParamType;
0052: import com.nabhinc.portal.config.KeywordsType;
0053: import com.nabhinc.portal.config.MimeTypeType;
0054: import com.nabhinc.portal.config.PortletCollectionType;
0055: import com.nabhinc.portal.config.PortletInfoType;
0056: import com.nabhinc.portal.config.PortletModeType;
0057: import com.nabhinc.portal.config.PortletNameType;
0058: import com.nabhinc.portal.config.PortletPreferencesType;
0059: import com.nabhinc.portal.config.PortletType;
0060: import com.nabhinc.portal.config.PreferenceType;
0061: import com.nabhinc.portal.config.SecurityConstraintType;
0062: import com.nabhinc.portal.config.SecurityRoleRefType;
0063: import com.nabhinc.portal.config.ShortTitleType;
0064: import com.nabhinc.portal.config.SupportedLocaleType;
0065: import com.nabhinc.portal.config.SupportsType;
0066: import com.nabhinc.portal.config.TitleType;
0067: import com.nabhinc.portal.config.UserAttributeType;
0068: import com.nabhinc.portal.config.ValueType;
0069: import com.nabhinc.portal.config.impl.PortletAppImpl;
0070: import com.nabhinc.portal.container.ActionRequestImpl;
0071: import com.nabhinc.portal.container.ActionResponseImpl;
0072: import com.nabhinc.portal.container.HttpServletRequestStringbeansWrapper;
0073: import com.nabhinc.portal.container.PortletConfigImpl;
0074: import com.nabhinc.portal.container.PortletContextImpl;
0075: import com.nabhinc.portal.container.PortletPreferencesImpl;
0076: import com.nabhinc.portal.container.RenderRequestImpl;
0077: import com.nabhinc.portal.container.RenderResponseImpl;
0078: import com.nabhinc.portal.login.LoginConstants;
0079: import com.nabhinc.portal.model.PortalConfiguration;
0080: import com.nabhinc.util.StringUtil;
0081:
0082: /**
0083: *
0084: *
0085: * @author Padmanabh Dabke
0086: * (c) 2002, 2003 Nabh Information Systems, Inc. All Rights Reserved.
0087: */
0088: public class PortletServlet extends AbstractServlet {
0089:
0090: private static final long serialVersionUID = 6377553888887070935L;
0091:
0092: /**
0093: * Stringbeans version string
0094: */
0095: public static final String VERSION = "3.5 Beta";
0096:
0097: /**
0098: * Version Info string
0099: */
0100: protected static String psServerInfo = "Stringbeans/" + VERSION;
0101:
0102: /**
0103: * Portlet.xml file path
0104: */
0105: public static final String PORTLET_XML_PATH = "/WEB-INF/portlet.xml";
0106:
0107: /**
0108: * Object representing portlet.xml file
0109: */
0110: protected PortletAppImpl psPortletApp = null;
0111:
0112: /**
0113: * Global PortletContext object
0114: */
0115: protected PortletContextImpl psPortletContext = null;
0116:
0117: /**
0118: * Supported portlet modes
0119: */
0120: protected HashMap psSupportedPortletModes = new HashMap();
0121:
0122: /**
0123: * Supported window states
0124: */
0125: protected HashMap psSupportedWindowStates = new HashMap();
0126:
0127: /**
0128: * User info attributes configured in portlet.xml. Currently
0129: * this value is not used anywhere.
0130: */
0131: protected Vector psSupportedUserAttributes = new Vector();
0132:
0133: /**
0134: * Portlet name -> PortletConfigInfo mapping
0135: */
0136: protected Hashtable psPortletMap = new Hashtable();
0137:
0138: /**
0139: * List of all PortletConfigInfo objects
0140: */
0141: protected Vector psPortletList = new Vector();
0142:
0143: /**
0144: * Map of portlet name -> "" for secure portlets.
0145: */
0146: protected HashMap psSecurePortlets = new HashMap();
0147:
0148: /**
0149: * Map of portlet categories -> portlet list
0150: */
0151: protected TreeMap psCategories = new TreeMap();
0152:
0153: /**
0154: * Flag to indicate wheter to share user info to external portlet context.
0155: */
0156: private boolean psSetUserRoleInfo = false;
0157:
0158: /* (non-Javadoc)
0159: * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
0160: */
0161: public void doGet(HttpServletRequest request,
0162: HttpServletResponse response) throws ServletException,
0163: IOException {
0164:
0165: // Set portlet config for requested portlet.
0166: String portletName = (String) request
0167: .getAttribute(PortalConstants.PORTLET_NAME_ATTRIB);
0168: if (portletName == null) {
0169: throw new ServletException(
0170: "You cannot access this servlet directly.");
0171: }
0172: PortletConfigInfo pConfigInfo = (PortletConfigInfo) psPortletMap
0173: .get(portletName);
0174: request.setAttribute(PortalConstants.PORTLET_CONFIG_ATTRIB,
0175: pConfigInfo.config);
0176:
0177: if (psSetUserRoleInfo) {
0178: HttpServletRequestStringbeansWrapper wrapper = (HttpServletRequestStringbeansWrapper) request;
0179: request.getSession().setAttribute(
0180: LoginConstants.USER_INFO_ATTRIBUTE,
0181: wrapper.getLocalUserInfo());
0182: }
0183:
0184: try {
0185: String method_id = (String) request
0186: .getAttribute(PortalConstants.METHOD_ID_ATTRIB);
0187: if (method_id.equals(PortalConstants.METHOD_RENDER)) {
0188: if (pConfigInfo.loadStatus == PortletConfigInfo.PORTLET_STATUS_LOADED) {
0189: RenderRequestImpl renderRequest = (RenderRequestImpl) request
0190: .getAttribute(PortalConstants.PORTLET_REQUEST_ATTRIB);
0191: RenderResponseImpl renderResponse = (RenderResponseImpl) request
0192: .getAttribute(PortalConstants.PORTLET_RESPONSE_ATTRIB);
0193: renderRequest.setHttpServletRequest(request);
0194: renderRequest
0195: .setPortletContext((PortletContextImpl) pConfigInfo.config
0196: .getPortletContext());
0197: ((PortletPreferencesImpl) renderRequest
0198: .getPreferences())
0199: .setPreferencesValidator(pConfigInfo.prefValidator);
0200: //renderResponse.setHttpServletResponse(response);
0201: pConfigInfo.portlet.render(renderRequest,
0202: renderResponse);
0203: }
0204: } else if (method_id
0205: .equals(PortalConstants.METHOD_PROCESS_ACTION)) {
0206: if (pConfigInfo.loadStatus == PortletConfigInfo.PORTLET_STATUS_LOADED) {
0207: ActionRequestImpl actionRequest = (ActionRequestImpl) request
0208: .getAttribute(PortalConstants.PORTLET_REQUEST_ATTRIB);
0209: ActionResponseImpl actionResponse = (ActionResponseImpl) request
0210: .getAttribute(PortalConstants.PORTLET_RESPONSE_ATTRIB);
0211: actionRequest.setHttpServletRequest(request);
0212: actionRequest
0213: .setPortletContext((PortletContextImpl) pConfigInfo.config
0214: .getPortletContext());
0215: ((PortletPreferencesImpl) actionRequest
0216: .getPreferences())
0217: .setPreferencesValidator(pConfigInfo.prefValidator);
0218: //actionResponse.setHttpServletResponse(response);
0219: pConfigInfo.portlet.processAction(actionRequest,
0220: actionResponse);
0221: }
0222: } else if (method_id
0223: .equals(PortalConstants.METHOD_UNLOAD_PORTLET)) {
0224: unloadPortlet(portletName, request, response);
0225: } else if (method_id
0226: .equals(PortalConstants.METHOD_LOAD_PORTLET)) {
0227: loadPortletNamed(portletName, request, response);
0228: } else if (method_id
0229: .equals(PortalConstants.METHOD_GET_PORTLET_STATUS)) {
0230: // The status is set for all methods anyway
0231: } else if (method_id
0232: .equals(PortalConstants.METHOD_GET_PORTLET_TITLE)) {
0233: RenderRequestImpl renderRequest = (RenderRequestImpl) request
0234: .getAttribute(PortalConstants.PORTLET_REQUEST_ATTRIB);
0235: String title = pConfigInfo.config.getResourceBundle(
0236: request.getLocale()).getString(
0237: "javax.portlet.title");
0238: if (title != null)
0239: renderRequest
0240: .setAttribute(
0241: PortalConstants.PORTLET_TITLE_ATTRIB,
0242: title);
0243: return;
0244: } else {
0245: throw new ServletException(
0246: "Unrecognized portlet method: " + method_id);
0247: }
0248: setPortletStatusAttributes(pConfigInfo, request);
0249: } catch (Exception e) {
0250: throw new ServletException(e);
0251: } finally {
0252: request
0253: .removeAttribute(PortalConstants.PORTLET_CONFIG_ATTRIB);
0254: }
0255:
0256: }
0257:
0258: /* (non-Javadoc)
0259: * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
0260: */
0261: public void doPost(HttpServletRequest arg0, HttpServletResponse arg1)
0262: throws ServletException, IOException {
0263: doGet(arg0, arg1);
0264: }
0265:
0266: /* (non-Javadoc)
0267: * @see javax.servlet.Servlet#init(javax.servlet.ServletConfig)
0268: */
0269: public void init(ServletConfig config) throws ServletException {
0270: super .init(config);
0271: ServletContext sContext = getServletContext();
0272: psPortletContext = new PortletContextImpl(
0273: sContext,
0274: psServerInfo,
0275: config
0276: .getInitParameter(PortalConfiguration.ROOT_DIR_PARAM_NAME));
0277:
0278: if ("true".equals(config.getInitParameter("setUserInfo")))
0279: psSetUserRoleInfo = true;
0280:
0281: try {
0282: info("Starting PortletServlet initialization for web context: "
0283: + sContext.getServletContextName() + ".");
0284: info("Processing portlet.xml file.");
0285: processPortletFile(sContext, null, null);
0286: info("PortletServlet initialization successful.");
0287: } catch (ServletException se) {
0288: fatal("PortletServlet initialization failed.", se);
0289: throw se;
0290: } catch (Throwable ex) {
0291: fatal("PortletServlet initialization failed.", ex);
0292: throw new ServletException(ex);
0293: }
0294:
0295: }
0296:
0297: protected InputStream getPortletConfigInputStream(
0298: ServletContext context, String servletURI)
0299: throws ServletException {
0300: InputStream is = context
0301: .getResourceAsStream("/WEB-INF/portlet.xml");
0302: if (is == null)
0303: throw new ServletException(
0304: "Failed to locate portlet.xml file.");
0305: return is;
0306: }
0307:
0308: @SuppressWarnings("unchecked")
0309: public PortletAppImpl processPortletFile(ServletContext context,
0310: String contextPath, String servletURI)
0311: throws ServletException {
0312: PortletAppImpl portletApp = null;
0313: InputStream pInput = null;
0314: try {
0315: // create a JAXBContext capable of handling classes generated into
0316: // the example package
0317: JAXBContext jc = JAXBContext
0318: .newInstance("com.nabhinc.portal.config");
0319:
0320: // create an Unmarshaller
0321: Unmarshaller u = jc.createUnmarshaller();
0322:
0323: // Unmarshal portlet.xml content
0324: //String realPath = context.getRealPath(PORTLET_XML_PATH);
0325: // System.out.println("Real path = " + realPath);
0326: pInput = getPortletConfigInputStream(context, servletURI);
0327: portletApp = (PortletAppImpl) u.unmarshal(pInput);
0328:
0329: if (contextPath == null) {
0330: psPortletApp = portletApp;
0331: }
0332: } catch (JAXBException ex) {
0333: throw new ServletException(
0334: "Failed to parse portlet.xml file.", ex);
0335: } finally {
0336: try {
0337: if (pInput != null)
0338: pInput.close();
0339: } catch (Exception ignore) {
0340: }
0341: }
0342: info("Successfully parsed portlet.xml file.");
0343:
0344: // Prepare a list of user attributes to be exposed.
0345: List uAttribList = portletApp.getUserAttribute();
0346: for (int i = 0; i < uAttribList.size(); i++) {
0347: String uAttrib = ((UserAttributeType) uAttribList.get(i))
0348: .getName().getValue();
0349: if (!psSupportedUserAttributes.contains(uAttrib))
0350: psSupportedUserAttributes.addElement(uAttrib);
0351:
0352: }
0353: info("Processed user info attributes.");
0354:
0355: // Populate map of portlets that need secure access
0356: List secList = portletApp.getSecurityConstraint();
0357: for (int i = 0; i < secList.size(); i++) {
0358: SecurityConstraintType constraint = (SecurityConstraintType) secList
0359: .get(i);
0360: String guarantee = constraint.getUserDataConstraint()
0361: .getTransportGuarantee().toUpperCase();
0362: if ("INTEGRAL".equals(guarantee)
0363: || "CONFIDENTIAL".equals(guarantee)) {
0364: /*
0365: List pCollList = constraint.getDisplayName();
0366: for (int j = 0; j < pCollList.size(); j++) {
0367: PortletCollectionType pColl =
0368: (PortletCollectionType) pCollList.get(j);
0369: List pNameList = pColl.getPortletName();
0370: for (int k = 0; k < pNameList.size(); k++) {
0371: psSecurePortlets.put(
0372: ((PortletNameType) pNameList.get(k)).getValue(),
0373: "");
0374:
0375: }
0376: }
0377: */
0378: PortletCollectionType pColl = constraint
0379: .getPortletCollection();
0380: List pNameList = pColl.getPortletName();
0381: for (int k = 0; k < pNameList.size(); k++) {
0382: psSecurePortlets.put(((PortletNameType) pNameList
0383: .get(k)).getValue(), "");
0384:
0385: }
0386: }
0387: }
0388: info("Processed secure portets.");
0389:
0390: // Populate PortalContext properties
0391: psSupportedPortletModes.put("view", "");
0392: psSupportedPortletModes.put("edit", "");
0393: psSupportedPortletModes.put("help", "");
0394: List pModeList = portletApp.getCustomPortletMode();
0395: if (pModeList != null) {
0396: for (int i = 0; i < pModeList.size(); i++) {
0397: String pMode = ((CustomPortletModeType) pModeList
0398: .get(i)).getPortletMode().getValue()
0399: .toLowerCase();
0400: psSupportedPortletModes.put(pMode, "");
0401:
0402: }
0403: }
0404: info("Processed supported portlet modes.");
0405:
0406: // Custom window states
0407: psSupportedWindowStates.put("normal", "");
0408: psSupportedWindowStates.put("maximized", "");
0409: psSupportedWindowStates.put("minimized", "");
0410: List wStateList = portletApp.getCustomWindowState();
0411:
0412: if (wStateList != null) {
0413: for (int i = 0; i < wStateList.size(); i++) {
0414: String wState = ((CustomWindowStateType) wStateList
0415: .get(i)).getWindowState().getValue()
0416: .toLowerCase();
0417: psSupportedWindowStates.put(wState, "");
0418: }
0419: }
0420: info("Processed portlet window states.");
0421:
0422: // Put the configured portlets in the portlet map
0423: List pList = portletApp.getPortlet();
0424: int numPortlets = pList.size();
0425: info("Starting portlet load.");
0426: info("Number of portlets configured = " + numPortlets);
0427: for (int i = 0; i < numPortlets; i++) {
0428: loadPortlet((PortletType) pList.get(i), -1, contextPath,
0429: servletURI);
0430: }
0431:
0432: return portletApp;
0433: }
0434:
0435: @SuppressWarnings("unchecked")
0436: public synchronized void replacePortlet(PortletType pType,
0437: int index, HttpServletRequest req, HttpServletResponse resp)
0438: throws ServletException, IOException {
0439: PortletConfigInfo pcInfo = (PortletConfigInfo) psPortletList
0440: .elementAt(index);
0441: String pName = pcInfo.name;
0442: boolean isSecurePortlet = psSecurePortlets.containsKey(pName);
0443:
0444: // Update local portlet info first
0445: deletePortlet(pName, req, resp);
0446: loadPortlet(pType, index, pcInfo.contextPath, pcInfo.servletURI);
0447: //put the new portlet to the secure portlet list if the same name was a secure portlet before replacing.
0448: if (pName.equals(pType.getPortletName().getValue())
0449: && isSecurePortlet)
0450: psSecurePortlets.put(pName, "");
0451:
0452: psPortletApp.getPortlet().add(index, pType);
0453:
0454: if (pcInfo.contextPath != null) {
0455: req
0456: .setAttribute(PortalConstants.PORTLET_NAME_ATTRIB,
0457: pName);
0458: req.setAttribute(PortalConstants.METHOD_ID_ATTRIB,
0459: PortalConstants.METHOD_REPLACE_PORTLET);
0460: RequestDispatcher dispatcher = getServletContext()
0461: .getContext(pcInfo.contextPath)
0462: .getRequestDispatcher(pcInfo.servletURI);
0463: dispatcher.include(req, resp);
0464: setPortletStatus(pcInfo, req);
0465: }
0466: }
0467:
0468: public synchronized void deletePortlet(String pName,
0469: HttpServletRequest req, HttpServletResponse resp)
0470: throws ServletException, IOException {
0471: PortletConfigInfo pcInfo = (PortletConfigInfo) psPortletMap
0472: .get(pName);
0473: if (pcInfo == null)
0474: return;
0475:
0476: // Clear local information
0477: unloadPortlet(pName, req, resp);
0478: psPortletMap.remove(pName);
0479: psSecurePortlets.remove(pName);
0480: psPortletList.remove(pcInfo);
0481: Iterator iter = psCategories.values().iterator();
0482: psPortletApp.getPortlet().remove(pcInfo.portletType);
0483: while (iter.hasNext()) {
0484: ((Vector) iter.next()).remove(pcInfo);
0485: }
0486:
0487: // If the portlet belongs to remote webapp, forward the request to
0488: // that PortletServlet.
0489: if (pcInfo.contextPath != null) {
0490: req
0491: .setAttribute(PortalConstants.PORTLET_NAME_ATTRIB,
0492: pName);
0493: req.setAttribute(PortalConstants.METHOD_ID_ATTRIB,
0494: PortalConstants.METHOD_DELETE_PORTLET);
0495: RequestDispatcher dispatcher = getServletContext()
0496: .getContext(pcInfo.contextPath)
0497: .getRequestDispatcher(pcInfo.servletURI);
0498: dispatcher.include(req, resp);
0499:
0500: }
0501: }
0502:
0503: public void unloadPortlet(String pName, HttpServletRequest req,
0504: HttpServletResponse resp) throws ServletException,
0505: IOException {
0506: PortletConfigInfo pcInfo = (PortletConfigInfo) psPortletMap
0507: .get(pName);
0508: if (pcInfo == null)
0509: return;
0510:
0511: if (pcInfo.contextPath == null) {
0512: synchronized (pcInfo) {
0513: try {
0514: if (pcInfo.portlet != null) {
0515: pcInfo.portlet.destroy();
0516: pcInfo.portlet = null;
0517: }
0518: } catch (Exception ex) {
0519: }
0520:
0521: pcInfo.loadError = null;
0522: pcInfo.loadStatus = PortletConfigInfo.PORTLET_STATUS_UNLOADED;
0523: }
0524: } else {
0525: pcInfo.loadError = null;
0526: pcInfo.loadStatus = PortletConfigInfo.PORTLET_STATUS_UNLOADED;
0527: req
0528: .setAttribute(PortalConstants.PORTLET_NAME_ATTRIB,
0529: pName);
0530: req.setAttribute(PortalConstants.METHOD_ID_ATTRIB,
0531: PortalConstants.METHOD_UNLOAD_PORTLET);
0532: RequestDispatcher dispatcher = getServletContext()
0533: .getContext(pcInfo.contextPath)
0534: .getRequestDispatcher(pcInfo.servletURI);
0535: dispatcher.include(req, resp);
0536:
0537: }
0538: }
0539:
0540: public void loadPortletNamed(String pName, HttpServletRequest req,
0541: HttpServletResponse resp) throws ServletException,
0542: IOException {
0543: PortletConfigInfo pcInfo = (PortletConfigInfo) psPortletMap
0544: .get(pName);
0545: if (pcInfo.contextPath == null) {
0546: createPortlet(pcInfo);
0547: } else {
0548: req
0549: .setAttribute(PortalConstants.PORTLET_NAME_ATTRIB,
0550: pName);
0551: req.setAttribute(PortalConstants.METHOD_ID_ATTRIB,
0552: PortalConstants.METHOD_LOAD_PORTLET);
0553: RequestDispatcher dispatcher = getServletContext()
0554: .getContext(pcInfo.contextPath)
0555: .getRequestDispatcher(pcInfo.servletURI);
0556: dispatcher.include(req, resp);
0557: setPortletStatus(pcInfo, req);
0558: }
0559: }
0560:
0561: public void createPortlet(PortletConfigInfo pcInfo) {
0562: // try to instantiate the portlet
0563: PortletType portletType = pcInfo.portletType;
0564: Portlet portlet = null;
0565: Throwable portletLoadError = null;
0566: int portletLoadStatus = PortletConfigInfo.PORTLET_STATUS_LOADED;
0567: String portletName = pcInfo.name;
0568:
0569: // Destroy original portlet if present
0570: if (pcInfo.portlet != null) {
0571: synchronized (pcInfo) {
0572: try {
0573: pcInfo.portlet.destroy();
0574: pcInfo.portlet = null;
0575: } catch (Exception ex) {
0576: }
0577: }
0578: }
0579:
0580: // Reset error and load status
0581: pcInfo.loadError = null;
0582: pcInfo.loadErrorStackTrace = null;
0583:
0584: try {
0585: info("Creating portlet " + portletName + " of class "
0586: + portletType.getPortletClass());
0587: portlet = (Portlet) Class.forName(
0588: portletType.getPortletClass()).newInstance();
0589: } catch (Throwable t) {
0590: warn("Failed to create instance of portlet " + portletName
0591: + ".", t);
0592: portletLoadError = t;
0593: portletLoadStatus = PortletConfigInfo.PORTLET_STATUS_INSTANTIATION_ERROR;
0594: }
0595:
0596: if (portletLoadError == null) {
0597: try {
0598: portlet.init(pcInfo.config);
0599: } catch (Throwable t) {
0600: warn("Failed to initialize portlet " + portletName
0601: + ".", t);
0602: portletLoadStatus = PortletConfigInfo.PORTLET_STATUS_INIT_ERROR;
0603: portletLoadError = t;
0604: portlet = null;
0605: }
0606: }
0607:
0608: pcInfo.portlet = portlet;
0609: if (portletLoadError != null) {
0610: pcInfo.loadErrorStackTrace = StringUtil
0611: .getErrorStackTraceString(portletLoadError);
0612: pcInfo.loadError = portletLoadError.toString();
0613: }
0614: pcInfo.loadStatus = portletLoadStatus;
0615:
0616: }
0617:
0618: @SuppressWarnings("unchecked")
0619: public void addPortlet(PortletType portletType)
0620: throws ServletException {
0621: loadPortlet(portletType, -1, null, null);
0622: psPortletApp.getPortlet().add(portletType);
0623: }
0624:
0625: @SuppressWarnings("unchecked")
0626: public void loadPortlet(PortletType portletType, int index,
0627: String contextPath, String servletURI)
0628: throws ServletException {
0629:
0630: String[] keywordArray = null;
0631:
0632: // Create PortletConfig for this portlet
0633: String resourceBundleName = null;
0634: if (portletType.getResourceBundle() != null) {
0635: resourceBundleName = portletType.getResourceBundle()
0636: .getValue();
0637: }
0638: PortletInfoType pInfo = portletType.getPortletInfo();
0639: Hashtable inlineProps = null;
0640: String titleStr = null;
0641: String shortTitleStr = null;
0642: String keywordStr = null;
0643:
0644: if (pInfo != null) {
0645: inlineProps = new Hashtable();
0646: KeywordsType kType = pInfo.getKeywords();
0647:
0648: if (kType != null) {
0649: keywordStr = kType.getValue();
0650: keywordArray = StringUtil.split(keywordStr, ",");
0651: inlineProps.put("javax.portlet.keywords", kType
0652: .getValue());
0653: }
0654: TitleType title = pInfo.getTitle();
0655: if (title != null) {
0656: inlineProps
0657: .put("javax.portlet.title", title.getValue());
0658: titleStr = title.getValue();
0659: }
0660: ShortTitleType shortTitle = pInfo.getShortTitle();
0661: if (shortTitle != null) {
0662: inlineProps.put("javax.portlet.short-title", shortTitle
0663: .getValue());
0664: shortTitleStr = shortTitle.getValue();
0665: }
0666: }
0667:
0668: ClassLoader pLoader = null;
0669: if (contextPath == null) {
0670: try {
0671: pLoader = Class.forName(portletType.getPortletClass())
0672: .getClassLoader();
0673:
0674: } catch (ClassNotFoundException e) {
0675:
0676: }
0677: }
0678:
0679: PortletConfigImpl pConfig = new PortletConfigImpl(
0680: psPortletContext, resourceBundleName, inlineProps,
0681: pLoader);
0682: PortletNameType portletNameT = portletType.getPortletName();
0683: if (portletNameT == null) {
0684: throw new ServletException(
0685: "Missing portlet name in portlet.xml.");
0686: }
0687: String portletName = portletNameT.getValue();
0688: info("Loading portlet " + portletName);
0689: pConfig.setPortletName(portletName);
0690: List initParams = portletType.getInitParam();
0691:
0692: if (initParams != null) {
0693: for (Iterator iter = initParams.iterator(); iter.hasNext();) {
0694: InitParamType element = (InitParamType) iter.next();
0695: pConfig.putInitParam(element.getName().getValue(),
0696: element.getValue().getValue());
0697:
0698: }
0699: }
0700: Hashtable<String, PortletPreferencesImpl.PrefInfo> prefMap = new Hashtable<String, PortletPreferencesImpl.PrefInfo>();
0701:
0702: PortletPreferencesType prefT = portletType
0703: .getPortletPreferences();
0704: PreferencesValidator prefValidator = null;
0705: Throwable prefValidatorError = null;
0706: // int portletLoadStatus = PortletConfigInfo.PORTLET_STATUS_LOADED;
0707:
0708: // Process validator creation only for local portlets.
0709: if (contextPath == null) {
0710: String validatorClass = null;
0711: if (prefT != null)
0712: validatorClass = prefT.getPreferencesValidator();
0713: if (validatorClass != null) {
0714: info("Creating preference validator for portlet "
0715: + portletName + ".");
0716: try {
0717: prefValidator = (PreferencesValidator) Class
0718: .forName(validatorClass).newInstance();
0719: } catch (Throwable ex) {
0720: warn(
0721: "Failed to create preference validator for portlet "
0722: + portletName + ".", ex);
0723: prefValidatorError = ex;
0724: // portletLoadStatus = PortletConfigInfo.PORTLET_STATUS_PREF_VALIDATOR_ERROR;
0725:
0726: }
0727: }
0728: }
0729:
0730: if (prefT != null) {
0731: List prefList = prefT.getPreference();
0732: if (prefList != null) {
0733: for (Iterator iter = prefList.iterator(); iter
0734: .hasNext();) {
0735: PreferenceType element = (PreferenceType) iter
0736: .next();
0737: boolean modifiable = true;
0738: if (element.getReadOnly() != null
0739: && element.getReadOnly().trim().equals(
0740: "true")) {
0741: modifiable = false;
0742: }
0743:
0744: String prefName = element.getName().getValue();
0745: List prefValueList = element.getValue();
0746: String[] prefValues = new String[prefValueList
0747: .size()];
0748: for (int j = 0; j < prefValueList.size(); j++) {
0749: prefValues[j] = ((ValueType) prefValueList
0750: .get(j)).getValue();
0751: }
0752: prefMap.put(prefName,
0753: new PortletPreferencesImpl.PrefInfo(
0754: prefName, modifiable, prefValues));
0755:
0756: }
0757: }
0758: }
0759:
0760: PortletConfigInfo pcInfo = new PortletConfigInfo(portletName,
0761: prefMap, pConfig, prefValidator, portletType,
0762: contextPath, servletURI);
0763:
0764: // Set default values for title, short title, and keywords
0765: pcInfo.shortTitle = shortTitleStr;
0766: pcInfo.title = titleStr;
0767: pcInfo.keywords = keywordStr;
0768:
0769: // Create portlet instance only if it is local context and we did not
0770: // come across an error in creating portlet validator
0771: if (contextPath == null) {
0772: if (prefValidatorError == null) {
0773: createPortlet(pcInfo);
0774: } else {
0775: pcInfo.loadError = StringUtil
0776: .getErrorStackTraceString(prefValidatorError);
0777: pcInfo.loadStatus = PortletConfigInfo.PORTLET_STATUS_PREF_VALIDATOR_ERROR;
0778: }
0779: } else {
0780: pcInfo.loadStatus = PortletConfigInfo.PORTLET_STATUS_LOADED;
0781: }
0782:
0783: List pDescrList = portletType.getDescription();
0784:
0785: for (int j = 0; j < pDescrList.size(); j++) {
0786: DescriptionType dType = (DescriptionType) pDescrList.get(j);
0787: String lang = dType.getLang() == null ? "" : dType
0788: .getLang();
0789: String country = "";
0790: if (lang.indexOf("_") > 0) {
0791: String[] temp = StringUtil.split(lang, "_");
0792: lang = temp[0];
0793: country = temp[1];
0794: }
0795:
0796: // Set default description if this is the first entry. This
0797: // may get overwritten later if the file defines a description
0798: // without a locale specification.
0799: if (j == 0)
0800: pcInfo.description = dType.getValue();
0801: if (lang.equals("")) {
0802: pcInfo.description = dType.getValue();
0803: } else {
0804: pcInfo.localizedDescriptions.put(new Locale(lang,
0805: country), dType.getValue());
0806:
0807: }
0808: }
0809:
0810: List pDisplayList = portletType.getDisplayName();
0811: for (int j = 0; j < pDisplayList.size(); j++) {
0812: DisplayNameType dType = (DisplayNameType) pDisplayList
0813: .get(j);
0814: String lang = dType.getLang() == null ? "" : dType
0815: .getLang();
0816: String country = "";
0817: if (lang.indexOf("_") > 0) {
0818: String[] temp = StringUtil.split(lang, "_");
0819: lang = temp[0];
0820: country = temp[1];
0821: }
0822: // Set default description if this is the first entry. This
0823: // may get overwritten later if the file defines a description
0824: // without a locale specification.
0825: if (j == 0)
0826: pcInfo.displayName = dType.getValue();
0827: if (lang.equals("")) {
0828: pcInfo.displayName = dType.getValue();
0829: } else {
0830: pcInfo.localizedDisplayNames.put(new Locale(lang,
0831: country), dType.getValue());
0832: }
0833: }
0834:
0835: List roleRefList = portletType.getSecurityRoleRef();
0836: for (int j = 0; j < roleRefList.size(); j++) {
0837: SecurityRoleRefType dType = (SecurityRoleRefType) roleRefList
0838: .get(j);
0839:
0840: String roleLink = null;
0841: if (dType.getRoleLink() == null)
0842: roleLink = dType.getRoleName();
0843: else
0844: roleLink = dType.getRoleLink().getValue();
0845:
0846: pcInfo.securityRoleMapping.put(dType.getRoleName(),
0847: roleLink);
0848: }
0849:
0850: List localeList = portletType.getSupportedLocale();
0851: for (int j = 0; j < localeList.size(); j++) {
0852: SupportedLocaleType dType = (SupportedLocaleType) localeList
0853: .get(j);
0854: if (j == 0)
0855: pcInfo.defaultLocale = dType.getValue();
0856: pcInfo.localeSupport.put(dType.getValue(), "");
0857: }
0858:
0859: List supportList = portletType.getSupports();
0860:
0861: if (supportList == null || supportList.size() == 0) {
0862: // Portlets should at least support view mode for text/html
0863: HashMap modeMap = new HashMap(1);
0864: modeMap.put("view", "");
0865: pcInfo.mimeTypeSupport.put(MimeTypes.HTML, modeMap);
0866: } else {
0867: for (int j = 0; j < supportList.size(); j++) {
0868: SupportsType dType = (SupportsType) supportList.get(j);
0869: MimeTypeType mType = dType.getMimeType();
0870: String mTypeStr = mType.getValue().toLowerCase();
0871: List modeList = dType.getPortletMode();
0872: HashMap modeMap = new HashMap(5);
0873: for (int k = 0; k < modeList.size(); k++) {
0874: PortletModeType pmType = (PortletModeType) modeList
0875: .get(k);
0876: String modeStr = pmType.getValue().toLowerCase();
0877: modeMap.put(modeStr, "");
0878: }
0879: // All portlets support "view" mode
0880: modeMap.put("view", "");
0881:
0882: if (mTypeStr.equals("*") || mTypeStr.equals("*/*")) {
0883: // Add the portlet modes to all supported mime types
0884: pcInfo.mimeTypeSupport.put(MimeTypes.HTML, modeMap);
0885: pcInfo.mimeTypeSupport.put(MimeTypes.WML, modeMap);
0886: pcInfo.mimeTypeSupport.put(MimeTypes.XHTML_MP,
0887: modeMap);
0888: } else if (mTypeStr.equals("text/*")) {
0889: pcInfo.mimeTypeSupport.put(MimeTypes.HTML, modeMap);
0890: pcInfo.mimeTypeSupport.put(MimeTypes.WML, modeMap);
0891: }
0892: pcInfo.mimeTypeSupport.put(mTypeStr.trim(), modeMap);
0893: }
0894: }
0895:
0896: ExpirationCacheType exType = portletType.getExpirationCache();
0897: if (exType != null)
0898: pcInfo.expirationCache = exType.getValue();
0899:
0900: // Add PortletConfigInfo in appropriate maps, lists, etc.
0901: addPortletEntry(pcInfo, index, keywordArray);
0902:
0903: if (pcInfo.loadError == null)
0904: info("Successfully loaded portlet " + portletName);
0905: }
0906:
0907: public boolean requiresSecureAccess(String portletName) {
0908: if (psSecurePortlets.get(portletName) == null) {
0909: return false;
0910: }
0911:
0912: return true;
0913: }
0914:
0915: public PortletAppImpl getPortletConfiguration() {
0916: return psPortletApp;
0917: }
0918:
0919: public HashMap getSecurePortlets() {
0920: return psSecurePortlets;
0921: }
0922:
0923: public boolean isWindowStateSupported(String wState) {
0924: return psSupportedWindowStates.get(wState) == null ? false
0925: : true;
0926: }
0927:
0928: public boolean isPortletModeSupported(String pMode) {
0929: return psSupportedPortletModes.get(pMode) == null ? false
0930: : true;
0931: }
0932:
0933: public boolean isPortletExists(String portletName) {
0934: if (psPortletMap.get(portletName) == null)
0935: return false;
0936: return true;
0937: }
0938:
0939: protected void initAbstractServlet(ServletConfig config)
0940: throws ServletException {
0941: super .init(config);
0942: }
0943:
0944: public Vector getPortletConfigInfoList() {
0945: return psPortletList;
0946: }
0947:
0948: private void setPortletStatusAttributes(
0949: PortletConfigInfo pConfigInfo, HttpServletRequest request) {
0950: request.setAttribute(PortalConstants.PORTLET_STATUS_ATTRIB,
0951: new Integer(pConfigInfo.loadStatus));
0952: request.removeAttribute(PortalConstants.LOAD_ERROR_ATTRIB);
0953: request
0954: .removeAttribute(PortalConstants.LOAD_ERROR_STACK_TRACE_ATTRIB);
0955: if (pConfigInfo.loadError != null) {
0956: request.setAttribute(PortalConstants.LOAD_ERROR_ATTRIB,
0957: pConfigInfo.loadError);
0958: request.setAttribute(
0959: PortalConstants.LOAD_ERROR_STACK_TRACE_ATTRIB,
0960: pConfigInfo.loadErrorStackTrace);
0961: }
0962:
0963: }
0964:
0965: protected void setPortletStatus(PortletConfigInfo pConfigInfo,
0966: HttpServletRequest request) {
0967: Integer statCode = (Integer) request
0968: .getAttribute(PortalConstants.PORTLET_STATUS_ATTRIB);
0969: if (statCode != null) {
0970: pConfigInfo.loadStatus = statCode.intValue();
0971: pConfigInfo.loadError = (String) request
0972: .getAttribute(PortalConstants.LOAD_ERROR_ATTRIB);
0973: pConfigInfo.loadErrorStackTrace = (String) request
0974: .getAttribute(PortalConstants.LOAD_ERROR_STACK_TRACE_ATTRIB);
0975: } else {
0976: pConfigInfo.loadStatus = PortletConfigInfo.PORTLET_STATUS_INSTANTIATION_ERROR;
0977: pConfigInfo.loadError = "Portlet Servlet has not been loaded or misconfigured.";
0978: pConfigInfo.loadErrorStackTrace = "";
0979:
0980: }
0981: }
0982:
0983: @SuppressWarnings({"unchecked","unchecked"})
0984: public void addPortletEntry(PortletConfigInfo pcInfo, int index,
0985: String[] keywordArray) {
0986: final String[] unClassifiedCategory = new String[] { "Unclassified" };
0987: if (keywordArray == null)
0988: keywordArray = unClassifiedCategory;
0989: pcInfo.keywordArray = keywordArray;
0990: for (int j = 0; j < keywordArray.length; j++) {
0991: String category = keywordArray[j].trim();
0992: Vector pVec = (Vector) psCategories.get(category);
0993: if (pVec == null) {
0994: pVec = new Vector(15);
0995: pVec.addElement(pcInfo);
0996: psCategories.put(category, pVec);
0997: } else {
0998: pVec.addElement(pcInfo);
0999: }
1000: }
1001:
1002: psPortletMap.put(pcInfo.name, pcInfo);
1003: if (index > -1) {
1004: psPortletList.insertElementAt(pcInfo, index);
1005: } else {
1006: if (pcInfo.contextPath == null
1007: && psPortletList.size() < psPortletApp.getPortlet()
1008: .size()) {
1009: // This happens during initialization
1010: psPortletList.addElement(pcInfo);
1011: } else {
1012: psPortletList.insertElementAt(pcInfo, psPortletApp
1013: .getPortlet().size());
1014: }
1015: }
1016:
1017: }
1018:
1019: public HashMap getSupportedPortletModes() {
1020: return psSupportedPortletModes;
1021: }
1022:
1023: public HashMap getSupportedWindowStates() {
1024: return psSupportedWindowStates;
1025: }
1026:
1027: public void destroy() {
1028: for (int i = 0; i < psPortletList.size(); i++) {
1029: PortletConfigInfo pcInfo = (PortletConfigInfo) psPortletList
1030: .elementAt(i);
1031: if (pcInfo == null)
1032: continue;
1033: if (pcInfo.contextPath == null) { // local portlet only
1034: if (pcInfo.portlet != null) {
1035: pcInfo.portlet.destroy();
1036: pcInfo.portlet = null;
1037: }
1038: }
1039:
1040: }
1041: }
1042:
1043: }
|