/* * JBoss, Home of Professional Open Source * Copyright 2011, Red Hat, Inc. and/or its affiliates, and individual * contributors by the @authors tag. See the copyright.txt in the * distribution for a full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.seam.jms.bridge; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.enterprise.event.Reception; import javax.enterprise.event.TransactionPhase; import javax.enterprise.inject.spi.AnnotatedParameter; import javax.enterprise.inject.spi.Bean; import javax.enterprise.inject.spi.BeanManager; import javax.enterprise.inject.spi.ObserverMethod; import javax.jms.Destination; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import org.jboss.solder.logging.Logger; import org.jboss.seam.jms.MessageManager; import org.jboss.seam.jms.Seam3JmsExtension; import org.jboss.seam.jms.annotations.OutboundLiteral; import org.jboss.solder.bean.ImmutableInjectionPoint; import org.jboss.solder.core.Veto; import static org.jboss.seam.jms.annotations.RoutingLiteral.EGRESS; /** * Forwards CDI events that match the provided {@link Route} configuration to * the configured destinations. * * @author Jordan Ganoff */ @Veto public class EgressRoutingObserver implements ObserverMethod<Object> { private Logger log; private BeanManager bm; private Route route; private Seam3JmsExtension extension; public EgressRoutingObserver(BeanManager bm, Route routing, Seam3JmsExtension extension) { this(routing, extension); this.bm = bm; } public EgressRoutingObserver(Route route, Seam3JmsExtension extension) { this.route = route; this.extension = extension; this.log = Logger.getLogger(EgressRoutingObserver.class); } public void setBeanManager(BeanManager beanManager) { this.bm = beanManager; this.loadDestinations(); } public Class<?> getBeanClass() { return getClass(); } public Set<Annotation> getObservedQualifiers() { Set<Annotation> as = new HashSet<Annotation>(); as.addAll(route.getQualifiers()); as.add(EGRESS); as.add(OutboundLiteral.INSTANCE); log.debugf("Inidicating that I observe these qualifiers: [%s]", as); return route.getQualifiers(); } public Type getObservedType() { return route.getPayloadType(); } public Reception getReception() { return Reception.ALWAYS; } public TransactionPhase getTransactionPhase() { return TransactionPhase.AFTER_SUCCESS; } public void notify(Object evt) { // FIXME Include qualifiers once CDI 1.0 MR is complete and // notify(Event, Set<Annotation>) is added log.debugf("Notified of an event: %s", evt); if (this.extension.isReadyToRoute()) forwardEvent(evt); else { this.log.warn("Adding event to evt cache " + evt); evtCache.add(evt); } } private List<Object> evtCache = new ArrayList<Object>(); private MessageManager getMessageBuilder() { Set<Bean<?>> beans = bm.getBeans(MessageManager.class); Bean<?> bean = bm.resolve(beans); MessageManager mb = (MessageManager) bm.getReference(bean, MessageManager.class, bm.createCreationalContext(bean)); return mb; } private void loadDestinations() { Set<Destination> destinations = new HashSet<Destination>(); destinations.addAll(route.getDestinations()); for (String dest : route.getDestinationJndiNames()) { Destination destination = lookupDestination(dest); destinations.add(destination); } for (AnnotatedParameter<?> ap : route.getAnnotatedParameters()) { Destination destination = lookupDestination(ap); destinations.add(destination); } log.infof("Routing destinations: [%s]", destinations); this.route.setDestinations(destinations); } private Destination lookupDestination(String jndiName) { try { Context c = new InitialContext(); return (Destination) c.lookup(jndiName); } catch (NamingException e) { log.warn("Unable to lookup " + jndiName, e); } return null; } private Destination lookupDestination(AnnotatedParameter<?> ap) { log.debug("Looking up destination: " + ap); Set<Bean<?>> beans = bm.getBeans(Destination.class); Bean<?> bean = bm.resolve(beans); ImmutableInjectionPoint iip = new ImmutableInjectionPoint(ap, bm, bean, false, false); Object o = bm.getInjectableReference(iip, bm.createCreationalContext(bean)); return (Destination) o; } private void forwardEvent(Object event) { if (!this.route.isEgressEnabled()) return; MessageManager msgBuilder = this.getMessageBuilder(); if (event instanceof String) { msgBuilder.sendTextToDestinations(event.toString(), route.getDestinations().toArray(new Destination[]{})); } else { msgBuilder.sendObjectToDestinations(event, route.getDestinations().toArray(new Destination[]{})); } } }