/* * * 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.qpid.server.configuration; import java.util.UUID; import java.util.Collection; import java.util.Collections; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; public class ConfigStore { private ConcurrentHashMap> _typeMap = new ConcurrentHashMap>(); private ConcurrentHashMap> _listenerMap = new ConcurrentHashMap>(); private AtomicReference _root = new AtomicReference(null); private final AtomicLong _objectIdSource = new AtomicLong(0l); private final AtomicLong _persistentObjectIdSource = new AtomicLong(0l); // TODO - should load/increment this on broker startup private long _sequenceNumber = 1L; public enum Event { CREATED, DELETED } public interface ConfigEventListener, C extends ConfiguredObject> { void onEvent(C object, Event evt); } private ConfigStore() { } public , C extends ConfiguredObject> ConfiguredObject getConfiguredObject(ConfigObjectType type, UUID id) { ConcurrentHashMap typeMap = _typeMap.get(type); if(typeMap != null) { return typeMap.get(id); } else { return null; } } public , C extends ConfiguredObject> Collection getConfiguredObjects(ConfigObjectType type) { ConcurrentHashMap typeMap = _typeMap.get(type); if(typeMap != null) { return typeMap.values(); } else { return Collections.EMPTY_LIST; } } public , C extends ConfiguredObject> void addConfiguredObject(ConfiguredObject object) { ConcurrentHashMap typeMap = _typeMap.get(object.getConfigType()); if(typeMap == null) { typeMap = new ConcurrentHashMap(); ConcurrentHashMap oldMap = _typeMap.putIfAbsent(object.getConfigType(), typeMap); if(oldMap != null) { typeMap = oldMap; } } typeMap.put(object.getId(), object); sendEvent(Event.CREATED, object); } public , C extends ConfiguredObject> void removeConfiguredObject(ConfiguredObject object) { ConcurrentHashMap typeMap = _typeMap.get(object.getConfigType()); if(typeMap != null) { typeMap.remove(object.getId()); sendEvent(Event.DELETED, object); } } public , C extends ConfiguredObject> void addConfigEventListener(T type, ConfigEventListener listener) { CopyOnWriteArrayList listeners = _listenerMap.get(type); if(listeners == null) { listeners = new CopyOnWriteArrayList(); CopyOnWriteArrayList oldListeners = _listenerMap.putIfAbsent(type, listeners); if(oldListeners != null) { listeners = oldListeners; } } listeners.add(listener); } public , C extends ConfiguredObject> void removeConfigEventListener(T type, ConfigEventListener listener) { CopyOnWriteArrayList listeners = _listenerMap.get(type); if(listeners != null) { listeners.remove(listener); } } private void sendEvent(Event e, ConfiguredObject o) { CopyOnWriteArrayList listeners = _listenerMap.get(o.getConfigType()); if(listeners != null) { for(ConfigEventListener listener : listeners) { listener.onEvent(o, e); } } } public boolean setRoot(SystemConfig object) { if(_root.compareAndSet(null,object)) { addConfiguredObject(object); return true; } else { return false; } } public UUID createId() { return new UUID(((_sequenceNumber & 0xFFFl)<<48), _objectIdSource.incrementAndGet()); } public UUID createPersistentId() { return new UUID(0L, _persistentObjectIdSource.incrementAndGet()); } public void persistentIdInUse(UUID id) { long lsb = id.getLeastSignificantBits(); long currentId; while((currentId = _persistentObjectIdSource.get()) < lsb) { _persistentObjectIdSource.compareAndSet(currentId, lsb); } } public SystemConfig getRoot() { return _root.get(); } public static ConfigStore newInstance() { return new ConfigStore(); } }