/* DelegatingVariableResolver.java {{IS_NOTE Purpose: Description: History: Dec 31, 2009 10:56:14 AM, Created by henrichen }}IS_NOTE Copyright (C) 2009 Potix Corporation. All Rights Reserved. {{IS_RIGHT This program is distributed under GPL Version 3.0 in the hope that it will be useful, but WITHOUT ANY WARRANTY. }}IS_RIGHT */ package org.zkoss.zkplus.cdi; import java.util.Set; import javax.enterprise.context.spi.CreationalContext; import javax.enterprise.inject.spi.Bean; import javax.enterprise.inject.spi.BeanManager; import org.zkoss.lang.Objects; import org.zkoss.xel.VariableResolverX; import org.zkoss.xel.XelContext; import org.zkoss.xel.XelException; /** * Generic CDI EL named managed bean resolver. * <p>Applicable to CDI version 1.0 or later</p> * @author henrichen * */ public class DelegatingVariableResolver implements VariableResolverX { private BeanManager _beanMgr; public DelegatingVariableResolver() { _beanMgr = CDIUtil.getBeanManager(); } public Object resolveVariable(String name) throws XelException { return resolveVariable(null, null, name); } @SuppressWarnings("rawtypes") public Object resolveVariable(XelContext ctx, Object base, Object name) throws XelException { if (base != null || !(name instanceof String)) return null; final Set<Bean<?>> beans = _beanMgr.getBeans((String) name); if (beans == null || beans.size() == 0) return null; //I(Dennis) think we don't need to check(if there are more than one bean has same name), CDI should check this when startup //However, Since it returns a Set, so I just check it. //Note, I do some test, the alternative bean will not be returned by the getBeans api with the name. Bean bean = null; for (Bean b : beans) { if (b.isAlternative()) continue; //(Ian Tsai) alternative is the bean with explicit declaration in bean.xml. they are reserved for Bean if (bean != null) { throw new XelException( "more than one non-alternative bean have same name " + bean + " and " + b + ", name " + name); } bean = b; } if (bean == null) return null; CreationalContext context = _beanMgr.createCreationalContext(null); /* * Ian Tsai & Dennis * * We are not sure what is the best way to handle the life cycle of CreationalContext. * CreationalContext is the context designed to serve a specific contextual bean type, * we are using null here, so we got no contextual concept. */ // CreationalContext context = ctx==null? // null:(CreationalContext)ctx.getAttribute(CREATIONAL_CONTEXT); // if(context==null){ // System.out.println(">>>>>create a new CreationalContext"); // context = _beanMgr.createCreationalContext(null); // if(ctx!=null){ // ctx.setAttribute(CREATIONAL_CONTEXT,context); // }else{ // // } // } Object value = _beanMgr.getReference(bean, bean.getBeanClass(), context); // follow the old implementation, we won't handle preDestroy of creationalContext in dependent scope. // we cannot call release() before user get the returned value and use it. // context.release(); return value; } public int hashCode() { return Objects.hashCode(_beanMgr); } public boolean equals(Object o) { return this == o || (o instanceof DelegatingVariableResolver && Objects.equals(_beanMgr, ((DelegatingVariableResolver) o)._beanMgr)); } }