SqlResourcespublic class SqlResources extends Object Provides a set of SQL String resources (eg SQL Strings)
to use for a database connection.
This class allows SQL strings to be customised to particular
database products, by detecting product information from the
jdbc DatabaseMetaData object. |
Fields Summary |
---|
private Map | m_sqlA map of statement types to SQL statements | private Map | m_dbOptionsA map of engine specific options | private static Map | stringTableA set of all used String values | private org.apache.oro.text.perl.Perl5Util | m_perl5UtilA Perl5 regexp matching helper class |
Methods Summary |
---|
public java.lang.String | getDbOption(java.lang.String name)Returns the dbOption string value set for the specified dbOption name.
return (String)m_dbOptions.get(name);
| public java.lang.String | getSqlString(java.lang.String name)Returns a named SQL string for the specified connection,
replacing parameters with the values set.
return (String)m_sql.get(name);
| public java.lang.String | getSqlString(java.lang.String name, boolean required)Returns a named SQL string for the specified connection,
replacing parameters with the values set.
String sql = getSqlString(name);
if (sql == null && required) {
StringBuffer exceptionBuffer =
new StringBuffer(64)
.append("Required SQL resource: '")
.append(name)
.append("' was not found.");
throw new RuntimeException(exceptionBuffer.toString());
}
return sql;
| public void | init(java.io.File sqlFile, java.lang.String sqlDefsSection, java.sql.Connection conn, java.util.Map configParameters)Configures a DbResources object to provide SQL statements from a file.
SQL statements returned may be specific to the particular type
and version of the connected database, as well as the database driver.
Parameters encoded as $(parameter} in the input file are
replace by values from the parameters Map, if the named parameter exists.
Parameter values may also be specified in the resourceSection element.
// Parse the sqlFile as an XML document.
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document sqlDoc = builder.parse(sqlFile);
// First process the database matcher, to determine the
// sql statements to use.
Element dbMatcherElement =
(Element)(sqlDoc.getElementsByTagName("dbMatchers").item(0));
String dbProduct = null;
if ( dbMatcherElement != null ) {
dbProduct = matchDbConnection(conn, dbMatcherElement);
m_perl5Util = null; // release the PERL matcher!
}
// Now get the options valid for the database product used.
Element dbOptionsElement =
(Element)(sqlDoc.getElementsByTagName("dbOptions").item(0));
if ( dbOptionsElement != null ) {
// First populate the map with default values
populateDbOptions("", dbOptionsElement, m_dbOptions);
// Now update the map with specific product values
if ( dbProduct != null ) {
populateDbOptions(dbProduct, dbOptionsElement, m_dbOptions);
}
}
// Now get the section defining sql for the repository required.
NodeList sections = sqlDoc.getElementsByTagName("sqlDefs");
int sectionsCount = sections.getLength();
Element sectionElement = null;
boolean found = false;
for (int i = 0; i < sectionsCount; i++ ) {
sectionElement = (Element)(sections.item(i));
String sectionName = sectionElement.getAttribute("name");
if ( sectionName != null && sectionName.equals(sqlDefsSection) ) {
found = true;
break;
}
}
if ( !found ) {
StringBuffer exceptionBuffer =
new StringBuffer(64)
.append("Error loading sql definition file. ")
.append("The element named \'")
.append(sqlDefsSection)
.append("\' does not exist.");
throw new RuntimeException(exceptionBuffer.toString());
}
// Get parameters defined within the file as defaults,
// and use supplied parameters as overrides.
Map parameters = new HashMap();
// First read from the <params> element, if it exists.
Element parametersElement =
(Element)(sectionElement.getElementsByTagName("parameters").item(0));
if ( parametersElement != null ) {
NamedNodeMap params = parametersElement.getAttributes();
int paramCount = params.getLength();
for (int i = 0; i < paramCount; i++ ) {
Attr param = (Attr)params.item(i);
String paramName = param.getName();
String paramValue = param.getValue();
parameters.put(paramName, paramValue);
}
}
// Then copy in the parameters supplied with the call.
parameters.putAll(configParameters);
// 2 maps - one for storing default statements,
// the other for statements with a "db" attribute matching this
// connection.
Map defaultSqlStatements = new HashMap();
Map dbProductSqlStatements = new HashMap();
// Process each sql statement, replacing string parameters,
// and adding to the appropriate map..
NodeList sqlDefs = sectionElement.getElementsByTagName("sql");
int sqlCount = sqlDefs.getLength();
for ( int i = 0; i < sqlCount; i++ ) {
// See if this needs to be processed (is default or product specific)
Element sqlElement = (Element)(sqlDefs.item(i));
String sqlDb = sqlElement.getAttribute("db");
Map sqlMap;
if ( sqlDb.equals("")) {
// default
sqlMap = defaultSqlStatements;
}
else if (sqlDb.equals(dbProduct) ) {
// Specific to this product
sqlMap = dbProductSqlStatements;
}
else {
// for a different product
continue;
}
// Get the key and value for this SQL statement.
String sqlKey = sqlElement.getAttribute("name");
if ( sqlKey == null ) {
// ignore statements without a "name" attribute.
continue;
}
String sqlString = sqlElement.getFirstChild().getNodeValue();
// Do parameter replacements for this sql string.
Iterator paramNames = parameters.keySet().iterator();
while ( paramNames.hasNext() ) {
String paramName = (String)paramNames.next();
String paramValue = (String)parameters.get(paramName);
StringBuffer replaceBuffer =
new StringBuffer(64)
.append("${")
.append(paramName)
.append("}");
sqlString = substituteSubString(sqlString, replaceBuffer.toString(), paramValue);
}
// See if we already have registered a string of this value
String shared = (String) stringTable.get(sqlString);
// If not, register it -- we will use it next time
if (shared == null) {
stringTable.put(sqlString, sqlString);
} else {
sqlString = shared;
}
// Add to the sqlMap - either the "default" or the "product" map
sqlMap.put(sqlKey, sqlString);
}
// Copy in default strings, then overwrite product-specific ones.
m_sql.putAll(defaultSqlStatements);
m_sql.putAll(dbProductSqlStatements);
| private java.lang.String | matchDbConnection(java.sql.Connection conn, org.w3c.dom.Element dbMatchersElement)Compares the DatabaseProductName value for a jdbc Connection
against a set of regular expressions defined in XML.
The first successful match defines the name of the database product
connected to. This value is then used to choose the specific SQL
expressions to use.
String dbProductName = conn.getMetaData().getDatabaseProductName();
NodeList dbMatchers =
dbMatchersElement.getElementsByTagName("dbMatcher");
for ( int i = 0; i < dbMatchers.getLength(); i++ ) {
// Get the values for this matcher element.
Element dbMatcher = (Element)dbMatchers.item(i);
String dbMatchName = dbMatcher.getAttribute("db");
StringBuffer dbProductPatternBuffer =
new StringBuffer(64)
.append("/")
.append(dbMatcher.getAttribute("databaseProductName"))
.append("/i");
// If the connection databaseProcuctName matches the pattern,
// use the match name from this matcher.
if ( m_perl5Util.match(dbProductPatternBuffer.toString(), dbProductName) ) {
return dbMatchName;
}
}
return null;
| private void | populateDbOptions(java.lang.String dbProduct, org.w3c.dom.Element dbOptionsElement, java.util.Map dbOptionsMap)Gets all the name/value pair db option couples related to the dbProduct,
and put them into the dbOptionsMap.
NodeList dbOptions =
dbOptionsElement.getElementsByTagName("dbOption");
for ( int i = 0; i < dbOptions.getLength(); i++ ) {
// Get the values for this option element.
Element dbOption = (Element)dbOptions.item(i);
// Check is this element is pertinent to the dbProduct
// Notice that a missing attribute returns "", good for defaults
if (!dbProduct.equalsIgnoreCase(dbOption.getAttribute("db"))) {
continue;
}
// Put into the map
dbOptionsMap.put(dbOption.getAttribute("name"), dbOption.getAttribute("value"));
}
| private java.lang.String | substituteSubString(java.lang.String input, java.lang.String find, java.lang.String replace)Replace substrings of one string with another string and return altered string.
int find_length = find.length();
int replace_length = replace.length();
StringBuffer output = new StringBuffer(input);
int index = input.indexOf(find);
int outputOffset = 0;
while ( index > -1 ) {
output.replace(index + outputOffset, index + outputOffset + find_length, replace);
outputOffset = outputOffset + (replace_length - find_length);
index = input.indexOf(find, index + find_length);
}
String result = output.toString();
return result;
|
|