package org.teiid.designer.runtime;
import java.io.File;
import java.util.Collection;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.eclipse.wst.server.core.IServer;
import org.teiid.core.designer.util.Base64;
import org.teiid.core.designer.util.StringUtilities;
import org.teiid.datatools.connectivity.spi.ISecureStorageProvider;
import org.teiid.designer.core.util.KeyInValueHashMap;
import org.teiid.designer.core.util.KeyInValueHashMap.KeyFromValueAdapter;
import org.teiid.designer.runtime.spi.ITeiidAdminInfo;
import org.teiid.designer.runtime.spi.ITeiidJdbcInfo;
import org.teiid.designer.runtime.spi.ITeiidServer;
import org.teiid.designer.runtime.version.spi.ITeiidServerVersion;
import org.teiid.designer.runtime.version.spi.TeiidServerVersion;
import org.teiid.designer.runtime.version.spi.TeiidServerVersion.Version;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class TeiidServerRegistryReader implements TeiidServerRegistryConstants {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder;
Document doc;
Element root;
ITeiidServer defaultServer;
TeiidServerManager teiidServerManager;
// secure storage provider needs to get passed in because getSecureStorageProvider() does a state check and when restoreServers() is called
// The state will not be STARTED
ISecureStorageProvider secureStorageProvider;
boolean doDebug;
/**
* The provider used for accessing the collection of available {@link IServer}s
* rather than relying on {@link parentServersProvider} directly, which makes unit testing difficult
*/
private IServersProvider parentServersProvider;
private final KeyInValueHashMap<String, ITeiidServer> teiidServers;
private class TeiidServerKeyValueAdapter implements KeyFromValueAdapter<String, ITeiidServer> {
@Override
public String getKey(ITeiidServer value) {
return value.getId();
}
}
public TeiidServerRegistryReader(
TeiidServerManager teiidServerManager,
IServersProvider parentServersProvider,
ISecureStorageProvider secureStorageProvider,
boolean doDebug) {
this.teiidServerManager = teiidServerManager;
this.parentServersProvider = parentServersProvider;
this.secureStorageProvider = secureStorageProvider;
this.doDebug = doDebug;
this.teiidServers = new KeyInValueHashMap<String, ITeiidServer>(new TeiidServerKeyValueAdapter());
}
public Collection<ITeiidServer> restoreServers() throws Exception {
factory = DocumentBuilderFactory.newInstance();
docBuilder = factory.newDocumentBuilder();
doc = docBuilder.parse(new File(teiidServerManager.getStateFileName()));
Node root = doc.getDocumentElement();
NodeList servers = root.getChildNodes();
for (int size = servers.getLength(), i = 0; i < size; ++i) {
Node serverNode = servers.item(i);
ITeiidServer teiidServer = loadServer(serverNode);
if( teiidServer != null ) {
teiidServers.add(teiidServer);
}
}
return teiidServers.values();
}
private ITeiidServer loadServer(Node serverNode) throws Exception {
ITeiidAdminInfo teiidAdminInfo = null;
ITeiidJdbcInfo teiidJdbcInfo = null;
String jdbcOverridePort = null;
// server attributes (host, custom label, default teiid instance)
NamedNodeMap serverAttributeMap = serverNode.getAttributes();
if (serverAttributeMap == null) {
return null;
}
String host = null;
String parentServerId = null;
String customLabel = null;
boolean previewServer = false;
if( doDebug ) System.out.println( " <<< LOADING SERVER INFO");
// version attribute
ITeiidServerVersion teiidServerVersion = Version.TEIID_DEFAULT.get();
Node versionNode = serverAttributeMap.getNamedItem(SERVER_VERSION);
if (versionNode != null) teiidServerVersion = new TeiidServerVersion(versionNode.getNodeValue());
attributeRead(SERVER_VERSION, teiidServerVersion.toString());
// host attribute
Node hostNode = serverAttributeMap.getNamedItem(HOST_ATTR);
if (hostNode != null) {
host = hostNode.getNodeValue();
attributeRead(HOST_ATTR, host);
}
Node parentServerNode = serverAttributeMap.getNamedItem(PARENT_SERVER_ID);
if (parentServerNode != null) {
parentServerId = parentServerNode.getNodeValue();
attributeRead(PARENT_SERVER_ID, parentServerId);
}
// custom label attribute
Node customLabelNode = serverAttributeMap.getNamedItem(CUSTOM_LABEL_ATTR);
if (customLabelNode != null) {
customLabel = customLabelNode.getNodeValue();
attributeRead(CUSTOM_LABEL_ATTR, customLabel);
}
// default teiid instance attribute
Node defaultServerNode = serverAttributeMap.getNamedItem(DEFAULT_ATTR);
if (defaultServerNode != null) {
previewServer = Boolean.parseBoolean(defaultServerNode.getNodeValue());
attributeRead(DEFAULT_ATTR, defaultServerNode.getNodeValue());
}
// Check for newer XML structure where server contains child nodes (admin & jdbc elements)
NodeList connectionNodes = serverNode.getChildNodes();
if (connectionNodes.getLength() > 0) {
for (int connSize = connectionNodes.getLength(), j = 0; j < connSize; ++j) {
Node connNode = connectionNodes.item(j);
if (connNode.getNodeType() != Node.TEXT_NODE) {
if (connNode.getNodeName().equalsIgnoreCase(ADMIN_TAG)) {
if( doDebug ) System.out.println(" <<< ADMIN INFO");
NamedNodeMap attributeMap = connNode.getAttributes();
if (attributeMap == null) continue;
// if host is null than an older registry xml file is being used
if (host == null) {
Node adminHostNode = attributeMap.getNamedItem(HOST_ATTR);
assert (adminHostNode != null);
host = adminHostNode.getNodeValue();
attributeRead(HOST_ATTR, host);
}
// port must be non-null/not empty to be valid server
Node adminPortNode = attributeMap.getNamedItem(PORT_ATTR); // should always have one
assert (adminPortNode != null);
String adminPort = adminPortNode.getNodeValue();
attributeRead(PORT_ATTR, adminPort);
// username must be non-null/not empty to be valid server
Node userNode = attributeMap.getNamedItem(USER_ATTR); // should always have one
assert (userNode != null);
String adminUsername = userNode.getNodeValue();
attributeRead(USER_ATTR, adminUsername);
Node passwordNode = attributeMap.getNamedItem(PASSWORD_ATTR);
String adminPassword = null;
if( passwordNode != null ) {
adminPassword = new String( Base64.decode(passwordNode.getNodeValue()), "UTF-8"); //$NON-NLS-1$
attributeRead(PASSWORD_ATTR, adminPassword);
}
Node adminSecureNode = attributeMap.getNamedItem(SECURE_ATTR);
String adminSecureStr = ((adminSecureNode == null) ? Boolean.FALSE.toString() : adminSecureNode.getNodeValue());
attributeRead(SECURE_ATTR, adminSecureStr);
teiidAdminInfo = new TeiidAdminInfo(host, adminPort, adminUsername, secureStorageProvider,
adminPassword, Boolean.parseBoolean(adminSecureStr));
} else if (connNode.getNodeName().equalsIgnoreCase(JDBC_TAG)) {
if( doDebug ) System.out.println(" <<< JDBC INFO");
NamedNodeMap attributeMap = connNode.getAttributes();
if (attributeMap == null) continue;
// if host is null than an older registry xml file is being used
if (host == null) {
Node jdbcHostNode = attributeMap.getNamedItem(JDBC_HOST_ATTR);
assert (jdbcHostNode != null);
host = jdbcHostNode.getNodeValue();
attributeRead(JDBC_HOST_ATTR, host);
}
// port must be non-null/not empty to be valid server
Node jdbcPortNode = attributeMap.getNamedItem(JDBC_PORT_ATTR);
assert (jdbcPortNode != null);
String jdbcPort = jdbcPortNode.getNodeValue();
// port override must be non-null/not empty to be valid server
Node jdbcPortOverrideNode = attributeMap.getNamedItem(JDBC_PORT_OVERRIDE_ATTR);
if( jdbcPortOverrideNode != null ) {
jdbcOverridePort = jdbcPortOverrideNode.getNodeValue();
attributeRead(JDBC_PORT_OVERRIDE_ATTR, jdbcOverridePort);
}
// username must be non-null/not empty to be valid server
Node jdbcUserNode = attributeMap.getNamedItem(JDBC_USER_ATTR);
assert (jdbcUserNode != null);
String jdbcUsername = jdbcUserNode.getNodeValue();
attributeRead(JDBC_USER_ATTR, jdbcUsername);
Node jdbcPasswordNode = attributeMap.getNamedItem(JDBC_PASSWORD_ATTR);
String jdbcPassword = null;
if( jdbcPasswordNode != null ) {
jdbcPassword = new String( Base64.decode(jdbcPasswordNode.getNodeValue()), "UTF-8"); //$NON-NLS-1$
attributeRead(JDBC_PASSWORD_ATTR, jdbcPassword);
}
Node jdbcSecureNode = attributeMap.getNamedItem(JDBC_SECURE_ATTR);
String jdbcSecureStr = ((jdbcSecureNode == null) ? Boolean.FALSE.toString() : jdbcSecureNode.getNodeValue());
attributeRead(JDBC_SECURE_ATTR, jdbcSecureStr);
teiidJdbcInfo = new TeiidJdbcInfo(host, jdbcPort, jdbcUsername, secureStorageProvider, jdbcPassword,
Boolean.parseBoolean(jdbcSecureStr));
}
}
}
}
// add server to registry
IServer parentServer = null;
try {
parentServer = findParentServer(host, parentServerId, teiidAdminInfo);
} catch (OrphanedTeiidServerException ex) {
// Cannot add the Teiid Instance since it has no parent
return null;
}
TeiidServerFactory teiidServerFactory = new TeiidServerFactory();
ITeiidServer teiidServer = teiidServerFactory.createTeiidServer(teiidServerVersion,
host,
teiidAdminInfo,
teiidJdbcInfo,
teiidServerManager,
parentServer);
teiidServer.setCustomLabel(customLabel);
if( !StringUtilities.isEmpty(jdbcOverridePort) ) {
teiidServerManager.getJdbcPortManager().setPort(teiidServer, Integer.parseInt(jdbcOverridePort), true);
}
if (previewServer) {
defaultServer = teiidServer;
}
return teiidServer;
}
private IServer findParentServer(String host, String parentServerId, ITeiidAdminInfo teiidAdminInfo) throws OrphanedTeiidServerException {
IServer[] servers = parentServersProvider.getServers();
for (IServer server : servers) {
if (! host.equals(server.getHost()))
continue;
if (parentServerId != null && ! server.getId().equals(parentServerId)) {
// Double checks against the parent server id only if a parent server id was
// save. In the case of the old registry format, this was not possible so host
// comparison is sufficient
continue;
}
return server;
}
throw new OrphanedTeiidServerException(teiidAdminInfo);
}
private void attributeRead(String key, String value) {
if( doDebug) System.out.println(" Read Server Attribute = " + key + " value = " + value);
}
public ITeiidServer getDefaultServer() {
return defaultServer;
}
}