/*
* 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.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.enterprise.inject.spi.AnnotatedParameter;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.inject.Qualifier;
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.solder.bean.ImmutableInjectionPoint;
/**
* JMS Event Bridge Routing
*
* @author Jordan Ganoff
*/
public class RouteImpl implements Route {
private RouteType type;
private String id;
private Type payloadType;
private Set<Annotation> qualifiers;
private Set<Destination> destinations;
private List<Set<Annotation>> destinationQualifiers;
private Set<String> destinationJndiNames;
private Set<AnnotatedParameter<?>> annotatedParameters;
private Logger logger;
public RouteImpl(RouteType type, Type payloadType) {
this(type);
this.payloadType = payloadType;
}
public RouteImpl(RouteType type) {
logger = Logger.getLogger(RouteImpl.class);
this.type = type;
this.enableEgress();
this.enableIngress();
qualifiers = new HashSet<Annotation>();
destinations = new HashSet<Destination>();
destinationQualifiers = new ArrayList<Set<Annotation>>();
destinationJndiNames = new HashSet<String>();
annotatedParameters = new HashSet<AnnotatedParameter<?>>();
}
public Route addQualifiers(Collection<Annotation> q) {
if (q != null) {
for (Annotation qualifier : q) {
if (!qualifier.annotationType().isAnnotationPresent(Qualifier.class)) {
throw new IllegalArgumentException("not a qualifier: " + qualifier);
}
qualifiers.add(qualifier);
}
}
return this;
}
public Route addQualifiers(Annotation... q) {
return addQualifiers(Arrays.asList(q));
}
public Route addDestinations(Destination... d) {
return addDestinations(Arrays.asList(d));
}
public Route addDestinations(Collection<Destination> d) {
this.destinations.addAll(d);
return this;
}
public <D extends Destination> Route connectTo(java.lang.Class<D> d, D destination) {
destinations.add(Destination.class.cast(destination));
return this;
}
public Route addDestinationQualifiers(Set<Annotation> qualifiers) {
this.destinationQualifiers.add(qualifiers);
return this;
}
public Route addDestinationJndiName(String jndi) {
this.destinationJndiNames.add(jndi);
return this;
}
public RouteType getType() {
return type;
}
public Type getPayloadType() {
return payloadType;
}
public Set<Annotation> getQualifiers() {
return qualifiers;
}
public Set<? extends Destination> getDestinations() {
return destinations;
}
public Set<String> getDestinationJndiNames() {
return destinationJndiNames;
}
public List<Set<Annotation>> getDestinationQualifiers() {
return destinationQualifiers;
}
public Route addAnnotatedParameter(AnnotatedParameter<?> ap) {
this.annotatedParameters.add(ap);
return this;
}
private boolean built = false;
private BeanManager bm;
public void build(BeanManager beanManager) {
if (!built) {
this.bm = beanManager;
loadDestinations();
this.built = true;
}
}
private void loadDestinations() {
Set<Destination> destinations = new HashSet<Destination>();
destinations.addAll(getDestinations());
for (String dest : getDestinationJndiNames()) {
Destination destination = lookupDestination(dest);
destinations.add(destination);
}
for (AnnotatedParameter<?> ap : getAnnotatedParameters()) {
Destination destination = lookupDestination(ap);
destinations.add(destination);
}
logger.infof("Routing destinations: [%s]", destinations);
setDestinations(destinations);
}
private Destination lookupDestination(String jndiName) {
try {
Context c = new InitialContext();
return (Destination) c.lookup(jndiName);
} catch (NamingException e) {
logger.warn("Unable to lookup " + jndiName, e);
}
return null;
}
private Destination lookupDestination(AnnotatedParameter<?> ap) {
logger.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;
}
public Set<AnnotatedParameter<?>> getAnnotatedParameters() {
return this.annotatedParameters;
}
@Override
public Route setType(Type type) {
this.payloadType = type;
return this;
}
public boolean validate() {
if (this.payloadType == null) {
logger.debug("No payload type found.");
return false;
}
if (this.annotatedParameters.isEmpty() && this.destinationJndiNames.isEmpty() && this.destinations.isEmpty()) {
logger.debug("No destinations configured.");
return false;
}
return true;
}
public void setDestinations(Collection<Destination> destinations) {
this.destinations = new HashSet<Destination>(destinations);
}
@Override
public Route id(String id) {
this.id = id;
return this;
}
@Override
public String getId() {
return this.id;
}
private boolean egressEnabled = false;
private boolean ingressEnabled = false;
@Override
public boolean isEgressEnabled() {
return egressEnabled;
}
@Override
public boolean isIngressEnabled() {
return ingressEnabled;
}
@Override
public void disableEgress() {
this.egressEnabled = false;
}
@Override
public void enableEgress() {
if (this.type == RouteType.BOTH || this.type == RouteType.EGRESS) {
this.egressEnabled = true;
} else {
this.egressEnabled = false;
}
}
@Override
public void disableIngress() {
this.ingressEnabled = false;
}
@Override
public void enableIngress() {
if (this.type == RouteType.BOTH || this.type == RouteType.INGRESS) {
this.ingressEnabled = true;
} else {
this.ingressEnabled = false;
}
}
}