com.tangosol.internal.net.cluster.LegacyXmlClusterDependencies Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of coherence Show documentation
Show all versions of coherence Show documentation
Oracle Coherence Community Edition
/*
* Copyright (c) 2000, 2023, Oracle and/or its affiliates.
*
* Licensed under the Universal Permissive License v 1.0 as shown at
* https://oss.oracle.com/licenses/upl.
*/
package com.tangosol.internal.net.cluster;
import com.oracle.coherence.common.base.Logger;
import com.oracle.coherence.common.net.InetAddresses;
import com.tangosol.coherence.config.ParameterMacroExpressionParser;
import com.tangosol.coherence.config.builder.AddressProviderBuilder;
import com.tangosol.coherence.config.builder.ListBasedAddressProviderBuilder;
import com.tangosol.coherence.config.builder.ParameterizedBuilderRegistry;
import com.tangosol.coherence.config.builder.ServiceFailurePolicyBuilder;
import com.tangosol.coherence.config.builder.SocketProviderBuilder;
import com.tangosol.coherence.config.xml.OperationalConfigNamespaceHandler;
import com.tangosol.coherence.config.xml.processor.AddressProviderBuilderProcessor;
import com.tangosol.coherence.config.xml.processor.SocketProviderProcessor;
import com.tangosol.config.ConfigurationException;
import com.tangosol.config.expression.ChainedParameterResolver;
import com.tangosol.config.expression.ScopedParameterResolver;
import com.tangosol.config.expression.SystemEnvironmentParameterResolver;
import com.tangosol.config.expression.SystemPropertyParameterResolver;
import com.tangosol.config.xml.DefaultProcessingContext;
import com.tangosol.config.xml.DocumentProcessor;
import com.tangosol.config.xml.NamespaceHandler;
import com.tangosol.internal.net.InetAddressRangeFilter;
import com.tangosol.internal.net.LegacyXmlConfigHelper;
import com.tangosol.io.WrapperStreamFactory;
import com.tangosol.net.AddressProvider;
import com.tangosol.net.AddressProviderFactory;
import com.tangosol.net.CompositeAddressProvider;
import com.tangosol.net.ConfigurableAddressProviderFactory;
import com.tangosol.net.InetAddressHelper;
import com.tangosol.net.SocketOptions;
import com.tangosol.persistence.ConfigurableSnapshotArchiverFactory;
import com.tangosol.persistence.SnapshotArchiverFactory;
import com.tangosol.net.internal.SubstitutionAddressProvider;
import com.tangosol.run.xml.SimpleElement;
import com.tangosol.run.xml.XmlElement;
import com.tangosol.run.xml.XmlHelper;
import com.tangosol.util.Base;
import com.tangosol.util.Filter;
import com.tangosol.util.LiteMap;
import com.tangosol.util.ResourceRegistry;
import com.tangosol.util.SafeLinkedList;
import com.tangosol.util.SimpleResourceRegistry;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.time.Duration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* LegacyXmlClusterDependencies parses the XML to populate the DefaultClusterDependencies.
*
* NOTE: This code will eventually be replaced by CODI.
*
* @author pfm 2011.05.08
* @since Coherence 3.7.1
*/
@SuppressWarnings("deprecation")
public class LegacyXmlClusterDependencies
extends DefaultClusterDependencies
{
/**
* Populate the LegacyXmlClusterDependencies object from the XML DOM.
*
* @param xml the XML element
*
* @return this object
*/
public LegacyXmlClusterDependencies fromXml(XmlElement xml)
{
Base.azzert(xml.getName().equals("cluster-config"));
// ------------------------------------------------------------------------
// BEGIN: Use CODI to parse the operational configuration (this shouldn't be here!)
// Need to process socket-providers definitions before processing unicast/socket-provider
// since it can reference a socket-provider definition via name.
// ------------------------------------------------------------------------
// NOTE: This code should produce the entire ClusterDependencies instance.
DocumentProcessor.DefaultDependencies dependencies =
new DocumentProcessor.DefaultDependencies(new OperationalConfigNamespaceHandler());
// a ResourceRegistry for the cluster (this will be discarded after parsing)
ResourceRegistry resourceRegistry = new SimpleResourceRegistry();
// establish a default ParameterResolver based on the System properties
// COH-9952 wrap the code in privileged block for upper-stack products
ScopedParameterResolver resolver = AccessController
.doPrivileged((PrivilegedAction) () ->
new ScopedParameterResolver(new ChainedParameterResolver(
new SystemPropertyParameterResolver(),
new SystemEnvironmentParameterResolver())));
// finish configuring the dependencies
dependencies.setResourceRegistry(resourceRegistry);
dependencies.setDefaultParameterResolver(resolver);
dependencies.setExpressionParser(ParameterMacroExpressionParser.INSTANCE);
dependencies.setClassLoader(Base.getContextClassLoader());
// establish the cluster-config processing context
DefaultProcessingContext ctxClusterConfig = new DefaultProcessingContext(dependencies, xml);
// add the default namespace handler
NamespaceHandler handler = dependencies.getDefaultNamespaceHandler();
if (handler != null)
{
ctxClusterConfig.ensureNamespaceHandler("", handler);
}
// add the ParameterizedBuilderRegistry as a Cookie, so we can look it up
ctxClusterConfig.addCookie(ParameterizedBuilderRegistry.class, getBuilderRegistry());
ctxClusterConfig.addCookie(DefaultClusterDependencies.class, this);
// process custom resources
XmlElement xmlResources = xml.getSafeElement("resources");
SimpleResourceRegistry customResources = new SimpleResourceRegistry();
DefaultProcessingContext ctxResources = new DefaultProcessingContext(ctxClusterConfig, xmlResources);
ctxResources.processDocument(xmlResources);
setCustomResourcesRegistry(customResources);
// process the definitions. Could be referenced socket-provider.
XmlElement xmlPasswordProviders = xml.getSafeElement("password-providers");
DefaultProcessingContext ctxPasswordProviders = new DefaultProcessingContext(ctxClusterConfig, xmlPasswordProviders);
ctxPasswordProviders.processDocument(xmlPasswordProviders);
ctxPasswordProviders.close();
// process the definitions. could be referenced in unicast-listener/socket-provider.
XmlElement xmlSocketProviders = xml.getSafeElement("socket-providers");
DefaultProcessingContext ctxSocketProviders = new DefaultProcessingContext(ctxClusterConfig, xmlSocketProviders);
ctxSocketProviders.processDocument(xmlSocketProviders);
ctxSocketProviders.close();
// process the definition. This must be after processing the
// definitions becuase the global provider may be a reference to an exiting provider.
XmlElement xmlGlobalSocketProvider = xml.getSafeElement("global-socket-provider");
DefaultProcessingContext ctxGlobalSocketProvider = new DefaultProcessingContext(ctxClusterConfig, xmlGlobalSocketProvider);
ctxGlobalSocketProvider.processDocument(xmlGlobalSocketProvider);
ctxGlobalSocketProvider.close();
// ------------------------------------------------------------------------
// SUSPEND: Use CODI to parse the operational configuration
// ------------------------------------------------------------------------
// the member identity gets data from both member-identity XML and unicast-listener xml.
DefaultMemberIdentity memberIdentity = new DefaultMemberIdentity();
configureMemberIdentity(xml, memberIdentity);
configureMulticastListener(xml); // this must be called before configureUnicastListener
configureAddressProviders(xml); // this must be called before configureUnicastListener
// COH-14170 replace SocketProviderFactory method calls using getUnicastSocketProviderXml()
XmlElement xmlUnicastSocketProvider = xml.getSafeElement("unicast-listener").getSafeElement("socket-provider");
DefaultProcessingContext ctxUnicastSocketProvider = new DefaultProcessingContext(ctxClusterConfig, xmlUnicastSocketProvider);
SocketProviderBuilder builder = new SocketProviderProcessor().process(ctxUnicastSocketProvider, xmlUnicastSocketProvider);
setUnicastSocketProviderBuilder(builder);
configureUnicastListener(xml, memberIdentity);
setMemberIdentity(memberIdentity);
configureTcpRingListener(xml);
configureShutdownListener(xml);
configureServiceGuardian(xml);
configurePacketSpeaker(xml);
configurePacketPublisher(xml);
configureIncomingMessageHandler(xml);
configureOutgoingMessageHandler(xml);
configureAuthorizedHosts(xml);
configureServices(xml);
configureFilters(xml);
configureSnapshotArchivers(xml);
configureClusterQuorumPolicy(xml);
// new in version 3.2: support configuration of license info
// this is from
String sEdition = xml.getSafeElement("edition-name").getString("CE");
setEdition(translateEditionName(sEdition));
String sMode = xml.getSafeElement("license-mode").getString("dev");
setMode(translateModeName(sMode));
setLambdasSerializationMode(xml.getSafeElement("lambdas-serialization").getString());
// ------------------------------------------------------------------------
// RESUME: Use CODI to parse the operational configuration (this shouldn't be here!)
// ------------------------------------------------------------------------
// process the
XmlElement xmlStorageAuthorizers = xml.getSafeElement("storage-authorizers");
DefaultProcessingContext ctxStorageAuthorizers = new DefaultProcessingContext(ctxClusterConfig,
xmlStorageAuthorizers);
ctxStorageAuthorizers.processDocument(xmlStorageAuthorizers);
XmlElement xmlSerializers = xml.getSafeElement("serializers");
DefaultProcessingContext ctxSerializers = new DefaultProcessingContext(ctxClusterConfig, xmlSerializers);
ctxSerializers.processDocument(xmlSerializers);
XmlElement xmlEnv = xml.getSafeElement("persistence-environments");
DefaultProcessingContext ctxPersistenceEnvironments = new DefaultProcessingContext(ctxClusterConfig, xmlEnv);
ctxPersistenceEnvironments.processDocument(xmlEnv);
// close the contexts we created
ctxUnicastSocketProvider.close();
ctxResources.close();
ctxSerializers.close();
ctxStorageAuthorizers.close();
ctxPersistenceEnvironments.close();
ctxClusterConfig.close();
// ------------------------------------------------------------------------
// END: Use CODI to parse the operational configuration
// ------------------------------------------------------------------------
return this;
}
// ----- internal methods ------------------------------------------------------
/**
* Configure the member identity fields.
*
* @param xml the member-identity xml element
* @param memberIdentity the memberIdentity to configure
*/
private void configureMemberIdentity(XmlElement xml, DefaultMemberIdentity memberIdentity)
{
XmlElement xmlCat = xml.getSafeElement("member-identity");
memberIdentity.setClusterName(xmlCat.getSafeElement("cluster-name").getString(memberIdentity.getClusterName()));
memberIdentity.setSiteName(xmlCat.getSafeElement("site-name").getString(memberIdentity.getSiteName()));
memberIdentity.setRackName(xmlCat.getSafeElement("rack-name").getString(memberIdentity.getRackName()));
memberIdentity.setMachineName(xmlCat.getSafeElement("machine-name").getString(memberIdentity.getMachineName()));
memberIdentity.setProcessName(xmlCat.getSafeElement("process-name").getString(memberIdentity.getProcessName()));
memberIdentity.setMemberName(xmlCat.getSafeElement("member-name").getString(memberIdentity.getMemberName()));
memberIdentity.setRoleName(xmlCat.getSafeElement("role-name").getString(memberIdentity.getRoleName()));
memberIdentity.setPriority(xmlCat.getSafeElement("priority").getInt(memberIdentity.getPriority()));
}
/**
* Configure the multicast listener fields.
*
* @param xml the multicast-listener xml element
*/
private void configureMulticastListener(XmlElement xml)
{
XmlElement xmlCat = xml.getSafeElement("multicast-listener");
//
setGroupInterface(resolveGroupInterface(xmlCat.getSafeElement("interface").getString("")));
//
setGroupAddress(resolveGroupAddress(xmlCat.getSafeElement("address").getString(DEFAULT_ADDR)));
//
setGroupPort(xmlCat.getSafeElement("port").getInt(getGroupPort()));
//
setGroupTimeToLive(xmlCat.getSafeElement("time-to-live").getInt(getGroupTimeToLive()));
//
XmlElement xmlSub = xmlCat.getSafeElement("packet-buffer");
XmlElement xmlVal = xmlSub.getElement("maximum-packets");
if (xmlVal == null) // size based
{
//
setGroupBufferSize((int) Base.parseMemorySize(
xmlSub.getSafeElement("size").getString(Integer.toString(getGroupBufferSize()))));
}
else
//
{
// recorded as negative size since we may not know the packet size
// until Cluster.onStart
setGroupBufferSize(-xmlVal.getInt());
if (xmlSub.getElement("size") != null)
{
throw new IllegalArgumentException("cannot specify maximum-packets and size within packet-buffer");
}
}
//
setGroupListenerPriority(xmlCat.getSafeElement("priority").getInt(getGroupListenerPriority()));
//
setClusterAnnounceTimeoutMillis(xmlCat.getSafeElement("join-timeout-milliseconds").getInt(
getClusterAnnounceTimeoutMillis()));
//
setPublisherGroupThreshold(xmlCat.getSafeElement("multicast-threshold-percent").getInt(
getPublisherGroupThreshold()));
}
/**
* Configure the unicast listener fields.
*
* @param xml the unicast-listener xml element
* @param memberIdentity this is needed to set the machine id.
*/
private void configureUnicastListener(XmlElement xml, DefaultMemberIdentity memberIdentity)
{
XmlElement xmlCat = xml.getSafeElement("unicast-listener");
// Delete when deprecated method getUnicastSocketProviderXml() is removed.
//
setUnicastSocketProviderXml(xmlCat.getSafeElement("socket-provider"));
//
setReliableTransport(xmlCat.getSafeElement("reliable-transport").getString(getReliableTransport()));
// - undocumented
setTcpDatagramSocketOptions(SocketOptions.load(xmlCat.getSafeElement("socket-options")));
//
memberIdentity.setMachineId(Integer.parseInt(xmlCat.getSafeElement("machine-id").getString("0")));
//
String sAddr = xmlCat.getSafeElement("address").getString();
if (sAddr != null && !sAddr.trim().isEmpty())
{
try
{
setLocalAddress(InetAddressHelper.getLocalAddress(sAddr));
}
catch (UnknownHostException e)
{
throw new IllegalArgumentException("unresolvable localhost " + sAddr, e);
}
}
//
setLocalPort(xmlCat.getSafeElement("port").getInt(getLocalPort()));
//
XmlElement xmlValue = xmlCat.getSafeElement("port-auto-adjust");
String sPortAuto = xmlValue.getString().trim();
if (sPortAuto.length() > 0 && Character.isDigit(sPortAuto.charAt(0)))
{
setLocalPortAutoAdjust(xmlValue.getInt(getLocalPortAutoAdjust()));
}
else
{
setLocalPortAutoAdjust(xmlValue.getBoolean(isLocalPortAutoAdjust()));
}
//
XmlElement xmlSub = xmlCat.getSafeElement("packet-buffer");
XmlElement xmlVal = xmlSub.getElement("maximum-packets");
if (xmlVal == null) // size based
{
//
setLocalBufferSize((int) Base.parseMemorySize(
xmlSub.getSafeElement("size").getString(Integer.toString(getLocalBufferSize()))));
}
else
//
{
// recorded as negative size since we may not know the packet size
// until Cluster.onStart
setLocalBufferSize(-xmlVal.getInt());
if (xmlSub.getElement("size") != null)
{
throw new IllegalArgumentException("cannot specify maximum-packets and size within packet-buffer");
}
}
//
setLocalListenerPriority(xmlCat.getSafeElement("priority").getInt(getLocalListenerPriority()));
//
setWellKnownAddresses(createWkaAddressProvider(xmlCat.getSafeElement("well-known-addresses")));
//
String sAddrDiscovery = xmlCat.getSafeElement("discovery-address").getString();
if (sAddrDiscovery != null && !sAddrDiscovery.trim().isEmpty())
{
try
{
setLocalDiscoveryAddress(InetAddressHelper.getLocalAddress(sAddrDiscovery));
}
catch (UnknownHostException e)
{
throw new IllegalArgumentException("unresolvable discovery address " + sAddrDiscovery, e);
}
}
}
/**
* Configure the tcpring listener fields.
*
* @param xml the tcpring-listener xml element
*/
private void configureTcpRingListener(XmlElement xml)
{
XmlElement xmlCat = xml.getSafeElement("tcp-ring-listener");
//
setTcpRingEnabled(xmlCat.getSafeElement("enabled").getBoolean(isTcpRingEnabled()));
//
setIpMonitorTimeoutMillis(XmlHelper.parseTime(xmlCat, "ip-timeout", getIpMonitorTimeoutMillis()));
//
setIpMonitorAttempts(xmlCat.getSafeElement("ip-attempts").getInt(getIpMonitorAttempts()));
//
setTcpBacklog(xmlCat.getSafeElement("listen-backlog").getInt(getTcpBacklog()));
//
setIpMonitorPriority(xmlCat.getSafeElement("priority").getInt(getIpMonitorPriority()));
// - undocumented
setTcpRingSocketOptions(SocketOptions.load(xmlCat.getSafeElement("socket-options")));
}
/**
* Configure the shutdown listener fields.
*
* @param xml the shutdown-listener xml element
*/
private void configureShutdownListener(XmlElement xml)
{
XmlElement xmlCat = xml.getSafeElement("shutdown-listener");
//
String sShutdownOption = xmlCat.getSafeElement("enabled").getString();
int nShutdownOption = getShutdownHookOption();
switch (sShutdownOption)
{
case "force":
case "true":
nShutdownOption = ClusterDependencies.SHUTDOWN_FORCE;
break;
case "none":
case "false":
nShutdownOption = ClusterDependencies.SHUTDOWN_NONE;
break;
case "graceful":
nShutdownOption = ClusterDependencies.SHUTDOWN_GRACEFUL;
break;
}
setShutdownHookOption(nShutdownOption);
}
/**
* Configure the service guardian fields.
*
* @param xml the service-guardian xml element
*/
private void configureServiceGuardian(XmlElement xml)
{
//
XmlElement xmlCat = xml.getSafeElement("service-guardian");
//
XmlElement xmlSub = xmlCat.getSafeElement("service-failure-policy");
ServiceFailurePolicyBuilder builder = LegacyXmlConfigHelper.parseServiceFailurePolicyBuilder(xmlSub);
if (builder != null)
{
setServiceFailurePolicyBuilder(builder);
}
//
setGuardTimeoutMillis(xmlCat.getSafeElement("timeout-milliseconds").getLong(getGuardTimeoutMillis()));
}
/**
* Configure the packet speaker fields.
*
* @param xml the packet-speaker xml element
*/
private void configurePacketSpeaker(XmlElement xml)
{
XmlElement xmlCat = xml.getSafeElement("packet-speaker");
//
setSpeakerEnabled(xmlCat.getSafeElement("enabled").getBoolean(isSpeakerEnabled()));
//
XmlElement xmlSub = xmlCat.getSafeElement("volume-threshold");
//
setSpeakerVolumeMinimum(xmlSub.getSafeElement("minimum-packets").getInt(getSpeakerVolumeMinimum()));
//
setSpeakerPriority(xmlCat.getSafeElement("priority").getInt(getSpeakerPriority()));
}
/**
* Configure the packet publisher fields.
*
* @param xml the packet-publisher xml element
*/
private void configurePacketPublisher(XmlElement xml)
{
XmlElement xmlCat = xml.getSafeElement("packet-publisher");
//
XmlElement xmlSub = xmlCat.getSafeElement("packet-size");
//
setPacketMaxLength(xmlSub.getSafeElement("maximum-length").getInt(getPacketMaxLength()));
//
setPacketPreferredLength(xmlSub.getSafeElement("preferred-length").getInt(getPacketPreferredLength()));
//
xmlSub = xmlCat.getSafeElement("packet-delivery");
//
setPublisherResendDelayMillis(xmlSub.getSafeElement("resend-milliseconds").getInt(
getPublisherResendDelayMillis()));
//
setPublisherResendTimeoutMillis(xmlSub.getSafeElement("timeout-milliseconds").getInt(
getPublisherResendTimeoutMillis()));
//
setClusterHeartbeatDelayMillis(xmlSub.getSafeElement("heartbeat-milliseconds").getInt(
getClusterHeartbeatDelayMillis()));
//
XmlElement xmlSub2 = xmlSub.getSafeElement("flow-control");
//
setFlowControlEnabled(xmlSub2.getSafeElement("enabled").getBoolean(isFlowControlEnabled()));
//
setLostPacketThreshold(xmlSub2.getSafeElement("pause-detection/maximum-packets").getInt(
getLostPacketThreshold()));
//
XmlElement xmlVal = xmlSub2.getSafeElement("outstanding-packets");
setOutstandingPacketMaximum(xmlVal.getSafeElement("maximum-packets").getInt(getOutstandingPacketMaximum()));
// read min second so it can be validated against max
setOutstandingPacketMinimum(xmlVal.getSafeElement("minimum-packets").getInt(getOutstandingPacketMinimum()));
//
xmlSub2 = xmlSub.getSafeElement("packet-bundling");
//
String sTime = xmlSub2.getSafeElement("maximum-deferral-time").getString();
if (sTime.length() > 0)
{
setPacketBundlingThresholdNanos(Base.parseTimeNanos(sTime));
}
//
setPacketBundlingAggression(xmlSub2.getSafeElement("aggression-factor").getDouble(
getPacketBundlingAggression()));
//
xmlSub = xmlCat.getSafeElement("notification-queueing");
//
setPublisherAckDelayMillis(xmlSub.getSafeElement("ack-delay-milliseconds").getInt(
getPublisherAckDelayMillis()));
//
setPublisherNackDelayMillis(xmlSub.getSafeElement("nack-delay-milliseconds").getInt(
getPublisherNackDelayMillis()));
//
xmlSub = xmlCat.getSafeElement("traffic-jam");
//
setPublisherCloggedCount(xmlSub.getSafeElement("maximum-packets").getInt(getPublisherCloggedCount()));
//
setPublisherCloggedDelayMillis(xmlSub.getSafeElement("pause-milliseconds").getInt(
getPublisherCloggedDelayMillis()));
//
xmlSub = xmlCat.getSafeElement("packet-buffer");
xmlVal = xmlSub.getElement("maximum-packets");
if (xmlVal == null) // size based
{
//
setPublisherSocketBufferSize((int) Base.parseMemorySize(
xmlSub.getSafeElement("size").getString(Integer.toString(getPublisherSocketBufferSize()))));
}
else
//
{
// recorded as negative size since we may not know the packet size
// until Cluster.onStart
setPublisherSocketBufferSize(-xmlVal.getInt());
if (xmlSub.getElement("size") != null)
{
throw new IllegalArgumentException("cannot specify maximum-packets and size within packet-buffer");
}
}
//
setPublisherPriority(xmlCat.getSafeElement("priority").getInt(getPublisherPriority()));
//
setTcmpEnabled(xmlCat.getSafeElement("enabled").getBoolean(isTcmpEnabled()));
}
/**
* Configure the incoming message handler fields.
*
* @param xml the incoming-message-handler xml element
*/
private void configureIncomingMessageHandler(XmlElement xml)
{
XmlElement xmlCat = xml.getSafeElement("incoming-message-handler");
//
setClusterTimestampMaxVarianceMillis(xmlCat.getSafeElement("maximum-time-variance").getInt(
getClusterTimestampMaxVarianceMillis()));
//
setReceiverNackEnabled(xmlCat.getSafeElement("use-nack-packets").getBoolean(isReceiverNackEnabled()));
//
setReceiverPriority(xmlCat.getSafeElement("priority").getInt(getReceiverPriority()));
}
/**
* Configure the outgoing message handler fields.
*
* @param xml the outgoing-message-handler xml element
*/
@SuppressWarnings("unchecked")
private void configureOutgoingMessageHandler(XmlElement xml)
{
XmlElement xmlCat = xml.getSafeElement("outgoing-message-handler");
//
List listFilter = new SafeLinkedList();
listFilter.addAll(LegacyXmlConfigHelper.parseFilterList(xmlCat));
setFilterList(listFilter);
}
/**
* Configure the authorized hosts fields.
*
* @param xml the authorized-hosts xml element
*/
@SuppressWarnings("rawtypes")
private void configureAuthorizedHosts(XmlElement xml)
{
XmlElement xmlCat = xml.getSafeElement("authorized-hosts");
// Use a custom filter if is specified.
//
XmlElement xmlVal = xmlCat.getElement("host-filter");
if (xmlVal != null && !XmlHelper.isEmpty(xmlVal))
{
setAuthorizedHostFilter((Filter) XmlHelper.createInstance(xmlVal,
/*loader*/ null, /*resolver*/ null, Filter.class));
// don't process any host-addresses since there is a custom filter.
return;
}
InetAddressRangeFilter filter = new InetAddressRangeFilter();
boolean fFilterAdded = false;
//
for (Iterator iter = xmlCat.getElements("host-address"); iter.hasNext(); )
{
xmlVal = (XmlElement) iter.next();
if (addAuthorizedHostsToFilter(filter, xmlVal.getString(), /* sAddrTo */ null))
{
fFilterAdded = true;
}
}
//
for (Iterator iter = xmlCat.getElements("host-range"); iter.hasNext(); )
{
xmlVal = (XmlElement) iter.next();
if (addAuthorizedHostsToFilter(filter, xmlVal.getSafeElement("from-address").getString(),
xmlVal.getSafeElement("to-address").getString()))
{
fFilterAdded = true;
}
}
if (fFilterAdded)
{
// the XML successfully specified at least 1 range so set the filter.
// NOTE: Never call setAuthorizedHostFilter if the filter is empty.
setAuthorizedHostFilter(filter);
}
}
/**
* Configure the services fields.
*
* @param xml the services xml element
*/
@SuppressWarnings("rawtypes")
private void configureServices(XmlElement xml)
{
Map mapService = new LiteMap<>();
Map> mapServiceFilter = new LiteMap<>();
for (Iterator iter = xml.getSafeElement("services").getElements("service"); iter.hasNext(); )
{
XmlElement xmlService = (XmlElement) iter.next();
String sType = xmlService.getSafeElement("service-type").getString();
String sComponent = xmlService.getSafeElement("service-component").getString();
mapService.put(sType, sComponent);
mapServiceFilter.put(sType, LegacyXmlConfigHelper.parseFilterList(xmlService));
// TODO - COH-5021 For now the ServiceTemplateMap is not used and it
// is empty
// Service.Template template = new Service.Template(sType,
// XmlHelper.transformInitParams(new SimpleElement(
// "config"), xmlService.getSafeElement("init-params")));
// String sType, XmlElement xmlInitParam;
}
setServiceMap(mapService);
// setServiceTemplateMap(mapServiceTemplate);
setServiceFilterMap(mapServiceFilter);
}
/**
* Configure the filter by creating a map of filters indexed by filter name.
*
* @param xml the filters xml element
*/
@SuppressWarnings("rawtypes")
private void configureFilters(XmlElement xml)
{
Map mapFilter = new LiteMap<>();
for (Iterator iter = xml.getSafeElement("filters").getElements("filter"); iter.hasNext(); )
{
XmlElement xmlFilter = (XmlElement) iter.next();
addFilterToMap(xmlFilter, mapFilter);
}
setFilterMap(mapFilter);
}
/**
* Configure the snapshot archivers by populating a map of snapshot
* archiver factories indexed by id.
*
* @param xml the snapshot-archivers xml element
*/
private void configureSnapshotArchivers(XmlElement xml)
{
Map mapSnapshotArchivers = new LiteMap<>();
for (Object o : xml.getSafeElement("snapshot-archivers").getElementList())
{
XmlElement xmlSnapshotArchivers = (XmlElement) o;
String sName = xmlSnapshotArchivers.getSafeAttribute("id").getString();
ConfigurableSnapshotArchiverFactory factory = new ConfigurableSnapshotArchiverFactory();
factory.setConfig(xmlSnapshotArchivers);
mapSnapshotArchivers.put(sName, factory);
}
setSnapshotArchiverMap(mapSnapshotArchivers);
}
/**
* Configure the address providers by populating a map of address provider factories
* indexed by id.
*
* @param xml the address-providers xml element
*/
@SuppressWarnings("rawtypes")
private void configureAddressProviders(XmlElement xml)
{
Map mapAddressProvider = new LiteMap<>();
// construct a "cluster-discovery" address provider based on WKA or MC address; see TcpInitiator.onDependencies
AddressProviderFactory factoryCluster;
XmlElement xmlWKA = xml.getSafeElement("unicast-listener").getSafeElement("well-known-addresses");
if (createWkaAddressProvider(xmlWKA) == null)
{
if (isWkaPresent(xmlWKA))
{
throw new IllegalArgumentException("Unresolvable WKA address(s) " + xmlWKA);
}
ListBasedAddressProviderBuilder factoryMulticast = new ListBasedAddressProviderBuilder();
factoryMulticast.add(getGroupAddress().getHostAddress(), getGroupPort());
factoryCluster = factoryMulticast;
}
else
{
factoryCluster = SubstitutionAddressProvider.createFactory(LegacyXmlConfigHelper
.parseAddressProvider("well-known-addresses", xml.getSafeElement("unicast-listener"), mapAddressProvider),
getGroupPort());
}
mapAddressProvider.put("cluster-discovery", factoryCluster);
for (Iterator iter = xml.getSafeElement("address-providers").getElements("address-provider"); iter.hasNext(); )
{
XmlElement xmlAddressProvider = (XmlElement) iter.next();
String sName = xmlAddressProvider.getSafeAttribute("id").getString();
XmlElement xmlLocalAddress = xmlAddressProvider.getElement("local-address");
if (mapAddressProvider.containsKey(sName))
{
throw new ConfigurationException("address provider '" + sName + "' has already been defined",
"remove duplicate provider definition");
}
else if (xmlLocalAddress == null)
{
ConfigurableAddressProviderFactory factory = new ConfigurableAddressProviderFactory();
factory.setConfig(xmlAddressProvider);
mapAddressProvider.put(sName, factory);
}
else
{
@SuppressWarnings("unused")
AddressProviderBuilder builder =
AddressProviderBuilderProcessor.newLocalAddressProviderBuilder(xmlLocalAddress);
}
}
setAddressProviderMap(mapAddressProvider);
}
/**
* Configure the cluster quorum policy.
*
* @param xml the cluster-quorum-policy xml element
*/
private void configureClusterQuorumPolicy(XmlElement xml)
{
XmlElement xmlCat = xml.getSafeElement("cluster-quorum-policy");
setClusterActionPolicyBuilder(new LegacyXmlConfigurableQuorumPolicy().createPolicyBuilder(xmlCat, null,
Base.getContextClassLoader()));
}
/**
* Add an authorized host range to the filter.
*
* @param sAddrFrom from address
* @param sAddrTo to address
*
* @return true if filter added
*/
private boolean addAuthorizedHostsToFilter(InetAddressRangeFilter filter, String sAddrFrom, String sAddrTo)
{
if (sAddrFrom == null || sAddrFrom.length() == 0)
{
if (sAddrTo != null && sAddrTo.length() != 0)
{
ensureAuthorizedHostFilter();
Base.azzertFailed("Both and elements must be specified");
}
return false;
}
InetAddress addrFrom;
InetAddress addrTo;
try
{
addrFrom = InetAddress.getByName(sAddrFrom);
addrTo = sAddrTo == null ? addrFrom : InetAddress.getByName(sAddrTo);
}
catch (UnknownHostException e)
{
Base.trace("Unresolvable authorized host will be ignored: " + e);
return false;
}
filter.addRange(addrFrom, addrTo);
return true;
}
/**
* Create a filter factory and add it to the filter map.
*
* @param xmlFilter the xml element
* @param mapFilter the map that holds the factory entries
*/
@SuppressWarnings("unchecked")
private void addFilterToMap(XmlElement xmlFilter, Map mapFilter)
{
String sClass = xmlFilter.getSafeElement("filter-class").getString();
String sName = xmlFilter.getSafeElement("filter-name").getString();
if (sName.length() == 0)
{
sName = xmlFilter.getSafeAttribute("id").getString();
}
XmlElement xmlConfig = new SimpleElement("filter");
XmlElement xmlInstance = xmlConfig.ensureElement("instance");
xmlInstance.ensureElement("class-name").setString(sClass);
XmlElement xmlParams = xmlFilter.getElement("init-params");
if (xmlParams != null)
{
xmlInstance.getElementList().add(xmlParams);
}
try
{
WrapperStreamFactory factory = (WrapperStreamFactory) XmlHelper.createInstance(xmlConfig,
Base.getContextClassLoader(),
/* resolver */
null, WrapperStreamFactory.class);
mapFilter.put(sName, factory);
}
catch (Throwable e)
{
throw new IllegalArgumentException("Error instantiating Filter with name: " + sName);
}
}
/**
* Parse the well known addresses to produce an AddressProvider.
*
* @param xml the well-known-addresses element
*
* @return the WKA address provider, or null if WKA is not enabled
*/
@SuppressWarnings("ConstantConditions")
private AddressProvider createWkaAddressProvider(XmlElement xml)
{
AddressProviderFactory factory = LegacyXmlConfigHelper.parseAddressProvider(xml, getAddressProviderMap());
AddressProvider provider = new SubstitutionAddressProvider(factory.createAddressProvider(null), getGroupPort());
if (!(provider instanceof Set))
{
CompositeAddressProvider providerComposite = new CompositeAddressProvider();
providerComposite.addProvider(provider);
provider = providerComposite;
}
Set> set = (Set>) provider;
if (set.isEmpty())
{
boolean fRetry = Boolean.getBoolean(PROP_WKA_RESOLVE_RETRY);
if (fRetry)
{
long nTimeout = Long.parseLong(System.getProperty(PROP_WKA_TIMEOUT,
String.valueOf(DEFAULT_WKA_RESOLVE_TIMEOUT.toMillis())));
long nRetry = Long.parseLong(System.getProperty(PROP_WKA_RESOLVE_FREQUENCY,
String.valueOf(DEFAULT_WKA_RESOLVE_FREQUENCY.toMillis())));
long nStart = System.currentTimeMillis();
Logger.info("Failed to resolve WKA addresses, retrying for " + nTimeout + " millis");
while (set.isEmpty() && nTimeout > (System.currentTimeMillis() - nStart))
{
Base.sleep(nRetry);
}
}
}
return ((Set>) provider).isEmpty() ? null : provider;
}
/**
* Ensure that the authorized host filter
*
* NOTE: Do not create this unless there are authorized hosts or else Coherence will
* reject the member during a join.
*/
private void ensureAuthorizedHostFilter()
{
Filter> filter = getAuthorizedHostFilter();
if (filter == null)
{
setAuthorizedHostFilter(new InetAddressRangeFilter());
}
}
/**
* Resolve the group address string.
*
* @param sAddr the group address string
*
* @return the group address
*/
private InetAddress resolveGroupAddress(String sAddr)
{
InetAddress addr = null;
if (sAddr != null && sAddr.trim().length() > 0)
{
try
{
addr = InetAddress.getByName(sAddr);
}
catch (Exception e)
{
throw Base.ensureRuntimeException(e, "Address=" + sAddr);
}
}
return addr;
}
/**
* Resolve the group interface string.
*
* @param sAddr the group interface
*
* @return the group interface InetAddress
*/
private InetAddress resolveGroupInterface(String sAddr)
{
InetAddress addr = null;
if (sAddr != null && sAddr.trim().length() > 0)
{
try
{
addr = InetAddresses.getLocalAddress(sAddr);
}
catch (Exception e)
{
throw Base.ensureRuntimeException(e, "Interface=" + sAddr);
}
}
return addr;
}
/**
* Translate the edition name.
*
* @param sName edition name
*
* @return edition integer
*/
private int translateEditionName(String sName)
{
Base.checkNotNull(sName, "Edition name");
String[] asNames =
{
"DC", "RTC", "SE", "CE", "EE", "GE"
};
for (int i = 0; i < asNames.length; i++)
{
if (asNames[i].equalsIgnoreCase(sName))
{
return i;
}
}
throw new IllegalArgumentException("Invalid edition name " + sName);
}
/**
* Translate the mode name into an integer
*
* @param sName mode name
*
* @return the mode integer
*/
private int translateModeName(String sName)
{
Base.checkNotNull(sName, "Mode ");
String[] names = {"eval", "dev", "prod"};
for (int i = 0; i < names.length; i++)
{
if (names[i].equalsIgnoreCase(sName))
{
return i;
}
}
throw new IllegalArgumentException("Invalid mode " + sName);
}
/**
* Return true if a WKA list is configured.
*
* @return true if a WKA list is configured
*/
@SuppressWarnings("unchecked")
private boolean isWkaPresent(XmlElement xmlConfig)
{
if (xmlConfig != null)
{
for (XmlElement xmlAddr : (List) xmlConfig.getElementList())
{
String sAddr;
switch (xmlAddr.getName())
{
case "socket-address":
sAddr = xmlAddr.getSafeElement("address").getString().trim();
break;
case "host-address":
case "address":
sAddr = xmlAddr.getString().trim();
break;
default:
continue;
}
if (!sAddr.isEmpty())
{
return true;
}
}
}
return false;
}
// ----- constants ------------------------------------------------------
/**
* The name of the System property to configure maximum time to attempt to resolve wka addresses.
* Set this system property to a number of milliseconds.
*/
public static final String PROP_WKA_TIMEOUT = "coherence.wka.dns.resolution.timeout";
/**
* System property for configuring the frequency to attempt dns resolution of wka addresses.
* Set this system property to a number of milliseconds.
*/
public static final String PROP_WKA_RESOLVE_FREQUENCY = "coherence.wka.dns.resolution.frequency";
/**
* The System property to set to block WKA resolution until at least one WKA address has been resolved.
*
* The default behaviour is not to retry.
*/
public static final String PROP_WKA_RESOLVE_RETRY = "coherence.wka.dns.resolution.retry";
/**
* The default timeout to wait for resolution of at least one WKA address.
*/
public static final Duration DEFAULT_WKA_RESOLVE_TIMEOUT = Duration.ofMinutes(6);
/**
* The default retry frequency to attempt resolution of at least one WKA address.
*/
public static final Duration DEFAULT_WKA_RESOLVE_FREQUENCY = Duration.ofMillis(10);
}