/******************************************************************************* * Copyright (c) 2007, 2012 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.core.namespaces; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; 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.IStatus; import org.eclipse.core.runtime.InvalidRegistryObjectException; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.osgi.framework.Bundle; import org.springframework.beans.BeanMetadataElement; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.xml.NamespaceHandler; import org.springframework.beans.factory.xml.NamespaceHandlerResolver; import org.springframework.ide.eclipse.beans.core.BeansCorePlugin; import org.springframework.ide.eclipse.core.SpringCorePreferences; import org.springframework.ide.eclipse.core.model.IModelSourceLocation; import org.springframework.ide.eclipse.core.model.ModelUtils; import org.springframework.ide.eclipse.core.model.xml.XmlSourceLocation; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import org.xml.sax.EntityResolver; /** * Some helper methods that deal with loading extension point contributions. * @author Torsten Juergeleit * @author Christian Dupuis * @author Martin Lippert * @since 2.0 */ public class NamespaceUtils { public static final String NAMESPACES_EXTENSION_POINT = BeansCorePlugin.PLUGIN_ID + ".namespaces"; public static final String RESOLVERS_EXTENSION_POINT = BeansCorePlugin.PLUGIN_ID + ".resolvers"; public static final String DEFAULT_NAMESPACE_URI = "http://www.springframework.org/schema/beans"; private static Set<NamespaceHandlerResolver> namespaceHandlerResolvers; private static Map<String, IModelElementProvider> modelElementProviders; private static Set<EntityResolver> entityResolvers; private static Map<NamespaceHandlerDescriptor, NamespaceHandler> namespaceHandlers; /** * Returns the namespace URI for the given {@link BeanMetadataElement} or * <code>"http://www.springframework.org/schema/beans"</code> if no namespace URI found. */ public static String getNameSpaceURI(BeanMetadataElement element) { IModelSourceLocation location = ModelUtils.getSourceLocation(element); if (location instanceof XmlSourceLocation) { String namespaceURI = ((XmlSourceLocation) location).getNamespaceURI(); if (namespaceURI != null) { return namespaceURI; } } return DEFAULT_NAMESPACE_URI; } /** * Returns a {@link Map} with all registered {@link NamespaceHandler}s. */ public synchronized static Map<NamespaceHandlerDescriptor, NamespaceHandler> getNamespaceHandlers() { if (namespaceHandlers == null) { Map<NamespaceHandlerDescriptor, NamespaceHandler> handlers = new HashMap<NamespaceHandlerDescriptor, NamespaceHandler>(); IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(NAMESPACES_EXTENSION_POINT); if (point != null) { for (IExtension extension : point.getExtensions()) { for (IConfigurationElement config : extension.getConfigurationElements()) { String uri = config.getAttribute("uri"); if (uri != null && config.getAttribute("namespaceHandler") != null) { try { String handlerClassName = config.getAttribute("namespaceHandler"); String provider = config.getAttribute("provider"); if (!StringUtils.hasLength(provider)) { provider = extension.getContributor().getName(); } Object handler = loadHandler(provider, handlerClassName); if (handler instanceof NamespaceHandler) { NamespaceHandler namespaceHandler = (NamespaceHandler) handler; namespaceHandler.init(); handlers.put( NamespaceHandlerDescriptor.createNamespaceHandlerDescriptor(uri, null), namespaceHandler); } } catch (InvalidRegistryObjectException e) { BeansCorePlugin.log(e); } } for (IConfigurationElement namespaceHandlerConfig : config.getChildren("namespaceHandler")) { if (uri != null && namespaceHandlerConfig.getAttribute("class") != null) { try { String schemaLocation = namespaceHandlerConfig.getAttribute("schemaLocation"); String handlerClassName = namespaceHandlerConfig.getAttribute("class"); String provider = namespaceHandlerConfig.getAttribute("provider"); if (!StringUtils.hasLength(provider)) { provider = extension.getContributor().getName(); } Object handler = loadHandler(provider, handlerClassName); if (handler instanceof NamespaceHandler) { NamespaceHandler namespaceHandler = (NamespaceHandler) handler; namespaceHandler.init(); handlers.put(NamespaceHandlerDescriptor.createNamespaceHandlerDescriptor(uri, schemaLocation), namespaceHandler); } } catch (InvalidRegistryObjectException e) { BeansCorePlugin.log(e); } } } } } } namespaceHandlers = handlers; } return namespaceHandlers; } /** * Returns a {@link Map} with all registered {@link IModelElementProvider}s. */ public synchronized static Map<String, IModelElementProvider> getElementProviders() { if (modelElementProviders == null) { Map<String, IModelElementProvider> providers = new HashMap<String, IModelElementProvider>(); IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(NAMESPACES_EXTENSION_POINT); if (point != null) { for (IExtension extension : point.getExtensions()) { for (IConfigurationElement config : extension.getConfigurationElements()) { String uri = config.getAttribute("uri"); if (uri != null && config.getAttribute("elementProvider") != null) { try { Object provider = config.createExecutableExtension("elementProvider"); if (provider instanceof IModelElementProvider) { providers.put(uri, (IModelElementProvider) provider); } } catch (CoreException e) { BeansCorePlugin.log(e); } } } } } modelElementProviders = providers; } return modelElementProviders; } /** * Returns a {@link Set} with all registered {@link NamespaceHandlerResolver}s. * @since 2.0.1 */ public synchronized static Set<NamespaceHandlerResolver> getNamespaceHandlerResolvers() { if (namespaceHandlerResolvers == null) { Set<NamespaceHandlerResolver> handlers = new HashSet<NamespaceHandlerResolver>(); IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(RESOLVERS_EXTENSION_POINT); if (point != null) { for (IExtension extension : point.getExtensions()) { for (IConfigurationElement config : extension.getConfigurationElements()) { if ("namespaceHandlerResolver".equals(config.getName()) && config.getAttribute("class") != null) { try { String handlerClassName = config.getAttribute("class"); Object handler = loadHandler(extension.getContributor().getName(), handlerClassName); if (handler instanceof NamespaceHandlerResolver) { NamespaceHandlerResolver namespaceHandlerResolver = (NamespaceHandlerResolver) handler; handlers.add(namespaceHandlerResolver); } } catch (InvalidRegistryObjectException e) { BeansCorePlugin.log(e); } } } } } // Add the OSGi-based namespace handler resolver handlers.add(BeansCorePlugin.getNamespaceHandlerResolver()); namespaceHandlerResolvers = handlers; } return namespaceHandlerResolvers; } /** * Returns a {@link Set} with all registered {@link EntityResolver}s. * @since 2.0.1 */ public synchronized static Set<EntityResolver> getEntityResolvers() { if (entityResolvers == null) { Set<EntityResolver> handlers = new HashSet<EntityResolver>(); IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(RESOLVERS_EXTENSION_POINT); if (point != null) { for (IExtension extension : point.getExtensions()) { for (IConfigurationElement config : extension.getConfigurationElements()) { if ("entityResolver".equals(config.getName()) && config.getAttribute("class") != null) { try { Object handler = config.createExecutableExtension("class"); if (handler instanceof EntityResolver) { EntityResolver entityResolver = (EntityResolver) handler; handlers.add(entityResolver); } } catch (CoreException e) { BeansCorePlugin.log(e); } } } } } entityResolvers = handlers; } return entityResolvers; } /** * Checks if a project should load namespace handlers from the classpath or use the global catalog. */ @SuppressWarnings("deprecation") public static boolean useNamespacesFromClasspath(IProject project) { if (project == null) { return false; } if (SpringCorePreferences.getProjectPreferences(project, BeansCorePlugin.PLUGIN_ID).getBoolean( BeansCorePlugin.PROJECT_PROPERTY_ID, false)) { return SpringCorePreferences.getProjectPreferences(project, BeansCorePlugin.PLUGIN_ID).getBoolean( BeansCorePlugin.LOAD_NAMESPACEHANDLER_FROM_CLASSPATH_ID, false); } return BeansCorePlugin.getDefault().getPluginPreferences().getBoolean( BeansCorePlugin.LOAD_NAMESPACEHANDLER_FROM_CLASSPATH_ID); } @SuppressWarnings("deprecation") public static boolean disableCachingForNamespaceLoadingFromClasspath(IProject project) { if (project == null) { return false; } if (SpringCorePreferences.getProjectPreferences(project, BeansCorePlugin.PLUGIN_ID).getBoolean( BeansCorePlugin.PROJECT_PROPERTY_ID, false)) { return SpringCorePreferences.getProjectPreferences(project, BeansCorePlugin.PLUGIN_ID).getBoolean( BeansCorePlugin.DISABLE_CACHING_FOR_NAMESPACE_LOADING_ID, false); } return BeansCorePlugin.getDefault().getPluginPreferences().getBoolean( BeansCorePlugin.DISABLE_CACHING_FOR_NAMESPACE_LOADING_ID); } private static Object loadHandler(String providerBundle, String handlerClassName) { Bundle bundle = Platform.getBundle(providerBundle); if (bundle != null) { try { Class<?> handlerClass = bundle.loadClass(handlerClassName); return BeanUtils.instantiate(handlerClass); } catch (ClassNotFoundException e) { BeansCorePlugin.log(new Status(IStatus.WARNING, BeansCorePlugin.PLUGIN_ID, 1, String.format( "Problem loading handler with class '%s' from bundle '%s'", handlerClassName, providerBundle), e)); } } else { BeansCorePlugin.log(new Status(IStatus.WARNING, BeansCorePlugin.PLUGIN_ID, String.format( "Problem loading handler with class '%s' from bundle '%s'", handlerClassName, providerBundle))); } return null; } public static class NamespaceHandlerDescriptor { private final String namespaceUri; private final String schemaLocation; NamespaceHandlerDescriptor(String namespaceUri, String schemaLocation) { this.namespaceUri = namespaceUri; this.schemaLocation = schemaLocation; } public static NamespaceHandlerDescriptor createNamespaceHandlerDescriptor(String namespaceUri, String schemaLocation) { if (StringUtils.hasText(schemaLocation)) { return new NamespaceHandlerDescriptor(namespaceUri, schemaLocation); } return new NamespaceHandlerDescriptor(namespaceUri, "*"); } @Override public boolean equals(Object obj) { if (!(obj instanceof NamespaceHandlerDescriptor)) { return false; } NamespaceHandlerDescriptor other = (NamespaceHandlerDescriptor) obj; return namespaceUri.equals(other.namespaceUri) && schemaLocation.equals(other.schemaLocation); } @Override public int hashCode() { return 31 ^ ObjectUtils.nullSafeHashCode(namespaceUri) * ObjectUtils.nullSafeHashCode(schemaLocation); } } }