Synchronize access on an identity’s trust cache.
[Sone.git] / src / main / java / net / pterodactylus / sone / freenet / wot / DefaultIdentity.java
1 /*
2  * Sone - DefaultIdentity.java - Copyright © 2010 David Roden
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 package net.pterodactylus.sone.freenet.wot;
19
20 import java.util.Collections;
21 import java.util.HashMap;
22 import java.util.HashSet;
23 import java.util.Map;
24 import java.util.Set;
25 import java.util.logging.Level;
26 import java.util.logging.Logger;
27
28 import net.pterodactylus.sone.freenet.plugin.PluginException;
29 import net.pterodactylus.util.cache.CacheException;
30 import net.pterodactylus.util.cache.CacheItem;
31 import net.pterodactylus.util.cache.DefaultCacheItem;
32 import net.pterodactylus.util.cache.MemoryCache;
33 import net.pterodactylus.util.cache.ValueRetriever;
34 import net.pterodactylus.util.cache.WritableCache;
35 import net.pterodactylus.util.collection.TimedMap;
36 import net.pterodactylus.util.logging.Logging;
37
38 /**
39  * A Web of Trust identity.
40  *
41  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
42  */
43 public class DefaultIdentity implements Identity {
44
45         /** The logger. */
46         private static final Logger logger = Logging.getLogger(DefaultIdentity.class);
47
48         /** The web of trust connector. */
49         private final WebOfTrustConnector webOfTrustConnector;
50
51         /** The ID of the identity. */
52         private final String id;
53
54         /** The nickname of the identity. */
55         private final String nickname;
56
57         /** The request URI of the identity. */
58         private final String requestUri;
59
60         /** The contexts of the identity. */
61         private final Set<String> contexts = Collections.synchronizedSet(new HashSet<String>());
62
63         /** The properties of the identity. */
64         private final Map<String, String> properties = Collections.synchronizedMap(new HashMap<String, String>());
65
66         /** Cached trust. */
67         /* synchronize on itself. */
68         private final WritableCache<OwnIdentity, Trust> trustCache = new MemoryCache<OwnIdentity, Trust>(new ValueRetriever<OwnIdentity, Trust>() {
69
70                 @Override
71                 @SuppressWarnings("synthetic-access")
72                 public CacheItem<Trust> retrieve(OwnIdentity ownIdentity) throws CacheException {
73                         try {
74                                 return new DefaultCacheItem<Trust>(webOfTrustConnector.getTrust(ownIdentity, DefaultIdentity.this));
75                         } catch (PluginException pe1) {
76                                 throw new CacheException("Could not retrieve trust for OwnIdentity: " + ownIdentity, pe1);
77                         }
78                 }
79
80         }, new TimedMap<OwnIdentity, CacheItem<Trust>>(60 * 60 * 1000));
81
82         /**
83          * Creates a new identity.
84          *
85          * @param webOfTrustConnector
86          *            The web of trust connector
87          * @param id
88          *            The ID of the identity
89          * @param nickname
90          *            The nickname of the identity
91          * @param requestUri
92          *            The request URI of the identity
93          */
94         public DefaultIdentity(WebOfTrustConnector webOfTrustConnector, String id, String nickname, String requestUri) {
95                 this.webOfTrustConnector = webOfTrustConnector;
96                 this.id = id;
97                 this.nickname = nickname;
98                 this.requestUri = requestUri;
99         }
100
101         //
102         // ACCESSORS
103         //
104
105         /**
106          * {@inheritDoc}
107          */
108         @Override
109         public String getId() {
110                 return id;
111         }
112
113         /**
114          * {@inheritDoc}
115          */
116         @Override
117         public String getNickname() {
118                 return nickname;
119         }
120
121         /**
122          * {@inheritDoc}
123          */
124         @Override
125         public String getRequestUri() {
126                 return requestUri;
127         }
128
129         /**
130          * {@inheritDoc}
131          */
132         @Override
133         public Set<String> getContexts() {
134                 return Collections.unmodifiableSet(contexts);
135         }
136
137         /**
138          * Sets the contexts of this identity.
139          * <p>
140          * This method is only called by the {@link IdentityManager}.
141          *
142          * @param contexts
143          *            The contexts to set
144          */
145         void setContextsPrivate(Set<String> contexts) {
146                 this.contexts.clear();
147                 this.contexts.addAll(contexts);
148         }
149
150         /**
151          * {@inheritDoc}
152          */
153         @Override
154         public boolean hasContext(String context) {
155                 return contexts.contains(context);
156         }
157
158         /**
159          * Adds the given context to this identity.
160          * <p>
161          * This method is only called by the {@link IdentityManager}.
162          *
163          * @param context
164          *            The context to add
165          */
166         void addContextPrivate(String context) {
167                 contexts.add(context);
168         }
169
170         /**
171          * Removes the given context from this identity.
172          * <p>
173          * This method is only called by the {@link IdentityManager}.
174          *
175          * @param context
176          *            The context to remove
177          */
178         public void removeContextPrivate(String context) {
179                 contexts.remove(context);
180         }
181
182         /**
183          * {@inheritDoc}
184          */
185         @Override
186         public Map<String, String> getProperties() {
187                 synchronized (properties) {
188                         return Collections.unmodifiableMap(properties);
189                 }
190         }
191
192         /**
193          * Sets all properties of this identity.
194          * <p>
195          * This method is only called by the {@link IdentityManager}.
196          *
197          * @param properties
198          *            The new properties of this identity
199          */
200         void setPropertiesPrivate(Map<String, String> properties) {
201                 synchronized (this.properties) {
202                         this.properties.clear();
203                         this.properties.putAll(properties);
204                 }
205         }
206
207         /**
208          * Sets the property with the given name to the given value.
209          * <p>
210          * This method is only called by the {@link IdentityManager}.
211          *
212          * @param name
213          *            The name of the property
214          * @param value
215          *            The value of the property
216          */
217         void setPropertyPrivate(String name, String value) {
218                 synchronized (properties) {
219                         properties.put(name, value);
220                 }
221         }
222
223         /**
224          * {@inheritDoc}
225          */
226         @Override
227         public String getProperty(String name) {
228                 synchronized (properties) {
229                         return properties.get(name);
230                 }
231         }
232
233         /**
234          * Removes the property with the given name.
235          * <p>
236          * This method is only called by the {@link IdentityManager}.
237          *
238          * @param name
239          *            The name of the property to remove
240          */
241         void removePropertyPrivate(String name) {
242                 synchronized (properties) {
243                         properties.remove(name);
244                 }
245         }
246
247         /**
248          * {@inheritDoc}
249          */
250         @Override
251         public Trust getTrust(OwnIdentity ownIdentity) {
252                 try {
253                         synchronized (trustCache) {
254                                 return trustCache.get(ownIdentity);
255                         }
256                 } catch (CacheException ce1) {
257                         logger.log(Level.WARNING, "Could not get trust for OwnIdentity: " + ownIdentity, ce1);
258                         return null;
259                 }
260         }
261
262         /**
263          * Sets the trust received for this identity by the given own identity.
264          *
265          * @param ownIdentity
266          *            The own identity that gives the trust
267          * @param trust
268          *            The trust received for this identity
269          */
270         void setTrustPrivate(OwnIdentity ownIdentity, Trust trust) {
271                 synchronized (trustCache) {
272                         trustCache.put(ownIdentity, trust);
273                 }
274         }
275
276         //
277         // OBJECT METHODS
278         //
279
280         /**
281          * {@inheritDoc}
282          */
283         @Override
284         public int hashCode() {
285                 return id.hashCode();
286         }
287
288         /**
289          * {@inheritDoc}
290          */
291         @Override
292         public boolean equals(Object object) {
293                 if (!(object instanceof DefaultIdentity)) {
294                         return false;
295                 }
296                 DefaultIdentity identity = (DefaultIdentity) object;
297                 return identity.id.equals(id);
298         }
299
300         /**
301          * {@inheritDoc}
302          */
303         @Override
304         public String toString() {
305                 return getClass().getSimpleName() + "[id=" + id + ",nickname=" + nickname + ",contexts=" + contexts + ",properties=" + properties + "]";
306         }
307
308 }