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

org.eclipse.core.internal.content.ContentTypeBuilder 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) 2004, 2017 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
 *     Mickael Istria (Red Hat Inc.) - [263316] regexp for file association
 *******************************************************************************/
package org.eclipse.core.internal.content;

import java.util.*;
import org.eclipse.core.internal.runtime.RuntimeLog;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.content.IContentDescription;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IScopeContext;
import org.eclipse.osgi.util.NLS;
import org.osgi.service.prefs.BackingStoreException;

/**
 * This class is a sidekick for ContentTypeManager that provides mechanisms for
 * creating content types from the extension registry (which ContentTypeManager
 *  is oblivious to).
 */
public class ContentTypeBuilder {
	public static final String PT_CONTENTTYPES = "contentTypes"; //$NON-NLS-1$
	private ContentTypeCatalog catalog;

	private static String getUniqueId(String namespace, String baseTypeId) {
		if (baseTypeId == null)
			return null;
		int separatorPosition = baseTypeId.lastIndexOf('.');
		// base type is defined in the same namespace
		if (separatorPosition == -1)
			baseTypeId = namespace + '.' + baseTypeId;
		return baseTypeId;
	}

	private static QualifiedName parseQualifiedName(String namespace, String value) {
		if (value == null)
			return null;
		int separatorPosition = value.lastIndexOf('.');
		// base type is defined in the same namespace
		if (separatorPosition == -1)
			return new QualifiedName(namespace, value);
		if (separatorPosition == 0 || separatorPosition == value.length() - 1)
			// invalid value specified
			return null;
		namespace = value.substring(0, separatorPosition);
		String simpleValue = value.substring(separatorPosition + 1);
		return new QualifiedName(namespace, simpleValue);
	}

	private static byte parsePriority(String priority) {
		if (priority == null)
			return ContentType.PRIORITY_NORMAL;
		if ("high".equals(priority)) //$NON-NLS-1$
			return ContentType.PRIORITY_HIGH;
		if ("low".equals(priority)) //$NON-NLS-1$
			return ContentType.PRIORITY_LOW;
		if (!"normal".equals(priority)) //$NON-NLS-1$
			return ContentType.PRIORITY_NORMAL;
		//TODO: should log - INVALID PRIORITY
		return ContentType.PRIORITY_NORMAL;
	}

	protected ContentTypeBuilder(ContentTypeCatalog catalog) {
		this.catalog = catalog;
	}

	private void addFileAssociation(IConfigurationElement fileAssociationElement, ContentType target) {
		String[] fileNames = Util.parseItems(fileAssociationElement.getAttribute("file-names")); //$NON-NLS-1$
		for (String fileName : fileNames)
			target.internalAddFileSpec(fileName, IContentType.FILE_NAME_SPEC | ContentType.SPEC_PRE_DEFINED);
		String[] fileExtensions = Util.parseItems(fileAssociationElement.getAttribute("file-extensions")); //$NON-NLS-1$
		for (String fileExtension : fileExtensions)
			target.internalAddFileSpec(fileExtension, IContentType.FILE_EXTENSION_SPEC | ContentType.SPEC_PRE_DEFINED);
		String[] filePatterns = Util.parseItems(fileAssociationElement.getAttribute("file-patterns")); //$NON-NLS-1$
		for (String filePattern : filePatterns)
			target.internalAddFileSpec(filePattern, IContentType.FILE_PATTERN_SPEC | ContentType.SPEC_PRE_DEFINED);
	}

	/**
	 * Builds all content types found in the extension registry.
	 */
	public void buildCatalog(IScopeContext context) {
		IConfigurationElement[] allContentTypeCEs = getConfigurationElements();
		for (IConfigurationElement allContentTypeCE : allContentTypeCEs)
			if ("content-type".equals(allContentTypeCE.getName())) //$NON-NLS-1$
				registerContentType(allContentTypeCE);
		for (String id : ContentTypeManager.getUserDefinedContentTypeIds(context)) {
			IEclipsePreferences node = context.getNode(id);
			catalog.addContentType(ContentType.createContentType(catalog, id,
					node.get(ContentType.PREF_USER_DEFINED__NAME, ContentType.EMPTY_STRING),
					(byte) 0, new String[0], new String[0], new String[0],
					node.get(ContentType.PREF_USER_DEFINED__BASE_TYPE_ID, null), null, Collections.emptyMap(),
					null));
		}
		for (IConfigurationElement allContentTypeCE : allContentTypeCEs)
			if ("file-association".equals(allContentTypeCE.getName())) //$NON-NLS-1$
				registerFileAssociation(allContentTypeCE);
		applyPreferences();
	}

	/**
	 * Applies any existing preferences to content types as a batch operation.
	 */
	private void applyPreferences() {
		try {
			final ContentTypeCatalog localCatalog = catalog;
			final IEclipsePreferences root = localCatalog.getManager().getPreferences();
			root.accept(node -> {
				if (node == root)
					return true;
				ContentType contentType = localCatalog.internalGetContentType(node.name());
				if (contentType != null)
					contentType.processPreferences(node);
				// content type nodes don't have any children anyway
				return false;
			});
		} catch (BackingStoreException bse) {
			ContentType.log(ContentMessages.content_errorLoadingSettings, bse);
		}
	}

	/**
	 * @throws CoreException if mandatory attributes are missing in the markup
	 */
	private ContentType createContentType(IConfigurationElement contentTypeCE) throws CoreException {
		String namespace = contentTypeCE.getContributor().getName();
		String simpleId = contentTypeCE.getAttribute("id"); //$NON-NLS-1$
		String name = contentTypeCE.getAttribute("name"); //$NON-NLS-1$

		if (simpleId == null)
			missingMandatoryAttribute(ContentMessages.content_missingIdentifier, namespace);
		String uniqueId;
		if (simpleId.lastIndexOf('.') == -1)
			uniqueId = namespace + '.' + simpleId;
		else
			uniqueId = simpleId;
		if (name == null)
			missingMandatoryAttribute(ContentMessages.content_missingName, uniqueId);

		byte priority = parsePriority(contentTypeCE.getAttribute("priority")); //$NON-NLS-1$ );
		String[] fileNames = Util.parseItems(contentTypeCE.getAttribute("file-names")); //$NON-NLS-1$
		String[] fileExtensions = Util.parseItems(contentTypeCE.getAttribute("file-extensions")); //$NON-NLS-1$
		String[] filePatterns = Util.parseItems(contentTypeCE.getAttribute("file-patterns")); //$NON-NLS-1$
		String baseTypeId = getUniqueId(namespace, contentTypeCE.getAttribute("base-type")); //$NON-NLS-1$
		String aliasTargetTypeId = getUniqueId(namespace, contentTypeCE.getAttribute("alias-for")); //$NON-NLS-1$
		IConfigurationElement[] propertyCEs = null;
		Map defaultProperties = null;
		if ((propertyCEs = contentTypeCE.getChildren("property")).length > 0) { //$NON-NLS-1$
			defaultProperties = new HashMap<>();
			for (IConfigurationElement propertyCE : propertyCEs) {
				String defaultValue = propertyCE.getAttribute("default"); //$NON-NLS-1$
				if (defaultValue == null)
					// empty string means: default value is null
					defaultValue = ""; //$NON-NLS-1$
				String propertyKey = propertyCE.getAttribute("name"); //$NON-NLS-1$
				QualifiedName qualifiedKey = parseQualifiedName(namespace, propertyKey);
				if (qualifiedKey == null) {
					if (ContentTypeManager.DebuggingHolder.DEBUGGING) {
						String message = NLS.bind(ContentMessages.content_invalidProperty, propertyKey, getUniqueId(namespace, simpleId));
						ContentType.log(message, null);
					}
					continue;
				}
				defaultProperties.put(qualifiedKey, defaultValue);
			}
		}
		String defaultCharset = contentTypeCE.getAttribute("default-charset"); //$NON-NLS-1$
		if (defaultCharset != null)
			if (defaultProperties == null)
				defaultProperties = Collections.singletonMap(IContentDescription.CHARSET, defaultCharset);
			else
				defaultProperties.putIfAbsent(IContentDescription.CHARSET, defaultCharset);
		return ContentType.createContentType(catalog, uniqueId, name, priority, fileExtensions, fileNames, filePatterns,
				baseTypeId, aliasTargetTypeId, defaultProperties, contentTypeCE);
	}

	// Store this around for performance
	private final static IConfigurationElement[] emptyConfArray = new IConfigurationElement[0];

	/**
	 * Gets configuration elements for both "backward compatible" extension point
	 * 		org.eclipse.core.runtime.contentTypes
	 * and "new" extension point controlled by this plugin:
	 * 		org.eclipse.core.contenttype.contentTypes
	 */
	protected IConfigurationElement[] getConfigurationElements() {
		IExtensionRegistry registry = RegistryFactory.getRegistry();
		if (registry == null)
			return emptyConfArray;
		IConfigurationElement[] oldConfigElements = emptyConfArray;
		IConfigurationElement[] newConfigElements = emptyConfArray;
		// "old" extension point
		IExtensionPoint oldPoint = registry.getExtensionPoint(IContentConstants.RUNTIME_NAME, PT_CONTENTTYPES);
		if (oldPoint != null)
			oldConfigElements = oldPoint.getConfigurationElements();
		// "new" extension point
		IExtensionPoint newPoint = registry.getExtensionPoint(IContentConstants.CONTENT_NAME, PT_CONTENTTYPES);
		if (newPoint != null)
			newConfigElements = newPoint.getConfigurationElements();

		IConfigurationElement[] allContentTypeCEs = new IConfigurationElement[oldConfigElements.length + newConfigElements.length];
		System.arraycopy(oldConfigElements, 0, allContentTypeCEs, 0, oldConfigElements.length);
		System.arraycopy(newConfigElements, 0, allContentTypeCEs, oldConfigElements.length, newConfigElements.length);

		return allContentTypeCEs;
	}

	private void missingMandatoryAttribute(String messageKey, String argument) throws CoreException {
		String message = NLS.bind(messageKey, argument);
		throw new CoreException(new Status(IStatus.ERROR, ContentMessages.OWNER_NAME, 0, message, null));
	}

	private void registerContentType(IConfigurationElement contentTypeCE) {
		try {
			ContentType contentType = createContentType(contentTypeCE);
			catalog.addContentType(contentType);
		} catch (CoreException e) {
			// failed validation
			RuntimeLog.log(e.getStatus());
		}
	}

	/* Adds extra file associations to existing content types. If the content
	 * type has not been added, the file association is ignored.
	 */
	private void registerFileAssociation(IConfigurationElement fileAssociationElement) {
		//TODO: need to ensure the config. element is valid
		String contentTypeId = getUniqueId(fileAssociationElement.getContributor().getName(), fileAssociationElement.getAttribute("content-type")); //$NON-NLS-1$
		ContentType target = catalog.internalGetContentType(contentTypeId);
		if (target == null)
			return;
		addFileAssociation(fileAssociationElement, target);
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy