package org.oddjob.sql;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.StringTokenizer;
import org.oddjob.arooa.ArooaSession;
import org.oddjob.arooa.convert.ArooaConversionException;
import org.oddjob.arooa.life.ArooaSessionAware;
import org.oddjob.arooa.runtime.ExpressionParser;
import org.oddjob.arooa.runtime.ParsedExpression;
import org.oddjob.beanbus.AbstractBusComponent;
import org.oddjob.beanbus.BusCrashException;
import org.oddjob.beanbus.BusDriver;
import org.oddjob.beanbus.BusException;
import org.oddjob.sql.SQLJob.DelimiterType;
/**
* Parses SQL from an InputStream into individual statements.
*
* @author rob
*/
public class ScriptParser extends AbstractBusComponent<String>
implements BusDriver<String>, ArooaSessionAware {
/**
* Keep the format of a SQL block.
*/
private boolean keepFormat;
/**
* Should properties be expanded in SQL.
*/
private boolean expandProperties;
/**
* The delimiter type indicating whether the delimiter will
* only be recognized on a line by itself
*/
private DelimiterType delimiterType = DelimiterType.NORMAL;
/**
* SQL Statement delimiter
*/
private String delimiter = ";";
/**
* Encoding to use when reading SQL statements from a file
*/
private String encoding = null;
/**
* Session.
*/
private ArooaSession session;
/**
* Input for the SQL.
*/
private InputStream input;
/**
* Stop flag.
*/
private volatile boolean stop;
@Override
public void setArooaSession(ArooaSession session) {
this.session = session;
}
/**
* Getter for keepFormat.
*
* @return keepFormat flag.
*/
public boolean isKeepFormat() {
return keepFormat;
}
/**
* Setter for keepFormat
*
* @param keepformat The keepFormat flag.
*/
public void setKeepFormat(boolean keepformat) {
this.keepFormat = keepformat;
}
/**
* Getter for expandProperties.
*
* @return The expandProperties flag.
*/
public boolean isExpandProperties() {
return expandProperties;
}
/**
* Setter for exapndProperties.
*
* @param expandProperties The expandProperties flag.
*/
public void setExpandProperties(boolean expandProperties) {
this.expandProperties = expandProperties;
}
/**
* Getter for delimiterType.
*
* @return The delimiterType.
*/
public DelimiterType getDelimiterType() {
return delimiterType;
}
/**
* Setter for delimiterType.
*
* @param delimiterType The delimiterType.
*/
public void setDelimiterType(DelimiterType delimiterType) {
this.delimiterType = delimiterType;
}
/**
* Getter for delimiter.
*
* @return The delimiter.
*/
public String getDelimiter() {
return delimiter;
}
/**
* Setter for delimiter.
*
* @param delimiter The delimiter.
*/
public void setDelimiter(String delimiter) {
this.delimiter = delimiter;
}
/**
* Getter for encoding.
*
* @return The encoding.
*/
public String getEncoding() {
return encoding;
}
/**
* Setter for encoding.
*
* @param encoding The encoding.
*/
public void setEncoding(String encoding) {
this.encoding = encoding;
}
@Override
public void run() {
stop = false;
try {
startBus();
doProcessing();
stopBus();
}
catch (BusException e) {
throw new RuntimeException(e);
}
finally {
try {
input.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
protected void doProcessing() throws BusException {
StringBuffer sql = new StringBuffer();
BufferedReader in = null;
try {
if (encoding == null) {
in = new BufferedReader(
new InputStreamReader(input));
}
else {
in = new BufferedReader(
new InputStreamReader(input, encoding));
}
} catch (UnsupportedEncodingException e1) {
throw new BusCrashException(e1);
}
while (!stop) {
String line;
try {
line = in.readLine();
} catch (IOException e) {
throw new BusCrashException(e);
}
if (line == null) {
break;
}
if (!keepFormat) {
line = line.trim();
}
if (expandProperties) {
try {
line = replaceProperties(line);
} catch (ArooaConversionException e) {
throw new IllegalArgumentException(line, e);
}
}
if (!keepFormat) {
if (line.startsWith("//")) {
continue;
}
if (line.startsWith("--")) {
continue;
}
StringTokenizer st = new StringTokenizer(line);
if (st.hasMoreTokens()) {
String token = st.nextToken();
if ("REM".equalsIgnoreCase(token)) {
continue;
}
}
}
sql.append(keepFormat ? "\n" : " ").append(line);
// SQL defines "--" as a comment to EOL
// and in Oracle it may contain a hint
// so we cannot just remove it, instead we must end it
if (!keepFormat && line.indexOf("--") >= 0) {
sql.append("\n");
}
if ((delimiterType.equals(DelimiterType.NORMAL)
&& line.lastIndexOf(delimiter) == line.length() - delimiter.length())
|| (delimiterType.equals(DelimiterType.ROW) && line.equalsIgnoreCase(delimiter))) {
String text = sql.substring(
0, sql.length() - delimiter.length()).trim();
if (text.length() > 0) {
dispatch(text);
}
sql.replace(0, sql.length(), "");
}
}
// Catch any statements not followed by ;
String text = sql.toString().trim();
if (text.length() > 0) {
dispatch(text.toString());
}
}
@Override
protected void stopTheBus() {
stop = true;
}
/**
* @param sql
*
* @throws BusCrashException
*/
private void dispatch(String sql) throws BusCrashException {
accept(sql);
}
String replaceProperties(String line) throws ArooaConversionException {
ExpressionParser lineParser = session.getTools().getExpressionParser();
ParsedExpression parsed = lineParser.parse(line);
return parsed.evaluate(session, String.class);
}
public void stop() {
requestBusStop();
}
public InputStream getInput() {
return input;
}
public void setInput(InputStream input) {
this.input = input;
}
}