Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
AbstractCacheManager |
|
| 2.6;2.6 |
1 | /* | |
2 | * Licensed to the Apache Software Foundation (ASF) under one | |
3 | * or more contributor license agreements. See the NOTICE file | |
4 | * distributed with this work for additional information | |
5 | * regarding copyright ownership. The ASF licenses this file | |
6 | * to you under the Apache License, Version 2.0 (the | |
7 | * "License"); you may not use this file except in compliance | |
8 | * with the License. You may obtain a copy of the License at | |
9 | * | |
10 | * http://www.apache.org/licenses/LICENSE-2.0 | |
11 | * | |
12 | * Unless required by applicable law or agreed to in writing, | |
13 | * software distributed under the License is distributed on an | |
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
15 | * KIND, either express or implied. See the License for the | |
16 | * specific language governing permissions and limitations | |
17 | * under the License. | |
18 | */ | |
19 | package org.apache.shiro.cache; | |
20 | ||
21 | import org.apache.shiro.util.Destroyable; | |
22 | import org.apache.shiro.util.LifecycleUtils; | |
23 | import org.apache.shiro.util.StringUtils; | |
24 | ||
25 | import java.util.Collection; | |
26 | import java.util.concurrent.ConcurrentHashMap; | |
27 | import java.util.concurrent.ConcurrentMap; | |
28 | ||
29 | /** | |
30 | * Very simple abstract {@code CacheManager} implementation that retains all created {@link Cache Cache} instances in | |
31 | * an in-memory {@link ConcurrentMap ConcurrentMap}. {@code Cache} instance creation is left to subclasses via | |
32 | * the {@link #createCache createCache} method implementation. | |
33 | * | |
34 | * @since 1.0 | |
35 | */ | |
36 | public abstract class AbstractCacheManager implements CacheManager, Destroyable { | |
37 | ||
38 | /** | |
39 | * Retains all Cache objects maintained by this cache manager. | |
40 | */ | |
41 | private final ConcurrentMap<String, Cache> caches; | |
42 | ||
43 | /** | |
44 | * Default no-arg constructor that instantiates an internal name-to-cache {@code ConcurrentMap}. | |
45 | */ | |
46 | 3 | public AbstractCacheManager() { |
47 | 3 | this.caches = new ConcurrentHashMap<String, Cache>(); |
48 | 3 | } |
49 | ||
50 | /** | |
51 | * Returns the cache with the specified {@code name}. If the cache instance does not yet exist, it will be lazily | |
52 | * created, retained for further access, and then returned. | |
53 | * | |
54 | * @param name the name of the cache to acquire. | |
55 | * @return the cache with the specified {@code name}. | |
56 | * @throws IllegalArgumentException if the {@code name} argument is {@code null} or does not contain text. | |
57 | * @throws CacheException if there is a problem lazily creating a {@code Cache} instance. | |
58 | */ | |
59 | public <K, V> Cache<K, V> getCache(String name) throws IllegalArgumentException, CacheException { | |
60 | 2 | if (!StringUtils.hasText(name)) { |
61 | 0 | throw new IllegalArgumentException("Cache name cannot be null or empty."); |
62 | } | |
63 | ||
64 | Cache cache; | |
65 | ||
66 | 2 | cache = caches.get(name); |
67 | 2 | if (cache == null) { |
68 | 2 | cache = createCache(name); |
69 | 2 | Cache existing = caches.putIfAbsent(name, cache); |
70 | 2 | if (existing != null) { |
71 | 0 | cache = existing; |
72 | } | |
73 | } | |
74 | ||
75 | //noinspection unchecked | |
76 | 2 | return cache; |
77 | } | |
78 | ||
79 | /** | |
80 | * Creates a new {@code Cache} instance associated with the specified {@code name}. | |
81 | * | |
82 | * @param name the name of the cache to create | |
83 | * @return a new {@code Cache} instance associated with the specified {@code name}. | |
84 | * @throws CacheException if the {@code Cache} instance cannot be created. | |
85 | */ | |
86 | protected abstract Cache createCache(String name) throws CacheException; | |
87 | ||
88 | /** | |
89 | * Cleanup method that first {@link LifecycleUtils#destroy destroys} all of it's managed caches and then | |
90 | * {@link java.util.Map#clear clears} out the internally referenced cache map. | |
91 | * | |
92 | * @throws Exception if any of the managed caches can't destroy properly. | |
93 | */ | |
94 | public void destroy() throws Exception { | |
95 | 0 | while (!caches.isEmpty()) { |
96 | 0 | for (Cache cache : caches.values()) { |
97 | 0 | LifecycleUtils.destroy(cache); |
98 | } | |
99 | 0 | caches.clear(); |
100 | } | |
101 | 0 | } |
102 | ||
103 | public String toString() { | |
104 | 3 | Collection<Cache> values = caches.values(); |
105 | 3 | StringBuilder sb = new StringBuilder(getClass().getSimpleName()) |
106 | .append(" with ") | |
107 | .append(caches.size()) | |
108 | .append(" cache(s)): ["); | |
109 | 3 | int i = 0; |
110 | 3 | for (Cache cache : values) { |
111 | 0 | if (i > 0) { |
112 | 0 | sb.append(", "); |
113 | } | |
114 | 0 | sb.append(cache.toString()); |
115 | 0 | i++; |
116 | } | |
117 | 3 | sb.append("]"); |
118 | 3 | return sb.toString(); |
119 | } | |
120 | } |