blob: 79819ee2bbff47c34e6c2c41278b4c67239ee3ea [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.openmeetings.cli;
import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.openmeetings.cli.ConnectionProperties.DbType;
import org.apache.openmeetings.util.OmFileHelper;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public abstract class ConnectionPropertiesPatcher {
protected static final String URL_PREFIX = "Url";
protected static final String DRIVER_PREFIX = "DriverClassName";
protected static final String USER_PREFIX = "Username";
protected static final String PASS_PREFIX = "Password";
protected ConnectionProperties props;
public static ConnectionPropertiesPatcher getPatcher(ConnectionProperties props) {
ConnectionPropertiesPatcher patcher = null;
switch (props.getDbType()) {
case db2:
patcher = new Db2Patcher();
break;
case mssql:
patcher = new MssqlPatcher();
break;
case mysql:
patcher = new MysqlPatcher();
break;
case oracle:
patcher = new OraclePatcher();
break;
case postgresql:
patcher = new PostgresPatcher();
break;
case derby:
default:
patcher = new DerbyPatcher();
break;
}
patcher.props = props;
return patcher;
}
public static ConnectionProperties getConnectionProperties(File conf) throws Exception {
ConnectionProperties props = new ConnectionProperties();
Document doc = getDocument(conf);
Attr attr = getConnectionProperties(doc);
String[] tokens = attr.getValue().split(",");
loadProperties(tokens, props);
return props;
}
private static Document getDocument(File xml) throws Exception {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
//dbFactory.setNamespaceAware(true);
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
return dBuilder.parse(xml);
}
private static Attr getConnectionProperties(Document doc) throws Exception {
XPath xPath = XPathFactory.newInstance().newXPath();
XPathExpression expr = xPath.compile("/persistence/persistence-unit/properties/property[@name='openjpa.ConnectionProperties']");
Element element = (Element)expr.evaluate(doc, XPathConstants.NODE);
return element.getAttributeNode("value");
}
public static void patch(ConnectionProperties props) throws Exception {
ConnectionPropertiesPatcher patcher = getPatcher(props);
Document doc = getDocument(OmFileHelper.getPersistence(props.getDbType()));
Attr attr = getConnectionProperties(doc);
String[] tokens = attr.getValue().split(",");
patcher.patchAttribute(tokens);
attr.setValue(StringUtils.join(tokens, ","));
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
transformer.transform(source, new StreamResult(OmFileHelper.getPersistence().getCanonicalPath())); //this constructor is used to avoid transforming path to URI
}
public static ConnectionProperties patch(String dbType, String host, String port, String db, String user, String pass) throws Exception {
ConnectionProperties props = getConnectionProperties(OmFileHelper.getPersistence(dbType));
props.setLogin(user);
props.setPassword(pass);
ConnectionPropertiesPatcher patcher = getPatcher(props);
props.setURL(patcher.getUrl(props.getURL(), host, port, db));
patch(props);
return props;
}
public static void updateUrl(ConnectionProperties props, String host, String port, String db) {
ConnectionPropertiesPatcher patcher = getPatcher(props);
props.setURL(patcher.getUrl(props.getURL(), host, port, db));
}
protected void patchAttribute(String[] tokens) {
for (int i = 0; i < tokens.length; ++i) {
patchProp(tokens, i, USER_PREFIX, props.getLogin());
patchProp(tokens, i, PASS_PREFIX, props.getPassword() == null ? "" : props.getPassword());
patchProp(tokens, i, URL_PREFIX, props.getURL());
}
}
protected static void patchProp(String[] tokens, int idx, String name, String value) {
String prop = tokens[idx].trim();
if (prop.startsWith(name)) {
prop = name + "=" + StringEscapeUtils.escapeXml10(value);
tokens[idx] = prop;
}
}
private static void loadProperties(String[] tokens, ConnectionProperties connectionProperties) {
String prop;
for (int i = 0; i < tokens.length; ++i) {
prop = getPropFromPersistence(tokens, i, DRIVER_PREFIX);
if (prop != null) {
connectionProperties.setDriver(prop);
}
prop = getPropFromPersistence(tokens, i, USER_PREFIX);
if (prop != null) {
connectionProperties.setLogin(prop);
}
prop = getPropFromPersistence(tokens, i, PASS_PREFIX);
if (prop != null) {
connectionProperties.setPassword(prop);
}
prop = getPropFromPersistence(tokens, i, URL_PREFIX);
if (prop != null) {
try {
//will try to "guess" dbType
String[] parts = prop.split(":");
connectionProperties.setDbType("sqlserver".equals(parts[1]) ? DbType.mssql : DbType.valueOf(parts[1]));
} catch (Exception e) {
//ignore
}
connectionProperties.setURL(prop);
}
}
}
protected static String getPropFromPersistence(String[] tokens, int idx, String name){
String prop = tokens[idx].trim();
if (prop.startsWith(name)) {
//From "Username=root" getting only "root"
return prop.substring(prop.indexOf("=") + 1);
}
return null;
}
protected abstract String getUrl(String url, String host, String port, String db);
}