/* | |
* 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); | |
} |