0001: /*
0002: * The Apache Software License, Version 1.1
0003: *
0004: * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved.
0005: *
0006: * Redistribution and use in source and binary forms, with or without
0007: * modification, are permitted provided that the following conditions
0008: * are met:
0009: *
0010: * 1. Redistributions of source code must retain the above copyright
0011: * notice, this list of conditions and the following disclaimer.
0012: *
0013: * 2. Redistributions in binary form must reproduce the above copyright
0014: * notice, this list of conditions and the following disclaimer in
0015: * the documentation and/or other materials provided with the
0016: * distribution.
0017: *
0018: * 3. The end-user documentation included with the redistribution, if
0019: * any, must include the following acknowlegement:
0020: * "This product includes software developed by the
0021: * Caucho Technology (http://www.caucho.com/)."
0022: * Alternately, this acknowlegement may appear in the software itself,
0023: * if and wherever such third-party acknowlegements normally appear.
0024: *
0025: * 4. The names "Hessian", "Resin", and "Caucho" must not be used to
0026: * endorse or promote products derived from this software without prior
0027: * written permission. For written permission, please contact
0028: * info@caucho.com.
0029: *
0030: * 5. Products derived from this software may not be called "Resin"
0031: * nor may "Resin" appear in their names without prior written
0032: * permission of Caucho Technology.
0033: *
0034: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0035: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0036: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0037: * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS
0038: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
0039: * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
0040: * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
0041: * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
0042: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
0043: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
0044: * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0045: *
0046: * @author Sam
0047: */
0048:
0049: package com.caucho.portal.generic.context;
0050:
0051: import com.caucho.portal.generic.*;
0052:
0053: import javax.portlet.*;
0054: import java.io.BufferedReader;
0055: import java.io.IOException;
0056: import java.io.InputStream;
0057: import java.io.OutputStream;
0058: import java.io.PrintWriter;
0059: import java.io.UnsupportedEncodingException;
0060: import java.util.*;
0061: import java.util.logging.Level;
0062: import java.util.logging.Logger;
0063:
0064: /**
0065: * ConnectionContext tracks the state of a PortletConnection and provides
0066: * methods for all operations that affect the connection.
0067: *
0068: * InterfaceImpl classes implement interfaces and delegate all operations to
0069: * the ConnectionContext.
0070: *
0071: * <ul>
0072: * <li>{@link com.caucho.portal.generic.context.ActionImpl}
0073: * <li>{@link com.caucho.portal.generic.context.RenderImpl}
0074: * <li>{@link com.caucho.portal.generic.context.PortalRequestImpl}
0075: * <li>{@link com.caucho.portal.generic.context.PortalResponseImpl}
0076: * </ul>
0077: *
0078: * <ul>
0079: * <li>{@link com.caucho.portal.generic.context.PortletRequestImpl}
0080: * <li>{@link com.caucho.portal.generic.context.PortletResponseImpl}
0081: * <li>{@link com.caucho.portal.generic.context.ActionRequestImpl}
0082: * <li>{@link com.caucho.portal.generic.context.ActionResponseImpl}
0083: * <li>{@link com.caucho.portal.generic.context.RenderRequestImpl}
0084: * <li>{@link com.caucho.portal.generic.context.RenderResponseImpl}
0085: * </ul>
0086: *
0087: * Some of the state of the connection depends on the "current window". The
0088: * ConnectionContext maintains a stack of {@link WindowContext}.
0089: */
0090: public class ConnectionContext {
0091: private static final Logger log = PortletConnection.log;
0092:
0093: private static final String EXPIRATION_CACHE = "javax.portlet.expirationCache";
0094:
0095: private static final String RENDER_REQUEST = "javax.portlet.renderRequest";
0096:
0097: private static final String RENDER_RESPONSE = "javax.portlet.renderResponse";
0098:
0099: private static final String PORTLET_CONFIG = "javax.portlet.portletConfig";
0100:
0101: private static final Locale LOCALE_ANY = new Locale("", "", "");
0102:
0103: ActionImpl _action = new ActionImpl(this );
0104: RenderImpl _render = new RenderImpl(this );
0105: PortalRequestImpl _portalRequest = new PortalRequestImpl(this );
0106: PortalResponseImpl _portalResponse = new PortalResponseImpl(this );
0107:
0108: PortletRequestImpl _portletRequest = new PortletRequestImpl(this );
0109: PortletResponseImpl _portletResponse = new PortletResponseImpl(this );
0110: ActionRequestImpl _actionRequest = new ActionRequestImpl(this );
0111: ActionResponseImpl _actionResponse = new ActionResponseImpl(this );
0112: RenderRequestImpl _renderRequest = new RenderRequestImpl(this );
0113: RenderResponseImpl _renderResponse = new RenderResponseImpl(this );
0114:
0115: final static int STAGE_START = 1;
0116: final static int STAGE_ACTION = 2;
0117: final static int STAGE_DONEACTION = 3;
0118: final static int STAGE_RENDER = 4;
0119: final static int STAGE_DONE = 5;
0120:
0121: private PortletConnection _connection;
0122:
0123: private InvocationFactory _invocationFactory;
0124: private TopLevelResponseHandler _topLevelResponseHandler;
0125:
0126: int _connectionExpirationCache = -1;
0127: boolean _connectionIsPrivate = false;
0128: private boolean _forbidRedirect;
0129:
0130: private PreferencesStore _preferencesStore;
0131: private UserAttributeStore _userAttributeStore;
0132:
0133: private int _stage = STAGE_START;
0134:
0135: private Map<String, WindowContext> _windowContextMap = new HashMap<String, WindowContext>();
0136:
0137: private ArrayList<WindowContext> _windowContextStack = new ArrayList<WindowContext>();
0138:
0139: private WindowContext _windowContext; // current
0140:
0141: public ConnectionContext(PortletConnection connection) {
0142: _connection = connection;
0143:
0144: _topLevelResponseHandler = new TopLevelResponseHandler(
0145: connection, this );
0146: }
0147:
0148: public void start(InvocationFactory invocationFactory) {
0149: log(Level.FINER, "starting connection");
0150:
0151: if (_stage != STAGE_START || _invocationFactory != null)
0152: throw new IllegalStateException("missing finish()? "
0153: + _stage);
0154:
0155: _invocationFactory = invocationFactory;
0156: }
0157:
0158: public void finish() {
0159: log(Level.FINEST, "finishing connection");
0160:
0161: try {
0162: for (int i = _windowContextStack.size() - 1; i >= 0; i--) {
0163: try {
0164: WindowContext windowContext = _windowContextStack
0165: .get(i);
0166:
0167: if (windowContext != null)
0168: finishWindowContext(windowContext);
0169: } catch (IOException ex) {
0170: log(Level.WARNING, ex.toString(), ex);
0171: }
0172: }
0173: } finally {
0174: _windowContextStack.clear();
0175: }
0176:
0177: _windowContextMap.clear();
0178: _windowContext = null;
0179: _stage = STAGE_START;
0180: _forbidRedirect = false;
0181: _preferencesStore = null;
0182: _userAttributeStore = null;
0183: _connection = null;
0184:
0185: _invocationFactory = null;
0186: }
0187:
0188: /**
0189: * finish a WindowContext that is no longer needed for this connection
0190: */
0191: private void finishWindowContext(WindowContext windowContext)
0192: throws IOException {
0193: Map<String, String> userAttributeMap = windowContext
0194: .getUserAttributeMap();
0195: LinkingPortletPreferences pref = windowContext.getPreferences();
0196:
0197: windowContext.finish();
0198:
0199: if (pref != null) {
0200: Map<String, String[]> store = pref.getStore();
0201: pref.finish();
0202: getPreferencesStore().finish(store);
0203: }
0204:
0205: if (userAttributeMap != null) {
0206: getUserAttributeStore().finish(userAttributeMap);
0207: }
0208: }
0209:
0210: protected void log(Level level, String message) {
0211: if (!log.isLoggable(level))
0212: return;
0213:
0214: String namespace = _windowContext == null ? null
0215: : _windowContext.getNamespace();
0216:
0217: log(namespace, level, message, null);
0218: }
0219:
0220: protected void log(Level level, String message, Exception ex) {
0221: if (!log.isLoggable(level))
0222: return;
0223:
0224: String namespace = _windowContext == null ? null
0225: : _windowContext.getNamespace();
0226:
0227: log(namespace, level, message, ex);
0228: }
0229:
0230: protected void log(String namespace, Level level, String message) {
0231: if (!log.isLoggable(level))
0232: return;
0233:
0234: log(namespace, level, message, null);
0235: }
0236:
0237: protected void log(String namespace, Level level, String message,
0238: Exception ex) {
0239: if (log.isLoggable(level)) {
0240: StringBuffer sb = new StringBuffer(256);
0241:
0242: sb.append('[');
0243:
0244: sb.append(_connection.getId());
0245:
0246: if (namespace != null) {
0247: sb.append(' ');
0248: sb.append(namespace);
0249: }
0250:
0251: sb.append(']');
0252:
0253: if (_stage == STAGE_ACTION)
0254: sb.append('a');
0255: else if (_stage == STAGE_RENDER)
0256: sb.append('r');
0257: else
0258: sb.append(' ');
0259:
0260: sb.append(' ');
0261: sb.append(message);
0262:
0263: if (ex == null)
0264: log.log(level, sb.toString());
0265: else
0266: log.log(level, sb.toString(), ex);
0267: }
0268: }
0269:
0270: protected PortletConnection getConnection() {
0271: return _connection;
0272: }
0273:
0274: protected InvocationFactory getInvocationFactory() {
0275: return _invocationFactory;
0276: }
0277:
0278: protected void setConnectionFailed(Exception ex) {
0279: _connection.setConnectionFailed(ex);
0280: }
0281:
0282: protected void setConnectionFailed() {
0283: _connection.setConnectionFailed();
0284: }
0285:
0286: protected boolean isConnectionFailed() {
0287: return _connection.isConnectionFailed();
0288: }
0289:
0290: public int getConnectionExpirationCache() {
0291: return _connectionExpirationCache;
0292: }
0293:
0294: protected void updateConnectionExpirationCache(int expirationCache) {
0295: if (_connectionExpirationCache != 0 && expirationCache >= 0
0296: && _connectionExpirationCache < expirationCache) {
0297: _connectionExpirationCache = expirationCache;
0298: }
0299: }
0300:
0301: public boolean isConnectionPrivate() {
0302: return _connectionIsPrivate;
0303: }
0304:
0305: protected void setConnectionPrivate() {
0306: _connectionIsPrivate = true;
0307: }
0308:
0309: protected void setForbidRedirect() {
0310: _forbidRedirect = true;
0311: }
0312:
0313: protected boolean isForbidRedirect() {
0314: return _forbidRedirect;
0315: }
0316:
0317: public PortalRequest getPortalRequest() {
0318: return _portalRequest;
0319: }
0320:
0321: public PortalResponse getPortalResponse() {
0322: return _portalResponse;
0323: }
0324:
0325: public Portal getPortal() {
0326: return _connection.getPortal();
0327: }
0328:
0329: public PortalContext getPortalContext() {
0330: return _connection.getPortal().getPortalContext();
0331: }
0332:
0333: protected PreferencesStore getPreferencesStore() {
0334: if (_preferencesStore == null)
0335: _preferencesStore = getPortal().getPreferencesStore();
0336:
0337: return _preferencesStore;
0338: }
0339:
0340: protected UserAttributeStore getUserAttributeStore() {
0341: if (_userAttributeStore == null)
0342: _userAttributeStore = getPortal().getUserAttributeStore();
0343:
0344: return _userAttributeStore;
0345: }
0346:
0347: private void pushStack(WindowContext windowContext) {
0348: _windowContextStack.add(_windowContext);
0349:
0350: _windowContext = windowContext;
0351: }
0352:
0353: private void popStack() {
0354: try {
0355: if (_windowContextStack.size() == 0)
0356: throw new IllegalStateException(
0357: "top of window stack reached, extra finish()?");
0358:
0359: WindowContext windowContext = _windowContext;
0360:
0361: _windowContext = null;
0362:
0363: if (_stage == STAGE_RENDER)
0364: finishWindowContext(windowContext);
0365:
0366: _windowContext = _windowContextStack
0367: .remove(_windowContextStack.size() - 1);
0368: } catch (Exception ex) {
0369: setConnectionFailed(ex);
0370: }
0371: }
0372:
0373: /**
0374: * See if the Window can handle the exception. Return true
0375: * if the exception has been handled in some way.
0376: *
0377: * Side-effect: might set windows.isExcluded to true
0378: * might set window.setException to null if it is handled
0379: */
0380: protected void handleException() throws PortletException,
0381: IOException {
0382: final Exception exception = _windowContext.getException();
0383:
0384: if (exception == null)
0385: return;
0386:
0387: if (log.isLoggable(Level.FINER))
0388: log(Level.FINER, "handling exception: "
0389: + exception.getClass().getName());
0390:
0391: final WindowContext windowContext = _windowContext;
0392:
0393: ExceptionEvent event = new ExceptionEvent() {
0394: public Exception getException() {
0395: return exception;
0396: }
0397:
0398: public void setHandled(boolean hideWindow) {
0399: windowContext.setException(null);
0400:
0401: if (hideWindow)
0402: windowContext.setExcluded();
0403: }
0404:
0405: public boolean isHandled() {
0406: return !windowContext.isException();
0407: }
0408:
0409: public boolean isHideWindow() {
0410: return windowContext.isExcluded();
0411: }
0412: };
0413:
0414: Window window = getWindow();
0415:
0416: window.handleException(getRenderRequest(), getRenderResponse(),
0417: event);
0418: }
0419:
0420: /**
0421: * Check for constraint failures and if any are encountered
0422: * set the _windowContext appropriately.
0423: */
0424: protected void checkConstraints() {
0425: ArrayList<Constraint> constraints = getWindow()
0426: .getConstraints();
0427:
0428: if (constraints == null)
0429: return;
0430:
0431: if (log.isLoggable(Level.FINER))
0432: log(Level.FINER, "checking constraints");
0433:
0434: int startIndex = _windowContext.getConstraintIndex();
0435:
0436: for (int i = startIndex; i < constraints.size(); i++) {
0437: _windowContext.setConstraintIndex(i + 1);
0438:
0439: Constraint constraint = constraints.get(i);
0440:
0441: int result = constraint.check(getPortletRequest(),
0442: getPortletResponse());
0443:
0444: if (result == Constraint.SC_PASS) {
0445: } else if (result == Constraint.SC_EXCLUDE) {
0446: _windowContext.setExcluded();
0447: if (log.isLoggable(Level.FINER))
0448: log(Level.FINE, "constraint excludes window");
0449:
0450: return;
0451: } else {
0452: _windowContext.setConstraintFailure(constraint, result);
0453:
0454: if (log.isLoggable(Level.FINER))
0455: log(Level.FINE, "constraint failed: "
0456: + constraint.getClass().getName());
0457:
0458: return;
0459: }
0460: }
0461: }
0462:
0463: /**
0464: * See if the Window can handle the constraint. Return true
0465: * if the constraint has been handled in some way.
0466: *
0467: * Side-effect: might set isExcluded to true
0468: */
0469: protected boolean handleConstraintFailure()
0470: throws PortletException, IOException {
0471: final Constraint constraint = _windowContext
0472: .getConstraintFailureConstraint();
0473:
0474: if (constraint == null)
0475: return true;
0476:
0477: if (log.isLoggable(Level.FINEST))
0478: log(Level.FINEST, "handling constraint failure: "
0479: + constraint.getClass().getName());
0480:
0481: final WindowContext windowContext = _windowContext;
0482:
0483: final int code = _windowContext.getConstraintFailureCode();
0484:
0485: ConstraintFailureEvent event = new ConstraintFailureEvent() {
0486: public Constraint getConstraint() {
0487: return constraint;
0488: }
0489:
0490: public int getStatusCode() {
0491: return code;
0492: }
0493:
0494: public void setHandled(boolean hideWindow) {
0495: windowContext.setConstraintFailure(null, 0);
0496:
0497: if (hideWindow)
0498: windowContext.setExcluded();
0499: }
0500:
0501: public boolean isHandled() {
0502: return !windowContext.isConstraintFailure();
0503: }
0504:
0505: public boolean isHideWindow() {
0506: return windowContext.isExcluded();
0507: }
0508: };
0509:
0510: Window window = getWindow();
0511:
0512: window.handleConstraintFailure(getRenderRequest(),
0513: getRenderResponse(), event);
0514:
0515: return !windowContext.isConstraintFailure();
0516: }
0517:
0518: private boolean startActionOrRender(Window window,
0519: String namespace, boolean isActionStage)
0520: throws PortletException, IOException {
0521: if (log.isLoggable(Level.FINEST)) {
0522: log(Level.FINER, "portlet `"
0523: + window.getPortletConfig().getPortletName()
0524: + "' for namespace `" + namespace + "'");
0525: }
0526:
0527: if (_windowContext != null
0528: && (_windowContext.isExcluded()
0529: || _windowContext.getException() != null || _windowContext
0530: .isConstraintFailure())) {
0531: if (log.isLoggable(Level.FINER)) {
0532: if (_windowContext.isExcluded())
0533: log(Level.FINER, "child `" + namespace
0534: + "' excluded because parent is excluded");
0535: else if (_windowContext.isException())
0536: log(Level.FINER, "child `" + namespace
0537: + "' excluded because parent has exception");
0538: else if (_windowContext.isConstraintFailure())
0539: log(
0540: Level.FINER,
0541: "child `"
0542: + namespace
0543: + "' excluded because parent has constraint failure");
0544: }
0545:
0546: return false;
0547: }
0548:
0549: boolean fail = true;
0550:
0551: try {
0552: boolean isTopLevel = _windowContextStack.size() == 0;
0553:
0554: // reuse a WindowContext prepared in a previous stage or create a new one
0555:
0556: WindowContext windowContext = namespace == null ? null
0557: : _windowContextMap.get(namespace);
0558:
0559: if (windowContext != null) {
0560:
0561: if (isActionStage)
0562: throw new PortletException("duplicate namespace `"
0563: + namespace + "'");
0564:
0565: else if (windowContext.getWindow() != window)
0566: throw new PortletException(
0567: "cannot have different Window"
0568: + " in render stage for namespace `"
0569: + namespace + "'");
0570:
0571: // check if windowContext was excluded in previous stage
0572:
0573: if (windowContext.isExcluded()) {
0574: if (log.isLoggable(Level.FINER)) {
0575: if (_windowContext.isExcluded())
0576: log(Level.FINER, "child `" + namespace
0577: + "' excluded in previous stage");
0578: }
0579:
0580: fail = false;
0581: return false;
0582: }
0583: } else {
0584: windowContext = new WindowContext();
0585:
0586: windowContext.start(window, namespace);
0587:
0588: if (windowContext.getNamespace() != null) {
0589: _windowContextMap.put(windowContext.getNamespace(),
0590: windowContext);
0591:
0592: // prepare invocation
0593:
0594: Invocation invocation = getInvocationFactory()
0595: .getInvocation(namespace);
0596:
0597: windowContext.setInvocation(invocation);
0598:
0599: if (invocation.isActionTarget()) {
0600: log(Level.FINER, "action target");
0601:
0602: Map<String, String[]> actionMap = invocation
0603: .releaseParameterMap();
0604:
0605: windowContext.setActionMap(actionMap);
0606: }
0607: }
0608: }
0609:
0610: // set the Context to work on the new namespace
0611:
0612: pushStack(windowContext);
0613:
0614: if (_windowContext.getNamespace() == null
0615: && log.isLoggable(Level.FINER))
0616: log(Level.FINER, "no invocation for null namespace");
0617:
0618: if (isActionStage) {
0619: checkConstraints();
0620:
0621: if (_windowContext.isConstraintFailure()
0622: || _windowContext.isExcluded()) {
0623: popStack();
0624: fail = false;
0625: return false;
0626: }
0627: }
0628:
0629: fail = false;
0630: } catch (PortletException ex) {
0631: setConnectionFailed(ex);
0632: throw ex;
0633: } catch (RuntimeException ex) {
0634: setConnectionFailed(ex);
0635: throw new PortletException(ex);
0636: } finally {
0637: if (fail) {
0638: setConnectionFailed();
0639: return false;
0640: }
0641: }
0642:
0643: return true;
0644: }
0645:
0646: public PortletRequest getPortletRequest() {
0647: return _portletRequest;
0648: }
0649:
0650: public PortletResponse getPortletResponse() {
0651: return _portletResponse;
0652: }
0653:
0654: public Action getAction(Window window, String namespace)
0655: throws PortletException, IOException {
0656: if (isConnectionFailed())
0657: return null;
0658:
0659: if (_stage == STAGE_START) {
0660: if (log.isLoggable(Level.FINER))
0661: log(Level.FINER, "starting action stage");
0662:
0663: _stage = STAGE_ACTION;
0664: } else if (_stage != STAGE_ACTION) {
0665: IllegalStateException ex = new IllegalStateException(
0666: "missing finish()? " + _stage);
0667:
0668: setConnectionFailed(ex);
0669:
0670: throw ex;
0671: }
0672:
0673: if (!startActionOrRender(window, namespace, true))
0674: return null;
0675:
0676: return getCurrentAction();
0677: }
0678:
0679: public Action getCurrentAction() {
0680: return _stage == STAGE_ACTION ? _action : null;
0681: }
0682:
0683: public boolean isTarget() {
0684: return (_stage == STAGE_ACTION
0685: && _windowContext.getActionMap() != null && !_windowContext
0686: .isExcluded());
0687:
0688: }
0689:
0690: public ActionRequest getActionRequest() {
0691: if (_stage != STAGE_ACTION || _windowContext.isExcluded())
0692: return null;
0693: else
0694: return _actionRequest;
0695: }
0696:
0697: public ActionResponse getActionResponse() {
0698: if (_stage != STAGE_ACTION || _windowContext.isExcluded())
0699: return null;
0700: else
0701: return _actionResponse;
0702: }
0703:
0704: public void processAction(Portlet portlet) {
0705: if (_stage != STAGE_ACTION)
0706: throw new IllegalStateException("not in action stage");
0707:
0708: if (log.isLoggable(Level.FINEST))
0709: log(Level.FINEST, "processAction()");
0710:
0711: try {
0712: portlet.processAction(_actionRequest, _actionResponse);
0713: } catch (Exception ex) {
0714: if (log.isLoggable(Level.FINE))
0715: log(Level.FINE, ex.toString(), ex);
0716:
0717: _windowContext.setException(ex);
0718: }
0719: }
0720:
0721: void finishAction() throws IOException, PortletException {
0722: boolean fail = true;
0723:
0724: try {
0725: if (_windowContext == null) {
0726: throw new IllegalStateException(
0727: "cannot finish action, at top of stack");
0728: }
0729:
0730: if (_stage != STAGE_ACTION && _stage != STAGE_DONEACTION) {
0731: throw new IllegalStateException(
0732: "cannot finish action for "
0733: + _windowContext.getNamespace()
0734: + ", stage is " + _stage);
0735: }
0736:
0737: popStack();
0738:
0739: if (_windowContext == null) {
0740: _stage = STAGE_DONEACTION;
0741:
0742: if (log.isLoggable(Level.FINER))
0743: log(Level.FINER, "finishing action stage");
0744: }
0745:
0746: fail = false;
0747: } catch (RuntimeException ex) {
0748: setConnectionFailed(ex);
0749: throw ex;
0750: } finally {
0751: if (fail)
0752: setConnectionFailed();
0753: }
0754: }
0755:
0756: // XXX: this is bogus, see comments in CacheKey.java
0757: // about how the cache key should be built up.
0758: // Basically, every WindowContext that has an expirationCache !=0
0759: // should have a CacheKey that get's filled with the invocation
0760: // for itself _and_ every child WindowContext during the action phase.
0761:
0762: private CacheKey getCacheKey() {
0763: CacheKey cacheKey = null;
0764:
0765: if (cacheKey == null)
0766: cacheKey = new CacheKey();
0767: else
0768: cacheKey.reset();
0769:
0770: WindowContext windowContext = _windowContext;
0771:
0772: if (windowContext.getNamespace() == null)
0773: return null;
0774:
0775: cacheKey.setNamespace(windowContext.getNamespace());
0776: cacheKey.setPortletMode(getPortletMode());
0777: cacheKey.setWindowState(getWindowState());
0778: cacheKey.setContentType(getResponseContentType());
0779: cacheKey.setLocale(getResponseLocale());
0780: cacheKey.setPrivate(windowContext.isPrivate());
0781: cacheKey.setRequestedSessionId(_connection
0782: .getRequestedSessionId());
0783:
0784: return null; // XXX:
0785: }
0786:
0787: /**
0788: * Reset window specific attributes to null and return a map of the old
0789: * values
0790: */
0791: private Map<String, String> resetWindowRequestAttributes() {
0792: Map<String, String> attr = null;
0793:
0794: attr = getAttribute(attr, "javax.portlet.title", true);
0795: attr = getAttribute(attr, "javax.portlet.short-title", true);
0796: attr = getAttribute(attr, "javax.portlet.keywords", true);
0797: attr = getAttribute(attr, "javax.portlet.description", true);
0798:
0799: return attr;
0800: }
0801:
0802: /**
0803: * Return a map of window specific request attributes, attributes with null
0804: * values are not included, the return may be null.
0805: */
0806: private Map<String, String> getWindowRequestAttributes() {
0807: Map<String, String> attr = null;
0808:
0809: attr = getAttribute(attr, "javax.portlet.title", false);
0810: getAttribute(attr, "javax.portlet.short-title", false);
0811: getAttribute(attr, "javax.portlet.keywords", false);
0812: getAttribute(attr, "javax.portlet.description", false);
0813:
0814: return attr;
0815: }
0816:
0817: private Map<String, String> getAttribute(Map<String, String> map,
0818: String name, boolean isReset) {
0819: String value = (String) _connection.getAttribute(name);
0820:
0821: if (isReset || value != null) {
0822: if (map == null)
0823: map = new LinkedHashMap<String, String>();
0824:
0825: map.put(name, value);
0826:
0827: if (isReset)
0828: _connection.removeAttribute(name);
0829: }
0830:
0831: return map;
0832: }
0833:
0834: private void restoreWindowRequestAttributes(Map<String, String> map) {
0835: if (map != null && !map.isEmpty()) {
0836: Iterator<Map.Entry<String, String>> iter = map.entrySet()
0837: .iterator();
0838:
0839: do {
0840: Map.Entry<String, String> entry = iter.next();
0841: _connection.setAttribute(entry.getKey(), entry
0842: .getValue());
0843: } while (iter.hasNext());
0844: }
0845: }
0846:
0847: public Render getRender(Window window, String namespace)
0848: throws PortletException, IOException {
0849: if (isConnectionFailed())
0850: return null;
0851:
0852: if (_stage == STAGE_START || _stage == STAGE_DONEACTION) {
0853: if (log.isLoggable(Level.FINER))
0854: log(Level.FINER, "starting render stage");
0855:
0856: _stage = STAGE_RENDER;
0857:
0858: _connection.setAttribute("javax.portlet.renderRequest",
0859: _renderRequest);
0860: _connection.setAttribute("javax.portlet.renderResponse",
0861: _renderResponse);
0862: } else if (_stage != STAGE_RENDER) {
0863: IllegalStateException ex = new IllegalStateException(
0864: "missing finish()? " + _stage);
0865:
0866: setConnectionFailed(ex);
0867:
0868: throw ex;
0869: }
0870:
0871: checkAlwaysWriteOrStream();
0872:
0873: ResponseHandler parentResponseHandler = _windowContext == null ? _topLevelResponseHandler
0874: : _windowContext.getResponseHandler();
0875:
0876: if (!startActionOrRender(window, namespace, false))
0877: return null;
0878:
0879: // discard preferences from action stage
0880:
0881: LinkingPortletPreferences pref = _windowContext
0882: .getPreferences();
0883: if (pref != null)
0884: pref.discard();
0885:
0886: // response handler
0887:
0888: _windowContext.setParentResponseHandler(parentResponseHandler);
0889:
0890: ResponseHandler responseHandler = parentResponseHandler;
0891:
0892: Renderer renderer = _windowContext.getWindow().getRenderer();
0893:
0894: if (renderer != null) {
0895: BufferFactory bufferFactory = getPortal()
0896: .getBufferFactory();
0897: int rendererBufferSize = renderer.getBufferSize();
0898:
0899: if (bufferFactory != null && rendererBufferSize != 0) {
0900:
0901: responseHandler = new BufferedResponseHandler(
0902: responseHandler, bufferFactory,
0903: rendererBufferSize);
0904: }
0905:
0906: responseHandler = new RendererResponseHandler(this ,
0907: responseHandler, renderer, getRenderRequest(),
0908: getRenderResponse(), namespace);
0909: }
0910:
0911: int bufferSize = _windowContext.getWindow().getBufferSize();
0912:
0913: if (bufferSize != 0) {
0914: BufferFactory bufferFactory = getPortal()
0915: .getBufferFactory();
0916:
0917: if (bufferFactory != null) {
0918: responseHandler = new BufferedResponseHandler(
0919: responseHandler, bufferFactory, bufferSize);
0920: }
0921: }
0922:
0923: _windowContext.setResponseHandler(responseHandler);
0924:
0925: boolean isPrivate = _windowContext.getWindow().isPrivate();
0926:
0927: if (isPrivate) {
0928: _windowContext.setPrivate();
0929: setConnectionPrivate();
0930: }
0931:
0932: // set request attributes
0933:
0934: _connection.setAttribute("javax.portlet.portletConfig",
0935: getWindow().getPortletConfig());
0936:
0937: Map<String, String> requestAttributes = resetWindowRequestAttributes();
0938:
0939: _windowContext.setWindowRequestAttributes(requestAttributes);
0940:
0941: // check for exception failures from previous stage
0942:
0943: if (_windowContext.isException()) {
0944: if (log.isLoggable(Level.FINE))
0945: log(Level.FINE, "previous exception");
0946:
0947: finishRender();
0948: return null;
0949: }
0950:
0951: // constraints
0952:
0953: if (!_windowContext.isConstraintFailure())
0954: checkConstraints();
0955:
0956: if (_windowContext.isConstraintFailure()) {
0957: if (!handleConstraintFailure()) {
0958: if (log.isLoggable(Level.FINE))
0959: log(Level.FINE,
0960: "constraint failure unhandled, propagating to parent");
0961: } else {
0962: if (log.isLoggable(Level.FINER)) {
0963: if (_windowContext.isExcluded())
0964: log(Level.FINER,
0965: "constraint failure handled, excluding");
0966: else
0967: log(Level.FINER,
0968: "constraint failure handled by window");
0969: }
0970: }
0971:
0972: finishRender();
0973: return null;
0974: }
0975:
0976: // XXX: cache caching
0977:
0978: int expirationCache = _windowContext.getExpirationCache();
0979:
0980: if (expirationCache != 0
0981: && (!isPrivate || getRequestedSessionId() != null)) {
0982: _windowContext.setExpirationCache(expirationCache);
0983: }
0984:
0985: Cache cache = getPortal().getCache();
0986: CacheKey cacheKey = null;
0987:
0988: if (cache != null)
0989: cacheKey = getCacheKey();
0990:
0991: if (cacheKey != null) {
0992: int result = cache.respondFromCache(cacheKey,
0993: getRenderRequest(), getRenderResponse());
0994:
0995: if (result != 0) {
0996: updateConnectionExpirationCache(result);
0997: return null;
0998: }
0999:
1000: CachingResponseHandler cacheResponseHandler = new CachingResponseHandler(
1001: _windowContext.getResponseHandler(), cache,
1002: _windowContext.getNamespace(), _windowContext
1003: .getExpirationCache(), _windowContext
1004: .isPrivate());
1005:
1006: _windowContext.setResponseHandler(cacheResponseHandler);
1007: }
1008:
1009: return getCurrentRender();
1010: }
1011:
1012: public RenderRequest getRenderRequest() {
1013: if (_stage != STAGE_RENDER || _windowContext.isExcluded())
1014: return null;
1015: else
1016: return _renderRequest;
1017: }
1018:
1019: public RenderResponse getRenderResponse() {
1020: if (_stage != STAGE_RENDER || _windowContext.isExcluded())
1021: return null;
1022: else
1023: return _renderResponse;
1024: }
1025:
1026: public void render(Portlet portlet) throws PortletException,
1027: IOException {
1028: if (_stage != STAGE_RENDER)
1029: throw new IllegalStateException("not in render stage");
1030:
1031: if (log.isLoggable(Level.FINEST))
1032: log(Level.FINEST, "render()");
1033:
1034: if (_windowContext.getException() == null
1035: && !_windowContext.isExcluded()
1036: && !_windowContext.isConstraintFailure()) {
1037: try {
1038: portlet.render(getRenderRequest(), getRenderResponse());
1039: } catch (Exception ex) {
1040: if (log.isLoggable(Level.FINE))
1041: log(Level.FINE, ex.toString(), ex);
1042:
1043: _windowContext.setException(ex);
1044:
1045: }
1046: }
1047: }
1048:
1049: public Render getCurrentRender() {
1050: return _stage == STAGE_RENDER ? _render : null;
1051: }
1052:
1053: void finishRender() throws IOException, PortletException {
1054: boolean fail = true;
1055:
1056: try {
1057: if (_windowContext == null) {
1058: throw new IllegalStateException(
1059: "cannot finish render, at top of stack");
1060: }
1061:
1062: Map<String, String> requestAttributes = _windowContext
1063: .getWindowRequestAttributes();
1064:
1065: if (_stage != STAGE_RENDER && _stage != STAGE_DONE) {
1066: throw new IllegalStateException(
1067: "cannot finish render for "
1068: + _windowContext.getNamespace()
1069: + ", stage is " + _stage);
1070: }
1071:
1072: if (_windowContext.isException()) {
1073: try {
1074: reset(false); // do not resetRenderer
1075:
1076: handleException();
1077:
1078: if (log.isLoggable(Level.FINE)) {
1079: if (_windowContext.isException())
1080: log(Level.FINE,
1081: "exception unhandled, propagating to parent");
1082: else if (_windowContext.isExcluded())
1083: log(Level.FINER,
1084: "exception handled, excluding");
1085: else
1086: log(Level.FINER,
1087: "exception handled by window");
1088: }
1089: } catch (Exception ex) {
1090: log.log(Level.WARNING, ex.toString(), ex);
1091: }
1092: }
1093:
1094: Exception exception = _windowContext.getException();
1095:
1096: boolean isException = exception != null;
1097:
1098: boolean isConstraintFailure = _windowContext
1099: .isConstraintFailure();
1100:
1101: Constraint constraintFailureConstraint = _windowContext
1102: .getConstraintFailureConstraint();
1103:
1104: int constraintFailureCode = _windowContext
1105: .getConstraintFailureCode();
1106:
1107: boolean killResponse = _windowContext.isExcluded()
1108: || isConstraintFailure || isException;
1109:
1110: if (killResponse) {
1111: if (log.isLoggable(Level.FINEST)) {
1112: if (isException)
1113: log(Level.FINEST,
1114: "killResponse due to exception");
1115: else if (_windowContext.isConstraintFailure())
1116: log(Level.FINEST,
1117: "killResponse due to constraintFailure");
1118: else
1119: log(Level.FINEST, "killResponse");
1120: }
1121:
1122: reset(true); // resetRenderer
1123: }
1124:
1125: // unwind the write streams and finish() them
1126:
1127: ResponseHandler parentResponseHandler = _windowContext
1128: .getParentResponseHandler();
1129:
1130: CachingResponseHandler cacheResponseHandler = null;
1131:
1132: ResponseHandler next = _windowContext.getResponseHandler();
1133:
1134: while (next != null && next != parentResponseHandler) {
1135: ResponseHandler responseHandler = next;
1136: next = next.getSuccessor();
1137:
1138: try {
1139: if (!killResponse && !isException) {
1140: responseHandler.flushBuffer();
1141: }
1142:
1143: if (responseHandler instanceof CachingResponseHandler)
1144: cacheResponseHandler = (CachingResponseHandler) responseHandler;
1145: else
1146: responseHandler.finish();
1147: } catch (Exception ex) {
1148: if (!isException) {
1149: isException = true;
1150: exception = ex;
1151: } else {
1152: if (log.isLoggable(Level.FINEST)) {
1153: log(Level.FINEST,
1154: "exception while finishing response handlers: "
1155: + ex.toString(), ex);
1156: }
1157: }
1158: }
1159: }
1160:
1161: String expirationCacheAttribute = (String) _connection
1162: .getAttribute(EXPIRATION_CACHE);
1163:
1164: _connection.removeAttribute(EXPIRATION_CACHE);
1165:
1166: // caching
1167:
1168: if (cacheResponseHandler != null) {
1169: if (killResponse) {
1170: cacheResponseHandler.finish(0, null, null);
1171: } else {
1172: try {
1173: int expirationCache = _windowContext
1174: .getExpirationCache();
1175: CacheKey cacheKey = null;
1176:
1177: if (expirationCache != 0
1178: && expirationCacheAttribute != null)
1179: expirationCache = Integer
1180: .parseInt(expirationCacheAttribute);
1181:
1182: if (expirationCache != 0)
1183: cacheKey = getCacheKey();
1184:
1185: cacheResponseHandler.finish(expirationCache,
1186: cacheKey, getWindowRequestAttributes());
1187:
1188: } catch (Exception ex) {
1189: if (!isException) {
1190: isException = true;
1191: exception = ex;
1192: }
1193: }
1194: }
1195: }
1196:
1197: WindowContext windowContext = _windowContext;
1198: String namespace = _windowContext.getNamespace();
1199:
1200: try {
1201: popStack();
1202: } finally {
1203: windowContext.finish();
1204: }
1205:
1206: if (isConstraintFailure) {
1207: if (_windowContext != null) {
1208: if (log.isLoggable(Level.FINEST))
1209: log(namespace, Level.FINEST,
1210: "propagating constraint failure "
1211: + constraintFailureConstraint
1212: .getClass().getName()
1213: + " to parent");
1214:
1215: _windowContext.setConstraintFailure(
1216: constraintFailureConstraint,
1217: constraintFailureCode);
1218: } else {
1219: if (log.isLoggable(Level.FINEST))
1220: log(namespace, Level.FINEST,
1221: "propagating constraint failure "
1222: + constraintFailureConstraint
1223: .getClass().getName()
1224: + " to connection");
1225:
1226: boolean handled = _connection
1227: .handleConstraintFailure(
1228: constraintFailureConstraint,
1229: constraintFailureCode);
1230:
1231: if (!handled && !isException) {
1232: isException = true;
1233: exception = new PortletException(
1234: "Constraint failure "
1235: + constraintFailureConstraint
1236: .getClass().getName()
1237: + "(" + constraintFailureCode
1238: + ")");
1239: }
1240: }
1241: }
1242:
1243: if (isException) {
1244: if (_windowContext != null) {
1245: if (log.isLoggable(Level.FINEST))
1246: log(namespace, Level.FINEST,
1247: "propagating exception "
1248: + exception.getClass()
1249: .getName()
1250: + " to parent");
1251:
1252: _windowContext.setException(exception);
1253: } else {
1254: if (log.isLoggable(Level.FINEST))
1255: log(namespace, Level.FINEST,
1256: "propagating exception "
1257: + exception.getClass()
1258: .getName()
1259: + " to connection");
1260:
1261: try {
1262: boolean handled = _connection
1263: .handleException(exception);
1264:
1265: if (!handled)
1266: setConnectionFailed(exception);
1267: } catch (Exception ex) {
1268: setConnectionFailed(exception);
1269: log.log(Level.WARNING, ex.toString(), ex);
1270: }
1271: }
1272: }
1273:
1274: if (_windowContext == null) {
1275: if (log.isLoggable(Level.FINER))
1276: log(Level.FINER, "finishing render stage");
1277:
1278: _stage = STAGE_DONE;
1279: _connection.setAttribute("javax.portlet.portletConfig",
1280: null);
1281:
1282: } else {
1283: _connection.setAttribute("javax.portlet.portletConfig",
1284: getWindow().getPortletConfig());
1285: }
1286:
1287: restoreWindowRequestAttributes(requestAttributes);
1288:
1289: fail = false;
1290: } catch (RuntimeException ex) {
1291: setConnectionFailed(ex);
1292: throw ex;
1293: } finally {
1294: if (fail)
1295: setConnectionFailed();
1296: }
1297: }
1298:
1299: /**
1300: * @throws IllegalStateException if the window with the namespace
1301: * has already been processed as the target of an action, or already
1302: * renderered.
1303: *
1304: * @throws IllegalArgumentException if the window with the namespace
1305: * is not found
1306: */
1307: protected void checkWindowMutable(String namespace)
1308: throws IllegalStateException, IllegalArgumentException {
1309: WindowContext windowContext = _windowContextMap.get(namespace);
1310:
1311: if (windowContext == null)
1312: throw new IllegalArgumentException("namespace `"
1313: + namespace + "' not known");
1314:
1315: if (windowContext.getActionMap() != null
1316: && !namespace.equals(getNamespace()))
1317: throw new IllegalStateException(
1318: "already did processAction() for namespace `"
1319: + namespace + "'");
1320:
1321: if (windowContext.getNamespace() == null)
1322: throw new IllegalStateException(
1323: "already did render() for namespace `" + namespace
1324: + "'");
1325: }
1326:
1327: protected Window getWindow() {
1328: return _windowContext.getWindow();
1329: }
1330:
1331: protected Window getWindow(String namespace) {
1332: WindowContext windowContext = _windowContextMap.get(namespace);
1333:
1334: return windowContext == null ? null : windowContext.getWindow();
1335: }
1336:
1337: protected String getNamespace() {
1338: return _windowContext.getNamespace();
1339: }
1340:
1341: protected Renderer getRenderer() {
1342: return _windowContext.getWindow().getRenderer();
1343: }
1344:
1345: protected Renderer getRenderer(String namespace) {
1346: WindowContext windowContext = _windowContextMap.get(namespace);
1347:
1348: return windowContext == null ? null : windowContext.getWindow()
1349: .getRenderer();
1350: }
1351:
1352: protected Invocation getInvocation() {
1353: Invocation invocation = _windowContext.getInvocation();
1354:
1355: if (invocation == null)
1356: throw new UnsupportedOperationException(
1357: "operation requires a namespace");
1358:
1359: return invocation;
1360: }
1361:
1362: protected Invocation getInvocation(String namespace) {
1363: return _invocationFactory.getInvocation(namespace);
1364: }
1365:
1366: protected void forbidRedirectIfInActionStage() {
1367: if (_stage == STAGE_ACTION)
1368: setForbidRedirect();
1369: }
1370:
1371: // -- Invocation - WindowState/PortletMode
1372:
1373: public Set<WindowState> getWindowStatesUsed() {
1374: return getInvocationFactory().getWindowStatesUsed();
1375: }
1376:
1377: public Set<PortletMode> getPortletModesUsed() {
1378: return getInvocationFactory().getPortletModesUsed();
1379: }
1380:
1381: protected boolean isPortletModeAllowed(Window window,
1382: PortletMode portletMode) {
1383: PortletRequest portletRequest = getPortletRequest();
1384:
1385: boolean allowed = true;
1386:
1387: Renderer renderer = window.getRenderer();
1388:
1389: if (renderer != null)
1390: allowed = renderer.isPortletModeAllowed(portletRequest,
1391: portletMode);
1392:
1393: if (allowed && window != null)
1394: allowed = window.isPortletModeAllowed(portletRequest,
1395: portletMode);
1396:
1397: if (allowed)
1398: allowed = getPortal().isPortletModeAllowed(portletRequest,
1399: portletMode);
1400:
1401: return allowed;
1402: }
1403:
1404: protected void setPortletMode(Window window, String namespace,
1405: Invocation invocation, PortletMode portletMode)
1406: throws PortletModeException {
1407: if (!isPortletModeAllowed(window, portletMode))
1408: throw new PortletModeException("PortletMode `"
1409: + portletMode + "' not allowed for namespace `"
1410: + namespace + "'", portletMode);
1411:
1412: forbidRedirectIfInActionStage();
1413:
1414: invocation.setPortletMode(portletMode);
1415: }
1416:
1417: public boolean isPortletModeAllowed(PortletMode portletMode) {
1418: return isPortletModeAllowed(getWindow(), getPortletMode());
1419: }
1420:
1421: public boolean isPortletModeAllowed(String namespace,
1422: PortletMode portletMode) {
1423: return isPortletModeAllowed(getWindow(namespace),
1424: getPortletMode(namespace));
1425: }
1426:
1427: public PortletMode getPortletMode() {
1428: return getInvocation().getPortletMode();
1429: }
1430:
1431: public PortletMode getPortletMode(String namespace) {
1432: return getInvocation(namespace).getPortletMode();
1433: }
1434:
1435: public void setPortletMode(PortletMode portletMode)
1436: throws PortletModeException {
1437: setPortletMode(getWindow(), getNamespace(), getInvocation(),
1438: portletMode);
1439: }
1440:
1441: public void setPortletMode(String namespace, PortletMode portletMode)
1442: throws PortletModeException {
1443: checkWindowMutable(namespace);
1444:
1445: setPortletMode(getWindow(namespace), namespace,
1446: getInvocation(namespace), portletMode);
1447: }
1448:
1449: protected boolean isWindowStateAllowed(Window window,
1450: WindowState windowState) {
1451: PortletRequest portletRequest = getPortletRequest();
1452:
1453: boolean allowed = true;
1454:
1455: Renderer renderer = window.getRenderer();
1456:
1457: if (renderer != null)
1458: allowed = renderer.isWindowStateAllowed(portletRequest,
1459: windowState);
1460:
1461: if (allowed && window != null)
1462: allowed = window.isWindowStateAllowed(portletRequest,
1463: windowState);
1464:
1465: if (allowed)
1466: allowed = getPortal().isWindowStateAllowed(portletRequest,
1467: windowState);
1468:
1469: return allowed;
1470: }
1471:
1472: protected void setWindowState(Window window, String namespace,
1473: Invocation invocation, WindowState windowState)
1474: throws WindowStateException {
1475: if (!isWindowStateAllowed(window, windowState))
1476: throw new WindowStateException("WindowState `"
1477: + windowState + "' not allowed for namespace `"
1478: + namespace + "'", windowState);
1479:
1480: forbidRedirectIfInActionStage();
1481:
1482: invocation.setWindowState(windowState);
1483: }
1484:
1485: public boolean isWindowStateAllowed(WindowState windowState) {
1486: return isWindowStateAllowed(getWindow(), windowState);
1487: }
1488:
1489: public boolean isWindowStateAllowed(String namespace,
1490: WindowState windowState) {
1491: return isWindowStateAllowed(getWindow(namespace), windowState);
1492: }
1493:
1494: public WindowState getWindowState() {
1495: return getInvocation().getWindowState();
1496: }
1497:
1498: public WindowState getWindowState(String namespace) {
1499: return getInvocation(namespace).getWindowState();
1500: }
1501:
1502: public void setWindowState(WindowState windowState)
1503: throws WindowStateException {
1504: setWindowState(getWindow(), getNamespace(), getInvocation(),
1505: windowState);
1506: }
1507:
1508: public void setWindowState(String namespace, WindowState windowState)
1509: throws WindowStateException {
1510: checkWindowMutable(namespace);
1511:
1512: setWindowState(getWindow(namespace), namespace,
1513: getInvocation(namespace), windowState);
1514: }
1515:
1516: // -- Invocation - parameters
1517:
1518: public Map<String, String[]> getActionParameterMap() {
1519: Map<String, String[]> actionMap = _windowContext.getActionMap();
1520:
1521: if (actionMap == null)
1522: throw new IllegalStateException("namespace `"
1523: + getNamespace() + "' is not target of action");
1524:
1525: return actionMap;
1526: }
1527:
1528: public Map<String, String[]> getRenderParameterMap() {
1529: return getInvocation().getParameterMap();
1530: }
1531:
1532: public Map<String, String[]> getRenderParameterMap(String namespace) {
1533: return getInvocation(namespace).getParameterMap();
1534: }
1535:
1536: private void checkNullName(String name) {
1537: if (name == null)
1538: throw new IllegalArgumentException(
1539: "parameter name cannot be null");
1540: }
1541:
1542: private void checkNullValue(Object value) {
1543: if (value == null)
1544: throw new IllegalArgumentException(
1545: "parameter value cannot be null");
1546: }
1547:
1548: protected String getParameter(Map<String, String[]> map, String name) {
1549: checkNullName(name);
1550:
1551: String values[] = map.get(name);
1552:
1553: return values == null || values.length == 0 ? null : values[0];
1554: }
1555:
1556: protected String[] getParameterValues(Map<String, String[]> map,
1557: String name) {
1558: checkNullName(name);
1559: return map.get(name);
1560: }
1561:
1562: protected Enumeration getParameterNames(Map<String, String[]> map) {
1563: return Collections.enumeration(map.keySet());
1564: }
1565:
1566: protected void setParameter(Map<String, String[]> map, String name,
1567: String value) {
1568: checkNullName(name);
1569: checkNullValue(value);
1570:
1571: map.put(name, new String[] { value });
1572: }
1573:
1574: protected void setParameters(Map<String, String[]> destMap,
1575: Map<String, String[]> srcMap) {
1576: checkNullValue(srcMap);
1577: destMap.clear();
1578:
1579: Iterator<Map.Entry<String, String[]>> iter = srcMap.entrySet()
1580: .iterator();
1581:
1582: while (iter.hasNext()) {
1583: Map.Entry<String, String[]> entry = iter.next();
1584:
1585: setParameter(destMap, entry.getKey(), entry.getValue());
1586: }
1587: }
1588:
1589: protected void setParameter(Map<String, String[]> map, String name,
1590: String[] values) {
1591: checkNullName(name);
1592: checkNullValue(values);
1593:
1594: if (values.length == 0)
1595: map.remove(name);
1596: else
1597: map.put(name, values);
1598: }
1599:
1600: public String getActionParameter(String name) {
1601: return getParameter(getActionParameterMap(), name);
1602: }
1603:
1604: public String[] getActionParameterValues(String name) {
1605: return getParameterValues(getActionParameterMap(), name);
1606: }
1607:
1608: public Enumeration getActionParameterNames() {
1609: return getParameterNames(getActionParameterMap());
1610: }
1611:
1612: public String getRenderParameter(String name) {
1613: return getParameter(getRenderParameterMap(), name);
1614: }
1615:
1616: public String[] getRenderParameterValues(String name) {
1617: return getParameterValues(getRenderParameterMap(), name);
1618: }
1619:
1620: public Enumeration getRenderParameterNames() {
1621: return getParameterNames(getRenderParameterMap());
1622: }
1623:
1624: public void setRenderParameters(Map<String, String[]> srcMap) {
1625: forbidRedirectIfInActionStage();
1626:
1627: setParameters(getRenderParameterMap(), srcMap);
1628: }
1629:
1630: public void setRenderParameter(String name, String value) {
1631: forbidRedirectIfInActionStage();
1632:
1633: setParameter(getRenderParameterMap(), name, value);
1634: }
1635:
1636: public void setRenderParameter(String name, String[] values) {
1637: forbidRedirectIfInActionStage();
1638:
1639: setParameter(getRenderParameterMap(), name, values);
1640: }
1641:
1642: public String getRenderParameter(String namespace, String name) {
1643: return getParameter(getRenderParameterMap(namespace), name);
1644: }
1645:
1646: public String[] getRenderParameterValues(String namespace,
1647: String name) {
1648: return getParameterValues(getRenderParameterMap(namespace),
1649: name);
1650: }
1651:
1652: public Enumeration getRenderParameterNames(String namespace) {
1653: return getParameterNames(getRenderParameterMap(namespace));
1654: }
1655:
1656: public void setRenderParameters(String namespace,
1657: Map<String, String[]> srcMap) {
1658: checkWindowMutable(namespace);
1659:
1660: forbidRedirectIfInActionStage();
1661:
1662: setParameters(getRenderParameterMap(namespace), srcMap);
1663: }
1664:
1665: public void setRenderParameter(String namespace, String name,
1666: String value) {
1667: checkWindowMutable(namespace);
1668:
1669: forbidRedirectIfInActionStage();
1670:
1671: setParameter(getRenderParameterMap(namespace), name, value);
1672: }
1673:
1674: public void setRenderParameter(String namespace, String name,
1675: String[] values) {
1676: checkWindowMutable(namespace);
1677:
1678: forbidRedirectIfInActionStage();
1679:
1680: setParameter(getRenderParameterMap(namespace), name, values);
1681: }
1682:
1683: // -- Invocation - urls
1684:
1685: protected PortalURL createURL(InvocationURL url) {
1686: return new PortalURL(this , url);
1687: }
1688:
1689: protected PortalURL createRenderURL(Invocation invocation,
1690: boolean keepParameters) {
1691: PortalURL url = createURL(invocation.createRenderURL());
1692:
1693: if (keepParameters)
1694: url.setParameters(invocation.getParameterMap());
1695:
1696: return url;
1697: }
1698:
1699: protected PortalURL createActionURL(Invocation invocation,
1700: boolean keepParameters) {
1701: PortalURL url = createURL(invocation.createActionURL());
1702:
1703: if (keepParameters)
1704: url.setParameters(invocation.getParameterMap());
1705:
1706: return url;
1707: }
1708:
1709: public PortalURL createRenderURL() {
1710: return createRenderURL(getInvocation(), false);
1711: }
1712:
1713: public PortalURL createActionURL() {
1714: return createActionURL(getInvocation(), false);
1715: }
1716:
1717: public PortalURL createRenderURL(String namespace,
1718: boolean keepParameters) {
1719: return createRenderURL(getInvocation(namespace), keepParameters);
1720: }
1721:
1722: public PortalURL createActionURL(String namespace,
1723: boolean keepParameters) {
1724: return createActionURL(getInvocation(namespace), keepParameters);
1725: }
1726:
1727: // -- Preferences
1728:
1729: public PortletPreferences getPreferences() {
1730: if (_windowContext.getPreferences() == null) {
1731: PreferencesStore store = getPreferencesStore();
1732:
1733: Window window = getWindow();
1734:
1735: PortletPreferences defaultPreferences = window == null ? null
1736: : window.getDefaultPreferences();
1737:
1738: ArrayList<PreferencesValidator> validators = window == null ? null
1739: : window.getPreferencesValidators();
1740:
1741: try {
1742: Map<String, String[]> storeMap = store
1743: .getPreferencesMap(getPortletRequest(),
1744: getNamespace());
1745:
1746: // XXX: pool these
1747: LinkingPortletPreferences pref = new LinkingPortletPreferences();
1748: pref.start(defaultPreferences, validators, storeMap);
1749:
1750: _windowContext.setPreferences(pref);
1751: } catch (IOException ex) {
1752: throw new RuntimeException(ex);
1753: }
1754: }
1755:
1756: return _windowContext.getPreferences();
1757: }
1758:
1759: // -- User Attributes
1760:
1761: public Map<String, String> getUserAttributeMap() throws IOException {
1762: if (_windowContext.getUserAttributeMap() == null) {
1763: UserAttributeStore store = getUserAttributeStore();
1764:
1765: Set<String> names = getPortal().getUserAttributeNames();
1766:
1767: Map<String, String> userAttributeMap = store
1768: .getUserAttributeMap(getPortletRequest(), names);
1769:
1770: _windowContext.setUserAttributeMap(userAttributeMap);
1771: }
1772:
1773: return _windowContext.getUserAttributeMap();
1774: }
1775:
1776: // Title
1777:
1778: public void setTitle(String title) {
1779: _connection.setAttribute("javax.portlet.title", title);
1780: }
1781:
1782: // -- Client information - character encoding, content type, locales
1783:
1784: // if the value has not been set for the connection,
1785: // the possibilities are defined by the client, and in the case
1786: // of locale and content type the capabilities defined by the
1787: // Window.
1788: //
1789: // Once the value is set for the conneciton, it is the only
1790: // possibility.
1791:
1792: /**
1793: * Get the locale already established or get the most preferred locale.
1794: */
1795: public Locale getResponseLocale() {
1796: // getResponseLocalesSet() updates the windowContext.getResponseLocale() with the
1797: // first entry
1798:
1799: getResponseLocalesSet();
1800: return _windowContext.getResponseLocale();
1801: }
1802:
1803: /**
1804: * True if the set is null or the set contains the locale, or the locale
1805: * without the variant, or the locale without the variant and country, or
1806: * LOCALE_ANY.
1807: */
1808: private boolean containsLocale(Set<Locale> set, Locale locale) {
1809: if (set == null || set.contains(locale))
1810: return true;
1811:
1812: String language = locale.getLanguage();
1813: String country = locale.getCountry();
1814: String variant = locale.getVariant();
1815:
1816: if (variant.length() > 0) {
1817: variant = "";
1818: Locale loc = new Locale(language, country, variant);
1819: if (set.contains(loc))
1820: return true;
1821: }
1822:
1823: if (country.length() > 0) {
1824: country = "";
1825: Locale loc = new Locale(language, country, variant);
1826: if (set.contains(loc))
1827: return true;
1828: }
1829:
1830: if (language.length() > 0) {
1831: Locale loc = LOCALE_ANY;
1832: if (set.contains(loc))
1833: return true;
1834: }
1835:
1836: return false;
1837: }
1838:
1839: /**
1840: * Get an ordered set containing all possible locales, the most preferred
1841: * Locale occurring first. If the locale is already established a Set
1842: * containing only the established locale is returned, if the established
1843: * locale is not one of the supported locales specified in the configuration
1844: * an empty set is returned.
1845: */
1846: public Set<Locale> getResponseLocalesSet() {
1847: Set<Locale> responseLocales = _windowContext
1848: .getResponseLocales();
1849:
1850: Locale established = _windowContext.getResponseHandler()
1851: .getLocale();
1852:
1853: // if it is established, make sure the set contains only
1854: // the established content type. Otherwise the set will
1855: // need to be rebuilt.
1856:
1857: if (established != null && responseLocales != null
1858: && (responseLocales.size() > 0)
1859: && !responseLocales.contains(established))
1860:
1861: responseLocales = null;
1862:
1863: if (responseLocales != null)
1864: return responseLocales;
1865:
1866: responseLocales = new LinkedHashSet<Locale>();
1867:
1868: Locale responseLocale = null; // first one added to Set
1869:
1870: Window window = getWindow();
1871:
1872: Set<Locale> configLocales = window == null ? null : window
1873: .getSupportedLocales();
1874:
1875: Set<Locale> clientLocales = _connection.getClientLocales();
1876:
1877: boolean configSupportsAll = configLocales == null
1878: || configLocales.isEmpty()
1879: || configLocales.contains(LOCALE_ANY);
1880:
1881: boolean clientSupportsAll = clientLocales == null
1882: || clientLocales.isEmpty()
1883: || clientLocales.contains(LOCALE_ANY);
1884:
1885: if (established != null) {
1886: boolean configSupports = configSupportsAll
1887: || containsLocale(configLocales, established);
1888:
1889: boolean clientSupports = clientSupportsAll
1890: || containsLocale(clientLocales, established);
1891:
1892: if (configSupports || clientSupports) {
1893: responseLocales.add(established);
1894: responseLocale = established;
1895: }
1896: } else if (configLocales == null) {
1897: Iterator<Locale> iter = clientLocales.iterator();
1898:
1899: while (iter.hasNext()) {
1900: Locale clientLocale = iter.next();
1901:
1902: if (clientLocale.equals(LOCALE_ANY))
1903: continue;
1904:
1905: if (responseLocale == null)
1906: responseLocale = clientLocale;
1907:
1908: responseLocales.add(clientLocale);
1909: }
1910: } else {
1911: Iterator<Locale> iter = configLocales.iterator();
1912:
1913: while (iter.hasNext()) {
1914: Locale configLocale = iter.next();
1915:
1916: if (configLocale.equals(LOCALE_ANY))
1917: continue;
1918:
1919: if (clientSupportsAll
1920: || clientLocales.contains(configLocale)) {
1921: responseLocales.add(configLocale);
1922:
1923: if (responseLocale == null)
1924: responseLocale = configLocale;
1925: }
1926: }
1927: }
1928:
1929: // XXX: default currently is platform default
1930:
1931: if (responseLocale == null && established == null) {
1932: responseLocale = Locale.getDefault();
1933: responseLocales.add(responseLocale);
1934: }
1935:
1936: _windowContext.setResponseLocale(responseLocale);
1937: _windowContext.setResponseLocales(responseLocales);
1938:
1939: return responseLocales;
1940: }
1941:
1942: /**
1943: * Get the character encoding already established or get the most preferred
1944: * character encoding.
1945: */
1946: public String getResponseCharacterEncoding() {
1947: // getResponseCharacterEncodingsSet() updates the
1948: // windowContext.getResponseCharacterEncoding() with the first entry
1949:
1950: getResponseCharacterEncodingsSet();
1951: return _windowContext.getResponseCharacterEncoding();
1952: }
1953:
1954: /**
1955: * Get an ordered set containing all possible character encodings, the most
1956: * preferred Locale occurring first. If the character encoding is already
1957: * established a Set containing only the established character encoding is
1958: * returned, if the established character encoding is not one of the
1959: * supported character encodings specified in the configuration an empty set
1960: * is returned.
1961: */
1962: public Set<String> getResponseCharacterEncodingsSet() {
1963: Set<String> responseEncodings = _windowContext
1964: .getResponseCharacterEncodings();
1965:
1966: String establishedEncoding = _windowContext
1967: .getResponseHandler().getCharacterEncoding();
1968:
1969: // if it is established, make sure the set contains only
1970: // the established character encoding. Otherwise the set will
1971: // need to be rebuilt.
1972:
1973: if (establishedEncoding != null && responseEncodings != null
1974: && (responseEncodings.size() > 0)
1975: && !responseEncodings.contains(establishedEncoding))
1976:
1977: responseEncodings = null;
1978:
1979: if (responseEncodings != null)
1980: return responseEncodings;
1981:
1982: responseEncodings = new LinkedHashSet<String>();
1983:
1984: String responseEncoding = null; // first one added to Set
1985:
1986: Set<String> clientEncodings = _connection
1987: .getClientCharacterEncodings();
1988:
1989: boolean clientSupportsAll = clientEncodings == null
1990: || clientEncodings.isEmpty()
1991: || clientEncodings.contains("*");
1992:
1993: if (establishedEncoding != null) {
1994: if (clientSupportsAll
1995: || clientEncodings.contains(establishedEncoding)) {
1996: responseEncodings.add(establishedEncoding);
1997: responseEncoding = establishedEncoding;
1998: }
1999: } else {
2000: Iterator<String> iter = clientEncodings.iterator();
2001:
2002: while (iter.hasNext()) {
2003: String clientEncoding = iter.next();
2004:
2005: responseEncodings.add(clientEncoding);
2006:
2007: if (responseEncoding == null)
2008: responseEncoding = clientEncoding;
2009: }
2010:
2011: if (responseEncoding == null) {
2012: // XXX: default is platform default
2013: responseEncoding = System.getProperty("file.encoding");
2014: responseEncodings.add(responseEncoding);
2015: }
2016: }
2017:
2018: _windowContext.setResponseCharacterEncoding(responseEncoding);
2019: _windowContext.setResponseCharacterEncodings(responseEncodings);
2020:
2021: return responseEncodings;
2022: }
2023:
2024: private String getWildcardContentType(String contentType) {
2025: // i.e "text/html" becomes "text/*", null if no wildcard possible
2026: // because there is no '/'
2027:
2028: int i = contentType.indexOf('/');
2029: if (i < 0)
2030: return null;
2031: else
2032: return contentType.substring(0, i + 1) + "*";
2033: }
2034:
2035: public String getResponseContentType() {
2036: // getResponseContentTypesSet() sets _windowContext.getResponseContentType
2037: // to the value of the first entry it add's to the set
2038: getResponseContentTypesSet();
2039:
2040: return _windowContext.getResponseContentType();
2041: }
2042:
2043: public Set<String> getResponseContentTypesSet() {
2044: Set<String> responseTypes = _windowContext
2045: .getResponseContentTypes();
2046:
2047: String establishedType = _windowContext.getResponseHandler()
2048: .getContentType();
2049:
2050: // if it is established, make sure the set contains only
2051: // the established content type. Otherwise the set will
2052: // need to be rebuilt.
2053:
2054: if (establishedType != null && responseTypes != null
2055: && (responseTypes.size() > 0)
2056: && !responseTypes.contains(establishedType))
2057:
2058: responseTypes = null;
2059:
2060: if (responseTypes != null)
2061: return responseTypes;
2062:
2063: responseTypes = new LinkedHashSet<String>();
2064:
2065: String responseType = null; // first one added to Set
2066:
2067: Window window = getWindow();
2068:
2069: Set<String> configTypes = window == null ? null : window
2070: .getSupportedContentTypes(getPortletMode());
2071:
2072: boolean configSupportsAll = configTypes == null
2073: || configTypes.contains("*/*");
2074:
2075: Set<String> clientTypes = _connection.getClientContentTypes();
2076:
2077: boolean clientSupportsAll = clientTypes == null
2078: || clientTypes.isEmpty() || clientTypes.contains("*/*");
2079:
2080: if (establishedType != null) {
2081: String wildcard = getWildcardContentType(establishedType);
2082:
2083: if ((configSupportsAll
2084: || configTypes.contains(establishedType) || configTypes
2085: .contains(wildcard))
2086: && (clientSupportsAll
2087: || clientTypes.contains(establishedType) || clientTypes
2088: .contains(wildcard))) {
2089: responseTypes.add(establishedType);
2090: responseType = establishedType;
2091: }
2092: } else if (configSupportsAll) {
2093: Iterator<String> iter = clientTypes.iterator();
2094:
2095: while (iter.hasNext()) {
2096: String clientType = iter.next();
2097:
2098: if (responseType == null)
2099: responseType = clientType;
2100:
2101: responseTypes.add(clientType);
2102: }
2103: } else {
2104:
2105: Iterator<String> iter = configTypes.iterator();
2106:
2107: // wildcards in the config are added a second time around, so that they
2108: // appear further down the list (they are less desirable as a return
2109: // value)
2110:
2111: boolean configHasWildcard = false;
2112:
2113: while (iter.hasNext()) {
2114: String configType = iter.next();
2115:
2116: boolean isUsableConfigType = false;
2117:
2118: if (configType.indexOf('*') > -1) {
2119: configHasWildcard = true;
2120: } else if (clientSupportsAll
2121: || clientTypes.contains(configType)) {
2122: isUsableConfigType = true;
2123: } else {
2124: String wildcardConfigType = getWildcardContentType(configType);
2125:
2126: if (wildcardConfigType != null
2127: && clientTypes.contains(wildcardConfigType)) {
2128: isUsableConfigType = true;
2129: }
2130: }
2131:
2132: if (isUsableConfigType) {
2133: responseTypes.add(configType);
2134:
2135: if (responseType == null)
2136: responseType = configType;
2137: }
2138: }
2139:
2140: if (configHasWildcard) {
2141:
2142: iter = clientTypes.iterator();
2143:
2144: while (iter.hasNext()) {
2145: String clientType = iter.next();
2146:
2147: boolean isUsableClientType = false;
2148:
2149: if (configSupportsAll)
2150: isUsableClientType = true;
2151: else {
2152: String wildcardClientType = clientType
2153: .indexOf('*') > -1 ? clientType
2154: : getWildcardContentType(clientType);
2155:
2156: if (wildcardClientType != null
2157: && configTypes
2158: .contains(wildcardClientType)) {
2159: isUsableClientType = true;
2160: }
2161: }
2162:
2163: if (isUsableClientType) {
2164: responseTypes.add(clientType);
2165:
2166: if (responseType == null)
2167: responseType = clientType;
2168: }
2169: }
2170: }
2171: }
2172:
2173: _windowContext.setResponseContentType(responseType);
2174: _windowContext.setResponseContentTypes(responseTypes);
2175:
2176: return responseTypes;
2177: }
2178:
2179: // -- ResponseHandler
2180:
2181: public String getContentType() {
2182: return _windowContext.getResponseHandler().getContentType();
2183: }
2184:
2185: public void setContentType(String contentType) {
2186: if (contentType.equals(_windowContext.getResponseHandler()
2187: .getContentType()))
2188: return;
2189:
2190: // make sure the content type is allowed before
2191: // allowing it to be set
2192:
2193: PortletMode currentMode = getPortletMode();
2194:
2195: Window window = _windowContext.getWindow();
2196:
2197: Set<String> configTypes = null;
2198:
2199: if (window != null)
2200: configTypes = window.getSupportedContentTypes(currentMode);
2201:
2202: if (configTypes != null && !configTypes.contains(contentType))
2203: throw new IllegalArgumentException(
2204: "portlet with namespace `"
2205: + _windowContext.getNamespace()
2206: + "' does not support content type `"
2207: + contentType + "'" + " when in mode `"
2208: + currentMode + "'");
2209:
2210: _windowContext.getResponseHandler().setContentType(contentType);
2211: }
2212:
2213: public Locale getLocale() {
2214: return _windowContext.getResponseHandler().getLocale();
2215: }
2216:
2217: public void addProperty(String key, String value) {
2218: _windowContext.getResponseHandler().addProperty(key, value);
2219: }
2220:
2221: public void setProperty(String key, String value) {
2222: _windowContext.getResponseHandler().setProperty(key, value);
2223: }
2224:
2225: public String getCharacterEncoding() {
2226: return _windowContext.getResponseHandler()
2227: .getCharacterEncoding();
2228: }
2229:
2230: public PrintWriter getWriter() throws IOException {
2231: return _windowContext.getResponseHandler().getWriter();
2232: }
2233:
2234: public void setBufferSize(int size) {
2235: _windowContext.getResponseHandler().setBufferSize(size);
2236: }
2237:
2238: public int getBufferSize() {
2239: return _windowContext.getResponseHandler().getBufferSize();
2240: }
2241:
2242: /**
2243: * @param flushToClient true flush all buffers through to the client.
2244: * If false, flush only the buffers for the current window
2245: */
2246: public void flushBuffer(boolean flushToClient) throws IOException {
2247: ResponseHandler parentResponseHandler = _windowContext
2248: .getParentResponseHandler();
2249:
2250: ResponseHandler responseHandler = _windowContext
2251: .getResponseHandler();
2252:
2253: while (responseHandler != null) {
2254: if (!flushToClient
2255: && responseHandler == parentResponseHandler)
2256: break;
2257:
2258: responseHandler.flushBuffer();
2259:
2260: responseHandler = responseHandler.getSuccessor();
2261: }
2262: }
2263:
2264: /**
2265: * @param resetRenderer if true, reset all of the buffers for the current
2266: * window. If false, reset all of the buffers until the
2267: * RendererResponseHandler, reset that too but in such a way
2268: * that it will write the decorations again.
2269: */
2270: public void reset(boolean resetRenderer) {
2271: ResponseHandler parentResponseHandler = _windowContext
2272: .getParentResponseHandler();
2273:
2274: ResponseHandler responseHandler = _windowContext
2275: .getResponseHandler();
2276:
2277: RendererResponseHandler renderer = null;
2278: boolean isWriter = false;
2279: boolean isOutputStream = false;
2280:
2281: while (responseHandler != null) {
2282: if (responseHandler == parentResponseHandler)
2283: break;
2284:
2285: if (!resetRenderer
2286: && (responseHandler instanceof RendererResponseHandler)) {
2287: renderer = ((RendererResponseHandler) responseHandler);
2288: isWriter = renderer.isWriter();
2289: isOutputStream = renderer.isOutputStream();
2290: }
2291:
2292: responseHandler.reset();
2293:
2294: responseHandler = responseHandler.getSuccessor();
2295: }
2296:
2297: if (renderer != null) {
2298: if (isWriter) {
2299: try {
2300: renderer.getWriter();
2301: } catch (IOException ex) {
2302: setConnectionFailed(ex);
2303: }
2304: }
2305:
2306: if (isOutputStream) {
2307: try {
2308: renderer.getOutputStream();
2309: } catch (IOException ex) {
2310: setConnectionFailed(ex);
2311: }
2312: }
2313: }
2314: }
2315:
2316: /**
2317: * If the current window has a renderer that is always-write or
2318: * always-stream, call getWriter() or getOutputStream()
2319: */
2320: protected void checkAlwaysWriteOrStream() throws IOException {
2321: if (_windowContext == null)
2322: return;
2323:
2324: ResponseHandler parentResponseHandler = _windowContext
2325: .getParentResponseHandler();
2326:
2327: ResponseHandler responseHandler = _windowContext
2328: .getResponseHandler();
2329: ResponseHandler next = responseHandler;
2330:
2331: while (next != null && next != parentResponseHandler) {
2332: if (responseHandler instanceof RendererResponseHandler) {
2333: RendererResponseHandler renderer = ((RendererResponseHandler) next);
2334: boolean isWriter = renderer.isWriter();
2335: boolean isOutputStream = renderer.isOutputStream();
2336:
2337: if (!isWriter && !isOutputStream) {
2338:
2339: if (renderer.isAlwaysWrite()) {
2340: if (getRenderResponse().getContentType() == null) {
2341: String contentType = renderer
2342: .getDefaultContentType();
2343: getRenderResponse().setContentType(
2344: contentType);
2345: }
2346:
2347: responseHandler.getWriter();
2348: } else if (renderer.isAlwaysStream()) {
2349: if (getRenderResponse().getContentType() == null) {
2350: String contentType = renderer
2351: .getDefaultContentType();
2352: getRenderResponse().setContentType(
2353: contentType);
2354: }
2355:
2356: responseHandler.getOutputStream();
2357: }
2358: }
2359:
2360: next = null;
2361: } else
2362: next = next.getSuccessor();
2363: }
2364: }
2365:
2366: public void resetBuffer(boolean resetRenderer) {
2367: ResponseHandler parentResponseHandler = _windowContext
2368: .getParentResponseHandler();
2369:
2370: ResponseHandler responseHandler = _windowContext
2371: .getResponseHandler();
2372:
2373: while (responseHandler != null) {
2374:
2375: if (responseHandler == parentResponseHandler)
2376: break;
2377:
2378: if (!resetRenderer
2379: && (responseHandler instanceof RendererResponseHandler))
2380: break;
2381:
2382: responseHandler.resetBuffer();
2383:
2384: responseHandler = responseHandler.getSuccessor();
2385: }
2386: }
2387:
2388: public boolean isCommitted() {
2389: return _windowContext.getResponseHandler().isCommitted();
2390: }
2391:
2392: public OutputStream getPortletOutputStream() throws IOException {
2393: return _windowContext.getResponseHandler().getOutputStream();
2394: }
2395:
2396: // -- Security and user identity
2397:
2398: public boolean isUserInRole(String role) {
2399: Window window = getWindow();
2400:
2401: Map<String, String> roleRefMap = window == null ? null : window
2402: .getRoleRefMap();
2403:
2404: if (roleRefMap != null) {
2405: String effectiveRole = roleRefMap.get(role);
2406:
2407: if (effectiveRole != null)
2408: role = effectiveRole;
2409: }
2410:
2411: return _connection.isUserInRole(role);
2412: }
2413:
2414: public String getRemoteUser() {
2415: return _connection.getRemoteUser();
2416: }
2417:
2418: public java.security.Principal getUserPrincipal() {
2419: return _connection.getUserPrincipal();
2420: }
2421:
2422: public String getAuthType() {
2423: return _connection.getAuthType();
2424: }
2425:
2426: public boolean isSecure() {
2427: return _connection.isSecure();
2428: }
2429:
2430: public String getRequestedSessionId() {
2431: return _connection.getRequestedSessionId();
2432: }
2433:
2434: public boolean isRequestedSessionIdValid() {
2435: return _connection.isRequestedSessionIdValid();
2436: }
2437:
2438: public boolean canGuaranteeIntegrity() {
2439: return _connection.canGuaranteeIntegrity();
2440: }
2441:
2442: public boolean canGuaranteeConfidentiality() {
2443: return _connection.canGuaranteeConfidentiality();
2444: }
2445:
2446: // -- Connection - request info
2447:
2448: public String getContextPath() {
2449: return _connection.getContextPath();
2450: }
2451:
2452: public String getServerName() {
2453: return _connection.getServerName();
2454: }
2455:
2456: public int getServerPort() {
2457: return _connection.getServerPort();
2458: }
2459:
2460: public String getScheme() {
2461: return _connection.getScheme();
2462: }
2463:
2464: public String getProperty(String name) {
2465: return _connection.getProperty(name);
2466: }
2467:
2468: public Enumeration getProperties(String name) {
2469: return _connection.getProperties(name);
2470: }
2471:
2472: public Enumeration getPropertyNames() {
2473: return _connection.getPropertyNames();
2474: }
2475:
2476: // -- Connection - attributes
2477:
2478: public Enumeration getAttributeNames() {
2479: return _connection.getAttributeNames();
2480: }
2481:
2482: public Object getAttribute(String name) {
2483: if (name.equals(PortletRequest.USER_INFO)) {
2484: try {
2485: return getUserAttributeMap();
2486: } catch (IOException ex) {
2487: throw new RuntimeException(ex);
2488: }
2489: } else
2490: return _connection.getAttribute(name);
2491: }
2492:
2493: public void setAttribute(String name, Object o) {
2494: _connection.setAttribute(name, o);
2495: }
2496:
2497: public void removeAttribute(String name) {
2498: _connection.removeAttribute(name);
2499: }
2500:
2501: public PortletSession getPortletSession() {
2502: return getPortletSession(false);
2503: }
2504:
2505: public PortletSession getPortletSession(boolean create) {
2506: return _connection.getPortletSession(create);
2507: }
2508:
2509: // -- Connection - Submit - Reader/InputStream
2510:
2511: public InputStream getSubmitInputStream() throws IOException {
2512: return _connection.getSubmitInputStream();
2513: }
2514:
2515: public void setSubmitCharacterEncoding(String enc)
2516: throws UnsupportedEncodingException {
2517: _connection.setSubmitCharacterEncoding(enc);
2518: }
2519:
2520: public String getSubmitCharacterEncoding() {
2521: return _connection.getSubmitCharacterEncoding();
2522: }
2523:
2524: public BufferedReader getSubmitReader()
2525: throws UnsupportedEncodingException, IOException {
2526: return _connection.getSubmitReader();
2527: }
2528:
2529: public String getSubmitContentType() {
2530: return _connection.getSubmitContentType();
2531: }
2532:
2533: public int getSubmitContentLength() {
2534: return _connection.getSubmitContentLength();
2535: }
2536:
2537: // Connection - urls and redirect
2538:
2539: public String resolveURL(String path) {
2540: return _connection.resolveURL(path);
2541: }
2542:
2543: public String resolveURL(String path, boolean isSecure)
2544: throws PortletSecurityException {
2545: return _connection.resolveURL(path, isSecure);
2546: }
2547:
2548: public String encodeURL(String path) {
2549: return _connection.encodeURL(path);
2550: }
2551:
2552: public void sendRedirect(String location) throws IOException {
2553: if (isForbidRedirect())
2554: throw new IllegalStateException(
2555: "sendRedirect() forbidden, portlet mode, window state, "
2556: + " or render parameters were set in action");
2557:
2558: _connection.sendRedirect(location);
2559: }
2560: }
|