Skip to content

Commit

Permalink
Add ConfigRecognizer API (#16958)
Browse files Browse the repository at this point in the history
Add ConfigRecognizer API

This commit introduces the ConfigRecognition API that is meant to
recognize if a provided declarative configuration is recognized by the
rules defined in a given implementation. The main use case for this
implementation is to recognize member, client and failover client XML
and YAML configurations just by looking into the content of the
configuration, without building any actual configuration.

Along with the API the following three implementations are added:
- MemberConfigRecognizer for recognizing member XML and YAML
configurations
- ClientConfigRecognizer for recognizing client XML and YAML
configurations
- ClientFailoverConfigRecognizer for recognizing failover client XML and
YAML configurations

All the three are extensible with custom recognizers so that even those
configurations can be recognized that would otherwise remain
unrecognized with the built-in set of recognizers that recognizes XML
and YAML configurations by checking the root node in the provided
configuration.

The API recognizes configuration provided in InputStreams only, while
the ConfigBuilder implementations can be built from files defined by
their location and URLs too. The reason for lacking the support for
these two options is that both are easy to convert to InputStreams and
that handling errors caused by non-existing resources, missing
privileges etc should be handled outside of this API with potentially
having more contextual information.

The built-in implementations honour parse errors with unrecognized
configuration. The reason is that the provided InputStream can be tested
both for XML and YAML configuration and at least one is expected to
lead to parse errors.

Implements #16866
  • Loading branch information
blazember committed Jun 26, 2020
1 parent 7708a85 commit 7d63cfd
Show file tree
Hide file tree
Showing 18 changed files with 1,314 additions and 3 deletions.
@@ -0,0 +1,72 @@
/*
* Copyright (c) 2008-2020, Hazelcast, Inc. All Rights Reserved.
*
* Licensed 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 com.hazelcast.client.config;

import com.hazelcast.client.config.impl.ClientXmlConfigRootTagRecognizer;
import com.hazelcast.client.config.impl.ClientYamlConfigRootTagRecognizer;
import com.hazelcast.config.ConfigRecognizer;
import com.hazelcast.internal.config.AbstractConfigRecognizer;

import java.util.LinkedList;
import java.util.List;

import static java.util.Arrays.asList;

/**
* {@link ConfigRecognizer} implementation that recognizes Hazelcast
* client declarative configurations based on an extensible set of
* built-in {@link ConfigRecognizer} implementations.
*/
public class ClientConfigRecognizer extends AbstractConfigRecognizer {

/**
* Constructs an instance with the built-in set of
* {@link ConfigRecognizer} implementations only.
*
* @throws Exception If there is an unexpected error occur during
* instantiation.
*/
public ClientConfigRecognizer() throws Exception {
super(builtInRecognizers());
}

/**
* Constructs an instance with the built-in set of
* {@link ConfigRecognizer} implementations extended with ones
* provided in {@code customRecognizers}.
*
* @param customRecognizers The custom config recognizers to use
* besides the built-in ones.
* @throws Exception If there is an unexpected error occur during
* instantiation.
*/
public ClientConfigRecognizer(ConfigRecognizer... customRecognizers) throws Exception {
super(recognizers(customRecognizers));
}

private static List<ConfigRecognizer> recognizers(ConfigRecognizer... customRecognizers) throws Exception {
List<ConfigRecognizer> configRecognizers = new LinkedList<>(builtInRecognizers());
configRecognizers.addAll(asList(customRecognizers));
return configRecognizers;
}

private static List<ConfigRecognizer> builtInRecognizers() throws Exception {
return asList(
new ClientXmlConfigRootTagRecognizer(),
new ClientYamlConfigRootTagRecognizer());
}
}
@@ -0,0 +1,72 @@
/*
* Copyright (c) 2008-2020, Hazelcast, Inc. All Rights Reserved.
*
* Licensed 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 com.hazelcast.client.config;

import com.hazelcast.client.config.impl.ClientFailoverXmlConfigRootTagRecognizer;
import com.hazelcast.client.config.impl.ClientFailoverYamlConfigRootTagRecognizer;
import com.hazelcast.config.ConfigRecognizer;
import com.hazelcast.internal.config.AbstractConfigRecognizer;

import java.util.LinkedList;
import java.util.List;

import static java.util.Arrays.asList;

/**
* {@link ConfigRecognizer} implementation that recognizes Hazelcast
* client failover declarative configurations based on an extensible set
* of built-in {@link ConfigRecognizer} implementations.
*/
public class ClientFailoverConfigRecognizer extends AbstractConfigRecognizer {

/**
* Constructs an instance with the built-in set of
* {@link ConfigRecognizer} implementations only.
*
* @throws Exception If there is an unexpected error occur during
* instantiation.
*/
public ClientFailoverConfigRecognizer() throws Exception {
super(builtInRecognizers());
}

/**
* Constructs an instance with the built-in set of
* {@link ConfigRecognizer} implementations extended with ones
* provided in {@code customRecognizers}.
*
* @param customRecognizers The custom config recognizers to use
* besides the built-in ones.
* @throws Exception If there is an unexpected error occur during
* instantiation.
*/
public ClientFailoverConfigRecognizer(ConfigRecognizer... customRecognizers) throws Exception {
super(recognizers(customRecognizers));
}

private static List<ConfigRecognizer> recognizers(ConfigRecognizer... customRecognizers) throws Exception {
List<ConfigRecognizer> configRecognizers = new LinkedList<>(builtInRecognizers());
configRecognizers.addAll(asList(customRecognizers));
return configRecognizers;
}

private static List<ConfigRecognizer> builtInRecognizers() throws Exception {
return asList(
new ClientFailoverXmlConfigRootTagRecognizer(),
new ClientFailoverYamlConfigRootTagRecognizer());
}
}
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2008-2020, Hazelcast, Inc. All Rights Reserved.
*
* Licensed 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 com.hazelcast.client.config.impl;

import com.hazelcast.config.ConfigRecognizer;
import com.hazelcast.internal.config.AbstractXmlConfigRootTagRecognizer;

/**
* This {@link ConfigRecognizer} implementation recognizes Hazelcast
* failover client XML configuration by checking if the defined root tag
* is "hazelcast-client-failover" or not. For the implementation details
* please refer to the {@link AbstractXmlConfigRootTagRecognizer}
* documentation.
*/
public class ClientFailoverXmlConfigRootTagRecognizer extends AbstractXmlConfigRootTagRecognizer {
public ClientFailoverXmlConfigRootTagRecognizer() throws Exception {
super(ClientFailoverConfigSections.CLIENT_FAILOVER.getName());
}
}
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2008-2020, Hazelcast, Inc. All Rights Reserved.
*
* Licensed 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 com.hazelcast.client.config.impl;

import com.hazelcast.config.ConfigRecognizer;
import com.hazelcast.internal.config.AbstractYamlConfigRootTagRecognizer;

/**
* This {@link ConfigRecognizer} implementation recognizes Hazelcast
* failover client YAML configuration by checking if the defined root tag
* is "hazelcast-client-failover" or not. For the implementation details
* please refer to the {@link AbstractYamlConfigRootTagRecognizer}
* documentation.
*/
public class ClientFailoverYamlConfigRootTagRecognizer extends AbstractYamlConfigRootTagRecognizer {
public ClientFailoverYamlConfigRootTagRecognizer() {
super(ClientFailoverConfigSections.CLIENT_FAILOVER.getName());
}
}
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2008-2020, Hazelcast, Inc. All Rights Reserved.
*
* Licensed 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 com.hazelcast.client.config.impl;

import com.hazelcast.config.ConfigRecognizer;
import com.hazelcast.internal.config.AbstractXmlConfigRootTagRecognizer;

/**
* This {@link ConfigRecognizer} implementation recognizes Hazelcast
* client XML configuration by checking if the defined root tag is
* "hazelcast-client" or not. For the implementation details please refer
* to the {@link AbstractXmlConfigRootTagRecognizer} documentation.
*/
public class ClientXmlConfigRootTagRecognizer extends AbstractXmlConfigRootTagRecognizer {
public ClientXmlConfigRootTagRecognizer() throws Exception {
super(ClientConfigSections.HAZELCAST_CLIENT.getName());
}
}
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2008-2020, Hazelcast, Inc. All Rights Reserved.
*
* Licensed 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 com.hazelcast.client.config.impl;

import com.hazelcast.config.ConfigRecognizer;
import com.hazelcast.internal.config.AbstractYamlConfigRootTagRecognizer;

/**
* This {@link ConfigRecognizer} implementation recognizes Hazelcast
* client YAML configuration by checking if the defined root tag is
* "hazelcast-client" or not. For the implementation details please refer
* to the {@link AbstractYamlConfigRootTagRecognizer} documentation.
*/
public class ClientYamlConfigRootTagRecognizer extends AbstractYamlConfigRootTagRecognizer {
public ClientYamlConfigRootTagRecognizer() {
super(ClientConfigSections.HAZELCAST_CLIENT.getName());
}
}
Expand Up @@ -69,7 +69,7 @@ protected ConfigType getConfigType() {
}

protected void schemaValidation(Document doc) throws Exception {
ArrayList<StreamSource> schemas = new ArrayList<StreamSource>();
ArrayList<StreamSource> schemas = new ArrayList<>();
InputStream inputStream = null;
String schemaLocation = doc.getDocumentElement().getAttribute("xsi:schemaLocation");
schemaLocation = schemaLocation.replaceAll("^ +| +$| (?= )", "");
Expand Down
36 changes: 36 additions & 0 deletions hazelcast/src/main/java/com/hazelcast/config/ConfigRecognizer.java
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2008-2020, Hazelcast, Inc. All Rights Reserved.
*
* Licensed 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 com.hazelcast.config;

/**
* Interface for recognizing a declarative Hazelcast configuration
* based on the rules defined in the actual implementation.
* The main use case for this interface is recognizing whether a given
* declarative configuration is a member or a client configuration.
*/
public interface ConfigRecognizer {
/**
* Recognizes the configuration given in the {@code configStream}
* argument.
*
* @param configStream The stream with the declarative configuration
* @return {@code true} if the configuration is recognized, {@code false}
* otherwise
* @throws Exception If any error occurs during the recognition
*/
boolean isRecognized(ConfigStream configStream) throws Exception;
}

0 comments on commit 7d63cfd

Please sign in to comment.