blob: e7c474bf556c25e0cfd6cf4ea184af25c3ae3fa7 [file] [log] [blame]
package org.apache.qpid.server.configuration.store;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.apache.log4j.Logger;
import org.apache.qpid.server.BrokerOptions;
import org.apache.qpid.server.configuration.ConfigurationEntry;
import org.apache.qpid.server.configuration.ConfigurationEntryStore;
import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.model.Port;
import org.apache.qpid.server.model.Protocol;
import org.apache.qpid.server.model.State;
import org.apache.qpid.server.model.VirtualHost;
import org.apache.qpid.server.util.MapValueConverter;
public class ManagementModeStoreHandler implements ConfigurationEntryStore
{
private static final Logger LOGGER = Logger.getLogger(ManagementModeStoreHandler.class);
private static final String MANAGEMENT_MODE_PORT_PREFIX = "MANAGEMENT-MODE-PORT-";
private static final String PORT_TYPE = Port.class.getSimpleName();
private static final String VIRTUAL_HOST_TYPE = VirtualHost.class.getSimpleName();
private static final String ATTRIBUTE_STATE = VirtualHost.STATE;
private final ConfigurationEntryStore _store;
private final Map<UUID, ConfigurationEntry> _cliEntries;
private final Map<UUID, Object> _quiescedEntries;
private final UUID _rootId;
public ManagementModeStoreHandler(ConfigurationEntryStore store, BrokerOptions options)
{
ConfigurationEntry storeRoot = store.getRootEntry();
_store = store;
_rootId = storeRoot.getId();
_cliEntries = createPortsFromCommadLineOptions(options);
_quiescedEntries = quiesceEntries(storeRoot, options);
}
@Override
public void open(String storeLocation)
{
throw new IllegalStateException("The store should be already opened");
}
@Override
public void open(String storeLocation, String initialStoreLocation)
{
throw new IllegalStateException("The store should be already opened");
}
@Override
public void open(String storeLocation, ConfigurationEntryStore initialStore)
{
throw new IllegalStateException("The store should be already opened");
}
@Override
public ConfigurationEntry getRootEntry()
{
return getEntry(_rootId);
}
@Override
public ConfigurationEntry getEntry(UUID id)
{
synchronized (_store)
{
if (_cliEntries.containsKey(id))
{
return _cliEntries.get(id);
}
ConfigurationEntry entry = _store.getEntry(id);
if (_quiescedEntries.containsKey(id))
{
entry = createEntryWithState(entry, State.QUIESCED);
}
else if (id == _rootId)
{
entry = createRootWithCLIEntries(entry);
}
return entry;
}
}
@Override
public void save(ConfigurationEntry... entries)
{
synchronized (_store)
{
ConfigurationEntry[] entriesToSave = new ConfigurationEntry[entries.length];
for (int i = 0; i < entries.length; i++)
{
ConfigurationEntry entry = entries[i];
UUID id = entry.getId();
if (_cliEntries.containsKey(id))
{
throw new IllegalConfigurationException("Cannot save configuration provided as command line argument:"
+ entry);
}
else if (_quiescedEntries.containsKey(id))
{
// save entry with the original state
entry = createEntryWithState(entry, _quiescedEntries.get(ATTRIBUTE_STATE));
}
else if (_rootId.equals(id))
{
// save root without command line entries
Set<UUID> childrenIds = new HashSet<UUID>(entry.getChildrenIds());
if (!_cliEntries.isEmpty())
{
childrenIds.removeAll(_cliEntries.entrySet());
}
HashMap<String, Object> attributes = new HashMap<String, Object>(entry.getAttributes());
entry = new ConfigurationEntry(entry.getId(), entry.getType(), attributes, childrenIds, this);
}
entriesToSave[i] = entry;
}
_store.save(entriesToSave);
}
}
@Override
public UUID[] remove(UUID... entryIds)
{
synchronized (_store)
{
for (UUID id : entryIds)
{
if (_cliEntries.containsKey(id))
{
throw new IllegalConfigurationException("Cannot change configuration for command line entry:"
+ _cliEntries.get(id));
}
}
UUID[] result = _store.remove(entryIds);
for (UUID id : entryIds)
{
if (_quiescedEntries.containsKey(id))
{
_quiescedEntries.remove(id);
}
}
return result;
}
}
@Override
public void copyTo(String copyLocation)
{
synchronized (_store)
{
_store.copyTo(copyLocation);
}
}
private Map<UUID, ConfigurationEntry> createPortsFromCommadLineOptions(BrokerOptions options)
{
int managementModeRmiPort = options.getManagementModeRmiPort();
if (managementModeRmiPort < 0)
{
throw new IllegalConfigurationException("Invalid rmi port is specified: " + managementModeRmiPort);
}
int managementModeConnectorPort = options.getManagementModeConnectorPort();
if (managementModeConnectorPort < 0)
{
throw new IllegalConfigurationException("Invalid connector port is specified: " + managementModeConnectorPort);
}
int managementModeHttpPort = options.getManagementModeHttpPort();
if (managementModeHttpPort < 0)
{
throw new IllegalConfigurationException("Invalid http port is specified: " + managementModeHttpPort);
}
Map<UUID, ConfigurationEntry> cliEntries = new HashMap<UUID, ConfigurationEntry>();
if (managementModeRmiPort != 0)
{
ConfigurationEntry entry = createCLIPortEntry(managementModeRmiPort, Protocol.RMI);
cliEntries.put(entry.getId(), entry);
if (managementModeConnectorPort == 0)
{
ConfigurationEntry connectorEntry = createCLIPortEntry(managementModeRmiPort + 100, Protocol.JMX_RMI);
cliEntries.put(connectorEntry.getId(), connectorEntry);
}
}
if (managementModeConnectorPort != 0)
{
ConfigurationEntry entry = createCLIPortEntry(managementModeConnectorPort, Protocol.JMX_RMI);
cliEntries.put(entry.getId(), entry);
}
if (managementModeHttpPort != 0)
{
ConfigurationEntry entry = createCLIPortEntry(managementModeHttpPort, Protocol.HTTP);
cliEntries.put(entry.getId(), entry);
}
return cliEntries;
}
private ConfigurationEntry createCLIPortEntry(int port, Protocol protocol)
{
Map<String, Object> attributes = new HashMap<String, Object>();
attributes.put(Port.PORT, port);
attributes.put(Port.PROTOCOLS, Collections.singleton(protocol));
attributes.put(Port.NAME, MANAGEMENT_MODE_PORT_PREFIX + protocol.name());
ConfigurationEntry portEntry = new ConfigurationEntry(UUID.randomUUID(), PORT_TYPE, attributes,
Collections.<UUID> emptySet(), this);
if (LOGGER.isDebugEnabled())
{
LOGGER.debug("Add management mode port configuration " + portEntry + " for port " + port + " and protocol "
+ protocol);
}
return portEntry;
}
private ConfigurationEntry createRootWithCLIEntries(ConfigurationEntry storeRoot)
{
Set<UUID> childrenIds = new HashSet<UUID>(storeRoot.getChildrenIds());
if (!_cliEntries.isEmpty())
{
childrenIds.addAll(_cliEntries.keySet());
}
ConfigurationEntry root = new ConfigurationEntry(storeRoot.getId(), storeRoot.getType(), new HashMap<String, Object>(
storeRoot.getAttributes()), childrenIds, this);
return root;
}
private Map<UUID, Object> quiesceEntries(ConfigurationEntry storeRoot, BrokerOptions options)
{
Map<UUID, Object> quiescedEntries = new HashMap<UUID, Object>();
Set<UUID> childrenIds;
int managementModeRmiPort = options.getManagementModeRmiPort();
int managementModeConnectorPort = options.getManagementModeConnectorPort();
int managementModeHttpPort = options.getManagementModeHttpPort();
childrenIds = storeRoot.getChildrenIds();
for (UUID id : childrenIds)
{
ConfigurationEntry entry = _store.getEntry(id);
String entryType = entry.getType();
Map<String, Object> attributes = entry.getAttributes();
boolean quiesce = false;
if (VIRTUAL_HOST_TYPE.equals(entryType))
{
quiesce = true;
}
else if (PORT_TYPE.equalsIgnoreCase(entryType))
{
if (attributes == null)
{
throw new IllegalConfigurationException("Port attributes are not set in " + entry);
}
Set<Protocol> protocols = getPortProtocolsAttribute(attributes);
if (protocols == null)
{
quiesce = true;
}
else
{
for (Protocol protocol : protocols)
{
switch (protocol)
{
case JMX_RMI:
quiesce = managementModeConnectorPort > 0 || managementModeRmiPort > 0;
break;
case RMI:
quiesce = managementModeRmiPort > 0;
break;
case HTTP:
case HTTPS:
quiesce = managementModeHttpPort > 0;
break;
default:
quiesce = true;
}
}
}
}
if (quiesce)
{
if (LOGGER.isDebugEnabled())
{
LOGGER.debug("Management mode quiescing entry " + entry);
}
// save original state
quiescedEntries.put(entry.getId(), attributes.get(ATTRIBUTE_STATE));
}
}
return quiescedEntries;
}
private Set<Protocol> getPortProtocolsAttribute(Map<String, Object> attributes)
{
Object object = attributes.get(Port.PROTOCOLS);
if (object == null)
{
return null;
}
return MapValueConverter.getEnumSetAttribute(Port.PROTOCOLS, attributes, Protocol.class);
}
private ConfigurationEntry createEntryWithState(ConfigurationEntry entry, Object state)
{
Map<String, Object> attributes = new HashMap<String, Object>(entry.getAttributes());
if (state == null)
{
attributes.remove(ATTRIBUTE_STATE);
}
else
{
attributes.put(ATTRIBUTE_STATE, state);
}
Set<UUID> originalChildren = entry.getChildrenIds();
Set<UUID> children = null;
if (originalChildren != null)
{
children = new HashSet<UUID>(originalChildren);
}
return new ConfigurationEntry(entry.getId(), entry.getType(), attributes, children, entry.getStore());
}
}