Program: 15787
Project: 15787
Buggy source:
/** 
 * Uses Beans introspection to locate a property or method with name matching the key name. If a method or property is found, it is wrapped into   {@link freemarker.template.TemplateMethodModelEx} (for a method orindexed property), or evaluated on-the-fly and the return value wrapped into appropriate model (for a simple property) Models for various properties and methods are cached on a per-class basis, so the costly introspection is performed only once per property or method of a class. (Side-note: this also implies that any class whose method has been called will be strongly referred to by the framework and will not become unloadable until this class has been unloaded first. Normally this is not an issue, but can be in a rare scenario where you create many classes on- the-fly. Also, as the cache grows with new classes and methods introduced to the framework, it may appear as if it were leaking memory. The framework does, however detect class reloads (if you happen to be in an environment that does this kind of things--servlet containers do it when they reload a web application) and flushes the cache. If no method or property matching the key is found, the framework will try to invoke methods with signature <tt>non-void-return-type get(java.lang.String)</tt>, then <tt>non-void-return-type get(java.lang.Object)</tt>, or  alternatively (if the wrapped object is a resource bundle)  <tt>Object getObject(java.lang.String)</tt>.
 * @throws TemplateModelException if there was no property nor method nora generic <tt>get</tt> method to invoke.
 */
public TemplateModel get(String key) throws TemplateModelException {
  Class clazz=object.getClass();
  Map classInfo=wrapper.getClassIntrospectionData(clazz);
  TemplateModel retval=null;
  try {
    if (wrapper.isMethodsShadowItems()) {
      Object fd=classInfo.get(key);
      if (fd != null) {
        retval=invokeThroughDescriptor(fd,classInfo);
      }
 else {
        retval=invokeGenericGet(classInfo,clazz,key);
      }
    }
 else {
      TemplateModel model=invokeGenericGet(classInfo,clazz,key);
      final TemplateModel nullModel=wrapper.wrap(null);
      if (model != nullModel && model != UNKNOWN) {
        return model;
      }
      Object fd=classInfo.get(key);
      if (fd != null) {
        retval=invokeThroughDescriptor(fd,classInfo);
        if (retval == UNKNOWN && model == nullModel) {
          retval=nullModel;
        }
      }
    }
    if (retval == UNKNOWN) {
      if (wrapper.isStrict()) {
        throw new InvalidPropertyException("String_Node_Str" + key);
      }
 else       if (logger.isDebugEnabled()) {
        logNoSuchKey(key,classInfo);
      }
      retval=wrapper.wrap(null);
    }
    return retval;
  }
 catch (  TemplateModelException e) {
    throw e;
  }
catch (  Exception e) {
    throw new TemplateModelException("String_Node_Str" + key + "String_Node_Str"+ "String_Node_Str"+ object.getClass().getName(),e);
  }
}

Fixed version (ground truth):
/** 
 * Uses Beans introspection to locate a property or method with name matching the key name. If a method or property is found, it is wrapped into   {@link freemarker.template.TemplateMethodModelEx} (for a method orindexed property), or evaluated on-the-fly and the return value wrapped into appropriate model (for a simple property) Models for various properties and methods are cached on a per-class basis, so the costly introspection is performed only once per property or method of a class. (Side-note: this also implies that any class whose method has been called will be strongly referred to by the framework and will not become unloadable until this class has been unloaded first. Normally this is not an issue, but can be in a rare scenario where you create many classes on- the-fly. Also, as the cache grows with new classes and methods introduced to the framework, it may appear as if it were leaking memory. The framework does, however detect class reloads (if you happen to be in an environment that does this kind of things--servlet containers do it when they reload a web application) and flushes the cache. If no method or property matching the key is found, the framework will try to invoke methods with signature <tt>non-void-return-type get(java.lang.String)</tt>, then <tt>non-void-return-type get(java.lang.Object)</tt>, or  alternatively (if the wrapped object is a resource bundle)  <tt>Object getObject(java.lang.String)</tt>.
 * @throws TemplateModelException if there was no property nor method nora generic <tt>get</tt> method to invoke.
 */
public TemplateModel get(String key) throws TemplateModelException {
  Class clazz=object.getClass();
  Map classInfo=wrapper.getClassIntrospectionData(clazz);
  TemplateModel retval=null;
  try {
    if (wrapper.isMethodsShadowItems()) {
      Object fd=classInfo.get(key);
      if (fd != null) {
        retval=invokeThroughDescriptor(fd,classInfo);
      }
 else {
        retval=invokeGenericGet(classInfo,clazz,key);
      }
    }
 else {
      TemplateModel model=invokeGenericGet(classInfo,clazz,key);
      final TemplateModel nullModel=wrapper.wrap(null);
      if (model != nullModel && model != UNKNOWN) {
        return model;
      }
      Object fd=classInfo.get(key);
      if (fd != null) {
        retval=invokeThroughDescriptor(fd,classInfo);
        if (retval == UNKNOWN && model == nullModel) {
          retval=nullModel;
        }
      }
    }
    if (retval == UNKNOWN) {
      if (wrapper.isStrict()) {
        throw new InvalidPropertyException("String_Node_Str" + key);
      }
 else       if (logger.isDebugEnabled()) {
        logNoSuchKey(key,classInfo);
      }
      retval=wrapper.wrap(null);
    }
    return retval;
  }
 catch (  TemplateModelException e) {
    throw e;
  }
catch (  Exception e) {
    throw new TemplateModelException("String_Node_Str" + key + "String_Node_Str"+ "String_Node_Str"+ object.getClass().getName()+ "String_Node_Str",e);
  }
}