/******************************************************************************* * Copyright (c) 2006, 2011 Spring IDE Developers * 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: * Spring IDE Developers - initial API and implementation *******************************************************************************/ package org.springframework.ide.eclipse.beans.ui.namespaces; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Properties; import java.util.Set; import java.util.regex.Matcher; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtension; import org.eclipse.core.runtime.IExtensionPoint; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.IContentProvider; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.ImageData; import org.springframework.ide.eclipse.beans.core.BeansCorePlugin; import org.springframework.ide.eclipse.beans.core.model.INamespaceDefinitionResolver; import org.springframework.ide.eclipse.beans.ui.BeansUIImages; import org.springframework.ide.eclipse.beans.ui.BeansUIPlugin; import org.springframework.ide.eclipse.beans.ui.namespaces.DefaultNamespaceDefinition.Version; import org.springframework.ide.eclipse.core.model.ISourceModelElement; import org.springframework.ide.eclipse.core.model.ModelUtils; import org.springframework.util.StringUtils; /** * Some helper methods. * @author Torsten Juergeleit * @author Christian Dupuis */ public class NamespaceUtils { public static final String NAMESPACES_EXTENSION_POINT = BeansUIPlugin.PLUGIN_ID + ".namespaces"; public static final String DEFAULT_NAMESPACE_URI = "http://www.springframework.org/schema/beans"; public static final String TOOLS_NAMESPACE_URI = "http://www.springframework.org/schema/tool"; public static final String P_NAMESPACE_URI = "http://www.springframework.org/schema/p"; public static final String C_NAMESPACE_URI = "http://www.springframework.org/schema/c"; private static final Object IMAGE_REGISTRY_LOCK = new Object(); private static final INamespaceDefinition P_NAMESPACE_DEFINITION = new DefaultNamespaceDefinition("p", P_NAMESPACE_URI, null, new DefaultImageAccessor(BeansUIPlugin.PLUGIN_ID, "/icons/full/obj16/property_obj.gif")); private static final INamespaceDefinition C_NAMESPACE_DEFINITION = new DefaultNamespaceDefinition("c", C_NAMESPACE_URI, null, new DefaultImageAccessor(BeansUIPlugin.PLUGIN_ID, "/icons/full/obj16/constructor_obj.gif")); /** * Returns the namespace URI for the given {@link ISourceModelElement} or * <code>"http://www.springframework.org/schema/beans"</code> if no namespace URI found. */ public static String getNameSpaceURI(ISourceModelElement element) { String namespaceURI = ModelUtils.getNameSpaceURI(element); if (namespaceURI == null) { namespaceURI = DEFAULT_NAMESPACE_URI; } return namespaceURI; } /** * Returns the {@link INamespaceLabelProvider} for the given {@link ISourceModelElement}'s namespace. */ public static INamespaceLabelProvider getLabelProvider(ISourceModelElement element) { IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(NAMESPACES_EXTENSION_POINT); if (point != null) { String namespaceURI = getNameSpaceURI(element); for (IExtension extension : point.getExtensions()) { for (IConfigurationElement config : extension.getConfigurationElements()) { if (namespaceURI.equals(config.getAttribute("uri"))) { if (config.getAttribute("labelProvider") != null) { try { Object provider = config.createExecutableExtension("labelProvider"); if (provider instanceof INamespaceLabelProvider) { return (INamespaceLabelProvider) provider; } } catch (CoreException e) { BeansUIPlugin.log(e); } } return null; } } } } return null; } /** * Returns the {@link ITreeContentProvider} for the given {@link ISourceModelElement}'s namespace. */ public static ITreeContentProvider getContentProvider(ISourceModelElement element) { IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(NAMESPACES_EXTENSION_POINT); if (point != null) { String namespaceURI = getNameSpaceURI(element); for (IExtension extension : point.getExtensions()) { for (IConfigurationElement config : extension.getConfigurationElements()) { if (namespaceURI.equals(config.getAttribute("uri"))) { if (config.getAttribute("contentProvider") != null) { try { Object provider = config.createExecutableExtension("contentProvider"); if (provider instanceof IContentProvider) { return (ITreeContentProvider) provider; } } catch (CoreException e) { BeansUIPlugin.log(e); } } return null; } } } } return null; } public static List<INamespaceDefinition> getNamespaceDefinitions() { return getNamespaceDefinitions(null); } public static List<INamespaceDefinition> getNamespaceDefinitions(final IProject project, final INamespaceDefinitionTemplate definitionTemplate) { if (definitionTemplate != null) { Job namespaceDefinitionJob = new Job((project != null ? String.format( "Loading namespaces for project '%s'", project.getName()) : "Loading namespaces")) { @Override protected IStatus run(IProgressMonitor monitor) { List<INamespaceDefinition> namespaceDefinitions = getNamespaceDefinitions(project); definitionTemplate.doWithNamespaceDefinitions((INamespaceDefinition[]) namespaceDefinitions .toArray(new INamespaceDefinition[namespaceDefinitions.size()]), project); return Status.OK_STATUS; } }; namespaceDefinitionJob.setPriority(Job.INTERACTIVE); namespaceDefinitionJob.schedule(); return Collections.emptyList(); } return getNamespaceDefinitions(project); } protected static List<INamespaceDefinition> getNamespaceDefinitions(IProject project) { List<INamespaceDefinition> namespaceDefinitions = new ArrayList<INamespaceDefinition>(); INamespaceDefinitionResolver definitionResolver = BeansCorePlugin.getNamespaceDefinitionResolver(project); Set<org.springframework.ide.eclipse.beans.core.model.INamespaceDefinition> detectedNamespaceDefinitions = definitionResolver .getNamespaceDefinitions(); IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(NAMESPACES_EXTENSION_POINT); if (point != null && !org.springframework.ide.eclipse.beans.core.namespaces.NamespaceUtils .useNamespacesFromClasspath(project)) { for (IExtension extension : point.getExtensions()) { for (IConfigurationElement config : extension.getConfigurationElements()) { String uri = config.getAttribute("uri"); org.springframework.ide.eclipse.beans.core.model.INamespaceDefinition namespaceDefinition = definitionResolver .resolveNamespaceDefinition(uri); detectedNamespaceDefinitions.remove(namespaceDefinition); String prefix = config.getAttribute("prefix"); if (!StringUtils.hasText(prefix) && namespaceDefinition != null) { prefix = namespaceDefinition.getPrefix(); } String schemaLocation = config.getAttribute("defaultSchemaLocation"); if (!StringUtils.hasText(schemaLocation) && namespaceDefinition != null) { schemaLocation = namespaceDefinition.getDefaultSchemaLocation(); } IImageAccessor image = null; if (config.getAttribute("icon") != null) { String ns = config.getDeclaringExtension().getNamespaceIdentifier(); String icon = config.getAttribute("icon"); image = new DefaultImageAccessor(ns, icon); } else if (namespaceDefinition != null) { image = new NamespaceDefinitionImageAccessor(namespaceDefinition); } DefaultNamespaceDefinition def = null; if (namespaceDefinition != null) { def = new DefaultNamespaceDefinition(prefix, uri, schemaLocation, namespaceDefinition.getUriMapping(), image); } else { def = new DefaultNamespaceDefinition(prefix, uri, schemaLocation, new Properties(), image); } // get schema locations from nested child elements IConfigurationElement[] schemaLocationConfigElements = config.getChildren("schemaLocation"); for (IConfigurationElement schemaLocationConfigElement : schemaLocationConfigElements) { def.addSchemaLocation(schemaLocationConfigElement.getAttribute("url")); } if (def.getSchemaLocations().size() == 0 && namespaceDefinition != null) { def.getSchemaLocations().addAll(namespaceDefinition.getSchemaLocations()); } namespaceDefinitions.add(def); } } } for (org.springframework.ide.eclipse.beans.core.model.INamespaceDefinition namespaceDefinition : detectedNamespaceDefinitions) { DefaultNamespaceDefinition def = new DefaultNamespaceDefinition(namespaceDefinition.getPrefix(), namespaceDefinition.getNamespaceUri(), namespaceDefinition.getDefaultSchemaLocation(), namespaceDefinition.getUriMapping(), new NamespaceDefinitionImageAccessor(namespaceDefinition)); def.getSchemaLocations().addAll(namespaceDefinition.getSchemaLocations()); namespaceDefinitions.add(def); } boolean foundPNamespace = false; boolean foundCNamespace = false; INamespaceDefinition defaultNamespace = null; // Remove the tool namespace as we don't want to surface on the UI for (INamespaceDefinition definition : new ArrayList<INamespaceDefinition>(namespaceDefinitions)) { if (TOOLS_NAMESPACE_URI.equals(definition.getNamespaceURI())) { namespaceDefinitions.remove(definition); } else if (DEFAULT_NAMESPACE_URI.equals(definition.getNamespaceURI())) { defaultNamespace = definition; } else if (P_NAMESPACE_URI.equals(definition.getNamespaceURI())) { foundPNamespace = true; } else if (C_NAMESPACE_URI.equals(definition.getNamespaceURI())) { foundCNamespace = true; } } if (!foundPNamespace && defaultNamespace != null) { // Add in p-Namespace if we found the default namespace namespaceDefinitions.add(P_NAMESPACE_DEFINITION); } if (!foundCNamespace && defaultNamespace != null) { // Add in c-Namespace if we found the default namespace // && is Spring 3.1 or greater Set<String> locations = defaultNamespace.getSchemaLocations(); for (String locationUri : locations) { if (isSpring31(locationUri)) { namespaceDefinitions.add(C_NAMESPACE_DEFINITION); break; } } } Collections.sort(namespaceDefinitions, new Comparator<INamespaceDefinition>() { public int compare(INamespaceDefinition o1, INamespaceDefinition o2) { if (o1 != null && o1.getDefaultNamespacePrefix() != null && o2 != null && o2.getDefaultNamespacePrefix() != null) { return o1.getDefaultNamespacePrefix().compareTo(o2.getDefaultNamespacePrefix()); } return 0; } }); return namespaceDefinitions; } private static boolean isSpring31(String locationUri) { Version minimum = new Version("3.1"); Version temp = Version.MINIMUM_VERSION; Matcher matcher = DefaultNamespaceDefinition.VERSION_PATTERN.matcher(locationUri); if (matcher.matches()) { temp = new Version(matcher.group(1)); } if (temp.compareTo(minimum) >= 0) { return true; } return false; } public static INamespaceDefinition getDefaultNamespaceDefinition() { INamespaceDefinitionResolver definitionResolver = BeansCorePlugin.getNamespaceDefinitionResolver(null); org.springframework.ide.eclipse.beans.core.model.INamespaceDefinition namespaceDefinition = definitionResolver .resolveNamespaceDefinition(DEFAULT_NAMESPACE_URI); IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(NAMESPACES_EXTENSION_POINT); if (point != null) { String namespaceURI = DEFAULT_NAMESPACE_URI; for (IExtension extension : point.getExtensions()) { for (IConfigurationElement config : extension.getConfigurationElements()) { if (namespaceURI.equals(config.getAttribute("uri"))) { String prefix = config.getAttribute("prefix"); if (!StringUtils.hasText(prefix) && namespaceDefinition != null) { prefix = namespaceDefinition.getPrefix(); } String schemaLocation = config.getAttribute("defaultSchemaLocation"); if (!StringUtils.hasText(schemaLocation) && namespaceDefinition != null) { schemaLocation = namespaceDefinition.getDefaultSchemaLocation(); } String uri = config.getAttribute("uri"); IImageAccessor image = null; if (config.getAttribute("icon") != null) { String ns = config.getDeclaringExtension().getNamespaceIdentifier(); String icon = config.getAttribute("icon"); image = new DefaultImageAccessor(ns, icon); } else if (namespaceDefinition != null) { image = new NamespaceDefinitionImageAccessor(namespaceDefinition); } return new DefaultNamespaceDefinition(prefix, uri, schemaLocation, namespaceDefinition.getUriMapping(), image); } } } } if (namespaceDefinition != null) { return new DefaultNamespaceDefinition(namespaceDefinition.getPrefix(), namespaceDefinition.getNamespaceUri(), namespaceDefinition.getDefaultSchemaLocation(), namespaceDefinition.getUriMapping(), new NamespaceDefinitionImageAccessor(namespaceDefinition)); } return null; } /** * Returns an {@link Image} instance which is located at the indicated icon path. */ public static Image getImage( org.springframework.ide.eclipse.beans.core.model.INamespaceDefinition namespaceDefinition) { if (StringUtils.hasText(namespaceDefinition.getIconPath())) { synchronized (IMAGE_REGISTRY_LOCK) { Image image = BeansUIPlugin.getDefault().getImageRegistry().get(namespaceDefinition.getIconPath()); if (image == null) { InputStream is = namespaceDefinition.getIconStream(); if (is != null) { try { ImageDescriptor imageDescriptor = ImageDescriptor.createFromImageData(new ImageData(is)); BeansUIPlugin.getDefault().getImageRegistry() .put(namespaceDefinition.getIconPath(), imageDescriptor); image = BeansUIPlugin.getDefault().getImageRegistry() .get(namespaceDefinition.getIconPath()); } catch (Exception e) { BeansUIPlugin.log(String.format( "Error creating image resource for namespace definition '%s'", namespaceDefinition.getNamespaceUri()), e); return BeansUIImages.getImage(BeansUIImages.IMG_OBJS_XSD); } finally { if (is != null) { try { is.close(); } catch (IOException e) { } } } } else { BeansUIPlugin .getDefault() .getImageRegistry() .put(namespaceDefinition.getIconPath(), BeansUIImages.getImage(BeansUIImages.IMG_OBJS_XSD)); image = BeansUIPlugin.getDefault().getImageRegistry().get(namespaceDefinition.getIconPath()); } } return image; } } else { return BeansUIImages.getImage(BeansUIImages.IMG_OBJS_XSD); } } /** * Returns an {@link Image} instance which is located at the indicated icon path. */ private static Image getImage(String ns, String icon) { if (StringUtils.hasText(icon)) { synchronized (IMAGE_REGISTRY_LOCK) { Image image = BeansUIPlugin.getDefault().getImageRegistry().get(icon); if (image == null) { ImageDescriptor imageDescriptor = BeansUIPlugin.imageDescriptorFromPlugin(ns, icon); BeansUIPlugin.getDefault().getImageRegistry().put(icon, imageDescriptor); image = BeansUIPlugin.getDefault().getImageRegistry().get(icon); } return image; } } else { return BeansUIImages.getImage(BeansUIImages.IMG_OBJS_XSD); } } public interface INamespaceDefinitionTemplate { void doWithNamespaceDefinitions(INamespaceDefinition[] namespaceDefinitions, IProject project); } private static class DefaultImageAccessor extends DisplayThreadImageAccessor { private final String ns; private final String icon; public DefaultImageAccessor(String ns, String icon) { this.ns = ns; this.icon = icon; } /** * {@inheritDoc} */ @Override protected Image createImage() { return NamespaceUtils.getImage(ns, icon); } } private static class NamespaceDefinitionImageAccessor extends DisplayThreadImageAccessor { private final org.springframework.ide.eclipse.beans.core.model.INamespaceDefinition definition; public NamespaceDefinitionImageAccessor( org.springframework.ide.eclipse.beans.core.model.INamespaceDefinition definition) { this.definition = definition; } /** * {@inheritDoc} */ @Override protected Image createImage() { return NamespaceUtils.getImage(definition); } } }