0001: /*
0002: * Copyright 2004-2005 Sun Microsystems, Inc. All rights reserved.
0003: * PROPRIETARY/CONFIDENTIAL. Use of this product is subject to license terms.
0004: */
0005: package com.sun.portal.desktop.context;
0006:
0007: import java.util.*;
0008: import java.util.logging.Logger;
0009: import java.util.logging.Level;
0010: import java.util.logging.LogRecord;
0011:
0012: import javax.servlet.http.HttpServletRequest;
0013: import javax.servlet.http.HttpServletResponse;
0014: import javax.servlet.ServletContext;
0015: import javax.servlet.ServletConfig;
0016:
0017: import com.sun.portal.providers.Provider;
0018: import com.sun.portal.providers.ProviderException;
0019: import com.sun.portal.providers.portletwindow.PortletWindowProvider;
0020: import com.sun.portal.providers.containers.ContainerProvider;
0021: import com.sun.portal.providers.containers.jsp.tab.JSPTabContainerProvider;
0022: import com.sun.portal.providers.util.ProviderProperties;
0023: import com.sun.portal.providers.context.ContainerProviderContext;
0024: import com.sun.portal.providers.context.ProviderContextException;
0025:
0026: import com.sun.portal.desktop.ServletContextThreadLocalizer;
0027: import com.sun.portal.desktop.ServletConfigThreadLocalizer;
0028: import com.sun.portal.desktop.DesktopRequestThreadLocalizer;
0029: import com.sun.portal.desktop.RequestThreadLocalizer;
0030: import com.sun.portal.desktop.dp.DPHelper;
0031: import com.sun.portal.desktop.dp.FQCN;
0032: import com.sun.portal.desktop.monitoring.MonitoringSubsystem;
0033: import com.sun.portal.desktop.monitoring.MonitoringSubsystemWrapper;
0034:
0035: import com.sun.portal.desktop.ubt.ProviderLogRecord;
0036: import com.sun.portal.desktop.ubt.DesktopEvents;
0037: import com.sun.portal.ubt.UBTLogManager;
0038: import com.sun.portal.ubt.UBTEvent;
0039: import com.sun.portal.ubt.UBTLogField;
0040: import com.sun.portal.log.common.PortalLogger;
0041: import com.sun.portal.monitoring.utilities.ActivityTime;
0042:
0043: public class PSContainerProviderContext extends PSProviderContext
0044: implements ContainerProviderContext {
0045: private static Logger logger = PortalLogger
0046: .getLogger(PSContainerProviderContext.class);
0047:
0048: private static LogRecord getLogRecord(Level level, String message,
0049: Object[] parameters, Throwable t) {
0050: LogRecord result = new LogRecord(level, message);
0051: result.setLoggerName(logger.getName());
0052: result.setParameters(parameters);
0053: result.setThrown(t);
0054: return result;
0055: }
0056:
0057: protected Map providerCache = new HashMap();
0058:
0059: //
0060: // caller pool is initialized to size 0.
0061: // items are added to to the pool as they are used
0062: // and returned. caller pool is allows to expand
0063: // to a very large size, however, in the normal
0064: // case it will only be as big as the number
0065: // of channels on the user's desktop. in cases where
0066: // there are multiple concurrent threads with the same
0067: // sid, the pool may expand to an size that is
0068: // n * m, where n = the number of concurrent same-sid
0069: // threads and m = the number of channels on
0070: // the desktop for the given sid.
0071: //
0072: // we always let the caller pool offer instances beyond the
0073: // max pool size.
0074: //
0075: static private int DEFAULT_MIN_SIZE = 0;
0076: static private int DEFAULT_MAX_SIZE = 10000;
0077: static private int DEFAULT_PARTITION_SIZE = 13;
0078:
0079: static protected ProviderCallerPool callerPool = null;
0080: static protected ProviderGetterPool getterPool = null;
0081:
0082: protected Map cachedContent = new HashMap();
0083: protected Map cachedTime = new HashMap();
0084:
0085: private long lastClassLoaderCheckTimer = 0;
0086: static private String CHECK_PROVIDER_CLASS_LOADER = "checkProviderClassLoader";
0087:
0088: private boolean parallelPortletAllowed = false;
0089: private static final String SUN = "Sun";
0090:
0091: public synchronized void init(HttpServletRequest req) {
0092: super .init(req);
0093:
0094: DesktopAppContext dac = DesktopAppContextThreadLocalizer.get();
0095:
0096: if (callerPool == null) {
0097: initCallerPool(dac);
0098: }
0099: if (getterPool == null) {
0100: initGetterPool(dac);
0101: }
0102:
0103: ServletContext sc = ServletContextThreadLocalizer.get();
0104: // Parallel Portlet execution is allowed only for Sun WebContainers
0105: // and disabled for BEA & IBM.
0106: String serverInfo = sc.getServerInfo();
0107: if (serverInfo != null && serverInfo.indexOf(SUN) >= 0)
0108: parallelPortletAllowed = true;
0109: logger.log(Level.FINEST, "PSDT_CSPDC0038", String
0110: .valueOf(parallelPortletAllowed));
0111: }
0112:
0113: public void refresh() {
0114: super .refresh();
0115:
0116: cachedContent = new HashMap();
0117: cachedTime = new HashMap();
0118:
0119: providerCache.clear();
0120: }
0121:
0122: public void contentChanged(String channel) {
0123: // remove content for channel
0124: removeCachedContent(channel);
0125:
0126: // remove content for channel's display ancestors
0127: HttpServletRequest req = DesktopRequestThreadLocalizer
0128: .getRequest();
0129: Set ancestors = getDesktopContext().getAncestors(req, channel);
0130: if (ancestors != null) {
0131: for (Iterator i = ancestors.iterator(); i.hasNext();) {
0132: String ancestor = (String) i.next();
0133: removeCachedContent(ancestor);
0134: }
0135: }
0136: }
0137:
0138: public void allContentChanged() {
0139: removeAllCachedContent();
0140: }
0141:
0142: public boolean existsChannel(String channel) {
0143: return getPropertiesContext().existsChannel(channel);
0144: }
0145:
0146: public void createChannel(String channelName, String providerName)
0147: throws ProviderContextException {
0148: try {
0149: getPropertiesContext().createChannel(channelName,
0150: providerName);
0151: } catch (ContextError ce) {
0152: throw new ProviderContextException(
0153: "PSContainerProviderContext.createChannel ", ce);
0154: }
0155: }
0156:
0157: public void createContainer(String channelName, String providerName)
0158: throws ProviderContextException {
0159: try {
0160: getPropertiesContext().createContainer(channelName,
0161: providerName);
0162: } catch (ContextError ce) {
0163: throw new ProviderContextException(
0164: "PSContainerProviderContext.createContainer", ce);
0165: }
0166: }
0167:
0168: public void removeChannel(String channelName)
0169: throws ProviderContextException {
0170: try {
0171: getPropertiesContext().removeChannel(channelName);
0172: } catch (ContextError ce) {
0173: throw new ProviderContextException(
0174: "PSContainerProviderContext.removeChannel ", ce);
0175: }
0176: }
0177:
0178: public void copyChannel(String srcName, String dstName)
0179: throws ProviderContextException {
0180: try {
0181: getPropertiesContext().copyChannel(srcName, dstName);
0182: } catch (ContextError ce) {
0183: throw new ProviderContextException(
0184: "PSContainerProviderContext.copyChannel()", ce);
0185: }
0186: }
0187:
0188: public List getSelectedChannels(String container)
0189: throws ProviderContextException {
0190: try {
0191: return getPropertiesContext()
0192: .getSelectedChannels(container);
0193: } catch (ContextError ce) {
0194: throw new ProviderContextException(
0195: "PSContainerProviderContext.getSelectedChannels ",
0196: ce);
0197: }
0198: }
0199:
0200: public List getAvailableChannels(String container)
0201: throws ProviderContextException {
0202: try {
0203: return getPropertiesContext().getAvailableChannels(
0204: container);
0205: } catch (ContextError ce) {
0206: throw new ProviderContextException(
0207: "PSContainerProviderContext.getAvailableChannels ",
0208: ce);
0209: }
0210: }
0211:
0212: public void setSelectedChannels(String container, List sel)
0213: throws ProviderContextException {
0214: try {
0215: getPropertiesContext().setSelectedChannels(container, sel);
0216: } catch (ContextError ce) {
0217: throw new ProviderContextException(
0218: "PSContainerProviderContext.setSelectedChannels ",
0219: ce);
0220: }
0221: }
0222:
0223: public void setAvailableChannels(String container, List avail)
0224: throws ProviderContextException {
0225: try {
0226: getPropertiesContext().setAvailableChannels(container,
0227: avail);
0228: } catch (ContextError ce) {
0229: throw new ProviderContextException(
0230: "PSContainerProviderContext.setAvailableChannels ",
0231: ce);
0232: }
0233: }
0234:
0235: public Provider getProvider(HttpServletRequest req, String parent,
0236: String channel) {
0237: Provider p = (Provider) providerCache.get(channel);
0238: DesktopContext dc = getDesktopContext();
0239: DesktopAppContext dac = DesktopAppContextThreadLocalizer.get();
0240:
0241: if (p == null) {
0242: try {
0243: p = initProvider(req, parent, channel);
0244: } catch (ProviderContextException pce) {
0245: if (logger.isLoggable(Level.WARNING)) {
0246: logger.log(getLogRecord(Level.WARNING,
0247: "PSDT_CSPDC0004", new Object[] { channel },
0248: pce));
0249: }
0250: }
0251:
0252: if (p != null) {
0253: synchronized (providerCache) {
0254: if (providerCache.get(channel) == null) {
0255: providerCache.put(channel, p);
0256: }
0257: }
0258: }
0259: } else {
0260: // Make sure the provider class loader is still valid.
0261: // Only done for authless desktop (see bug 4840480).
0262:
0263: // Note: We only use a flag to mark requests we need to check
0264: // and all the subsequence calls to getProvider() will be tested.
0265: // This means it is possible that a provider is checked more than
0266: // once if a desktop uses the same provider for different channels.
0267: // It is possible to put logic to make sure each provider is only
0268: // checked once, but the piece of code is only executed for authless
0269: // desktop and executed far apart (default 1 hour). The potential
0270: // performance gain does not warrant the extra logic.
0271:
0272: long currentTime = System.currentTimeMillis();
0273: String providerClassName;
0274:
0275: if (isAuthless(req)) {
0276: if (req.getAttribute(CHECK_PROVIDER_CLASS_LOADER) != null
0277: || (currentTime - lastClassLoaderCheckTimer > 1000 * dac
0278: .getClassLoaderRevalidateInterval())) {
0279:
0280: //Update the timer and mark the req, so all checking can be
0281: //done for all the providers in the request.
0282:
0283: lastClassLoaderCheckTimer = System
0284: .currentTimeMillis();
0285: req.setAttribute(CHECK_PROVIDER_CLASS_LOADER,
0286: Boolean.TRUE);
0287:
0288: try {
0289: providerClassName = getClassName(channel);
0290: ProviderClassLoader pcl = ProviderClassLoader
0291: .getInstance(providerClassName, dc
0292: .getProviderClassBaseDir());
0293: } catch (ProviderContextException pce) {
0294: if (logger.isLoggable(Level.WARNING)) {
0295: logger.log(getLogRecord(Level.WARNING,
0296: "PSDT_CSPDC0005",
0297: new Object[] { channel }, pce));
0298: }
0299: }
0300: }
0301: }
0302: }
0303:
0304: return p;
0305: }
0306:
0307: private Provider initProvider(HttpServletRequest req,
0308: String parent, String channel)
0309: throws ProviderContextException {
0310: //
0311: // get the fqName for the CP
0312: //
0313: String providerClassName;
0314:
0315: providerClassName = getClassName(channel);
0316: if (providerClassName == null) {
0317: return null;
0318: }
0319:
0320: //
0321: // catch if class cannot be found. this is either webserver
0322: // config problem or user error. solution for now will be to
0323: // simply print the error message to the logs and not init
0324: // the provider.
0325: //
0326: // TBD(jtb):perhaps a better solution for the future would be to draw
0327: // a "dummy" provider box and fill in some error text. this would
0328: // be considerable work because we'd either need to fake the existence
0329: // of a provider object, or have some actually DummyProvider
0330: // class
0331: //
0332:
0333: Provider p = null;
0334: DesktopContext dc = getDesktopContext();
0335:
0336: try {
0337: ProviderClassLoader pcl = ProviderClassLoader.getInstance(
0338: providerClassName, dc.getProviderClassBaseDir());
0339: Class pclClass = pcl.loadClass(providerClassName);
0340:
0341: if (pclClass == null) {
0342: if (logger.isLoggable(Level.INFO)) {
0343: logger.log(Level.INFO, "PSDT_CSPDC0006",
0344: new String[] { providerClassName, channel,
0345: parent });
0346: }
0347: return null;
0348: }
0349:
0350: p = (Provider) pclClass.newInstance();
0351: p.init(channel, req);
0352:
0353: } catch (NoClassDefFoundError ncdfe) {
0354: if (logger.isLoggable(Level.INFO)) {
0355: logger.log(Level.INFO, "PSDT_CSPDC0003", ncdfe);
0356: }
0357: } catch (IllegalAccessException iae) {
0358: if (logger.isLoggable(Level.INFO)) {
0359: logger.log(Level.INFO, "PSDT_CSPDC0003", iae);
0360: }
0361: } catch (ClassCastException cce) {
0362: if (logger.isLoggable(Level.INFO)) {
0363: logger.log(Level.INFO, "PSDT_CSPDC0003", cce);
0364: }
0365: } catch (InstantiationException ie) {
0366: if (logger.isLoggable(Level.INFO)) {
0367: logger.log(Level.INFO, "PSDT_CSPDC0003", ie);
0368: }
0369: } catch (SecurityException se) {
0370: if (logger.isLoggable(Level.INFO)) {
0371: logger.log(Level.INFO, "PSDT_CSPDC0003", se);
0372: }
0373: } catch (ProviderException pe) {
0374: if (logger.isLoggable(Level.INFO)) {
0375: logger.log(Level.INFO, "PSDT_CSPDC0003", pe);
0376: }
0377: } catch (ClassNotFoundException cnfe) {
0378: if (logger.isLoggable(Level.INFO)) {
0379: logger.log(Level.INFO, "PSDT_CSPDC0003", cnfe);
0380: }
0381: }
0382:
0383: lastClassLoaderCheckTimer = System.currentTimeMillis();
0384: return p;
0385: }
0386:
0387: public void initProviders(HttpServletRequest req, String parent,
0388: List providers, int timeout) {
0389: // pre-init providers
0390: Monitor monitor = new Monitor();
0391: Map getters = new HashMap();
0392:
0393: DesktopAppContext dac = DesktopAppContextThreadLocalizer.get();
0394: DesktopContext dc = DesktopContextThreadLocalizer.get();
0395: ServletContext sc = ServletContextThreadLocalizer.get();
0396: HttpServletRequest origReq = RequestThreadLocalizer
0397: .getRequest();
0398: HttpServletResponse origRes = RequestThreadLocalizer
0399: .getResponse();
0400:
0401: HttpServletResponse res = DesktopRequestThreadLocalizer
0402: .getResponse();
0403:
0404: for (int i = 0; i < providers.size(); i++) {
0405: String channel = (String) providers.get(i);
0406: monitor.addTask();
0407: //ProviderGetter getter = new ProviderGetter(this, parent, channel, monitor, req);
0408: //getter.start();
0409:
0410: ReusableProviderGetter getter = getterPool.obtainGetter(
0411: dac, dc, this , parent, channel, monitor, req, res,
0412: origReq, origRes, sc);
0413:
0414: if (getter == null) {
0415: if (logger.isLoggable(Level.INFO)) {
0416: logger.info("PSDT_CSPDC0007");
0417: }
0418: continue;
0419: }
0420:
0421: getter.execute();
0422: getters.put(channel, getter);
0423: }
0424:
0425: monitor.start();
0426: if (!monitor.isDoneWaiting(timeout)) {
0427: if (logger.isLoggable(Level.INFO)) {
0428: logger.log(Level.INFO, "PSDT_CSPDC0008", monitor
0429: .getCompleted());
0430: }
0431: }
0432:
0433: // interrupt all the threads that are still working.
0434: for (Iterator i = getters.keySet().iterator(); i.hasNext();) {
0435: String providerName = (String) i.next();
0436: if (!monitor.contains(providerName)) {
0437: ReusableProviderGetter getter = (ReusableProviderGetter) getters
0438: .get(providerName);
0439: getter.interrupt();
0440: }
0441: }
0442: }
0443:
0444: protected synchronized void removeCachedContent(String name) {
0445: cachedContent.remove(name);
0446: cachedTime.remove(name);
0447: }
0448:
0449: protected synchronized void removeAllCachedContent() {
0450: cachedContent.clear();
0451: cachedTime.clear();
0452: }
0453:
0454: public synchronized void putCachedContent(String name,
0455: StringBuffer content) {
0456: cachedContent.put(name, content);
0457: cachedTime.put(name,
0458: new Long(System.currentTimeMillis() / 1000));
0459: }
0460:
0461: public StringBuffer getCachedContent(String name) {
0462: return (StringBuffer) cachedContent.get(name);
0463: }
0464:
0465: public long getCachedTime(String name) {
0466: Long t = (Long) cachedTime.get(name);
0467:
0468: if (t == null) {
0469: return 0;
0470: }
0471:
0472: return t.longValue();
0473: }
0474:
0475: public StringBuffer getContent(HttpServletRequest req,
0476: HttpServletResponse res, String parent, String name)
0477: throws ProviderException {
0478: ActivityTime activityTime = new ActivityTime();
0479: FQCN fqcn = DPHelper.getFQCN(DesktopContextThreadLocalizer
0480: .get().getDPRoot(), name);
0481: MonitoringSubsystemWrapper.getDesktopMonitoringSubsystem()
0482: .getContentChannelActionStatistic().mark(activityTime);
0483: Provider p = getProvider(req, parent, name);
0484:
0485: if (p == null) {
0486: MonitoringSubsystemWrapper.getDesktopMonitoringSubsystem()
0487: .getContentChannelActionStatistic().measure(
0488: activityTime, fqcn.plain());
0489: return null;
0490: }
0491:
0492: if (!p.isPresentable(req)) {
0493: // channel is not presentable for this client type
0494: // return null.
0495: MonitoringSubsystemWrapper.getDesktopMonitoringSubsystem()
0496: .getContentChannelActionStatistic().measure(
0497: activityTime, fqcn.plain());
0498: return null;
0499: }
0500: long refreshTime = 0;
0501:
0502: try {
0503: refreshTime = p.getRefreshTime();
0504: } catch (ProviderException pe) {
0505: if (logger.isLoggable(Level.INFO)) {
0506: logger.log(getLogRecord(Level.INFO, "PSDT_CSPDC0009",
0507: new Object[] { name }, pe));
0508: }
0509: }
0510: long timeCached = getCachedTime(name);
0511: long now = System.currentTimeMillis() / 1000;
0512:
0513: StringBuffer content = getCachedContent(name);
0514: if ((content == null)
0515: || ((timeCached != -1) && (now >= (timeCached + refreshTime)))) {
0516: MonitoringSubsystemWrapper.getDesktopMonitoringSubsystem()
0517: .startProviderServiceTransaction(fqcn.encoded(),
0518: MonitoringSubsystem.CHANNEL_ACTION_CONTENT);
0519: if (logger.isLoggable(Level.FINEST)) {
0520: logger.log(Level.FINEST, "PSDT_CSPDC0028", p.getName());
0521: }
0522:
0523: //
0524: // 1) there was no cached content for the channel OR
0525: // 2) the time cached was set NOT to -1 AND
0526: // 3) the refresh time has expired
0527:
0528: //check if parent container name is set. if set save the old value.
0529: String oldParent = ParentContainerThreadLocalizer.get();
0530:
0531: //set the new parent
0532: ParentContainerThreadLocalizer.set(parent);
0533:
0534: // store visible portlets in session (for IPC)
0535: if (p instanceof ContainerProvider) {
0536: try {
0537: // if this is the top-level container
0538: if (getBooleanProperty(name, "isTopLevel", false)) {
0539: // Clear the list of portlets in desktopSession
0540: setSessionProperty(
0541: ProviderProperties.TAB_PORTLET_LIST,
0542: null);
0543: }
0544: Set portlets = new TreeSet();
0545: createVisiblePortletsList(req, p, portlets);
0546: if (portlets.size() > 0) {
0547: Set portletSet = (Set) getSessionProperty(ProviderProperties.TAB_PORTLET_LIST);
0548: if (portletSet != null) {
0549: portlets.addAll(portletSet);
0550: }
0551: setSessionProperty(
0552: ProviderProperties.TAB_PORTLET_LIST,
0553: portlets);
0554: }
0555: } catch (ProviderContextException pce) {
0556: if (logger.isLoggable(Level.WARNING)) {
0557: logger.log(getLogRecord(Level.WARNING,
0558: "PSDT_CSPDC0033",
0559: new Object[] { parent }, pce));
0560: }
0561: }
0562: }
0563: //
0564: // get fresh content
0565: //
0566: try {
0567: content = p.getContent(req, res);
0568:
0569: //set the parent container to the old parent.
0570: ParentContainerThreadLocalizer.set(oldParent);
0571:
0572: if (refreshTime > 0) {
0573: putCachedContent(p.getName(), content);
0574: }
0575:
0576: try {
0577: UBTLogManager manager = UBTLogManager.getInstance();
0578: if (manager.isUBTEnabled()) {
0579: UBTEvent prov_ren = UBTEvent
0580: .getInstance(DesktopEvents.PROVIDER_RENDER_FRESH);
0581: prov_ren.put(UBTLogField.CHANNEL_NAME, name);
0582: prov_ren.put(UBTLogField.PROVIDER, p.getClass()
0583: .getName());
0584: prov_ren.put(UBTLogField.CONTAINER_NAME, this
0585: .getParentContainerName(name));
0586: prov_ren.put(UBTLogField.ACTION, "Content");
0587: manager.logEvent(new ProviderLogRecord(
0588: prov_ren, req, res, this .getUserID()));
0589: }
0590: } catch (Exception e) {
0591: ; // ok to ignore
0592: }
0593: } finally {
0594: MonitoringSubsystemWrapper
0595: .getDesktopMonitoringSubsystem()
0596: .stopProviderServiceTransaction(
0597: fqcn.encoded(),
0598: MonitoringSubsystem.CHANNEL_ACTION_CONTENT);
0599: MonitoringSubsystemWrapper
0600: .getDesktopMonitoringSubsystem()
0601: .getContentChannelActionStatistic().measure(
0602: activityTime, fqcn.plain());
0603: }
0604: } else {
0605: MonitoringSubsystemWrapper.getDesktopMonitoringSubsystem()
0606: .startProviderServiceTransaction(fqcn.encoded(),
0607: MonitoringSubsystem.CACHED_CONTENT);
0608: //
0609: // use the cached copy
0610: //
0611: if (logger.isLoggable(Level.FINEST)) {
0612: logger.log(Level.FINEST, "PSDT_CSPDC0029", p.getName());
0613: }
0614:
0615: try {
0616: UBTLogManager manager = UBTLogManager.getInstance();
0617: if (manager.isUBTEnabled()) {
0618: UBTEvent prov_ren = UBTEvent
0619: .getInstance(DesktopEvents.PROVIDER_RENDER_CACHE);
0620: prov_ren.put(UBTLogField.CHANNEL_NAME, p.getName());
0621: prov_ren.put(UBTLogField.PROVIDER, p.getClass()
0622: .getName());
0623: prov_ren.put(UBTLogField.CONTAINER_NAME, this
0624: .getParentContainerName(p.getName()));
0625: prov_ren.put(UBTLogField.ACTION, "Content");
0626: manager.logEvent(new ProviderLogRecord(prov_ren,
0627: req, res, this .getUserID()));
0628: }
0629: } catch (Exception e) {
0630: ; // ok to ignore
0631: }
0632:
0633: MonitoringSubsystemWrapper.getDesktopMonitoringSubsystem()
0634: .stopProviderServiceTransaction(fqcn.encoded(),
0635: MonitoringSubsystem.CACHED_CONTENT);
0636: MonitoringSubsystemWrapper.getDesktopMonitoringSubsystem()
0637: .getChannelCacheHitsStatistic().measure(
0638: activityTime, fqcn.plain());
0639: }
0640:
0641: return content;
0642: }
0643:
0644: private void createVisiblePortletsList(HttpServletRequest req,
0645: Provider p, Set portlets) throws ProviderContextException,
0646: ProviderException {
0647: if (p instanceof JSPTabContainerProvider) {
0648: String selected = req.getParameter(p.getName()
0649: + ".setSelected");
0650: if ((selected != null) && (selected.length() > 0)) {
0651: return;
0652: }
0653: String name = ((JSPTabContainerProvider) p)
0654: .getSelectedTab().getName();
0655: Provider provider = getProvider(req, p.getName(), name);
0656: createVisiblePortletsList(req, provider, portlets);
0657: } else if (p instanceof ContainerProvider) {
0658: ContainerProvider cp = (ContainerProvider) p;
0659: List channelList = cp.getSelectedChannels();
0660: for (int i = 0; i < channelList.size(); i++) {
0661: String name = (String) channelList.get(i);
0662: Provider provider = getProvider(req, p.getName(), name);
0663: createVisiblePortletsList(req, provider, portlets);
0664: }
0665: } else {
0666: if (p instanceof PortletWindowProvider) {
0667: String entity = getStringProperty(p.getName(),
0668: "entityIDPrefix")
0669: + "|" + p.getName();
0670: portlets.add(entity);
0671: }
0672: }
0673: }
0674:
0675: public Map getContent(HttpServletRequest req,
0676: HttpServletResponse res, String parent, List providers,
0677: int timeout) throws ProviderException {
0678: Monitor monitor = new Monitor();
0679: Map content = new HashMap();
0680: Map callers = new HashMap();
0681:
0682: List parallelProviders;
0683: if (!parallelPortletAllowed) {
0684: // when running on web containers that does not allow parallel execution
0685: // of portlets such as IBM & BEA, sequentially execute all the portlets
0686: // (wsrp and local portlets) before executing providers in parallel
0687: parallelProviders = new java.util.ArrayList(providers
0688: .size());
0689: for (int i = 0; i < providers.size(); i++) {
0690: String channel = (String) providers.get(i);
0691: if (isPortlet(channel)) {
0692: StringBuffer channelContent = null;
0693: try {
0694: channelContent = getContent(req, res, parent,
0695: channel);
0696: } catch (Throwable t) {
0697: if (logger.isLoggable(Level.INFO)) {
0698: logger.log(getLogRecord(Level.INFO,
0699: "PSDT_CSPDC0010",
0700: new Object[] { channel }, t));
0701: }
0702: }
0703: content.put(channel, channelContent);
0704: } else {
0705: parallelProviders.add(channel);
0706: }
0707: }
0708: } else {
0709: parallelProviders = providers;
0710: }
0711:
0712: DesktopAppContext dac = DesktopAppContextThreadLocalizer.get();
0713: DesktopContext dc = DesktopContextThreadLocalizer.get();
0714: ServletContext sc = ServletContextThreadLocalizer.get();
0715: ServletConfig scfg = ServletConfigThreadLocalizer.get();
0716: HttpServletRequest origReq = RequestThreadLocalizer
0717: .getRequest();
0718: HttpServletResponse origRes = RequestThreadLocalizer
0719: .getResponse();
0720: Map detachedChannels = null;
0721: String maximizedChannel = null;
0722: boolean existMaximizedChannel = false;
0723: Map minimizedChannels = null;
0724: try {
0725: //Check if there is any channel which is maximized
0726: existMaximizedChannel = existsStringProperty(parent,
0727: ProviderProperties.MAXIMIZED_CHANNEL);
0728: //Get the name of maximized channel if it exists
0729: if (existMaximizedChannel) {
0730: maximizedChannel = getStringProperty(parent,
0731: ProviderProperties.MAXIMIZED_CHANNEL);
0732:
0733: // If maximized channel was removed from dp.
0734: if (!(providers.contains(maximizedChannel))) {
0735: existMaximizedChannel = false;
0736: }
0737:
0738: }
0739:
0740: //Get the collection of channels which are minimized
0741: minimizedChannels = getCollectionPropertyIE(parent,
0742: ProviderProperties.CHANNELS_IS_MINIMIZED);
0743:
0744: //Get the collection of channels which are detached
0745: detachedChannels = getCollectionPropertyIE(parent,
0746: ProviderProperties.CHANNELS_IS_DETACHED);
0747: } catch (ProviderContextException pce) {
0748: if (logger.isLoggable(Level.INFO)) {
0749: logger.log(getLogRecord(Level.INFO, "PSDT_CSPDC0011",
0750: new Object[] { parent }, pce));
0751: }
0752: }
0753:
0754: FQCN fqcn = null;
0755: for (int i = 0; i < parallelProviders.size(); i++) {
0756: ActivityTime activityTime2 = new ActivityTime();
0757: MonitoringSubsystemWrapper.getDesktopMonitoringSubsystem()
0758: .getChannelCacheHitsStatistic().mark(activityTime2);
0759:
0760: String channel = (String) parallelProviders.get(i);
0761: fqcn = DPHelper.getFQCN(dc.getDPRoot(), channel);
0762: Provider p = getProvider(req, parent, channel);
0763:
0764: //in case initProvider failed, skip this provider
0765: if (p == null) {
0766: continue;
0767: }
0768:
0769: // check whether the provider is presentable for this client type
0770: if (!p.isPresentable(req)) {
0771: // channel is not presentable for the client type
0772: // skip this provider
0773: continue;
0774: }
0775:
0776: //Get the content of maximized channel only, if it exists.
0777: if (existMaximizedChannel && maximizedChannel != null
0778: && maximizedChannel.trim().length() > 0) {
0779: if (!channel.equalsIgnoreCase(maximizedChannel))
0780: continue;
0781: }
0782:
0783: //if the channel is detached, don't get the content
0784: if (checkChannel(detachedChannels, channel))
0785: continue;
0786:
0787: //if the channel is minimized, don't get the content
0788: if (checkChannel(minimizedChannels, channel))
0789: continue;
0790:
0791: long refreshTime = 0;
0792: try {
0793: refreshTime = p.getRefreshTime();
0794: } catch (ProviderException pe) {
0795: if (logger.isLoggable(Level.INFO)) {
0796: logger.log(getLogRecord(Level.INFO,
0797: "PSDT_CSPDC0009", new Object[] { channel },
0798: pe));
0799: }
0800: }
0801: long timeCached = getCachedTime(channel);
0802: long now = System.currentTimeMillis() / 1000;
0803:
0804: //
0805: // see if content is cached
0806: //
0807: StringBuffer channelContent = getCachedContent(channel);
0808: if ((channelContent == null)
0809: || ((timeCached != -1) && (now >= (timeCached + refreshTime)))) {
0810: if (logger.isLoggable(Level.FINEST)) {
0811: logger.log(Level.FINEST, "PSDT_CSPDC0028", p
0812: .getName());
0813: }
0814:
0815: //
0816: // 1) there was no cached content for the channel OR
0817: // 2) the time cached was set NOT to -1 AND
0818: // 3) the refresh time has expired
0819: //
0820: // get fresh content
0821: //
0822: monitor.addTask();
0823:
0824: ReusableProviderCaller caller = callerPool
0825: .obtainCaller(dac, dc, this , p, parent,
0826: monitor, req, res, origReq, origRes,
0827: scfg, sc);
0828: if (caller == null) {
0829: if (logger.isLoggable(Level.INFO)) {
0830: logger.info("PSDT_CSPDC0012");
0831: }
0832: continue;
0833: }
0834:
0835: caller.execute();
0836: callers.put(p.getName(), caller);
0837: try {
0838: UBTLogManager manager = UBTLogManager.getInstance();
0839: if (manager.isUBTEnabled()) {
0840: UBTEvent prov_ren = UBTEvent
0841: .getInstance(DesktopEvents.PROVIDER_RENDER_FRESH);
0842: prov_ren.put(UBTLogField.CHANNEL_NAME, p
0843: .getName());
0844: prov_ren.put(UBTLogField.PROVIDER, p.getClass()
0845: .getName());
0846: prov_ren.put(UBTLogField.CONTAINER_NAME, this
0847: .getParentContainerName(p.getName()));
0848: prov_ren.put(UBTLogField.ACTION, "Content");
0849: manager.logEvent(new ProviderLogRecord(
0850: prov_ren, req, res, this .getUserID()));
0851: }
0852: } catch (Exception e) {
0853: ; // ok to ignore
0854: }
0855: } else {
0856: MonitoringSubsystemWrapper
0857: .getDesktopMonitoringSubsystem()
0858: .startProviderServiceTransaction(
0859: fqcn.encoded(),
0860: MonitoringSubsystem.CACHED_CONTENT);
0861: //
0862: // use the cached copy
0863: //
0864: if (logger.isLoggable(Level.FINEST)) {
0865: logger.log(Level.FINEST, "PSDT_CSPDC0029", p
0866: .getName());
0867: }
0868: content.put(channel, channelContent);
0869: try {
0870: UBTLogManager manager = UBTLogManager.getInstance();
0871: if (manager.isUBTEnabled()) {
0872: UBTEvent prov_ren = UBTEvent
0873: .getInstance(DesktopEvents.PROVIDER_RENDER_CACHE);
0874: prov_ren.put(UBTLogField.CHANNEL_NAME, p
0875: .getName());
0876: prov_ren.put(UBTLogField.PROVIDER, p.getClass()
0877: .getName());
0878: prov_ren.put(UBTLogField.CONTAINER_NAME, this
0879: .getParentContainerName(p.getName()));
0880: prov_ren.put(UBTLogField.ACTION, "Content");
0881: manager.logEvent(new ProviderLogRecord(
0882: prov_ren, req, res, this .getUserID()));
0883: }
0884: } catch (Exception e) {
0885: ; // ok to ignore
0886: }
0887:
0888: MonitoringSubsystemWrapper
0889: .getDesktopMonitoringSubsystem()
0890: .stopProviderServiceTransaction(fqcn.encoded(),
0891: MonitoringSubsystem.CACHED_CONTENT);
0892: MonitoringSubsystemWrapper
0893: .getDesktopMonitoringSubsystem()
0894: .getChannelCacheHitsStatistic().measure(
0895: activityTime2, fqcn.plain());
0896: }
0897: }
0898:
0899: monitor.start();
0900: if (!monitor.isDoneWaiting(timeout)) {
0901: logger.log(Level.INFO, "PSDT_CSPDC0013",
0902: new String[] { monitor.getCompleted().keySet()
0903: .toString() });
0904: }
0905:
0906: // interrupt all the threads that are still working.
0907: for (Iterator i = callers.keySet().iterator(); i.hasNext();) {
0908: String providerName = (String) i.next();
0909: if (!monitor.contains(providerName)) {
0910: ReusableProviderCaller caller = (ReusableProviderCaller) callers
0911: .get(providerName);
0912: caller.interrupt();
0913: }
0914: }
0915:
0916: //
0917: // content map contains cached contnt plus content fetched via callers
0918: // stored in the monitor
0919: //
0920: content.putAll(monitor.getCompleted());
0921: return content;
0922: }
0923:
0924: //A method to obtain collection property if it exists. This method is
0925: //used to obtain detached channels and minimized channels
0926: private Map getCollectionPropertyIE(String parent,
0927: String propertyName) throws ProviderContextException {
0928: Map map = null;
0929: boolean existsProp = existsCollectionProperty(parent,
0930: propertyName);
0931: if (existsProp) {
0932: map = getCollectionProperty(parent, propertyName);
0933: }
0934: return map;
0935: }
0936:
0937: private boolean checkChannel(Map map, String channel) {
0938: if (map != null) {
0939: Iterator iter = map.keySet().iterator();
0940: while (iter.hasNext()) {
0941: String cname = (String) iter.next();
0942: if (cname.equalsIgnoreCase(channel)) {
0943: Boolean boolVal = (Boolean) map.get(cname);
0944: return boolVal.booleanValue();
0945: }
0946: }
0947: }
0948: return false;
0949: }
0950:
0951: private void initCallerPool(DesktopAppContext dac) {
0952:
0953: int minSize = dac.getCallerPoolMinSize();
0954: if (minSize < 0) {
0955: logger.log(Level.FINE, "PSDT_CSPDC0014", new String[] {
0956: Integer.toString(minSize),
0957: Integer.toString(DEFAULT_MIN_SIZE) });
0958: minSize = DEFAULT_MIN_SIZE;
0959: }
0960: int maxSize = dac.getCallerPoolMaxSize();
0961: if (maxSize < 0) {
0962: logger.log(Level.FINE, "PSDT_CSPDC0015", new String[] {
0963: Integer.toString(maxSize),
0964: Integer.toString(DEFAULT_MAX_SIZE) });
0965: maxSize = DEFAULT_MAX_SIZE;
0966: }
0967: int partitionSize = dac.getCallerPoolPartitionSize();
0968: if (partitionSize <= 0) {
0969: logger.log(Level.FINE, "PSDT_CSPDC0016", new String[] {
0970: Integer.toString(partitionSize),
0971: Integer.toString(DEFAULT_PARTITION_SIZE) });
0972: partitionSize = DEFAULT_PARTITION_SIZE;
0973: }
0974: callerPool = new ProviderCallerPool(minSize, maxSize, true,
0975: partitionSize);
0976:
0977: }
0978:
0979: private void initGetterPool(DesktopAppContext dac) {
0980:
0981: int minSize = dac.getGetterPoolMinSize();
0982: if (minSize < 0) {
0983: logger.log(Level.FINE, "PSDT_CSPDC0014", new String[] {
0984: Integer.toString(minSize),
0985: Integer.toString(DEFAULT_MIN_SIZE) });
0986: minSize = DEFAULT_MIN_SIZE;
0987: }
0988: int maxSize = dac.getGetterPoolMaxSize();
0989: if (maxSize < 0) {
0990: logger.log(Level.FINE, "PSDT_CSPDC0015", new String[] {
0991: Integer.toString(maxSize),
0992: Integer.toString(DEFAULT_MAX_SIZE) });
0993: maxSize = DEFAULT_MAX_SIZE;
0994: }
0995: int partitionSize = dac.getGetterPoolPartitionSize();
0996: if (partitionSize <= 0) {
0997: logger.log(Level.FINE, "PSDT_CSPDC0016", new String[] {
0998: Integer.toString(partitionSize),
0999: Integer.toString(DEFAULT_PARTITION_SIZE) });
1000: partitionSize = DEFAULT_PARTITION_SIZE;
1001: }
1002: getterPool = new ProviderGetterPool(minSize, maxSize, true,
1003: partitionSize);
1004: }
1005:
1006: /**
1007: * Returns true if the channel represents a remote or local portlet
1008: */
1009: private boolean isPortlet(String channel) {
1010: boolean result = false;
1011: try {
1012: String className = getClassName(channel);
1013: if (className == null) {
1014: if (logger.isLoggable(Level.WARNING)) {
1015: logger.log(getLogRecord(Level.WARNING,
1016: "PSDT_CSPDC0005", new Object[] { channel },
1017: null));
1018: }
1019: return result;
1020: }
1021: result = (className.endsWith("PortletWindowProvider") || className
1022: .endsWith("WSRPWindowProvider"));
1023: } catch (ProviderContextException pce) {
1024: if (logger.isLoggable(Level.WARNING)) {
1025: logger.log(getLogRecord(Level.WARNING,
1026: "PSDT_CSPDC0005", new Object[] { channel },
1027: null));
1028: }
1029: }
1030: return result;
1031: }
1032: }
|