org.springframework.ide.eclipse.beans.ui.namespaces.DefaultNamespaceDefinition.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.ide.eclipse.beans.ui.namespaces.DefaultNamespaceDefinition.java

Source

/*******************************************************************************
 * Copyright (c) 2007, 2010 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.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.Preferences;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.core.JarEntryFile;
import org.eclipse.swt.graphics.Image;
import org.springframework.ide.eclipse.beans.core.BeansCorePlugin;
import org.springframework.ide.eclipse.beans.ui.BeansUIImages;
import org.springframework.ide.eclipse.core.SpringCorePreferences;
import org.springframework.ide.eclipse.core.java.JdtUtils;
import org.springframework.util.StringUtils;

/**
 * Default implementation of {@link INamespaceDefinition}.
 * @author Christian Dupuis
 * @since 2.0
 */
@SuppressWarnings({ "deprecation", "restriction" })
public class DefaultNamespaceDefinition implements INamespaceDefinition {

    public static final Pattern VERSION_PATTERN = Pattern.compile(".*-([0-9,.]*)\\.xsd");

    private final String defaultLocation;

    private final IImageAccessor imageAccessor;

    private Set<String> locations = new HashSet<String>();

    private final String defaultPrefix;

    private final String uri;

    private Properties uriMapping = new Properties();

    public DefaultNamespaceDefinition(String prefix, String uri, String defaultLocation,
            IImageAccessor imageAccessor) {
        this(prefix, uri, defaultLocation, new Properties(), imageAccessor);
    }

    public DefaultNamespaceDefinition(String prefix, String uri, String defaultLocation, final Image image) {
        this(prefix, uri, defaultLocation, new IImageAccessor() {

            public Image getImage() {
                return image;
            }
        });
    }

    public DefaultNamespaceDefinition(String prefix, String uri, String defaultLocation,
            Properties namespaceDefinition, IImageAccessor imageAccessor) {
        if (prefix != null) {
            this.defaultPrefix = prefix;
        } else {
            int ix = uri.lastIndexOf('/');
            this.defaultPrefix = uri.substring(ix + 1);
        }
        this.uri = uri;
        this.defaultLocation = defaultLocation;
        this.uriMapping = namespaceDefinition;
        this.imageAccessor = imageAccessor;
    }

    public void addSchemaLocation(String location) {
        locations.add(location);
    }

    /**
     * {@inheritDoc}
     */
    public boolean equals(Object obj) {
        if (obj instanceof DefaultNamespaceDefinition) {
            DefaultNamespaceDefinition o = (DefaultNamespaceDefinition) obj;
            return o.defaultPrefix.equals(defaultPrefix) && o.uri.equals(uri);
        }
        return false;
    }

    public String getDefaultNamespacePrefix() {
        return defaultPrefix;
    }

    public String getDefaultSchemaLocation() {
        return getDefaultSchemaLocation(null);
    }

    /**
     * {@inheritDoc}
     */
    public String getDefaultSchemaLocation(IResource resource) {
        String location = null;
        if (hasProjectSpecificOptions(resource)) {
            SpringCorePreferences prefs = SpringCorePreferences.getProjectPreferences(resource.getProject(),
                    BeansCorePlugin.PLUGIN_ID);
            if (prefs.getBoolean(BeansCorePlugin.NAMESPACE_DEFAULT_FROM_CLASSPATH_ID, true)) {
                location = getDefaultSchemaLocationFromClasspath(resource);
            }
            if ("".equals(location) || location == null) {
                location = prefs
                        .getString(BeansCorePlugin.NAMESPACE_DEFAULT_VERSION_PREFERENCE_ID + getNamespaceURI(), "");
            }
        } else {
            Preferences prefs = BeansCorePlugin.getDefault().getPluginPreferences();
            if (prefs.getBoolean(BeansCorePlugin.NAMESPACE_DEFAULT_FROM_CLASSPATH_ID)) {
                location = getDefaultSchemaLocationFromClasspath(resource);
            }
            if ("".equals(location) || location == null) {
                location = prefs
                        .getString(BeansCorePlugin.NAMESPACE_DEFAULT_VERSION_PREFERENCE_ID + getNamespaceURI());
            }
        }
        if ("".equals(location) || location == null) {
            return defaultLocation;
        } else {
            return location;
        }
    }

    /**
     * {@inheritDoc}
     */
    public Image getNamespaceImage() {
        if (imageAccessor != null) {
            return imageAccessor.getImage();
        }
        return BeansUIImages.getImage(BeansUIImages.IMG_OBJS_XSD);
    }

    /**
     * {@inheritDoc}
     */
    public String getNamespacePrefix() {
        return defaultPrefix;
    }

    /**
     * {@inheritDoc}
     */
    public String getNamespacePrefix(IResource resource) {
        String prefix = null;
        if (hasProjectSpecificOptions(resource)) {
            SpringCorePreferences prefs = SpringCorePreferences.getProjectPreferences(resource.getProject(),
                    BeansCorePlugin.PLUGIN_ID);
            prefix = prefs.getString(BeansCorePlugin.NAMESPACE_PREFIX_PREFERENCE_ID + getNamespaceURI(), "");
        } else {
            Preferences prefs = BeansCorePlugin.getDefault().getPluginPreferences();
            prefix = prefs.getString(BeansCorePlugin.NAMESPACE_PREFIX_PREFERENCE_ID + getNamespaceURI());
        }
        if (StringUtils.hasLength(prefix)) {
            return prefix;
        }
        return defaultPrefix;
    }

    /**
     * {@inheritDoc}
     */
    public String getNamespaceURI() {
        return uri;
    }

    /**
     * {@inheritDoc}
     */
    public Set<String> getSchemaLocations() {
        return locations;
    }

    /**
     * {@inheritDoc}
     */
    public int hashCode() {
        return defaultPrefix.hashCode() ^ uri.hashCode();
    }

    private String getDefaultSchemaLocationFromClasspath(IResource resource) {
        IJavaProject jp = JdtUtils.getJavaProject(resource);
        Set<String> existingLocations = new HashSet<String>();
        try {
            for (Map.Entry<Object, Object> entry : uriMapping.entrySet()) {

                // Check that we are looking for relevant entries only; e.g. util, tool and beans are in the same
                // package
                if (((String) entry.getKey()).startsWith(uri)) {
                    String fileLocation = (String) entry.getValue();

                    // Get the package name from the location
                    String packageName = "";
                    int ix = fileLocation.lastIndexOf('/');
                    if (ix > 0) {
                        packageName = fileLocation.substring(0, ix).replace('/', '.');
                    }

                    // Search in all project packages
                    for (IPackageFragmentRoot root : jp.getPackageFragmentRoots()) {
                        IPackageFragment pf = root.getPackageFragment(packageName);
                        if (pf.exists()) {
                            for (Object obj : pf.getNonJavaResources()) {
                                // Entry is coming from a JAR file on the classpath
                                if (obj instanceof JarEntryFile
                                        && ("/" + fileLocation)
                                                .equals((((JarEntryFile) obj).getFullPath().toString()))
                                        && locations.contains(entry.getKey())) {
                                    existingLocations.add((String) entry.getKey());
                                }
                                // Entry is coming from the local project
                                else if (obj instanceof IFile && fileLocation.equals(
                                        pf.getElementName().replace('.', '/') + "/" + ((IFile) obj).getName())
                                        && locations.contains(entry.getKey())) {
                                    existingLocations.add((String) entry.getKey());
                                }
                            }
                        }
                    }
                }
            }
        } catch (JavaModelException e) {
            // We have a safe fall-back
        }

        // Search for the highest version among the existing resources
        String highestLocation = null;
        Version version = Version.MINIMUM_VERSION;
        for (String location : existingLocations) {
            Version tempVersion = Version.MINIMUM_VERSION;
            Matcher matcher = VERSION_PATTERN.matcher(location);
            if (matcher.matches()) {
                tempVersion = new Version(matcher.group(1));
            }
            if (tempVersion.compareTo(version) >= 0) {
                version = tempVersion;
                highestLocation = location;
            }
        }
        return highestLocation;
    }

    private boolean hasProjectSpecificOptions(IResource resource) {
        if (resource == null) {
            return false;
        }
        return SpringCorePreferences.getProjectPreferences(resource.getProject(), BeansCorePlugin.PLUGIN_ID)
                .getBoolean(BeansCorePlugin.PROJECT_PROPERTY_ID, false);
    }

    static class Version implements Comparable<Version> {

        private static final String MINIMUM_VERSION_STRING = "0";

        public static final Version MINIMUM_VERSION = new Version(MINIMUM_VERSION_STRING);

        private final org.osgi.framework.Version version;

        public Version(String v) {
            org.osgi.framework.Version tempVersion = null;
            try {
                tempVersion = org.osgi.framework.Version.parseVersion(v);
            } catch (Exception e) {
                // make sure that we don't crash on any new version numbers format that we don't support
                BeansCorePlugin.log("Cannot convert schema vesion", e);
                tempVersion = org.osgi.framework.Version.parseVersion(MINIMUM_VERSION_STRING);
            }
            this.version = tempVersion;
        }

        public int compareTo(Version v2) {
            return this.version.compareTo(v2.version);
        }
    }

}