All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.codehaus.jackson.map.ser.SerializerCache Maven / Gradle / Ivy

Go to download

Data Mapper package is a high-performance data binding package built on Jackson JSON processor

There is a newer version: 1.9.13
Show newest version
package org.codehaus.jackson.map.ser;

import java.util.*;

import org.codehaus.jackson.type.JavaType;
import org.codehaus.jackson.map.JsonSerializer;

/**
 * Simple cache object that allows for doing 2-level lookups: first level is
 * by "local" read-only lookup Map (used without locking)
 * and second backup level is by a shared modifiable HashMap.
 * The idea is that after a while, most serializers are found from the
 * local Map (to optimize performance, reduce lock contention),
 * but that during buildup we can use a shared map to reduce both
 * number of distinct read-only maps constructed, and number of
 * serializers constructed.
 *

* Since version 1.5 cache will actually contain three kinds of entries, * based on combination of class pair key. First class in key is for the * type to serialize, and second one is type used for determining how * to resolve value type. One (but not both) of entries can be null. */ public final class SerializerCache { /** * Shared, modifiable map; all access needs to be through synchronized blocks. *

* NOTE: keys are of various types (see below for key types), in addition to * basic {@link JavaType} used for "untyped" serializers. */ private HashMap> _sharedMap = new HashMap>(64); /** * Most recent read-only instance, created from _sharedMap, if any. */ private ReadOnlyClassToSerializerMap _readOnlyMap = null; public SerializerCache() { } /** * Method that can be called to get a read-only instance populated from the * most recent version of the shared lookup Map. */ public ReadOnlyClassToSerializerMap getReadOnlyLookupMap() { ReadOnlyClassToSerializerMap m; synchronized (this) { m = _readOnlyMap; if (m == null) { _readOnlyMap = m = ReadOnlyClassToSerializerMap.from(_sharedMap); } } return m.instance(); } /** * Method that checks if the shared (and hence, synchronized) lookup Map might have * untyped serializer for given type. */ public JsonSerializer untypedValueSerializer(Class type) { synchronized (this) { return _sharedMap.get(new UntypedKeyRaw(type)); } } /** * @since 1.5 */ public JsonSerializer untypedValueSerializer(JavaType type) { synchronized (this) { return _sharedMap.get(type); } } public JsonSerializer typedValueSerializer(JavaType type) { synchronized (this) { return _sharedMap.get(new TypedKeyFull(type)); } } public JsonSerializer typedValueSerializer(Class cls) { synchronized (this) { return _sharedMap.get(new TypedKeyRaw(cls)); } } /** * Method called if none of lookups succeeded, and caller had to construct * a serializer. If so, we will update the shared lookup map so that it * can be resolved via it next time. */ public void addTypedSerializer(JavaType type, JsonSerializer ser) { synchronized (this) { if (_sharedMap.put(new TypedKeyFull(type), ser) == null) { // let's invalidate the read-only copy, too, to get it updated _readOnlyMap = null; } } } public void addTypedSerializer(Class cls, JsonSerializer ser) { synchronized (this) { if (_sharedMap.put(new TypedKeyRaw(cls), ser) == null) { // let's invalidate the read-only copy, too, to get it updated _readOnlyMap = null; } } } public void addNonTypedSerializer(Class type, JsonSerializer ser) { synchronized (this) { if (_sharedMap.put(new UntypedKeyRaw(type), ser) == null) { // let's invalidate the read-only copy, too, to get it updated _readOnlyMap = null; } } } /** * @since 1.5 */ public void addNonTypedSerializer(JavaType type, JsonSerializer ser) { synchronized (this) { if (_sharedMap.put(type, ser) == null) { // let's invalidate the read-only copy, too, to get it updated _readOnlyMap = null; } } } /** * @since 1.4 */ public synchronized int size() { return _sharedMap.size(); } public synchronized void flush() { _sharedMap.clear(); } /* /************************************************************** /* Helper class(es) /************************************************************** */ /** * Key object used for "typed" serializers (type serializer wrapping * value serializer). These are only used * for root-level (and similar) access. */ public final static class TypedKeyRaw { Class _type; int _hashCode; public TypedKeyRaw(Class cls) { reset(cls); } public void reset(Class cls) { _type = cls; _hashCode = cls.getName().hashCode(); } @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (o.getClass() != getClass()) return false; return ((TypedKeyRaw) o)._type == _type; } @Override public int hashCode() { return _hashCode; } } public final static class TypedKeyFull { JavaType _type; public TypedKeyFull(JavaType type) { _type = type; } public void reset(JavaType type) { _type = type; } @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (o.getClass() != getClass()) return false; return ((TypedKeyFull) o)._type.equals(_type); } @Override public int hashCode() { return _type.hashCode(); } } public final static class UntypedKeyRaw { Class _type; int _hashCode; public UntypedKeyRaw(Class cls) { reset(cls); } public void reset(Class cls) { _type = cls; _hashCode = cls.getName().hashCode(); } @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (o.getClass() != getClass()) return false; return ((UntypedKeyRaw) o)._type == _type; } @Override public int hashCode() { return _hashCode; } } }