Modified: 
turbine/fulcrum/trunk/json/jackson2/src/java/org/apache/fulcrum/json/jackson/Jackson2MapperService.java
URL: 
http://svn.apache.org/viewvc/turbine/fulcrum/trunk/json/jackson2/src/java/org/apache/fulcrum/json/jackson/Jackson2MapperService.java?rev=1845825&r1=1845824&r2=1845825&view=diff
==============================================================================
--- 
turbine/fulcrum/trunk/json/jackson2/src/java/org/apache/fulcrum/json/jackson/Jackson2MapperService.java
 (original)
+++ 
turbine/fulcrum/trunk/json/jackson2/src/java/org/apache/fulcrum/json/jackson/Jackson2MapperService.java
 Mon Nov  5 17:43:51 2018
@@ -27,6 +27,7 @@ import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 
 import org.apache.avalon.framework.activity.Initializable;
 import org.apache.avalon.framework.configuration.Configurable;
@@ -34,6 +35,7 @@ import org.apache.avalon.framework.confi
 import org.apache.avalon.framework.configuration.ConfigurationException;
 import org.apache.avalon.framework.logger.AbstractLogEnabled;
 import org.apache.avalon.framework.logger.LogEnabled;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.fulcrum.json.JsonService;
 import org.apache.fulcrum.json.jackson.filters.CustomModuleWrapper;
 import org.apache.fulcrum.json.jackson.jsonpath.DefaultJsonPathWrapper;
@@ -74,817 +76,742 @@ import com.fasterxml.jackson.databind.se
  * 
  * By default a filter is defined by its {@link Class#getName()}.
  * 
- * Note: If using {@link SimpleNameIntrospector}, filter caches are set by 
class id. Caching is enabled by default, if not (a) by setting {@link 
#cacheFilters} to <code>false</code>.  
- * By setting (b) the Boolean parameter clean {@link 
#serializeAllExceptFilter(Object, Class, Boolean, String...)} or {@link 
#serializeOnlyFilter(Object, Class, Boolean, String...)} 
- * you could clean the filter. If caching is disabled each filter will be 
unregistered and the cache cleaned.
+ * Note: If using {@link SimpleNameIntrospector}, filter caches are set by 
class
+ * id. Caching is enabled by default, if not (a) by setting
+ * {@link #cacheFilters} to <code>false</code>. By setting (b) the Boolean
+ * parameter clean
+ * {@link #serializeAllExceptFilter(Object, Class, Boolean, String...)} or
+ * {@link #serializeOnlyFilter(Object, Class, Boolean, String...)} you could
+ * clean the filter. If caching is disabled each filter will be unregistered 
and
+ * the cache cleaned.
  * 
  * @author <a href="mailto:g...@apache.org";>Georg Kallidis</a>
  * @version $Id$
  * 
  */
-public class Jackson2MapperService extends AbstractLogEnabled implements
-        JsonService, Initializable, Configurable {
+public class Jackson2MapperService extends AbstractLogEnabled implements 
JsonService, Initializable, Configurable {
 
+       private static final String DEFAULT_TYPING = "defaultTyping";
+       private static final String CACHE_FILTERS = "cacheFilters";
+       private static final String DATE_FORMAT = "dateFormat";
+       private static final String ESCAPE_CHARS = "escapeCharsGlobal";
+       private static final String ESCAPE_CHAR_CLASS = "escapeCharsClass";
+       private static final String USE_JSON_PATH = "useJsonPath";
+       ObjectMapper mapper;
+       AnnotationIntrospector primary; // support default
+       AnnotationIntrospector secondary;
+
+       private static final String ANNOTATIONINSPECTOR = 
"annotationInspectors";
+
+       private Map<String, String> annotationInspectors = null;
+       private Map<String, Boolean> features = null;
+       private Map<String, String> featureTypes = null;
+
+       private String dateFormat;
+
+       /**
+        * Default dateformat is <code>MM/dd/yyyy</code>, could be overwritten 
in
+        * {@link #setDateFormat(DateFormat)}.
+        */
+       public static final String DEFAULTDATEFORMAT = "MM/dd/yyyy";
+
+       private boolean cacheFilters = true; // true -> this is by default true 
in jackson, if not using
+                                                                               
        // multiple serialization in one thread
+       String[] defaultTypeDefs = null;
+       private CacheService cacheService;
+       private boolean escapeCharsGlobal = false; // to be backward 
compatible, but should be true, then escaping to avoid
+                                                                               
                // XSS payload by default
+       private boolean useJsonPath = false;
+       private String escapeCharsClass = null;
+
+       @Override
+       public String ser(Object src) throws Exception {
+               return ser(src, false);
+       }
+
+       @Override
+       public <T> String ser(Object src, Class<T> type) throws Exception {
+               return ser(src, type, false);
+       }
+
+       public String ser(Object src, FilterProvider filter) throws Exception {
+               return ser(src, filter, false);
+       }
+
+       public String ser(Object src, FilterProvider filter, Boolean 
cleanCache) throws Exception {
+               String serResult = null;
+               if (src == null) {
+                       getLogger().info("no serializable object.");
+                       return serResult;
+               }
+               if (filter == null) {
+                       getLogger().debug("ser class::" + src.getClass() + " 
without filter.");
+                       return ser(src);
+               } else {
+                       getLogger().debug("add filter for cache filter Class " 
+ src.getClass().getName());
+                       
setCustomIntrospectorWithExternalFilterId(src.getClass(), null); // filter class
+                       cacheService.getFilters().put(src.getClass().getName(), 
filter);
+               }
+               getLogger().debug("ser class::" + src.getClass() + " with 
filter " + filter);
+               mapper.setFilterProvider(filter);
+               String res = mapper.writer(filter).writeValueAsString(src);
+               if (cleanCache) {
+                       cacheService.cleanSerializerCache(mapper);
+               }
+               return res;
+       }
+
+       @Override
+       public <T> T deSer(String json, Class<T> type) throws Exception {
+               ObjectReader reader = null;
+               if (type != null)
+                       reader = mapper.readerFor(type);
+               else
+                       reader = mapper.reader();
+
+               return reader.readValue(json);
+       }
+
+       public <T> T deSer(Object src, Class<T> type) throws Exception {
+               return mapper.convertValue(src, type);
+       }
+
+       public <T> Collection<T> deSerCollectionWithType(String json, Class<? 
extends Collection> collectionClass,
+                       Class<T> type) throws Exception {
+               return mapper.readValue(json, 
mapper.getTypeFactory().constructCollectionType(collectionClass, type));
+       }
+
+       public <T> String serCollectionWithTypeReference(Collection<T> src, 
TypeReference collectionType,
+                       Boolean cleanCache) throws Exception {
+               String res = 
mapper.writerFor(collectionType).writeValueAsString(src);
+               if (cleanCache) {
+                       cacheService.cleanSerializerCache(mapper);
+               }
+               return res;
+       }
+
+       @Override
+       public <T> Collection<T> deSerCollection(String json, Object 
collectionType, Class<T> elementType)
+                       throws Exception {
+               if (collectionType instanceof TypeReference) {
+                       return mapper.readValue(json, (TypeReference<T>) 
collectionType);
+               } else {
+                       return mapper.readValue(json, mapper.getTypeFactory()
+                                       
.constructCollectionType(((Collection<T>) collectionType).getClass(), 
elementType));
+               }
+       }
+
+       public <T> List<T> deSerList(String json, Class<? extends List> 
targetList, Class<T> elementType) throws Exception {
+               return mapper.readValue(json, 
mapper.getTypeFactory().constructParametricType(targetList, elementType));
+       }
+
+       public <T, U> Map<T, U> deSerMap(String json, Class<? extends Map> 
mapClass, Class<T> keyClass, Class<U> valueClass)
+                       throws Exception {
+               return mapper.readValue(json, 
mapper.getTypeFactory().constructMapType(mapClass, keyClass, valueClass));
+       }
+
+       public <T> Collection<T> deSerCollectionWithTypeReference(String json, 
TypeReference<T> collectionType)
+                       throws Exception {
+               return mapper.readValue(json, collectionType);
+       }
+
+       /**
+        * @param name   name of the module
+        * @param target target class
+        * @param mixin  provide mixin as class. Deregistering module could be 
only done
+        *               by setting this parameter to null.
+        * 
+        * @see #addAdapter(String, Class, Object)
+        */
+       @Override
+       public JsonService addAdapter(String name, Class target, Class mixin) 
throws Exception {
+               getLogger().debug(
+                               "registering unversioned simple mixin module 
named " + name + " of type " + mixin + "  for: " + target);
+               mapper.addMixIn(target, mixin);
+               return this;
+       }
+
+       /**
+        * Add a named module or a {@link Module}.
+        * 
+        * @param name   Name of the module, optional. Could be null, if module 
is a
+        *               {@link Module}.
+        * 
+        * @param target Target class, optional. Could be null, if module is a
+        *               {@link Module}.
+        * 
+        * @param module Either an Jackson Module @link {@link Module} or an 
custom
+        *               wrapper @link CustomModuleWrapper.
+        * 
+        * @see JsonService#addAdapter(String, Class, Object)
+        */
+       @Override
+       public JsonService addAdapter(String name, Class target, Object module) 
throws Exception {
+               if (module instanceof CustomModuleWrapper) {
+                       CustomModuleWrapper cmw = (CustomModuleWrapper) module;
+                       Module cm = new CustomModule(name, target, 
cmw.getSer(), cmw.getDeSer());
+                       getLogger().debug("registering custom module " + cm + " 
 for: " + target);
+                       mapper.registerModule(cm);
+               } else if (module instanceof Module) {
+                       getLogger().debug("registering module " + module);
+                       mapper.registerModule((Module) module);
+               } else {
+                       throw new Exception("expecting module type" + 
Module.class);
+               }
+               return this;
+       }
+
+       /**
+        * set a single mixin. convenience method, calls
+        * {@link ObjectMapper#registerModule(Module)}
+        * 
+        * @param src    he object to be serialized
+        * @param name   the name for the mixin
+        * @param target the target class for the mixin
+        * @param mixin  the mixin class
+        * @return serialized result
+        * @throws JsonProcessingException if not properly processed
+        */
+       @SuppressWarnings("rawtypes")
+       public String withMixinModule(Object src, String name, Class target, 
Class mixin) throws JsonProcessingException {
+               Module mx = new MixinModule(name, target, mixin);
+               getLogger().debug("registering module " + mx + ", mixin: " + 
mixin);
+               return 
mapper.registerModule(mx).writer().writeValueAsString(src);
+       }
+
+       /**
+        * This is a convenience method with read, but the old mixins will be 
cleared
+        * {@link ObjectMapper#setMixIns(Map)}
+        * 
+        * @param src    the object to be serialized
+        * @param target the target class for the mixin
+        * @param mixin  the mixin class
+        * @return serialized result
+        * @throws JsonProcessingException if fail
+        */
+       @SuppressWarnings("rawtypes")
+       public String withSetMixins(Object src, Class target, Class mixin) 
throws JsonProcessingException {
+               return setMixins(target, 
mixin).writer().writeValueAsString(src);
+       }
+
+       /**
+        * @param target The target class
+        * @param mixin  the mixin class
+        * @return an objectmapper
+        */
+       @SuppressWarnings("rawtypes")
+       public ObjectMapper setMixins(Class target, Class mixin) {
+               Map<Class<?>, Class<?>> sourceMixins = null;
+               if (target != null) {
+                       sourceMixins = new HashMap<>(1);
+                       sourceMixins.put(target, mixin);
+               }
+               getLogger().debug("clean set mixins for target " + target + ", 
mixin: " + mixin);
+               return mapper.setMixIns(sourceMixins);
+       }
+
+       @Override
+       public String serializeAllExceptFilter(Object src, String... 
filterAttr) throws Exception {
+               return serializeAllExceptFilter(src, src.getClass(), true, 
filterAttr);
+       }
+
+       @Override
+       public synchronized String serializeAllExceptFilter(Object src, Boolean 
cache, String... filterAttr)
+                       throws Exception {
+               return serializeAllExceptFilter(src, src.getClass(), cache, 
filterAttr);
+       }
+
+       public synchronized <T> String serializeAllExceptFilter(Object src, 
Class<T>[] filterClasses, String... filterAttr)
+                       throws Exception {
+               return serializeAllExceptFilter(src, filterClasses, true, 
filterAttr);
+       }
+
+       @Override
+       public synchronized <T> String serializeAllExceptFilter(Object src, 
Class<T> filterClass, String... filterAttr)
+                       throws Exception {
+               return serializeAllExceptFilter(src, filterClass, true, 
filterAttr);
+       }
+
+       @Override
+       public <T> String serializeAllExceptFilter(Object src, Class<T> 
filterClass, Boolean cleanFilter,
+                       String... filterAttr) throws Exception {
+               return serializeAllExceptFilter(src, new Class[] { filterClass 
}, cleanFilter, filterAttr);
+       }
+
+       /**
+        * 
+        * @param src           the object to be serailized, may be a list
+        * @param filterClasses the same object class or a detail class, which 
should be
+        *                      filtered
+        * @param               <T> class type
+        * @param clean         cleaning the cache after serialization
+        * @param filterAttr    attributes to be filtered for filtered class
+        * @return the serailized string
+        * @throws Exception generic exception
+        */
+       public synchronized <T> String serializeAllExceptFilter(Object src, 
Class<T>[] filterClasses, Boolean clean,
+                       String... filterAttr) throws Exception {
+               PropertyFilter pf = null;
+               if (filterAttr != null)
+                       pf = 
SimpleBeanPropertyFilter.serializeAllExcept(filterAttr);
+               else if (filterClasses == null) { // no filter
+                       return ser(src, clean);
+                       // should be better:
+                       // return filter(src, new Class<?>[] { src.getClass() 
}, filterClasses, pf,
+                       // clean);
+               }
+               return filter(src, new Class<?>[] { filterClasses[0] }, 
filterClasses, pf, clean);
+       }
+
+       @Override
+       public String serializeOnlyFilter(Object src, String... filterAttrs) 
throws Exception {
+               return serializeOnlyFilter(src, src.getClass(), true, 
filterAttrs);
+       }
+
+       @Override
+       public synchronized String serializeOnlyFilter(Object src, Boolean 
cache, String... filterAttr) throws Exception {
+               return serializeOnlyFilter(src, src.getClass(), cache, 
filterAttr);
+       }
+
+       @Override
+       public synchronized <T> String serializeOnlyFilter(Object src, Class<T> 
filterClass, String... filterAttr)
+                       throws Exception {
+               return serializeOnlyFilter(src, filterClass, true, filterAttr);
+       }
+
+       @Override
+       public synchronized <T> String serializeOnlyFilter(Object src, Class<T> 
filterClass, Boolean refresh,
+                       String... filterAttr) throws Exception {
+               return serializeOnlyFilter(src, new Class[] { filterClass }, 
refresh, filterAttr);
+       }
+
+       public synchronized <T> String serializeOnlyFilter(Object src, 
Class<T>[] filterClasses, Boolean refresh,
+                       String... filterAttr) throws Exception {
+               PropertyFilter pf = null;
+               if (filterAttr != null && filterAttr.length > 0 && 
!"".equals(filterAttr[0])) {
+                       pf = 
SimpleBeanPropertyFilter.filterOutAllExcept(filterAttr);
+                       getLogger().debug("setting filteroutAllexcept filter 
for size of filterAttr: " + filterAttr.length);
+               } else {
+                       getLogger().warn("no filter attributes set!");
+                       pf = 
SimpleBeanPropertyFilter.filterOutAllExcept("dummy");
+               }
+               if (filterClasses == null)
+                       throw new Exception("You have to provide some class to 
apply the filtering!");
+               return filter(src, filterClasses, null, pf, refresh);
+       }
+
+       @Override
+       public String ser(Object src, Boolean cleanCache) throws Exception {
+               if 
(cacheService.getFilters().containsKey(src.getClass().getName())) {
+                       getLogger().warn("Found registered filter - using 
instead of default view filter for class:"
+                                       + src.getClass().getName());
+                       SimpleFilterProvider filter = (SimpleFilterProvider) 
cacheService.getFilters()
+                                       .get(src.getClass().getName());
+                       return ser(src, filter, cleanCache);// 
mapper.writerWithView(src.getClass()).writeValueAsString(src);
+               }
+               String res = 
mapper.writerWithView(Object.class).writeValueAsString(src);
+               if (cleanCache != null && cleanCache) {
+                       cacheService.cleanSerializerCache(mapper);
+               }
+               return res;
+       }
+
+       @Override
+       public <T> String ser(Object src, Class<T> type, Boolean cleanCache) 
throws Exception {
+               getLogger().info("serializing object:" + src + " for type " + 
type);
+               if (src != null && 
cacheService.getFilters().containsKey(src.getClass().getName())) {
+                       getLogger().warn("Found registered filter - could not 
use custom view and custom filter for class:"
+                                       + src.getClass().getName());
+                       // throw new
+                       // Exception("Found registered filter - could not use 
custom view and custom
+                       // filter for class:"+
+                       // src.getClass().getName());
+                       SimpleFilterProvider filter = (SimpleFilterProvider) 
cacheService.getFilters()
+                                       .get(src.getClass().getName());
+                       return ser(src, filter);
+               }
+
+               String res = (type != null) ? 
mapper.writerWithView(type).writeValueAsString(src)
+                               : mapper.writeValueAsString(src);
+               if (cleanCache) {
+                       cacheService.cleanSerializerCache(mapper);
+               }
+               return res;
+       }
+
+       /**
+        * 
+        * @param src            The source Object to be filtered.
+        * @param filterClass    This Class array contains at least one 
element. If no
+        *                       class is provided it is the class type of the 
source
+        *                       object. The filterClass is to become the key 
of the
+        *                       filter object cache.
+        * @param excludeClasses The classes to be excluded, optionally used 
only for
+        *                       methods like
+        *                       {@link #serializeAllExceptFilter(Object, 
Class[], String...)}.
+        * @param pf             Expecting a property filter from e.g @link
+        *                       {@link SimpleBeanPropertyFilter}.
+        * @param clean          if <code>true</code> does not reuse the filter 
object
+        *                       (no cashing).
+        * @return The serialized Object as String
+        * @throws Exception
+        */
+       private <T> String filter(Object src, Class<?>[] filterClasses, 
Class<T>[] excludeClasses, PropertyFilter pf,
+                       Boolean clean) throws Exception {
+               FilterProvider filter = null;
+               if (filterClasses.length > 0) {
+                       filter = retrieveFilter(pf, filterClasses[0], 
excludeClasses);
+               }
+               getLogger().info("filtering with filter " + filter);
+               String serialized = ser(src, filter, clean);
+               if (!cacheFilters || clean) {
+                       if (filterClasses.length > 0) {
+                               boolean exclude = (excludeClasses != null) ? 
true : false;
+                               cacheService.removeFilter(filterClasses[0], 
exclude);
+                       }
+               }
+               return serialized;
+       }
+
+       private <T> SimpleFilterProvider retrieveFilter(PropertyFilter pf, 
Class<?> filterClass,
+                       Class<T>[] excludeClasses) {
+               SimpleFilterProvider filter = null;
+               if (pf != null) {
+                       filter = new SimpleFilterProvider();
+                       filter.setDefaultFilter(pf);
+               }
+               if 
(!cacheService.getFilters().containsKey(filterClass.getName())) {
+                       getLogger().debug("add filter for cache filter Class " 
+ filterClass.getName());
+                       setCustomIntrospectorWithExternalFilterId(filterClass, 
excludeClasses); // filter class
+                       if (pf != null) {
+                               
cacheService.getFilters().put(filterClass.getName(), filter);
+                       }
+               } else {
+                       filter = (SimpleFilterProvider) 
cacheService.getFilters().get(filterClass.getName());
+                       // 
setCustomIntrospectorWithExternalFilterId(filterClass); // filter
+                       // class
+               }
+               getLogger().debug("set filter:" + filter);
+               return filter;
+       }
+
+       /**
+        * @param filterClass
+        *                          <li>Adding filterClass into
+        *                          {@link 
SimpleNameIntrospector#setFilteredClass(Class)}
+        *                          enables the filtering process.
+        * @param externalFilterIds
+        *                          <li>Adding externalFilterIs to
+        *                          {@link 
SimpleNameIntrospector#setExternalFilterExcludeClasses(Class...)}
+        *                          excludes these classes.
+        */
+       private <T> void setCustomIntrospectorWithExternalFilterId(Class<?> 
filterClass,
+                       Class<T>[] externalFilterClassIds) {
+               if (primary instanceof SimpleNameIntrospector) {
+                       // first one is required that we get to the 
PropertyFilter
+                       ((SimpleNameIntrospector) 
primary).setFilteredClasses(filterClass);
+                       if (externalFilterClassIds != null) {
+                               ((SimpleNameIntrospector) 
primary).setIsExludeType(true);
+                               for (Class<T> filterClazz : 
externalFilterClassIds) {
+                                       getLogger().debug("added class for 
filters " + filterClazz);
+                               }
+                               ((SimpleNameIntrospector) 
primary).setExternalFilterExcludeClasses(externalFilterClassIds);
+                       }
+               }
+       }
+
+       public Jackson2MapperService registerModule(Module module) {
+               mapper.registerModule(module);
+               return this;
+       }
+
+       public <T> void addSimpleModule(SimpleModule module, Class<T> type, 
JsonSerializer<T> ser) {
+               module.addSerializer(type, ser);
+       }
+
+       public <T> void addSimpleModule(SimpleModule module, Class<T> type, 
JsonDeserializer<T> deSer) {
+               module.addDeserializer(type, deSer);
+       }
+
+       /**
+        * Default Dateformat: {@link #DEFAULTDATEFORMAT}
+        */
+       @Override
+       public void setDateFormat(final DateFormat df) {
+               mapper.setDateFormat(df);
+       }
+
+       /**
+        * Avalon component lifecycle method
+        */
+       @Override
+       public void configure(Configuration conf) throws ConfigurationException 
{
+               getLogger().debug("conf.getName()" + conf.getName());
+               this.annotationInspectors = new HashMap<>();
+
+               final Configuration configuredAnnotationInspectors = 
conf.getChild(ANNOTATIONINSPECTOR, false);
+
+               if (configuredAnnotationInspectors != null) {
+                       Configuration[] nameVal = 
configuredAnnotationInspectors.getChildren();
+                       for (int i = 0; i < nameVal.length; i++) {
+                               String key = nameVal[i].getName();
+                               getLogger().debug("configured key: " + key);
+                               if (key.equals("features")) {
+                                       this.features = new HashMap<>();
+                                       this.featureTypes = new HashMap<>();
+                                       Configuration[] localFeatures = 
nameVal[i].getChildren();
+                                       for (int j = 0; j < 
localFeatures.length; j++) {
+                                               boolean featureValue = 
localFeatures[j].getAttributeAsBoolean("value", false);
+                                               String featureType = 
localFeatures[j].getAttribute("type");
+                                               String feature = 
localFeatures[j].getValue();
+                                               
getLogger().debug("configuredAnnotationInspectors " + feature + ":" + 
featureValue);
+                                               this.features.put(feature, 
featureValue);
+                                               this.featureTypes.put(feature, 
featureType);
+                                       }
+                               } else {
+                                       String val = nameVal[i].getValue();
+                                       
getLogger().debug("configuredAnnotationInspectors " + key + ":" + val);
+                                       this.annotationInspectors.put(key, val);
+                               }
+                       }
+               }
+               final Configuration configuredDateFormat = 
conf.getChild(DATE_FORMAT, true);
+               this.dateFormat = 
configuredDateFormat.getValue(DEFAULTDATEFORMAT);
+
+               final Configuration configuredKeepFilter = 
conf.getChild(CACHE_FILTERS, false);
+               if (configuredKeepFilter != null) {
+                       this.cacheFilters = 
configuredKeepFilter.getValueAsBoolean();
+               }
+               final Configuration configuredEscapeChars = 
conf.getChild(ESCAPE_CHARS, false);
+               if (configuredEscapeChars != null) {
+                       this.escapeCharsGlobal = 
configuredEscapeChars.getValueAsBoolean();
+               }
+               final Configuration configuredEscapeCharClass = 
conf.getChild(ESCAPE_CHAR_CLASS, false);
+               if (configuredEscapeCharClass != null) {
+                       this.escapeCharsClass = 
configuredEscapeCharClass.getValue();
+               }
+
+               final Configuration configuredDefaultType = 
conf.getChild(DEFAULT_TYPING, false);
+               if (configuredDefaultType != null) {
+                       defaultTypeDefs = new String[] { 
configuredDefaultType.getAttribute("type"),
+                                       
configuredDefaultType.getAttribute("key") };
+               }
+               final Configuration configuredjsonPath = 
conf.getChild(USE_JSON_PATH, false);
+               if (configuredjsonPath != null) {
+                       this.useJsonPath = 
configuredjsonPath.getValueAsBoolean();
+               }
+       }
+
+       @Override
+       public void initialize() throws Exception {
+               mapper = new ObjectMapper(null, null, null);// add configurable 
JsonFactory,.. later?
+
+               initAnnotationInspectors();
+
+               initFeatures();
+
+               initDefaultTyping();
+
+               getLogger().info("setting date format to:" + dateFormat);
+               getLogger().info("cacheFilters is:" + cacheFilters);
+               if (!cacheFilters) {
+                       
mapper.configure(SerializationFeature.FLUSH_AFTER_WRITE_VALUE, true);
+               }
+
+               mapper.setDateFormat(new SimpleDateFormat(dateFormat));
+
+               if (escapeCharsGlobal) {
+                       
mapper.getFactory().setCharacterEscapes(characterEscapes);
+               }
+               if (escapeCharsClass != null) {
+                       try {
+                               characterEscapes = (CharacterEscapes) 
Class.forName(escapeCharsClass).getConstructor().newInstance();
+                       } catch (Exception e) {
+                               throw new Exception(
+                                               "JsonMapperService: Error 
instantiating " + escapeCharsClass + " for " + ESCAPE_CHAR_CLASS);
+                       }
+               }
+
+               getLogger().debug("initialized mapper:" + mapper);
+
+               mapper.getSerializerProvider().setNullValueSerializer(new 
JsonSerializer<Object>() {
+                       @Override
+                       public void serialize(Object value, JsonGenerator jgen, 
SerializerProvider provider) throws IOException {
+                               jgen.writeString("");
+
+                       }
+               });
+               cacheService = new CacheService(primary);
+               if (cacheService instanceof LogEnabled) {
+                       
cacheService.enableLogging(getLogger().getChildLogger(cacheService.getClass().getSimpleName()));
+                       getLogger().info("setting cacheService logger: " + 
cacheService.getClass().getSimpleName());
+               }
+
+               if (useJsonPath) {
+                       // set it before runtime
+                       DefaultJsonPathWrapper djpw = null;
+                       try {
+                               djpw = new DefaultJsonPathWrapper(this.mapper);
+                               getLogger().debug("******** initialized new 
jsonPath defaults: " + djpw.getJsonPathDefault());
+                       } catch (Exception e) {
+                               throw new Exception(
+                                               "JsonMapperService: Error 
instantiating " + djpw + " using useJsonPath=" + useJsonPath);
+                       }
+
+               }
+       }
+
+       private void initDefaultTyping() {
+               if (defaultTypeDefs != null && defaultTypeDefs.length == 2) {
+                       DefaultTyping defaultTyping = 
DefaultTyping.valueOf(defaultTypeDefs[0]);
+                       mapper.enableDefaultTypingAsProperty(defaultTyping, 
defaultTypeDefs[1]);
+                       getLogger().info("default typing is " + 
defaultTypeDefs[0] + " with key:" + defaultTypeDefs[1]);
+               }
+       }
+
+       private void initFeatures() throws Exception {
+               if (features != null && !features.isEmpty()) {
+                       
+                       for (Entry<String, Boolean> entry : 
features.entrySet()) {
+                               String featureKey = entry.getKey();
+                               Boolean featureValue = entry.getValue();        
+                               String featureType = 
featureTypes.get(featureKey);
+                               Class<?> configFeature = null;
+                               try {
+                                       getLogger().debug("initializing 
featureType:  " + featureType);
+                                       configFeature = 
Class.forName(featureType);
+                               } catch (Exception e) {
+                                       throw new Exception("JsonMapperService: 
Error instantiating " + featureType + " for " + featureKey,
+                                                       e);
+                               }
+                               ConfigFeature feature = null;
+                               if (!StringUtils.isEmpty(featureKey) && 
featureValue != null) {
+                                       try {
+                                               if 
(configFeature.equals(SerializationFeature.class)) {
+                                                       feature = 
SerializationFeature.valueOf(featureKey);
+                                                       
mapper.configure((SerializationFeature) feature, featureValue);
+                                                       assert 
mapper.getSerializationConfig()
+                                                                       
.isEnabled((SerializationFeature) feature) == featureValue;
+                                                       
getLogger().info("initialized serconfig mapper feature: " + feature + " with "
+                                                                       + 
mapper.getSerializationConfig().isEnabled((SerializationFeature) feature));
+                                               } else if 
(configFeature.equals(DeserializationFeature.class)) {
+                                                       feature = 
DeserializationFeature.valueOf(featureKey);
+                                                       
mapper.configure((DeserializationFeature) feature, featureValue);
+                                                       assert 
mapper.getDeserializationConfig()
+                                                                       
.isEnabled((DeserializationFeature) feature) == featureValue;
+                                                       
getLogger().info("initialized deserconfig mapper feature: " + feature + " with "
+                                                                       + 
mapper.getDeserializationConfig().isEnabled((DeserializationFeature) feature));
+                                               } else if 
(configFeature.equals(MapperFeature.class)) {
+                                                       feature = 
MapperFeature.valueOf(featureKey);
+                                                       
mapper.configure((MapperFeature) feature, featureValue);
+                                                       assert 
mapper.getDeserializationConfig().isEnabled((MapperFeature) feature) == 
featureValue;
+                                                       assert 
mapper.getSerializationConfig().isEnabled((MapperFeature) feature) == 
featureValue;
+                                                       
getLogger().info("initialized serconfig mapper feature: " + feature + " with "
+                                                                       + 
mapper.getDeserializationConfig().isEnabled((MapperFeature) feature));
+                                                       
getLogger().info("initialized deserconfig mapper feature: " + feature + " with "
+                                                                       + 
mapper.getSerializationConfig().isEnabled((MapperFeature) feature));
+                                               } else if 
(configFeature.equals(JsonParser.class)) {
+                                                       Feature parserFeature = 
JsonParser.Feature.valueOf(featureKey);
+                                                       
getLogger().info("initializing parser feature: " + parserFeature + " with " + 
featureValue);
+                                                       
mapper.configure(parserFeature, featureValue);
+                                               } else if 
(configFeature.equals(JsonGenerator.class)) {
+                                                       
com.fasterxml.jackson.core.JsonGenerator.Feature genFeature = 
JsonGenerator.Feature
+                                                                       
.valueOf(featureKey);
+                                                       
getLogger().info("initializing parser feature: " + genFeature + " with " + 
featureValue);
+                                                       
mapper.configure(genFeature, featureValue);
+                                               }
+                                       } catch (Exception e) {
+                                               throw new 
Exception("JsonMapperService: Error instantiating feature " + featureKey + " 
with  "
+                                                               + featureValue, 
e);
+                                       }
+                               }
+                       }
+               }
+       }
+
+       private void initAnnotationInspectors() throws Exception {
+               for (Entry<String, String> entry : 
annotationInspectors.entrySet()) {
+                       String key = entry.getKey();
+                       String avClass = entry.getValue();
+                       if (key.equals("primary") && 
!StringUtils.isEmpty(avClass)) {
+                               try {
+                                       primary = (AnnotationIntrospector) 
Class.forName(avClass).getConstructor().newInstance();
+                               } catch (Exception e) {
+                                       throw new Exception("JsonMapperService: 
Error instantiating " + avClass + " for " + key);
+                               }
+                       } else if (key.equals("secondary") && avClass != null) {
+                               try {
+                                       secondary = (AnnotationIntrospector) 
Class.forName(avClass).getConstructor().newInstance();
+                               } catch (Exception e) {
+                                       throw new Exception("JsonMapperService: 
Error instantiating " + avClass + " for " + key);
+                               }
+                       }
+               }
+               if (primary == null) {
+                       primary = new JacksonAnnotationIntrospector(); // 
support default
+                       getLogger().info("using default introspector:" + 
primary.getClass().getName());
+                       mapper.setAnnotationIntrospector(primary);
+               } else if (primary != null && secondary != null) {
+                       AnnotationIntrospector pair = new 
AnnotationIntrospectorPair(primary, secondary);
+                       mapper.setAnnotationIntrospector(pair);
+               } else {
+                       mapper.setAnnotationIntrospector(primary);
+               }
+
+               if (primary instanceof LogEnabled) {
+                       ((LogEnabled) 
primary).enableLogging(getLogger().getChildLogger(primary.getClass().getSimpleName()));
+                       getLogger().info("setting primary introspector logger: 
" + primary.getClass().getSimpleName());
+               }
+               if (secondary instanceof LogEnabled) {
+                       ((LogEnabled) 
secondary).enableLogging(getLogger().getChildLogger(secondary.getClass().getSimpleName()));
+                       getLogger().info("setting secondary introspector 
logger: " + secondary.getClass().getSimpleName());
+               }
+       }
+
+       public ObjectMapper getMapper() {
+               return mapper;
+       }
+
+       public void setMapper(ObjectMapper mapper) {
+               this.mapper = mapper;
+       }
+
+       public boolean isCacheFilters() {
+               return cacheFilters;
+       }
+
+       public void setCacheFilters(boolean cacheFilters) {
+               this.cacheFilters = cacheFilters;
+               if (!cacheFilters)
+                       
mapper.configure(SerializationFeature.FLUSH_AFTER_WRITE_VALUE, true);
+       }
+
+       static CharacterEscapes characterEscapes = new CharacterEscapes() {
+               private static final long serialVersionUID = 1L;
+               private final int[] asciiEscapes;
+               { // instance init
+                       int[] esc = standardAsciiEscapesForJSON();
+                       // this avoids to get evaluated immediately
+                       esc['<'] = CharacterEscapes.ESCAPE_STANDARD;
+                       esc['>'] = CharacterEscapes.ESCAPE_STANDARD;
+                       esc['&'] = CharacterEscapes.ESCAPE_STANDARD;
+                       esc['\''] = CharacterEscapes.ESCAPE_STANDARD;
+                       // esc['/'] = '/'; //CharacterEscapes.ESCAPE_CUSTOM;
+                       asciiEscapes = esc;
+               }
+
+               @Override
+               public int[] getEscapeCodesForAscii() {
+                       return asciiEscapes;
+               }
 
-    private static final String DEFAULT_TYPING = "defaultTyping";
-    private static final String CACHE_FILTERS = "cacheFilters";
-    private static final String DATE_FORMAT = "dateFormat";
-    private static final String ESCAPE_CHARS = "escapeCharsGlobal";
-    private static final String ESCAPE_CHAR_CLASS = "escapeCharsClass";
-    private static final String USE_JSON_PATH = "useJsonPath";
-    ObjectMapper mapper;
-    AnnotationIntrospector primary; // support default
-    AnnotationIntrospector secondary;
-
-    private static final String ANNOTATIONINSPECTOR = "annotationInspectors";
-
-    private Map<String, String> annotationInspectors = null;
-    private Map<String, Boolean> features = null;
-    private Map<String, String> featureTypes = null;
-
-    private String dateFormat;
-
-    /**
-     * Default dateformat is <code>MM/dd/yyyy</code>, could be overwritten in 
{@link #setDateFormat(DateFormat)}.
-     */
-    public static final String DEFAULTDATEFORMAT = "MM/dd/yyyy";
-
-    private boolean cacheFilters = true; // true -> this is by default true in 
jackson, if not using
-                                        // multiple serialization in one thread
-    String[] defaultTypeDefs = null;
-    private CacheService cacheService;
-    private boolean escapeCharsGlobal = false; // to be backward compatible, 
but should be true, then escaping to avoid XSS payload by default
-    private boolean useJsonPath = false;
-    private String escapeCharsClass = null;
-
-    @Override
-    public String ser(Object src) throws Exception {
-        return ser(src, false);
-    }
-
-    @Override
-    public <T> String ser(Object src, Class<T> type) throws Exception {
-       return ser(src, type, false);
-    }
-
-    public String ser(Object src, FilterProvider filter) throws Exception {
-        return ser(src, filter, false);
-    }
-    
-    public String ser(Object src, FilterProvider filter, Boolean cleanCache) 
throws Exception {
-        String serResult= null;
-        if (src == null) {
-            getLogger().info("no serializable object.");
-            return serResult;
-        } 
-        if (filter == null) {
-            getLogger().debug("ser class::" + src.getClass() + " without 
filter."); 
-            return ser(src);
-        } else {
-            getLogger().debug("add filter for cache filter Class " + 
src.getClass().getName());
-            setCustomIntrospectorWithExternalFilterId(src.getClass(), null); 
// filter class
-            cacheService.getFilters().put(src.getClass().getName(), filter);   
 
-        }
-        getLogger().debug("ser class::" + src.getClass() + " with filter " + 
filter);
-        mapper.setFilterProvider(filter);
-        String res =  mapper.writer(filter).writeValueAsString(src);
-        if (cleanCache) {
-            cacheService.cleanSerializerCache(mapper);
-        }
-        return res;
-    }
-
-    @Override
-    public <T> T deSer(String json, Class<T> type) throws Exception {
-        ObjectReader reader = null;
-        if (type != null)
-            reader = mapper.readerFor(type);
-        else
-            reader = mapper.reader();
-
-        return reader.readValue(json);
-    }
-    
-    public <T> T deSer(Object src, Class<T> type) throws Exception {
-        return mapper.convertValue( src, type);
-    }
-    
-    public <T> Collection<T> deSerCollectionWithType(String json, Class<? 
extends Collection> collectionClass, Class<T> type)
-            throws Exception {
-        return mapper.readValue(json, mapper.getTypeFactory()
-                .constructCollectionType(collectionClass, type));
-    }
-    
-    public <T> String serCollectionWithTypeReference(Collection<T> src, 
TypeReference collectionType, Boolean cleanCache)
-            throws Exception {
-        String res =  mapper.writerFor(collectionType).writeValueAsString(src);
-        if (cleanCache) {
-            cacheService.cleanSerializerCache(mapper);
-        }
-        return res;
-    }
-    
-    @Override
-    public <T> Collection<T> deSerCollection(String json,
-            Object collectionType, Class<T> elementType) throws Exception {
-        if (collectionType instanceof TypeReference) {
-            return mapper.readValue(json, (TypeReference<T>)collectionType);
-        } else {
-            return mapper.readValue(json, mapper.getTypeFactory()
-                    
.constructCollectionType(((Collection<T>)collectionType).getClass(), 
elementType));         
-        }
-    }
-    
-    public <T> List<T> deSerList(String json, Class<? extends List> 
targetList, Class<T> elementType) throws Exception {
-        return mapper.readValue(json, 
mapper.getTypeFactory().constructParametricType(targetList,elementType));       
 
-    }
-    
-    public <T,U> Map<T,U> deSerMap(String json, Class<? extends Map> mapClass, 
Class<T> keyClass, Class<U> valueClass) throws Exception {
-        return mapper.readValue(json, 
mapper.getTypeFactory().constructMapType(mapClass, keyClass, valueClass));      
  
-    }
-    
-    public <T> Collection<T> deSerCollectionWithTypeReference(String json,
-            TypeReference<T> collectionType ) throws Exception {
-            return mapper.readValue(json, collectionType);
-    }
-
-    /**
-     * @param name name of the module
-     * @param target target class
-     * @param mixin provide mixin as class. 
-     *      Deregistering module could be only done by setting this parameter 
to null.
-     * 
-     * @see #addAdapter(String, Class, Object)
-     */
-    @Override
-    public JsonService addAdapter(String name, Class target, Class mixin)
-            throws Exception {
-        getLogger().debug("registering unversioned simple mixin module named " 
+ name + " of type " + mixin + "  for: " + target);
-        mapper.addMixIn(target, mixin);
-        return this;
-    }
-
-    /**
-     * Add a named module or a {@link Module}.
-     * 
-     * @param name Name of the module, optional. Could be null, if module is a 
 {@link Module}.
-     * 
-     * @param target Target class, optional. Could be null, if module is a  
{@link Module}.
-     * 
-     * @param module
-     *            Either an Jackson Module @link {@link Module} or an custom
-     *            wrapper @link CustomModuleWrapper. 
-     * 
-     * @see JsonService#addAdapter(String, Class, Object)
-     */
-    @Override
-    public JsonService addAdapter(String name, Class target, Object module)
-            throws Exception {
-        if (module instanceof CustomModuleWrapper) {
-            CustomModuleWrapper cmw = (CustomModuleWrapper) module;
-            Module cm = new CustomModule(name, target, cmw.getSer(),
-                    cmw.getDeSer());
-            getLogger().debug("registering custom module " + cm + "  for: " + 
target);
-            mapper.registerModule(cm);
-        } else if (module instanceof Module) {
-            getLogger().debug(
-                    "registering module " + module );
-            mapper.registerModule((Module) module);
-        } else {
-            throw new Exception("expecting module type" + Module.class);
-        }
-        return this;
-    }
-    
-    /**
-     * set a single mixin. convenience method, calls {@link 
ObjectMapper#registerModule(Module)}.
-     * 
-     * @param src the object to be serialized
-     * @param name the name for the mixin
-     * @param target the target class for the mixin
-     * @param mixin the mixin class
-     * @return serialized result
-     * @throws JsonProcessingException
-     */
-    @SuppressWarnings("rawtypes")
-    public String withMixinModule(Object src, String name, Class target,
-            Class mixin) throws JsonProcessingException {
-        Module mx = new MixinModule(name, target, mixin);
-        getLogger().debug("registering module " + mx + ", mixin: " + mixin);
-        return mapper.registerModule(mx).writer().writeValueAsString(src);
-    }
-    
-    /**
-     * convenience method with read (but old mixins will be cleared!).
-     * 
-     * @see  {@link ObjectMapper#setMixins(Class, Class)}
-     * 
-     * @param src the object to be serialized
-     * @param target the target class for the mixin
-     * @param mixin the mixin class
-     * @return serialized result
-     * @throws JsonProcessingException
-     */
-    @SuppressWarnings("rawtypes")
-    public String withSetMixins(Object src, Class target,
-              Class mixin) throws JsonProcessingException {
-        return setMixins(target, mixin).writer().writeValueAsString(src);
-    }
-    
-    @SuppressWarnings("rawtypes")
-    public ObjectMapper setMixins(Class target,
-              Class mixin) {
-        Map<Class<?>, Class<?>> sourceMixins = null;
-        if (target != null) {
-            sourceMixins = new HashMap<>(1);
-            sourceMixins.put( target,mixin );   
-        }
-        getLogger().debug("clean set mixins for target " + target + ", mixin: 
" + mixin);
-        return mapper.setMixIns( sourceMixins );
-    }
-    
-    @Override
-    public String serializeAllExceptFilter(Object src, String... filterAttr)
-            throws Exception {
-        return serializeAllExceptFilter(src, src.getClass(), true, filterAttr);
-    }
-    
-    @Override
-    public synchronized String serializeAllExceptFilter(Object src, Boolean 
cache, String... filterAttr) throws Exception {
-        return serializeAllExceptFilter(src, src.getClass(), cache, 
filterAttr);
-    }
-    
-    public synchronized <T> String serializeAllExceptFilter(Object src,
-            Class<T>[] filterClasses, String... filterAttr) throws Exception {
-        return serializeAllExceptFilter(src, filterClasses, true, filterAttr);
-    }
-    
-    @Override
-    public synchronized <T> String serializeAllExceptFilter(Object src,
-            Class<T> filterClass, String... filterAttr) throws Exception {
-        return serializeAllExceptFilter(src, filterClass, true, filterAttr);
-    }
-    
-    @Override
-    public <T> String serializeAllExceptFilter(Object src,
-            Class<T> filterClass, Boolean cleanFilter, String... filterAttr)
-            throws Exception {
-        return serializeAllExceptFilter(src, new Class[] {filterClass}, 
cleanFilter, filterAttr);
-    }
-    
-    /**
-     * 
-     * @param src  the object to be serailized, may be a list
-     * @param filterClasses the same object class or a detail class, which 
should be filtered
-     * @param clean cleaning the cache after serialization
-     * @param filterAttr attributes to be filtered for filtered class
-     * @return the serailized string
-     * @throws Exception
-     */
-    public synchronized <T> String serializeAllExceptFilter(Object src,
-            Class<T>[] filterClasses, Boolean clean, String... filterAttr) 
throws Exception {
-        PropertyFilter pf = null;
-        if (filterAttr != null)
-            pf = SimpleBeanPropertyFilter.serializeAllExcept(filterAttr);
-        else if (filterClasses == null) { //no filter
-            return ser(src, clean); 
-            // should be better: 
-             //return filter(src, new Class<?>[] { src.getClass() }, 
filterClasses, pf, clean);
-        }
-        return filter(src, new Class<?>[] { filterClasses[0] }, filterClasses, 
pf, clean);
-    }
-    
-    @Override
-    public String serializeOnlyFilter(Object src, String... filterAttrs)
-            throws Exception {
-        return serializeOnlyFilter(src, src.getClass(), true, filterAttrs);
-    }
-    
-    @Override
-    public synchronized String serializeOnlyFilter(Object src,
-             Boolean cache, String... filterAttr) throws Exception {
-        return serializeOnlyFilter(src, src.getClass(), cache, filterAttr);
-    }
-    
-    @Override
-    public synchronized <T> String serializeOnlyFilter(Object src,
-            Class<T> filterClass,  String... filterAttr) throws Exception {
-        return serializeOnlyFilter(src, filterClass, true, filterAttr);
-    }
-
-    @Override
-    public synchronized <T> String serializeOnlyFilter(Object src,
-            Class<T> filterClass, Boolean refresh, String... filterAttr) 
throws Exception {
-        return serializeOnlyFilter(src, new Class[]{ filterClass }, refresh, 
filterAttr);
-    }
-    
-    
-    public synchronized <T> String serializeOnlyFilter(Object src,
-            Class<T>[] filterClasses, Boolean refresh, String... filterAttr) 
throws Exception {
-        PropertyFilter pf = null;
-        if (filterAttr != null && filterAttr.length > 0 && ! 
"".equals(filterAttr[0]) ) {
-            pf = SimpleBeanPropertyFilter.filterOutAllExcept(filterAttr);
-            getLogger().debug("setting filteroutAllexcept filter for size of 
filterAttr: " + filterAttr.length);
-        } else {
-            getLogger().warn("no filter attributes set!");
-            pf = SimpleBeanPropertyFilter.filterOutAllExcept("dummy");
-        }
-        if (filterClasses == null) throw new Exception("You have to provide 
some class to apply the filtering!");
-        return filter(src, filterClasses, null, pf, refresh);
-    }
-    
-    @Override
-    public String ser(Object src, Boolean cleanCache) throws Exception {
-        if (cacheService.getFilters().containsKey(src.getClass().getName())) {
-            getLogger().warn(
-                    "Found registered filter - using instead of default view 
filter for class:"
-                            + src.getClass().getName());
-            SimpleFilterProvider filter = (SimpleFilterProvider) 
cacheService.getFilters().get(src.getClass()
-                    .getName());
-            return ser(src, filter, 
cleanCache);//mapper.writerWithView(src.getClass()).writeValueAsString(src);
-        }
-        String res = 
mapper.writerWithView(Object.class).writeValueAsString(src);
-        if (cleanCache != null && cleanCache) {
-            cacheService.cleanSerializerCache(mapper);
-        }
-        return res;
-    }
-
-    @Override
-    public <T> String ser(Object src, Class<T> type, Boolean cleanCache)
-            throws Exception {
-        getLogger().info("serializing object:" + src + " for type "+ type);
-        if (src != null && 
cacheService.getFilters().containsKey(src.getClass().getName())) {
-            getLogger()
-                    .warn("Found registered filter - could not use custom view 
and custom filter for class:"
-                            + src.getClass().getName());
-            // throw new
-            // Exception("Found registered filter - could not use custom view 
and custom filter for class:"+
-            // src.getClass().getName());
-            SimpleFilterProvider filter = (SimpleFilterProvider) 
cacheService.getFilters().get(src.getClass()
-                    .getName());
-            return ser(src, filter);
-        }
-
-        String res = (type != null)? 
mapper.writerWithView(type).writeValueAsString(src): 
mapper.writeValueAsString(src);
-        if (cleanCache) {
-            cacheService.cleanSerializerCache(mapper);
-        }
-        return res;
-    }  
-
-    /**
-     * 
-     * @param src The source Object to be filtered.
-     * @param filterClass This Class array contains at least one element. If 
no class is provided it is the class type of the source object. 
-     * The filterClass is to become the key of the filter object cache.
-     * @param excludeClasses The classes to be excluded, optionally used only 
for methods like {@link #serializeAllExceptFilter(Object, Class[], String...)}.
-     * @param pf Expecting a property filter from e.g @link {@link 
SimpleBeanPropertyFilter}.
-     * @param clean if <code>true</code> does not reuse the filter object (no 
cashing).  
-     * @return The serialized Object as String 
-     * @throws Exception
-     */
-    private <T> String filter(Object src, Class<?>[] filterClasses, Class<T>[] 
excludeClasses,
-            PropertyFilter pf,  Boolean clean) throws Exception {
-        FilterProvider filter = null;
-        if (filterClasses.length >0) {
-            filter = retrieveFilter(pf, filterClasses[0], excludeClasses);
-        } 
-        getLogger().info("filtering with filter "+ filter);
-        String serialized = ser(src, filter, clean);
-        if (!cacheFilters || clean) {
-            if (filterClasses.length >0) {
-                boolean exclude = (excludeClasses !=null)? true:false;
-                cacheService.removeFilter(filterClasses[0],exclude);
-            }  
-        }
-        return serialized;
-    }
-    
-    private <T> SimpleFilterProvider retrieveFilter(PropertyFilter pf, 
Class<?> filterClass, 
-            Class<T>[] excludeClasses ) {
-        SimpleFilterProvider filter = null;
-        if (pf != null) {
-            filter = new SimpleFilterProvider();
-            filter.setDefaultFilter(pf);
-        }
-        if (!cacheService.getFilters().containsKey(filterClass.getName())) {
-            getLogger().debug("add filter for cache filter Class " + 
filterClass.getName());
-            setCustomIntrospectorWithExternalFilterId(filterClass, 
excludeClasses); // filter class
-            if (pf != null)  {
-                cacheService.getFilters().put(filterClass.getName(), filter);  
  
-            } 
-        } else {
-            filter = 
(SimpleFilterProvider)cacheService.getFilters().get(filterClass
-                    .getName());
-            //setCustomIntrospectorWithExternalFilterId(filterClass); // filter
-            // class
-        }
-        getLogger().debug("set filter:"+ filter);
-        return filter; 
-    }
-
-    /**
-     * @param filterClass <li>Adding filterClass into {@link 
SimpleNameIntrospector#setFilteredClass(Class)} enables the filtering process.
-     * @param externalFilterIds <li>Adding externalFilterIs to {@link 
SimpleNameIntrospector#setExternalFilterExcludeClasses(Class...)} excludes 
these classes.
-     */
-    private <T> void setCustomIntrospectorWithExternalFilterId(Class<?> 
filterClass,
-            Class<T>[] externalFilterClassIds) {
-        if (primary instanceof SimpleNameIntrospector) {
-            // first one is required that we get to the PropertyFilter 
-            ((SimpleNameIntrospector) primary).setFilteredClasses(filterClass);
-            if (externalFilterClassIds != null) {
-                ((SimpleNameIntrospector) primary).setIsExludeType(true);
-                for (Class<T> filterClazz : externalFilterClassIds) {
-                    getLogger().debug("added class for filters "
-                            + filterClazz);                    
-                }
-                ((SimpleNameIntrospector) 
primary).setExternalFilterExcludeClasses(externalFilterClassIds);
-            }
-        }
-    }
-
-    public Jackson2MapperService registerModule(Module module) {
-        mapper.registerModule(module);
-        return this;
-    }
-
-    public <T> void addSimpleModule(SimpleModule module, Class<T> type,
-            JsonSerializer<T> ser) {
-        module.addSerializer(type, ser);
-    }
-
-    public <T> void addSimpleModule(SimpleModule module, Class<T> type,
-            JsonDeserializer<T> deSer) {
-        module.addDeserializer(type, deSer);
-    }
-
-    /**
-     * Default Dateformat: {@link #DEFAULTDATEFORMAT}
-     */
-    @Override
-    public void setDateFormat(final DateFormat df) {
-        mapper.setDateFormat(df);
-    }
-
-    /**
-     * Avalon component lifecycle method
-     */
-    @Override
-    public void configure(Configuration conf) throws ConfigurationException {
-        getLogger().debug("conf.getName()" + conf.getName());
-        this.annotationInspectors = new HashMap<>();
-
-        final Configuration configuredAnnotationInspectors = conf.getChild(
-                ANNOTATIONINSPECTOR, false);
-        
-        if (configuredAnnotationInspectors != null) {
-            Configuration[] nameVal = configuredAnnotationInspectors
-                    .getChildren();
-            for (int i = 0; i < nameVal.length; i++) {
-                String key = nameVal[i].getName();
-                getLogger().debug("configured key: " + key);
-                if (key.equals("features")) {
-                    this.features = new HashMap<>();
-                    this.featureTypes = new HashMap<>();
-                    Configuration[] localFeatures = nameVal[i].getChildren();
-                    for (int j = 0; j < localFeatures.length; j++) {
-                        boolean featureValue = localFeatures[j]
-                                .getAttributeAsBoolean("value", false);
-                        String featureType = 
localFeatures[j].getAttribute("type");
-                        String feature = localFeatures[j].getValue();
-                        getLogger().debug(
-                                "configuredAnnotationInspectors " + feature
-                                        + ":" + featureValue);
-                        this.features.put(feature, featureValue);
-                        this.featureTypes.put(feature, featureType);
-                    }
-                } else {
-                    String val = nameVal[i].getValue();
-                    getLogger()
-                            .debug("configuredAnnotationInspectors " + key
-                                    + ":" + val);
-                    this.annotationInspectors.put(key, val);
-                }
-            }
-        }
-        final Configuration configuredDateFormat = conf.getChild(DATE_FORMAT,
-                true);
-        this.dateFormat = configuredDateFormat.getValue(DEFAULTDATEFORMAT);
-
-        final Configuration configuredKeepFilter = conf.getChild(CACHE_FILTERS,
-                false);
-        if (configuredKeepFilter != null) {
-            this.cacheFilters = configuredKeepFilter.getValueAsBoolean();
-        }
-        final Configuration configuredEscapeChars = conf.getChild(ESCAPE_CHARS,
-                false);
-        if (configuredEscapeChars != null) {
-            this.escapeCharsGlobal  = 
configuredEscapeChars.getValueAsBoolean();
-        }
-        final Configuration configuredEscapeCharClass = 
conf.getChild(ESCAPE_CHAR_CLASS,
-                false);
-        if (configuredEscapeCharClass != null) {
-            this.escapeCharsClass  = configuredEscapeCharClass.getValue();
-        }
-        
-        final Configuration configuredDefaultType = conf.getChild(
-                DEFAULT_TYPING, false);
-        if (configuredDefaultType != null) {
-            defaultTypeDefs = new String[] {
-                    configuredDefaultType.getAttribute("type"),
-                    configuredDefaultType.getAttribute("key") };
-        }
-        final Configuration configuredjsonPath = conf.getChild(
-                USE_JSON_PATH, false);
-        if (configuredjsonPath != null) {
-            this.useJsonPath  = configuredjsonPath.getValueAsBoolean();
-        }
-    }
-
-    @Override
-    public void initialize() throws Exception {
-        mapper = new ObjectMapper(null, null, null);// add configurable 
JsonFactory,.. later?
-
-        initAnnotationInspectors();
-
-        initFeatures();
-
-        initDefaultTyping();
-
-        getLogger().info("setting date format to:" + dateFormat);
-        getLogger().info("cacheFilters is:" + cacheFilters);
-        if (!cacheFilters) {
-            mapper.configure(SerializationFeature.FLUSH_AFTER_WRITE_VALUE, 
true);
-        }
-
-        mapper.setDateFormat(new SimpleDateFormat(dateFormat));
-        
-        if (escapeCharsGlobal) {
-            mapper.getFactory().setCharacterEscapes(characterEscapes);
-        }
-        if (escapeCharsClass != null) {
-            try {
-                characterEscapes = (CharacterEscapes) 
Class.forName(escapeCharsClass).getConstructor()
-                        .newInstance();
-            } catch (Exception e) {
-                throw new Exception(
-                        "JsonMapperService: Error instantiating " + 
escapeCharsClass
-                                + " for " + ESCAPE_CHAR_CLASS );
-            }
-        }
-
-        getLogger().debug("initialized mapper:" + mapper);
-
-        mapper.getSerializerProvider().setNullValueSerializer(
-                new JsonSerializer<Object>() {
-                    @Override
-                    public void serialize(Object value, JsonGenerator jgen,
-                            SerializerProvider provider) throws IOException
-                             {
-                        jgen.writeString("");
-
-                    }
-                });
-        cacheService = new CacheService(primary);
-        if (cacheService instanceof LogEnabled)
-        {
-            
cacheService.enableLogging(getLogger().getChildLogger(cacheService.getClass().getSimpleName()));
-            getLogger().info(
-                    "setting cacheService logger: "
-                            + cacheService.getClass().getSimpleName());
-        }
-        
-        if (useJsonPath) {
-            // set it before runtime
-            DefaultJsonPathWrapper djpw = null;
-            try {
-                djpw = new DefaultJsonPathWrapper(this.mapper);
-                getLogger().debug("******** initialized new jsonPath defaults: 
" +djpw.getJsonPathDefault());
-            } catch (Exception e) {
-                throw new Exception(
-                        "JsonMapperService: Error instantiating " + djpw
-                                + " using useJsonPath=" + useJsonPath);
-            }
-
-        }
-    }
-
-    private void initDefaultTyping()
-    {
-        if (defaultTypeDefs != null && defaultTypeDefs.length == 2) {
-            DefaultTyping defaultTyping = DefaultTyping
-                    .valueOf(defaultTypeDefs[0]);
-            mapper.enableDefaultTypingAsProperty(defaultTyping,
-                    defaultTypeDefs[1]);
-            getLogger().info(
-                    "default typing is " + defaultTypeDefs[0] + " with key:"
-                            + defaultTypeDefs[1]);
-        }
-    }
-
-    private void initFeatures()
-        throws Exception
-    {
-        if (features != null && !features.isEmpty()) {
-            Iterator<String> featureKeys = features.keySet().iterator();
-            while (featureKeys.hasNext()) {
-                String featureKey = featureKeys.next();// e.g.
-                                                                 // 
FAIL_ON_EMPTY_BEANS
-                Boolean featureValue = features.get(featureKey); // e.g.false
-                String featureType = featureTypes.get(featureKey);
-                Class<?> configFeature = null;
-                try {
-                    getLogger().debug(
-                            "initializing featureType:  " + featureType);
-                    configFeature = Class.forName(featureType);
-                } catch (Exception e) {
-                    throw new Exception(
-                            "JsonMapperService: Error instantiating "
-                                    + featureType + " for " + featureKey,e);
-                }
-                ConfigFeature feature = null;
-                if (featureKey != null && featureValue != null) {
-                    try {
-                        if (configFeature.equals(SerializationFeature.class)) {
-                            feature = SerializationFeature.valueOf(featureKey);
-                            mapper.configure((SerializationFeature) feature,
-                                    featureValue);
-                            assert mapper.getSerializationConfig().isEnabled(
-                                    (SerializationFeature) feature) == 
featureValue;
-                            getLogger()
-                                    .info("initialized serconfig mapper 
feature: "
-                                            + feature
-                                            + " with "
-                                            + mapper.getSerializationConfig()
-                                                    .isEnabled(
-                                                            
(SerializationFeature) feature));
-                        } else if (configFeature
-                                .equals(DeserializationFeature.class)) {
-                            feature = DeserializationFeature
-                                    .valueOf(featureKey);
-                            mapper.configure((DeserializationFeature) feature,
-                                    featureValue);
-                            assert mapper.getDeserializationConfig().isEnabled(
-                                    (DeserializationFeature) feature) == 
featureValue;
-                            getLogger()
-                                    .info("initialized deserconfig mapper 
feature: "
-                                            + feature
-                                            + " with "
-                                            + mapper.getDeserializationConfig()
-                                                    .isEnabled(
-                                                            
(DeserializationFeature) feature));
-                        } else if (configFeature.equals(MapperFeature.class)) {
-                            feature = MapperFeature.valueOf(featureKey);
-                            mapper.configure((MapperFeature) feature,
-                                    featureValue);
-                            assert mapper.getDeserializationConfig().isEnabled(
-                                    (MapperFeature) feature) == featureValue;
-                            assert mapper.getSerializationConfig().isEnabled(
-                                    (MapperFeature) feature) == featureValue;
-                            getLogger()
-                                    .info("initialized serconfig mapper 
feature: "
-                                            + feature
-                                            + " with "
-                                            + mapper.getDeserializationConfig()
-                                                    .isEnabled(
-                                                            (MapperFeature) 
feature));
-                            getLogger()
-                                    .info("initialized deserconfig mapper 
feature: "
-                                            + feature
-                                            + " with "
-                                            + mapper.getSerializationConfig()
-                                                    .isEnabled(
-                                                            (MapperFeature) 
feature));
-                        } else if (configFeature.equals(JsonParser.class)) {
-                            Feature parserFeature = 
JsonParser.Feature.valueOf(featureKey);
-                            getLogger()
-                            .info("initializing parser feature: "
-                                    + parserFeature
-                                    + " with "
-                                    + featureValue);
-                            mapper.configure(parserFeature,
-                                    featureValue);
-                        } else if (configFeature.equals(JsonGenerator.class)) {
-                            com.fasterxml.jackson.core.JsonGenerator.Feature 
genFeature = JsonGenerator.Feature.valueOf(featureKey);
-                            getLogger()
-                            .info("initializing parser feature: "
-                                    + genFeature
-                                    + " with "
-                                    + featureValue);
-                            mapper.configure(genFeature,
-                                    featureValue);
-                        }
-                    } catch (Exception e) {
-                        throw new Exception(
-                                "JsonMapperService: Error instantiating 
feature "
-                                        + featureKey + " with  " + 
featureValue,
-                                e);
-                    }
-                }
-            }
-        }
-    }
-
-    private void initAnnotationInspectors()
-        throws Exception
-    {
-        Iterator<String> aiKeys = annotationInspectors.keySet().iterator();
-        while (aiKeys.hasNext()) {
-            String key = aiKeys.next();
-            String avClass = annotationInspectors.get(key);
-            if (key.equals("primary") && avClass != null) {
-                try {
-                    primary = (AnnotationIntrospector) 
Class.forName(avClass).getConstructor()
-                            .newInstance();
-                } catch (Exception e) {
-                    throw new Exception(
-                            "JsonMapperService: Error instantiating " + avClass
-                                    + " for " + key);
-                }
-            } else if (key.equals("secondary") && avClass != null) {
-                try {
-                    secondary = (AnnotationIntrospector) 
Class.forName(avClass).getConstructor()
-                            .newInstance();
-                } catch (Exception e) {
-                    throw new Exception(
-                            "JsonMapperService: Error instantiating " + avClass
-                                    + " for " + key);
-                }
-            }
-        }
-        if (primary == null) {
-            primary = new JacksonAnnotationIntrospector(); // support default
-            getLogger().info(
-                    "using default introspector:"
-                            + primary.getClass().getName());
-            mapper.setAnnotationIntrospector(primary);
-        } else if (primary != null && secondary != null){
-            AnnotationIntrospector pair = new AnnotationIntrospectorPair(
-                    primary, secondary);
-            mapper.setAnnotationIntrospector(pair);
-        } else {
-            mapper.setAnnotationIntrospector(primary);
-        }
-        
-        if (primary instanceof LogEnabled)
-        {
-            
((LogEnabled)primary).enableLogging(getLogger().getChildLogger(primary.getClass().getSimpleName()));
-            getLogger().info(
-                    "setting primary introspector logger: "
-                            + primary.getClass().getSimpleName());
-        }
-        if (secondary instanceof LogEnabled)
-        {
-            
((LogEnabled)secondary).enableLogging(getLogger().getChildLogger(secondary.getClass().getSimpleName()));
-            getLogger().info(
-                    "setting secondary introspector logger: "
-                            + secondary.getClass().getSimpleName());
-        }
-    }
-    
-    public ObjectMapper getMapper() {
-        return mapper;
-    }
-
-    public void setMapper(ObjectMapper mapper) {
-        this.mapper = mapper;
-    }
-
-    public boolean isCacheFilters() {
-        return cacheFilters;
-    }
-
-    public void setCacheFilters(boolean cacheFilters) {
-        this.cacheFilters = cacheFilters;
-        if (!cacheFilters)
-            mapper.configure(SerializationFeature.FLUSH_AFTER_WRITE_VALUE, 
true);
-    }
-    
-    static CharacterEscapes characterEscapes = new CharacterEscapes() {
-        private static final long serialVersionUID = 1L;
-        private final int[] asciiEscapes;
-         { // instance init
-            int[] esc = standardAsciiEscapesForJSON();
-            // this avoids to get evaluated immediately
-            esc['<'] = CharacterEscapes.ESCAPE_STANDARD;
-            esc['>'] = CharacterEscapes.ESCAPE_STANDARD;
-            esc['&'] = CharacterEscapes.ESCAPE_STANDARD;
-            esc['\''] = CharacterEscapes.ESCAPE_STANDARD;
-            //esc['/'] = '/'; //CharacterEscapes.ESCAPE_CUSTOM;
-            asciiEscapes = esc;
-        }
-        @Override
-        public int[] getEscapeCodesForAscii() {
-            return asciiEscapes;
-        }
-        @Override
-        public SerializableString getEscapeSequence(final int ch) {
+               @Override
+               public SerializableString getEscapeSequence(final int ch) {
 //            if ( ch == '/') { 
 //                return new SerializedString("\\\\/");
 //            } else {
-                return null;
+                       return null;
 //            }
-        }
-    };
+               }
+       };
 }

Modified: 
turbine/fulcrum/trunk/json/jackson2/src/java/org/apache/fulcrum/json/jackson/filters/CustomModuleWrapper.java
URL: 
http://svn.apache.org/viewvc/turbine/fulcrum/trunk/json/jackson2/src/java/org/apache/fulcrum/json/jackson/filters/CustomModuleWrapper.java?rev=1845825&r1=1845824&r2=1845825&view=diff
==============================================================================
--- 
turbine/fulcrum/trunk/json/jackson2/src/java/org/apache/fulcrum/json/jackson/filters/CustomModuleWrapper.java
 (original)
+++ 
turbine/fulcrum/trunk/json/jackson2/src/java/org/apache/fulcrum/json/jackson/filters/CustomModuleWrapper.java
 Mon Nov  5 17:43:51 2018
@@ -29,29 +29,49 @@ import com.fasterxml.jackson.databind.se
  * 
  * @author gkallidis
  *
- * @param <T>
+ * @param <T> the class to wrap
  */
 public class CustomModuleWrapper<T> {
-    StdSerializer<T> ser;
-    StdDeserializer<T> deSer;
+       
+       // serializer and deserializer objects
+    StdSerializer<T> ser = null;
+    StdDeserializer<T> deSer = null;
 
+    /**
+     * Constructor for the custom module wrapper
+     * 
+     * @param ser the standard serializer
+     * @param deSer the standard de-serializer
+     */
     public CustomModuleWrapper(StdSerializer<T> ser, StdDeserializer<T> deSer) 
{
         this.ser = ser;
         this.deSer = deSer;
     }
 
+    /**
+     * @return the serializer
+     */
     public StdSerializer<T> getSer() {
         return ser;
     }
 
+    /**
+     * @param ser set the standard serializer
+     */
     public void setSer(StdSerializer<T> ser) {
         this.ser = ser;
     }
 
+    /**
+     * @return the de-serializer in use
+     */
     public StdDeserializer<T> getDeSer() {
         return deSer;
     }
 
+    /**
+     * @param deSer standard deserializer
+     */
     public void setDeSer(StdDeserializer<T> deSer) {
         this.deSer = deSer;
     }


Reply via email to