001: package net.sourceforge.squirrel_sql.plugins.sqlparam;
002:
003: /*
004: * Copyright (C) 2007 Thorsten Mürell
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU General Public License
008: * as published by the Free Software Foundation; either version 2
009: * of the License, or any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
019: */
020: import java.awt.AWTEvent;
021: import java.awt.ActiveEvent;
022: import java.awt.Component;
023: import java.awt.MenuComponent;
024: import java.awt.Toolkit;
025: import java.lang.reflect.InvocationTargetException;
026: import java.util.HashMap;
027: import java.util.Map;
028: import java.util.regex.Matcher;
029: import java.util.regex.Pattern;
030:
031: import javax.swing.JLayeredPane;
032: import javax.swing.SwingUtilities;
033:
034: import net.sourceforge.squirrel_sql.client.session.ISession;
035: import net.sourceforge.squirrel_sql.client.session.event.ISQLExecutionListener;
036: import net.sourceforge.squirrel_sql.fw.gui.GUIUtils;
037: import net.sourceforge.squirrel_sql.fw.gui.action.SelectInternalFrameCommand;
038: import net.sourceforge.squirrel_sql.fw.util.log.ILogger;
039: import net.sourceforge.squirrel_sql.fw.util.log.LoggerController;
040: import net.sourceforge.squirrel_sql.plugins.sqlparam.gui.AskParamValueDialog;
041:
042: /**
043: * This listener listens for SQL execution.
044: *
045: * @author Thorsten Mürell
046: */
047: public class SQLParamExecutionListener implements ISQLExecutionListener {
048:
049: private final static ILogger log = LoggerController
050: .createLogger(SQLParamPlugin.class);
051: private ISession session = null;
052: private SQLParamPlugin plugin = null;
053: private AskParamValueDialog dialog = null;
054:
055: /**
056: * The constructor
057: *
058: * @param plugin
059: * @param session
060: */
061: public SQLParamExecutionListener(SQLParamPlugin plugin,
062: ISession session) {
063: this .session = session;
064: this .plugin = plugin;
065: }
066:
067: /**
068: * This method is called when the SQL was executed.
069: *
070: * @param sql
071: */
072: public void statementExecuted(String sql) {
073: // log.info("SQL executed: " + sql);
074: }
075:
076: /**
077: * Called prior to an individual statement being executed. If you modify the
078: * script remember to return it so that the caller knows about the
079: * modifications.
080: *
081: * @param sql The SQL to be executed.
082: *
083: * @return The SQL to be executed. If <TT>null</TT> returned then the
084: * statement will not be executed.
085: */
086: public String statementExecuting(String sql) {
087: // log.info("SQL starting to execute: " + sql);
088: StringBuffer buffer = new StringBuffer(sql);
089: Map<String, String> cache = plugin.getCache();
090: Map<String, String> currentCache = new HashMap<String, String>();
091: Pattern p = Pattern.compile(":[a-zA-Z]\\w+");
092:
093: Matcher m = p.matcher(buffer);
094:
095: while (m.find()) {
096: if (isQuoted(buffer, m.start()))
097: continue;
098: final String var = m.group();
099: String value = null;
100: if (currentCache.containsKey(var)) {
101: value = currentCache.get(var);
102: } else {
103: final String oldValue = cache.get(var);
104: if (SwingUtilities.isEventDispatchThread()) {
105: createParameterDialog(var, oldValue);
106: while (!dialog.isDone()) {
107: try {
108: AWTEvent event = Toolkit
109: .getDefaultToolkit()
110: .getSystemEventQueue()
111: .getNextEvent();
112: Object source = event.getSource();
113: if (event instanceof ActiveEvent) {
114: ((ActiveEvent) event).dispatch();
115: } else if (source instanceof Component) {
116: ((Component) source)
117: .dispatchEvent(event);
118: } else if (source instanceof MenuComponent) {
119: ((MenuComponent) source)
120: .dispatchEvent(event);
121: } else {
122: System.err
123: .println("Unable to dispatch: "
124: + event);
125: }
126: } catch (Exception e) {
127: e.printStackTrace();
128: }
129: }
130: } else {
131: try {
132: SwingUtilities.invokeAndWait(new Runnable() {
133: public void run() {
134: createParameterDialog(var, oldValue);
135: }
136: });
137: while (!dialog.isDone()) {
138: wait();
139: }
140: } catch (InvocationTargetException ite) {
141: ite.printStackTrace();
142: } catch (InterruptedException ie) {
143: ie.printStackTrace();
144: }
145: }
146: if (dialog.isCancelled()) {
147: dialog = null;
148: return null;
149: }
150: value = sanitizeValue(dialog.getValue(), dialog
151: .isQuotingNeeded());
152: cache.put(var, dialog.getValue());
153: currentCache.put(var, value);
154: dialog = null;
155: }
156: buffer.replace(m.start(), m.end(), value);
157: m.reset();
158: }
159:
160: GUIUtils.processOnSwingEventThread(new Runnable() {
161: public void run() {
162: new SelectInternalFrameCommand(session
163: .getActiveSessionWindow()).execute();
164: }
165: });
166: // log.info("SQL passing to execute: " + buffer.toString());
167: return buffer.toString();
168: }
169:
170: private void createParameterDialog(String parameter, String oldValue) {
171: dialog = new AskParamValueDialog(parameter, oldValue);
172: session.getApplication().getMainFrame().addInternalFrame(
173: dialog, true);
174: dialog.setLayer(JLayeredPane.MODAL_LAYER);
175: dialog.moveToFront();
176: GUIUtils.centerWithinDesktop(dialog);
177: dialog.setVisible(true);
178: }
179:
180: private String sanitizeValue(String value, boolean quoting) {
181: String retValue = value;
182: boolean quotesNeeded = quoting;
183:
184: try {
185: Float.parseFloat(value);
186: } catch (NumberFormatException nfe) {
187: quotesNeeded = true;
188: }
189:
190: if (quotesNeeded) {
191: retValue = "'" + value + "'";
192: }
193: return retValue;
194: }
195:
196: private boolean isQuoted(StringBuffer buffer, int position) {
197: String part = buffer.substring(0, position);
198: if (searchAllOccurences(part, "\"") % 2 != 0)
199: return true;
200: if (searchAllOccurences(part, "'") % 2 != 0)
201: return true;
202: return false;
203: }
204:
205: private int searchAllOccurences(String haystack, String needle) {
206: int i = 0;
207: int pos = 0;
208: while ((pos = haystack.indexOf(needle, pos + 1)) > -1) {
209: i++;
210: }
211: return i;
212: }
213:
214: }
|