001: /******************************************************************************
002: * JBoss, a division of Red Hat *
003: * Copyright 2006, 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.hibernate.HibernateException;
025: import org.hibernate.Session;
026: import org.hibernate.SessionFactory;
027: import org.jboss.portal.common.util.ParameterValidation;
028: import org.jboss.portal.core.event.PortalEventListenerRegistry;
029: import org.jboss.portal.jems.as.system.AbstractJBossService;
030: import org.jboss.portal.portlet.PortletInvoker;
031: import org.jboss.portal.portlet.PortletInvokerException;
032: import org.jboss.portal.portlet.federation.FederatedPortletInvoker;
033: import org.jboss.portal.portlet.federation.FederatingPortletInvoker;
034: import org.jboss.portal.wsrp.WSRPConsumer;
035:
036: import javax.naming.InitialContext;
037: import java.util.Collection;
038: import java.util.Collections;
039: import java.util.Iterator;
040: import java.util.SortedMap;
041: import java.util.TreeMap;
042:
043: /**
044: * @author <a href="mailto:chris.laprun@jboss.com">Chris Laprun</a>
045: * @version $Revision: 9864 $
046: * @since 2.6
047: */
048: public class ConsumerRegistryService extends AbstractJBossService
049: implements ConsumerRegistry {
050: /** Gives access to the Portal's portlet invokers */
051: private FederatingPortletInvoker federatingPortletInvoker;
052:
053: private SortedMap<String, WSRPConsumer> consumers;
054:
055: private SessionFactory sessionFactory;
056:
057: private String sessionFactoryJNDIName;
058:
059: private PortalEventListenerRegistry portalEventListenerRegistry;
060:
061: private static final String CONSUMER_WITH_ID = "Consumer with id '";
062: private static final String RELEASE_SESSIONS_LISTENER = "release_sessions_listener_";
063:
064: public FederatingPortletInvoker getFederatingPortletInvoker() {
065: return federatingPortletInvoker;
066: }
067:
068: public void setPortalEventListenerRegistry(
069: PortalEventListenerRegistry portalEventListenerRegistry) {
070: this .portalEventListenerRegistry = portalEventListenerRegistry;
071: }
072:
073: public WSRPConsumer createConsumer(String id,
074: Integer expirationCacheSeconds) {
075: ParameterValidation.throwIllegalArgExceptionIfNullOrEmpty(id,
076: "Consumer identifier", "Creating a Consumer");
077:
078: if (getConsumer(id) != null) {
079: throw new ConsumerException(CONSUMER_WITH_ID + id
080: + "' already exists!");
081: }
082:
083: ProducerInfo info = new ProducerInfo();
084: info.setId(id);
085: info.setRegistry(this );
086: info.setExpirationCacheSeconds(expirationCacheSeconds);
087:
088: try {
089: Session session = sessionFactory.getCurrentSession();
090:
091: session.persist(info);
092: } catch (HibernateException e) {
093: throw new ConsumerException("Couldn't create Consumer '"
094: + id + "'", e);
095: }
096:
097: log.info(CONSUMER_WITH_ID + id + "' created");
098: return createConsumerFrom(info);
099: }
100:
101: public void destroyConsumer(String id) {
102: ParameterValidation.throwIllegalArgExceptionIfNullOrEmpty(id,
103: "Consumer identifier", "Destroying a Consumer");
104:
105: WSRPConsumer consumer = getConsumer(id);
106: if (consumer != null) {
107: ProducerInfo info = consumer.getProducerInfo();
108:
109: try {
110: consumer.releaseSessions();
111: } catch (PortletInvokerException e) {
112: log
113: .debug("releaseSessions failed when attempting to destroy "
114: + CONSUMER_WITH_ID + id + "'");
115: }
116:
117: // if the consumer is registered, deregister it
118: if (info.isRegistered()) {
119: registerOrDeregisterConsumerWith(id, false);
120: }
121:
122: deactivateConsumerWith(id);
123: consumers.remove(id);
124:
125: Session session = sessionFactory.getCurrentSession();
126:
127: session.delete(info);
128: } else {
129: throw new ConsumerException(CONSUMER_WITH_ID + id
130: + "' doesn't exist!");
131: }
132:
133: log.info(CONSUMER_WITH_ID + id + "' destroyed");
134: }
135:
136: public void persistConsumer(WSRPConsumer consumer) {
137: ParameterValidation.throwIllegalArgExceptionIfNull(consumer,
138: "Consumer");
139:
140: ProducerInfo info = consumer.getProducerInfo();
141:
142: try {
143: Session session = sessionFactory.getCurrentSession();
144: session.persist(info);
145: } catch (HibernateException e) {
146: throw new ConsumerException(CONSUMER_WITH_ID + info.getId()
147: + "' couldn't be persisted!");
148: }
149:
150: createConsumerFrom(info);
151: }
152:
153: public void setFederatingPortletInvoker(
154: FederatingPortletInvoker federatingPortletInvoker) {
155: this .federatingPortletInvoker = federatingPortletInvoker;
156: }
157:
158: public String getSessionFactoryJNDIName() {
159: return sessionFactoryJNDIName;
160: }
161:
162: public void setSessionFactoryJNDIName(String sessionFactoryJNDIName) {
163: this .sessionFactoryJNDIName = sessionFactoryJNDIName;
164: }
165:
166: private WSRPConsumer createConsumerFrom(ProducerInfo producerInfo) {
167: WSRPConsumer consumer = new WSRPConsumerImpl(producerInfo);
168: consumers.put(producerInfo.getId(), consumer);
169:
170: return consumer;
171: }
172:
173: public void activateConsumerWith(String id)
174: throws ConsumerException {
175: ParameterValidation.throwIllegalArgExceptionIfNullOrEmpty(id,
176: "Consumer identifier", "Activating a Consumer");
177:
178: // if the consumer associated with the given id is already registered, don't do anything
179: if (federatingPortletInvoker.getFederatedInvoker(id) == null) {
180: startOrStopConsumer(id, true);
181: } else {
182: // todo: fix-me federated portlet invoker gets desynchronized...
183: WSRPConsumer consumer = getConsumer(id);
184: if (consumer != null && !consumer.isActive()) {
185: federatingPortletInvoker.unregisterInvoker(id);
186: startOrStopConsumer(id, true);
187: }
188: }
189: }
190:
191: public void deactivateConsumerWith(String id)
192: throws ConsumerException {
193: ParameterValidation.throwIllegalArgExceptionIfNullOrEmpty(id,
194: "Consumer identifier", "Deactivating a Consumer");
195:
196: // only process if there is a registered Consumer with the specified id
197: if (federatingPortletInvoker.getFederatedInvoker(id) != null) {
198: startOrStopConsumer(id, false);
199: } else {
200: // todo: fix-me federated portlet invoker gets desynchronized...
201: WSRPConsumer consumer = getConsumer(id);
202: if (consumer != null && consumer.isActive()) {
203: federatingPortletInvoker.registerInvoker(id, consumer);
204: startOrStopConsumer(id, false);
205: }
206: }
207: }
208:
209: public void updateProducerInfo(ProducerInfo producerInfo) {
210: ParameterValidation.throwIllegalArgExceptionIfNull(
211: producerInfo, "ProducerInfo");
212:
213: Session session = sessionFactory.getCurrentSession();
214: try {
215:
216: // Retrieve the previous id of the given ProducerInfo to update local consumers map if needed
217: String oldId = (String) session
218: .createQuery(
219: "select pi.persistentId from ProducerInfo pi where pi.id = :key")
220: .setParameter("key", producerInfo.getKey())
221: .uniqueResult();
222: if (producerInfo.getId().equals(oldId)) {
223: oldId = null; // reset oldId as the ProducerInfo's id hasn't been modified
224: }
225:
226: // merge old producer info with new data
227: session.update(producerInfo);
228:
229: // if we updated and oldId is not null, we need to update the local consumers map
230: if (oldId != null) {
231: WSRPConsumer consumer = consumers.remove(oldId);
232: consumers.put(producerInfo.getId(), consumer);
233: }
234: } catch (HibernateException e) {
235: throw new ConsumerException(
236: "Couldn't update ProducerInfo for Consumer '"
237: + producerInfo.getId() + "'", e);
238: }
239: }
240:
241: protected void startService() throws Exception {
242: InitialContext initialContext = new InitialContext();
243: sessionFactory = (SessionFactory) initialContext
244: .lookup(sessionFactoryJNDIName);
245:
246: // load the configured consumers
247: consumers = new TreeMap<String, WSRPConsumer>();
248:
249: Session session = sessionFactory.getCurrentSession();
250:
251: Iterator producerInfos = session.createQuery(
252: "from ProducerInfo pi order by pi.persistentId")
253: .iterate();
254:
255: // load the configured producers
256: ProducerInfo producerInfo;
257: while (producerInfos.hasNext()) {
258: producerInfo = (ProducerInfo) producerInfos.next();
259:
260: // need to set the registry after loading from DB since registry is not persisted.
261: producerInfo.setRegistry(this );
262:
263: createConsumerFrom(producerInfo);
264:
265: try {
266: // if the producer is marked as active, activate it fo' real! :)
267: if (producerInfo.isActive()) {
268: activateConsumerWith(producerInfo.getId());
269: }
270: } catch (Exception e) {
271: producerInfo.setActive(false);
272: updateProducerInfo(producerInfo);
273: }
274:
275: }
276: }
277:
278: protected void stopService() throws Exception {
279: sessionFactory = null;
280:
281: for (WSRPConsumer consumer : consumers.values()) {
282: // if producer is not active, it shouldn't be registered with the federating portlet invoker, hence do not
283: // unregister it.
284: if (consumer.getProducerInfo().isActive()) {
285: federatingPortletInvoker.unregisterInvoker(consumer
286: .getProducerId());
287: }
288:
289: try {
290: consumer.stop();
291: } catch (Exception e) {
292: // ignore and continue
293: }
294: }
295:
296: consumers.clear();
297: consumers = null;
298: }
299:
300: public Collection getConfiguredConsumers() {
301: return Collections.unmodifiableCollection(consumers.values());
302: }
303:
304: public WSRPConsumer getConsumer(String id) {
305: ParameterValidation.throwIllegalArgExceptionIfNullOrEmpty(id,
306: "consumer id", null);
307: return consumers.get(id);
308: }
309:
310: public void registerOrDeregisterConsumerWith(String id,
311: boolean register) {
312: ParameterValidation.throwIllegalArgExceptionIfNullOrEmpty(id,
313: "Consumer identifier",
314: "Registering or deregistering a Consumer");
315:
316: WSRPConsumer consumer = getConsumer(id);
317:
318: if (consumer == null) {
319: throw new ConsumerException(CONSUMER_WITH_ID + id
320: + "' doesn't exist!");
321: }
322:
323: try {
324: if (register) {
325: consumer.getProducerInfo().register();
326: } else {
327: consumer.getProducerInfo().deregister();
328: }
329: } catch (Exception e) {
330: // unexpected exception: deactivate the consumer
331: deactivateConsumerWith(id);
332: Throwable cause = e.getCause();
333: throw new ConsumerException("Couldn't "
334: + (register ? "register" : "deregister")
335: + CONSUMER_WITH_ID + id + "'",
336: cause != null ? cause : e);
337: }
338: }
339:
340: private void startOrStopConsumer(String id, boolean start) {
341: WSRPConsumer consumer;
342:
343: try {
344: if (start) {
345: consumer = getConsumer(id);
346:
347: if (consumer == null) {
348: throw new IllegalArgumentException(CONSUMER_WITH_ID
349: + id + "' doesn't exist!");
350: }
351:
352: consumer.activate();
353: federatingPortletInvoker.registerInvoker(id, consumer);
354: portalEventListenerRegistry.registerListener(
355: getListenerIdFrom(id), consumer);
356: } else {
357: FederatedPortletInvoker fedInvoker = federatingPortletInvoker
358: .getFederatedInvoker(id);
359: if (fedInvoker != null) {
360: PortletInvoker invoker = fedInvoker
361: .getPortletInvoker();
362: if (invoker instanceof WSRPConsumer) {
363: consumer = (WSRPConsumer) invoker;
364: consumer.deactivate();
365: federatingPortletInvoker.unregisterInvoker(id);
366: portalEventListenerRegistry
367: .unregisterListener(getListenerIdFrom(id));
368: } else {
369: throw new IllegalArgumentException(
370: "PortletInvoker with id '" + id
371: + "' is not a WSRPConsumer!");
372: }
373: } else {
374: throw new IllegalArgumentException(
375: "There is no registered PortletInvoker with id '"
376: + id + "'");
377: }
378: }
379: } catch (Exception e) {
380: throw new ConsumerException("Couldn't "
381: + (start ? "start" : "stop")
382: + " Consumer service '" + id + "'", e);
383: }
384:
385: // update ProducerInfo
386: updateProducerInfo(consumer.getProducerInfo());
387: }
388:
389: private String getListenerIdFrom(String id) {
390: return RELEASE_SESSIONS_LISTENER + id;
391: }
392: }
|