blob: d879163a1a2488213706c8b6f29119535fcd3234 [file] [log] [blame]
/*=========================================================================
* (c)Copyright 2002-2011, GemStone Systems, Inc. All Rights Reserved.
* 1260 NW Waterhouse Ave., Suite 200, Beaverton, OR 97006
* All Rights Reserved.
* =======================================================================*/
package com.gemstone.gemfire.mgmt.DataBrowser.ui.actions;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.window.ApplicationWindow;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import com.gemstone.gemfire.cache.query.QueryInvalidException;
import com.gemstone.gemfire.mgmt.DataBrowser.app.DataBrowserApp;
import com.gemstone.gemfire.mgmt.DataBrowser.connection.SecurityAttributes;
import com.gemstone.gemfire.mgmt.DataBrowser.controller.DataBrowserController;
import com.gemstone.gemfire.mgmt.DataBrowser.controller.IQueryExecutedEvent;
import com.gemstone.gemfire.mgmt.DataBrowser.controller.IQueryExecutionListener;
import com.gemstone.gemfire.mgmt.DataBrowser.controller.InvalidConfigurationException;
import com.gemstone.gemfire.mgmt.DataBrowser.controller.MissingSecuritiesPropException;
import com.gemstone.gemfire.mgmt.DataBrowser.controller.QueryConfigurationPrms;
import com.gemstone.gemfire.mgmt.DataBrowser.model.member.GemFireMember;
import com.gemstone.gemfire.mgmt.DataBrowser.query.QueryExecutionException;
import com.gemstone.gemfire.mgmt.DataBrowser.query.QueryResult;
import com.gemstone.gemfire.mgmt.DataBrowser.ui.CustomUIMessages;
import com.gemstone.gemfire.mgmt.DataBrowser.ui.MainAppWindow;
import com.gemstone.gemfire.mgmt.DataBrowser.ui.SpecifySecuritiesDlg;
import com.gemstone.gemfire.mgmt.DataBrowser.ui.SecurityPropComposite.Data;
import com.gemstone.gemfire.mgmt.DataBrowser.ui.SecurityPropComposite.SecurityProp;
import com.gemstone.gemfire.mgmt.DataBrowser.utils.LogUtil;
import com.gemstone.gemfire.security.AuthenticationFailedException;
/**
* @author mghosh
*
*/
public class ExecuteQuery extends AbstractDataBrowserAction implements
IRunnableWithProgress {
private String queryString_ = null;
private QueryExecListener qExecutionListener_;
protected Data securityProps = null;
private static final String iconEnabled = null;
private static final String iconDisabled = null;
/**
*
*/
public ExecuteQuery() {
super();
}
/**
* @return the queryString_
*/
public final String getQueryString() {
return queryString_;
}
/**
* @param queryString_
* the queryString_ to set
*/
public final void setQueryString(String qs) {
queryString_ = qs;
}
// **********************************************************
//
// IRunnableWithProgress
//
// **********************************************************
/*
* (non-Javadoc)
*
* @see
* org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.
* runtime.IProgressMonitor)
*/
public void run(IProgressMonitor monitor) throws InvocationTargetException,
InterruptedException {
// TODO Auto-generated method stub
}
// **********************************************************
//
// AbstractDataBrowserAction stuff
//
// **********************************************************
/*
* (non-Javadoc)
*
* @see
* com.gemstone.gemfire.mgmt.DataBrowser.ui.actions.AbstractDataBrowserAction
* #getText()
*/
@Override
public String getText() {
return "Execute Query";
}
/*
* (non-Javadoc)
*
* @see
* com.gemstone.gemfire.mgmt.DataBrowser.ui.actions.AbstractDataBrowserAction
* #getDisabledIcon()
*/
@Override
public String getDisabledIcon() {
return iconDisabled;
}
/*
* (non-Javadoc)
*
* @see
* com.gemstone.gemfire.mgmt.DataBrowser.ui.actions.AbstractDataBrowserAction
* #getEnabledIcon()
*/
@Override
public String getEnabledIcon() {
return iconEnabled;
}
// ********************************************************** //
// IAction stuff
//
// **********************************************************
//
// /* (non-Javadoc)
// * @see org.eclipse.jface.action.Action#getDisabledImageDescriptor()
// */
// @Override
// public ImageDescriptor getDisabledImageDescriptor() {
// // TODO Auto-generated method stub
// return super.getDisabledImageDescriptor();
// }
//
// /* (non-Javadoc)
// * @see org.eclipse.jface.action.Action#getImageDescriptor()
// */
// @Override
// public ImageDescriptor getImageDescriptor() {
// final String fqnImage_ = "/com/gemstone/gemfire/mgmt/DataBrowser/resources/icons/ExecuteQuery.ico";
// InputStream isImage = null;
// try {
// isImage = getClass().getResourceAsStream(fqnImage_);
//
// if (null != isImage) {
// imgEnabled_ = new Image(null, isImage);
// imgDescEnabled_ = ImageDescriptor.createFromImage(imgEnabled_);
// }
// } catch (NullPointerException xptn) {
// // handler for getResourceAsStream
// LogUtil.warning(
// "NullPointerException in ExecuteQuery.getImageDescriptor (getResourceAsStream). Continuing...",
// xptn );
// } catch (SWTException xptn) {
// // handler for org.eclipse.swt.graphics.Image ctor
// // we continue an try to add the other nodes
// LogUtil.warning(
// "SWTException in ExecuteQuery.getImageDescriptor (org.eclipse.swt.graphics.Image ctor). Continuing...",
// xptn );
// } catch (SWTError err) {
// // Log this (Image ctor could throw this), and rethrow
// LogUtil.error(
// "SWTError in ExecuteQuery.getImageDescriptor (org.eclipse.swt.graphics.Image ctor). This could be due to handles in the underlying widget kit being exhaused. Terminating.",
// err );
// throw err;
// }
// finally {
// if( null != isImage ) {
// try {
// isImage.close();
// } catch (IOException e) {
// LogUtil.warning(
// "IOException in QueryPrefsPage.getImageDescriptor (isImage.close(..)). Ignoring.",
// e );
// }
// isImage = null;
// }
// }
//
// return imgDescEnabled_;
// }
//
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.action.Action#getDescription()
*/
@Override
public String getDescription() {
return "Executes a GemFire OQL Query";
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.action.Action#getToolTipText()
*/
@Override
public String getToolTipText() {
return "Execute a GemFire OQL query";
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.action.Action#isEnabled()
*/
@Override
public boolean isEnabled() {
DataBrowserApp app = DataBrowserApp.getInstance();
boolean fRet = true;
if (null != app) {
DataBrowserController ctrlr = app.getController();
if (null != ctrlr) {
fRet = ctrlr.hasConnection();
}
}
return fRet;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.action.Action#run()
*/
@Override
public void run() {
runWithEvent(new Event());
}
protected ApplicationWindow getApplicationWindow() {
DataBrowserApp app = DataBrowserApp.getInstance();
return app.getMainWindow();
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.jface.action.Action#runWithEvent(org.eclipse.swt.widgets.Event)
*/
@Override
public void runWithEvent(Event event1) {
DataBrowserApp app = DataBrowserApp.getInstance();
if (null != app) {
MainAppWindow wnd = (MainAppWindow)getApplicationWindow();
if (null != wnd) {
ArrayList<Object> p = new ArrayList<Object>();
// TODO MGH - this might be a default config param?
p.add(Integer.valueOf(0)); // get the current selection
ArrayList<Object> r = new ArrayList<Object>();
wnd.sendCustomMessage(CustomUIMessages.QRY_MSG_GET_QUERY_STR_FOR_EXEC,
p, r);
String strQuery = null;
if (1 == r.size()) {
Object rv = r.get(0);
if (rv instanceof String) {
strQuery = (String) rv;
}
}
if (strQuery == null) {
p = new ArrayList<Object>();
p.add(Integer.valueOf(1)); // get the last query string line
r = new ArrayList<Object>();
wnd.sendCustomMessage(
CustomUIMessages.QRY_MSG_GET_QUERY_STR_FOR_EXEC, p, r);
if (1 == r.size()) {
Object rv = r.get(0);
if (rv instanceof String) {
strQuery = (String) rv;
}
}
}
if (strQuery == null || (0 == strQuery.length())) {
MessageBox mb = new MessageBox(wnd.getShell(), SWT.OK);
mb.setText("DataBrowser Error");
mb.setMessage("No query string provided for execution.");
mb.open();
return;
}
p = new ArrayList<Object>();
r = new ArrayList<Object>();
wnd.sendCustomMessage(
CustomUIMessages.QRY_MEMBER_SELECTED_FOR_QUERY_EXEC, p, r);
GemFireMember member = null;
// TODO MGH - is there any possibility that multiple members could be
// selected?
if (1 == r.size()) {
Object rv = r.get(0);
if (rv instanceof GemFireMember) {
member = (GemFireMember) rv;
}
}
if (member == null) {
MessageBox mb = new MessageBox(wnd.getShell(), SWT.OK);
mb.setText("DataBrowser Error");
mb
.setMessage("A GemFire member must be selected to execute a query. Please select a member from the list.");
mb.open();
return;
}
QueryConfigurationPrms qryParams = new QueryConfigurationPrms();
qryParams.setQueryString(strQuery);
qryParams.setMember(member);
if (qExecutionListener_ == null)
qExecutionListener_ = new QueryExecListener();
qryParams.setQueryExecutionListener(qExecutionListener_);
securityProps = null;
executeQuery(app, qryParams);
}
}
}
protected void executeQuery(DataBrowserApp app,
QueryConfigurationPrms qryParams) {
boolean retry = false;
do {
retry = false;
try {
LogUtil.fine("ExecuteQuery.runWithEvent: About to execute.");
setQueryString(qryParams.getQueryString());
app.getController().executeQuery(qryParams);
retry = false;
}
catch (InvalidConfigurationException xptn) {
LogUtil.error("ExecuteQuery.runWithEvent: Could not execute query.",
xptn);
retry = false;
errorOccuredWhileQueryExecution(xptn);
}
catch (QueryExecutionException e) {
LogUtil.error("ExecuteQuery.runWithEvent: Could not execute query.", e);
retry = false;
errorOccuredWhileQueryExecution(e);
}
catch (MissingSecuritiesPropException e) {
MessageBox mb = new MessageBox(app.getMainWindow().getShell(), SWT.YES
| SWT.NO);
mb.setText("DataBrowser Error");
mb
.setMessage("Security is enabled on the server.\nWould you like to specify the security properties and execute the query again?");
int open = mb.open();
if (open == SWT.YES) {
boolean popUpSpecifySecurityDlg = popUpSpecifySecurityDlg();
if (popUpSpecifySecurityDlg)
retry = true;
else{
retry = false;
cancelQuery();
}
}
}
catch (AuthenticationFailedException ex) {
MessageBox mb = new MessageBox(getApplicationWindow().getShell(),
SWT.YES | SWT.NO);
mb.setText("DataBrowser Error");
String errMsg = ex.getMessage() + " " + qryParams.getQueryString();
errMsg = errMsg
+ ". \n"
+ "Would you like to specify security properties and execute the query again ?";
mb.setMessage(errMsg);
int iRetry = mb.open();
if (SWT.YES == iRetry) {
boolean popUpSpecifySecurityDlg = popUpSpecifySecurityDlg();
if (popUpSpecifySecurityDlg) {
retry = true;
}
}
if(!retry)
cancelQuery();
} finally {
/* un-setting query string as currently it's not required further. */
setQueryString(null);
}
} while (retry);
}
/**
* This is suppose to do clean up, if any, once error happened while query
* execution
*
* @param e
*/
protected void errorOccuredWhileQueryExecution(Exception e) {
}
/**
* cancel the query execution if query already running
*/
protected void cancelQuery(){
}
private boolean popUpSpecifySecurityDlg() {
DataBrowserApp app = DataBrowserApp.getInstance();
Shell shl = getApplicationWindow().getShell();
SpecifySecuritiesDlg dlg = new SpecifySecuritiesDlg(shl);
String errMsg = null;
boolean fPromptForRetry = false;
boolean fRetry = false;
boolean okPressed = false;
do {
fRetry = false;
fPromptForRetry = false;
okPressed = false;
dlg.setSecurityData(securityProps);
int iRetCode = dlg.open();
fRetry = false;
if (Window.OK == iRetCode) {
okPressed = true;
DataBrowserController cntrlr = DataBrowserApp.getInstance()
.getController();
SecurityAttributes sAttrs = new SecurityAttributes();
securityProps = dlg.getData();
String pluginJarFQN = securityProps.getSecurityPlugin();
List<SecurityProp> secProperties = securityProps.getSecurityProperties();
if ((pluginJarFQN.trim().length() == 0)) {
fPromptForRetry = true;
errMsg = "No Security plugin provided. \nWould you like to specify security properties again ?";
}
if (true == fPromptForRetry) {
if (null != errMsg) {
LogUtil.error(errMsg);
}
MessageBox mb = new MessageBox(shl, SWT.YES | SWT.NO);
mb.setText( "Warning" );
if (null == errMsg) {
errMsg = "No Security plugin provided. \nWould you like to specify security properties again ?";
}
mb.setMessage(errMsg);
int iRetry = mb.open();
fRetry = (SWT.YES == iRetry) ? true : false;
} else {
sAttrs.setSecurityPluginPath(pluginJarFQN);
Map<String, String> props = new HashMap<String, String>();
for (int i = 0; i < secProperties.size(); i++) {
SecurityProp securityProp = secProperties.get(i);
String key = securityProp.getKey();
String value = securityProp.getValue();
props.put(key, value);
}
sAttrs.setSecurityProperties(props);
cntrlr.setSecurityAttributes(sAttrs);
}
}
} while (true == fRetry);
return okPressed;
}
protected void errorInQueryExecution(IQueryExecutedEvent queryEvent,
Throwable ex) {
DataBrowserApp app = DataBrowserApp.getInstance();
final ApplicationWindow wnd = getApplicationWindow();
if (ex instanceof QueryExecutionException) {
QueryExecutionException qEx = (QueryExecutionException) ex;
if (qEx.isAuthenticationFailed()) {
reExecuteQuery(queryEvent, ex);
return;
} else if (qEx.isAuthorizationFailed()) {
MessageBox mb = new MessageBox(wnd.getShell(), SWT.OK);
mb.setText("DataBrowser Error");
mb.setMessage("An error occurred during executing the query:\t"
+ queryEvent.getQueryString() + "\n\n" + "Error Details = "
+ ex.getMessage());
mb.open();
return;
}
}
if (ex instanceof AuthenticationFailedException) {
reExecuteQuery(queryEvent, ex);
return;
}
MessageBox mb = new MessageBox(wnd.getShell(), SWT.OK);
mb.setText("DataBrowser Error");
String errorMessage = "Following error occurred: \n";;
String syntaxError = "";
if (ex instanceof QueryInvalidException) {
syntaxError = extractSyntaxErrorInfo((QueryInvalidException)ex, queryEvent.getQueryString());
}
if (ex != null && (ex.getMessage() != null)) {
errorMessage = errorMessage + ex.getMessage();
} else {
String exception = String.valueOf(ex);
errorMessage = errorMessage + exception;
}
mb.setMessage(errorMessage + "\n" + syntaxError + "\nPlease check logs for further details.");
mb.open();
}
protected String extractSyntaxErrorInfo(QueryInvalidException ex, String queryString) {
String syntaxError = "";
antlr.RecognitionException recogException = null;
Throwable cause = ex.getCause();
if (cause instanceof antlr.TokenStreamRecognitionException) {
recogException = ((antlr.TokenStreamRecognitionException) cause).recog;
} else if (cause instanceof antlr.RecognitionException) {
recogException = (antlr.RecognitionException) cause;
}
if (recogException != null) {
int errorAt = recogException.getColumn();
if (queryString != null) {
queryString = queryString.trim(); //trims spaces & \r
int queryLength = queryString.length();
StringBuilder errorPointer = new StringBuilder();
for (int i = 0; i <= queryLength; i++) {
if (i == errorAt - 1) {
errorPointer.append("^");
} else {
errorPointer.append("-");
}
}
LogUtil.error(ex.getMessage() + "\n\t" + queryString
+ "\n\t" + errorPointer.toString());
}
/*
* Line number information is also available. But it's for the line number
* for a multi line query and it is not the line number on the UI. Hence,
* skipping line number for now as it will be confusing to the user
*/
syntaxError = "In the query string for character at position: " + errorAt;
}
return syntaxError;
}
private void reExecuteQuery(IQueryExecutedEvent queryEvent, Throwable ex) {
DataBrowserApp app = DataBrowserApp.getInstance();
ApplicationWindow wnd = getApplicationWindow();
MessageBox mb = new MessageBox(wnd.getShell(), SWT.YES | SWT.NO);
mb.setText("DataBrowser Error");
String errMsg = ex.getMessage() + " " + queryEvent.getQueryString();
errMsg = errMsg + ". \n" + "Would you like to specify security properties and execute the query again ?";
mb.setMessage(errMsg);
int iRetry = mb.open();
boolean fPromptForRetry = (SWT.YES == iRetry) ? true : false;
if (fPromptForRetry) {
boolean popUpSpecifySecurityDlg = popUpSpecifySecurityDlg();
if (popUpSpecifySecurityDlg) {
QueryConfigurationPrms qryParams = new QueryConfigurationPrms();
qryParams.setQueryString(queryEvent.getQueryString());
qryParams.setMember(queryEvent.getMember());
qryParams.setQueryExecutionListener(new QueryExecListener());
executeQuery(app, qryParams);
}else{
cancelQuery();
}
}
}
protected class QueryExecListener implements IQueryExecutionListener {
private QueryResultProcessor queryResultProcessor = new QueryResultProcessor();
QueryExecListener() {
}
/*
* (non-Javadoc)
*
* @see
* com.gemstone.gemfire.mgmt.DataBrowser.controller.IQueryExecutionListener
* #queryExecuted
* (com.gemstone.gemfire.mgmt.DataBrowser.controller.IQueryExecutedEvent)
*/
public void queryExecuted(IQueryExecutedEvent queryEvent) {
QueryResult qryres = queryEvent.getQueryResult();
DataBrowserApp app = DataBrowserApp.getInstance();
ApplicationWindow wnd = getApplicationWindow();
queryResultProcessor.addResults(qryres);
if (queryResultProcessor.isProcessed()) {
queryResultProcessor.setProcessed(false);
runTaskInAsyncUIThread(wnd.getShell(), queryResultProcessor);
}
}
/*
* (non-Javadoc)
*
* @see
* com.gemstone.gemfire.mgmt.DataBrowser.controller.IQueryExecutionListener
* #queryFailed
* (com.gemstone.gemfire.mgmt.DataBrowser.controller.IQueryExecutedEvent,
* java.lang.Throwable)
*/
public void queryFailed(final IQueryExecutedEvent queryEvent,
final Throwable ex) {
if (ex != null) {
LogUtil.error("Error while executing query: ", ex);
}
DataBrowserApp app = DataBrowserApp.getInstance();
final ApplicationWindow wnd = getApplicationWindow();
Runnable runnable = new Runnable() {
public void run() {
errorInQueryExecution(queryEvent, ex);
}
};
runTaskInAsyncUIThread(wnd.getShell(), runnable);
}
private void runTaskInAsyncUIThread(Shell shell, Runnable runnable) {
Display display = shell.getDisplay();
display.asyncExec(runnable);
}
}
private static class QueryResultProcessor implements Runnable {
private boolean processed = true;
QueryResult queryResults = null;
public void run() {
processed = false;
ArrayList<Object> res = new ArrayList<Object>();
ArrayList<Object> prms = new ArrayList<Object>();
if (queryResults == null) {
processed = true;
return;
}
synchronized (this) {
prms.add(queryResults);
queryResults = null;
processed = true;
}
DataBrowserApp app = DataBrowserApp.getInstance();
if (null != app) {
final MainAppWindow wnd = app.getMainWindow();
if (wnd != null) {
Shell shell = wnd.getShell();
if (shell != null && !shell.isDisposed()) {
wnd.sendCustomMessage(
CustomUIMessages.QRY_MSG_ADD_QUERY_SINGLE_RESULT, prms, res);
}
}
}
}
public boolean isProcessed() {
return processed;
}
public void setProcessed(boolean processed) {
this.processed = processed;
}
public void addResults(QueryResult qryres) {
if (queryResults == null) {
queryResults = qryres;
return;
}
synchronized (this) {
queryResults = qryres;
}
}
}
}