/* * Copyright 2012-2015 Aerospike, Inc. * * Portions may be licensed to Aerospike, Inc. under one or more contributor * license agreements. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.aerospike.aql.plugin.builder; import java.io.File; import java.io.IOException; import java.util.List; import java.util.Map; import java.util.regex.Pattern; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.IResourceDeltaVisitor; import org.eclipse.core.resources.IResourceVisitor; import org.eclipse.core.resources.IncrementalProjectBuilder; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Status; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.ui.editors.text.FileDocumentProvider; import org.eclipse.ui.editors.text.TextFileDocumentProvider; import org.eclipse.ui.texteditor.IDocumentProvider; import org.xml.sax.helpers.DefaultHandler; import com.aerospike.aql.AQL; import com.aerospike.aql.grammar.IErrorReporter; import com.aerospike.aql.plugin.editors.AQLDocumentProvider; import com.aerospike.client.AerospikeException; import com.aerospike.core.CoreActivator; import com.aerospike.core.views.ResultsConsoleView; public class AQLBuilder extends IncrementalProjectBuilder { Pattern errorPattern = Pattern.compile("line $d+:$d+"); FileDocumentProvider documentProvider = new AQLDocumentProvider(); public static final String ID = "com.aerospike.aql.plugin.builder.AQLBuilder"; private static final String MARKER_TYPE = "AerospikeAQL.aqlProblem"; class AQLDeltaVisitor implements IResourceDeltaVisitor { /* * (non-Javadoc) * * @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta) */ public boolean visit(IResourceDelta delta) throws CoreException { IResource resource = delta.getResource(); switch (delta.getKind()) { case IResourceDelta.ADDED: // handle added resource checkAQL(resource, false); break; case IResourceDelta.REMOVED: // handle removed resource checkAQL(resource, true); break; case IResourceDelta.CHANGED: // handle changed resource checkAQL(resource, false); break; } //return true to continue visiting children. return true; } } class AQLResourceVisitor implements IResourceVisitor { public boolean visit(IResource resource) { checkAQL(resource, false); //return true to continue visiting children. return true; } } class AQLErrorHandler extends DefaultHandler implements IErrorReporter{ private IFile file; private IDocument document; private IDocumentProvider provider = new TextFileDocumentProvider(); private int errors = 0; public AQLErrorHandler(IFile file) { this.file = file; try { this.provider.connect(file); } catch (CoreException e) { CoreActivator.log(Status.ERROR, "Error connecting to " + file.getName(), e); } this.document = provider.getDocument(file); } private void addMarker(IFile file, String error, int line, int charStart, int charEnd, int severity) throws BadLocationException { try { IMarker marker = file.createMarker(MARKER_TYPE); int offset = document.getLineOffset(line - 1); marker.setAttribute(IMarker.CHAR_START, charStart + offset); marker.setAttribute(IMarker.CHAR_END, charEnd + offset); marker.setAttribute(IMarker.LINE_NUMBER, line); marker.setAttribute(IMarker.MESSAGE, error); marker.setAttribute(IMarker.SEVERITY, severity); } catch (CoreException e) { } } @Override public void reportError(int line, int charStart, int charEnd, String message) { try { addMarker(this.file, message, line, charStart, charEnd, IMarker.SEVERITY_ERROR); errors++; } catch (BadLocationException e) { CoreActivator.log(Status.ERROR, "Error adding marker to " + file.getName(), e); } } @Override public int getErrorCount() { return errors; } @Override public List<String> getErrorList() { // TODO Auto-generated method stub return null; } @Override public void reportError(int line, String message) { try { addMarker(this.file, message, line, 0, 0, IMarker.SEVERITY_ERROR); errors++; } catch (BadLocationException e) { CoreActivator.log(Status.ERROR, "Error adding marker to " + file.getName(), e); } } @Override public void reportError(int arg0, AerospikeException arg1) { // TODO Auto-generated method stub } } /* * (non-Javadoc) * * @see org.eclipse.core.internal.events.InternalBuilder#build(int, * java.util.Map, org.eclipse.core.runtime.IProgressMonitor) */ protected IProject[] build(int kind, Map args, IProgressMonitor monitor) throws CoreException { if (kind == FULL_BUILD) { fullBuild(monitor); } else { IResourceDelta delta = getDelta(getProject()); if (delta == null) { fullBuild(monitor); } else { incrementalBuild(delta, monitor); } } return null; } protected void clean(IProgressMonitor monitor) throws CoreException { // delete markers set and files created getProject().deleteMarkers(MARKER_TYPE, true, IResource.DEPTH_INFINITE); } void checkAQL(IResource resource, boolean remove) { if (resource instanceof IFile && resource.getName().endsWith(".aql")) { IFile file = (IFile) resource; deleteMarkers(file); AQLErrorHandler reporter = new AQLErrorHandler(file); try { processAQL(file, reporter, remove); } catch (Exception e1) { e1.printStackTrace(); } } } private void processAQL(IFile sqlFile, AQLErrorHandler reporter, boolean remove) { int errors = 0; try { //AQLErrorHandler errorHandler = new AQLErrorHandler(sqlFile); //final ResultsConsoleView results = new ResultsConsoleView(); // find the Aerospike console and display it // IWorkbench wb = PlatformUI.getWorkbench(); // IWorkbenchWindow win = wb.getActiveWorkbenchWindow(); // IWorkbenchPage page = win.getActivePage(); // IConsoleView view = (IConsoleView) page.showView(IConsoleConstants.ID_CONSOLE_VIEW); // view.display(results.getConsole()); AQL aql = new AQL(); File sourceFile = new File(sqlFile.getRawLocation().toOSString()); aql.setErrorReporter(reporter); aql.compile(sourceFile); } catch (NumberFormatException e) { CoreActivator.showError(e, "Could not process AQL file: " + sqlFile.getName()); } catch (IOException e) { CoreActivator.showError(e, "Could not process AQL file: " + sqlFile.getName()); } } private void deleteMarkers(IFile file) { try { file.deleteMarkers(MARKER_TYPE, false, IResource.DEPTH_ZERO); } catch (CoreException ce) { } } protected void fullBuild(final IProgressMonitor monitor) throws CoreException { try { getProject().accept(new AQLResourceVisitor()); } catch (CoreException e) { } } protected void incrementalBuild(IResourceDelta delta, IProgressMonitor monitor) throws CoreException { // the visitor does the work. delta.accept(new AQLDeltaVisitor()); } }