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

org.apache.geronimo.jcache.simple.SimpleManager Maven / Gradle / Ivy

The newest version!
/*
 * 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.geronimo.jcache.simple;

import static java.util.Collections.unmodifiableSet;
import static org.apache.geronimo.jcache.simple.Asserts.assertNotNull;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.cache.Cache;
import javax.cache.CacheException;
import javax.cache.CacheManager;
import javax.cache.configuration.Configuration;
import javax.cache.spi.CachingProvider;

public class SimpleManager implements CacheManager {

    private final CachingProvider provider;

    private final URI uri;

    private final ClassLoader loader;

    private final Properties properties;

    private final ConcurrentMap> caches = new ConcurrentHashMap<>();

    private final Properties configProperties;

    private final ExecutorService executorService;

    private volatile boolean closed = false;

    SimpleManager(final CachingProvider provider, final URI uri, final ClassLoader loader, final Properties properties) {
        this.provider = provider;
        this.uri = uri;
        this.loader = loader;
        this.properties = readConfig(uri, loader, properties);
        this.configProperties = properties;

        ExecutorService executorService = rawProperty("geronimo.pool");
        if (executorService == null) {
            final int poolSize = Integer.parseInt(this.properties.getProperty("pool.size", "16"));
            final SimpleThreadFactory threadFactory = new SimpleThreadFactory("geronimo-simple-jcache-[" + uri.toASCIIString() + "]-");
            executorService = poolSize > 0 ? Executors.newFixedThreadPool(poolSize, threadFactory)
                    : Executors.newCachedThreadPool(threadFactory);
        }
        this.executorService = executorService;
    }

    private  T rawProperty(final String name) {
        final Object value = this.properties.get(name);
        if (value == null) {
            return (T) this.properties.get(name);
        }
        return (T) value;
    }

    private Properties readConfig(final URI uri, final ClassLoader loader, final Properties properties) {
        final Properties props = new Properties();
        try {
            if (SimpleProvider.DEFAULT_URI.toString().equals(uri.toString()) || uri.getScheme().equals("geronimo")
                    || uri.getScheme().equals("classpath")) {

                final Enumeration resources = loader.getResources(uri.toASCIIString().substring((uri.getScheme() + "://").length()));
                while (resources.hasMoreElements()) {
                    do {
                        addProperties(resources.nextElement(), props);
                    } while (resources.hasMoreElements());
                }
            } else {
                props.load(uri.toURL().openStream());
            }
        } catch (final IOException e) {
            throw new IllegalStateException(e);
        }
        if (properties != null) {
            props.putAll(properties);
        }
        return props;
    }

    private void addProperties(final URL url, final Properties aggregator) {
        try (final InputStream inputStream = url.openStream()) {
            aggregator.load(inputStream);
        } catch (final IOException e) {
            throw new IllegalArgumentException(e);
        }
    }

    private void assertNotClosed() {
        if (isClosed()) {
            throw new IllegalStateException("cache manager closed");
        }
    }

    @Override
    public > Cache createCache(final String cacheName, final C configuration)
            throws IllegalArgumentException {
        assertNotClosed();
        assertNotNull(cacheName, "cacheName");
        assertNotNull(configuration, "configuration");
        final Class keyType = configuration.getKeyType();
        final Class valueType = configuration.getValueType();
        if (!caches.containsKey(cacheName)) {
            final Cache cache = ClassLoaderAwareCache.wrap(loader, new SimpleCache(loader, this, cacheName,
                    new SimpleConfiguration<>(configuration, keyType, valueType), properties, executorService));
            caches.putIfAbsent(cacheName, cache);
        } else {
            throw new CacheException("cache " + cacheName + " already exists");
        }
        return (Cache) getCache(cacheName, keyType, valueType);
    }

    @Override
    public void destroyCache(final String cacheName) {
        assertNotClosed();
        assertNotNull(cacheName, "cacheName");
        final Cache cache = caches.remove(cacheName);
        if (cache != null && !cache.isClosed()) {
            cache.clear();
            cache.close();
        }
    }

    @Override
    public void enableManagement(final String cacheName, final boolean enabled) {
        assertNotClosed();
        assertNotNull(cacheName, "cacheName");
        final SimpleCache cache = of(cacheName);
        if (cache != null) {
            if (enabled) {
                cache.enableManagement();
            } else {
                cache.disableManagement();
            }
        }
    }

    private SimpleCache of(final String cacheName) {
        return SimpleCache.class.cast(ClassLoaderAwareCache.getDelegate(caches.get(cacheName)));
    }

    @Override
    public void enableStatistics(final String cacheName, final boolean enabled) {
        assertNotClosed();
        assertNotNull(cacheName, "cacheName");
        final SimpleCache cache = of(cacheName);
        if (cache != null) {
            if (enabled) {
                cache.enableStatistics();
            } else {
                cache.disableStatistics();
            }
        }
    }

    @Override
    public synchronized void close() {
        if (isClosed()) {
            return;
        }

        assertNotClosed();
        for (final Cache c : caches.values()) {
            c.close();
        }
        caches.clear();
        for (final Runnable task : executorService.shutdownNow()) {
            task.run();
        }
        closed = true;
        if (SimpleProvider.class.isInstance(provider)) {
            SimpleProvider.class.cast(provider).remove(this);
        } // else throw?
    }

    @Override
    public  T unwrap(final Class clazz) {
        if (clazz.isInstance(this)) {
            return clazz.cast(this);
        }
        throw new IllegalArgumentException(clazz.getName() + " not supported in unwrap");
    }

    @Override
    public boolean isClosed() {
        return closed;
    }

    @Override
    public  Cache getCache(final String cacheName) {
        assertNotClosed();
        assertNotNull(cacheName, "cacheName");
        return (Cache) doGetCache(cacheName, null, null);
    }

    @Override
    public Iterable getCacheNames() {
        assertNotClosed();
        return unmodifiableSet(new HashSet<>(caches.keySet()));
    }

    @Override
    public  Cache getCache(final String cacheName, final Class keyType, final Class valueType) {
        assertNotClosed();
        assertNotNull(cacheName, "cacheName");
        assertNotNull(keyType, "keyType");
        assertNotNull(valueType, "valueType");
        try {
            return doGetCache(cacheName, keyType, valueType);
        } catch (final IllegalArgumentException iae) {
            throw new ClassCastException(iae.getMessage());
        }
    }

    private  Cache doGetCache(final String cacheName, final Class keyType, final Class valueType) {
        final Cache cache = (Cache) caches.get(cacheName);
        if (keyType == null && valueType == null) {
            return cache;
        }
        if (cache == null) {
            return null;
        }

        final Configuration config = cache.getConfiguration(Configuration.class);
        if ((keyType != null && !config.getKeyType().isAssignableFrom(keyType))
                || (valueType != null && !config.getValueType().isAssignableFrom(valueType))) {
            throw new IllegalArgumentException(
                    "this cache is <" + config.getKeyType().getName() + ", " + config.getValueType().getName() + "> "
                            + " and not <" + keyType.getName() + ", " + valueType.getName() + ">");
        }
        return cache;
    }

    @Override
    public CachingProvider getCachingProvider() {
        return provider;
    }

    @Override
    public URI getURI() {
        return uri;
    }

    @Override
    public ClassLoader getClassLoader() {
        return loader;
    }

    @Override
    public Properties getProperties() {
        return configProperties;
    }

    public void release(final String name) {
        caches.remove(name);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy