001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.commons.jcs3.jcache;
020
021import javax.cache.CacheManager;
022import javax.cache.configuration.OptionalFeature;
023import javax.cache.spi.CachingProvider;
024import java.net.URI;
025import java.util.Map;
026import java.util.Properties;
027import java.util.concurrent.ConcurrentHashMap;
028import java.util.concurrent.ConcurrentMap;
029
030public class JCSCachingProvider implements CachingProvider
031{
032    public static final URI DEFAULT_URI = URI.create("jcs://jcache.ccf");
033
034    private final ConcurrentMap<ClassLoader, ConcurrentMap<URI, CacheManager>> cacheManagersByLoader = new ConcurrentHashMap<>();
035
036    @Override
037    public CacheManager getCacheManager(final URI inUri, final ClassLoader inClassLoader, final Properties properties)
038    {
039        final URI uri = inUri != null ? inUri : getDefaultURI();
040        final ClassLoader classLoader = inClassLoader != null ? inClassLoader : getDefaultClassLoader();
041
042        ConcurrentMap<URI, CacheManager> managers = cacheManagersByLoader.get(classLoader);
043        if (managers == null)
044        {
045            managers = new ConcurrentHashMap<>();
046            final ConcurrentMap<URI, CacheManager> existingManagers = cacheManagersByLoader.putIfAbsent(classLoader, managers);
047            if (existingManagers != null)
048            {
049                managers = existingManagers;
050            }
051        }
052
053        CacheManager mgr = managers.get(uri);
054        if (mgr == null)
055        {
056            mgr = new JCSCachingManager(this, uri, classLoader, properties);
057            final CacheManager existing = managers.putIfAbsent(uri, mgr);
058            if (existing != null)
059            {
060                mgr = existing;
061            }
062        }
063
064        return mgr;
065    }
066
067    @Override
068    public URI getDefaultURI()
069    {
070        return DEFAULT_URI;
071    }
072
073    @Override
074    public void close()
075    {
076        for (final Map<URI, CacheManager> v : cacheManagersByLoader.values())
077        {
078            for (final CacheManager m : v.values())
079            {
080                m.close();
081            }
082            v.clear();
083        }
084        cacheManagersByLoader.clear();
085    }
086
087    @Override
088    public void close(final ClassLoader classLoader)
089    {
090        final Map<URI, CacheManager> cacheManagers = cacheManagersByLoader.remove(classLoader);
091        if (cacheManagers != null)
092        {
093            for (final CacheManager mgr : cacheManagers.values())
094            {
095                mgr.close();
096            }
097            cacheManagers.clear();
098        }
099    }
100
101    @Override
102    public void close(final URI uri, final ClassLoader classLoader)
103    {
104        final Map<URI, CacheManager> cacheManagers = cacheManagersByLoader.remove(classLoader);
105        if (cacheManagers != null)
106        {
107            final CacheManager mgr = cacheManagers.remove(uri);
108            if (mgr != null)
109            {
110                mgr.close();
111            }
112        }
113    }
114
115    @Override
116    public CacheManager getCacheManager(final URI uri, final ClassLoader classLoader)
117    {
118        return getCacheManager(uri, classLoader, getDefaultProperties());
119    }
120
121    @Override
122    public CacheManager getCacheManager()
123    {
124        return getCacheManager(getDefaultURI(), getDefaultClassLoader());
125    }
126
127    @Override
128    public boolean isSupported(final OptionalFeature optionalFeature)
129    {
130        return optionalFeature == OptionalFeature.STORE_BY_REFERENCE;
131    }
132
133    @Override
134    public ClassLoader getDefaultClassLoader()
135    {
136        return JCSCachingProvider.class.getClassLoader();
137    }
138
139    @Override
140    public Properties getDefaultProperties()
141    {
142        return new Properties();
143    }
144
145    void remove(final CacheManager mgr)
146    {
147        final ClassLoader classLoader = mgr.getClassLoader();
148        final Map<URI, CacheManager> mgrs = cacheManagersByLoader.get(classLoader);
149        if (mgrs != null)
150        {
151            mgrs.remove(mgr.getURI());
152            if (mgrs.isEmpty())
153            {
154                cacheManagersByLoader.remove(classLoader);
155            }
156        }
157    }
158}