Merge branch 'eugenia/web_ui_beta_fixes' into madhusudancs/error-reporting
diff --git a/asterix-app/src/main/java/edu/uci/ics/asterix/api/http/servlet/APIServlet.java b/asterix-app/src/main/java/edu/uci/ics/asterix/api/http/servlet/APIServlet.java
index c7954d8..fcea1ea 100644
--- a/asterix-app/src/main/java/edu/uci/ics/asterix/api/http/servlet/APIServlet.java
+++ b/asterix-app/src/main/java/edu/uci/ics/asterix/api/http/servlet/APIServlet.java
@@ -89,29 +89,12 @@
         } catch (ParseException | TokenMgrError | edu.uci.ics.asterix.aqlplus.parser.TokenMgrError pe) {
             GlobalConfig.ASTERIX_LOGGER.log(Level.INFO, pe.toString(), pe);
             out.println("<pre class=\"error\">");
-            String message = pe.getMessage();
-            message = message.replace("<", "&lt");
-            message = message.replace(">", "&gt");
-            out.println("SyntaxError:" + message);
-            int pos = message.indexOf("line");
-            if (pos > 0) {
-                int columnPos = message.indexOf(",", pos + 1 + "line".length());
-                int lineNo = Integer.parseInt(message.substring(pos + "line".length() + 1, columnPos));
-                String[] lines = query.split("\n");
-                if (lineNo >= lines.length) {
-                    out.println("===> &ltBLANK LINE&gt");
-                } else {
-                    String line = lines[lineNo - 1];
-                    out.println("==> " + line);
-                }
-            }
-            out.println("</pre>");
-        } catch (Exception e) {
-            String errorMessage = ResultUtils.extractErrorMessage(e);
-            GlobalConfig.ASTERIX_LOGGER.log(Level.SEVERE, errorMessage, e);
-            out.println("<pre class=\"error\">");
+            String errorMessage = ResultUtils.buildParseExceptionMessage(pe, query);
             out.println(errorMessage);
             out.println("</pre>");
+        } catch (Exception e) {
+            GlobalConfig.ASTERIX_LOGGER.log(Level.SEVERE, e.getMessage(), e);
+            ResultUtils.webUIErrorHandler(out, e);
         }
     }
 
@@ -126,7 +109,7 @@
         } else {
             resourcePath = requestURI;
         }
-                
+
         InputStream is = APIServlet.class.getResourceAsStream(resourcePath);
         if (is == null) {
             response.sendError(HttpServletResponse.SC_NOT_FOUND);
@@ -134,18 +117,18 @@
         }
 
         // Special handler for font files and .png resources
-        if (resourcePath.endsWith(".png")) { 
-            
+        if (resourcePath.endsWith(".png")) {
+
             BufferedImage img = ImageIO.read(is);
             OutputStream outputStream = response.getOutputStream();
-            String formatName = "png";            
+            String formatName = "png";
             response.setContentType("image/png");
             ImageIO.write(img, formatName, outputStream);
             outputStream.close();
             return;
 
         }
-        
+
         response.setCharacterEncoding("utf-8");
         InputStreamReader isr = new InputStreamReader(is);
         StringBuilder sb = new StringBuilder();
diff --git a/asterix-app/src/main/java/edu/uci/ics/asterix/api/http/servlet/RESTAPIServlet.java b/asterix-app/src/main/java/edu/uci/ics/asterix/api/http/servlet/RESTAPIServlet.java
index dff759d..c5d0e57 100644
--- a/asterix-app/src/main/java/edu/uci/ics/asterix/api/http/servlet/RESTAPIServlet.java
+++ b/asterix-app/src/main/java/edu/uci/ics/asterix/api/http/servlet/RESTAPIServlet.java
@@ -32,6 +32,7 @@
 import edu.uci.ics.asterix.aql.base.Statement.Kind;
 import edu.uci.ics.asterix.aql.parser.AQLParser;
 import edu.uci.ics.asterix.aql.parser.ParseException;
+import edu.uci.ics.asterix.aql.parser.TokenMgrError;
 import edu.uci.ics.asterix.aql.translator.AqlTranslator;
 import edu.uci.ics.asterix.common.config.GlobalConfig;
 import edu.uci.ics.asterix.metadata.MetadataManager;
@@ -95,35 +96,22 @@
             AqlTranslator aqlTranslator = new AqlTranslator(aqlStatements, out, sessionConfig, format);
 
             aqlTranslator.compileAndExecute(hcc, hds, asyncResults);
-
-        } catch (ParseException pe) {
-            GlobalConfig.ASTERIX_LOGGER.log(Level.INFO, pe.toString(), pe);
-            StringBuilder errorMessage = new StringBuilder();
-            String message = pe.getLocalizedMessage();
-            message = message.replace("<", "&lt");
-            message = message.replace(">", "&gt");
-            errorMessage.append("SyntaxError:" + message + "\n");
-            int pos = message.indexOf("line");
-            if (pos > 0) {
-                int columnPos = message.indexOf(",", pos + 1 + "line".length());
-                int lineNo = Integer.parseInt(message.substring(pos + "line".length() + 1, columnPos));
-                String line = query.split("\n")[lineNo - 1];
-                errorMessage.append("==> " + line + "\n");
-            }
-            JSONObject errorResp = ResultUtils.getErrorResponse(2, errorMessage.toString());
+        } catch (ParseException | TokenMgrError | edu.uci.ics.asterix.aqlplus.parser.TokenMgrError pe) {
+            GlobalConfig.ASTERIX_LOGGER.log(Level.SEVERE, pe.getMessage(), pe);
+            String errorMessage = ResultUtils.buildParseExceptionMessage(pe, query);
+            JSONObject errorResp = ResultUtils.getErrorResponse(2, errorMessage, "", "");
             out.write(errorResp.toString());
         } catch (Exception e) {
-            String errorMessage = ResultUtils.extractErrorMessage(e);
-            GlobalConfig.ASTERIX_LOGGER.log(Level.SEVERE, errorMessage, e);
-            JSONObject errorResp = ResultUtils.getErrorResponse(99, errorMessage);
-            out.write(errorResp.toString());
+            GlobalConfig.ASTERIX_LOGGER.log(Level.SEVERE, e.getMessage(), e);
+            ResultUtils.apiErrorHandler(out, e);
         }
     }
 
     private boolean checkForbiddenStatements(List<Statement> aqlStatements, PrintWriter out) {
         for (Statement st : aqlStatements) {
             if (!getAllowedStatements().contains(st.getKind())) {
-                JSONObject errorResp = ResultUtils.getErrorResponse(1, String.format(getErrorMessage(), st.getKind()));
+                JSONObject errorResp = ResultUtils.getErrorResponse(1, String.format(getErrorMessage(), st.getKind()),
+                        "", "");
                 out.write(errorResp.toString());
                 return true;
             }
diff --git a/asterix-app/src/main/java/edu/uci/ics/asterix/aql/translator/AqlTranslator.java b/asterix-app/src/main/java/edu/uci/ics/asterix/aql/translator/AqlTranslator.java
index 41be278..93dcf39 100644
--- a/asterix-app/src/main/java/edu/uci/ics/asterix/aql/translator/AqlTranslator.java
+++ b/asterix-app/src/main/java/edu/uci/ics/asterix/aql/translator/AqlTranslator.java
@@ -186,112 +186,107 @@
             metadataProvider.setOutputFile(outputFile);
             metadataProvider.setConfig(config);
             jobsToExecute.clear();
-            try {
-                switch (stmt.getKind()) {
-                    case SET: {
-                        handleSetStatement(metadataProvider, stmt, config);
-                        break;
-                    }
-                    case DATAVERSE_DECL: {
-                        activeDefaultDataverse = handleUseDataverseStatement(metadataProvider, stmt);
-                        break;
-                    }
-                    case CREATE_DATAVERSE: {
-                        handleCreateDataverseStatement(metadataProvider, stmt);
-                        break;
-                    }
-                    case DATASET_DECL: {
-                        handleCreateDatasetStatement(metadataProvider, stmt, hcc);
-                        break;
-                    }
-                    case CREATE_INDEX: {
-                        handleCreateIndexStatement(metadataProvider, stmt, hcc);
-                        break;
-                    }
-                    case TYPE_DECL: {
-                        handleCreateTypeStatement(metadataProvider, stmt);
-                        break;
-                    }
-                    case NODEGROUP_DECL: {
-                        handleCreateNodeGroupStatement(metadataProvider, stmt);
-                        break;
-                    }
-                    case DATAVERSE_DROP: {
-                        handleDataverseDropStatement(metadataProvider, stmt, hcc);
-                        break;
-                    }
-                    case DATASET_DROP: {
-                        handleDatasetDropStatement(metadataProvider, stmt, hcc);
-                        break;
-                    }
-                    case INDEX_DROP: {
-                        handleIndexDropStatement(metadataProvider, stmt, hcc);
-                        break;
-                    }
-                    case TYPE_DROP: {
-                        handleTypeDropStatement(metadataProvider, stmt);
-                        break;
-                    }
-                    case NODEGROUP_DROP: {
-                        handleNodegroupDropStatement(metadataProvider, stmt);
-                        break;
-                    }
-
-                    case CREATE_FUNCTION: {
-                        handleCreateFunctionStatement(metadataProvider, stmt);
-                        break;
-                    }
-
-                    case FUNCTION_DROP: {
-                        handleFunctionDropStatement(metadataProvider, stmt);
-                        break;
-                    }
-
-                    case LOAD_FROM_FILE: {
-                        handleLoadFromFileStatement(metadataProvider, stmt, hcc);
-                        break;
-                    }
-                    case WRITE_FROM_QUERY_RESULT: {
-                        handleWriteFromQueryResultStatement(metadataProvider, stmt, hcc);
-                        break;
-                    }
-                    case INSERT: {
-                        handleInsertStatement(metadataProvider, stmt, hcc);
-                        break;
-                    }
-                    case DELETE: {
-                        handleDeleteStatement(metadataProvider, stmt, hcc);
-                        break;
-                    }
-
-                    case BEGIN_FEED: {
-                        handleBeginFeedStatement(metadataProvider, stmt, hcc);
-                        break;
-                    }
-
-                    case CONTROL_FEED: {
-                        handleControlFeedStatement(metadataProvider, stmt, hcc);
-                        break;
-                    }
-
-                    case QUERY: {
-                        metadataProvider.setResultSetId(new ResultSetId(resultSetIdCounter++));
-                        executionResult.add(handleQuery(metadataProvider, (Query) stmt, hcc, hdc, asyncResults));
-                        break;
-                    }
-
-                    case WRITE: {
-                        Pair<IAWriterFactory, FileSplit> result = handleWriteStatement(metadataProvider, stmt);
-                        if (result.first != null) {
-                            writerFactory = result.first;
-                        }
-                        outputFile = result.second;
-                        break;
-                    }
-
+            switch (stmt.getKind()) {
+                case SET: {
+                    handleSetStatement(metadataProvider, stmt, config);
+                    break;
                 }
-            } catch (Exception e) {
-                throw new AlgebricksException(e);
+                case DATAVERSE_DECL: {
+                    activeDefaultDataverse = handleUseDataverseStatement(metadataProvider, stmt);
+                    break;
+                }
+                case CREATE_DATAVERSE: {
+                    handleCreateDataverseStatement(metadataProvider, stmt);
+                    break;
+                }
+                case DATASET_DECL: {
+                    handleCreateDatasetStatement(metadataProvider, stmt, hcc);
+                    break;
+                }
+                case CREATE_INDEX: {
+                    handleCreateIndexStatement(metadataProvider, stmt, hcc);
+                    break;
+                }
+                case TYPE_DECL: {
+                    handleCreateTypeStatement(metadataProvider, stmt);
+                    break;
+                }
+                case NODEGROUP_DECL: {
+                    handleCreateNodeGroupStatement(metadataProvider, stmt);
+                    break;
+                }
+                case DATAVERSE_DROP: {
+                    handleDataverseDropStatement(metadataProvider, stmt, hcc);
+                    break;
+                }
+                case DATASET_DROP: {
+                    handleDatasetDropStatement(metadataProvider, stmt, hcc);
+                    break;
+                }
+                case INDEX_DROP: {
+                    handleIndexDropStatement(metadataProvider, stmt, hcc);
+                    break;
+                }
+                case TYPE_DROP: {
+                    handleTypeDropStatement(metadataProvider, stmt);
+                    break;
+                }
+                case NODEGROUP_DROP: {
+                    handleNodegroupDropStatement(metadataProvider, stmt);
+                    break;
+                }
+
+                case CREATE_FUNCTION: {
+                    handleCreateFunctionStatement(metadataProvider, stmt);
+                    break;
+                }
+
+                case FUNCTION_DROP: {
+                    handleFunctionDropStatement(metadataProvider, stmt);
+                    break;
+                }
+
+                case LOAD_FROM_FILE: {
+                    handleLoadFromFileStatement(metadataProvider, stmt, hcc);
+                    break;
+                }
+                case WRITE_FROM_QUERY_RESULT: {
+                    handleWriteFromQueryResultStatement(metadataProvider, stmt, hcc);
+                    break;
+                }
+                case INSERT: {
+                    handleInsertStatement(metadataProvider, stmt, hcc);
+                    break;
+                }
+                case DELETE: {
+                    handleDeleteStatement(metadataProvider, stmt, hcc);
+                    break;
+                }
+
+                case BEGIN_FEED: {
+                    handleBeginFeedStatement(metadataProvider, stmt, hcc);
+                    break;
+                }
+
+                case CONTROL_FEED: {
+                    handleControlFeedStatement(metadataProvider, stmt, hcc);
+                    break;
+                }
+
+                case QUERY: {
+                    metadataProvider.setResultSetId(new ResultSetId(resultSetIdCounter++));
+                    executionResult.add(handleQuery(metadataProvider, (Query) stmt, hcc, hdc, asyncResults));
+                    break;
+                }
+
+                case WRITE: {
+                    Pair<IAWriterFactory, FileSplit> result = handleWriteStatement(metadataProvider, stmt);
+                    if (result.first != null) {
+                        writerFactory = result.first;
+                    }
+                    outputFile = result.second;
+                    break;
+                }
             }
         }
         return executionResult;
@@ -364,7 +359,7 @@
             MetadataManager.INSTANCE.commitTransaction(mdTxnCtx);
         } catch (Exception e) {
             abort(e, e, mdTxnCtx);
-            throw new AlgebricksException(e);
+            throw e;
         } finally {
             releaseWriteLatch();
         }
@@ -528,7 +523,7 @@
                 }
             }
 
-            throw new AlgebricksException(e);
+            throw e;
         } finally {
             releaseWriteLatch();
         }
@@ -664,7 +659,7 @@
                             + "." + datasetName + "." + indexName + ") couldn't be removed from the metadata", e);
                 }
             }
-            throw new AlgebricksException(e);
+            throw e;
         } finally {
             releaseWriteLatch();
         }
@@ -703,7 +698,7 @@
             MetadataManager.INSTANCE.commitTransaction(mdTxnCtx);
         } catch (Exception e) {
             abort(e, e, mdTxnCtx);
-            throw new AlgebricksException(e);
+            throw e;
         } finally {
             releaseWriteLatch();
         }
@@ -817,7 +812,7 @@
                 }
             }
 
-            throw new AlgebricksException(e);
+            throw e;
         } finally {
             releaseWriteLatch();
         }
@@ -922,7 +917,7 @@
                 }
             }
 
-            throw new AlgebricksException(e);
+            throw e;
         } finally {
             releaseWriteLatch();
         }
@@ -1027,7 +1022,7 @@
                 }
             }
 
-            throw new AlgebricksException(e);
+            throw e;
 
         } finally {
             releaseWriteLatch();
@@ -1054,7 +1049,7 @@
             MetadataManager.INSTANCE.commitTransaction(mdTxnCtx);
         } catch (Exception e) {
             abort(e, e, mdTxnCtx);
-            throw new AlgebricksException(e);
+            throw e;
         } finally {
             releaseWriteLatch();
         }
@@ -1080,7 +1075,7 @@
             MetadataManager.INSTANCE.commitTransaction(mdTxnCtx);
         } catch (Exception e) {
             abort(e, e, mdTxnCtx);
-            throw new AlgebricksException(e);
+            throw e;
         } finally {
             releaseWriteLatch();
         }
@@ -1106,7 +1101,7 @@
             MetadataManager.INSTANCE.commitTransaction(mdTxnCtx);
         } catch (Exception e) {
             abort(e, e, mdTxnCtx);
-            throw new AlgebricksException(e);
+            throw e;
         } finally {
             releaseWriteLatch();
         }
@@ -1130,7 +1125,7 @@
             MetadataManager.INSTANCE.commitTransaction(mdTxnCtx);
         } catch (Exception e) {
             abort(e, e, mdTxnCtx);
-            throw new AlgebricksException(e);
+            throw e;
         } finally {
             releaseWriteLatch();
         }
@@ -1178,7 +1173,7 @@
                 abort(e, e, mdTxnCtx);
             }
 
-            throw new AlgebricksException(e);
+            throw e;
         } finally {
             releaseReadLatch();
         }
@@ -1208,7 +1203,7 @@
             if (bActiveTxn) {
                 abort(e, e, mdTxnCtx);
             }
-            throw new AlgebricksException(e);
+            throw e;
         } finally {
             releaseReadLatch();
         }
@@ -1241,7 +1236,7 @@
             if (bActiveTxn) {
                 abort(e, e, mdTxnCtx);
             }
-            throw new AlgebricksException(e);
+            throw e;
         } finally {
             releaseReadLatch();
         }
@@ -1275,7 +1270,7 @@
             if (bActiveTxn) {
                 abort(e, e, mdTxnCtx);
             }
-            throw new AlgebricksException(e);
+            throw e;
         } finally {
             releaseReadLatch();
         }
@@ -1341,7 +1336,7 @@
             if (bActiveTxn) {
                 abort(e, e, mdTxnCtx);
             }
-            throw new AlgebricksException(e);
+            throw e;
         } finally {
             releaseReadLatch();
         }
@@ -1370,7 +1365,7 @@
             if (bActiveTxn) {
                 abort(e, e, mdTxnCtx);
             }
-            throw new AlgebricksException(e);
+            throw e;
         } finally {
             releaseReadLatch();
         }
@@ -1401,29 +1396,38 @@
                     handle.put(jobId.getId());
                     handle.put(metadataProvider.getResultSetId().getId());
                     response.put("handle", handle);
+                    out.print(response);
+                    out.flush();
                 } else {
+                    if (pdf == DisplayFormat.HTML) {
+                        out.println("<h4>Results:</h4>");
+                        out.println("<pre>");
+                    }
+
                     ByteBuffer buffer = ByteBuffer.allocate(ResultReader.FRAME_SIZE);
                     ResultReader resultReader = new ResultReader(hcc, hdc);
                     resultReader.open(jobId, metadataProvider.getResultSetId());
                     buffer.clear();
-                    JSONArray results = new JSONArray();
+
                     while (resultReader.read(buffer) > 0) {
-                        results.put(ResultUtils.getJSONFromBuffer(buffer, resultReader.getFrameTupleAccessor()));
+                        response.put("results",
+                                ResultUtils.getJSONFromBuffer(buffer, resultReader.getFrameTupleAccessor()));
                         buffer.clear();
+                        switch (pdf) {
+                            case HTML:
+                                ResultUtils.prettyPrintHTML(out, response);
+                                break;
+                            case TEXT:
+                            case JSON:
+                                out.print(response);
+                                break;
+                        }
+                        out.flush();
                     }
-                    response.put("results", results);
-                }
-                switch (pdf) {
-                    case HTML:
-                        out.println("<h4>Results:</h4>");
-                        out.println("<pre>");
-                        ResultUtils.prettyPrintHTML(out, response);
+                    if (pdf == DisplayFormat.HTML) {
                         out.println("</pre>");
-                        break;
-                    case TEXT:
-                    case JSON:
-                        out.print(response);
-                        break;
+                    }
+
                 }
                 hcc.waitForCompletion(jobId);
             }
@@ -1434,7 +1438,7 @@
             if (bActiveTxn) {
                 abort(e, e, mdTxnCtx);
             }
-            throw new AlgebricksException(e);
+            throw e;
         } finally {
             releaseReadLatch();
         }
@@ -1464,7 +1468,7 @@
             MetadataManager.INSTANCE.commitTransaction(mdTxnCtx);
         } catch (Exception e) {
             abort(e, e, mdTxnCtx);
-            throw new AlgebricksException(e);
+            throw e;
         } finally {
             releaseWriteLatch();
         }
@@ -1503,8 +1507,7 @@
         return format;
     }
 
-    private String getActiveDataverseName(String dataverse)
-            throws AlgebricksException {
+    private String getActiveDataverseName(String dataverse) throws AlgebricksException {
         if (dataverse != null) {
             return dataverse;
         }
@@ -1513,13 +1516,11 @@
         }
         throw new AlgebricksException("dataverse not specified");
     }
-    
-    private String getActiveDataverseName(Identifier dataverse)
-            throws AlgebricksException {
-        return getActiveDataverseName(
-                dataverse != null ? dataverse.getValue() : null);
+
+    private String getActiveDataverseName(Identifier dataverse) throws AlgebricksException {
+        return getActiveDataverseName(dataverse != null ? dataverse.getValue() : null);
     }
-    
+
     private void acquireWriteLatch() {
         MetadataManager.INSTANCE.acquireWriteLatch();
     }
diff --git a/asterix-app/src/main/java/edu/uci/ics/asterix/result/ResultUtils.java b/asterix-app/src/main/java/edu/uci/ics/asterix/result/ResultUtils.java
index 02cf6a4..44a54e0 100644
--- a/asterix-app/src/main/java/edu/uci/ics/asterix/result/ResultUtils.java
+++ b/asterix-app/src/main/java/edu/uci/ics/asterix/result/ResultUtils.java
@@ -14,14 +14,22 @@
  */
 package edu.uci.ics.asterix.result;
 
+import java.io.BufferedReader;
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.nio.ByteBuffer;
 
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
 
+import com.sun.el.parser.ParseException;
+
+import edu.uci.ics.asterix.api.http.servlet.APIServlet;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
 import edu.uci.ics.hyracks.api.comm.IFrameTupleAccessor;
 import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
 import edu.uci.ics.hyracks.dataflow.common.comm.util.ByteBufferInputStream;
@@ -51,13 +59,18 @@
         return resultRecords;
     }
 
-    public static JSONObject getErrorResponse(int errorCode, String errorMessage) {
+    public static JSONObject getErrorResponse(int errorCode, String errorMessage, String errorSummary,
+            String errorStackTrace) {
         JSONObject errorResp = new JSONObject();
         JSONArray errorArray = new JSONArray();
         errorArray.put(errorCode);
         errorArray.put(errorMessage);
         try {
             errorResp.put("error-code", errorArray);
+            if (!errorSummary.equals(""))
+                errorResp.put("summary", errorSummary);
+            if (!errorStackTrace.equals(""))
+                errorResp.put("stacktrace", errorStackTrace);
         } catch (JSONException e) {
             // TODO(madhusudancs): Figure out what to do when JSONException occurs while building the results.
         }
@@ -65,30 +78,116 @@
     }
 
     public static void prettyPrintHTML(PrintWriter out, JSONObject jsonResultObj) {
-        JSONArray resultsWrapper;
-        JSONArray resultsArray;
         try {
-            resultsWrapper = jsonResultObj.getJSONArray("results");
-            for (int i = 0; i < resultsWrapper.length(); i++) {
-                resultsArray = resultsWrapper.getJSONArray(i);
-                for (int j = 0; j < resultsArray.length(); j++) {
-                    out.print(resultsArray.getString(j));
-                }
+            JSONArray resultsArray = jsonResultObj.getJSONArray("results");
+            for (int i = 0; i < resultsArray.length(); i++) {
+                out.print(resultsArray.getString(i));
             }
         } catch (JSONException e) {
             // TODO(madhusudancs): Figure out what to do when JSONException occurs while building the results.
         }
     }
 
+    public static void webUIErrorHandler(PrintWriter out, Exception e) {
+        String errorTemplate = "%s\n%s\n%s";
+        try {
+            String resourcePath = "/webui/errortemplate.html";
+            InputStream is = APIServlet.class.getResourceAsStream(resourcePath);
+            InputStreamReader isr = new InputStreamReader(is);
+            StringBuilder sb = new StringBuilder();
+            BufferedReader br = new BufferedReader(isr);
+            String line = br.readLine();
+
+            while (line != null) {
+                sb.append(line);
+                line = br.readLine();
+            }
+            errorTemplate = sb.toString();
+        } catch (IOException ioe) {
+            // If there is an IOException reading the error template html file, default value of error template is used.
+        }
+
+        String errorOutput = String.format(errorTemplate, extractErrorMessage(e), extractErrorSummary(e),
+                extractFullStackTrace(e));
+        out.println(errorOutput);
+    }
+
+    public static void apiErrorHandler(PrintWriter out, Exception e) {
+        int errorCode = 99;
+        if (e instanceof ParseException) {
+            errorCode = 2;
+        } else if (e instanceof AlgebricksException) {
+            errorCode = 3;
+        } else if (e instanceof HyracksDataException) {
+            errorCode = 4;
+        }
+
+        JSONObject errorResp = ResultUtils.getErrorResponse(errorCode, extractErrorMessage(e), extractErrorSummary(e),
+                extractFullStackTrace(e));
+        out.write(errorResp.toString());
+    }
+
+    public static String buildParseExceptionMessage(Throwable e, String query) {
+        StringBuilder errorMessage = new StringBuilder();
+        String message = e.getMessage();
+        message = message.replace("<", "&lt");
+        message = message.replace(">", "&gt");
+        errorMessage.append("SyntaxError:" + message + "\n");
+        int pos = message.indexOf("line");
+        if (pos > 0) {
+            int columnPos = message.indexOf(",", pos + 1 + "line".length());
+            int lineNo = Integer.parseInt(message.substring(pos + "line".length() + 1, columnPos));
+            String[] lines = query.split("\n");
+            if (lineNo >= lines.length) {
+                errorMessage.append("===> &ltBLANK LINE&gt \n");
+            } else {
+                String line = lines[lineNo - 1];
+                errorMessage.append("==> " + line);
+            }
+        }
+        return errorMessage.toString();
+    }
+
+    private static Throwable getRootCause(Throwable cause) {
+        Throwable nextCause = cause.getCause();
+        while (nextCause != null) {
+            cause = nextCause;
+            nextCause = cause.getCause();
+        }
+        return cause;
+    }
+
     /**
-     * extract meaningful part of a stack trace:
+     * Extract the message in the root cause of the stack trace:
+     * 
+     * @param e
+     * @return error message string.
+     */
+    private static String extractErrorMessage(Throwable e) {
+        Throwable cause = getRootCause(e);
+
+        String exceptionClassName = "";
+        String[] messageSplits = cause.toString().split(":");
+        if (messageSplits.length > 1) {
+            String fullyQualifiedExceptionClassName = messageSplits[0];
+            System.out.println(fullyQualifiedExceptionClassName);
+            String[] hierarchySplits = fullyQualifiedExceptionClassName.split("\\.");
+            if (hierarchySplits.length > 0) {
+                exceptionClassName = hierarchySplits[hierarchySplits.length - 1];
+            }
+        }
+        return cause.getLocalizedMessage() + " [" + exceptionClassName + "]";
+    }
+
+    /**
+     * Extract the meaningful part of a stack trace:
      * a. the causes in the stack trace hierarchy
      * b. the top exception for each cause
      * 
      * @param e
      * @return the contacted message containing a and b.
      */
-    public static String extractErrorMessage(Throwable e) {
+    private static String extractErrorSummary(Throwable e) {
         StringBuilder errorMessageBuilder = new StringBuilder();
         Throwable cause = e;
         errorMessageBuilder.append(cause.getLocalizedMessage());
@@ -99,4 +198,17 @@
         }
         return errorMessageBuilder.toString();
     }
+
+    /**
+     * Extract the full stack trace:
+     * 
+     * @param e
+     * @return the string containing the full stack trace of the error.
+     */
+    private static String extractFullStackTrace(Throwable e) {
+        StringWriter stringWriter = new StringWriter();
+        PrintWriter printWriter = new PrintWriter(stringWriter);
+        e.printStackTrace(printWriter);
+        return stringWriter.toString();
+    }
 }
diff --git a/asterix-app/src/main/resources/webui/errortemplate.html b/asterix-app/src/main/resources/webui/errortemplate.html
new file mode 100644
index 0000000..8c39e03
--- /dev/null
+++ b/asterix-app/src/main/resources/webui/errortemplate.html
@@ -0,0 +1,38 @@
+<div class="accordion" id="errorblock">
+  <div class="accordion-group">
+    <div class="accordion-heading">
+      <a class="accordion-toggle" data-toggle="collapse" data-parent="#errorblock" href="#levelOne">
+        Message
+      </a>
+    </div>
+    <div id="levelOne" class="accordion-body collapse in">
+      <div class="accordion-inner">
+        <pre class="error">%s</pre>
+      </div>
+    </div>
+  </div>
+  <div class="accordion-group">
+    <div class="accordion-heading">
+      <a class="accordion-toggle" data-toggle="collapse" data-parent="#errorblock" href="#levelTwo">
+        Summary
+      </a>
+    </div>
+    <div id="levelTwo" class="accordion-body collapse">
+      <div class="accordion-inner">
+        <pre class="error">%s</pre>
+      </div>
+    </div>
+  </div>
+  <div class="accordion-group">
+    <div class="accordion-heading">
+      <a class="accordion-toggle" data-toggle="collapse" data-parent="#errorblock" href="#levelThree">
+        Full Stack Trace
+      </a>
+    </div>
+    <div id="levelThree" class="accordion-body collapse">
+      <div class="accordion-inner">
+        <pre class="error">%s</pre>
+      </div>
+    </div>
+  </div>
+</div>
diff --git a/asterix-app/src/main/resources/webui/querytemplate.html b/asterix-app/src/main/resources/webui/querytemplate.html
index 9021e0b..40ce161 100644
--- a/asterix-app/src/main/resources/webui/querytemplate.html
+++ b/asterix-app/src/main/resources/webui/querytemplate.html
@@ -54,11 +54,16 @@
             var resSet = 0;
             var resPattern = /<h4>Results:<\/h4>/g;
             var durPattern = /<PRE>Duration/g;
+            var errorPattern = /<div class="accordion" id="errorblock">/g;
             var resultCount = data.match(resPattern);
 
-            if (!resPattern.test(data)) {
+            if (!resPattern.test(data) && errorPattern.test(data)) {
+                $('#output-heading').html('Error');
+                $('#output-heading').addClass('error');
                 $('#output-message').html(data);
-            } else { 
+            } else {
+                $('#output-heading').html('Output');
+                $('#output-heading').removeClass('error');
                 if (resultCount.length <= 1) {
                     $('#output-message').html(data);
                 } else {
@@ -66,7 +71,7 @@
                     var results = splitData[0].split('<h4>');
                     var components = results.slice(1, results.length);
                     var sections = components.length / resultCount.length;
-                    
+
                     for (resSet = 0; resSet < resultCount.length; resSet++) {
 
                         $('#output-message').append('<h4>' + components[(resSet+1)*sections - 1]);
@@ -80,12 +85,12 @@
                                 .css("margin-bottom", "1em")
                                 .html('Result Plan #' + resNum + '<i id="ibtn' + resSet + '" class="icon-plus extarget"></i>')
                                 .appendTo('#output-message');
-                        
+
                             $('<div/>')
                                 .attr("id", "collapse" + resSet)
                                 .attr("class", "collapse in")
                                 .appendTo('#output-message');
-                        
+
                             for (var c = 0; c < sections - 1; c++) {
                                 var pos = resSet*sections + c;
                                 $('#collapse' + resSet).append('<h4>' + components[pos]);
@@ -97,7 +102,7 @@
                             });
                             */
 
-			    $('#output-message').append("<hr/>");
+                            $('#output-message').append("<hr/>");
                         }
 
                     }
@@ -135,7 +140,7 @@
 
         <!-- Temporary logo placeholder -->
         <a class="brand" href="#"><img src="/webui/static/img/finalasterixlogo.png"></a>
-        
+
         <div class="nav-collapse collapse">
           <ul class="nav">
             <li><a href="http://code.google.com/p/asterixdb/" target="_blank">
@@ -182,7 +187,7 @@
 
        <div class="span6">
          <div class="output">
-           <label class="heading">Output</label>
+           <label id="output-heading" class="heading">Output</label>
            <div id="output-message" class="message">
            </div>
          </div>
diff --git a/asterix-app/src/main/resources/webui/static/css/style.css b/asterix-app/src/main/resources/webui/static/css/style.css
index 906181b..a3e411c 100644
--- a/asterix-app/src/main/resources/webui/static/css/style.css
+++ b/asterix-app/src/main/resources/webui/static/css/style.css
@@ -87,6 +87,10 @@
     color : #17265a;
 }
 
+div.output label.heading.error {
+    color: #E03809; 
+}
+
 div.output h4 {
     color : #17265a;
 }
@@ -95,6 +99,14 @@
     color : #17265a;
 }
 
+.accordion-inner {
+    padding : 0 0 0 0;
+}
+
+#errorblock .accordion-group .accordion-heading a.accordion-toggle {
+    color: #E03809;
+}
+
 div.output .message {
     -webkit-box-sizing: border-box;
     -moz-box-sizing: border-box;
@@ -105,22 +117,7 @@
 }
 
 div.output .message pre.error {
-    -webkit-box-sizing: border-box;
-    -moz-box-sizing: border-box;
-    -ms-box-sizing: border-box;
-    box-sizing: border-box;
-    border-color: rgba(82, 168, 236, 0.8);
-    outline: 0;
-    outline: thin dotted 9;
-
-    -webkit-box-shadow: inset 0 1px 1px rgba(250, 0, 0, 0.075), 0 0 8px rgba(255, 0, 0, 0.8);
-    -moz-box-shadow: inset 0 1px 1px rgba(250, 0, 0, 0.075), 0 0 8px rgba(255, 0, 0, 1.0);
-    box-shadow: inset 0 1px 1px rgba(250, 0, 0, 0.075), 0 0 8px rgba(255, 0, 0, 1.0);
-    color: #000;
-    resize: none;
-    border: 1px solid #eee;
-    margin-top: 7px;
-    padding: 20px 20px 20px 20px;
+   border: 0;
 }
 
 .footer {
diff --git a/asterix-maven-plugins/lexer-generator-maven-plugin/pom.xml b/asterix-maven-plugins/lexer-generator-maven-plugin/pom.xml
index 6b444e8..6be403e 100644
--- a/asterix-maven-plugins/lexer-generator-maven-plugin/pom.xml
+++ b/asterix-maven-plugins/lexer-generator-maven-plugin/pom.xml
@@ -18,8 +18,8 @@
         <artifactId>maven-compiler-plugin</artifactId>
         <version>2.0.2</version>
         <configuration>
-          <source>1.6</source>
-          <target>1.6</target>
+          <source>1.7</source>
+          <target>1.7</target>
 	  <fork>true</fork>
         </configuration>
       </plugin>