| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.chemistry.opencmis.client.bindings.spi.atompub; |
| |
| import java.io.Serializable; |
| import java.util.HashSet; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.apache.chemistry.opencmis.client.bindings.cache.Cache; |
| import org.apache.chemistry.opencmis.client.bindings.cache.impl.CacheImpl; |
| import org.apache.chemistry.opencmis.client.bindings.cache.impl.ContentTypeCacheLevelImpl; |
| import org.apache.chemistry.opencmis.client.bindings.cache.impl.LruCacheLevelImpl; |
| import org.apache.chemistry.opencmis.client.bindings.cache.impl.MapCacheLevelImpl; |
| import org.apache.chemistry.opencmis.client.bindings.spi.BindingSession; |
| import org.apache.chemistry.opencmis.commons.SessionParameter; |
| import org.apache.chemistry.opencmis.commons.SessionParameterDefaults; |
| import org.apache.chemistry.opencmis.commons.impl.Constants; |
| import org.apache.chemistry.opencmis.commons.impl.IOUtils; |
| import org.apache.chemistry.opencmis.commons.impl.UrlBuilder; |
| |
| /** |
| * Link cache. |
| */ |
| public class LinkCache implements Serializable { |
| |
| private static final long serialVersionUID = 1L; |
| |
| private static final Set<String> KNOWN_LINKS = new HashSet<String>(); |
| |
| static { |
| KNOWN_LINKS.add(Constants.REL_ACL); |
| KNOWN_LINKS.add(Constants.REL_DOWN); |
| KNOWN_LINKS.add(Constants.REL_UP); |
| KNOWN_LINKS.add(Constants.REL_FOLDERTREE); |
| KNOWN_LINKS.add(Constants.REL_RELATIONSHIPS); |
| KNOWN_LINKS.add(Constants.REL_SELF); |
| KNOWN_LINKS.add(Constants.REL_ALLOWABLEACTIONS); |
| KNOWN_LINKS.add(Constants.REL_EDITMEDIA); |
| KNOWN_LINKS.add(Constants.REL_POLICIES); |
| KNOWN_LINKS.add(Constants.REL_VERSIONHISTORY); |
| KNOWN_LINKS.add(Constants.REL_WORKINGCOPY); |
| KNOWN_LINKS.add(AtomPubParser.LINK_REL_CONTENT); |
| } |
| |
| private final Cache linkCache; |
| private final Cache typeLinkCache; |
| private final Cache collectionLinkCache; |
| private final Cache templateCache; |
| private final Cache repositoryLinkCache; |
| |
| /** |
| * Constructor. |
| */ |
| public LinkCache(BindingSession session) { |
| int repCount = session.get(SessionParameter.CACHE_SIZE_REPOSITORIES, |
| SessionParameterDefaults.CACHE_SIZE_REPOSITORIES); |
| if (repCount < 1) { |
| repCount = SessionParameterDefaults.CACHE_SIZE_REPOSITORIES; |
| } |
| |
| int typeCount = session.get(SessionParameter.CACHE_SIZE_TYPES, SessionParameterDefaults.CACHE_SIZE_TYPES); |
| if (typeCount < 1) { |
| typeCount = SessionParameterDefaults.CACHE_SIZE_TYPES; |
| } |
| |
| int objCount = session.get(SessionParameter.CACHE_SIZE_LINKS, SessionParameterDefaults.CACHE_SIZE_LINKS); |
| if (objCount < 1) { |
| objCount = SessionParameterDefaults.CACHE_SIZE_LINKS; |
| } |
| |
| linkCache = new CacheImpl("Link Cache"); |
| linkCache.initialize(new String[] { |
| MapCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=" + repCount, // repository |
| LruCacheLevelImpl.class.getName() + " " + LruCacheLevelImpl.MAX_ENTRIES + "=" + objCount, // id |
| MapCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=12", // rel |
| ContentTypeCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=3," |
| + MapCacheLevelImpl.SINGLE_VALUE + "=true" // type |
| }); |
| |
| typeLinkCache = new CacheImpl("Type Link Cache"); |
| typeLinkCache.initialize(new String[] { |
| MapCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=" + repCount, // repository |
| LruCacheLevelImpl.class.getName() + " " + LruCacheLevelImpl.MAX_ENTRIES + "=" + typeCount, // id |
| MapCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=12", // rel |
| ContentTypeCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=3," |
| + MapCacheLevelImpl.SINGLE_VALUE + "=true"// type |
| }); |
| |
| collectionLinkCache = new CacheImpl("Collection Link Cache"); |
| collectionLinkCache.initialize(new String[] { |
| MapCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=" + repCount, // repository |
| MapCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=8" // collection |
| }); |
| |
| templateCache = new CacheImpl("URI Template Cache"); |
| templateCache.initialize(new String[] { |
| MapCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=" + repCount, // repository |
| MapCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=6" // type |
| }); |
| |
| repositoryLinkCache = new CacheImpl("Repository Link Cache"); |
| repositoryLinkCache.initialize(new String[] { |
| MapCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=" + repCount, // repository |
| MapCacheLevelImpl.class.getName() + " " + MapCacheLevelImpl.CAPACITY + "=6" // rel |
| }); |
| } |
| |
| /** |
| * Adds a link. |
| */ |
| public void addLink(String repositoryId, String id, String rel, String type, String link) { |
| if (KNOWN_LINKS.contains(rel)) { |
| linkCache.put(link, repositoryId, id, rel, type); |
| } else if (Constants.REL_ALTERNATE.equals(rel)) { |
| // use streamId instead of type as discriminating parameter |
| String streamId = extractStreamId(link); |
| if (streamId != null) { |
| linkCache.put(link, repositoryId, id, rel, streamId); |
| } |
| } |
| } |
| |
| /** |
| * Tries to extract a streamId from an alternate link. |
| */ |
| // this is not strictly in the spec |
| protected String extractStreamId(String link) { |
| int i = link.lastIndexOf('?'); |
| if (i > 0) { |
| String[] params = link.substring(i + 1).split("&"); |
| for (String param : params) { |
| String[] parts = param.split("=", 2); |
| if (parts[0].equals(Constants.PARAM_STREAM_ID) && parts.length == 2) { |
| return parts[1]; |
| } |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Removes all links of an object. |
| */ |
| public void removeLinks(String repositoryId, String id) { |
| linkCache.remove(repositoryId, id); |
| } |
| |
| /** |
| * Gets a link. |
| */ |
| public String getLink(String repositoryId, String id, String rel, String type) { |
| return (String) linkCache.get(repositoryId, id, rel, type); |
| } |
| |
| /** |
| * Gets a link. |
| */ |
| public String getLink(String repositoryId, String id, String rel) { |
| return getLink(repositoryId, id, rel, null); |
| } |
| |
| /** |
| * Checks a link. |
| */ |
| public int checkLink(String repositoryId, String id, String rel, String type) { |
| return linkCache.check(repositoryId, id, rel, type); |
| } |
| |
| /** |
| * Locks the link cache. |
| */ |
| public void lockLinks() { |
| linkCache.writeLock(); |
| } |
| |
| /** |
| * Unlocks the link cache. |
| */ |
| public void unlockLinks() { |
| linkCache.writeUnlock(); |
| } |
| |
| /** |
| * Adds a type link. |
| */ |
| public void addTypeLink(String repositoryId, String id, String rel, String type, String link) { |
| if (KNOWN_LINKS.contains(rel)) { |
| typeLinkCache.put(link, repositoryId, id, rel, type); |
| } |
| } |
| |
| /** |
| * Removes all links of a type. |
| */ |
| public void removeTypeLinks(String repositoryId, String id) { |
| typeLinkCache.remove(repositoryId, id); |
| } |
| |
| /** |
| * Gets a type link. |
| */ |
| public String getTypeLink(String repositoryId, String id, String rel, String type) { |
| return (String) typeLinkCache.get(repositoryId, id, rel, type); |
| } |
| |
| /** |
| * Locks the type link cache. |
| */ |
| public void lockTypeLinks() { |
| typeLinkCache.writeLock(); |
| } |
| |
| /** |
| * Unlocks the type link cache. |
| */ |
| public void unlockTypeLinks() { |
| typeLinkCache.writeUnlock(); |
| } |
| |
| /** |
| * Adds a collection. |
| */ |
| public void addCollection(String repositoryId, String collection, String link) { |
| collectionLinkCache.put(link, repositoryId, collection); |
| } |
| |
| /** |
| * Gets a collection. |
| */ |
| public String getCollection(String repositoryId, String collection) { |
| return (String) collectionLinkCache.get(repositoryId, collection); |
| } |
| |
| /** |
| * Adds an URI template. |
| */ |
| public void addTemplate(String repositoryId, String type, String link) { |
| templateCache.put(link, repositoryId, type); |
| } |
| |
| /** |
| * Gets an URI template and replaces place holders with the given |
| * parameters. |
| */ |
| public String getTemplateLink(String repositoryId, String type, Map<String, Object> parameters) { |
| String template = (String) templateCache.get(repositoryId, type); |
| if (template == null) { |
| return null; |
| } |
| |
| StringBuilder result = new StringBuilder(); |
| StringBuilder param = new StringBuilder(); |
| |
| boolean paramMode = false; |
| for (int i = 0; i < template.length(); i++) { |
| char c = template.charAt(i); |
| |
| if (paramMode) { |
| if (c == '}') { |
| paramMode = false; |
| |
| String paramValue = UrlBuilder.normalizeParameter(parameters.get(param.toString())); |
| if (paramValue != null) { |
| result.append(IOUtils.encodeURL(paramValue)); |
| } |
| |
| param = new StringBuilder(); |
| } else { |
| param.append(c); |
| } |
| } else { |
| if (c == '{') { |
| paramMode = true; |
| } else { |
| result.append(c); |
| } |
| } |
| } |
| |
| return result.toString(); |
| } |
| |
| /** |
| * Adds a collection. |
| */ |
| public void addRepositoryLink(String repositoryId, String rel, String link) { |
| repositoryLinkCache.put(link, repositoryId, rel); |
| } |
| |
| /** |
| * Gets a collection. |
| */ |
| public String getRepositoryLink(String repositoryId, String rel) { |
| return (String) repositoryLinkCache.get(repositoryId, rel); |
| } |
| |
| /** |
| * Removes all entries of the given repository from the caches. |
| */ |
| public void clearRepository(String repositoryId) { |
| linkCache.remove(repositoryId); |
| typeLinkCache.remove(repositoryId); |
| collectionLinkCache.remove(repositoryId); |
| templateCache.remove(repositoryId); |
| repositoryLinkCache.remove(repositoryId); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see java.lang.Object#toString() |
| */ |
| @Override |
| public String toString() { |
| return "Link Cache [link cache=" + linkCache + ", type link cache=" + typeLinkCache |
| + ", collection link cache=" + collectionLinkCache + ", repository link cache=" + repositoryLinkCache |
| + ", template cache=" + templateCache + "]"; |
| } |
| } |