/* * Copyright 2012 Red Hat, Inc. and/or its affiliates. * * Licensed under the Eclipse Public License version 1.0, available at * http://www.eclipse.org/legal/epl-v10.html */ package org.jboss.forge.furnace.container.cdi.services; import java.util.concurrent.Callable; import javax.enterprise.context.spi.CreationalContext; import javax.enterprise.inject.spi.Bean; import javax.enterprise.inject.spi.BeanManager; import javax.enterprise.inject.spi.InjectionPoint; import org.jboss.forge.furnace.addons.Addon; import org.jboss.forge.furnace.container.cdi.impl.WeldServiceRegistry; import org.jboss.forge.furnace.exception.ContainerException; import org.jboss.forge.furnace.proxy.ClassLoaderInterceptor; import org.jboss.forge.furnace.proxy.Proxies; import org.jboss.forge.furnace.spi.ExportedInstance; import org.jboss.forge.furnace.util.Assert; import org.jboss.forge.furnace.util.ClassLoaders; /** * @author <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a> */ public class ExportedInstanceImpl<R> implements ExportedInstance<R> { private final Addon addon; private final BeanManager manager; private CreationalContext<R> context; private final Bean<R> requestedBean; private final Class<R> requestedType; private final Class<? extends R> actualType; public ExportedInstanceImpl(Addon addon, BeanManager manager, Bean<R> requestedBean, Class<R> requestedType, Class<? extends R> actualType) { Assert.notNull(addon, "Source addon must not be null."); Assert.notNull(manager, "Bean manager must not be null."); Assert.notNull(requestedBean, "Requested bean must not be null."); Assert.notNull(requestedType, "Requested type must not be null."); Assert.notNull(actualType, "Actual type must not be null."); this.addon = addon; this.manager = manager; this.requestedBean = requestedBean; this.requestedType = requestedType; this.actualType = actualType; } @Override @SuppressWarnings("unchecked") public R get() { Callable<Object> task = new Callable<Object>() { @Override public Object call() throws Exception { context = manager.createCreationalContext(requestedBean); Object delegate = manager.getReference(requestedBean, actualType, context); return Proxies.enhance(addon.getClassLoader(), delegate, new ClassLoaderInterceptor(addon.getClassLoader(), delegate)); } }; try { return (R) ClassLoaders.executeIn(addon.getClassLoader(), task); } catch (Exception e) { throw new ContainerException("Failed to get instance of [" + actualType + "] with proxy for ClassLoader [" + addon.getClassLoader() + "]", e); } } @Override public Class<? extends R> getActualType() { return actualType; } @Override public Addon getSourceAddon() { return addon; } @SuppressWarnings("unchecked") public Object get(final InjectionPoint injectionPoint) { // FIXME remove the need for this method (which is currently still not working right for producer methods that // require an InjectionPoint Callable<Object> task = new Callable<Object>() { @Override public Object call() throws Exception { Bean<R> bean = (Bean<R>) manager.resolve(manager.getBeans(actualType, WeldServiceRegistry.getQualifiersFrom(actualType))); context = manager.createCreationalContext(bean); Object delegate = manager.getInjectableReference(injectionPoint, context); return Proxies.enhance(addon.getClassLoader(), delegate, new ClassLoaderInterceptor(addon.getClassLoader(), delegate)); } }; try { return ClassLoaders.executeIn(addon.getClassLoader(), task); } catch (Exception e) { throw new ContainerException("Failed to get instance of [" + actualType + "] from addon [" + addon + "]", e); } } @Override public void release(R instance) { context.release(); } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("ExportedInstanceImpl ["); if (requestedType != null) builder.append("requestedType=").append(requestedType).append(", "); if (actualType != null) builder.append("actualType=").append(actualType).append(", "); if (addon.getClassLoader() != null) builder.append("addon.getClassLoader()=").append(addon.getClassLoader()); builder.append("]"); return builder.toString(); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((actualType == null) ? 0 : actualType.getName().hashCode()); result = prime * result + ((requestedType == null) ? 0 : requestedType.getName().hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; ExportedInstanceImpl<?> other = (ExportedInstanceImpl<?>) obj; if (actualType == null) { if (other.actualType != null) return false; } else if (!actualType.getName().equals(other.actualType.getName())) return false; if (requestedType == null) { if (other.requestedType != null) return false; } else if (!requestedType.getName().equals(other.requestedType.getName())) return false; return true; } }