Here is the same method with the fix:
----------------
private Map getChildrenFromExternalSource(String source) throws Exception {
log.debug(">> getChildrenFromExternalSource(" + source + ")");
Map props = new HashMap();
if (source.trim().length() == 0) {
throw new SQLUnitException(IErrorCodes.ELEMENT_IS_NULL,
new String[] {"connection.@extern"});
} else {
// see if the file exists
File f = new File(source);
if (f.exists())
{
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
String line;
while ((line = reader.readLine()) != null)
{
if (line.startsWith("#"))
continue;
int index = line.indexOf("=");
if(index<0)
{
continue;
}
String key = line.substring(0,index).trim();
String value = (line.substring(index,line.length())).trim();
if (key.startsWith("sqlunit."))
{
key = getInternalForm(key);
}
Now I am facing an interesting Class loader issue. If I define my connection to SQLServer inside the XML then it is connecting fine. However, If I move the connection information into a property file and reference it through extern, I am getting a class not found exception:
--------------
java.lang.ClassNotFoundException: =com/microsoft/jdbc/sqlserver/SQLServerDriver
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:141)
at net.sourceforge.sqlunit.ConnectionHandler.process(ConnectionHandler.java:163)
at net.sourceforge.sqlunit.SQLUnit.processDoc(SQLUnit.java:187)
at net.sourceforge.sqlunit.SQLUnit.testWrapper(SQLUnit.java:142)
at net.sourceforge.sqlunit.SQLUnit.runTest(SQLUnit.java:130)
at net.sourceforge.antsqlunittask.SqlunitTask.execute(SqlunitTask.java:98)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:193)
at org.apache.tools.ant.Task.perform(Task.java:341)
at org.apache.tools.ant.Target.execute(Target.java:309)
at org.apache.tools.ant.Target.performTasks(Target.java:336)
at org.apache.tools.ant.Project.executeTarget(Project.java:1339)
at org.apache.tools.ant.Project.executeTargets(Project.java:1255)
at org.apache.tools.ant.Main.runBuild(Main.java:609)
at org.apache.tools.ant.Main.start(Main.java:196)
at org.apache.tools.ant.Main.main(Main.java:235)
------------------------
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I noticed that following method is using line.split() to find the key and value coming from lines in the external property file.
Unfortunately, the split call fails to achive the objective when the JDBC url itself has multiple equal sigs as below.
sqlunit.url=jdbc:microsoft:sqlserver://DBSQL:1433;DatabaseName=dbC;User=sqlunitid;Password=sqlunitpass
The remedy would be to find the first index of 'equals sign' and manual substring the line using the index.
I will attempt this and will get back.
Here is the same method with the fix:
----------------
private Map getChildrenFromExternalSource(String source) throws Exception {
log.debug(">> getChildrenFromExternalSource(" + source + ")");
Map props = new HashMap();
if (source.trim().length() == 0) {
throw new SQLUnitException(IErrorCodes.ELEMENT_IS_NULL,
new String[] {"connection.@extern"});
} else {
// see if the file exists
File f = new File(source);
if (f.exists())
{
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
String line;
while ((line = reader.readLine()) != null)
{
if (line.startsWith("#"))
continue;
int index = line.indexOf("=");
if(index<0)
{
continue;
}
String key = line.substring(0,index).trim();
String value = (line.substring(index,line.length())).trim();
if (key.startsWith("sqlunit."))
{
key = getInternalForm(key);
}
System.out.println("KEY:" + key);
System.out.println("VALUE:" + value);
props.put(key, value);
}
reader.close();
} else {
try {
ResourceBundle r = ResourceBundle.getBundle(source);
for (Enumeration e = r.getKeys(); e.hasMoreElements(); ) {
String name = (String) e.nextElement();
String value = r.getString(name);
if (name.startsWith("sqlunit.")) {
name = getInternalForm(name);
props.put(name, value);
}
}
} catch (MissingResourceException e) {} // fall through
}
}
return props;
}
------------------
Now I am facing an interesting Class loader issue. If I define my connection to SQLServer inside the XML then it is connecting fine. However, If I move the connection information into a property file and reference it through extern, I am getting a class not found exception:
--------------
java.lang.ClassNotFoundException: =com/microsoft/jdbc/sqlserver/SQLServerDriver
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:141)
at net.sourceforge.sqlunit.ConnectionHandler.process(ConnectionHandler.java:163)
at net.sourceforge.sqlunit.SQLUnit.processDoc(SQLUnit.java:187)
at net.sourceforge.sqlunit.SQLUnit.testWrapper(SQLUnit.java:142)
at net.sourceforge.sqlunit.SQLUnit.runTest(SQLUnit.java:130)
at net.sourceforge.antsqlunittask.SqlunitTask.execute(SqlunitTask.java:98)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:193)
at org.apache.tools.ant.Task.perform(Task.java:341)
at org.apache.tools.ant.Target.execute(Target.java:309)
at org.apache.tools.ant.Target.performTasks(Target.java:336)
at org.apache.tools.ant.Project.executeTarget(Project.java:1339)
at org.apache.tools.ant.Project.executeTargets(Project.java:1255)
at org.apache.tools.ant.Main.runBuild(Main.java:609)
at org.apache.tools.ant.Main.start(Main.java:196)
at org.apache.tools.ant.Main.main(Main.java:235)
------------------------
I later realized a simple and elegant way to handle this.
Changed the split call to pass an additional argument "2".
String[] nameValue = line.split("\\s*=\\s*", 2);
That took care of the problem with parsing and classloading issue.
Cool, thanks for the fix, I will put it into cvs.
-sujit