001/* 002 * (C) Copyright 2014 Nuxeo SAS (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl-2.1.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Maxime Hilaire 016 * 017 */ 018package org.nuxeo.ecm.core.cache; 019 020import java.util.ArrayList; 021import java.util.HashMap; 022import java.util.List; 023import java.util.Map; 024 025import org.apache.commons.logging.Log; 026import org.apache.commons.logging.LogFactory; 027import org.nuxeo.runtime.model.ContributionFragmentRegistry; 028 029/** 030 * Registry to register cache 031 * 032 * @since 6.0 033 */ 034public final class CacheRegistry extends ContributionFragmentRegistry<CacheDescriptor> { 035 036 private static final Log log = LogFactory.getLog(CacheRegistry.class); 037 038 // map of cache 039 protected final Map<String, CacheDescriptor> caches = new HashMap<String, CacheDescriptor>(); 040 041 @Override 042 public String getContributionId(CacheDescriptor contrib) { 043 return contrib.name; 044 } 045 046 @Override 047 public void contributionUpdated(String id, CacheDescriptor descriptor, CacheDescriptor newOrigContrib) { 048 String name = descriptor.name; 049 if (name == null) { 050 throw new RuntimeException("The cache name must not be null!"); 051 } 052 if (descriptor.remove) { 053 contributionRemoved(id, descriptor); 054 return; 055 } 056 057 if (caches.containsKey(name)) { 058 throw new IllegalStateException(String.format( 059 "Another cache has already been registered for the given name %s", name)); 060 } 061 062 caches.put(name, descriptor); 063 log.info("cache registered: " + name); 064 } 065 066 @Override 067 public boolean isSupportingMerge() { 068 return false; 069 } 070 071 @Override 072 public void contributionRemoved(String id, CacheDescriptor origContrib) { 073 String name = origContrib.name; 074 CacheDescriptor cache = caches.remove(name); 075 if (cache == null) { 076 throw new IllegalStateException("No such cache registered" + name); 077 } 078 try { 079 cache.stop(); 080 } catch (RuntimeException e) { 081 log.error(String.format("Error while removing cache '%s'", name), e); 082 } 083 log.info("cache removed: " + name); 084 } 085 086 @Override 087 public CacheDescriptor clone(CacheDescriptor orig) { 088 return orig.clone(); 089 } 090 091 @Override 092 public void merge(CacheDescriptor src, CacheDescriptor dst) { 093 boolean remove = src.remove; 094 // keep old remove info: if old contribution was removed, new one 095 // should replace the old one completely 096 if (remove) { 097 dst.remove = remove; 098 // don't bother merging 099 return; 100 } 101 102 } 103 104 public CacheAttributesChecker getCache(String name) { 105 if (caches.containsKey(name)) { 106 return caches.get(name).cacheChecker; 107 } 108 return null; 109 } 110 111 public List<CacheAttributesChecker> getCaches() { 112 List<CacheAttributesChecker> res = new ArrayList<CacheAttributesChecker>(caches.size()); 113 for (CacheDescriptor desc : caches.values()) { 114 res.add(desc.cacheChecker); 115 } 116 return res; 117 } 118 119 public void start() { 120 RuntimeException errors = new RuntimeException("Cannot start caches, check suppressed error"); 121 for (CacheDescriptor desc : caches.values()) { 122 try { 123 desc.start(); 124 } catch (RuntimeException cause) { 125 errors.addSuppressed(cause); 126 } 127 } 128 if (errors.getSuppressed().length > 0) { 129 throw errors; 130 } 131 } 132 133 public void stop() { 134 RuntimeException errors = new RuntimeException("Cannot stop caches, check suppressed error"); 135 for (CacheDescriptor desc : caches.values()) { 136 try { 137 desc.stop(); 138 } catch (RuntimeException cause) { 139 errors.addSuppressed(cause); 140 } 141 } 142 if (errors.getSuppressed().length > 0) { 143 throw errors; 144 } 145 } 146 147}