001/*
002 * (C) Copyright 2015 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.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 * Nuxeo - initial API and implementation
016 */
017
018package org.nuxeo.ecm.core.transientstore;
019
020import java.util.HashMap;
021import java.util.Map;
022
023import org.nuxeo.ecm.core.transientstore.api.TransientStore;
024import org.nuxeo.ecm.core.transientstore.api.TransientStoreConfig;
025import org.nuxeo.ecm.core.transientstore.api.TransientStoreService;
026import org.nuxeo.runtime.model.ComponentContext;
027import org.nuxeo.runtime.model.ComponentInstance;
028import org.nuxeo.runtime.model.DefaultComponent;
029
030/**
031 * Component exposing the {@link TransientStoreService} and managing the unerlying extension point
032 *
033 * @author <a href="mailto:tdelprat@nuxeo.com">Tiry</a>
034 * @since 7.2
035 */
036public class TransientStorageComponent extends DefaultComponent implements TransientStoreService {
037
038    protected Map<String, TransientStoreConfig> configs = new HashMap<>();
039
040    protected Map<String, TransientStore> stores = new HashMap<>();
041
042    public static final String EP_STORE = "store";
043
044    public static final String DEFAULT_STORE_NAME = "default";
045
046    @Override
047    public TransientStore getStore(String name) {
048        TransientStore store = stores.get(name);
049        if (store == null) {
050            store = stores.get(DEFAULT_STORE_NAME);
051            if (store == null) {
052                store = registerDefaultStore();
053            }
054        }
055        return store;
056    }
057
058    protected TransientStore registerDefaultStore() {
059        synchronized (this) {
060            TransientStore defaultStore = stores.get(DEFAULT_STORE_NAME);
061            if (defaultStore == null) {
062                TransientStoreConfig defaultConfig = new TransientStoreConfig(DEFAULT_STORE_NAME);
063                defaultStore = defaultConfig.getStore();
064                stores.put(defaultConfig.getName(), defaultStore);
065            }
066            return defaultStore;
067        }
068    }
069
070    public void doGC() {
071        stores.values().forEach(TransientStore::doGC);
072    }
073
074    @Override
075    public void registerContribution(Object contribution, String extensionPoint, ComponentInstance contributor) {
076        if (EP_STORE.equals(extensionPoint)) {
077            TransientStoreConfig config = (TransientStoreConfig) contribution;
078            // XXX merge
079            configs.put(config.getName(), config);
080        }
081    }
082
083    @Override
084    public void unregisterContribution(Object contribution, String extensionPoint, ComponentInstance contributor) {
085        if (EP_STORE.equals(extensionPoint)) {
086            TransientStoreConfig config = (TransientStoreConfig) contribution;
087            TransientStore store = stores.get(config.getName());
088            store.shutdown();
089        }
090    }
091
092    @Override
093    public void applicationStarted(ComponentContext context) {
094        for (TransientStoreConfig config : configs.values()) {
095            registerStore(config);
096        }
097    }
098
099    protected TransientStore registerStore(TransientStoreConfig config) {
100        TransientStore store = config.getStore();
101        stores.put(config.getName(), store);
102        return store;
103    }
104
105    @Override
106    public void deactivate(ComponentContext context) {
107        stores.values().forEach(TransientStore::shutdown);
108        super.deactivate(context);
109    }
110
111    public void cleanUpStores() {
112        stores.values().forEach(TransientStore::removeAll);
113    }
114
115}