001/* 002 * (C) Copyright 2014 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Maxime Hilaire 018 * 019 */ 020package org.nuxeo.ecm.core.cache; 021 022import java.util.HashMap; 023import java.util.Map; 024 025import org.nuxeo.common.xmap.annotation.XNode; 026import org.nuxeo.common.xmap.annotation.XNodeMap; 027import org.nuxeo.common.xmap.annotation.XObject; 028import org.nuxeo.ecm.core.api.NuxeoException; 029import org.nuxeo.ecm.core.cache.CacheServiceImpl.CachePubSubInvalidator; 030 031/** 032 * Descriptor of cache contrib 033 * 034 * @since 6.0 035 */ 036@XObject("cache") 037public class CacheDescriptor { 038 039 /** Default TTL in minutes. */ 040 public static final long DEFAULT_TTL = 1; 041 042 /** 043 * Default max size 044 * 045 * @since 9.3 046 */ 047 public static final long DEFAULT_MAX_SIZE = 100; 048 049 /** 050 * Maximum number of entries the cache may contain. 051 * 052 * @since 9.3 053 */ 054 public static final String OPTION_MAX_SIZE = "maxSize"; 055 056 /** @since 9.3 */ 057 public static final String OPTION_CONCURRENCY_LEVEL = "concurrencyLevel"; 058 059 @XNode("@name") 060 public String name; 061 062 @XNode("@remove") 063 public boolean remove; 064 065 @XNode("@class") 066 protected Class<? extends CacheManagement> klass; 067 068 @XNode("ttl") 069 public Long ttl; 070 071 @XNodeMap(value = "option", key = "@name", type = HashMap.class, componentType = String.class) 072 public Map<String, String> options = new HashMap<String, String>(); 073 074 public CacheDescriptor() { 075 } 076 077 /** 078 * Copy constructor. 079 */ 080 public CacheDescriptor(CacheDescriptor other) { 081 name = other.name; 082 ttl = other.ttl; 083 klass = other.klass; 084 options = new HashMap<String, String>(other.options); 085 } 086 087 @Override 088 public CacheDescriptor clone() { 089 return new CacheDescriptor(this); 090 } 091 092 public void merge(CacheDescriptor other) { 093 remove = other.remove; 094 if (other.ttl != null) { 095 ttl = other.ttl; 096 } 097 if (other.klass != null) { 098 klass = other.klass; 099 } 100 if (other.options != null) { 101 if (options == null) { 102 options = new HashMap<>(other.options); 103 } else { 104 options.putAll(other.options); 105 } 106 } 107 } 108 109 public long getTTL() { 110 return ttl == null ? DEFAULT_TTL : ttl.longValue(); 111 } 112 113 @Override 114 public String toString() { 115 return name + ": " + klass + ": " + ttl + ": " + options; 116 } 117 118 protected CacheManagement newInstance(CachePubSubInvalidator invalidator) { 119 CacheManagement cache; 120 if (klass == null) { 121 cache = new InMemoryCacheImpl(this); // default cache implementation 122 } else { 123 try { 124 cache = klass.getConstructor(CacheDescriptor.class).newInstance(this); 125 } catch (ReflectiveOperationException e) { 126 throw new NuxeoException("Failed to instantiate class: " + klass + " for cache: " + name, e); 127 } 128 } 129 // wrap with checker, metrics and invalidator 130 cache = new CacheAttributesChecker(cache); 131 cache = new CacheMetrics(cache); 132 if (invalidator != null) { 133 cache = new CacheInvalidator(cache, invalidator); 134 } 135 return cache; 136 } 137 138}