1 /**
2  *  Copyright Terracotta, Inc.
3  *
4  *  Licensed under the Apache License, Version 2.0 (the "License");
5  *  you may not use this file except in compliance with the License.
6  *  You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License.
15  */

16
17 package net.sf.ehcache.config;
18
19 import net.sf.ehcache.CacheManager;
20 import net.sf.ehcache.Ehcache;
21
22 /**
23  * Class to hold the SizeOf policy configuration.
24  *
25  * @author Ludovic Orban
26  */

27 public class SizeOfPolicyConfiguration implements Cloneable {
28     /**
29      * Default max traversal depth
30      */

31     public static final int DEFAULT_MAX_SIZEOF_DEPTH = 1000;
32     /**
33      * Default max traversal depth exceeded behavior
34      */

35     public static final MaxDepthExceededBehavior DEFAULT_MAX_DEPTH_EXCEEDED_BEHAVIOR = MaxDepthExceededBehavior.CONTINUE;
36
37     /**
38      * Enum of the possible behaviors of the SizeOf engine when the max depth is exceeded
39      */

40     public static enum MaxDepthExceededBehavior {
41         /**
42          * Abort the SizeOf engine's traversal and immediately return the partially calculated size
43          */

44         ABORT,
45
46         /**
47          * Warn about the exceeded max depth but continue traversal of the sized element
48          */

49         CONTINUE;
50
51         /**
52          * Returns true if this behavior is equal to ABORT
53          *
54          * @return true if this behavior is equal to ABORT
55          */

56         public boolean isAbort() {
57             return this == ABORT;
58         }
59
60         /**
61          * Returns true if this behavior is equal to CONTINUE
62          *
63          * @return true if this behavior is equal to CONTINUE
64          */

65         public boolean isContinue() {
66             return this == CONTINUE;
67         }
68     }
69
70     private volatile int maxDepth = DEFAULT_MAX_SIZEOF_DEPTH;
71     private volatile MaxDepthExceededBehavior maxDepthExceededBehavior = DEFAULT_MAX_DEPTH_EXCEEDED_BEHAVIOR;
72
73
74     /**
75      * Gets the maximum depth the SizeOf engine can normally traverse
76      *
77      * @return the maximum depth the SizeOf engine can normally traverse
78      */

79     public int getMaxDepth() {
80         return maxDepth;
81     }
82
83     /**
84      * Sets the maximum depth the SizeOf engine can normally traverse
85      *
86      * @param maxDepth the maximum depth the SizeOf engine can normally traverse
87      */

88     public void setMaxDepth(int maxDepth) {
89         this.maxDepth = maxDepth;
90     }
91
92     /**
93      * Builder method to set the maximum depth the SizeOf engine can normally traverse
94      *
95      * @param maxDepth the maximum depth the SizeOf engine can normally traverse
96      * @return this SizeOfPolicyConfiguration object
97      */

98     public SizeOfPolicyConfiguration maxDepth(int maxDepth) {
99         setMaxDepth(maxDepth);
100         return this;
101     }
102
103     /**
104      * Gets the behavior of the SizeOf engine when the max depth is reached
105      *
106      * @return the behavior of the SizeOf engine when the max depth is reached
107      */

108     public MaxDepthExceededBehavior getMaxDepthExceededBehavior() {
109         return maxDepthExceededBehavior;
110     }
111
112     /**
113      * Sets the behavior of the SizeOf engine when the max depth is reached
114      *
115      * @param maxDepthExceededBehavior the behavior of the SizeOf engine when the max depth is reached
116      */

117     public void setMaxDepthExceededBehavior(String maxDepthExceededBehavior) {
118         if (maxDepthExceededBehavior == null) {
119             throw new IllegalArgumentException("maxDepthExceededBehavior must be non-null");
120         }
121         this.maxDepthExceededBehavior(MaxDepthExceededBehavior.valueOf(MaxDepthExceededBehavior.class, maxDepthExceededBehavior.toUpperCase()));
122     }
123
124     /**
125      * Builder method to set the behavior of the SizeOf engine when the max depth is reached
126      *
127      * @param maxDepthExceededBehavior the behavior of the SizeOf engine when the max depth is reached
128      * @return this SizeOfPolicyConfiguration object
129      */

130     public SizeOfPolicyConfiguration maxDepthExceededBehavior(MaxDepthExceededBehavior maxDepthExceededBehavior) {
131         this.maxDepthExceededBehavior = maxDepthExceededBehavior;
132         return this;
133     }
134
135     /**
136      * Builder method to set the behavior of the SizeOf engine when the max depth is reached using a String object
137      *
138      * @param maxDepthExceededBehavior the behavior of the SizeOf engine when the max depth is reached
139      * @return this SizeOfPolicyConfiguration object
140      */

141     public SizeOfPolicyConfiguration maxDepthExceededBehavior(String maxDepthExceededBehavior) {
142         setMaxDepthExceededBehavior(maxDepthExceededBehavior);
143         return this;
144     }
145
146     /**
147      * Helper method which resolves the max depth of a cache, using the cache manager's one if none was configured
148      * on the cache itself.
149      *
150      * @param cache the cache from which to resolve the max depth
151      * @return the resolved max depth
152      */

153     public static int resolveMaxDepth(Ehcache cache) {
154         if (cache == null) {
155             return DEFAULT_MAX_SIZEOF_DEPTH;
156         }
157         CacheManager cacheManager = cache.getCacheManager();
158         return resolvePolicy(cacheManager == null ? null : cacheManager.getConfiguration(), cache.getCacheConfiguration()).getMaxDepth();
159     }
160
161     /**
162      * Helper method which resolves the MaxDepthExceededBehavior of a cache, using the cache manager's one if none was configured
163      * on the cache itself.
164      *
165      * @param cache the cache from which to resolve the MaxDepthExceededBehavior
166      * @return the resolved MaxDepthExceededBehavior
167      */

168     public static MaxDepthExceededBehavior resolveBehavior(Ehcache cache) {
169         if (cache == null) {
170             return DEFAULT_MAX_DEPTH_EXCEEDED_BEHAVIOR;
171         }
172         CacheManager cacheManager = cache.getCacheManager();
173         if (cacheManager == null) {
174             return resolvePolicy(null, cache.getCacheConfiguration()).getMaxDepthExceededBehavior();
175         } else {
176             return resolvePolicy(cacheManager.getConfiguration(), cache.getCacheConfiguration()).getMaxDepthExceededBehavior();
177         }
178     }
179
180     private static SizeOfPolicyConfiguration resolvePolicy(Configuration configuration, CacheConfiguration cacheConfiguration) {
181         SizeOfPolicyConfiguration sizeOfPolicyConfiguration = null;
182         if (cacheConfiguration != null) {
183             sizeOfPolicyConfiguration = cacheConfiguration.getSizeOfPolicyConfiguration();
184         }
185         if (sizeOfPolicyConfiguration == null) {
186             if (configuration != null) {
187                 sizeOfPolicyConfiguration = configuration.getSizeOfPolicyConfiguration();
188             } else {
189                 sizeOfPolicyConfiguration = new SizeOfPolicyConfiguration();
190             }
191         }
192
193         return sizeOfPolicyConfiguration;
194     }
195
196     @Override
197     public int hashCode() {
198         final int prime = 31;
199         int result = 1;
200         result = prime * result + maxDepth;
201         result = prime * result + ((maxDepthExceededBehavior == null) ? 0 : maxDepthExceededBehavior.hashCode());
202         return result;
203     }
204
205     @Override
206     public boolean equals(Object obj) {
207         if (this == obj) {
208             return true;
209         } else if (obj == null || getClass() != obj.getClass()) {
210             return false;
211         }
212         SizeOfPolicyConfiguration other = (SizeOfPolicyConfiguration) obj;
213         return (maxDepth == other.maxDepth && maxDepthExceededBehavior == other.maxDepthExceededBehavior);
214     }
215 }
216