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

org.nlab.xml.stream.factory.AbstractStaxCachedFactory Maven / Gradle / Ivy

package org.nlab.xml.stream.factory;


import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang3.Validate;


/**
 * @author nlabrot
 *
 * Factory aware of the following issue http://java.net/jira/browse/JAXP-68
 * JAXP RI has an issue on factory in a multithread context
 */
public abstract class AbstractStaxCachedFactory {

    private static final String WOODSTOX_FACTORY_PREFIX = "Wstx";

    private Map> factoriesMap = new ConcurrentHashMap>();


    protected T getOrCreateFactory(Object... properties) {
        Validate.isTrue(properties.length % 2 == 0);

        long key = createKey(properties);

        if (factoriesMap.containsKey(key) && factoriesMap.get(key).get() != null) {
            return factoriesMap.get(key).get();
        }

        T factory = createFactory(properties);

        if (factoriesMap.get(key) == null) {
            factoriesMap.put(key, createHolder(factory));
        } else {
            factoriesMap.get(key).set(factory);
        }

        return factory;

    }

    protected static long createKey(Object... properties) {
        long key = 0;
        for (Object prop : properties) {
            key = key + (long) prop.hashCode();
        }
        return key;
    }


    protected abstract T createFactory(Object[] properties);


    private Holder createHolder(T value) {
        if (value.getClass().getSimpleName().startsWith(WOODSTOX_FACTORY_PREFIX)) {
            return new GlobalHolder<>(value);
        } else {
            return new ThreadLocalHolder<>(value);
        }
    }


    //Holder
    public interface Holder {
        void set(T t);

        T get();
    }

    /**
     * Holder bounded to a thread
     */
    private final class ThreadLocalHolder extends ThreadLocal implements Holder {
        public ThreadLocalHolder(T value) {
            this.set(value);
        }
    }

    /**
     * Holder bounded to the application
     */
    private final class GlobalHolder implements Holder {
        protected volatile T value;

        private GlobalHolder(T value) {
            this.value = value;
        }

        @Override
        public void set(T t) {
            this.value = t;
        }

        @Override
        public T get() {
            return value;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy