gt:         field = getField(name, type.getSuperclass());
context: package com.nettap.inception.util;
  
  import com.nettap.inception.annotation.JsonLazy;
  import com.nettap.inception.annotation.PropertyFilter;
  import java.io.IOException;
  import java.io.OutputStream;
  import java.lang.annotation.Annotation;
  import java.lang.reflect.Field;
  import java.lang.reflect.Type;
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.List;
  import java.util.Set;
  import java.util.TreeSet;
  import javax.persistence.Id;
  import javax.persistence.ManyToMany;
  import javax.persistence.ManyToOne;
  import javax.persistence.OneToMany;
  import javax.persistence.OneToOne;
  import javax.ws.rs.Produces;
  import javax.ws.rs.core.MediaType;
  import javax.ws.rs.core.MultivaluedMap;
  import javax.ws.rs.ext.Provider;
  import org.codehaus.jackson.JsonEncoding;
  import org.codehaus.jackson.JsonGenerator;
  import org.codehaus.jackson.JsonStreamContext;
  import org.codehaus.jackson.annotate.JsonManagedReference;
  import org.codehaus.jackson.map.DeserializationConfig;
  //import org.codehaus.jackson.map.MapperConfig;
  import org.codehaus.jackson.map.ObjectMapper;
  import org.codehaus.jackson.map.ObjectWriter;
  import org.codehaus.jackson.map.SerializationConfig;
  import org.codehaus.jackson.map.SerializerProvider;
  import org.codehaus.jackson.map.annotate.JsonView;
  //import org.codehaus.jackson.map.introspect.AnnotatedClass;
  //import org.codehaus.jackson.map.introspect.AnnotatedField;
  //import org.codehaus.jackson.map.introspect.AnnotatedMember;
  //import org.codehaus.jackson.map.introspect.AnnotatedMethod;
  //import org.codehaus.jackson.map.introspect.AnnotatedParameter;
  //import org.codehaus.jackson.map.introspect.JacksonAnnotationIntrospector;
  //import org.codehaus.jackson.map.jsontype.TypeResolverBuilder;
  import org.codehaus.jackson.map.ser.BeanPropertyFilter;
  import org.codehaus.jackson.map.ser.BeanPropertyWriter;
  //import org.codehaus.jackson.map.ser.impl.SimpleBeanPropertyFilter;
  import org.codehaus.jackson.map.ser.impl.SimpleFilterProvider;
  import org.codehaus.jackson.map.util.JSONPObject;
  import org.codehaus.jackson.type.JavaType;
  import org.jboss.resteasy.plugins.providers.jackson.ResteasyJacksonProvider;
  
  /**
   * Implementation of JAX-RS abstractions needed for binding JSON content
   * (to and?) from Java Objects.  It uses a property filter (annotation) to
   * determine whether a property is contained in the JSON output response.
   *
   * @author <a href='mailto:butch57@gmail.com'>Butch Gaston</a>
   * @since 1.0
   */
  @Provider
  //@Consumes({ MediaType.APPLICATION_JSON, "text/json" })
  @Produces({ MediaType.APPLICATION_JSON, "text/json" })
  public class JsonProvider   //TODO: rename to FilteredJsonProvider or FilteredJsonWriter
    extends ResteasyJacksonProvider
  {
    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(JsonProvider.class);
  
  
    public JsonProvider()
    {
      log.debug("created");
      configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
      configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false);
    }
  
    @Override
    public void writeTo(Object value, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String,Object> httpHeaders, OutputStream entityStream)
      throws IOException
    {
      String s = "";
      for (String name : httpHeaders.keySet())
        s += "  header: "+name+": "+httpHeaders.get(name)+"\n";
      log.debug("writeTo:\n"
          +"  value: "+value+"\n"
          +"  type: "+type+"\n"
          +"  genericType: "+genericType+"\n"
          +"  method anns: "+Arrays.toString(annotations)+"\n"
          +"  mediaType: "+mediaType+"\n"
          +s
      );
      /*
      log.debug(new com.bc.ApplicationException().getStackTraceText());
      */
  
      MyFilter filter = new MyFilter();
      for (Annotation ann : annotations)
      {
        if (PropertyFilter.class == ann.annotationType())
          filter.addPropertyFilter((PropertyFilter) ann);
        else if (JsonView.class == ann.annotationType())
          filter.addViews((JsonView) ann);
        else if (JsonLazy.class == ann.annotationType())
          filter.addViews((JsonLazy) ann);
      }
  
      ObjectMapper mapper = locateMapper(type, mediaType);
      mapper.getDeserializationConfig().disable(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES);
      mapper.getSerializationConfig().disable(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS);
      JsonEncoding enc = findEncoding(mediaType, httpHeaders);
  
      JsonGenerator jg = mapper.getJsonFactory().createJsonGenerator(entityStream, enc);
      jg.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
      if (mapper.getSerializationConfig().isEnabled(SerializationConfig.Feature.INDENT_OUTPUT))
        jg.useDefaultPrettyPrinter();
  
      JavaType rootType = null;
      if (genericType != null && value != null)
      {
        if (genericType.getClass() != Class.class)
        {
          rootType = mapper.getTypeFactory().constructType(genericType);
          if (rootType.getRawClass() == Object.class)
            rootType = null;
        }
      }
      log.debug("writeTo: rootType: "+rootType);
  
      if (_jsonpFunctionName != null)
      {
        log.debug("writeTo: WRITER: _jsonpFunctionName: "+_jsonpFunctionName);
        mapper.writeValue(jg, new JSONPObject(_jsonpFunctionName, value, rootType));  //FIXME: filter here???
  
        return;
      }
  
      ObjectWriter writer = (rootType == null ? mapper.writer() : mapper.typedWriter(rootType));
  
      //NOTE: requires JsonFilter("default") on model
      writer = writer.withFilters(new SimpleFilterProvider().addFilter("default", filter));
      log.debug("writeTo: filter: "+filter);
  
      try
      {
        writer.writeValue(jg, value);
      }
      catch (Exception ex)
      {
        log.error(ex+"\n"+com.nettap.inception.exception.ApplicationException.getStackTraceText(ex));
      }
  
      //super.writeTo(value, type, genericType, annotations, mediaType, httpHeaders, entityStream);
    }
  
    class MyFilter
      implements BeanPropertyFilter
    {
      private List<String> excludes = new ArrayList<String>();
      private List<String> includes = new ArrayList<String>();
      private List<Class> views = new ArrayList<Class>();
      private Set<String> managedRefs = new TreeSet<String>();
  
  
      public MyFilter addPropertyFilter(PropertyFilter filter)
      {
        log.debug("created");
        addExcludes(filter.value());
        addExcludes(filter.exclude());
        addIncludes(filter.include());
  
        return this;
      }
  
      public String toString()
      {
        return getClass().getSimpleName()+"{"
          +"includes "+includes
          +", excludes "+excludes
          +", views "+views
          +"}";
      }
  
      public MyFilter addExcludes(String... excludes)
      {
        this.excludes.addAll(parseFilterValue(excludes));
  
        return this;
      }
  
      public MyFilter addIncludes(String... includes)
      {
        this.includes.addAll(parseFilterValue(includes));
  
        return this;
      }
  
      public MyFilter addViews(JsonView views)
      {
        this.views.addAll(Arrays.asList(views.value()));
  
        return this;
      }
  
      public MyFilter addViews(JsonLazy views)
      {
        this.views.addAll(Arrays.asList(views.value()));
  
        return this;
      }
  
      private List<String> parseFilterValue(String[] values)
      {
        List<String> list = new ArrayList<String>();
  
        for (String value : values)
        {
          if (value.contains(","))
            for (String v : value.split(","))
              list.add(v);
          else
            list.add(value);
        }
  
        return list;
      }
  
      private Field getField(String name, Class type)
      {
        Field field = null;
  
        if (name == null || type == null)
          return field;
  
        for (Field f : type.getDeclaredFields())
        {
          if (name.equals(f.getName()))
          {
            field = f;
            break;
          }
        }
  
        if (field == null && type.getSuperclass() != null)
  