/*
* Copyright (c) 2001, 2002 The XDoclet team
* All rights reserved.
*/
package xdoclet.modules.ejb.env;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import org.apache.commons.logging.Log;
import xjavadoc.XClass;
import xjavadoc.XTag;
import xdoclet.XDocletException;
import xdoclet.modules.ejb.EjbTagsHandler;
import xdoclet.modules.ejb.XDocletModulesEjbMessages;
import xdoclet.modules.ejb.home.HomeTagsHandler;
import xdoclet.modules.ejb.intf.InterfaceTagsHandler;
import xdoclet.util.LogUtil;
import xdoclet.util.Translator;
/**
* @author Matthias Germann
* @created April 5, 2005
* @xdoclet.taghandler namespace="EjbEnvEjbRef"
* @version $Revision 1.1 $
* @todo refactor ejbRefId properly to account for ejb:bean - it may not be needed anymore.
* @todo refactor storeReferringClassId properly to take ejb:bean into account - may not be needed
* anymore.
*/
public class EnvEjbRefTagsHandler extends EnvTagsHandler
{
/**
* The id of the EJB referencing another EJB, used for setting up a correct unique id for the ejb-ref.
*
* @see #ejbRefId()
* @see #forAllEjbRefs(java.lang.String,java.util.Properties)
* @see #storeReferringClassId()
*/
private String referringClassId;
private Map already = new HashMap();
private XClass refedEJBClass;
/**
* Returns unique id for the specified ejb-ref. It prefixes it with the referring class's id, then a _ and the id of
* the ejb object.
*
* @return Description of the Returned Value
* @exception XDocletException
* @todo refactor this properly to account for ejb:bean - it may not be needed anymore.
* @doc.tag type="content"
*/
public String ejbRefId() throws XDocletException
{
return referringClassId + '_' + EjbTagsHandler.getEjbIdFor(refedEJBClass);
}
/**
* Evaluates the body block for each ejb reference.
*
* @param template The body of the block tag
* @param attributes The attributes of the template tag
* @exception XDocletException
* @doc.tag type="block"
* @doc.param name="tagName" description="the ejb-ref tag" default="ejb.ejb-ref"
*/
public void forAllEjbRefs(String template, Properties attributes) throws XDocletException
{
already.clear();
if (attributes.getProperty("tagName") == null) {
attributes.setProperty("tagName", "ejb.ejb-ref");
}
forTags(template, attributes, true, true, true);
already.clear();
}
/**
* Evaluates the body block for each method- and field-level ejb reference.
*
* @param template The body of the block tag
* @param attributes The attributes of the template tag
* @exception XDocletException
* @doc.tag type="block"
* @doc.param name="tagName" description="the ejb-ref tag" default="ejb.ejb-ref"
*/
public void forAllEjbRefMembers(String template, Properties attributes) throws XDocletException
{
already.clear();
if (attributes.getProperty("tagName") == null) {
attributes.setProperty("tagName", "ejb.ejb-ref");
}
forTags(template, attributes, false, true, true);
already.clear();
}
/**
* Evaluates the body block for each method-level ejb reference.
*
* @param template The body of the block tag
* @param attributes The attributes of the template tag
* @exception XDocletException
* @doc.tag type="block"
* @doc.param name="tagName" description="the ejb-ref tag" default="ejb.ejb-ref"
*/
public void forAllEjbRefMethods(String template, Properties attributes) throws XDocletException
{
already.clear();
if (attributes.getProperty("tagName") == null) {
attributes.setProperty("tagName", "ejb.ejb-ref");
}
forTags(template, attributes, false, true, false);
already.clear();
}
/**
* Returns the global JNDI name for the current EJB ref.
*
* @return The JNDI name of current EJB ref.
* @exception XDocletException
* @doc.tag type="content"
*/
public String ejbRefJndiName() throws XDocletException
{
String ejbRefJndiName = null;
String jndiNameParameter = currentTag.getAttributeValue("jndi-name");
if (jndiNameParameter != null) {
ejbRefJndiName = jndiNameParameter;
}
else {
String refed_ejb_name = currentTag.getAttributeValue("ejb-name");
if (refed_ejb_name == null) {
throw new XDocletException("No ejb-name attribute found in ejb-ref specified in bean " + getCurrentClass());
}
XClass refed_clazz = findEjb(refed_ejb_name);
String ejb_type = EjbTagsHandler.isLocalEjb(refed_clazz) ? "local" : "remote";
ejbRefJndiName = HomeTagsHandler.getJndiNameOfTypeFor(ejb_type, refed_clazz);
}
return ejbRefJndiName;
}
/**
* Generates code if the ejb-ref is local
*
* @param template
* @exception XDocletException
* @doc.tag type="block"
*/
public void ifLocalEjbRef(String template) throws XDocletException
{
if (isLocalEjbRef(currentTag)) {
generate(template);
}
}
/**
* Generates code if the ejb-ref is local
*
* @param template
* @exception XDocletException
* @doc.tag type="block"
*/
public void ifRemoteEjbRef(String template) throws XDocletException
{
if (isRemoteEjbRef(currentTag)) {
generate(template);
}
}
public String name(Properties attributes) throws XDocletException
{
if (currentMember == null) {
return EjbTagsHandler.ejbRefName(currentTag, refedEJBClass);
}
else {
attributes.setProperty("paramName", "ref-name");
return super.name(attributes);
}
}
/**
* Returns the home interface for the current ejb reference
*
* @return the fully qualified class name
* @throws XDocletException if an error occures
* @doc.tag type="content"
*/
public String homeInterface() throws XDocletException
{
String intf;
if ("ejb.ejb-external-ref".equals(currentTag.getName())) {
intf = currentTag.getAttributeValue("home");
if (intf == null) {
mandatoryParamNotFound(currentTag.getDoc(), "home", "ejb.ejb-external-ref");
}
}
else {
String type = isRemoteEjbRef(currentTag) ? "remote" : "local";
intf = HomeTagsHandler.getHomeInterface(type, getCurrentClass());
}
return intf;
}
/**
* Returns the component interface for the current ejb reference
*
* @return the fully qualified class name
* @throws XDocletException if an error occures
* @doc.tag type="content"
*/
public String componentInterface() throws XDocletException
{
String intf;
if ("ejb.ejb-external-ref".equals(currentTag.getName())) {
intf = currentTag.getAttributeValue("business");
if (intf == null) {
intf = currentTag.getAttributeValue("remote");
}
if (intf == null) {
mandatoryParamNotFound(currentTag.getDoc(), "business", "ejb.ejb-external-ref");
}
}
else {
String type = isRemoteEjbRef(currentTag) ? "remote" : "local";
intf = InterfaceTagsHandler.getComponentInterface(type, getCurrentClass());
}
return intf;
}
/**
* Return true if the ejb-ref is local
*
* @param ejbRefTag
* @return true if the ejb-ref is local otherwise false
* @exception XDocletException
*/
protected boolean isLocalEjbRef(XTag ejbRefTag) throws XDocletException
{
String viewTypeParameter = ejbRefTag.getAttributeValue("view-type");
if (viewTypeParameter == null) {
return EjbTagsHandler.isLocalEjb(refedEJBClass) && !EjbTagsHandler.isRemoteEjb(refedEJBClass);
/*
* TODO introspection for fields and methods
* / use the memeber's type for field- and method-level tags
* XClass type;
* if (currentMember instanceof XMethod) {
* type = ((XMethod) currentMember).getReturnType().getType();
* }
* else {
* type = ((XField) currentMember).getType();
* }
* return type.isA("javax.ejb.EJBLocalHome") || type.isA("javax.ejb.EJBLocalObject");
*/
}
else {
return "local".equals(viewTypeParameter);
}
}
/**
* Return true if the ejb-ref is remote
*
* @param ejbRefTag
* @return true if the ejb-ref is remote otherwise false
* @exception XDocletException
*/
protected boolean isRemoteEjbRef(XTag ejbRefTag) throws XDocletException
{
return !isLocalEjbRef(ejbRefTag);
}
/*
* (non-Javadoc)
* @see xdoclet.modules.ejb.env.EnvTagsHandler#doGenerate(java.lang.String)
*/
protected void doGenerate(String template) throws XDocletException
{
Log log = LogUtil.getLog(EnvEjbRefTagsHandler.class, "doGenerate");
storeReferringClassId();
String ejbNameAttribute = currentTag.getAttributeValue("ejb-name");
if ("ejb.ejb-ref".equals(currentTag.getName())) {
if (ejbNameAttribute == null || ejbNameAttribute.length() < 1) {
mandatoryParamNotFound(currentTag.getDoc(), "ejb-name", "ejb.ejb-ref");
}
refedEJBClass = findEjb(ejbNameAttribute);
}
String refName = name(new Properties());
if (!already.containsKey(refName)) {
already.put(refName, currentTag);
if (refedEJBClass != null) {
pushCurrentClass(refedEJBClass);
}
generate(template);
if (refedEJBClass != null) {
popCurrentClass();
}
}
else {
XTag previousTag = (XTag) already.get(refName);
String prevEjbName = previousTag.getAttributeValue("ejb-name");
if (prevEjbName == null)
prevEjbName = "";
String prevJndiName = previousTag.getAttributeValue("jndi-name");
if (prevJndiName == null)
prevJndiName = "";
if (!(prevEjbName.equals(currentTag.getAttributeValue("ejb-name")) ||
prevJndiName.equals(currentTag.getAttributeValue("jndi-name")))) {
log.error("Duplicate @ejb.ejb-ref found with different parameters!");
log.error("Previous tag: @ejb.ejb-ref ref-name=\"" +
previousTag.getAttributeValue("ref-name") + "\" ejb-name=\"" +
previousTag.getAttributeValue("ejb-name") + "\" view-type=\"" +
previousTag.getAttributeValue("view-type") + "\"");
log.error("Current tag: @ejb.ejb-ref ref-name=\"" +
currentTag.getAttributeValue("ref-name") + "\" ejb-name=\"" +
currentTag.getAttributeValue("ejb-name") + "\" view-type=\"" +
currentTag.getAttributeValue("view-type") + "\"");
throw new XDocletException("Duplicate @ejb.ejb-ref with different parameters");
}
else {
log.warn("Duplicated @ejb.ejb-ref found, ref-name=\"" + refName + "\"");
}
}
referringClassId = null;
}
/**
* Stores the id of current EJB for further use by other tags in referringClassId attribute.
*
* @exception XDocletException
* @todo refactor this properly to take ejb:bean into account - may not be needed anymore.
*/
protected void storeReferringClassId() throws XDocletException
{
referringClassId = EjbTagsHandler.getEjbIdFor(getCurrentClass());
}
/**
* Finds and returns the class with the specified ejbName. An XDocletException is thrown if not found.
*
* @param ejbName Description of Parameter
* @return Description of the Returned Value
* @exception XDocletException
*/
protected XClass findEjb(String ejbName) throws XDocletException
{
Collection classes = getXJavaDoc().getSourceClasses();
for (Iterator i = classes.iterator(); i.hasNext(); ) {
XClass clazz = (XClass) i.next();
if (EjbTagsHandler.isEjb(clazz) && ejbName.equals(EjbTagsHandler.getEjbNameFor(clazz))) {
return clazz;
}
}
throw new XDocletException(Translator.getString(XDocletModulesEjbMessages.class, XDocletModulesEjbMessages.NOT_DEFINED, new String[]{ejbName}));
}
}