Package org.drools.eclipse.builder

Source Code of org.drools.eclipse.builder.DroolsBuilder$DroolsBuildDeltaVisitor

/*
* Copyright 2010 JBoss Inc
*
* 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 org.drools.eclipse.builder;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.antlr.runtime.RecognitionException;
import org.drools.commons.jci.problems.CompilationProblem;
import org.drools.compiler.DescrBuildError;
import org.drools.compiler.DroolsError;
import org.drools.compiler.DroolsParserException;
import org.drools.compiler.FactTemplateError;
import org.drools.compiler.FieldTemplateError;
import org.drools.compiler.FunctionError;
import org.drools.compiler.GlobalError;
import org.drools.compiler.ImportError;
import org.drools.compiler.ParserError;
import org.drools.compiler.RuleBuildError;
import org.drools.decisiontable.InputType;
import org.drools.decisiontable.SpreadsheetCompiler;
import org.drools.eclipse.DRLInfo;
import org.drools.eclipse.DroolsEclipsePlugin;
import org.drools.eclipse.ProcessInfo;
import org.drools.eclipse.preferences.IDroolsConstants;
import org.drools.eclipse.util.DroolsRuntimeManager;
import org.drools.eclipse.wizard.project.NewDroolsProjectWizard;
import org.drools.ide.common.client.modeldriven.brl.RuleModel;
import org.drools.ide.common.client.modeldriven.dt.TypeSafeGuidedDecisionTable;
import org.drools.ide.common.server.util.BRDRLPersistence;
import org.drools.ide.common.server.util.BRXMLPersistence;
import org.drools.ide.common.server.util.GuidedDTDRLPersistence;
import org.drools.ide.common.server.util.GuidedDTXMLPersistence;
import org.drools.lang.ExpanderException;
import org.drools.template.parser.DecisionTableParseException;
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.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;

/**
* Automatically syntax checks .drl files and adds possible
* errors or warnings to the problem list. Nominally is triggerd on save.
*/
public class DroolsBuilder extends IncrementalProjectBuilder {

    public static final String BUILDER_ID = "org.drools.eclipse.droolsbuilder";

    protected IProject[] build(int kind, Map args, IProgressMonitor monitor)
            throws CoreException {
        IProject currentProject = getProject();
        if (currentProject == null || !currentProject.isAccessible()) {
            return new IProject[0];
        }
        try {
            if (monitor != null && monitor.isCanceled())
                throw new OperationCanceledException();

            if (kind == IncrementalProjectBuilder.FULL_BUILD) {
                fullBuild(monitor);
            } else {
                IResourceDelta delta = getDelta(getProject());
                if (delta == null) {
                    fullBuild(monitor);
                } else {
                    incrementalBuild(delta, monitor);
                }
            }
        } catch (CoreException e) {
            IMarker marker = currentProject.createMarker(IDroolsModelMarker.DROOLS_MODEL_PROBLEM_MARKER);
            marker.setAttribute(IMarker.MESSAGE, "Error when trying to build Drools project: " + e.getLocalizedMessage());
            marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
        }
        return getRequiredProjects(currentProject);
    }
   
    protected void fullBuild(IProgressMonitor monitor)
            throws CoreException {
        removeProblemsFor(getProject());
        IJavaProject project = JavaCore.create(getProject());
        IClasspathEntry[] classpathEntries = project.getRawClasspath();
        for (int i = 0; i < classpathEntries.length; i++) {
            if (NewDroolsProjectWizard.DROOLS_CLASSPATH_CONTAINER_PATH.equals(classpathEntries[i].getPath().toString())) {
                String[] jars = DroolsRuntimeManager.getDroolsRuntimeJars(getProject());
                if (jars == null || jars.length == 0) {
                    String runtime = DroolsRuntimeManager.getDroolsRuntime(getProject());
                    IMarker marker = getProject().createMarker(IDroolsModelMarker.DROOLS_MODEL_PROBLEM_MARKER);
                    if (runtime == null) {
                        marker.setAttribute(IMarker.MESSAGE, "Could not find default Drools runtime");
                    } else {
                        marker.setAttribute(IMarker.MESSAGE, "Could not find Drools runtime " + runtime);
                    }
                    marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
                    return;
                }
            }
        }
        getProject().accept(new DroolsBuildVisitor());
    }
   
    protected void incrementalBuild(IResourceDelta delta,
            IProgressMonitor monitor) throws CoreException {
        boolean buildAll = DroolsEclipsePlugin.getDefault().getPreferenceStore().getBoolean(IDroolsConstants.BUILD_ALL);
        if (buildAll) {
            // to make sure that all rules are checked when a java file is changed
            fullBuild(monitor);
        } else {
            delta.accept(new DroolsBuildDeltaVisitor());
        }
    }

    private class DroolsBuildVisitor implements IResourceVisitor {
        public boolean visit(IResource res) {
            return parseResource(res, true);
        }
    }

    private class DroolsBuildDeltaVisitor implements IResourceDeltaVisitor {
        public boolean visit(IResourceDelta delta) throws CoreException {
            return parseResource(delta.getResource(), false);
        }
    }
   
    protected boolean parseResource(IResource res, boolean clean) {
        try {
            // exclude .guvnorinfo files
            if (".guvnorinfo".equals(res.getName())) {
                return false;
            }
            IJavaProject project = JavaCore.create(res.getProject());
            // exclude files that are located in the output directory,
            // unless the ouput directory is the same as the project location
            if (!project.getOutputLocation().equals(project.getPath())
                    && project.getOutputLocation().isPrefixOf(res.getFullPath())) {
                return false;
            }
        } catch (JavaModelException e) {
            // do nothing
        }
       
        if (!res.exists()) {
            removeProblemsFor(res);
            DroolsEclipsePlugin.getDefault().invalidateResource(res);
            return false;
        }

        if (res instanceof IFile
                && ("drl".equals(res.getFileExtension())
                    || "dslr".equals(res.getFileExtension())
                    || ".package".equals(res.getName()))) {
            removeProblemsFor(res);
            try {
                if (clean) {
                    DroolsEclipsePlugin.getDefault().invalidateResource(res);
                }
                DroolsBuildMarker[] markers = parseDRLFile((IFile) res, new String(Util.getResourceContentsAsCharArray((IFile) res)));
                for (int i = 0; i < markers.length; i++) {
                    createMarker(res, markers[i].getText(), markers[i].getLine());
                }
            } catch (Throwable t) {
                DroolsEclipsePlugin.log(t);
                createMarker(res, t.getMessage(), -1);
            }
            return false;
        } else if (res instanceof IFile && "xls".equals(res.getFileExtension())) {
            removeProblemsFor(res);
            try {
                if (clean) {
                    DroolsEclipsePlugin.getDefault().invalidateResource(res);
                }
                DroolsBuildMarker[] markers = parseXLSFile((IFile) res);
                for (int i = 0; i < markers.length; i++) {
                    createMarker(res, markers[i].getText(), markers[i].getLine());
                }
            } catch (Throwable t) {
                createMarker(res, t.getMessage(), -1);
            }
            return false;
        } else if (res instanceof IFile && "csv".equals(res.getFileExtension())) {
            removeProblemsFor(res);
            try {
                if (clean) {
                    DroolsEclipsePlugin.getDefault().invalidateResource(res);
                }
                DroolsBuildMarker[] markers = parseCSVFile((IFile) res);
                for (int i = 0; i < markers.length; i++) {
                    createMarker(res, markers[i].getText(), markers[i].getLine());
                }
            } catch (Throwable t) {
                createMarker(res, t.getMessage(), -1);
            }
            return false;
        } else if (res instanceof IFile && "brl".equals(res.getFileExtension())) {
            removeProblemsFor(res);
            try {
                if (clean) {
                    DroolsEclipsePlugin.getDefault().invalidateResource(res);
                }
                DroolsBuildMarker[] markers = parseBRLFile((IFile) res);
                for (int i = 0; i < markers.length; i++) {
                    createMarker(res, markers[i].getText(), markers[i].getLine());
                }
            } catch (Throwable t) {
                createMarker(res, t.getMessage(), -1);
            }
            return false;
        } else if (res instanceof IFile && "rf".equals(res.getFileExtension())) {
            removeProblemsFor(res);
            try {
                if (clean) {
                    DroolsEclipsePlugin.getDefault().invalidateResource(res);
                }
                DroolsBuildMarker[] markers = parseRuleFlowFile((IFile) res);
                for (int i = 0; i < markers.length; i++) {
                    createMarker(res, markers[i].getText(), markers[i].getLine());
                }
            } catch (Throwable t) {
                createMarker(res, t.getMessage(), -1);
            }
            return false;
        } else if (res instanceof IFile && ("bpmn".equals(res.getFileExtension())
                || "bpmn2".equals(res.getFileExtension()))) {
            removeProblemsFor(res);
            try {
                if (clean) {
                    DroolsEclipsePlugin.getDefault().invalidateResource(res);
                }
                DroolsBuildMarker[] markers = parseRuleFlowFile((IFile) res);
                for (int i = 0; i < markers.length; i++) {
                    createMarker(res, markers[i].getText(), markers[i].getLine());
                }
            } catch (Throwable t) {
                createMarker(res, t.getMessage(), -1);
            }
            return false;
        }

        return true;
    }
   
    private DroolsBuildMarker[] parseDRLFile(IFile file, String content) {
        List markers = new ArrayList();
        try {
            DRLInfo drlInfo =
                DroolsEclipsePlugin.getDefault().parseResource(file, true);
            //parser errors
            markParseErrors(markers, drlInfo.getParserErrors());
            markOtherErrors(markers, drlInfo.getBuilderErrors());
        } catch (DroolsParserException e) {
            // we have an error thrown from DrlParser
            Throwable cause = e.getCause();
            if (cause instanceof RecognitionException ) {
                RecognitionException recogErr = (RecognitionException) cause;
                markers.add(new DroolsBuildMarker(recogErr.getMessage(), recogErr.line)); //flick back the line number
            }
        } catch (Exception t) {
            String message = t.getMessage();
            if (message == null || message.trim().equals("")) {
                message = "Error: " + t.getClass().getName();
            }
            markers.add(new DroolsBuildMarker(message));
        }
        return (DroolsBuildMarker[]) markers.toArray(new DroolsBuildMarker[markers.size()]);
    }

    private DroolsBuildMarker[] parseXLSFile(IFile file) {
        List markers = new ArrayList();
        try {
            SpreadsheetCompiler converter = new SpreadsheetCompiler();
            String drl = converter.compile(file.getContents(), InputType.XLS);
            DRLInfo drlInfo =
                DroolsEclipsePlugin.getDefault().parseXLSResource(drl, file);
            // parser errors
            markParseErrors(markers, drlInfo.getParserErrors());
            markOtherErrors(markers, drlInfo.getBuilderErrors());
        } catch (DroolsParserException e) {
            // we have an error thrown from DrlParser
            Throwable cause = e.getCause();
            if (cause instanceof RecognitionException ) {
                RecognitionException recogErr = (RecognitionException) cause;
                markers.add(new DroolsBuildMarker(recogErr.getMessage(), recogErr.line)); //flick back the line number
            }
        } catch (DecisionTableParseException e) {
            if (!"No RuleTable's were found in spreadsheet.".equals(e.getMessage())) {
                throw e;
            }
        } catch (Exception t) {
            String message = t.getMessage();
            if (message == null || message.trim().equals( "" )) {
                message = "Error: " + t.getClass().getName();
            }
            markers.add(new DroolsBuildMarker(message));
        }
        return (DroolsBuildMarker[]) markers.toArray(new DroolsBuildMarker[markers.size()]);
    }

    private DroolsBuildMarker[] parseCSVFile(IFile file) {
        List markers = new ArrayList();
        try {
            SpreadsheetCompiler converter = new SpreadsheetCompiler();
            String drl = converter.compile(file.getContents(), InputType.CSV);
            DRLInfo drlInfo =
                DroolsEclipsePlugin.getDefault().parseXLSResource(drl, file);
            // parser errors
            markParseErrors(markers, drlInfo.getParserErrors());
            markOtherErrors(markers, drlInfo.getBuilderErrors());
        } catch (DroolsParserException e) {
            // we have an error thrown from DrlParser
            Throwable cause = e.getCause();
            if (cause instanceof RecognitionException ) {
                RecognitionException recogErr = (RecognitionException) cause;
                markers.add(new DroolsBuildMarker(recogErr.getMessage(), recogErr.line)); //flick back the line number
            }
        } catch (Exception t) {
            String message = t.getMessage();
            if (message == null || message.trim().equals( "" )) {
                message = "Error: " + t.getClass().getName();
            }
            markers.add(new DroolsBuildMarker(message));
        }
        return (DroolsBuildMarker[]) markers.toArray(new DroolsBuildMarker[markers.size()]);
    }

    private DroolsBuildMarker[] parseBRLFile(IFile file) {
        List markers = new ArrayList();
        try {
            String brl = convertToString(file.getContents());
            RuleModel model = BRXMLPersistence.getInstance().unmarshal(brl);
            String drl = BRDRLPersistence.getInstance().marshal(model);

            // TODO pass this through DSL converter in case brl is based on dsl

            DRLInfo drlInfo =
                DroolsEclipsePlugin.getDefault().parseBRLResource(drl, file);
            // parser errors
            markParseErrors(markers, drlInfo.getParserErrors());
            markOtherErrors(markers, drlInfo.getBuilderErrors());
        } catch (DroolsParserException e) {
            // we have an error thrown from DrlParser
            Throwable cause = e.getCause();
            if (cause instanceof RecognitionException ) {
                RecognitionException recogErr = (RecognitionException) cause;
                markers.add(new DroolsBuildMarker(recogErr.getMessage(), recogErr.line)); //flick back the line number
            }
        } catch (Exception t) {
            String message = t.getMessage();
            if (message == null || message.trim().equals( "" )) {
                message = "Error: " + t.getClass().getName();
            }
            markers.add(new DroolsBuildMarker(message));
        }
        return (DroolsBuildMarker[]) markers.toArray(new DroolsBuildMarker[markers.size()]);
    }
   
    private DroolsBuildMarker[] parseGDSTFile(IFile file) {
        List markers = new ArrayList();
        try {
            String gdst = convertToString(file.getContents());
            TypeSafeGuidedDecisionTable dt = GuidedDTXMLPersistence.getInstance().unmarshal(gdst);
            String drl = GuidedDTDRLPersistence.getInstance().marshal(dt);

            // TODO pass this through DSL converter in case brl is based on dsl

            DRLInfo drlInfo =
                DroolsEclipsePlugin.getDefault().parseGDSTResource(drl, file);
            // parser errors
            markParseErrors(markers, drlInfo.getParserErrors());
            markOtherErrors(markers, drlInfo.getBuilderErrors());
        } catch (DroolsParserException e) {
            // we have an error thrown from DrlParser
            Throwable cause = e.getCause();
            if (cause instanceof RecognitionException ) {
                RecognitionException recogErr = (RecognitionException) cause;
                markers.add(new DroolsBuildMarker(recogErr.getMessage(), recogErr.line)); //flick back the line number
            }
        } catch (Exception t) {
            String message = t.getMessage();
            if (message == null || message.trim().equals( "" )) {
                message = "Error: " + t.getClass().getName();
            }
            markers.add(new DroolsBuildMarker(message));
        }
        return (DroolsBuildMarker[]) markers.toArray(new DroolsBuildMarker[markers.size()]);
    }
   
    protected DroolsBuildMarker[] parseRuleFlowFile(IFile file) {
        if (!file.exists()) {
            return new DroolsBuildMarker[0];
        }
        List markers = new ArrayList();
        try {
            String input = convertToString(file.getContents());
            ProcessInfo processInfo =
                DroolsEclipsePlugin.getDefault().parseProcess(input, file);
            if (processInfo != null) {
                markParseErrors(markers, processInfo.getErrors());
            }
        } catch (Exception t) {
            t.printStackTrace();
            String message = t.getMessage();
            if (message == null || message.trim().equals( "" )) {
                message = "Error: " + t.getClass().getName();
            }
            markers.add(new DroolsBuildMarker(message));
        }
        return (DroolsBuildMarker[]) markers.toArray(new DroolsBuildMarker[markers.size()]);
    }
   
    protected static String convertToString(final InputStream inputStream) throws IOException {
        Reader reader = new InputStreamReader(inputStream);
        final StringBuffer text = new StringBuffer();
        final char[] buf = new char[1024];
        int len = 0;
        while ((len = reader.read(buf)) >= 0) {
            text.append(buf, 0, len);
        }
        return text.toString();
    }

    /**
     * This will create markers for parse errors.
     * Parse errors mean that antlr has picked up some major typos in the input source.
     */
    protected void markParseErrors(List markers, List parserErrors) {
        for ( Iterator iter = parserErrors.iterator(); iter.hasNext(); ) {
            Object error = iter.next();
            if (error instanceof ParserError) {
                ParserError err = (ParserError) error;
                markers.add(new DroolsBuildMarker(err.getMessage(), err.getRow()));
            } else if (error instanceof ExpanderException) {
                ExpanderException exc = (ExpanderException) error;
                // TODO line mapping is incorrect
                markers.add(new DroolsBuildMarker(exc.getMessage(), -1));
            } else {
                markers.add(new DroolsBuildMarker(error.toString()));
            }
        }
    }

    /**
     * This will create markers for build errors that happen AFTER parsing.
     */
    private void markOtherErrors(List markers,
                                        DroolsError[] buildErrors) {
        // TODO are there warnings too?
        for (int i = 0; i < buildErrors.length; i++ ) {
            DroolsError error = buildErrors[i];
            if (error instanceof GlobalError) {
                GlobalError globalError = (GlobalError) error;
                markers.add(new DroolsBuildMarker("Global error: " + globalError.getGlobal(), -1));
            } else if (error instanceof RuleBuildError) {
                RuleBuildError ruleError = (RuleBuildError) error;
                // TODO try to retrieve line number (or even character start-end)
                // disabled for now because line number are those of the rule class,
                // not the rule file itself
                if (ruleError.getObject() instanceof CompilationProblem[]) {
                    CompilationProblem[] problems = (CompilationProblem[]) ruleError.getObject();
                    for (int j = 0; j < problems.length; j++) {
                        markers.add(new DroolsBuildMarker(problems[j].getMessage(), ruleError.getLine()));
                    }
                } else {
                    markers.add(new DroolsBuildMarker(ruleError.getRule().getName() + ":" + ruleError.getMessage(), ruleError.getLine()));
                }
            } else if (error instanceof ParserError) {
                ParserError parserError = (ParserError) error;
                // TODO try to retrieve character start-end
                markers.add(new DroolsBuildMarker(parserError.getMessage(), parserError.getRow()));
            } else if (error instanceof FunctionError) {
                FunctionError functionError = (FunctionError) error;
                // TODO add line to function error
                // TODO try to retrieve character start-end
                if (functionError.getObject() instanceof CompilationProblem[]) {
                    CompilationProblem[] problems = (CompilationProblem[]) functionError.getObject();
                    for (int j = 0; j < problems.length; j++) {
                        markers.add(new DroolsBuildMarker(problems[j].getMessage(), functionError.getErrorLines()[j]));
                    }
                } else {
                    markers.add(new DroolsBuildMarker(functionError.getFunctionDescr().getName() + ":" + functionError.getMessage(), -1));
                }
            } else if (error instanceof FieldTemplateError) {
                markers.add(new DroolsBuildMarker(error.getMessage(), ((FieldTemplateError) error).getLine()));
            } else if (error instanceof FactTemplateError) {
                markers.add(new DroolsBuildMarker(error.getMessage(), ((FactTemplateError) error).getLine()));
            } else if (error instanceof ImportError) {
                markers.add(new DroolsBuildMarker("ImportError: " + error.getMessage()));
            } else if (error instanceof DescrBuildError) {
                markers.add(new DroolsBuildMarker("BuildError: " + error.getMessage(), ((DescrBuildError) error).getLine()));
            } else {
                markers.add(new DroolsBuildMarker("Unknown DroolsError " + error.getClass() + ": " + error));
            }
        }
    }

    protected void createMarker(final IResource res, final String message, final int lineNumber) {
        try {
            IWorkspaceRunnable r= new IWorkspaceRunnable() {
                public void run(IProgressMonitor monitor) throws CoreException {
                    IMarker marker = res
                        .createMarker(IDroolsModelMarker.DROOLS_MODEL_PROBLEM_MARKER);
                    marker.setAttribute(IMarker.MESSAGE, message);
                    marker.setAttribute(IMarker.SEVERITY,
                            IMarker.SEVERITY_ERROR);
                    marker.setAttribute(IMarker.LINE_NUMBER, lineNumber);
                }
            };
            res.getWorkspace().run(r, null, IWorkspace.AVOID_UPDATE, null);
        } catch (CoreException e) {
            DroolsEclipsePlugin.log(e);
        }
    }
   
    protected void removeProblemsFor(IResource resource) {
        try {
            if (resource != null && resource.exists()) {
                resource.deleteMarkers(
                        IDroolsModelMarker.DROOLS_MODEL_PROBLEM_MARKER, false,
                        IResource.DEPTH_INFINITE);
            }
        } catch (CoreException e) {
            DroolsEclipsePlugin.log(e);
        }
    }
   
    private IProject[] getRequiredProjects(IProject project) {
        IJavaProject javaProject = JavaCore.create(project);
        List projects = new ArrayList();
        try {
            IClasspathEntry[] entries = javaProject.getResolvedClasspath(true);
            for (int i = 0, l = entries.length; i < l; i++) {
                IClasspathEntry entry = entries[i];
                if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
                    IProject p = project.getWorkspace().getRoot().getProject(entry.getPath().lastSegment()); // missing projects are considered too
                    if (p != null && !projects.contains(p)) {
                        projects.add(p);
                    }
                }
            }
        } catch(JavaModelException e) {
            return new IProject[0];
        }
        return (IProject[]) projects.toArray(new IProject[projects.size()]);
    }

}
TOP

Related Classes of org.drools.eclipse.builder.DroolsBuilder$DroolsBuildDeltaVisitor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.