Skip to content

Commit 9dfae48

Browse files
committed
With the update of some of the dependencies and the removal of some of very old
dependencies, some codes have been refactored: - The application cache in the Caching Engine is now based upon the new version of ehcache. In its new version the element expiry mechanism has now to be explicitly defined. If ehcache 3 provides a default mechanism for TTL-based expiry or TTI-based expiry, nothing is provided to define a mechanism based upon both TTL and TTI as it was in ehcache 2. So a custom expiry mechanism is defined to implement close the way the TTL-and-TTI-based expiry was managed in ehcache 2. With the new version of ehcache, any null key throws immediately NullPointerException. This cause problems with MessageManager that uses the application cache and particularely in tests. So, the tests were updated to initialize MessageManager and a check is performed in MessageManager when accessing the application cache to catch the NullPointerException exception. - In the last version of Apache POI, the attributes are now encapsultated by getter. So replace all the direct attribute accesses by their counterpart getter. - The iCal4J API as some subtle changes. The HTMLProperty is modified consequently to those changes. - In the new Jackson version, the null fields are now also serialized. Set a configuration parameter to the ObjectMapper in JSONCodec so that Jackson behaves like its previous versions. - The very old informa library to produce or to consume RSS feeds is now replaced by the last version of Rome. All the codes that used informa are now refactored to use Rome instead of informa.
1 parent 571ff25 commit 9dfae48

File tree

29 files changed

+562
-297
lines changed

29 files changed

+562
-297
lines changed

core-api/pom.xml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@
6060
<artifactId>commons-io</artifactId>
6161
</dependency>
6262
<dependency>
63-
<groupId>net.sf.ehcache</groupId>
64-
<artifactId>ehcache-core</artifactId>
63+
<groupId>org.ehcache</groupId>
64+
<artifactId>ehcache</artifactId>
6565
</dependency>
6666
<dependency>
6767
<groupId>org.slf4j</groupId>
@@ -76,8 +76,8 @@
7676
<artifactId>slf4j-log4j12</artifactId>
7777
</dependency>
7878
<dependency>
79-
<groupId>log4j</groupId>
80-
<artifactId>log4j</artifactId>
79+
<groupId>org.apache.logging.log4j</groupId>
80+
<artifactId>log4j-core</artifactId>
8181
</dependency>
8282

8383
<!-- Tests-->

core-api/src/main/java/org/silverpeas/core/cache/model/AbstractCache.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@
3333
public abstract class AbstractCache extends AbstractSimpleCache
3434
implements Cache {
3535

36-
// In seconds, 12 hours (60seconds x 60minutes x 12hours)
37-
private final static int DEFAULT_TIME_TO_IDLE = 60 * 60 * 12;
36+
// In seconds, 12 hours (60 seconds x 60 minutes x 12 hours)
37+
private static final int DEFAULT_TIME_TO_IDLE = 60 * 60 * 12;
3838

3939
@Override
4040
public String add(final Object value, final int timeToLive) {

core-api/src/main/java/org/silverpeas/core/cache/model/Cache.java

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -30,42 +30,56 @@
3030
public interface Cache extends SimpleCache {
3131

3232
/**
33-
* Adds a value and generate a unique key to retrieve later the value.
34-
* After the given time, the value is trashed.
33+
* Adds a value and generates a unique mapping key to be used to retrieve later the value.
3534
* @param value an object to add into the cache
36-
* @param timeToLive 0 = unlimited
37-
* @return the key to which the added object is mapped in the cache
35+
* @param timeToLive the time to live in seconds of the value in the cache. After this time,
36+
* the value expires and consequently it is removed from the cache. 0 = unlimited.
37+
* @return the key to which the added value is mapped in the cache
3838
*/
3939
String add(Object value, int timeToLive);
4040

4141
/**
42-
* Adds a value and generate a unique key to retrieve later the value.
43-
* After the given live time, the value is trashed.
44-
* After the given idle time, the value is trashed.
42+
* Adds a value and generate a unique mapping key to be used to retrieve later the value.
43+
* When both the time to live and the time to idle are set, the lifetime of the value in the
44+
* cache is initially bounded by the time to live except if the lifetime computed from the time
45+
* to live at the last access of the value (access time plus the
46+
* time to idle) exceeds this initial lifetime.
4547
* @param value the object to add in the cache.
46-
* @param timeToLive 0 = unlimited
47-
* @param timeToIdle 0 = unlimited
48+
* @param timeToLive the time to live in seconds of the object in the cache. The time to live
49+
* can be exceeded if the time to idle is set and the value is accessed after the time to live
50+
* minus the time to idle. 0 = unlimited.
51+
* @param timeToIdle the time to idle in seconds of the object in the cache between two accesses.
52+
* With the time to live set, the time to idle is taken into account only once the time starting
53+
* at the access time exceed the initial lifetime of the value computed from the time to live.
54+
* After this time, the value expires and consequently it is remove from the cache. 0 = unlimited.
4855
* @return the key to which the added object is mapped in the cache
4956
*/
5057
String add(Object value, int timeToLive, int timeToIdle);
5158

5259
/**
53-
* Puts a value for a given key.
54-
* After the given time, the value is trashed.
55-
* @param key the key with which the object to add has to be mapped.
56-
* @param value the object to add in the cache.
57-
* @param timeToLive 0 = unlimited
60+
* Puts a new value for the given key and updates its time to live.
61+
* @param key the key with which the object to put has to be mapped.
62+
* @param value the object to put in the cache.
63+
* @param timeToLive the time to live in seconds of the value in the cache. After this time,
64+
* the value expires and consequently it is removed from the cache. 0 = unlimited.
5865
*/
5966
void put(Object key, Object value, int timeToLive);
6067

6168
/**
62-
* Puts a value for a given key.
63-
* After the given time, the value is trashed.
64-
* After the given idle time, the value is trashed.
65-
* @param key the key with which the object to add has to be mapped.
66-
* @param value the object to add in the cache.
67-
* @param timeToLive 0 = unlimited
68-
* @param timeToIdle 0 = unlimited
69+
* Puts a new value for the given key and updates both its time to live and its time to idle.
70+
* When both the time to live and the time to idle are set, the lifetime of the value in the
71+
* cache is initially bounded by the time to live except if the lifetime computed from the time
72+
* to live at the last access of the value (access time plus the
73+
* time to idle) exceeds this initial lifetime.
74+
* @param key the key with which the object to put has to be mapped.
75+
* @param value the object to put in the cache.
76+
* @param timeToLive the time to live in seconds of the object in the cache. The time to live
77+
* can be exceeded if the time to idle is set and the value is accessed after the time to live
78+
* minus the time to idle. 0 = unlimited.
79+
* @param timeToIdle the time to idle in seconds of the object in the cache between two accesses.
80+
* With the time to live set, the time to idle is taken into account only once the time starting
81+
* at the access time exceed the initial lifetime of the value computed from the time to live.
82+
* After this time, the value expires and consequently it is remove from the cache. 0 = unlimited.
6983
*/
7084
void put(Object key, Object value, int timeToLive, int timeToIdle);
7185
}

core-api/src/main/java/org/silverpeas/core/cache/model/SimpleCache.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,13 @@ public interface SimpleCache {
4646

4747
/**
4848
* Gets a typed element from the cache.
49-
* Null is returned if an element exists for the given key but the object type doesn't
50-
* correspond.
49+
* Null is returned if an element exists for the given key but the object doesn't satisfy the
50+
* expected type.
5151
* @param <T> the concrete type of the object to get.
5252
* @param key the key with which the object to get is mapped in the cache.
53-
* @param classType the class of the instance to get.
54-
* @return the object mapped with the key or null if no there is no object mapped with the
55-
* specified key.
53+
* @param classType the class type the instance to get as to satisfy.
54+
* @return the object mapped with the key or null if either there is no object mapped with the
55+
* specified key or the object doesn't satisfy the expected class type.
5656
*/
5757
<T> T get(Object key, Class<T> classType);
5858

core-api/src/main/java/org/silverpeas/core/cache/service/EhCache.java

Lines changed: 114 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -23,52 +23,52 @@
2323
*/
2424
package org.silverpeas.core.cache.service;
2525

26-
import net.sf.ehcache.Cache;
27-
import net.sf.ehcache.CacheManager;
28-
import net.sf.ehcache.Element;
29-
import net.sf.ehcache.config.CacheConfiguration;
26+
import org.ehcache.Cache;
27+
import org.ehcache.UserManagedCache;
28+
import org.ehcache.ValueSupplier;
29+
import org.ehcache.config.builders.ResourcePoolsBuilder;
30+
import org.ehcache.config.builders.UserManagedCacheBuilder;
31+
import org.ehcache.expiry.Duration;
32+
import org.ehcache.expiry.Expiry;
3033
import org.silverpeas.core.cache.model.AbstractCache;
3134

35+
import static java.util.concurrent.TimeUnit.SECONDS;
36+
3237
/**
3338
* Implementation of the Cache that uses EhCache API.
3439
* User: Yohann Chastagnier Date: 11/09/13
3540
*/
3641
final class EhCache extends AbstractCache {
3742

38-
private final static String CACHE_NAME = "SILVERPEAS_COMMON_EH_CACHE";
39-
40-
private final CacheManager cacheManager;
43+
private final UserManagedCache<Object, Element> managedCache;
4144

4245
/**
4346
* Initialization of the service using EhCache API.
4447
*
4548
* @param nbMaxElements maximum capacity of the cache.
4649
*/
47-
EhCache(int nbMaxElements) {
48-
cacheManager = CacheManager.getInstance();
49-
if (!cacheManager.cacheExists(CACHE_NAME)) {
50-
cacheManager.addCache(new Cache(new CacheConfiguration(CACHE_NAME, nbMaxElements)));
51-
} else {
52-
// Resizing dynamically the cache that already exists
53-
getCache().getCacheConfiguration().setMaxEntriesLocalHeap(nbMaxElements);
50+
EhCache(long nbMaxElements) {
51+
UserManagedCacheBuilder cacheBuilder =
52+
UserManagedCacheBuilder.newUserManagedCacheBuilder(Object.class, Element.class)
53+
.withExpiry(new PerElementExpiration());
54+
if (nbMaxElements > 0) {
55+
cacheBuilder = cacheBuilder.withResourcePools(ResourcePoolsBuilder.heap(nbMaxElements));
5456
}
57+
managedCache = cacheBuilder.build(true);
5558
}
5659

5760
/**
5861
* Gets the cache.
5962
*
6063
* @return the underlying cache used for its implementation.
6164
*/
62-
Cache getCache() {
63-
return cacheManager.getCache(CACHE_NAME);
65+
Cache<Object, Element> getCache() {
66+
return managedCache;
6467
}
6568

6669
@Override
6770
public void clear() {
68-
Cache cache = getCache();
69-
for (Object key : cache.getKeys()) {
70-
cache.remove(key);
71-
}
71+
getCache().clear();
7272
}
7373

7474
@Override
@@ -91,19 +91,106 @@ public Object remove(final Object key) {
9191

9292
@Override
9393
public <T> T remove(final Object key, final Class<T> classType) {
94-
T value = get(key, classType);
95-
if (value != null) {
96-
getCache().remove(key);
94+
T value = null;
95+
Element element = getCache().get(key);
96+
if (element != null) {
97+
value = element.getValue(classType);
98+
if (value != null) {
99+
getCache().remove(key);
100+
}
97101
}
98102
return value;
99103
}
100104

101105
@Override
102106
public void put(final Object key, final Object value, final int timeToLive,
103107
final int timeToIdle) {
104-
Element element = new Element(key, value);
105-
element.setTimeToLive(timeToLive);
106-
element.setTimeToIdle(timeToIdle);
107-
getCache().put(element);
108+
Element element = new Element(value)
109+
.withTimeToLive(timeToLive)
110+
.withTimeToIdle(timeToIdle);
111+
getCache().put(key, element);
112+
}
113+
114+
/**
115+
* An element in the cache. It decorated any value to put into the cache with TTL and TTI
116+
* information.
117+
*/
118+
static class Element {
119+
private Object value;
120+
private int ttl;
121+
private int tti;
122+
123+
public Element(final Object value) {
124+
this.value = value;
125+
}
126+
127+
public Element withTimeToLive(int ttl) {
128+
this.ttl = ttl;
129+
return this;
130+
}
131+
132+
public Element withTimeToIdle(int tti) {
133+
this.tti = tti;
134+
return this;
135+
}
136+
137+
public Object getObjectValue() {
138+
return value;
139+
}
140+
141+
public <T> T getValue(Class<T> clazz) {
142+
if (value == null || !clazz.isAssignableFrom(value.getClass())) {
143+
return null;
144+
}
145+
return (T) value;
146+
}
147+
148+
public int getTimeToLive() {
149+
return ttl;
150+
}
151+
152+
public int getTimeToIdle() {
153+
return tti;
154+
}
155+
}
156+
157+
/**
158+
* A custom expiration rule based upon both TTL and TTI for each element in the cache.
159+
*/
160+
private class PerElementExpiration implements Expiry<Object, Element> {
161+
162+
@Override
163+
public Duration getExpiryForCreation(final Object key, final Element value) {
164+
Duration expiration = Duration.INFINITE;
165+
if (value.getTimeToLive() <= 0 && value.getTimeToIdle() > 0) {
166+
expiration = Duration.of(value.getTimeToIdle(), SECONDS);
167+
} else if (value.getTimeToLive() > 0) {
168+
expiration = Duration.of(value.getTimeToLive(), SECONDS);
169+
}
170+
return expiration;
171+
}
172+
173+
@Override
174+
public Duration getExpiryForAccess(final Object key,
175+
final ValueSupplier<? extends Element> value) {
176+
Duration expiration = null;
177+
Element element = value.value();
178+
if (element.getTimeToIdle() > 0) {
179+
expiration = Duration.of(element.getTimeToIdle(), SECONDS);
180+
}
181+
return expiration;
182+
}
183+
184+
@Override
185+
public Duration getExpiryForUpdate(final Object key,
186+
final ValueSupplier<? extends Element> oldValue, final Element newValue) {
187+
Duration expiration = Duration.INFINITE;
188+
if (newValue.getTimeToLive() <= 0 && newValue.getTimeToIdle() > 0) {
189+
expiration = Duration.of(newValue.getTimeToIdle(), SECONDS);
190+
} else if (newValue.getTimeToLive() > 0) {
191+
expiration = Duration.of(newValue.getTimeToLive(), SECONDS);
192+
}
193+
return expiration;
194+
}
108195
}
109196
}

core-api/src/main/java/org/silverpeas/core/notification/message/MessageManager.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,12 @@ protected static String getLanguage(String registredKey) {
116116
}
117117

118118
public static void clear(String registredKey) {
119-
applicationCache.remove(registredKey);
119+
try {
120+
applicationCache.remove(registredKey);
121+
} catch (NullPointerException e) {
122+
// the MessageManager was already cleared!
123+
SilverLogger.getLogger(MessageManager.class).silent(e);
124+
}
120125
}
121126

122127
public static String getRegistredKey() {
@@ -158,7 +163,14 @@ protected static LocalizationBundle getLocalizationBundle(String messageContaine
158163

159164

160165
public static MessageContainer getMessageContainer(String registredKey) {
161-
return applicationCache.get(registredKey, MessageContainer.class);
166+
try {
167+
return applicationCache.get(registredKey, MessageContainer.class);
168+
} catch (NullPointerException e) {
169+
SilverLogger.getLogger(MessageManager.class)
170+
.silent(e)
171+
.error("No Message Container registered!");
172+
return null;
173+
}
162174
}
163175

164176
/**

core-api/src/main/java/org/silverpeas/core/util/JSONCodec.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
*/
2424
package org.silverpeas.core.util;
2525

26+
import com.fasterxml.jackson.annotation.JsonInclude;
2627
import com.fasterxml.jackson.databind.AnnotationIntrospector;
2728
import com.fasterxml.jackson.databind.DeserializationFeature;
2829
import com.fasterxml.jackson.databind.JsonNode;
@@ -46,7 +47,7 @@
4647
* corresponding Java bean.
4748
* <p>
4849
* In order to perform the marshalling and the unmarchalling, the fields of the bean must be
49-
* annotated with the JAXB annotations.
50+
* annotated with the JAXB annotations. All null fields are by default ignored.
5051
* @author mmoquillon
5152
*/
5253
public class JSONCodec {
@@ -160,6 +161,7 @@ private static ObjectMapper getObjectMapper() {
160161
AnnotationIntrospector introspector = new JaxbAnnotationIntrospector(
161162
TypeFactory.defaultInstance());
162163
mapper.setAnnotationIntrospector(introspector);
164+
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
163165
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
164166
return mapper;
165167
}

0 commit comments

Comments
 (0)