Java tutorial
/* * 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; import java.io.Reader; import java.io.StringReader; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.MissingResourceException; import java.util.ResourceBundle; import org.drools.compiler.DrlParser; import org.drools.compiler.DroolsError; import org.drools.compiler.DroolsParserException; import org.drools.compiler.PackageBuilder; import org.drools.compiler.PackageBuilderConfiguration; import org.drools.compiler.PackageRegistry; import org.drools.core.util.StringUtils; import org.drools.eclipse.DRLInfo.FunctionInfo; import org.drools.eclipse.DRLInfo.RuleInfo; import org.drools.eclipse.builder.DroolsBuilder; import org.drools.eclipse.builder.Util; import org.drools.eclipse.dsl.editor.DSLAdapter; import org.drools.eclipse.editors.AbstractRuleEditor; import org.drools.eclipse.preferences.IDroolsConstants; import org.drools.eclipse.util.ProjectClassLoader; import org.drools.io.ResourceFactory; import org.drools.lang.descr.PackageDescr; import org.drools.rule.Package; import org.drools.rule.builder.dialect.java.JavaDialectConfiguration; import org.drools.xml.SemanticModules; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceVisitor; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.debug.core.DebugException; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.resource.ImageRegistry; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.forms.FormColors; import org.eclipse.ui.plugin.AbstractUIPlugin; import org.jbpm.bpmn2.xml.BPMNDISemanticModule; import org.jbpm.bpmn2.xml.BPMNSemanticModule; import org.jbpm.compiler.ProcessBuilderImpl; import org.jbpm.compiler.xml.ProcessSemanticModule; import org.jbpm.compiler.xml.XmlProcessReader; import org.jbpm.process.core.Process; import org.osgi.framework.BundleContext; /** * The main plugin class to be used in the desktop. */ public class DroolsEclipsePlugin extends AbstractUIPlugin { public static final int INTERNAL_ERROR = 120; public static final String PLUGIN_ID = "org.drools.eclipse"; public static final String BUILD_RESULT_PACKAGE = "Package"; public static final String BUILD_RESULT_PACKAGE_DESCR = "PackageDescr"; //The shared instance. private static DroolsEclipsePlugin plugin; //Resource bundle. private ResourceBundle resourceBundle; private Map<String, Color> colors = new HashMap<String, Color>(); private Map<IResource, DRLInfo> parsedRules = new HashMap<IResource, DRLInfo>(); private Map<IResource, DRLInfo> compiledRules = new HashMap<IResource, DRLInfo>(); private Map<String, RuleInfo> ruleInfoByClassNameMap = new HashMap<String, RuleInfo>(); private Map<String, FunctionInfo> functionInfoByClassNameMap = new HashMap<String, FunctionInfo>(); private Map<IResource, ProcessInfo> processInfos = new HashMap<IResource, ProcessInfo>(); private Map<String, ProcessInfo> processInfosById = new HashMap<String, ProcessInfo>(); private boolean useCachePreference; private FormColors ruleBuilderFormColors; /** * The constructor. */ public DroolsEclipsePlugin() { super(); plugin = this; } /** * This method is called upon plug-in activation */ public void start(BundleContext context) throws Exception { super.start(context); IPreferenceStore preferenceStore = getPreferenceStore(); useCachePreference = preferenceStore.getBoolean(IDroolsConstants.CACHE_PARSED_RULES); preferenceStore.addPropertyChangeListener(new IPropertyChangeListener() { public void propertyChange(PropertyChangeEvent event) { if (IDroolsConstants.CACHE_PARSED_RULES.equals(event.getProperty())) { useCachePreference = ((Boolean) event.getNewValue()).booleanValue(); if (!useCachePreference) { clearCache(); } } } }); } public void clearCache() { parsedRules.clear(); compiledRules.clear(); ruleInfoByClassNameMap.clear(); functionInfoByClassNameMap.clear(); processInfos.clear(); processInfosById = null; } /** * This method is called when the plug-in is stopped */ public void stop(BundleContext context) throws Exception { super.stop(context); plugin = null; resourceBundle = null; parsedRules = null; compiledRules = null; processInfos = null; processInfosById = null; for (Color color : colors.values()) { color.dispose(); } } /** * Returns the shared instance. */ public static DroolsEclipsePlugin getDefault() { return plugin; } /** * Returns the string from the plugin's resource bundle, * or 'key' if not found. */ public static String getResourceString(String key) { ResourceBundle bundle = DroolsEclipsePlugin.getDefault().getResourceBundle(); try { return (bundle != null) ? bundle.getString(key) : key; } catch (MissingResourceException e) { return key; } } /** * Returns the plugin's resource bundle, */ public ResourceBundle getResourceBundle() { try { if (resourceBundle == null) resourceBundle = ResourceBundle.getBundle("droolsIDE.DroolsIDEPluginResources"); } catch (MissingResourceException x) { resourceBundle = null; } return resourceBundle; } /** * Returns an image descriptor for the image file at the given * plug-in relative path. * Uses the plug ins image registry to "cache" it. * * @param path the path * @return the image descriptor */ public static ImageDescriptor getImageDescriptor(String path) { DroolsEclipsePlugin plugin = getDefault(); ImageRegistry reg = plugin.getImageRegistry(); ImageDescriptor des = reg.getDescriptor(path); if (des == null) { des = AbstractUIPlugin.imageDescriptorFromPlugin("org.drools.eclipse", path); reg.put(path, des); } return des; } public static String getUniqueIdentifier() { if (getDefault() == null) { return PLUGIN_ID; } return getDefault().getBundle().getSymbolicName(); } public static void log(Throwable t) { Throwable top = t; if (t instanceof DebugException) { DebugException de = (DebugException) t; IStatus status = de.getStatus(); if (status.getException() != null) { top = status.getException(); } } log(new Status(IStatus.ERROR, getUniqueIdentifier(), INTERNAL_ERROR, "Internal error in Drools Plugin: ", top)); } public static void log(IStatus status) { getDefault().getLog().log(status); } public Color getColor(String type) { return (Color) colors.get(type); } public void setColor(String type, Color color) { colors.put(type, color); } protected void initializeDefaultPreferences(IPreferenceStore store) { store.setDefault(IDroolsConstants.BUILD_ALL, false); store.setDefault(IDroolsConstants.EDITOR_FOLDING, true); store.setDefault(IDroolsConstants.CACHE_PARSED_RULES, true); store.setDefault(IDroolsConstants.DSL_RULE_EDITOR_COMPLETION_FULL_SENTENCES, true); store.setDefault(IDroolsConstants.SKIN, "BPMN2"); store.setDefault(IDroolsConstants.ALLOW_NODE_CUSTOMIZATION, false); store.setDefault(IDroolsConstants.INTERNAL_API, 2); store.setDefault(IDroolsConstants.FLOW_NODES, "1111111111111"); } public DRLInfo parseResource(IResource resource, boolean compile) throws DroolsParserException { DRLInfo result = (DRLInfo) compiledRules.get(resource); if (result == null && !compile) { result = (DRLInfo) parsedRules.get(resource); } if (result != null) { return result; } return generateParsedResource(resource, compile); } public DRLInfo parseResource(AbstractRuleEditor editor, boolean useUnsavedContent, boolean compile) throws DroolsParserException { IResource resource = editor.getResource(); if (!editor.isDirty() || !useUnsavedContent) { DRLInfo result = (DRLInfo) compiledRules.get(resource); if (result == null && !compile) { result = (DRLInfo) parsedRules.get(resource); } if (result != null) { return result; } } if (!editor.isDirty()) { return generateParsedResource(editor.getContent(), resource, true, compile); } // TODO: can we cache result when using unsaved content as well? return generateParsedResource(editor.getContent(), resource, !useUnsavedContent, compile); } public DRLInfo parseXLSResource(String content, IResource resource) throws DroolsParserException { DRLInfo result = (DRLInfo) compiledRules.get(resource); if (result != null) { return result; } return generateParsedResource(content, resource, false, true); } public DRLInfo parseBRLResource(String content, IResource resource) throws DroolsParserException { DRLInfo result = (DRLInfo) compiledRules.get(resource); if (result != null) { return result; } return generateParsedResource(content, resource, false, true); } public DRLInfo parseGDSTResource(String content, IResource resource) throws DroolsParserException { DRLInfo result = (DRLInfo) compiledRules.get(resource); if (result != null) { return result; } return generateParsedResource(content, resource, false, true); } public void invalidateResource(IResource resource) { DRLInfo cached = (DRLInfo) compiledRules.remove(resource); if (cached != null) { RuleInfo[] ruleInfos = cached.getRuleInfos(); for (int i = 0; i < ruleInfos.length; i++) { ruleInfoByClassNameMap.remove(ruleInfos[i].getClassName()); } FunctionInfo[] functionInfos = cached.getFunctionInfos(); for (int i = 0; i < functionInfos.length; i++) { functionInfoByClassNameMap.remove(functionInfos[i].getClassName()); } } parsedRules.remove(resource); ProcessInfo processInfo = processInfos.remove(resource); if (processInfo != null) { processInfosById.remove(processInfo.getProcessId()); } } private DRLInfo generateParsedResource(IResource resource, boolean compile) throws DroolsParserException { if (resource instanceof IFile) { IFile file = (IFile) resource; try { String content = new String(Util.getResourceContentsAsCharArray(file)); return generateParsedResource(content, file, true, compile); } catch (CoreException e) { log(e); } } return null; } @SuppressWarnings("unchecked") public DRLInfo generateParsedResource(String content, IResource resource, boolean useCache, boolean compile) throws DroolsParserException { useCache = useCache && useCachePreference; DrlParser parser = new DrlParser(); try { Reader dslReader = DSLAdapter.getDSLContent(content, resource); ClassLoader oldLoader = Thread.currentThread().getContextClassLoader(); ClassLoader newLoader = DroolsBuilder.class.getClassLoader(); String level = null; // resource could be null when opening a read-only remote file if (resource != null && resource.getProject().getNature("org.eclipse.jdt.core.javanature") != null) { IJavaProject project = JavaCore.create(resource.getProject()); newLoader = ProjectClassLoader.getProjectClassLoader(project); level = project.getOption(JavaCore.COMPILER_COMPLIANCE, true); } try { Thread.currentThread().setContextClassLoader(newLoader); PackageBuilderConfiguration builder_configuration = new PackageBuilderConfiguration(); if (level != null) { JavaDialectConfiguration javaConf = (JavaDialectConfiguration) builder_configuration .getDialectConfiguration("java"); javaConf.setJavaLanguageLevel(level); } builder_configuration.getClassLoader().addClassLoader(newLoader); // first parse the source PackageDescr packageDescr = null; List<DroolsError> parserErrors = null; if (useCache && resource != null) { DRLInfo cachedDrlInfo = (DRLInfo) parsedRules.get(resource); if (cachedDrlInfo != null) { packageDescr = cachedDrlInfo.getPackageDescr(); parserErrors = cachedDrlInfo.getParserErrors(); } } if (packageDescr == null) { if (dslReader != null) { packageDescr = parser.parse(true, content, dslReader); } else { packageDescr = parser.parse(true, content); } parserErrors = parser.getErrors(); } PackageBuilder builder = new PackageBuilder(builder_configuration); DRLInfo result = null; // compile parsed rules if necessary if (packageDescr != null && compile && !parser.hasErrors()) { // check whether a .package file exists and add it if (resource != null && resource.getParent() != null) { MyResourceVisitor visitor = new MyResourceVisitor(); resource.getParent().accept(visitor, IResource.DEPTH_ONE, IResource.NONE); IResource packageDef = visitor.getPackageDef(); if (packageDef != null) { PackageDescr desc = parseResource(packageDef, false).getPackageDescr(); if (desc != null) { builder.addPackage(desc); } } } builder.addPackage(packageDescr); // make sure the namespace is set, use default if necessary, as this is used to build the DRLInfo if (StringUtils.isEmpty(packageDescr.getNamespace())) { packageDescr.setNamespace(builder.getPackageBuilderConfiguration().getDefaultPackageName()); } result = new DRLInfo(resource == null ? "" : resource.getProjectRelativePath().toString(), packageDescr, parserErrors, builder.getPackageRegistry(packageDescr.getNamespace()).getPackage(), builder.getErrors().getErrors(), builder.getPackageRegistry(packageDescr.getNamespace()) .getDialectCompiletimeRegistry()); } else { result = new DRLInfo(resource == null ? "" : resource.getProjectRelativePath().toString(), packageDescr, parserErrors, new PackageRegistry(builder, new Package("")).getDialectCompiletimeRegistry()); } // cache result if (useCache && resource != null) { if (compile && !parser.hasErrors()) { parsedRules.remove(resource); compiledRules.put(resource, result); RuleInfo[] ruleInfos = result.getRuleInfos(); for (int i = 0; i < ruleInfos.length; i++) { ruleInfoByClassNameMap.put(ruleInfos[i].getClassName(), ruleInfos[i]); } FunctionInfo[] functionInfos = result.getFunctionInfos(); for (int i = 0; i < functionInfos.length; i++) { functionInfoByClassNameMap.put(functionInfos[i].getClassName(), functionInfos[i]); } } else { parsedRules.put(resource, result); } } return result; } finally { Thread.currentThread().setContextClassLoader(oldLoader); } } catch (CoreException e) { log(e); } return null; } public RuleInfo getRuleInfoByClass(String ruleClassName) { return (RuleInfo) ruleInfoByClassNameMap.get(ruleClassName); } public FunctionInfo getFunctionInfoByClass(String functionClassName) { return (FunctionInfo) functionInfoByClassNameMap.get(functionClassName); } public ProcessInfo parseProcess(String input, IResource resource) { try { ClassLoader oldLoader = Thread.currentThread().getContextClassLoader(); ClassLoader newLoader = this.getClass().getClassLoader(); String level = null; if (resource.getProject().getNature("org.eclipse.jdt.core.javanature") != null) { IJavaProject project = JavaCore.create(resource.getProject()); newLoader = ProjectClassLoader.getProjectClassLoader(project); level = project.getOption(JavaCore.COMPILER_COMPLIANCE, true); } try { Thread.currentThread().setContextClassLoader(newLoader); PackageBuilderConfiguration configuration = new PackageBuilderConfiguration(); if (level != null) { JavaDialectConfiguration javaConf = (JavaDialectConfiguration) configuration .getDialectConfiguration("java"); javaConf.setJavaLanguageLevel(level); } configuration.getClassLoader().addClassLoader(newLoader); SemanticModules modules = configuration.getSemanticModules(); modules.addSemanticModule(new BPMNSemanticModule()); modules.addSemanticModule(new BPMNDISemanticModule()); modules.addSemanticModule(new ProcessSemanticModule()); XmlProcessReader xmlReader = new XmlProcessReader(modules); List<org.drools.definition.process.Process> processes = (List<org.drools.definition.process.Process>) xmlReader .read(new StringReader(input)); if (processes != null) { for (org.drools.definition.process.Process process : processes) { if (process != null) { return parseProcess((Process) process, resource, configuration); } else { throw new IllegalArgumentException("Could not parse process " + resource); } } } } finally { Thread.currentThread().setContextClassLoader(oldLoader); } } catch (Exception e) { log(e); } return null; } public ProcessInfo getProcessInfo(String processId) { return processInfosById.get(processId); } public IResource findProcessResource(String processId) { if (processId == null) { return null; } for (Map.Entry<IResource, ProcessInfo> entry : processInfos.entrySet()) { if (processId.equals(entry.getValue().getProcessId())) { return entry.getKey(); } } return null; } public ProcessInfo parseProcess(Process process, IResource resource, PackageBuilderConfiguration config) { PackageBuilder packageBuilder = new PackageBuilder(config); ProcessBuilderImpl processBuilder = new ProcessBuilderImpl(packageBuilder); processBuilder.buildProcess(process, ResourceFactory.newUrlResource("file://" + resource.getLocation().toString())); ProcessInfo processInfo = new ProcessInfo(process.getId(), process); List<DroolsError> errors = new ArrayList<DroolsError>(); errors.addAll(processBuilder.getErrors()); errors.addAll(Arrays.asList(packageBuilder.getErrors().getErrors())); processInfo.setErrors(errors); if (useCachePreference) { processInfos.put(resource, processInfo); processInfosById.put(process.getId(), processInfo); } return processInfo; } /** * Form Colors, default colors for now. * * @param display * @return */ public FormColors getRuleBuilderFormColors(Display display) { if (ruleBuilderFormColors == null) { ruleBuilderFormColors = new FormColors(display); ruleBuilderFormColors.markShared(); } return ruleBuilderFormColors; } private class MyResourceVisitor implements IResourceVisitor { private IResource packageDef; public boolean visit(IResource resource) throws CoreException { if ("package".equals(resource.getFileExtension())) { packageDef = resource; } return true; } public IResource getPackageDef() { return packageDef; } } }