This project has retired. For details please refer to its Attic page.
LinkCache xref

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.chemistry.opencmis.client.bindings.spi.atompub;
20  
21  import java.io.Serializable;
22  import java.io.UnsupportedEncodingException;
23  import java.net.URLEncoder;
24  import java.util.HashSet;
25  import java.util.Map;
26  import java.util.Set;
27  
28  import org.apache.chemistry.opencmis.client.bindings.cache.Cache;
29  import org.apache.chemistry.opencmis.client.bindings.cache.impl.CacheImpl;
30  import org.apache.chemistry.opencmis.client.bindings.cache.impl.ContentTypeCacheLevelImpl;
31  import org.apache.chemistry.opencmis.client.bindings.cache.impl.LruCacheLevelImpl;
32  import org.apache.chemistry.opencmis.client.bindings.cache.impl.MapCacheLevelImpl;
33  import org.apache.chemistry.opencmis.client.bindings.spi.BindingSession;
34  import org.apache.chemistry.opencmis.commons.SessionParameter;
35  import org.apache.chemistry.opencmis.commons.impl.Constants;
36  import org.apache.chemistry.opencmis.commons.impl.UrlBuilder;
37  
38  /**
39   * Link cache.
40   */
41  public class LinkCache implements Serializable {
42  
43      private static final long serialVersionUID = 1L;
44  
45      private static final Set<String> KNOWN_LINKS = new HashSet<String>();
46  
47      static {
48          KNOWN_LINKS.add(Constants.REL_ACL);
49          KNOWN_LINKS.add(Constants.REL_DOWN);
50          KNOWN_LINKS.add(Constants.REL_UP);
51          KNOWN_LINKS.add(Constants.REL_FOLDERTREE);
52          KNOWN_LINKS.add(Constants.REL_RELATIONSHIPS);
53          KNOWN_LINKS.add(Constants.REL_SELF);
54          KNOWN_LINKS.add(Constants.REL_ALLOWABLEACTIONS);
55          KNOWN_LINKS.add(Constants.REL_EDITMEDIA);
56          KNOWN_LINKS.add(Constants.REL_POLICIES);
57          KNOWN_LINKS.add(Constants.REL_VERSIONHISTORY);
58          KNOWN_LINKS.add(Constants.REL_WORKINGCOPY);
59          KNOWN_LINKS.add(AtomPubParser.LINK_REL_CONTENT);
60      }
61  
62      private static final int CACHE_SIZE_REPOSITORIES = 10;
63      private static final int CACHE_SIZE_TYPES = 100;
64      private static final int CACHE_SIZE_OBJECTS = 400;
65  
66      private final Cache linkCache;
67      private final Cache typeLinkCache;
68      private final Cache collectionLinkCache;
69      private final Cache templateCache;
70      private final Cache repositoryLinkCache;
71  
72      /**
73       * Constructor.
74       */
75      public LinkCache(BindingSession session) {
76          int repCount = session.get(SessionParameter.CACHE_SIZE_REPOSITORIES, CACHE_SIZE_REPOSITORIES);
77          if (repCount < 1) {
78              repCount = CACHE_SIZE_REPOSITORIES;
79          }
80  
81          int typeCount = session.get(SessionParameter.CACHE_SIZE_TYPES, CACHE_SIZE_TYPES);
82          if (typeCount < 1) {
83              typeCount = CACHE_SIZE_TYPES;
84          }
85  
86          int objCount = session.get(SessionParameter.CACHE_SIZE_LINKS, CACHE_SIZE_OBJECTS);
87          if (objCount < 1) {
88              objCount = CACHE_SIZE_OBJECTS;
89          }
90  
91          linkCache = new CacheImpl("Link Cache");
92          linkCache.initialize(new String[] {
93                  MapCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=" + repCount, // repository
94                  LruCacheLevelImpl.class.getName() + " " + LruCacheLevelImpl.MAX_ENTRIES + "=" + objCount, // id
95                  MapCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=12", // rel
96                  ContentTypeCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=3,"
97                          + MapCacheLevelImpl.SINGLE_VALUE + "=true" // type
98          });
99  
100         typeLinkCache = new CacheImpl("Type Link Cache");
101         typeLinkCache.initialize(new String[] {
102                 MapCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=" + repCount, // repository
103                 LruCacheLevelImpl.class.getName() + " " + LruCacheLevelImpl.MAX_ENTRIES + "=" + typeCount, // id
104                 MapCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=12", // rel
105                 ContentTypeCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=3,"
106                         + MapCacheLevelImpl.SINGLE_VALUE + "=true"// type
107         });
108 
109         collectionLinkCache = new CacheImpl("Collection Link Cache");
110         collectionLinkCache.initialize(new String[] {
111                 MapCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=" + repCount, // repository
112                 MapCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=8" // collection
113         });
114 
115         templateCache = new CacheImpl("URI Template Cache");
116         templateCache.initialize(new String[] {
117                 MapCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=" + repCount, // repository
118                 MapCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=6" // type
119         });
120 
121         repositoryLinkCache = new CacheImpl("Repository Link Cache");
122         repositoryLinkCache.initialize(new String[] {
123                 MapCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=" + repCount, // repository
124                 MapCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=6" // rel
125         });
126     }
127 
128     /**
129      * Adds a link.
130      */
131     public void addLink(String repositoryId, String id, String rel, String type, String link) {
132         if (KNOWN_LINKS.contains(rel)) {
133             linkCache.put(link, repositoryId, id, rel, type);
134         } else if (Constants.REL_ALTERNATE.equals(rel)) {
135             // use streamId instead of type as discriminating parameter
136             String streamId = extractStreamId(link);
137             if (streamId != null) {
138                 linkCache.put(link, repositoryId, id, rel, streamId);
139             }
140         }
141     }
142 
143     /**
144      * Tries to extract a streamId from an alternate link.
145      */
146     // this is not strictly in the spec
147     protected String extractStreamId(String link) {
148         int i = link.lastIndexOf('?');
149         if (i > 0) {
150             String[] params = link.substring(i + 1).split("&");
151             for (String param : params) {
152                 String[] parts = param.split("=", 2);
153                 if (parts[0].equals(Constants.PARAM_STREAM_ID)
154                         && parts.length == 2) {
155                     return parts[1];
156                 }
157             }
158         }
159         return null;
160     }
161 
162     /**
163      * Removes all links of an object.
164      */
165     public void removeLinks(String repositoryId, String id) {
166         linkCache.remove(repositoryId, id);
167     }
168 
169     /**
170      * Gets a link.
171      */
172     public String getLink(String repositoryId, String id, String rel, String type) {
173         return (String) linkCache.get(repositoryId, id, rel, type);
174     }
175 
176     /**
177      * Gets a link.
178      */
179     public String getLink(String repositoryId, String id, String rel) {
180         return getLink(repositoryId, id, rel, null);
181     }
182 
183     /**
184      * Checks a link.
185      */
186     public int checkLink(String repositoryId, String id, String rel, String type) {
187         return linkCache.check(repositoryId, id, rel, type);
188     }
189 
190     /**
191      * Locks the link cache.
192      */
193     public void lockLinks() {
194         linkCache.writeLock();
195     }
196 
197     /**
198      * Unlocks the link cache.
199      */
200     public void unlockLinks() {
201         linkCache.writeUnlock();
202     }
203 
204     /**
205      * Adds a type link.
206      */
207     public void addTypeLink(String repositoryId, String id, String rel, String type, String link) {
208         if (KNOWN_LINKS.contains(rel)) {
209             typeLinkCache.put(link, repositoryId, id, rel, type);
210         }
211     }
212 
213     /**
214      * Removes all links of a type.
215      */
216     public void removeTypeLinks(String repositoryId, String id) {
217         typeLinkCache.remove(repositoryId, id);
218     }
219 
220     /**
221      * Gets a type link.
222      */
223     public String getTypeLink(String repositoryId, String id, String rel, String type) {
224         return (String) typeLinkCache.get(repositoryId, id, rel, type);
225     }
226 
227     /**
228      * Locks the type link cache.
229      */
230     public void lockTypeLinks() {
231         typeLinkCache.writeLock();
232     }
233 
234     /**
235      * Unlocks the type link cache.
236      */
237     public void unlockTypeLinks() {
238         typeLinkCache.writeUnlock();
239     }
240 
241     /**
242      * Adds a collection.
243      */
244     public void addCollection(String repositoryId, String collection, String link) {
245         collectionLinkCache.put(link, repositoryId, collection);
246     }
247 
248     /**
249      * Gets a collection.
250      */
251     public String getCollection(String repositoryId, String collection) {
252         return (String) collectionLinkCache.get(repositoryId, collection);
253     }
254 
255     /**
256      * Adds an URI template.
257      */
258     public void addTemplate(String repositoryId, String type, String link) {
259         templateCache.put(link, repositoryId, type);
260     }
261 
262     /**
263      * Gets an URI template and replaces place holders with the given
264      * parameters.
265      */
266     public String getTemplateLink(String repositoryId, String type, Map<String, Object> parameters) {
267         String template = (String) templateCache.get(repositoryId, type);
268         if (template == null) {
269             return null;
270         }
271 
272         StringBuilder result = new StringBuilder();
273         StringBuilder param = new StringBuilder();
274 
275         boolean paramMode = false;
276         for (int i = 0; i < template.length(); i++) {
277             char c = template.charAt(i);
278 
279             if (paramMode) {
280                 if (c == '}') {
281                     paramMode = false;
282 
283                     String paramValue = UrlBuilder.normalizeParameter(parameters.get(param.toString()));
284                     if (paramValue != null) {
285                         try {
286                             result.append(URLEncoder.encode(paramValue, "UTF-8"));
287                         } catch (UnsupportedEncodingException e) {
288                             result.append(paramValue);
289                         }
290                     }
291 
292                     param = new StringBuilder();
293                 } else {
294                     param.append(c);
295                 }
296             } else {
297                 if (c == '{') {
298                     paramMode = true;
299                 } else {
300                     result.append(c);
301                 }
302             }
303         }
304 
305         return result.toString();
306     }
307 
308     /**
309      * Adds a collection.
310      */
311     public void addRepositoryLink(String repositoryId, String rel, String link) {
312         repositoryLinkCache.put(link, repositoryId, rel);
313     }
314 
315     /**
316      * Gets a collection.
317      */
318     public String getRepositoryLink(String repositoryId, String rel) {
319         return (String) repositoryLinkCache.get(repositoryId, rel);
320     }
321 
322     /**
323      * Removes all entries of the given repository from the caches.
324      */
325     public void clearRepository(String repositoryId) {
326         linkCache.remove(repositoryId);
327         typeLinkCache.remove(repositoryId);
328         collectionLinkCache.remove(repositoryId);
329         templateCache.remove(repositoryId);
330         repositoryLinkCache.remove(repositoryId);
331     }
332 
333     /*
334      * (non-Javadoc)
335      *
336      * @see java.lang.Object#toString()
337      */
338     @Override
339     public String toString() {
340         return "Link Cache [link cache=" + linkCache + ", type link cache=" + typeLinkCache
341                 + ", collection link cache=" + collectionLinkCache + ", repository link cache=" + repositoryLinkCache
342                 + ",  template cache=" + templateCache + "]";
343     }
344 }