• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mybatis / ibatis-2 / #341

08 Sep 2023 11:16PM UTC coverage: 64.938% (+0.03%) from 64.913%
#341

push

github

web-flow
Merge pull request #183 from hazendaz/master

fixes #174, update GHA, maven wrapper, fix EOL markers, do not use star imports

5047 of 7772 relevant lines covered (64.94%)

0.65 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

68.32
/src/main/java/com/ibatis/sqlmap/engine/cache/CacheModel.java
1
/*
2
 * Copyright 2004-2023 the original author or authors.
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
 *    https://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
package com.ibatis.sqlmap.engine.cache;
17

18
import com.ibatis.common.logging.Log;
19
import com.ibatis.common.logging.LogFactory;
20
import com.ibatis.sqlmap.engine.mapping.statement.ExecuteListener;
21
import com.ibatis.sqlmap.engine.mapping.statement.MappedStatement;
22

23
import java.io.*;
24
import java.util.HashSet;
25
import java.util.Iterator;
26
import java.util.Properties;
27
import java.util.Set;
28

29
/**
30
 * Wrapper for Caches.
31
 */
32
public class CacheModel implements ExecuteListener {
33

34
  /** The Constant log. */
35
  private static final Log log = LogFactory.getLog(CacheModel.class);
1✔
36

37
  /** The Constant MAX_OBJECT_LOG_SIZE. */
38
  private static final int MAX_OBJECT_LOG_SIZE = 200;
39

40
  /**
41
   * This is used to represent null objects that are returned from the cache so that they can be cached, too.
42
   */
43
  public static final Object NULL_OBJECT = "SERIALIZABLE_NULL_OBJECT";
1✔
44

45
  /** The requests. */
46
  private int requests = 0;
1✔
47

48
  /** The hits. */
49
  private int hits = 0;
1✔
50

51
  /** Constant to turn off periodic cache flushes. */
52
  private static final long NO_FLUSH_INTERVAL = -99999;
53

54
  /** The id. */
55
  private String id;
56

57
  /** The read only. */
58
  private boolean readOnly;
59

60
  /** The serialize. */
61
  private boolean serialize;
62

63
  /** The last flush. */
64
  private long lastFlush;
65

66
  /** The flush interval. */
67
  private long flushInterval;
68

69
  /** The flush interval seconds. */
70
  private long flushIntervalSeconds;
71

72
  /** The flush trigger statements. */
73
  private Set flushTriggerStatements;
74

75
  /** The controller. */
76
  private CacheController controller;
77

78
  /** The resource. */
79
  private String resource;
80

81
  /**
82
   * Default constructor.
83
   */
84
  public CacheModel() {
1✔
85
    this.flushInterval = NO_FLUSH_INTERVAL;
1✔
86
    this.flushIntervalSeconds = NO_FLUSH_INTERVAL;
1✔
87
    this.lastFlush = System.currentTimeMillis();
1✔
88
    this.flushTriggerStatements = new HashSet();
1✔
89
  }
1✔
90

91
  /**
92
   * Getter for the cache model's id.
93
   *
94
   * @return the id
95
   */
96
  public String getId() {
97
    return id;
1✔
98
  }
99

100
  /**
101
   * Setter for the cache model's id.
102
   *
103
   * @param id
104
   *          - the new id
105
   */
106
  public void setId(String id) {
107
    this.id = id;
1✔
108
  }
1✔
109

110
  /**
111
   * Getter for read-only property.
112
   *
113
   * @return true if a read-only model
114
   */
115
  public boolean isReadOnly() {
116
    return readOnly;
1✔
117
  }
118

119
  /**
120
   * Setter for read-only property.
121
   *
122
   * @param readOnly
123
   *          - the new setting
124
   */
125
  public void setReadOnly(boolean readOnly) {
126
    this.readOnly = readOnly;
1✔
127
  }
1✔
128

129
  /**
130
   * Getter to tell if the cache serializes.
131
   *
132
   * @return true if the cache model serializes objects
133
   */
134
  public boolean isSerialize() {
135
    return serialize;
1✔
136
  }
137

138
  /**
139
   * Setter to tell the cache to serialize objects.
140
   *
141
   * @param serialize
142
   *          - if the cache model is to serialize objects
143
   */
144
  public void setSerialize(boolean serialize) {
145
    this.serialize = serialize;
1✔
146
  }
1✔
147

148
  /**
149
   * Getter for resource property.
150
   *
151
   * @return the value of the resource property
152
   */
153
  public String getResource() {
154
    return resource;
×
155
  }
156

157
  /**
158
   * Setter for resource property.
159
   *
160
   * @param resource
161
   *          - the new value
162
   */
163
  public void setResource(String resource) {
164
    this.resource = resource;
1✔
165
  }
1✔
166

167
  /**
168
   * Sets up the controller for the cache model.
169
   *
170
   * @param controller
171
   *          the new cache controller
172
   *
173
   * @throws ClassNotFoundException
174
   *           - if the class cannot be found
175
   * @throws InstantiationException
176
   *           - if the class cannot be instantiated
177
   * @throws IllegalAccessException
178
   *           - if the classes constructor is not accessible
179
   */
180
  public void setCacheController(CacheController controller)
181
      throws ClassNotFoundException, InstantiationException, IllegalAccessException {
182
    this.controller = controller;
1✔
183
  }
1✔
184

185
  /**
186
   * Getter for flushInterval property.
187
   *
188
   * @return The flushInterval (in milliseconds)
189
   */
190
  public long getFlushInterval() {
191
    return flushInterval;
×
192
  }
193

194
  /**
195
   * Getter for flushInterval property.
196
   *
197
   * @return The flushInterval (in milliseconds)
198
   */
199
  public long getFlushIntervalSeconds() {
200
    return flushIntervalSeconds;
×
201
  }
202

203
  /**
204
   * Setter for flushInterval property.
205
   *
206
   * @param flushInterval
207
   *          The new flushInterval (in milliseconds)
208
   */
209
  public void setFlushInterval(long flushInterval) {
210
    this.flushInterval = flushInterval;
1✔
211
    this.flushIntervalSeconds = flushInterval / 1000;
1✔
212
  }
1✔
213

214
  /**
215
   * Adds a flushTriggerStatment. When a flushTriggerStatment is executed, the cache is flushed (cleared).
216
   *
217
   * @param statementName
218
   *          The statement to add.
219
   */
220
  public void addFlushTriggerStatement(String statementName) {
221
    flushTriggerStatements.add(statementName);
1✔
222
  }
1✔
223

224
  /**
225
   * Gets an Iterator containing all flushTriggerStatment objects for this cache.
226
   *
227
   * @return The Iterator
228
   */
229
  public Iterator getFlushTriggerStatementNames() {
230
    return flushTriggerStatements.iterator();
1✔
231
  }
232

233
  /**
234
   * ExecuteListener event. This will be called by a MappedStatement for which this cache is registered as a
235
   * ExecuteListener. It will be called each time an executeXXXXXX method is called. In the case of the Cache class, it
236
   * is registered in order to flush the cache whenever a certain statement is executed. (i.e. the flushOnExecute cache
237
   * policy)
238
   *
239
   * @param statement
240
   *          The statement to execute
241
   */
242
  public void onExecuteStatement(MappedStatement statement) {
243
    flush();
1✔
244
  }
1✔
245

246
  /**
247
   * Returns statistical information about the cache.
248
   *
249
   * @return the number of cache hits divided by the total requests
250
   */
251
  public double getHitRatio() {
252
    return (double) hits / (double) requests;
×
253
  }
254

255
  /**
256
   * Configures the cache.
257
   *
258
   * @param props
259
   *          the props
260
   */
261
  public void configure(Properties props) {
262
    controller.setProperties(props);
×
263
  }
×
264

265
  /**
266
   * Clears the cache.
267
   */
268
  public void flush() {
269
    synchronized (this) {
1✔
270
      controller.flush(this);
1✔
271
      lastFlush = System.currentTimeMillis();
1✔
272
      if (log.isDebugEnabled()) {
1✔
273
        log("flushed", false, null);
×
274
      }
275
    }
1✔
276
  }
1✔
277

278
  /**
279
   * Get an object out of the cache. A side effect of this method is that is may clear the cache if it has not been
280
   * cleared in the flushInterval.
281
   *
282
   * @param key
283
   *          The key of the object to be returned
284
   *
285
   * @return The cached object (or null)
286
   */
287
  public Object getObject(CacheKey key) {
288
    Object value = null;
1✔
289
    synchronized (this) {
1✔
290
      if (flushInterval != NO_FLUSH_INTERVAL && System.currentTimeMillis() - lastFlush > flushInterval) {
1✔
291
        flush();
×
292
      }
293

294
      value = controller.getObject(this, key);
1✔
295
      if (serialize && !readOnly && (value != NULL_OBJECT && value != null)) {
1✔
296
        try {
297
          ByteArrayInputStream bis = new ByteArrayInputStream((byte[]) value);
1✔
298
          ObjectInputStream ois = new ObjectInputStream(bis);
1✔
299
          value = ois.readObject();
1✔
300
          ois.close();
1✔
301
        } catch (Exception e) {
×
302
          throw new RuntimeException("Error caching serializable object.  Be sure you're not attempting to use "
×
303
              + "a serialized cache for an object that may be taking advantage of lazy loading.  Cause: " + e, e);
304
        }
1✔
305
      }
306
      requests++;
1✔
307
      if (value != null) {
1✔
308
        hits++;
1✔
309
      }
310
      if (log.isDebugEnabled()) {
1✔
311
        if (value != null) {
×
312
          log("retrieved object", true, value);
×
313
        } else {
314
          log("cache miss", false, null);
×
315
        }
316
      }
317
    }
1✔
318
    return value;
1✔
319
  }
320

321
  /**
322
   * Add an object to the cache.
323
   *
324
   * @param key
325
   *          The key of the object to be cached
326
   * @param value
327
   *          The object to be cached
328
   */
329
  public void putObject(CacheKey key, Object value) {
330
    if (null == value)
1✔
331
      value = NULL_OBJECT;
×
332
    synchronized (this) {
1✔
333
      if (serialize && !readOnly && value != NULL_OBJECT) {
1✔
334
        try {
335
          ByteArrayOutputStream bos = new ByteArrayOutputStream();
1✔
336
          ObjectOutputStream oos = new ObjectOutputStream(bos);
1✔
337
          oos.writeObject(value);
1✔
338
          oos.flush();
1✔
339
          oos.close();
1✔
340
          value = bos.toByteArray();
1✔
341
        } catch (IOException e) {
×
342
          throw new RuntimeException("Error caching serializable object.  Cause: " + e, e);
×
343
        }
1✔
344
      }
345
      controller.putObject(this, key, value);
1✔
346
      if (log.isDebugEnabled()) {
1✔
347
        log("stored object", true, value);
×
348
      }
349
    }
1✔
350
  }
1✔
351

352
  /**
353
   * Get the maximum size of an object in the log output.
354
   *
355
   * @return Maximum size of a logged object in the output
356
   */
357
  protected int getMaxObjectLogSize() {
358
    return MAX_OBJECT_LOG_SIZE;
×
359
  }
360

361
  /**
362
   * Log a cache action. Since this method is pretty heavy weight, it's best to enclose it with a log.isDebugEnabled()
363
   * when called.
364
   *
365
   * @param action
366
   *          String to output
367
   * @param addValue
368
   *          Add the value being cached to the log
369
   * @param cacheValue
370
   *          The value being logged
371
   */
372
  protected void log(String action, boolean addValue, Object cacheValue) {
373
    StringBuilder output = new StringBuilder("Cache '");
×
374
    output.append(getId());
×
375
    output.append("': ");
×
376
    output.append(action);
×
377
    if (addValue) {
×
378
      String cacheObjectStr = (cacheValue == null ? "null" : cacheValue.toString());
×
379
      output.append(" '");
×
380
      if (cacheObjectStr.length() < getMaxObjectLogSize()) {
×
381
        output.append(cacheObjectStr);
×
382
      } else {
383
        output.append(cacheObjectStr.substring(1, getMaxObjectLogSize()));
×
384
        output.append("...");
×
385
      }
386
      output.append("'");
×
387
    }
388
    log.debug(output.toString());
×
389
  }
×
390

391
  /**
392
   * Sets the controller properties.
393
   *
394
   * @param cacheProps
395
   *          the new controller properties
396
   */
397
  public void setControllerProperties(Properties cacheProps) {
398
    controller.setProperties(cacheProps);
1✔
399
  }
1✔
400
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc