* DLTK Validators API
diff --git a/core/plugins/org.eclipse.dltk.validators.core/.classpath b/core/plugins/org.eclipse.dltk.validators.core/.classpath
new file mode 100644
index 0000000..751c8f2
--- /dev/null
+++ b/core/plugins/org.eclipse.dltk.validators.core/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/core/plugins/org.eclipse.dltk.validators.core/.cvsignore b/core/plugins/org.eclipse.dltk.validators.core/.cvsignore
new file mode 100644
index 0000000..ba077a4
--- /dev/null
+++ b/core/plugins/org.eclipse.dltk.validators.core/.cvsignore
@@ -0,0 +1 @@
+bin
diff --git a/core/plugins/org.eclipse.dltk.validators.core/.project b/core/plugins/org.eclipse.dltk.validators.core/.project
new file mode 100644
index 0000000..d9080be
--- /dev/null
+++ b/core/plugins/org.eclipse.dltk.validators.core/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.dltk.validators.core</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/core/plugins/org.eclipse.dltk.validators.core/META-INF/MANIFEST.MF b/core/plugins/org.eclipse.dltk.validators.core/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..4fa28d8
--- /dev/null
+++ b/core/plugins/org.eclipse.dltk.validators.core/META-INF/MANIFEST.MF
@@ -0,0 +1,14 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: DLTK Model Validators core
+Bundle-SymbolicName: org.eclipse.dltk.validators.core;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: org.eclipse.dltk.validators.internal.core.ValidatorsCore
+Require-Bundle: org.eclipse.core.runtime,
+ org.eclipse.dltk.core,
+ org.eclipse.core.resources,
+ org.eclipse.core.filesystem,
+ org.eclipse.core.variables
+Eclipse-LazyStart: true
+Export-Package: org.eclipse.dltk.validators.core,
+ org.eclipse.dltk.validators.internal.core;x-friends:="org.eclipse.dltk.validators.core.tests,org.eclipse.dltk.validators.ui"
diff --git a/core/plugins/org.eclipse.dltk.validators.core/build.properties b/core/plugins/org.eclipse.dltk.validators.core/build.properties
new file mode 100644
index 0000000..e9863e2
--- /dev/null
+++ b/core/plugins/org.eclipse.dltk.validators.core/build.properties
@@ -0,0 +1,5 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ plugin.xml
diff --git a/core/plugins/org.eclipse.dltk.validators.core/plugin.xml b/core/plugins/org.eclipse.dltk.validators.core/plugin.xml
new file mode 100644
index 0000000..117816f
--- /dev/null
+++ b/core/plugins/org.eclipse.dltk.validators.core/plugin.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.2"?>
+<plugin>
+ <extension-point id="validator" name="DLTK Validator" schema="schema/validator.exsd"/>
+ <extension
+ point="org.eclipse.dltk.core.builder">
+ <builder
+ class="org.eclipse.dltk.validators.internal.core.ValidatorBuilder"
+ nature="#">
+ </builder>
+ </extension>
+
+</plugin>
diff --git a/core/plugins/org.eclipse.dltk.validators.core/schema/validator.exsd b/core/plugins/org.eclipse.dltk.validators.core/schema/validator.exsd
new file mode 100644
index 0000000..6edb65a
--- /dev/null
+++ b/core/plugins/org.eclipse.dltk.validators.core/schema/validator.exsd
@@ -0,0 +1,119 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.dltk.validators.core">
+<annotation>
+ <appInfo>
+ <meta.schema plugin="org.eclipse.dltk.validators.core" id="validator" name="DLTK Validator"/>
+ </appInfo>
+ <documentation>
+
+ </documentation>
+ </annotation>
+
+ <element name="extension">
+ <complexType>
+ <sequence>
+ <element ref="validatorType" minOccurs="1" maxOccurs="unbounded"/>
+ </sequence>
+ <attribute name="point" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appInfo>
+ <meta.attribute translatable="true"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="validatorType">
+ <complexType>
+ <attribute name="id" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="class" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appInfo>
+ <meta.attribute kind="java" basedOn="org.eclipse.dltk.validators.core.IValidatorType"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ <attribute name="nature" type="string" use="required">
+ <annotation>
+ <documentation>
+ Used to filter validators only for selected type of projects.
+ </documentation>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="since"/>
+ </appInfo>
+ <documentation>
+
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="examples"/>
+ </appInfo>
+ <documentation>
+
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="apiInfo"/>
+ </appInfo>
+ <documentation>
+
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="implementation"/>
+ </appInfo>
+ <documentation>
+
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="copyright"/>
+ </appInfo>
+ <documentation>
+
+ </documentation>
+ </annotation>
+
+</schema>
diff --git a/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/core/AbstractValidator.java b/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/core/AbstractValidator.java
new file mode 100644
index 0000000..0e882d3
--- /dev/null
+++ b/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/core/AbstractValidator.java
@@ -0,0 +1,38 @@
+package org.eclipse.dltk.validators.core;
+
+
+public abstract class AbstractValidator implements IValidator {
+ private String id;
+ private String name;
+ private IValidatorType type;
+ boolean active = true;
+
+ protected AbstractValidator(String id, String name, IValidatorType type ) {
+ this.id = id;
+ this.name = name;
+ this.type = type;
+ }
+ public String getID() {
+ return this.id;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public IValidatorType getValidatorType() {
+ return this.type;
+ }
+ protected void setID(String id ) {
+ this.id = id;
+ }
+ public void setName( String name ) {
+ this.name = name;
+ }
+ public boolean isActive() {
+ return active;
+ }
+ public void setActive(boolean active) {
+ this.active = active;
+ }
+}
diff --git a/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/core/AbstractValidatorType.java b/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/core/AbstractValidatorType.java
new file mode 100644
index 0000000..e9c599c
--- /dev/null
+++ b/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/core/AbstractValidatorType.java
@@ -0,0 +1,20 @@
+package org.eclipse.dltk.validators.core;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public abstract class AbstractValidatorType implements IValidatorType {
+ protected Map validators = new HashMap();
+
+ public IValidator[] getValidators() {
+ return (IValidator[])validators.values().toArray(new IValidator[validators.size()]);
+ }
+
+ public IValidator findValidator(String id) {
+ return (IValidator)this.validators.get(id);
+ }
+
+ public void disposeValidator(String id) {
+ validators.remove(id);
+ }
+}
diff --git a/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/core/IValidator.java b/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/core/IValidator.java
new file mode 100644
index 0000000..fa40db8
--- /dev/null
+++ b/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/core/IValidator.java
@@ -0,0 +1,33 @@
+package org.eclipse.dltk.validators.core;
+
+import java.io.OutputStream;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.dltk.core.ISourceModule;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * Contains validator properties.
+ * @author Haiodo
+ *
+ */
+public interface IValidator {
+ String getID();
+ String getName();
+ void setName(String name);
+ IValidatorType getValidatorType();
+ boolean isValidatorValid();
+
+ //Per-resouce operations
+ // If console is non null then output to console are possible.
+ IStatus validate(ISourceModule module, OutputStream console );
+ IStatus validate(IResource resource, OutputStream console );
+
+ // Used to store information into
+ void storeTo(Document doc, Element element);
+
+ boolean isActive();
+ void setActive(boolean active);
+}
diff --git a/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/core/IValidatorChangedListener.java b/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/core/IValidatorChangedListener.java
new file mode 100644
index 0000000..334ad38
--- /dev/null
+++ b/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/core/IValidatorChangedListener.java
@@ -0,0 +1,7 @@
+package org.eclipse.dltk.validators.core;
+
+public interface IValidatorChangedListener {
+ public void validatorChanged(IValidator validator);
+ public void validatorAdded(IValidator validator);
+ public void validatorRemoved(IValidator validator);
+}
diff --git a/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/core/IValidatorType.java b/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/core/IValidatorType.java
new file mode 100644
index 0000000..c8a67a0
--- /dev/null
+++ b/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/core/IValidatorType.java
@@ -0,0 +1,55 @@
+package org.eclipse.dltk.validators.core;
+
+import java.io.IOException;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.dltk.compiler.problem.IProblemReporter;
+import org.eclipse.dltk.core.ISourceModule;
+import org.w3c.dom.Element;
+
+/**
+ * Validator class
+ *
+ * @author Haiodo
+ *
+ */
+public interface IValidatorType {
+ /**
+ * Return validator identifier, must be equal to extension point id. Used to
+ * determine validator UI configuration preferences.
+ *
+ * @return
+ */
+ String getID();
+
+ String getNature();
+
+ String getName();
+
+ /**
+ * If return true, then this validatorh has UI, and some instances of this
+ * validator could be used. For example external tool validator should
+ * return true here, to support specify external progman and arguments.
+ *
+ * If return false, then this is always runningm builtin validator. Static checkers could be here.
+ *
+ * @return
+ */
+ boolean isConfigurable();
+
+ /**
+ * If true then validators of this type could not be added, edited or removed, only activated or diactivated.
+ * @return
+ */
+ boolean isBuiltin();
+
+ IValidator createValidatorFrom(String id, Element validatorElement) throws IOException;
+ IValidator createValidator(String id);
+
+ IValidator[] getValidators();
+
+ IValidator findValidator(String id);
+
+ void disposeValidator(String id);
+}
diff --git a/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/core/PropertyChangeEvent.java b/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/core/PropertyChangeEvent.java
new file mode 100644
index 0000000..2765b99
--- /dev/null
+++ b/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/core/PropertyChangeEvent.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.dltk.validators.core;
+
+
+import java.util.EventObject;
+/**
+ * An event object describing a change to a named property.
+ * <p>
+ * ScriptRuntime provides change notification for properties of Interpreter installs
+ * </p>
+ * <p>
+ * Clients may instantiate this class; not intended to be subclassed.
+ * </p>
+ *
+ */
+public class PropertyChangeEvent extends EventObject {
+
+ /**
+ * All serializable objects should have a stable serialVersionUID
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * The name of the changed property.
+ */
+ private String propertyName;
+
+ /**
+ * The old value of the changed property, or <code>null</code> if
+ * not known or not relevant.
+ */
+ private Object oldValue;
+
+ /**
+ * The new value of the changed property, or <code>null</code> if
+ * not known or not relevant.
+ */
+ private Object newValue;
+
+ /**
+ * Creates a new property change event.
+ *
+ * @param source the object whose property has changed
+ * @param property the property that has changed (must not be
+ * <code>null</code>)
+ * @param oldValue the old value of the property, or
+ * <code>null</code> if none
+ * @param newValue the new value of the property, or
+ * <code>null</code> if none
+ */
+ public PropertyChangeEvent(
+ Object source,
+ String property,
+ Object oldValue,
+ Object newValue) {
+
+ super(source);
+ if (property == null) {
+ throw new IllegalArgumentException();
+ }
+ this.propertyName = property;
+ this.oldValue = oldValue;
+ this.newValue = newValue;
+ }
+
+ /**
+ * Returns the name of the property that changed.
+ *
+ * @return the name of the property that changed
+ */
+ public String getProperty() {
+ return propertyName;
+ }
+
+ /**
+ * Returns the new value of the property.
+ *
+ * @return the new value, or <code>null</code> if not known
+ * or not relevant
+ */
+ public Object getNewValue() {
+ return newValue;
+ }
+
+ /**
+ * Returns the old value of the property.
+ *
+ * @return the old value, or <code>null</code> if not known
+ * or not relevant
+ */
+ public Object getOldValue() {
+ return oldValue;
+ }
+}
diff --git a/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/core/ValidatorRuntime.java b/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/core/ValidatorRuntime.java
new file mode 100644
index 0000000..4db5b25
--- /dev/null
+++ b/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/core/ValidatorRuntime.java
@@ -0,0 +1,374 @@
+package org.eclipse.dltk.validators.core;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
+
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.dltk.compiler.problem.DLTKProblemReporter;
+import org.eclipse.dltk.compiler.problem.DefaultProblemFactory;
+import org.eclipse.dltk.compiler.problem.IProblem;
+import org.eclipse.dltk.compiler.problem.IProblemFactory;
+import org.eclipse.dltk.compiler.problem.IProblemReporter;
+import org.eclipse.dltk.core.DLTKLanguageManager;
+import org.eclipse.dltk.core.IDLTKLanguageToolkit;
+import org.eclipse.dltk.core.IModelElement;
+import org.eclipse.dltk.core.IProblemRequestor;
+import org.eclipse.dltk.core.ISourceModule;
+import org.eclipse.dltk.validators.internal.core.CompositeId;
+import org.eclipse.dltk.validators.internal.core.ListenerList;
+import org.eclipse.dltk.validators.internal.core.ValidatorDefinitionsContainer;
+import org.eclipse.dltk.validators.internal.core.ValidatorManager;
+import org.eclipse.dltk.validators.internal.core.ValidatorsCore;
+
+public final class ValidatorRuntime {
+
+ public static final String PREF_VALIDATOR_XML = ValidatorsCore.PLUGIN_ID
+ + ".PREF_VALIDATOR_XML"; //$NON-NLS-1$
+
+ public static final String MARKER_VALIDATOR = ValidatorsCore.PLUGIN_ID
+ + ".marker_validator_id";
+
+ // lock for interpreter initialization
+ private static Object fgValidatorLock = new Object();
+ private static boolean fgInitializingValidators = false;
+ //
+ private static ListenerList fgValidatorListeners = new ListenerList(5);
+ //
+ //
+ // private static ThreadLocal fgProjects = new ThreadLocal(); // Lists
+ // private static ThreadLocal fgEntryCount = new ThreadLocal(); // Integers
+
+ private static Set fgContributedValidators = new HashSet();
+
+ private ValidatorRuntime() {
+ }
+
+ public static IValidatorType getValidatorType(String id) {
+ IValidatorType[] interpreterTypes = getValidatorTypes();
+ for (int i = 0; i < interpreterTypes.length; i++) {
+ if (interpreterTypes[i].getID().equals(id)) {
+ return interpreterTypes[i];
+ }
+ }
+ return null;
+ }
+
+ public static IValidatorType[] getValidatorTypes() {
+ initializeValidators();
+ try {
+ return ValidatorManager.getAllValidatorTypes();
+ } catch (CoreException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ public static IValidatorType[] getValidatorTypes(String nature) {
+ try {
+ return ValidatorManager.getValidators(nature);
+ } catch (CoreException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ public static String getCompositeIdFromValidator(IValidator validator) {
+ if (validator == null) {
+ return null;
+ }
+ IValidatorType validatorType = validator.getValidatorType();
+ String typeID = validatorType.getID();
+ CompositeId id = new CompositeId(new String[] { typeID,
+ validator.getID() });
+ return id.toString();
+ }
+
+ public static IValidator getValidatorFromCompositeId(String idString) {
+ if (idString == null || idString.length() == 0) {
+ return null;
+ }
+ CompositeId id = CompositeId.fromString(idString);
+ if (id.getPartCount() == 2) {
+ IValidatorType validatorType = getValidatorType(id.get(0));
+ if (validatorType != null) {
+ return validatorType.findValidator(id.get(1));
+ }
+ }
+ return null;
+ }
+
+ public static void saveInterpreterConfiguration() throws CoreException {
+ IValidatorType[] vals = getValidatorTypes();
+ if (vals == null || vals.length == 0) {
+ // if the Interpreter types have not been instantiated, there can be
+ // no changes.
+ return;
+ }
+ try {
+ String xml = getValidatorsAsXML();
+ getPreferences().setValue(PREF_VALIDATOR_XML, xml);
+ savePreferences();
+ } catch (IOException e) {
+ throw new CoreException(new Status(IStatus.ERROR, "Error",
+ IStatus.ERROR, "Exception occured", e));
+ } catch (ParserConfigurationException e) {
+ throw new CoreException(new Status(IStatus.ERROR, "Error",
+ IStatus.ERROR, "Exception occured", e));
+ } catch (TransformerException e) {
+ throw new CoreException(new Status(IStatus.ERROR, "Error",
+ IStatus.ERROR, "Exception occured", e));
+ }
+ }
+
+ private static String getValidatorsAsXML() throws IOException,
+ ParserConfigurationException, TransformerException {
+ ValidatorDefinitionsContainer container = new ValidatorDefinitionsContainer();
+
+ IValidatorType[] validatorTypes = getValidatorTypes();
+ for (int i = 0; i < validatorTypes.length; ++i) {
+ IValidator[] Interpreters = validatorTypes[i].getValidators();
+ for (int j = 0; j < Interpreters.length; j++) {
+ IValidator install = Interpreters[j];
+ container.addValidator(install);
+ }
+ }
+ return container.getAsXML();
+ }
+
+ private static boolean addPersistedValidators(
+ ValidatorDefinitionsContainer interpreterDefs) throws IOException {
+
+ String validatorXMLString = getPreferences().getString(
+ PREF_VALIDATOR_XML);
+
+ if (validatorXMLString.length() > 0) {
+ try {
+ ByteArrayInputStream inputStream = new ByteArrayInputStream(
+ validatorXMLString.getBytes());
+ ValidatorDefinitionsContainer.parseXMLIntoContainer(
+ inputStream, interpreterDefs);
+ return false;
+ } catch (IOException ioe) {
+ // DLTKLaunchingPlugin.log(ioe);
+ }
+ }
+ return true;
+ }
+
+ public static boolean isContributedValidator(String id) {
+ getValidatorTypes();
+ return fgContributedValidators.contains(id);
+ }
+
+ public static Preferences getPreferences() {
+ return ValidatorsCore.getDefault().getPluginPreferences();
+ }
+
+ public static void savePreferences() {
+ ValidatorsCore.getDefault().savePluginPreferences();
+ }
+
+ /**
+ * Perform Interpreter type and Interpreter install initialization. Does not
+ * hold locks while performing change notification.
+ *
+ *
+ */
+ private static void initializeValidators() {
+ ValidatorDefinitionsContainer validatorDefs = null;
+ boolean setPref = false;
+ synchronized (fgValidatorLock) {
+
+ try {
+ fgInitializingValidators = true;
+ // 1. load Validators type extensions
+ // initializeValidatorTypeExtensions();
+ try {
+ validatorDefs = new ValidatorDefinitionsContainer();
+
+ // 2. add persisted Validators
+ setPref = addPersistedValidators(validatorDefs);
+
+ // 4. load contributed Validators installs
+ // addValidatorExtensions(InterpreterDefs);
+
+ } catch (IOException e) {
+ // DLTKLaunchingPlugin.log(e);
+ }
+ } finally {
+ fgInitializingValidators = false;
+ }
+ }
+ if (validatorDefs != null) {
+ // notify of initial Interpreters for backwards compatibility
+ IValidatorType[] validatorTypes = null;
+ try {
+ validatorTypes = ValidatorManager.getAllValidatorTypes();
+ } catch (CoreException e1) {
+ return;
+ }
+ for (int i = 0; i < validatorTypes.length; i++) {
+ IValidatorType type = validatorTypes[i];
+ IValidator[] installs = type.getValidators();
+ if (installs != null) {
+ for (int j = 0; j < installs.length; j++) {
+ fireInterpreterAdded(installs[j]);
+ }
+ }
+ }
+
+ // save settings if required
+ if (setPref) {
+ try {
+ String xml = validatorDefs.getAsXML();
+ getPreferences().setValue(PREF_VALIDATOR_XML, xml);
+ } catch (ParserConfigurationException e) {
+ // DLTKLaunchingPlugin.log(e);
+ } catch (IOException e) {
+ // DLTKLaunchingPlugin.log(e);
+ } catch (TransformerException e) {
+ // DLTKLaunchingPlugin.log(e);
+ }
+
+ }
+
+ }
+ }
+
+ public static void addValidatorChangedListener(
+ IValidatorChangedListener listener) {
+ fgValidatorListeners.add(listener);
+ }
+
+ public static void removeValidatorInstallChangedListener(
+ IValidatorChangedListener listener) {
+ fgValidatorListeners.remove(listener);
+ }
+
+ public static void fireInterpreterChanged(IValidator validator) {
+ Object[] listeners = fgValidatorListeners.getListeners();
+ for (int i = 0; i < listeners.length; i++) {
+ IValidatorChangedListener listener = (IValidatorChangedListener) listeners[i];
+ listener.validatorChanged(validator);
+ }
+ }
+
+ public static void fireInterpreterAdded(IValidator Interpreter) {
+ if (!fgInitializingValidators) {
+ Object[] listeners = fgValidatorListeners.getListeners();
+ for (int i = 0; i < listeners.length; i++) {
+ IValidatorChangedListener listener = (IValidatorChangedListener) listeners[i];
+ listener.validatorAdded(Interpreter);
+ }
+ }
+ }
+
+ public static void fireInterpreterRemoved(IValidator Interpreter) {
+ Object[] listeners = fgValidatorListeners.getListeners();
+ for (int i = 0; i < listeners.length; i++) {
+ IValidatorChangedListener listener = (IValidatorChangedListener) listeners[i];
+ listener.validatorRemoved(Interpreter);
+ }
+ }
+
+ public static IValidatorType[] getPossibleValidatorTypes() {
+ List possible = new ArrayList();
+ IValidatorType[] vals = getValidatorTypes();
+ for (int i = 0; i < vals.length; i++) {
+ if (!vals[i].isBuiltin()) {
+ possible.add(vals[i]);
+ }
+ }
+ return (IValidatorType[]) possible.toArray(new IValidatorType[possible
+ .size()]);
+ }
+
+ public static IValidator[] getActiveValidators() {
+ List possible = new ArrayList();
+ IValidatorType[] vals = getValidatorTypes();
+ for (int i = 0; i < vals.length; i++) {
+ IValidator[] v = vals[i].getValidators();
+ for (int j = 0; j < v.length; j++) {
+ if (v[j].isActive() && v[j].isValidatorValid()) {
+ if (!possible.contains(v[j])) {
+ possible.add(v[j]);
+ }
+ }
+ }
+ }
+ return (IValidator[]) possible.toArray(new IValidator[possible.size()]);
+ }
+
+ public static void executeActiveValidatorsWithConsole(OutputStream stream,
+ List elements, List resources) {
+ IValidator[] activeValidators = getActiveValidators();
+ if (elements != null) {
+ for (Iterator iterator = elements.iterator(); iterator.hasNext();) {
+ IModelElement el = (IModelElement) iterator.next();
+ if (el instanceof ISourceModule) {
+ ISourceModule module = (ISourceModule) el;
+ IDLTKLanguageToolkit toolkit = null;
+ try {
+ toolkit = DLTKLanguageManager
+ .getLanguageToolkit(module);
+ } catch (CoreException e) {
+ try {
+ if (stream != null) {
+ stream
+ .write(("Error to check element:" + module
+ .getPath()).getBytes());
+ }
+ } catch (IOException e1) {
+ e1.printStackTrace();
+ }
+ e.printStackTrace();
+ continue;
+ }
+ for (int i = 0; i < activeValidators.length; i++) {
+ IValidator v = activeValidators[i];
+ String nature = v.getValidatorType().getNature();
+ if (toolkit.getNatureID().equals(nature)
+ || nature.equals("#")) {
+
+ IStatus e = v.validate(module, stream);
+ if (e.getSeverity() == IStatus.ERROR) {
+ if (stream != null) {
+ String message = e.getMessage();
+ try {
+ stream.write(message.getBytes());
+ } catch (IOException e1) {
+ e1.printStackTrace();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ }
+ }
+ if (resources != null) {
+ for (Iterator iterator = resources.iterator(); iterator.hasNext();) {
+ IResource el = (IResource) iterator.next();
+ for (int i = 0; i < activeValidators.length; i++) {
+ IValidator v = activeValidators[i];
+ v.validate(el, stream);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/internal/core/CompositeId.java b/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/internal/core/CompositeId.java
new file mode 100644
index 0000000..2aa79ed
--- /dev/null
+++ b/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/internal/core/CompositeId.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.dltk.validators.internal.core;
+
+import java.util.ArrayList;
+
+/**
+ * Utility class for id's made of multiple Strings
+ */
+public class CompositeId {
+ private String[] fParts;
+
+ public CompositeId(String[] parts) {
+ fParts= parts;
+ }
+
+ public static CompositeId fromString(String idString) {
+ ArrayList parts= new ArrayList();
+ int commaIndex= idString.indexOf(',');
+ while (commaIndex > 0) {
+ int length= Integer.valueOf(idString.substring(0, commaIndex)).intValue();
+ String part= idString.substring(commaIndex+1, commaIndex+1+length);
+ parts.add(part);
+ idString= idString.substring(commaIndex+1+length);
+ commaIndex= idString.indexOf(',');
+ }
+ String[] result= (String[])parts.toArray(new String[parts.size()]);
+ return new CompositeId(result);
+ }
+
+ public String toString() {
+ StringBuffer buf= new StringBuffer();
+ for (int i= 0; i < fParts.length; i++) {
+ buf.append(fParts[i].length());
+ buf.append(',');
+ buf.append(fParts[i]);
+ }
+ return buf.toString();
+ }
+
+ public String get(int index) {
+ return fParts[index];
+ }
+
+ public int getPartCount() {
+ return fParts.length;
+ }
+}
diff --git a/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/internal/core/ListenerList.java b/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/internal/core/ListenerList.java
new file mode 100644
index 0000000..07550dc
--- /dev/null
+++ b/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/internal/core/ListenerList.java
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.dltk.validators.internal.core;
+
+
+/**
+ * Local version of org.eclipse.jface.util.ListenerList (modified)s
+ */
+public class ListenerList {
+ /**
+ * The current number of listeners.
+ * Maintains invariant: 0 <= fSize <= listeners.length.
+ */
+ private int fSize;
+
+ /**
+ * The list of listeners. Initially <code>null</code> but initialized
+ * to an array of size capacity the first time a listener is added.
+ * Maintains invariant: listeners != null if and only if fSize != 0
+ */
+ private Object[] fListeners= null;
+
+ /**
+ * The empty array singleton instance, returned by getListeners()
+ * when size == 0.
+ */
+ private static final Object[] EmptyArray= new Object[0];
+
+ /**
+ * Creates a listener list with the given initial capacity.
+ *
+ * @param capacity the number of listeners which this list can initially accept
+ * without growing its internal representation; must be at least 1
+ */
+ public ListenerList(int capacity) {
+ if (capacity < 1) {
+ throw new IllegalArgumentException();
+ }
+ fListeners= new Object[capacity];
+ fSize= 0;
+ }
+
+ /**
+ * Adds a listener to the list.
+ * Has no effect if an identical listener is already registered.
+ *
+ * @param listener a listener
+ */
+ public synchronized void add(Object listener) {
+ if (listener == null) {
+ throw new IllegalArgumentException();
+ }
+ // check for duplicates using identity
+ for (int i= 0; i < fSize; ++i) {
+ if (fListeners[i] == listener) {
+ return;
+ }
+ }
+ // grow array if necessary
+ if (fSize == fListeners.length) {
+ Object[] temp= new Object[(fSize * 2) + 1];
+ System.arraycopy(fListeners, 0, temp, 0, fSize);
+ fListeners= temp;
+ }
+ fListeners[fSize++]= listener;
+ }
+
+ /**
+ * Returns an array containing all the registered listeners.
+ * The resulting array is unaffected by subsequent adds or removes.
+ * If there are no listeners registered, the result is an empty array
+ * singleton instance (no garbage is created).
+ * Use this method when notifying listeners, so that any modifications
+ * to the listener list during the notification will have no effect on the
+ * notification itself.
+ */
+ public synchronized Object[] getListeners() {
+ if (fSize == 0) {
+ return EmptyArray;
+ }
+ Object[] result= new Object[fSize];
+ System.arraycopy(fListeners, 0, result, 0, fSize);
+ return result;
+ }
+
+ /**
+ * Removes a listener from the list.
+ * Has no effect if an identical listener was not already registered.
+ *
+ * @param listener a listener
+ */
+ public synchronized void remove(Object listener) {
+ if (listener == null) {
+ throw new IllegalArgumentException();
+ }
+
+ for (int i= 0; i < fSize; ++i) {
+ if (fListeners[i] == listener) {
+ if (--fSize == 0) {
+ fListeners= new Object[1];
+ } else {
+ if (i < fSize) {
+ fListeners[i]= fListeners[fSize];
+ }
+ fListeners[fSize]= null;
+ }
+ return;
+ }
+ }
+ }
+
+ /**
+ * Removes all the listeners from the list.
+ */
+ public void removeAll() {
+ fListeners= new Object[0];
+ fSize= 0;
+ }
+
+ /**
+ * Returns the number of registered listeners
+ *
+ * @return the number of registered listeners
+ */
+ public int size() {
+ return fSize;
+ }
+}
+
diff --git a/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/internal/core/ValidatorBuilder.java b/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/internal/core/ValidatorBuilder.java
new file mode 100644
index 0000000..3d008e1
--- /dev/null
+++ b/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/internal/core/ValidatorBuilder.java
@@ -0,0 +1,30 @@
+package org.eclipse.dltk.validators.internal.core;
+
+import java.util.List;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.dltk.core.IDLTKProject;
+import org.eclipse.dltk.core.builder.IScriptBuilder;
+import org.eclipse.dltk.validators.core.ValidatorRuntime;
+
+public class ValidatorBuilder implements IScriptBuilder {
+
+ public IStatus[] buildModelElements(IDLTKProject project, List elements,
+ IProgressMonitor monitor) {
+ ValidatorRuntime.executeActiveValidatorsWithConsole(null, elements, null);
+ return null;
+ }
+
+ public IStatus[] buildResources(IDLTKProject project, List resources,
+ IProgressMonitor monitor) {
+ ValidatorRuntime.executeActiveValidatorsWithConsole(null, null, resources);
+ return null;
+ }
+
+ public List getDependencies(IDLTKProject project, List resources) {
+ //We don't provide dependencies here.
+ return null;
+ }
+
+}
diff --git a/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/internal/core/ValidatorDefinitionsContainer.java b/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/internal/core/ValidatorDefinitionsContainer.java
new file mode 100644
index 0000000..392ed8a
--- /dev/null
+++ b/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/internal/core/ValidatorDefinitionsContainer.java
@@ -0,0 +1,309 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.dltk.validators.internal.core;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
+
+import org.eclipse.core.runtime.Status;
+import org.eclipse.dltk.core.DLTKCore;
+import org.eclipse.dltk.validators.core.IValidator;
+import org.eclipse.dltk.validators.core.IValidatorType;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+public class ValidatorDefinitionsContainer {
+
+ private Map fValidatorTypeToValidatorMap;
+
+ private List fValidatorList;
+
+ private List fInvalidValidatorList;
+
+ public ValidatorDefinitionsContainer() {
+ fValidatorTypeToValidatorMap = new HashMap(10);
+ fInvalidValidatorList = new ArrayList(10);
+ fValidatorList = new ArrayList(10);
+ }
+
+ public void addValidator(IValidator validator) {
+ if (!fValidatorList.contains(validator)) {
+ IValidatorType InterpreterInstallType = validator
+ .getValidatorType();
+ List validatorList = (List) fValidatorTypeToValidatorMap
+ .get(InterpreterInstallType);
+ if (validatorList == null) {
+ validatorList = new ArrayList(3);
+ fValidatorTypeToValidatorMap.put(InterpreterInstallType,
+ validatorList);
+ }
+ validatorList.add(validator);
+ if (!validator.isValidatorValid()) {
+ fInvalidValidatorList.add(validator);
+ }
+ fValidatorList.add(validator);
+ }
+ }
+
+ public void addValidatorList(List validatorList) {
+ Iterator iterator = validatorList.iterator();
+ while (iterator.hasNext()) {
+ IValidator validator = (IValidator) iterator.next();
+ addValidator(validator);
+ }
+ }
+
+ public Map getValidateTypeToValidatorsMap() {
+ return fValidatorTypeToValidatorMap;
+ }
+
+ public List getValidatorList() {
+ return fValidatorList;
+ }
+
+ public List getValidatorList(String nature) {
+ List res = new ArrayList(fValidatorList.size());
+ for (Iterator iter = fValidatorList.iterator(); iter.hasNext();) {
+ IValidator validator = (IValidator) iter.next();
+ String sharp = "#";
+ String nature2 = validator.getValidatorType().getNature();
+ if (nature2.equals(nature) || nature2.equals(sharp)) {
+ res.add(validator);
+ }
+ }
+ return res;
+ }
+
+ public List getValidValidatorsList() {
+ List validators = getValidatorList();
+ List resultList = new ArrayList(validators.size());
+ resultList.addAll(validators);
+ resultList.removeAll(fInvalidValidatorList);
+ return resultList;
+ }
+
+ public List getValidValidatorsList(String nature) {
+ List Interpreters = getValidatorList(nature);
+ List resultList = new ArrayList(Interpreters.size());
+ resultList.addAll(Interpreters);
+ resultList.removeAll(fInvalidValidatorList);
+ return resultList;
+ }
+
+ public String getAsXML() throws ParserConfigurationException, IOException,
+ TransformerException {
+
+ // Create the Document and the top-level node
+ Document doc = ValidatorsCore.getDocument();
+ Element config = doc.createElement("validatorSettings"); //$NON-NLS-1$
+ doc.appendChild(config);
+
+ // Create a node for each install type represented in this container
+ Set validatorTypeSet = getValidateTypeToValidatorsMap().keySet();
+ Iterator keyIterator = validatorTypeSet.iterator();
+ while (keyIterator.hasNext()) {
+ IValidatorType validatorType = (IValidatorType) keyIterator.next();
+ if (validatorType.isConfigurable()) {
+ Element valiatorTypeElement = validatorTypeAsElement(doc,
+ validatorType);
+ config.appendChild(valiatorTypeElement);
+ }
+ }
+
+ // Serialize the Document and return the resulting String
+ return ValidatorsCore.serializeDocument(doc);
+ }
+
+ private Element validatorTypeAsElement(Document doc,
+ IValidatorType validatorType) {
+
+ // Create a node for the Interpreter type and set its 'id' attribute
+ Element element = doc.createElement("validatorType"); //$NON-NLS-1$
+ element.setAttribute("id", validatorType.getID()); //$NON-NLS-1$
+
+ // For each Interpreter of the specified type, create a subordinate node
+ // for it
+ List validatorList = (List) getValidateTypeToValidatorsMap().get(
+ validatorType);
+ Iterator validatorIterator = validatorList.iterator();
+ while (validatorIterator.hasNext()) {
+ IValidator validator = (IValidator) validatorIterator.next();
+ Element validatorElement = validatorAsElement(doc, validator);
+ element.appendChild(validatorElement);
+ }
+
+ return element;
+ }
+
+ private Element validatorAsElement(Document doc, IValidator validator) {
+
+ // Create the node for the Interpreter and set its 'id' & 'name'
+ // attributes
+ Element element = doc.createElement("validator"); //$NON-NLS-1$
+ element.setAttribute("id", validator.getID()); //$NON-NLS-1$
+ element.setAttribute("name", validator.getName()); //$NON-NLS-1$
+ element.setAttribute("active", Boolean.toString(validator.isActive()));
+
+ validator.storeTo(doc, element);
+
+ return element;
+ }
+
+ public static ValidatorDefinitionsContainer parseXMLIntoContainer(
+ InputStream inputStream) throws IOException {
+ ValidatorDefinitionsContainer container = new ValidatorDefinitionsContainer();
+ parseXMLIntoContainer(inputStream, container);
+ return container;
+ }
+
+ public static void parseXMLIntoContainer(InputStream inputStream,
+ ValidatorDefinitionsContainer container) throws IOException {
+
+ // Wrapper the stream for efficient parsing
+ InputStream stream = new BufferedInputStream(inputStream);
+
+ // Do the parsing and obtain the top-level node
+ Element config = null;
+ try {
+ DocumentBuilder parser = DocumentBuilderFactory.newInstance()
+ .newDocumentBuilder();
+ parser.setErrorHandler(new DefaultHandler());
+ config = parser.parse(new InputSource(stream)).getDocumentElement();
+ } catch (SAXException e) {
+ throw new IOException(ValidatorMessages.ValidatorRuntime_badFormat);
+ } catch (ParserConfigurationException e) {
+ stream.close();
+ throw new IOException(ValidatorMessages.ValidatorRuntime_badFormat);
+ } finally {
+ stream.close();
+ }
+
+ // If the top-level node wasn't what we expected, bail out
+ if (!config.getNodeName().equalsIgnoreCase("validatorSettings")) { //$NON-NLS-1$
+ throw new IOException(ValidatorMessages.ValidatorRuntime_badFormat);
+ }
+
+ // Traverse the parsed structure and populate the InterpreterType to
+ // Interpreter Map
+ NodeList list = config.getChildNodes();
+ int length = list.getLength();
+ for (int i = 0; i < length; ++i) {
+ Node node = list.item(i);
+ short type = node.getNodeType();
+ if (type == Node.ELEMENT_NODE) {
+ Element validatorTypeElement = (Element) node;
+ if (validatorTypeElement.getNodeName().equalsIgnoreCase(
+ "validatorType")) { //$NON-NLS-1$
+ populateValidatorTypes(validatorTypeElement, container);
+ }
+ }
+ }
+ }
+
+ /**
+ * For the specified Interpreter type node, parse all subordinate
+ * Interpreter definitions and add them to the specified container.
+ */
+ private static void populateValidatorTypes(Element validatorTypeElement,
+ ValidatorDefinitionsContainer container) {
+
+ // Retrieve the 'id' attribute and the corresponding Interpreter type
+ // object
+ String id = validatorTypeElement.getAttribute("id"); //$NON-NLS-1$
+ IValidatorType validatorType = ValidatorManager
+ .getValidatorTypeFromID(id);
+ if (validatorType != null) {
+
+ // For each Interpreter child node, populate the container with a
+ // subordinate node
+ NodeList validatorNodeList = validatorTypeElement.getChildNodes();
+ for (int i = 0; i < validatorNodeList.getLength(); ++i) {
+ Node InterpreterNode = validatorNodeList.item(i);
+ short type = InterpreterNode.getNodeType();
+ if (type == Node.ELEMENT_NODE) {
+ Element InterpreterElement = (Element) InterpreterNode;
+ if (InterpreterElement.getNodeName().equalsIgnoreCase(
+ "validator")) { //$NON-NLS-1$
+ populateValidatorForType(validatorType,
+ InterpreterElement, container);
+ }
+ }
+ }
+ } else {
+ if (DLTKCore.DEBUG) {
+ System.err.println("Interpreter type element with unknown id."); //$NON-NLS-1$
+ }
+ }
+ }
+
+ /**
+ * Parse the specified Interpreter node, create a InterpreterStandin for it,
+ * and add this to the specified container.
+ */
+ private static void populateValidatorForType(
+ IValidatorType interpreterType, Element validatorElement,
+ ValidatorDefinitionsContainer container) {
+ String id = validatorElement.getAttribute("id"); //$NON-NLS-1$
+ String name = validatorElement.getAttribute("name"); //$NON-NLS-1$
+ boolean active = Boolean.parseBoolean(validatorElement.getAttribute("active"));
+ if (id != null) {
+ try {
+ IValidator validator = interpreterType
+ .createValidatorFrom(id, validatorElement);
+ validator.setName(name);
+ validator.setActive(active);
+ container.addValidator(validator);
+ }
+ catch(IOException e ) {
+ DLTKCore.getDefault().getLog().log(new Status(0,ValidatorsCore.PLUGIN_ID, "Failed to load validator from XML..."));
+ }
+ } else {
+ if (DLTKCore.DEBUG) {
+ System.err
+ .println("id attribute missing from Interpreter element specification."); //$NON-NLS-1$
+ }
+ }
+ }
+
+ /**
+ * Removes the Interpreter from this container.
+ *
+ * @param Interpreter
+ * Interpreter intall
+ */
+ public void removeValidator(IValidator Interpreter) {
+ fValidatorList.remove(Interpreter);
+ fInvalidValidatorList.remove(Interpreter);
+ List list = (List) fValidatorTypeToValidatorMap.get(Interpreter
+ .getValidatorType());
+ if (list != null) {
+ list.remove(Interpreter);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/internal/core/ValidatorManager.java b/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/internal/core/ValidatorManager.java
new file mode 100644
index 0000000..4b8b3ed
--- /dev/null
+++ b/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/internal/core/ValidatorManager.java
@@ -0,0 +1,131 @@
+package org.eclipse.dltk.validators.internal.core;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.dltk.validators.core.IValidatorType;
+
+public class ValidatorManager {
+
+ private final static String LANGUAGE_EXTPOINT = ValidatorsCore.PLUGIN_ID
+ + ".validator";
+
+ private final static String NATURE_ATTR = "nature";
+
+ // Contains list of validators for selected nature.
+ private static Map validators;
+
+ private static Map idToValidatorType = null;
+
+ public static IValidatorType getValidatorTypeFromID( String id ) {
+ if( idToValidatorType == null ) {
+ idToValidatorType = new HashMap();
+ try {
+ IValidatorType[] allValidatorTypes = getAllValidatorTypes();
+ for (int i = 0; i < allValidatorTypes.length; i++) {
+ idToValidatorType.put(allValidatorTypes[i].getID(), allValidatorTypes[i] );
+ }
+ } catch (CoreException e) {
+ idToValidatorType = null;
+ return null;
+ }
+ }
+ return (IValidatorType)idToValidatorType.get(id);
+ }
+
+ private static void initialize() {
+ if (validators != null) {
+ return;
+ }
+
+ validators = new HashMap(5);
+ IConfigurationElement[] cfg = Platform.getExtensionRegistry()
+ .getConfigurationElementsFor(LANGUAGE_EXTPOINT);
+
+ for (int i = 0; i < cfg.length; i++) {
+ String nature = cfg[i].getAttribute(NATURE_ATTR);
+ if (validators.get(nature) != null) {
+ List elements = (List)validators.get(nature);
+ elements.add(cfg[i]);
+ continue;
+ }
+ List elements = new ArrayList();
+ elements.add( cfg[i] );
+ validators.put( nature, elements );
+ }
+ }
+ /**
+ * Return merged with all elements with nature #
+ * @param natureId
+ * @return
+ * @throws CoreException
+ */
+ public static IValidatorType[] getValidators(String natureId)
+ throws CoreException {
+ initialize();
+
+ List results = new ArrayList();
+ processNature(natureId, results);
+ // Add from # nature.
+ processNature( "#", results );
+ return (IValidatorType[])results.toArray(new IValidatorType[results.size()]);
+ }
+ private static void processNature(String natureId, List results)
+ throws CoreException {
+ Object ext = validators.get(natureId);
+
+ if (ext != null) {
+ if( ext instanceof IValidatorType[]) {
+ IValidatorType[] b = (IValidatorType[])ext;
+ for (int i = 0; i < b.length; i++) {
+ if( !results.contains(b[i])) {
+ results.add(b[i]);
+ }
+ }
+ }
+ else if ( ext instanceof List ) {
+ List elements = (List)ext;
+ IValidatorType[] result = new IValidatorType[elements.size()];
+ for( int i = 0; i < elements.size(); ++i ) {
+ Object e = elements.get(i);
+ if( e instanceof IValidatorType ) {
+ result[i] = (IValidatorType)e;
+ }
+ else {
+ IConfigurationElement cfg = (IConfigurationElement) e;
+ IValidatorType builder = (IValidatorType) cfg
+ .createExecutableExtension("class");
+ result[i] = builder;
+ }
+ }
+ validators.put(natureId, result) ;
+ for (int i = 0; i < result.length; i++) {
+ if( !results.contains(result[i])) {
+ results.add(result[i]);
+ }
+ }
+ }
+ }
+ }
+
+ public static IValidatorType[] getAllValidatorTypes() throws CoreException {
+
+ initialize();
+ List result = new ArrayList();
+ Iterator iterator = validators.keySet().iterator();
+ while( iterator.hasNext() ) {
+ String nature = (String)iterator.next();
+ IValidatorType[] b = getValidators(nature);
+ for( int i = 0; i < b.length; ++i ) {
+ result.add(b[i]);
+ }
+ }
+ return (IValidatorType[])result.toArray(new IValidatorType[result.size()]);
+ }
+}
diff --git a/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/internal/core/ValidatorMessages.java b/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/internal/core/ValidatorMessages.java
new file mode 100644
index 0000000..c92a595
--- /dev/null
+++ b/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/internal/core/ValidatorMessages.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.dltk.validators.internal.core;
+
+import org.eclipse.osgi.util.NLS;
+
+public class ValidatorMessages extends NLS {
+ private static final String BUNDLE_NAME = ValidatorMessages.class.getName();//$NON-NLS-1$
+ public static String ValidatorRuntime_badFormat;
+
+
+ static {
+ // load message values from bundle file
+ NLS.initializeMessages(BUNDLE_NAME, ValidatorMessages.class);
+ }
+
+
+
+
+
+}
\ No newline at end of file
diff --git a/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/internal/core/ValidatorMessages.properties b/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/internal/core/ValidatorMessages.properties
new file mode 100644
index 0000000..91c2aeb
--- /dev/null
+++ b/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/internal/core/ValidatorMessages.properties
@@ -0,0 +1 @@
+ValidatorRuntime_badFormat = Bad format
\ No newline at end of file
diff --git a/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/internal/core/ValidatorUtils.java b/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/internal/core/ValidatorUtils.java
new file mode 100644
index 0000000..f3ba8d3
--- /dev/null
+++ b/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/internal/core/ValidatorUtils.java
@@ -0,0 +1,142 @@
+package org.eclipse.dltk.validators.internal.core;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceVisitor;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.dltk.core.DLTKCore;
+import org.eclipse.dltk.core.DLTKLanguageManager;
+import org.eclipse.dltk.core.IDLTKProject;
+import org.eclipse.dltk.core.IModelElement;
+import org.eclipse.dltk.core.IModelElementVisitor;
+import org.eclipse.dltk.core.IParent;
+import org.eclipse.dltk.core.ISourceModule;
+import org.eclipse.dltk.core.ModelException;
+import org.eclipse.dltk.core.search.IDLTKSearchScope;
+import org.eclipse.dltk.core.search.SearchEngine;
+import org.eclipse.dltk.internal.core.BuiltinProjectFragment;
+import org.eclipse.dltk.internal.core.BuiltinSourceModule;
+import org.eclipse.dltk.internal.core.ExternalProjectFragment;
+import org.eclipse.dltk.internal.core.ExternalSourceModule;
+import org.eclipse.dltk.internal.core.util.HandleFactory;
+
+public class ValidatorUtils {
+ private static class ResourceVisitor implements IResourceVisitor {
+ private List resources;
+
+ public ResourceVisitor(List resources) {
+ this.resources = resources;
+ }
+
+ public boolean visit(IResource resource) {
+ if (!this.resources.contains(resource)
+ && resource.getType() == IResource.FILE) {
+ resources.add(resource);
+ return false;
+ }
+ return true;
+ }
+ }
+
+ private static class SourceModuleVisitor implements IModelElementVisitor {
+ private List elements;
+
+ public SourceModuleVisitor(List elements) {
+ this.elements = elements;
+ }
+
+ /**
+ * Visit only external source modules, witch we aren't builded yet.
+ */
+ public boolean visit(IModelElement element) {
+ if (element.getElementType() == IModelElement.PROJECT_FRAGMENT) {
+ if ((element instanceof ExternalProjectFragment)
+ || (element instanceof BuiltinProjectFragment)) {
+ return false;
+ }
+ }
+ if (element.getElementType() == IModelElement.SOURCE_MODULE
+ && !(element instanceof ExternalSourceModule || element instanceof BuiltinSourceModule)) {
+ if (!elements.contains(element)) {
+ elements.add(element);
+ }
+ return false; // do not enter into source module content.
+ }
+ return true;
+ }
+ }
+ public static void processResourcesToElements(Object o, final List elements, final List resources ) {
+ if( o instanceof IResource ) {
+ List els = new ArrayList();
+ ResourceVisitor visitor = new ResourceVisitor(els);
+ try {
+ ((IResource)o).accept(visitor);
+ } catch (CoreException e) {
+ e.printStackTrace();
+ }
+ for (int i = 0; i < els.size(); i++) {
+ Object eo = convertResourceToModelElement(els.get(i));
+ if( eo != null ) {
+ if( eo instanceof IModelElement && !elements.contains(eo) ) {
+ elements.add(eo);
+ }
+ else if( eo instanceof IResource && !resources.contains(eo) ) {
+ resources.add(eo);
+ }
+ }
+ }
+ }
+ else if( o instanceof IModelElement ) {
+ if( o instanceof IParent ) {
+ SourceModuleVisitor visitor = new SourceModuleVisitor(elements);
+ try {
+ ((IModelElement)o).accept(visitor);
+ } catch (ModelException e) {
+ e.printStackTrace();
+ }
+ }
+ else if ( !(o instanceof ISourceModule )) {
+ ISourceModule module = (ISourceModule)((IModelElement)o).getAncestor(IModelElement.SOURCE_MODULE);
+ if( elements.contains(module)) {
+ elements.add(module);
+ }
+ }
+ else if( o instanceof ISourceModule) {
+ if( !elements.contains(o)) {
+ elements.add(o);
+ }
+ }
+ }
+ }
+ private static HandleFactory factory = new HandleFactory();
+ private static Object convertResourceToModelElement( Object o ) {
+ if( o instanceof IModelElement ) {
+ return o;
+ }
+ if( !(o instanceof IResource)) {
+ return null;
+ }
+ IResource res = (IResource)o;
+ IProject project = res.getProject();
+ if( !DLTKLanguageManager.hasScriptNature(project)) {
+ return null; // Lets pass not script projects.
+ }
+ IDLTKProject scriptProject = DLTKCore.create(project);
+ IDLTKSearchScope scope = SearchEngine
+ .createSearchScope(new IModelElement[] { scriptProject });
+
+ IModelElement element = factory.createOpenable(res.getFullPath()
+ .toString(), scope);
+ if (element != null
+ && element.getElementType() == IModelElement.SOURCE_MODULE
+ && element.exists()) {
+// elements.add(element);
+ return element;
+ } else {
+ return res;
+ }
+ }
+}
diff --git a/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/internal/core/ValidatorsCore.java b/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/internal/core/ValidatorsCore.java
new file mode 100644
index 0000000..4e0dded
--- /dev/null
+++ b/core/plugins/org.eclipse.dltk.validators.core/src/org/eclipse/dltk/validators/internal/core/ValidatorsCore.java
@@ -0,0 +1,202 @@
+package org.eclipse.dltk.validators.internal.core;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
+import org.eclipse.core.runtime.Preferences.PropertyChangeEvent;
+import org.eclipse.dltk.validators.core.IValidator;
+import org.eclipse.dltk.validators.core.IValidatorChangedListener;
+import org.eclipse.dltk.validators.core.ValidatorRuntime;
+import org.osgi.framework.BundleContext;
+import org.w3c.dom.Document;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class ValidatorsCore extends Plugin implements IPropertyChangeListener {
+
+ // The plug-in ID
+ public static final String PLUGIN_ID = "org.eclipse.dltk.validators.core";
+
+ // The shared instance
+ private static ValidatorsCore plugin;
+
+ private boolean fIgnoreValidatorDefPropertyChangeEvents = false;
+
+ private boolean fBatchingChanges;
+
+ private static final String EMPTY_STRING = ""; //$NON-NLS-1$
+
+ private String fOldInterpreterPrefString = EMPTY_STRING;
+
+ /**
+ * The constructor
+ */
+ public ValidatorsCore() {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.Plugins#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ plugin = this;
+
+ getPluginPreferences().addPropertyChangeListener(this);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception {
+ plugin = null;
+ super.stop(context);
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static ValidatorsCore getDefault() {
+ return plugin;
+ }
+
+ /**
+ * Returns a Document that can be used to build a DOM tree
+ *
+ * @return the Document
+ * @throws ParserConfigurationException
+ * if an exception occurs creating the document builder
+ */
+ public static Document getDocument() throws ParserConfigurationException {
+ DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder docBuilder = dfactory.newDocumentBuilder();
+ Document doc = docBuilder.newDocument();
+ return doc;
+ }
+
+ public static String serializeDocument(Document doc) throws IOException,
+ TransformerException {
+ ByteArrayOutputStream s = new ByteArrayOutputStream();
+
+ TransformerFactory factory = TransformerFactory.newInstance();
+ Transformer transformer = factory.newTransformer();
+ transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
+
+ DOMSource source = new DOMSource(doc);
+ StreamResult outputTarget = new StreamResult(s);
+ transformer.transform(source, outputTarget);
+
+ return s.toString("UTF8"); //$NON-NLS-1$
+ }
+ public void setIgnoreValidatorDefPropertyChangeEvents(boolean ignore) {
+ fIgnoreValidatorDefPropertyChangeEvents = ignore;
+ }
+
+ public boolean isIgnoreValidatorDefPropertyChangeEvents() {
+ return fIgnoreValidatorDefPropertyChangeEvents;
+ }
+
+ public void propertyChange(PropertyChangeEvent event) {
+ String property = event.getProperty();
+ if (property.equals(ValidatorRuntime.PREF_VALIDATOR_XML)) {
+ if (!isIgnoreValidatorDefPropertyChangeEvents()) {
+ processValidatorPrefsChanged((String) event.getOldValue(),
+ (String) event.getNewValue());
+ }
+ }
+ }
+ private ValidatorDefinitionsContainer getValidatorDefinitions(String xml) {
+ if (xml.length() > 0) {
+ try {
+ ByteArrayInputStream stream = new ByteArrayInputStream(xml
+ .getBytes("UTF8")); //$NON-NLS-1$
+ return ValidatorDefinitionsContainer
+ .parseXMLIntoContainer(stream);
+ } catch (IOException e) {
+ ValidatorsCore.getDefault().getLog().log(new Status( 0, ValidatorsCore.PLUGIN_ID, "Exception", e ));
+ }
+ }
+ return new ValidatorDefinitionsContainer();
+ }
+ protected void processValidatorPrefsChanged(String oldValue,
+ String newValue) {
+
+ // batch changes
+ fBatchingChanges = true;
+ try {
+
+ String oldPrefString;
+ String newPrefString;
+
+ // If empty new value, save the old value and wait for 2nd
+ // propertyChange notification
+ if (newValue == null || newValue.equals(EMPTY_STRING)) {
+ fOldInterpreterPrefString = oldValue;
+ return;
+ }
+ // An empty old value signals the second notification in the import
+ // preferences
+ // sequence. Now that we have both old & new prefs, we can parse and
+ // compare them.
+ else if (oldValue == null || oldValue.equals(EMPTY_STRING)) {
+ oldPrefString = fOldInterpreterPrefString;
+ newPrefString = newValue;
+ }
+ // If both old & new values are present, this is a normal user
+ // change
+ else {
+ oldPrefString = oldValue;
+ newPrefString = newValue;
+ }
+
+ // Generate the previous Interpreters
+ ValidatorDefinitionsContainer oldResults = getValidatorDefinitions(oldPrefString);
+
+ // Generate the current
+ ValidatorDefinitionsContainer newResults = getValidatorDefinitions(newPrefString);
+
+ // Determine the deteled Interpreters
+ List deleted = oldResults.getValidatorList();
+ List current = newResults.getValidatorList();
+ deleted.removeAll(current);
+
+ // Dispose deleted Interpreters. The 'disposeInterpreterInstall'
+ // method fires notification of the
+ // deletion.
+ Iterator deletedIterator = deleted.iterator();
+ while (deletedIterator.hasNext()) {
+ IValidator deletedValidatorStandin = (IValidator) deletedIterator
+ .next();
+ deletedValidatorStandin.getValidatorType()
+ .disposeValidator(
+ deletedValidatorStandin.getID());
+ }
+ } finally {
+ // stop batch changes
+ fBatchingChanges = false;
+ }
+ }
+}