com.hazelcast.client.config.XmlClientConfigBuilder Maven / Gradle / Ivy
The newest version!
/*
* 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.config.AbstractXmlConfigBuilder;
import com.hazelcast.config.ConfigLoader;
import com.hazelcast.config.InvalidConfigurationException;
import com.hazelcast.logging.ILogger;
import com.hazelcast.logging.Logger;
import com.hazelcast.nio.IOUtil;
import com.hazelcast.util.ExceptionUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Properties;
import static com.hazelcast.util.Preconditions.checkNotNull;
import static com.hazelcast.util.Preconditions.checkTrue;
import static com.hazelcast.util.StringUtil.LINE_SEPARATOR;
/**
* Loads the {@link com.hazelcast.client.config.ClientConfig} using XML.
*/
public class XmlClientConfigBuilder extends AbstractXmlConfigBuilder {
private static final ILogger LOGGER = Logger.getLogger(XmlClientConfigBuilder.class);
private final InputStream in;
public XmlClientConfigBuilder(String resource) throws IOException {
URL url = ConfigLoader.locateConfig(resource);
checkTrue(url != null, "Could not load " + resource);
this.in = url.openStream();
}
public XmlClientConfigBuilder(File file) throws IOException {
checkNotNull(file, "File is null!");
this.in = new FileInputStream(file);
}
public XmlClientConfigBuilder(URL url) throws IOException {
checkNotNull(url, "URL is null!");
this.in = url.openStream();
}
public XmlClientConfigBuilder(InputStream in) {
this.in = in;
}
/**
* Loads the client config using the following resolution mechanism:
*
* - first it checks if a system property 'hazelcast.client.config' is set. If it exist and
* it begins with 'classpath:', then a classpath resource is loaded. Else it will assume it is a file
* reference. The configuration file or resource will be loaded only if the postfix of its name ends
* with `.xml`.
* - it checks if a hazelcast-client.xml is available in the working dir
* - it checks if a hazelcast-client.xml is available on the classpath
* - it loads the hazelcast-client-default.xml
*
*/
public XmlClientConfigBuilder() {
this((XmlClientConfigLocator) null);
}
/**
* Constructs a {@link XmlClientConfigBuilder} that loads the configuration
* with the provided {@link XmlClientConfigLocator}.
*
* If the provided {@link XmlClientConfigLocator} is {@code null}, a new
* instance is created and the config is located in every possible
* places. For these places, please see {@link XmlClientConfigLocator}.
*
* If the provided {@link XmlClientConfigLocator} is not {@code null}, it
* is expected that it already located the configuration XML to load
* from. No further attempt to locate the configuration XML is made
* if the configuration XML is not located already.
*
* @param locator the configured locator to use
*/
public XmlClientConfigBuilder(XmlClientConfigLocator locator) {
if (locator == null) {
locator = new XmlClientConfigLocator();
locator.locateEverywhere();
}
this.in = locator.getIn();
}
@Override
protected Document parse(InputStream inputStream) throws Exception {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
DocumentBuilder builder = dbf.newDocumentBuilder();
try {
return builder.parse(inputStream);
} catch (Exception e) {
String msg = "Failed to parse Config Stream"
+ LINE_SEPARATOR + "Exception: " + e.getMessage()
+ LINE_SEPARATOR + "HazelcastClient startup interrupted.";
LOGGER.severe(msg);
throw new InvalidConfigurationException(e.getMessage(), e);
} finally {
IOUtil.closeResource(inputStream);
}
}
public XmlClientConfigBuilder setProperties(Properties properties) {
setPropertiesInternal(properties);
return this;
}
@Override
protected ConfigType getConfigType() {
return ConfigType.CLIENT;
}
public ClientConfig build() {
return build(Thread.currentThread().getContextClassLoader());
}
public ClientConfig build(ClassLoader classLoader) {
ClientConfig clientConfig = new ClientConfig();
build(clientConfig, classLoader);
return clientConfig;
}
void build(ClientConfig clientConfig, ClassLoader classLoader) {
clientConfig.setClassLoader(classLoader);
try {
parseAndBuildConfig(clientConfig);
} catch (Exception e) {
throw ExceptionUtil.rethrow(e);
} finally {
IOUtil.closeResource(in);
}
}
private void parseAndBuildConfig(ClientConfig clientConfig) throws Exception {
Document doc = parse(in);
Element root = doc.getDocumentElement();
checkRootElement(root);
try {
root.getTextContent();
} catch (Throwable e) {
domLevel3 = false;
}
process(root);
schemaValidation(root.getOwnerDocument());
new ClientDomConfigProcessor(domLevel3, clientConfig).buildConfig(root);
}
private void checkRootElement(Element root) {
String rootNodeName = root.getNodeName();
if (!ClientConfigSections.HAZELCAST_CLIENT.isEqual(rootNodeName)) {
throw new InvalidConfigurationException("Invalid root element in xml configuration! "
+ "Expected: <" + ClientConfigSections.HAZELCAST_CLIENT.name + ">, Actual: <" + rootNodeName + ">.");
}
}
}