Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
// ***************************************************************************************************************************
// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance *
// * with the License. You may obtain a copy of the License at *
// * *
// * http://www.apache.org/licenses/LICENSE-2.0 *
// * *
// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an *
// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the *
// * specific language governing permissions and limitations under the License. *
// ***************************************************************************************************************************
package org.apache.juneau;
import static org.apache.juneau.BeanContext.*;
import static org.apache.juneau.internal.ClassUtils.*;
import static org.apache.juneau.internal.StringUtils.*;
import java.lang.reflect.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.locks.*;
import org.apache.juneau.internal.*;
import org.apache.juneau.json.*;
import org.apache.juneau.parser.*;
/**
* A store for instantiating {@link Context} objects.
*
*
* The hierarchy of these objects are...
*
*
* {@link PropertyStore} - A thread-safe, modifiable context property store.
* Used to create {@link Context} objects.
*
* {@link Context} - A reusable, cacheable, thread-safe, read-only context with configuration properties copied
* from the store.
* Often used to create {@link Session} objects.
*
* {@link Session} - A one-time-use non-thread-safe object.
* Used by serializers and parsers to retrieve context properties and to be used as scratchpads.
*
*
*
PropertyStore objects
*
* Property stores can be thought of as consisting of the following:
*
*
A Map<String,Object> of context properties.
*
A Map<Class,Context> of context instances.
*
*
*
* Property stores are used to create and cache {@link Context} objects using the {@link #getContext(Class)} method.
*
*
* As a general rule, {@link PropertyStore} objects are 'slow'.
* Setting and retrieving properties on a store can involve relatively slow data conversion and synchronization.
* However, the {@link #getContext(Class)} method is fast, and will return cached context objects if the context
* properties have not changed.
*
*
* Property stores can be used to store context properties for a variety of contexts.
* For example, a single store can store context properties for the JSON serializer, XML serializer, HTML serializer
* etc... and can thus be used to retrieve context objects for those serializers.
*
*
Context properties
*
* Context properties are 'settings' for serializers and parsers.
* For example, the {@link BeanContext#BEAN_sortProperties} context property defines whether bean properties should be
* serialized in alphabetical order.
*
*
* Each {@link Context} object should contain the context properties that apply to it as static fields
* (e.g {@link BeanContext#BEAN_sortProperties}).
*
*
* Context properties can be of the following types:
*
*
* SIMPLE - A simple property.
* Examples include: booleans, integers, Strings, Classes, etc...
* An example of this would be the {@link BeanContext#BEAN_sortProperties} property.
* It's name is simply "BeanContext.sortProperties".
*
* SET - A sorted set of objects.
* These are denoted by appending ".set" to the property name.
* Objects can be of any type, even complex types.
* Sorted sets use tree sets to maintain the value in alphabetical order.
* For example, the {@link BeanContext#BEAN_notBeanClasses} property is used to store classes that should not be
* treated like beans.
* It's name is "BeanContext.notBeanClasses.set".
*
* LIST - A list of unique objects.
* These are denoted by appending ".list" to the property name.
* Objects can be of any type, even complex types.
* Use lists if the ordering of the values in the set is important (similar to how the order of entries in a
* classpath is important).
* For example, the {@link BeanContext#BEAN_beanFilters} property is used to store bean filters.
* It's name is "BeanContext.transforms.list".
*
* MAP - A sorted map of key-value pairs.
* These are denoted by appending ".map" to the property name.
* Keys can be any type directly convertible to and from Strings.
* Values can be of any type, even complex types.
* For example, the {@link BeanContext#BEAN_implClasses} property is used to specify the names of implementation
* classes for interfaces.
* It's name is "BeanContext.implClasses.map".
*
*
*
* All context properties are set using the {@link #setProperty(String, Object)} method.
*
*
* Default values for context properties can be specified globally as system properties.
* Example: System.setProperty(BEAN_sortProperties, true);
*
*
* SET and LIST properties can be added to using the {@link #addToProperty(String, Object)} method and removed from
* using the {@link #removeFromProperty(String, Object)} method.
*
*
* SET and LIST properties can also be added to and removed from by appending ".add" or ".remove" to
* the property name and using the {@link #setProperty(String, Object)} method.
*
*
* The following shows the two different ways to append to a set or list property:
*
* PropertyStore ps = new PropertyStore().setProperty("BeanContext.notBeanClasses.set",
* Collections.emptySet());
*
* // Append to set property using addTo().
* ps.addToProperty("BeanContext.notBeanClasses.set", MyNotBeanClass.class);
*
* // Append to set property using set().
* ps.setProperty("BeanContext.notBeanClasses.set.add", MyNotBeanClass.class);
*
*
*
* SET and LIST properties can also be set and manipulated using JSON strings.
*
* PropertyStore ps = PropertyStore.create();
*
* // Set SET value using JSON array.
* ps.setProperty("BeanContext.notBeanClasses.set", "['com.my.MyNotBeanClass1']");
*
* // Add to SET using simple string.
* ps.addToProperty("BeanContext.notBeanClasses.set", "com.my.MyNotBeanClass2");
*
* // Add an array of values as a JSON array..
* ps.addToProperty("BeanContext.notBeanClasses.set", "['com.my.MyNotBeanClass3']");
*
* // Remove an array of values as a JSON array..
* ps.removeFromProperty("BeanContext.notBeanClasses.set", "['com.my.MyNotBeanClass3']");
*
*
*
* MAP properties can be added to using the {@link #putToProperty(String, Object, Object)} and
* {@link #putToProperty(String, Object)} methods.
* MAP property entries can be removed by setting the value to null
* (e.g. putToProperty("BEAN_implClasses", MyNotBeanClass.class, null);.
* MAP properties can also be added to by appending ".put" to the property name and using the
* {@link #setProperty(String, Object)} method.
*
*
* The following shows the two different ways to append to a set property:
*
* PropertyStore ps = PropertyStore.create().setProperty("BeanContext.implClasses.map",
* Collections.emptyMap());
*
* // Append to map property using putTo().
* ps.putToProperty("BeanContext.implClasses.map", MyInterface.class, MyInterfaceImpl.class);
*
* // Append to map property using set().
* Map m = new AMap().append(MyInterface.class,MyInterfaceImpl.class);
* ps.setProperty("BeanContext.implClasses.map.put", m);
*
*
*
* MAP properties can also be set and manipulated using JSON strings.
*
* PropertyStore ps = PropertyStore.create();
*
* // Set MAP value using JSON object.
* ps.setProperty("BeanContext.implClasses.map",
* "{'com.my.MyInterface1':'com.my.MyInterfaceImpl1'}");
*
* // Add to MAP using JSON object.
* ps.putToProperty("BeanContext.implClasses.map",
* "{'com.my.MyInterface2':'com.my.MyInterfaceImpl2'}");
*
* // Remove from MAP using JSON object.
* ps.putToProperty("BeanContext.implClasses.map", "{'com.my.MyInterface2':null}");
*
*
*
* Context properties are retrieved from this store using the following 3 methods:
*
*
* {@link #getProperty(String, Class, Object)} - Retrieve a SIMPLE or SET property converted to the specified
* class type.
*
* {@link #getMap(String, Class, Class, Map)} - Retrieve a MAP property with keys/values converted to the
* specified class types.
*
* {@link #getPropertyMap(String)} - Retrieve a map of all context properties with the specified prefix
* (e.g. "BeanContext" for {@link BeanContext} properties).
*
*
*
* As a general rule, only {@link Context} objects will use these read methods.
*
*
Context objects
*
* A Context object can be thought of as unmodifiable snapshot of a store.
* They should be 'fast' by avoiding synchronization by using final fields whenever possible.
* However, they MUST be thread safe.
*
*
* Context objects are created using the {@link #getContext(Class)} method.
* As long as the properties on a store have not been modified, the store will return a cached copy of a context.
*
* PropertyStore ps = PropertyStore.create();
*
* // Get BeanContext with default store settings.
* BeanContext bc = ps.getContext(BeanContext.class);
*
* // Get another one. This will be the same one.
* BeanContext bc2 = ps.getContext(BeanContext.class);
* assertTrue(bc1 == bc2);
*
* // Set a property.
* ps.setProperty(BEAN_sortProperties, true);
*
* // Get another one. This will be different!
* bc2 = f.getContext(BeanContext.class);
* assertFalse(bc1 == bc2);
*
*
*
Session objects
*
* Session objects are created through {@link Context} objects, typically through a createContext() method.
* Unlike context objects, they are NOT reusable and NOT thread safe.
* They are meant to be used one time and then thrown away.
* They should NEVER need to use synchronization.
*
*
* Session objects are also often used as scratchpads for information such as keeping track of call stack information
* to detect recursive loops when serializing beans.
*/
public final class PropertyStore {
// All configuration properties in this object.
// Keys are property prefixes (e.g. 'BeanContext').
// Values are maps containing properties for that specific prefix.
private Map properties = new ConcurrentSkipListMap();
// Context cache.
// This gets cleared every time any properties change on this object.
private final Map,Context> contexts = new ConcurrentHashMap,Context>();
// Global Context cache.
// Property stores that are the 'same' will use the same maps from this cache.
// 'same' means the context properties are all the same when converted to strings.
private static final ConcurrentHashMap,Context>>
globalContextCache = new ConcurrentHashMap,Context>>();
private ReadWriteLock lock = new ReentrantReadWriteLock();
private Lock rl = lock.readLock(), wl = lock.writeLock();
// Classloader used to instantiate Class instances.
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
// Parser to use to convert JSON strings to POJOs
ReaderParser defaultParser;
// Bean session for converting strings to POJOs.
private static BeanSession beanSession;
// Used to keep properties in alphabetical order regardless of whether
// they're not strings.
private static Comparator