All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.core.internal.resources.PathVariableManager Maven / Gradle / Ivy

Go to download

AspectJ tools most notably contains the AspectJ compiler (AJC). AJC applies aspects to Java classes during compilation, fully replacing Javac for plain Java classes and also compiling native AspectJ or annotation-based @AspectJ syntax. Furthermore, AJC can weave aspects into existing class files in a post-compile binary weaving step. This library is a superset of AspectJ weaver and hence also of AspectJ runtime.

There is a newer version: 1.9.22.1
Show newest version
/*******************************************************************************
 * Copyright (c) 2000, 2015 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     James Blackburn (Broadcom Corp.) - ongoing development
 *     Lars Vogel  - Bug 473427
 *******************************************************************************/
package org.eclipse.core.internal.resources;

import java.net.URI;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.core.internal.events.PathVariableChangeEvent;
import org.eclipse.core.internal.utils.FileUtil;
import org.eclipse.core.internal.utils.Messages;
import org.eclipse.core.resources.IPathVariableChangeEvent;
import org.eclipse.core.resources.IPathVariableChangeListener;
import org.eclipse.core.resources.IPathVariableManager;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceStatus;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Preferences;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.core.runtime.Status;
import org.eclipse.osgi.util.NLS;

/**
 * Core's implementation of IPathVariableManager.
 */
public class PathVariableManager implements IPathVariableManager, IManager {

	static final String VARIABLE_PREFIX = "pathvariable."; //$NON-NLS-1$
	private Set listeners;
	private Map> projectListeners;

	private Preferences preferences;

	/**
	 * Constructor for the class.
	 */
	public PathVariableManager() {
		this.listeners = Collections.synchronizedSet(new HashSet<>());
		this.projectListeners = Collections.synchronizedMap(new HashMap<>());
		this.preferences = ResourcesPlugin.getPlugin().getPluginPreferences();
	}

	/**
	 * @see org.eclipse.core.resources.IPathVariableManager#addChangeListener(IPathVariableChangeListener)
	 */
	@Override
	public void addChangeListener(IPathVariableChangeListener listener) {
		listeners.add(listener);
	}

	synchronized public void addChangeListener(IPathVariableChangeListener listener, IProject project) {
		Collection list = projectListeners.get(project);
		if (list == null) {
			list = Collections.synchronizedSet(new HashSet<>());
			projectListeners.put(project, list);
		}
		list.add(listener);
	}

	/**
	 * Throws a runtime exception if the given name is not valid as a path
	 * variable name.
	 */
	private void checkIsValidName(String name) throws CoreException {
		IStatus status = validateName(name);
		if (!status.isOK())
			throw new CoreException(status);
	}

	/**
	 * Throws an exception if the given path is not valid as a path variable
	 * value.
	 */
	private void checkIsValidValue(IPath newValue) throws CoreException {
		IStatus status = validateValue(newValue);
		if (!status.isOK())
			throw new CoreException(status);
	}

	/**
	 * Fires a property change event corresponding to a change to the
	 * current value of the variable with the given name.
	 *
	 * @param name the name of the variable, to be used as the variable
	 *      in the event object
	 * @param value the current value of the path variable or null if
	 *      the variable was deleted
	 * @param type one of IPathVariableChangeEvent.VARIABLE_CREATED,
	 *      IPathVariableChangeEvent.VARIABLE_CHANGED, or
	 *      IPathVariableChangeEvent.VARIABLE_DELETED
	 * @see IPathVariableChangeEvent
	 * @see IPathVariableChangeEvent#VARIABLE_CREATED
	 * @see IPathVariableChangeEvent#VARIABLE_CHANGED
	 * @see IPathVariableChangeEvent#VARIABLE_DELETED
	 */
	private void fireVariableChangeEvent(String name, IPath value, int type) {
		fireVariableChangeEvent(this.listeners, name, value, type);
	}

	private void fireVariableChangeEvent(Collection list, String name, IPath value, int type) {
		if (list.isEmpty())
			return;
		// use a separate collection to avoid interference of simultaneous additions/removals
		IPathVariableChangeListener[] listenerArray = list.toArray(new IPathVariableChangeListener[list.size()]);
		final PathVariableChangeEvent pve = new PathVariableChangeEvent(this, name, value, type);
		for (final IPathVariableChangeListener listener : listenerArray) {
			ISafeRunnable job = new ISafeRunnable() {
				@Override
				public void handleException(Throwable exception) {
					// already being logged in SafeRunner#run()
				}

				@Override
				public void run() throws Exception {
					listener.pathVariableChanged(pve);
				}
			};
			SafeRunner.run(job);
		}
	}

	public void fireVariableChangeEvent(IProject project, String name, IPath value, int type) {
		Collection list = projectListeners.get(project);
		if (list != null)
			fireVariableChangeEvent(list, name, value, type);
	}

	/**
	 * Return a key to use in the Preferences.
	 */
	private String getKeyForName(String varName) {
		return VARIABLE_PREFIX + varName;
	}

	/**
	 * @see org.eclipse.core.resources.IPathVariableManager#getPathVariableNames()
	 */
	@Override
	public String[] getPathVariableNames() {
		List result = new LinkedList<>();
		String[] names = preferences.propertyNames();
		for (String name : names) {
			if (name.startsWith(VARIABLE_PREFIX)) {
				String key = name.substring(VARIABLE_PREFIX.length());
				// filter out names for preferences which might be valid in the
				// preference store but does not have valid path variable names
				// and/or values. We can get in this state if the user has
				// edited the file on disk or set a preference using the prefix
				// reserved to path variables (#VARIABLE_PREFIX).
				// TODO: we may want to look at removing these keys from the
				// preference store as a garbage collection means
				if (validateName(key).isOK() && validateValue(getValue(key)).isOK())
					result.add(key);
			}
		}
		return result.toArray(new String[result.size()]);
	}

	/**
	 * Note that if a user changes the key in the preferences file to be invalid
	 * and then calls #getValue using that key, they will get the value back for
	 * that. But then if they try and call #setValue using the same key it will throw
	 * an exception. We may want to revisit this behaviour in the future.
	 *
	 * @see org.eclipse.core.resources.IPathVariableManager#getValue(String)
	 */
	@Deprecated
	@Override
	public IPath getValue(String varName) {
		String key = getKeyForName(varName);
		String value = preferences.getString(key);
		return value.length() == 0 ? null : IPath.fromPortableString(value);
	}

	/**
	 * @see org.eclipse.core.resources.IPathVariableManager#isDefined(String)
	 */
	@Override
	public boolean isDefined(String varName) {
		return getValue(varName) != null;
	}

	/**
	 * @see org.eclipse.core.resources.IPathVariableManager#removeChangeListener(IPathVariableChangeListener)
	 */
	@Override
	public void removeChangeListener(IPathVariableChangeListener listener) {
		listeners.remove(listener);
	}

	synchronized public void removeChangeListener(IPathVariableChangeListener listener, IProject project) {
		Collection list = projectListeners.get(project);
		if (list != null) {
			list.remove(listener);
			if (list.isEmpty())
				projectListeners.remove(project);
		}
	}

	/**
	 * @see org.eclipse.core.resources.IPathVariableManager#resolvePath(IPath)
	 */
	@Deprecated
	@Override
	public IPath resolvePath(IPath path) {
		if (path == null || path.segmentCount() == 0 || path.isAbsolute() || path.getDevice() != null)
			return path;
		IPath value = getValue(path.segment(0));
		return value == null ? path : value.append(path.removeFirstSegments(1));
	}

	@Override
	public URI resolveURI(URI uri) {
		if (uri == null || uri.isAbsolute())
			return uri;
		String schemeSpecificPart = uri.getSchemeSpecificPart();
		if (schemeSpecificPart == null || schemeSpecificPart.isEmpty()) {
			return uri;
		}
		IPath raw = IPath.fromOSString(schemeSpecificPart);
		IPath resolved = resolvePath(raw);
		return raw == resolved ? uri : URIUtil.toURI(resolved);
	}

	/**
	 * @see org.eclipse.core.resources.IPathVariableManager#setValue(String, IPath)
	 */
	@Override
	public void setValue(String varName, IPath newValue) throws CoreException {
		checkIsValidName(varName);
		//convert path value to canonical form
		if (newValue != null && newValue.isAbsolute())
			newValue = FileUtil.canonicalPath(newValue);
		checkIsValidValue(newValue);
		int eventType;
		// read previous value and set new value atomically in order to generate the right event
		synchronized (this) {
			IPath currentValue = getValue(varName);
			boolean variableExists = currentValue != null;
			if (!variableExists && newValue == null)
				return;
			if (variableExists && currentValue.equals(newValue))
				return;
			if (newValue == null) {
				preferences.setToDefault(getKeyForName(varName));
				eventType = IPathVariableChangeEvent.VARIABLE_DELETED;
			} else {
				preferences.setValue(getKeyForName(varName), newValue.toPortableString());
				eventType = variableExists ? IPathVariableChangeEvent.VARIABLE_CHANGED : IPathVariableChangeEvent.VARIABLE_CREATED;
			}
		}
		// notify listeners from outside the synchronized block to avoid deadlocks
		fireVariableChangeEvent(varName, newValue, eventType);
	}

	/**
	 * @see org.eclipse.core.internal.resources.IManager#shutdown(IProgressMonitor)
	 */
	@Override
	public void shutdown(IProgressMonitor monitor) {
		// The preferences for this plug-in are saved in the Plugin.shutdown
		// method so we don't have to do it here.
	}

	/**
	 * @see org.eclipse.core.internal.resources.IManager#startup(IProgressMonitor)
	 */
	@Override
	public void startup(IProgressMonitor monitor) {
		// since we are accessing the preference store directly, we don't
		// need to do any setup here.
	}

	/**
	 * @see org.eclipse.core.resources.IPathVariableManager#validateName(String)
	 */
	@Override
	public IStatus validateName(String name) {
		String message = null;
		if (name.length() == 0) {
			message = Messages.pathvar_length;
			return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
		}

		char first = name.charAt(0);
		if (!Character.isLetter(first) && first != '_') {
			message = NLS.bind(Messages.pathvar_beginLetter, String.valueOf(first));
			return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
		}

		for (int i = 1; i < name.length(); i++) {
			char following = name.charAt(i);
			if (Character.isWhitespace(following))
				return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, Messages.pathvar_whitespace);
			if (!Character.isLetter(following) && !Character.isDigit(following) && following != '_') {
				message = NLS.bind(Messages.pathvar_invalidChar, String.valueOf(following));
				return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
			}
		}
		return Status.OK_STATUS;
	}

	/**
	 * @see IPathVariableManager#validateValue(IPath)
	 */
	@Override
	public IStatus validateValue(IPath value) {
		if (value != null && (!value.isValidPath(value.toString()) || !value.isAbsolute())) {
			String message = Messages.pathvar_invalidValue;
			return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
		}
		return Status.OK_STATUS;
	}

	/**
	 * @see IPathVariableManager#convertToRelative(URI, boolean, String)
	 */
	@Override
	public URI convertToRelative(URI path, boolean force, String variableHint) throws CoreException {
		return PathVariableUtil.convertToRelative(this, path, null, false, variableHint);
	}

	/**
	 * see IPathVariableManager#getURIValue(String)
	 */
	@Override
	public URI getURIValue(String name) {
		IPath path = getValue(name);
		if (path != null)
			return URIUtil.toURI(path);
		return null;
	}

	/**
	 * see IPathVariableManager#setURIValue(String, URI)
	 */
	@Override
	public void setURIValue(String name, URI value) throws CoreException {
		setValue(name, (value != null ? URIUtil.toPath(value) : null));
	}

	/**
	 * @see IPathVariableManager#validateValue(URI)
	 */
	@Override
	public IStatus validateValue(URI path) {
		return validateValue(path != null ? URIUtil.toPath(path) : (IPath) null);
	}

	public URI resolveURI(URI uri, IResource resource) {
		return resolveURI(uri);
	}

	public String[] getPathVariableNames(IResource resource) {
		return getPathVariableNames();
	}

	@Override
	public URI getVariableRelativePathLocation(URI location) {
		try {
			URI result = convertToRelative(location, false, null);
			if (!result.equals(location))
				return result;
		} catch (CoreException e) {
			// handled by returning null
		}
		return null;
	}

	/**
	 * @see IPathVariableManager#convertToUserEditableFormat(String, boolean)
	 */
	@Override
	public String convertToUserEditableFormat(String value, boolean locationFormat) {
		return PathVariableUtil.convertToUserEditableFormatInternal(value, locationFormat);
	}

	@Override
	public String convertFromUserEditableFormat(String userFormat, boolean locationFormat) {
		return PathVariableUtil.convertFromUserEditableFormatInternal(this, userFormat, locationFormat);
	}

	@Override
	public boolean isUserDefined(String name) {
		return ProjectVariableProviderManager.getDefault().findDescriptor(name) == null;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy