001: /**
002: * Copyright 2003 Sun Microsystems, Inc. All
003: * rights reserved. Use of this product is subject
004: * to license terms. Federal Acquisitions:
005: * Commercial Software -- Government Users
006: * Subject to Standard License Terms and
007: * Conditions.
008: *
009: * Sun, Sun Microsystems, the Sun logo, and Sun ONE
010: * are trademarks or registered trademarks of Sun Microsystems,
011: * Inc. in the United States and other countries.
012: */package com.sun.portal.wsrp.consumer.markup.impl;
013:
014: import com.sun.portal.container.ContainerRequest;
015: import com.sun.portal.container.ContainerException;
016: import com.sun.portal.container.ContentException;
017:
018: import com.sun.portal.wsrp.consumer.producermanager.ProducerEntityStatus;
019: import com.sun.portal.wsrp.consumer.markup.ProducerSessionManager;
020: import com.sun.portal.wsrp.consumer.markup.MarkupConfig;
021: import com.sun.portal.wsrp.consumer.markup.MarkupContentException;
022: import com.sun.portal.wsrp.consumer.common.RemoteServiceStubManager;
023: import com.sun.portal.wsrp.consumer.common.WSRPConsumerException;
024: import com.sun.portal.wsrp.consumer.common.WSRPConsumerErrorCode;
025:
026: import com.sun.portal.wsrp.common.stubs.SessionContext;
027: import com.sun.portal.wsrp.common.stubs.WSRP_v1_Markup_PortType;
028: import com.sun.portal.wsrp.common.stubs.CookieProtocol;
029: import com.sun.portal.wsrp.common.stubs.RegistrationContext;
030: import com.sun.portal.wsrp.common.stubs.InitCookie;
031: import com.sun.portal.wsrp.common.stubs.InvalidRegistrationFault;
032: import com.sun.portal.wsrp.common.stubs.AccessDeniedFault;
033: import com.sun.portal.wsrp.common.stubs.OperationFailedFault;
034: import com.sun.portal.log.common.PortalLogger;
035:
036: import java.net.URL;
037: import java.rmi.RemoteException;
038: import java.util.logging.Level;
039: import java.util.logging.Logger;
040:
041: import javax.xml.rpc.Stub;
042:
043: import com.sun.xml.rpc.client.http.CookieJar;
044: import com.sun.xml.rpc.client.StubPropertyConstants;
045:
046: /**
047: * This implementation has methods to manage the session and cookies
048: * with a WSRP Producer for a portal user, that is allowed to have
049: * portlets that require init cookie support. Information about
050: * the session ids and markup port to be used is bucketed as instances of
051: * ProducerSessionInfo. Criteria to bucket them depends on the
052: * CookieProtocol of the producer. Each instance of this class has
053: * a Markup Port type that would be used by all requests for a user
054: * to a producer that meets the crietria. These instances are stored
055: * in the provider context as a session properties. The key for this property is
056: * based on the cookie protocol. If CookieProtocol is not
057: * perGroup, key is producer entity id, which means all requests to this producer
058: * use the same markup port.
059: * If CookieProtocol is perGroup, key is producer entity id + group id.
060: *
061: */
062: public class ProducerSessionManagerInitCookie implements
063: ProducerSessionManager {
064:
065: private static Logger logger = PortalLogger
066: .getLogger(ProducerSessionManagerInitCookie.class);
067:
068: /**
069: * This method processes the SessionContext sent by the producer
070: * as part of the response.
071: * Information in SessionContext must be stored so that it can be returned
072: * on following requests to maintain the session.
073: *
074: * @param markupConfig markup configuration object.
075: * @param request container request.
076: * @param sessionContext session context sent back as a response from the producer.
077: * @exception com.sun.portal.container.ContainerException
078: * @exception com.sun.portal.container.ContentException
079: */
080:
081: public void processSessionContext(MarkupConfig markupConfig,
082: ContainerRequest request, SessionContext sessionContext)
083: throws ContainerException, ContentException {
084:
085: ProducerSessionInfo producerSessionInfo = getProducerSessionInfo(
086: markupConfig, request);
087:
088: if (sessionContext != null) {
089: producerSessionInfo.setSessionId(request.getEntityID(),
090: sessionContext.getSessionID());
091: }
092:
093: //
094: // Make the cookie jar available in the session
095: // so it can be shared by non-jaxrpc request like proxy
096: // Internal API of JAXPRC
097:
098: CookieJar cookieJar = (CookieJar) (((Stub) producerSessionInfo
099: .getMarkupPort())
100: ._getProperty(StubPropertyConstants.HTTP_COOKIE_JAR));
101: if (cookieJar != null) {
102:
103: if (logger.isLoggable(Level.FINEST))
104: logger.log(Level.FINEST, "PSWS_CSPWCMI0012",
105: getCookieHandleKey(markupConfig, request));
106:
107: request.getHttpServletRequest().getSession(true)
108: .setAttribute(
109: getCookieHandleKey(markupConfig, request),
110: cookieJar);
111: } else {
112: if (logger.isLoggable(Level.FINEST))
113: logger.log(Level.FINEST, "PSWS_CSPWCMI0012",
114: getCookieHandleKey(markupConfig, request));
115: }
116:
117: }
118:
119: /**
120: * Get the session id to be returned back to producer
121: * for this request
122: *
123: * @param markupConfig
124: * @param request
125: * @exception com.sun.portal.container.ContainerException
126: * @exception com.sun.portal.container.ContentException
127: */
128: public String getProducerSessionId(MarkupConfig markupConfig,
129: ContainerRequest request) throws ContainerException,
130: ContentException {
131:
132: ProducerSessionInfo authProducerSessionInfo = getProducerSessionInfo(
133: markupConfig, request);
134:
135: return authProducerSessionInfo.getSessionId(request
136: .getEntityID());
137: }
138:
139: /**
140: * Invalidate or remove the session explicitly.
141: *
142: * @param markupConfig
143: * @param request
144: * @exception com.sun.portal.container.ContainerException
145: * @exception com.sun.portal.container.ContentException
146: */
147: public void resetSessionId(String invalidSessionId,
148: MarkupConfig markupConfig, ContainerRequest request)
149: throws ContainerException, ContentException {
150:
151: ProducerSessionInfo authProducerSessionInfo = getProducerSessionInfo(
152: markupConfig, request);
153:
154: authProducerSessionInfo.releaseSessionId(request.getEntityID());
155:
156: }
157:
158: /**
159: * Returns a markup porttype stub that can be used
160: * for calling remote markup methods. If initCookie
161: * requirement is on for this producer, this stub
162: * is ornamented with all the right cookies.
163: *
164: * @param markupConfig
165: * @param request
166: * @exception com.sun.portal.container.ContainerException
167: * @exception com.sun.portal.container.ContentException
168: */
169:
170: public WSRP_v1_Markup_PortType getMarkupPortType(
171: MarkupConfig markupConfig, ContainerRequest request)
172: throws ContainerException, ContentException {
173:
174: ProducerSessionInfo authProducerSessionInfo = getProducerSessionInfo(
175: markupConfig, request);
176: WSRP_v1_Markup_PortType port = authProducerSessionInfo
177: .getMarkupPort();
178:
179: if (port == null) {
180:
181: // note, that this instance of port
182: // is set up in two steps. First step creates an instance and
183: // second steps assigns the instance in ProducerSessionInfo.
184: // The second step is an atomic operation.
185: // this is to avoid infamous synchronize problem when
186: // objects are half baked or that double-locking ..
187: //
188: synchronized (authProducerSessionInfo) {
189: port = authProducerSessionInfo.getMarkupPort();
190: if (port == null) {
191: if (logger.isLoggable(Level.FINEST))
192: logger.log(Level.FINEST, "PSWS_CSPWCMI0014",
193: markupConfig.getProducerEntityId());
194:
195: port = obtainMarkupPort(markupConfig);
196: authProducerSessionInfo.setMarkupPort(port);
197: }
198: }
199: }
200:
201: return port;
202:
203: }
204:
205: /**
206: * This method is called by the caller( MarkupManager) whenever
207: * it finds get a InvalidCookie fault. In that case, we need to clear
208: * the markup stub that is used and present in the relevant
209: * AuthProducerSessioninfo.
210: * Note that all methods setting the markup port in the ProducerSessionInfo
211: * sunchronize on the ProducerSessionInfo object.
212: */
213:
214: public void resetMarkupPortType(
215: WSRP_v1_Markup_PortType invalidPortType,
216: MarkupConfig markupConfig, ContainerRequest request)
217: throws ContainerException, ContentException {
218:
219: ProducerSessionInfo authProducerSessionInfo = getProducerSessionInfo(
220: markupConfig, request);
221:
222: WSRP_v1_Markup_PortType port = authProducerSessionInfo
223: .getMarkupPort();
224:
225: // clear it only if someone else hasn't cleared it
226: // hence the ==
227: if (port == invalidPortType) {
228: synchronized (authProducerSessionInfo) {
229: port = authProducerSessionInfo.getMarkupPort();
230: if (port == invalidPortType) {
231: authProducerSessionInfo
232: .setMarkupPort((WSRP_v1_Markup_PortType) null);
233: }
234: }
235: }
236: }
237:
238: /**
239: * Return the instance of ProducerSessionInfo
240: * from provider context containing session information that can used
241: * for operations to the producer/portlet targeted in the request.
242: * If none exists, initialize one sych object and set it up in
243: * the provider context.
244: */
245:
246: private ProducerSessionInfo getProducerSessionInfo(
247: MarkupConfig markupConfig, ContainerRequest request)
248: throws ContainerException, ContentException {
249:
250: String key = getSessionInfoKey(markupConfig);
251:
252: ProducerSessionInfo session = (ProducerSessionInfo) MarkupUtil
253: .getSessionProperty(markupConfig, request, key);
254:
255: if (session == null) {
256: synchronized (request.getHttpServletRequest()) {
257:
258: //
259: // check again before creating an instance of
260: // authProducerSessionInfo
261: // Also note, that this instance of ProducerSessionInfo
262: // is set up in two steps. First step creates an instance and
263: // second steps assigns the instance in the provider context.
264: // The second step is an atomic operation.
265: // this is to avoid infamous synchronize problem when
266: // objects are half baked or that double-locking ..
267:
268: session = (ProducerSessionInfo) MarkupUtil
269: .getSessionProperty(markupConfig, request, key);
270:
271: if (session == null) {
272:
273: if (logger.isLoggable(Level.FINEST))
274: logger.log(Level.FINEST, "PSWS_CSPWCMI0015",
275: key);
276:
277: session = new ProducerSessionInfo(markupConfig
278: .getProducerEntityId(), markupConfig
279: .getPortletDescription().getGroupID(), null);
280:
281: MarkupUtil.setSessionProperty(markupConfig,
282: request, key, session);
283: }
284: }
285: }
286:
287: return session;
288:
289: }
290:
291: /**
292: * This method gets a markup port that is initialized with cookie
293: * if needed that can be used later by the markup for its operation.
294: */
295:
296: private WSRP_v1_Markup_PortType obtainMarkupPort(
297: MarkupConfig markupConfig) throws ContainerException,
298: ContentException {
299:
300: //
301: // get an instance of Markup port type based on
302: // the cookie requirment of the service description
303: //
304:
305: WSRP_v1_Markup_PortType markupPortType = null;
306:
307: URL producerURL = markupConfig.getProducerEntity().getURL();
308:
309: RemoteServiceStubManager rssm = markupConfig
310: .getRemoteServiceStubManager();
311: CookieProtocol cookieProtocol = markupConfig
312: .getServiceDescription().getRequiresInitCookie();
313:
314: try {
315:
316: //
317: // retrieve the markup port type endpoint from
318: // the producer entity
319: //
320:
321: String endpoint = markupConfig.getProducerEntity()
322: .getMarkupEndpoint();
323:
324: if (cookieProtocol == null
325: || cookieProtocol.equals(CookieProtocol.none)) {
326:
327: // If cookie protocol is none, that means all
328: // users, all requests to this producer can share
329: // the same stub.
330: //
331:
332: markupPortType = rssm.getMarkupPortType(endpoint,
333: RemoteServiceStubManager.FOR_ALL);
334: } else {
335: //
336: // Get a brand new MarkupPortType that be used for all
337: // the requests to this producer or a group of portlets
338: // in this producer -- for this user.
339: //
340:
341: markupPortType = rssm.getMarkupPortType(endpoint,
342: RemoteServiceStubManager.PER_SESSION);
343: // Set the property to indicate we are
344: // interested in maintaining the session
345: // through JAX-RPC
346: //
347:
348: ((Stub) markupPortType)._setProperty(
349: Stub.SESSION_MAINTAIN_PROPERTY, Boolean.TRUE);
350:
351: if (logger.isLoggable(Level.FINEST))
352: logger.log(Level.FINEST, "PSWS_CSPWCMI0016");
353:
354: RegistrationContext registrationContext = markupConfig
355: .getProducerEntity().getRegistrationContext();
356: InitCookie initCookie = new InitCookie();
357: initCookie.setRegistrationContext(registrationContext);
358: markupPortType.initCookie(initCookie);
359: }
360: } catch (InvalidRegistrationFault fault) {
361:
362: try {
363: markupConfig.getProducerEntityManager().setStatus(
364: markupConfig.getProducerEntityId(),
365: ProducerEntityStatus.BAD_REGISTRATION);
366: } catch (WSRPConsumerException ex) {
367: throw new ContainerException(
368: "Bad Registration:failed to disable producer:"
369: + fault.toString(), ex);
370: }
371:
372: throw new MarkupContentException(MarkupContentException
373: .getFaultErrorCode(fault), "Fault from producer:"
374: + fault.toString(), fault);
375: } catch (AccessDeniedFault fault) {
376: throw new MarkupContentException(MarkupContentException
377: .getFaultErrorCode(fault), "Fault from producer:"
378: + fault.toString(), fault);
379: } catch (OperationFailedFault fault) {
380: throw new MarkupContentException(MarkupContentException
381: .getFaultErrorCode(fault), "Fault from producer:"
382: + fault.toString(), fault);
383: } catch (RemoteException ex) {
384: throw new MarkupContentException(
385: WSRPConsumerErrorCode.REMOTE_EXCEPTION,
386: "RemoteException from producer:" + ex.toString(),
387: ex);
388: } catch (WSRPConsumerException ex) {
389: throw new ContainerException(
390: "RemoteException from producer:" + ex.toString(),
391: ex);
392: }
393:
394: return markupPortType;
395:
396: }
397:
398: /**
399: * Returns the key that it is used to store the
400: * cookie jar in the session.
401: * We need to share this string with the proxy servlet
402: * that also might want to read or update the cookies
403: * when processing a url of type resource. ( Alejandro
404: * belives it this way. Personally I don't believe it.)
405: *
406: * @param markupConfig
407: * @param request
408: * @exception com.sun.portal.container.ContainerException
409: * @exception com.sun.portal.container.ContentException
410: */
411: public String getCookieHandleKey(MarkupConfig markupConfig,
412: ContainerRequest request) throws ContainerException {
413:
414: return getSessionInfoKey(markupConfig) + "_cookieHandle";
415: }
416:
417: /**
418: * An ProducerSessionInfo instance created to manage session
419: * is stored in the provider context with the key
420: * calculated based on how the markup port in it is to be shared
421: * Obviously that is based on the cookie protocol.
422: * If CookieProtocol is not on, or is perUser, that means
423: * the ProducerSessionInfo manages all the sessions
424: * for a logged in user to a given producer. Hence the key is
425: * the producerEntityId.
426: * If it is perGroup, that means the stub can used
427: * only for portlets that belong to the same group. Hence the
428: * key is producerEntityId + group Id.
429: */
430:
431: private String getSessionInfoKey(MarkupConfig markupConfig) {
432:
433: //
434: // Markup key generated needs to be based on
435: // what kind of initCookie
436: // is needed for this producer/portlet
437: //
438:
439: CookieProtocol cookieProtocol = markupConfig
440: .getServiceDescription().getRequiresInitCookie();
441: if (CookieProtocol.perGroup.equals(cookieProtocol)) {
442: return markupConfig.getProducerEntityId() + "_"
443: + markupConfig.getPortletDescription().getGroupID();
444: } else {
445:
446: return markupConfig.getProducerEntityId();
447: }
448:
449: }
450:
451: }
|