001: /******************************************************************************
002: * JBoss, a division of Red Hat *
003: * Copyright 2007, Red Hat Middleware, LLC, and individual *
004: * contributors as indicated by the @authors tag. See the *
005: * copyright.txt in the distribution for a full listing of *
006: * individual contributors. *
007: * *
008: * This is free software; you can redistribute it and/or modify it *
009: * under the terms of the GNU Lesser General Public License as *
010: * published by the Free Software Foundation; either version 2.1 of *
011: * the License, or (at your option) any later version. *
012: * *
013: * This software is distributed in the hope that it will be useful, *
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of *
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
016: * Lesser General Public License for more details. *
017: * *
018: * You should have received a copy of the GNU Lesser General Public *
019: * License along with this software; if not, write to the Free *
020: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
021: * 02110-1301 USA, or see the FSF site: http://www.fsf.org. *
022: ******************************************************************************/package org.jboss.portal.wsrp.consumer;
023:
024: import org.jboss.logging.Logger;
025: import org.jboss.portal.common.util.ParameterValidation;
026: import org.jboss.portal.portlet.InvokerUnavailableException;
027: import org.jboss.portal.portlet.NoSuchPortletException;
028: import org.jboss.portal.portlet.Portlet;
029: import org.jboss.portal.portlet.PortletContext;
030: import org.jboss.portal.portlet.PortletInvokerException;
031: import org.jboss.portal.wsrp.WSRPConstants;
032: import org.jboss.portal.wsrp.WSRPTypeFactory;
033: import org.jboss.portal.wsrp.consumer.portlet.WSRPPortlet;
034: import org.jboss.portal.wsrp.consumer.portlet.info.WSRPPortletInfo;
035: import org.jboss.portal.wsrp.core.CookieProtocol;
036: import org.jboss.portal.wsrp.core.GetPortletDescription;
037: import org.jboss.portal.wsrp.core.GetPortletPropertyDescription;
038: import org.jboss.portal.wsrp.core.GetServiceDescription;
039: import org.jboss.portal.wsrp.core.InvalidHandleFault;
040: import org.jboss.portal.wsrp.core.InvalidRegistrationFault;
041: import org.jboss.portal.wsrp.core.ModifyRegistration;
042: import org.jboss.portal.wsrp.core.OperationFailedFault;
043: import org.jboss.portal.wsrp.core.PortletDescription;
044: import org.jboss.portal.wsrp.core.PortletDescriptionResponse;
045: import org.jboss.portal.wsrp.core.PortletPropertyDescriptionResponse;
046: import org.jboss.portal.wsrp.core.RegistrationContext;
047: import org.jboss.portal.wsrp.core.RegistrationState;
048: import org.jboss.portal.wsrp.core.ServiceDescription;
049: import org.jboss.portal.wsrp.core.WSRP_v1_PortletManagement_PortType;
050: import org.jboss.portal.wsrp.servlet.UserAccess;
051:
052: import java.util.Collections;
053: import java.util.HashMap;
054: import java.util.HashSet;
055: import java.util.LinkedHashMap;
056: import java.util.Map;
057: import java.util.Set;
058:
059: /**
060: * @author <a href="mailto:chris.laprun@jboss.com">Chris Laprun</a>
061: * @version $Revision: 9360 $
062: * @since 2.6
063: */
064: public class ProducerInfo {
065: private final static Logger log = Logger
066: .getLogger(ProducerInfo.class);
067:
068: // Persistent information
069:
070: /** DB primary key */
071: private Long key;
072:
073: /** Configuration of the remote WS endpoints */
074: private EndpointConfigurationInfo persistentEndpointInfo;
075:
076: /** Registration information */
077: private RegistrationInfo persistentRegistrationInfo;
078:
079: /** The Producer's identifier */
080: private String persistentId;
081:
082: /** The cache expiration duration (in seconds) for cached values */
083: private Integer persistentExpirationCacheSeconds;
084:
085: /** The activated status of the associated Consumer */
086: private boolean persistentActive;
087:
088: // Transient information
089:
090: /** The Cookie handling policy required by the Producer */
091: private CookieProtocol requiresInitCookie;
092:
093: /** The Producer-Offered Portlets (handle -> WSRPPortlet) */
094: private Map<String, Portlet> popsMap;
095:
096: /** A cache for Consumer-Configured Portlets (handle -> WSRPPortlet) */
097: private Map<String, Portlet> ccpsMap;
098:
099: /** Portlet groups. */
100: private Map<String, Set<Portlet>> portletGroups;
101:
102: /** Time at which the cache expires */
103: private long expirationTimeMillis;
104:
105: private boolean isModifyRegistrationRequired;
106:
107: private ConsumerRegistry registry;
108: private static final String REGISTER_MEANING = "Should clients ask for a new service description?";
109: private static final String REFRESH_MEANING = "Did just refresh?";
110: private static final String ERASED_LOCAL_REGISTRATION_INFORMATION = "Erased local registration information!";
111:
112: /*protected org.jboss.portal.wsrp.core.ItemDescription[] userCategoryDescriptions;
113: protected org.jboss.portal.wsrp.core.ItemDescription[] customUserProfileItemDescriptions;
114: protected org.jboss.portal.wsrp.core.ItemDescription[] customWindowStateDescriptions;
115: protected org.jboss.portal.wsrp.core.ItemDescription[] customModeDescriptions;
116:
117: protected org.jboss.portal.wsrp.core.ModelDescription registrationPropertyDescription;
118: protected java.lang.String[] locales;
119: protected org.jboss.portal.wsrp.core.ResourceList resourceList;*/
120:
121: public ProducerInfo() {
122: persistentEndpointInfo = new EndpointConfigurationInfo(this );
123: }
124:
125: public ConsumerRegistry getRegistry() {
126: return registry;
127: }
128:
129: public void setRegistry(ConsumerRegistry registry) {
130: this .registry = registry;
131: }
132:
133: public Long getKey() {
134: return key;
135: }
136:
137: public void setKey(Long key) {
138: this .key = key;
139: }
140:
141: public EndpointConfigurationInfo getEndpointConfigurationInfo() {
142: return persistentEndpointInfo;
143: }
144:
145: void setEndpointConfigurationInfo(
146: EndpointConfigurationInfo endpointConfigurationInfo) {
147: this .persistentEndpointInfo = endpointConfigurationInfo;
148: }
149:
150: public RegistrationInfo getRegistrationInfo() {
151: return persistentRegistrationInfo;
152: }
153:
154: public void setRegistrationInfo(RegistrationInfo registrationInfo) {
155: this .persistentRegistrationInfo = registrationInfo;
156: }
157:
158: public boolean isRegistered() {
159: if (persistentRegistrationInfo != null) {
160: Boolean valid = persistentRegistrationInfo
161: .isRegistrationValid();
162: if (valid == null) {
163: return persistentRegistrationInfo
164: .getRegistrationHandle() != null;
165: } else {
166: return valid;
167: }
168: }
169:
170: return false;
171: }
172:
173: public boolean isRegistrationRequired() {
174: return persistentRegistrationInfo != null
175: && persistentRegistrationInfo
176: .isRegistrationDeterminedRequired();
177: }
178:
179: public boolean isRegistrationChecked() {
180: return persistentRegistrationInfo != null
181: && persistentRegistrationInfo.isRegistrationRequired() != null;
182: }
183:
184: public boolean hasLocalRegistrationInfo() {
185: return persistentRegistrationInfo != null
186: && persistentRegistrationInfo.hasLocalInfo();
187: }
188:
189: /**
190: * Determines whether the associated consumer is active.
191: *
192: * @return
193: */
194: public boolean isActive() {
195: return persistentActive && persistentEndpointInfo.isAvailable();
196: }
197:
198: /**
199: * Activates or de-activate this Consumer. Note that this shouldn't be called directly as ConsumersRegistry will
200: * handle activation.
201: *
202: * @param active
203: */
204: public void setActive(boolean active) {
205: this .persistentActive = active;
206: }
207:
208: public void setActiveAndSave(boolean active) {
209: setActive(active);
210: registry.updateProducerInfo(this );
211: }
212:
213: public boolean isModifyRegistrationRequired() {
214: return isModifyRegistrationRequired
215: || (persistentRegistrationInfo != null && persistentRegistrationInfo
216: .isModified());
217: }
218:
219: CookieProtocol getRequiresInitCookie() {
220: return requiresInitCookie;
221: }
222:
223: /**
224: * Refreshes the producer's information from the service description if required.
225: *
226: * @param forceRefresh whether or not to force a refresh regardless of whether one would have been required based on
227: * cache expiration
228: * @return <code>true</code> if the producer's information was just refreshed, <code>false</code> otherwise
229: * @throws PortletInvokerException if registration was required but couldn't be achieved properly
230: */
231: public boolean refresh(boolean forceRefresh)
232: throws PortletInvokerException {
233: return detailedRefresh(forceRefresh).specificCode();
234: }
235:
236: public RefreshResult detailedRefresh(boolean forceRefresh)
237: throws PortletInvokerException {
238: RefreshResult result = internalRefresh(forceRefresh);
239:
240: // update DB
241: if (result.specificCode()) {
242: // mark as inactive if the refresh had issues...
243: if (result.hasIssues()) {
244: setActive(false);
245: } else {
246: // mark as active if it wasn't already
247: if (!isActive()) {
248: setActive(true);
249: }
250: }
251:
252: registry.updateProducerInfo(this );
253: }
254:
255: return result;
256: }
257:
258: private RefreshResult internalRefresh(boolean forceRefresh)
259: throws PortletInvokerException {
260: ServiceDescription serviceDescription;
261: // might neeed a different cache value: right now, we cache the whole producer info but we might want to cache
262: // POPs and rest of producer info separetely...
263: if (forceRefresh || isRefreshNeeded(true)) {
264: log.debug("Refreshing info for producer '" + getId() + "'");
265: RefreshResult result = new RefreshResult(true,
266: REFRESH_MEANING);
267: try {
268: persistentEndpointInfo.refresh();
269: } catch (InvokerUnavailableException e) {
270: result.appendToStatus(
271: "Couldn't refresh endpoint information: ")
272: .append(e.getLocalizedMessage());
273: }
274: // save changes to endpoint
275: registry.updateProducerInfo(this );
276:
277: boolean registeredSDSucceeded = true;
278: try {
279: // if we don't yet have registration information, get an unregistered service description
280: serviceDescription = getUnmanagedServiceDescription(persistentRegistrationInfo == null);
281: result.setServiceDescription(serviceDescription);
282: } catch (OperationFailedFault operationFailedFault) {
283: if (hasLocalRegistrationInfo()) {
284: log
285: .debug("OperationFailedFault occurred, might indicate a need to modify registration");
286: registeredSDSucceeded = false;
287: // attempt to get unregistered service description
288: serviceDescription = getServiceDescription(true);
289: result.setServiceDescription(serviceDescription);
290:
291: // validate the registration information
292: RefreshResult registrationResult = internalRefreshRegistration(
293: serviceDescription, false, true, true);
294: if (registrationResult.hasIssues()) {
295: isModifyRegistrationRequired = true;
296: setActiveAndSave(false);
297: }
298:
299: result.appendToStatus(registrationResult
300: .getStatus(), false);
301: result.setHasIssues(registrationResult.hasIssues());
302: return result;
303: } else {
304: serviceDescription = rethrowAsInvokerUnvailable(operationFailedFault);
305: }
306: }
307:
308: // do we need to call initCookie or not?
309: requiresInitCookie = serviceDescription
310: .getRequiresInitCookie();
311:
312: // do we need to register?
313: if (serviceDescription.isRequiresRegistration()) {
314: // refresh and force check for extra props if the registered SD failed
315: RefreshResult registrationResult = internalRefreshRegistration(
316: serviceDescription, true, forceRefresh,
317: !registeredSDSucceeded);
318: registry.updateProducerInfo(this );
319:
320: result.appendToStatus(registrationResult.getStatus());
321:
322: // attempt to register and determine if the current service description can be used to extract POPs
323: if (registeredSDSucceeded
324: && !registrationResult.hasIssues()) {
325: registrationResult = register(serviceDescription,
326: false);
327: if (registrationResult.specificCode()) {
328: // registration occurred, so we should ask for a new service description
329: serviceDescription = getServiceDescription(false);
330: }
331:
332: // extract the POPs
333: extractOfferedPortlets(serviceDescription);
334: }
335:
336: result.appendToStatus(registrationResult.getStatus());
337: result.setHasIssues(registrationResult.hasIssues());
338: result
339: .appendToStatus("Producer information successfully refreshed");
340:
341: return result;
342: } else {
343: log.debug("Registration not required");
344: persistentRegistrationInfo = new RegistrationInfo(this ,
345: false);
346: extractOfferedPortlets(serviceDescription);
347: return result;
348: }
349: }
350:
351: return new RefreshResult(false, REFRESH_MEANING);
352: }
353:
354: public String getId() {
355: return persistentId;
356: }
357:
358: public void setId(String id) {
359: this .persistentId = id;
360: }
361:
362: /**
363: * Extracts a map of offered Portlet objects from ServiceDescription
364: *
365: * @param sd
366: * @return a Map (portlet handle -> Portlet) of the offered portlets.
367: */
368: private Map extractOfferedPortlets(ServiceDescription sd) {
369: if (sd == null) {
370: throw new IllegalArgumentException(
371: "Provided ServiceDescription can't be null");
372: }
373:
374: PortletDescription[] portletDescriptions = sd
375: .getOfferedPortlets();
376:
377: if (portletDescriptions != null) {
378: int length = portletDescriptions.length;
379: log.debug("Extracting " + length + " portlets.");
380: popsMap = new LinkedHashMap<String, Portlet>(length);
381: portletGroups = new HashMap<String, Set<Portlet>>();
382:
383: for (int i = 0; i < length; i++) {
384: PortletDescription portletDescription = portletDescriptions[i];
385: WSRPPortlet wsrpPortlet = createWSRPPortletFromPortletDescription(portletDescription);
386:
387: if (wsrpPortlet != null) {
388: popsMap.put(wsrpPortlet.getContext().getId(),
389: wsrpPortlet);
390: }
391: }
392: } else {
393: popsMap = Collections.emptyMap();
394: portletGroups = Collections.emptyMap();
395: }
396:
397: //todo: could extract more information here... and rename method more appropriately
398: resetCacheTimerIfNeeded();
399:
400: return popsMap;
401: }
402:
403: /**
404: * @param portletDescription
405: * @return
406: * @since 2.6
407: */
408: WSRPPortlet createWSRPPortletFromPortletDescription(
409: PortletDescription portletDescription) {
410: ParameterValidation.throwIllegalArgExceptionIfNull(
411: portletDescription, "PortletDescription");
412: String portletHandle = portletDescription.getPortletHandle();
413: log
414: .debug("Extracting info for '" + portletHandle
415: + "' portlet");
416: WSRPPortletInfo info = new WSRPPortletInfo(portletDescription,
417: this );
418: WSRPPortlet wsrpPortlet = null;
419: if (info.isUsesMethodGet()) {
420: log
421: .warn("Portlet '"
422: + portletHandle
423: + "' uses the GET method in forms. Since we don't handle this, this portlet will be excluded from "
424: + "the list of offered portlets for producer "
425: + persistentId);
426: } else {
427: if (info.isHasUserSpecificState()) {
428: log
429: .debug("Portlet '"
430: + portletHandle
431: + "' will store persistent state for each user. NOT WELL TESTED!");
432: }
433:
434: wsrpPortlet = new WSRPPortlet(PortletContext
435: .createPortletContext(portletHandle), info);
436:
437: // add the portlet to the appropriate group if needed
438: String portletGroupId = portletDescription.getGroupID();
439: if (portletGroupId != null) {
440: Set<Portlet> groupedPortlets = portletGroups
441: .get(portletGroupId);
442: if (groupedPortlets == null) {
443: groupedPortlets = new HashSet<Portlet>();
444: portletGroups.put(portletGroupId, groupedPortlets);
445: }
446: groupedPortlets.add(wsrpPortlet);
447: }
448: }
449: return wsrpPortlet;
450: }
451:
452: public Portlet getPortlet(PortletContext portletContext)
453: throws PortletInvokerException {
454: String portletHandle = portletContext.getId();
455: ParameterValidation.throwIllegalArgExceptionIfNullOrEmpty(
456: portletHandle, "Portlet handle", "getPortlet");
457: log.debug("Retrieving portlet '" + portletHandle + "'");
458:
459: // check if we need to refresh
460: boolean justRefreshed = refresh(false);
461:
462: // First try caches if caches are still valid or we just refreshed
463: Portlet portlet = getPortletFromCaches(portletHandle,
464: justRefreshed);
465:
466: if (portlet != null) // we had a match in cache, return it
467: {
468: log.debug("Portlet was cached");
469: return portlet;
470: } else // otherwise, retrieve just the information for the appropriate portlet
471: {
472: log
473: .debug("Trying to retrieve portlet via getPortletDescription");
474:
475: GetPortletDescription gpd = WSRPTypeFactory
476: .createGetPortletDescription(
477: getRegistrationContext(), portletContext);
478: gpd.setUserContext(UserAccess.getUserContext());
479:
480: try {
481: PortletDescriptionResponse response = persistentEndpointInfo
482: .getPortletManagementService()
483: .getPortletDescription(gpd);
484: ParameterValidation.throwIllegalArgExceptionIfNull(
485: response, "PortletDescriptionResponse");
486: portlet = createWSRPPortletFromPortletDescription(response
487: .getPortletDescription());
488:
489: // add the portlet to the CCP cache
490: if (ccpsMap == null) {
491: ccpsMap = new HashMap<String, Portlet>();
492: }
493: ccpsMap.put(portletHandle, portlet);
494:
495: return portlet;
496: } catch (InvalidHandleFault invalidHandleFault) {
497: throw new NoSuchPortletException(invalidHandleFault,
498: portletHandle);
499: } catch (Exception e) {
500: log
501: .debug(
502: "Couldn't get portlet via getPortletDescription for producer '"
503: + persistentId
504: + "'. Attempting to retrieve it from the service description as this producer might not support the PortletManagement interface.",
505: e);
506:
507: justRefreshed = refresh(true);
508: portlet = getPortletFromCaches(portletHandle,
509: justRefreshed);
510:
511: if (portlet == null) {
512: throw new NoSuchPortletException(portletHandle);
513: } else {
514: return portlet;
515: }
516: }
517: }
518: }
519:
520: private Portlet getPortletFromCaches(String portletHandle,
521: boolean justRefreshed) {
522: Portlet portlet = null;
523:
524: if (justRefreshed || (useCache() && !isCacheExpired())) {
525: log.debug("Trying cached POPs");
526:
527: portlet = popsMap.get(portletHandle);
528:
529: if (portlet == null && ccpsMap != null) {
530: log.debug("Trying cached CCPs");
531: portlet = ccpsMap.get(portletHandle);
532: }
533: }
534: return portlet;
535: }
536:
537: public Map<String, Set<Portlet>> getPortletGroupMap()
538: throws PortletInvokerException {
539: refresh(false);
540: return portletGroups;
541: }
542:
543: public Map<String, Portlet> getPortletMap()
544: throws PortletInvokerException {
545: refresh(false);
546: return popsMap;
547: }
548:
549: // Cache support ****************************************************************************************************
550:
551: private boolean useCache() {
552: return persistentExpirationCacheSeconds != null
553: && persistentExpirationCacheSeconds > 0;
554: }
555:
556: private void resetCacheTimerIfNeeded() {
557: if (useCache()) {
558: // reset expiration time
559: expirationTimeMillis = System.currentTimeMillis()
560: + (persistentExpirationCacheSeconds * 1000);
561: }
562: }
563:
564: /**
565: * @return
566: * @since 2.6
567: */
568: private boolean isCacheExpired() {
569: boolean result = !useCache()
570: || System.currentTimeMillis() > expirationTimeMillis
571: || popsMap == null || portletGroups == null;
572: if (result) {
573: log.debug("Cache expired or not used");
574: }
575: return result;
576: }
577:
578: public Integer getExpirationCacheSeconds() {
579: return persistentExpirationCacheSeconds;
580: }
581:
582: public void setExpirationCacheSeconds(Integer expirationCacheSeconds) {
583: this .persistentExpirationCacheSeconds = expirationCacheSeconds;
584: }
585:
586: private ServiceDescription getUnmanagedServiceDescription(
587: boolean asUnregistered) throws PortletInvokerException,
588: OperationFailedFault {
589: GetServiceDescription request = getServiceDescriptionRequest(asUnregistered);
590:
591: ServiceDescription serviceDescription;
592: try {
593: serviceDescription = persistentEndpointInfo
594: .getServiceDescriptionService()
595: .getServiceDescription(request);
596:
597: if (serviceDescription != null) {
598: return serviceDescription;
599: } else {
600: // todo: do something better
601: throw new NullPointerException(
602: "null service description: deal with it!");
603: }
604: } catch (Exception e) {
605: log
606: .debug(
607: "Caught Exception in getServiceDescription:\n",
608: e);
609:
610: // de-activate
611: setActiveAndSave(false);
612:
613: if (e instanceof InvalidRegistrationFault) {
614: resetRegistration();
615: } else if (e instanceof OperationFailedFault) {
616: throw (OperationFailedFault) e; // rethrow to deal at higher level as meaning can vary depending on context
617: }
618:
619: return rethrowAsInvokerUnvailable(e);
620: }
621: }
622:
623: ServiceDescription getServiceDescription(boolean asUnregistered)
624: throws PortletInvokerException {
625: try {
626: return getUnmanagedServiceDescription(asUnregistered);
627: } catch (OperationFailedFault operationFailedFault) {
628: return rethrowAsInvokerUnvailable(operationFailedFault);
629: }
630: }
631:
632: private ServiceDescription rethrowAsInvokerUnvailable(Exception e)
633: throws InvokerUnavailableException {
634: Throwable cause = e.getCause();
635: throw new InvokerUnavailableException(
636: "Problem getting service description for producer "
637: + persistentId
638: + ", please see the logs for more information.",
639: cause == null ? e : cause);
640: }
641:
642: private GetServiceDescription getServiceDescriptionRequest(
643: boolean asUnregistred) throws PortletInvokerException {
644: //todo: might need to implement customization of default service description
645: GetServiceDescription gsd = WSRPTypeFactory
646: .createGetServiceDescription();
647:
648: gsd.setDesiredLocales(WSRPConstants.DEFAULT_LOCALES);
649: if (asUnregistred) {
650: return gsd;
651: } else {
652: gsd.setRegistrationContext(getRegistrationContext());
653: return gsd;
654: }
655: }
656:
657: public RegistrationContext getRegistrationContext()
658: throws PortletInvokerException {
659: if (persistentRegistrationInfo == null) {
660: refresh(false);
661: }
662:
663: return persistentRegistrationInfo.getRegistrationContext();
664: }
665:
666: public void resetRegistration() throws PortletInvokerException {
667: if (persistentRegistrationInfo != null) {
668: persistentRegistrationInfo.resetRegistration();
669: }
670:
671: refresh(true);
672: }
673:
674: // make package only after package reorg
675: public PortletPropertyDescriptionResponse getPropertyDescriptionsFor(
676: String portletHandle) {
677: ParameterValidation.throwIllegalArgExceptionIfNullOrEmpty(
678: portletHandle, "portlet handle", null);
679: try {
680: WSRP_v1_PortletManagement_PortType service = getEndpointConfigurationInfo()
681: .getPortletManagementService();
682:
683: GetPortletPropertyDescription request = WSRPTypeFactory
684: .createSimpleGetPortletPropertyDescription(portletHandle);
685: request.setRegistrationContext(getRegistrationContext());
686: request.setUserContext(UserAccess.getUserContext());
687:
688: return service.getPortletPropertyDescription(request);
689: } catch (InvalidHandleFault invalidHandleFault) {
690: throw new IllegalArgumentException("Unknown portlet '"
691: + portletHandle + "'");
692: } catch (InvalidRegistrationFault invalidRegistrationFault) {
693: try {
694: resetRegistration();
695: } catch (PortletInvokerException e) {
696: throw new RuntimeException(
697: "Couldn't reset registration", e);
698: }
699: throw new IllegalArgumentException(
700: "Couldn't get property descriptions for portlet '"
701: + portletHandle
702: + "' because the provided registration is invalid!");
703: } catch (Exception e) {
704: // if we receive an exception that we cannot handle, since the support for PortletManagement is optional,
705: // just return null as if the portlet had no properties
706: log.debug(
707: "Couldn't get property descriptions for portlet '"
708: + portletHandle + "'", e);
709: return null;
710: }
711: }
712:
713: public void register() throws PortletInvokerException {
714: register(null, false);
715: }
716:
717: /**
718: * Attempts to register with the producer.
719: *
720: * @param serviceDescription
721: * @param forceRefresh
722: * @return <code>true</code> if the client code should ask for a new service description, <code>false</code> if the
723: * specified description is good to be further processed
724: * @throws PortletInvokerException
725: * @since 2.6
726: */
727: private RefreshResult register(
728: ServiceDescription serviceDescription, boolean forceRefresh)
729: throws PortletInvokerException {
730: if (persistentRegistrationInfo == null) {
731: persistentRegistrationInfo = new RegistrationInfo(this );
732: }
733:
734: if (!isRegistered()) {
735: persistentEndpointInfo.refresh();
736:
737: if (serviceDescription == null) {
738: serviceDescription = getServiceDescription(false);
739: }
740:
741: if (serviceDescription.isRequiresRegistration()) {
742: // check if the configured registration information is correct and if we can get the service description
743: RefreshResult result = persistentRegistrationInfo
744: .refresh(serviceDescription, persistentId,
745: true, forceRefresh, false);
746: if (!result.hasIssues()) {
747: try {
748: log.debug("Attempting registration");
749: RegistrationContext registrationContext = persistentEndpointInfo
750: .getRegistrationService().register(
751: persistentRegistrationInfo
752: .getRegistrationData());
753:
754: if (registrationContext == null) {
755: setActive(false);
756: throw new PortletInvokerException(
757: "Received null response after registration from producer '"
758: + persistentId + "'");
759: }
760:
761: persistentRegistrationInfo
762: .setRegistrationContext(registrationContext);
763: String msg = "Consumer with id '"
764: + persistentId
765: + "' successfully registered with handle: '"
766: + registrationContext
767: .getRegistrationHandle() + "'";
768: log.debug(msg);
769: result.appendToStatus(msg);
770: return new RefreshResult(result, true,
771: REGISTER_MEANING);
772: } catch (Exception e) {
773: persistentRegistrationInfo.resetRegistration();
774: setActive(false);
775: throw new PortletInvokerException(
776: "Couldn't register with producer '"
777: + persistentId + "'", e);
778: } finally {
779: registry.updateProducerInfo(this );
780: }
781: } else {
782: log.debug(result.getStatus());
783: setActiveAndSave(false);
784: throw new PortletInvokerException(
785: "Consumer is not ready to be registered with producer because of missing or invalid registration information.");
786: }
787: }
788: }
789:
790: return new RefreshResult(false, REGISTER_MEANING);
791: }
792:
793: public void deregister() throws PortletInvokerException {
794: if (isRegistered()) {
795: persistentEndpointInfo.refresh();
796:
797: try {
798: persistentEndpointInfo.getRegistrationService()
799: .deregister(getRegistrationContext());
800: persistentRegistrationInfo.resetRegistration();
801: log.info("Consumer with id '" + persistentId
802: + "' deregistered.");
803:
804: invalidateCache();
805: } catch (Exception e) {
806: throw new PortletInvokerException(
807: "Couldn't deregister with producer '"
808: + persistentId + "'", e);
809: } finally {
810: registry.updateProducerInfo(this );
811: }
812: } else {
813: throw new IllegalStateException(
814: "Cannot deregister producer '" + persistentId
815: + "' as it's not registered");
816: }
817:
818: }
819:
820: public void modifyRegistration() throws PortletInvokerException {
821: if (persistentRegistrationInfo != null
822: && persistentRegistrationInfo.getRegistrationHandle() != null) {
823: persistentEndpointInfo.refresh();
824:
825: try {
826: RegistrationContext registrationContext = getRegistrationContext();
827: ModifyRegistration modifyRegistration = WSRPTypeFactory
828: .createModifyRegistration(registrationContext,
829: persistentRegistrationInfo
830: .getRegistrationData());
831: RegistrationState state = persistentEndpointInfo
832: .getRegistrationService().modifyRegistration(
833: modifyRegistration);
834:
835: // force refresh of internal RegistrationInfo state
836: persistentRegistrationInfo
837: .setRegistrationValidInternalState();
838:
839: // registration is not modified anymore :)
840: isModifyRegistrationRequired = false;
841:
842: if (state != null) {
843: persistentRegistrationInfo
844: .setRegistrationState(state
845: .getRegistrationState());
846: }
847: log.info("Consumer with id '" + persistentId
848: + "' sucessfully modified its registration.");
849:
850: // reset cache to be able to see new offered portlets on the next refresh
851: invalidateCache();
852: } catch (Exception e) {
853: throw new PortletInvokerException(
854: "Couldn't modify registration with producer '"
855: + persistentId + "'", e);
856: } finally {
857: registry.updateProducerInfo(this );
858: }
859: } else {
860: throw new IllegalStateException(
861: "Cannot modify registration for producer '"
862: + persistentId + "' as it's not registered");
863: }
864: }
865:
866: private void invalidateCache() {
867: if (useCache()) {
868: expirationTimeMillis = System.currentTimeMillis();
869: }
870: }
871:
872: private RefreshResult internalRefreshRegistration(
873: ServiceDescription serviceDescription,
874: boolean mergeWithLocalInfo, boolean forceRefresh,
875: boolean forceCheckOfExtraProps)
876: throws PortletInvokerException {
877: if (persistentRegistrationInfo == null) {
878: persistentRegistrationInfo = new RegistrationInfo(this );
879: }
880:
881: RefreshResult result = persistentRegistrationInfo.refresh(
882: serviceDescription, persistentId, mergeWithLocalInfo,
883: forceRefresh, forceCheckOfExtraProps);
884:
885: log
886: .debug("Refreshed registration information for consumer with id '"
887: + persistentId + "'");
888:
889: return result;
890: }
891:
892: public boolean isRefreshNeeded(boolean considerCache) {
893: boolean result = (considerCache && isCacheExpired())
894: || persistentRegistrationInfo == null
895: || persistentRegistrationInfo.isRefreshNeeded()
896: || persistentEndpointInfo.isRefreshNeeded();
897: if (result) {
898: log.debug("Refresh needed for producer '" + persistentId
899: + "'");
900: }
901: return result;
902: }
903:
904: void removeHandleFromCaches(String portletHandle) {
905: log.debug("Removing '" + portletHandle + "' from caches.");
906: ccpsMap.remove(portletHandle);
907: popsMap.remove(portletHandle);
908: }
909:
910: public void eraseRegistrationInfo() {
911: persistentRegistrationInfo = null;
912:
913: registry.updateProducerInfo(this);
914:
915: log.warn(ERASED_LOCAL_REGISTRATION_INFORMATION);
916: log.debug(ERASED_LOCAL_REGISTRATION_INFORMATION);
917: }
918: }
|