blob: 92871791c77b4272c9312b2ec76081258754910c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2017 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
*
*******************************************************************************/
package org.eclipse.dltk.validators.core;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.Preferences;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.DLTKLanguageManager;
import org.eclipse.dltk.core.IDLTKLanguageToolkit;
import org.eclipse.dltk.core.IModelElement;
import org.eclipse.dltk.core.IScriptProject;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.validators.internal.core.ValidatorDefinitionsContainer;
import org.eclipse.dltk.validators.internal.core.ValidatorManager;
import org.eclipse.dltk.validators.internal.core.ValidatorsCore;
import org.xml.sax.InputSource;
public final class ValidatorRuntime {
public static final String PREF_VALIDATOR_XML = ValidatorsCore.PLUGIN_ID + ".PREF_VALIDATOR_XML"; //$NON-NLS-1$
/**
* EMF validators configuration
*/
public static final String PREF_CONFIGURATION = ValidatorsCore.PLUGIN_ID + ".configuration"; //$NON-NLS-1$
// public static final String MARKER_VALIDATOR = ValidatorsCore.PLUGIN_ID
// + ".marker_validator_id"; //$NON-NLS-1$
// lock for interpreter initialization
private static final Object fgValidatorLock = new Object();
private static boolean fgInitializingValidators = false;
private static boolean isInitialized = false;
//
private static final ListenerList<IValidatorChangedListener> fgValidatorListeners = new ListenerList<>(
ListenerList.IDENTITY);
public static final String ANY_NATURE = "#"; //$NON-NLS-1$
private ValidatorRuntime() {
}
public static IValidatorType getValidatorType(String id) {
IValidatorType[] types = getValidatorTypes();
for (int i = 0; i < types.length; i++) {
if (types[i].getID().equals(id)) {
return types[i];
}
}
return null;
}
public static IValidatorType[] getValidatorTypes() {
initializeValidators();
try {
return ValidatorManager.getAllValidatorTypes();
} catch (CoreException e) {
if (DLTKCore.DEBUG) {
e.printStackTrace();
}
return null;
}
}
public static IValidatorType[] getValidatorTypes(String nature) {
initializeValidators();
try {
return ValidatorManager.getValidators(nature);
} catch (CoreException e) {
if (DLTKCore.DEBUG) {
e.printStackTrace();
}
return null;
}
}
public static void saveValidatorConfiguration() 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, ValidatorsCore.PLUGIN_ID, IStatus.OK,
Messages.ValidatorRuntime_exceptionOccurred, e));
} catch (ParserConfigurationException e) {
throw new CoreException(new Status(IStatus.ERROR, ValidatorsCore.PLUGIN_ID, IStatus.OK,
Messages.ValidatorRuntime_exceptionOccurred, e));
} catch (TransformerException e) {
throw new CoreException(new Status(IStatus.ERROR, ValidatorsCore.PLUGIN_ID, IStatus.OK,
Messages.ValidatorRuntime_exceptionOccurred, e));
}
}
private static String getValidatorsAsXML() throws IOException, ParserConfigurationException, TransformerException {
ValidatorDefinitionsContainer container = new ValidatorDefinitionsContainer();
IValidatorType[] validatorTypes = getValidatorTypes();
for (int i = 0; i < validatorTypes.length; ++i) {
container.addValidators(validatorTypes[i].getValidators());
}
return container.getAsXML();
}
private static boolean addPersistedValidators(ValidatorDefinitionsContainer interpreterDefs) throws IOException {
String validatorXMLString = getPreferences().getString(PREF_VALIDATOR_XML);
if (validatorXMLString.length() > 0) {
try {
interpreterDefs.parseXML(new InputSource(new StringReader(validatorXMLString)));
return false;
} catch (IOException ioe) {
// DLTKLaunchingPlugin.log(ioe);
}
}
return true;
}
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) {
if (isInitialized) {
return;
}
isInitialized = true;
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;
}
// register loaded validators with corresponding types
for (Iterator i = validatorDefs.getValidatorList().iterator(); i.hasNext();) {
final IValidator validator = (IValidator) i.next();
final String typeId = validator.getValidatorType().getID();
for (int j = 0; j < validatorTypes.length; ++j) {
final IValidatorType validatorType = validatorTypes[j];
if (typeId.equals(validatorType.getID())) {
if (validatorType.findValidator(validator.getID()) == null) {
validatorType.addValidator(validator);
}
break;
}
}
}
// 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 removeValidatorChangedListener(IValidatorChangedListener listener) {
fgValidatorListeners.remove(listener);
}
public static void fireValidatorChanged(IValidator validator) {
for (IValidatorChangedListener listener : fgValidatorListeners) {
// IValidatorChangedListener listener = (IValidatorChangedListener)
// listeners[i];
// listener.validatorChanged(validator);
}
}
public static void fireValidatorAdded(IValidator Interpreter) {
if (!fgInitializingValidators) {
for (IValidatorChangedListener listener : fgValidatorListeners) {
// IValidatorChangedListener listener =
// (IValidatorChangedListener) listeners[i];
// listener.validatorAdded(Interpreter);
}
}
}
public static void fireValidatorRemoved(IValidator Interpreter) {
for (IValidatorChangedListener listener : fgValidatorListeners) {
// IValidatorChangedListener listener = (IValidatorChangedListener)
// listeners[i];
// listener.validatorRemoved(Interpreter);
}
}
/**
* Returns array of validator types which are not built-in, i.e. new instances
* of that types could be added by the user.
*
* @return
*/
public static IValidatorType[] getPossibleValidatorTypes() {
List<IValidatorType> possible = new ArrayList<>();
IValidatorType[] vals = getValidatorTypes();
for (int i = 0; i < vals.length; i++) {
if (!vals[i].isBuiltin()) {
possible.add(vals[i]);
}
}
return possible.toArray(new IValidatorType[possible.size()]);
}
public static IValidator[] getAllValidators() {
List<IValidator> 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 (!possible.contains(v[j])) {
possible.add(v[j]);
}
}
}
return possible.toArray(new IValidator[possible.size()]);
}
private static ISourceModule[] filterModulesForValidator(List elements, IValidator v, IProgressMonitor monitor) {
final List<ISourceModule> result = new ArrayList<>();
final String nature = v.getValidatorType().getNature();
for (Iterator iterator = elements.iterator(); iterator.hasNext();) {
IModelElement el = (IModelElement) iterator.next();
if (el instanceof ISourceModule) {
ISourceModule module = (ISourceModule) el;
IDLTKLanguageToolkit toolkit = null;
toolkit = DLTKLanguageManager.getLanguageToolkit(module);
if (toolkit != null && toolkit.getNatureId().equals(nature) || nature.equals(ANY_NATURE)) {
result.add(module);
}
}
}
return result.toArray(new ISourceModule[result.size()]);
}
public static void executeCleanAllValidatorsWithConsole(List elements, List resources) {
executeCleanAllValidatorsWithConsole(elements, resources);
}
/**
* @deprecated
*/
@Deprecated
public static final IValidatorPredicate AUTOMATIC = validator -> validator.isAutomatic();
public static class AutomaticValidatorPredicate implements IValidatorPredicate {
private final IScriptProject project;
public AutomaticValidatorPredicate(IScriptProject project) {
this.project = project;
}
@Override
public boolean evaluate(IValidator validator) {
return validator.isAutomatic(project);
}
}
public static final IValidatorPredicate ALL = validator -> true;
public static IValidator[] getProjectValidators(IScriptProject project, Class validatorType,
IValidatorPredicate predicate) {
String[] natureIds;
try {
natureIds = project.getProject().getDescription().getNatureIds();
} catch (CoreException e) {
ValidatorsCore.log(e.getStatus());
natureIds = new String[0];
}
final List<IValidator> result = new ArrayList();
final IValidatorType[] types = ValidatorRuntime.getValidatorTypes();
for (int i = 0; i < types.length; ++i) {
final IValidatorType type = types[i];
if (checkValidatorTypeNature(type, natureIds) && type.supports(validatorType)) {
final IValidator[] validators = type.getValidators();
for (int j = 0; j < validators.length; ++j) {
final IValidator validator = validators[j];
if (predicate.evaluate(validator) && validator.isValidatorValid(project)) {
result.add(validator);
}
}
}
}
return result.toArray(new IValidator[result.size()]);
}
/**
* @param type
* @param natureIds
* @return
*/
private static boolean checkValidatorTypeNature(IValidatorType type, String[] natureIds) {
final String natureId = type.getNature();
if (ANY_NATURE.equals(natureId)) {
return true;
}
for (int i = 0; i < natureIds.length; ++i) {
if (natureId.equals(natureIds[i])) {
return true;
}
}
return false;
}
public static IStatus executeSourceModuleValidators(IScriptProject project, List sourceModules,
IValidatorOutput output, IValidatorPredicate predicate, IProgressMonitor monitor) {
final IValidator[] validators = getProjectValidators(project, ISourceModuleValidator.class, predicate);
if (validators.length != 0) {
return executeSourceModuleValidators(project, sourceModules, output, validators, monitor);
}
return Status.OK_STATUS;
}
public static IStatus executeSourceModuleValidators(IScriptProject project, List sourceModules,
IValidatorOutput output, final IValidator[] validators, IProgressMonitor monitor) {
monitor.beginTask(Messages.ValidatorRuntime_runningValidators, validators.length * 100);
for (int i = 0; i < validators.length; ++i) {
if (monitor.isCanceled()) {
return Status.CANCEL_STATUS;
}
final IValidator validator = validators[i];
final ISourceModuleValidator mValidator = (ISourceModuleValidator) validator.getValidator(project,
ISourceModuleValidator.class);
if (mValidator != null) {
final ISourceModule[] mArray = filterModulesForValidator(sourceModules, validator, monitor);
if (monitor.isCanceled()) {
return Status.CANCEL_STATUS;
}
final IProgressMonitor submonitor = new SubProgressMonitor(monitor, 100);
if (mArray.length != 0) {
mValidator.validate(mArray, output, submonitor);
}
submonitor.done();
}
}
monitor.done();
return Status.OK_STATUS;
}
public static IStatus executeAutomaticResourceValidators(IScriptProject project, List resources,
IValidatorOutput output, IProgressMonitor monitor) {
return executeResourceValidators(project, resources, output, new AutomaticValidatorPredicate(project), monitor);
}
public static IStatus executeResourceValidators(IScriptProject project, List resources, IValidatorOutput output,
IValidatorPredicate predicate, IProgressMonitor monitor) {
final IValidator[] validators = getProjectValidators(project, IResourceValidator.class, predicate);
if (validators.length != 0) {
final IResource[] resArray = (IResource[]) resources.toArray(new IResource[resources.size()]);
monitor.beginTask(Messages.ValidatorRuntime_runningValidators, validators.length * 100);
for (int i = 0; i < validators.length; ++i) {
if (monitor.isCanceled()) {
return Status.CANCEL_STATUS;
}
final IValidator validator = validators[i];
final IResourceValidator resourceValidator = (IResourceValidator) validator.getValidator(project,
IResourceValidator.class);
if (resourceValidator != null) {
final IProgressMonitor submonitor = new SubProgressMonitor(monitor, 100);
resourceValidator.validate(resArray, output, submonitor);
submonitor.done();
}
}
monitor.done();
}
return Status.OK_STATUS;
}
/**
* @param project
* @param modules
* @param resources
* @param monitor
*/
public static void cleanAll(IScriptProject project, ISourceModule[] modules, IResource[] resources,
IProgressMonitor monitor) {
final IValidatorType[] types = ValidatorRuntime.getValidatorTypes();
for (int i = 0; i < types.length; ++i) {
final IValidatorType type = types[i];
final IValidator[] validators = type.getValidators();
for (int j = 0; j < validators.length; ++j) {
final IValidator validator = validators[j];
final ISourceModuleValidator smValidator = (ISourceModuleValidator) validator.getValidator(project,
ISourceModuleValidator.class);
if (smValidator != null) {
smValidator.clean(modules);
}
final IResourceValidator rValidator = (IResourceValidator) validator.getValidator(project,
IResourceValidator.class);
if (rValidator != null) {
rValidator.clean(resources);
}
}
}
}
public static void fireValidatorChanged() {
synchronized (fgValidatorLock) {
isInitialized = false;
}
Object[] listeners = fgValidatorListeners.getListeners();
for (int i = 0; i < listeners.length; i++) {
IValidatorChangedListener listener = (IValidatorChangedListener) listeners[i];
listener.validatorChanged();
}
}
}