001/* 002 * (C) Copyright 2014-2016 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 * Thierry Martins 019 * 020 */ 021 022package org.nuxeo.ecm.core.cache; 023 024import java.util.ArrayList; 025import java.util.HashMap; 026import java.util.List; 027import java.util.Map; 028 029import org.apache.commons.logging.Log; 030import org.apache.commons.logging.LogFactory; 031import org.nuxeo.runtime.RuntimeServiceEvent; 032import org.nuxeo.runtime.RuntimeServiceListener; 033import org.nuxeo.runtime.api.Framework; 034import org.nuxeo.runtime.model.ComponentContext; 035import org.nuxeo.runtime.model.ComponentInstance; 036import org.nuxeo.runtime.model.ComponentName; 037import org.nuxeo.runtime.model.DefaultComponent; 038import org.nuxeo.runtime.model.Extension; 039 040/** 041 * Cache service implementation to manage nuxeo cache 042 * 043 * @since 6.0 044 */ 045public class CacheServiceImpl extends DefaultComponent implements CacheService { 046 047 /** 048 * @since 8.2 049 */ 050 public static final String DEFAULT_CACHE_ID = "default-cache"; 051 052 public static final ComponentName NAME = new ComponentName(CacheServiceImpl.class.getName()); 053 054 private static final Log log = LogFactory.getLog(CacheServiceImpl.class); 055 056 protected final CacheRegistry cacheRegistry = new CacheRegistry(); 057 058 /** 059 * Contains the names of all caches which have not been registered from an extension 060 */ 061 protected final List<String> autoregisteredCacheNames = new ArrayList<String>(); 062 063 @Override 064 public Cache getCache(String name) { 065 return cacheRegistry.getCache(name); 066 } 067 068 @Override 069 public void deactivate(ComponentContext context) { 070 if (cacheRegistry.caches.size() > 0) { 071 Map<String, CacheDescriptor> descriptors = new HashMap<String, CacheDescriptor>(cacheRegistry.caches); 072 for (CacheDescriptor desc : descriptors.values()) { 073 cacheRegistry.contributionRemoved(desc.name, desc); 074 if (!autoregisteredCacheNames.remove(desc.name)) { 075 log.warn("Unregistery leaked contribution " + desc.name); 076 } 077 } 078 } 079 } 080 081 @Override 082 public int getApplicationStartedOrder() { 083 ComponentInstance repositoryComponent = Framework.getRuntime().getComponentInstance( 084 "org.nuxeo.ecm.core.repository.RepositoryServiceComponent"); 085 if (repositoryComponent == null) { 086 return super.getApplicationStartedOrder(); 087 } 088 return ((DefaultComponent) repositoryComponent.getInstance()).getApplicationStartedOrder() - 5; 089 } 090 091 @Override 092 public void applicationStarted(ComponentContext context) { 093 Framework.addListener(new RuntimeServiceListener() { 094 095 @Override 096 public void handleEvent(RuntimeServiceEvent event) { 097 if (RuntimeServiceEvent.RUNTIME_ABOUT_TO_STOP != event.id) { 098 return; 099 } 100 Framework.removeListener(this); 101 cacheRegistry.stop(); 102 } 103 }); 104 cacheRegistry.start(); 105 } 106 107 @Override 108 public void registerExtension(Extension extension) { 109 Object[] contribs = extension.getContributions(); 110 for (Object contrib : contribs) { 111 CacheDescriptor descriptor = (CacheDescriptor) contrib; 112 registerCache(descriptor); 113 } 114 } 115 116 public void registerCache(CacheDescriptor descriptor) { 117 cacheRegistry.addContribution(descriptor); 118 } 119 120 @Override 121 public void registerCache(String name, int maxSize, int timeout) { 122 CacheDescriptor desc; 123 if (cacheRegistry.caches.get(DEFAULT_CACHE_ID) != null) { 124 desc = new CacheDescriptor(cacheRegistry.caches.get(DEFAULT_CACHE_ID)); 125 } else { 126 desc = new CacheDescriptor(); 127 } 128 desc.name = name; 129 desc.ttl = timeout; 130 desc.options.put("maxSize", String.valueOf(maxSize)); 131 if (cacheRegistry.caches.get(name) == null) { 132 registerCache(desc); 133 autoregisteredCacheNames.add(name); 134 } else { 135 CacheDescriptor oldDesc = cacheRegistry.caches.get(name); 136 cacheRegistry.merge(oldDesc, desc); 137 } 138 } 139 140 @Override 141 public void unregisterExtension(Extension extension) throws RuntimeException { 142 Object[] contribs = extension.getContributions(); 143 for (Object contrib : contribs) { 144 CacheDescriptor descriptor = (CacheDescriptor) contrib; 145 cacheRegistry.removeContribution(descriptor); 146 } 147 } 148 149 public void unregisterCache(CacheDescriptor descriptor) { 150 cacheRegistry.removeContribution(descriptor); 151 } 152 153 154 @Override 155 public <T> T getAdapter(Class<T> adapter) { 156 if (adapter.isAssignableFrom(CacheRegistry.class)) { 157 return adapter.cast(cacheRegistry); 158 } 159 return super.getAdapter(adapter); 160 } 161}