de.lynorics.eclipse.jangaroo.m2e.JangarooProjectConversionParticipant.java Source code

Java tutorial

Introduction

Here is the source code for de.lynorics.eclipse.jangaroo.m2e.JangarooProjectConversionParticipant.java

Source

/*
 * Copyright 2014
 *
 * Licensed under the Eclipse Public License version 1.0, available at
 * http://opensource.org/licenses/eclipse-1.0.txt
 */
package de.lynorics.eclipse.jangaroo.m2e;

import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import org.apache.maven.model.Build;
import org.apache.maven.model.Model;
import org.apache.maven.model.Resource;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.m2e.core.project.conversion.AbstractProjectConversionParticipant;

public class JangarooProjectConversionParticipant extends AbstractProjectConversionParticipant {

    private static final String DEFAULT_JANGAROO_SOURCE = "src/main/joo"; //$NON-NLS-1$
    private static final String DEFAULT_GENERATED_SOURCE = "target/generated-sources/joo"; //$NON-NLS-1$

    private static final String DEFAULT_RESOURCES = "src/main/resources"; //$NON-NLS-1$
    private static final String DEFAULT_GENERATED_RESOURCES = "target/generated-resources"; //$NON-NLS-1$

    private static final String COMPILER_GROUP_ID = "net.jangaroo"; //$NON-NLS-1$
    private static final String COMPILER_ARTIFACT_ID = "maven-compiler-plugin"; //$NON-NLS-1$
    private static final String DEFAULT_COMPILER_VERSION = "2.0.8"; //$NON-NLS-1$

    private static final String TARGET_KEY = "target"; //$NON-NLS-1$
    private static final String SOURCE_KEY = "source"; //$NON-NLS-1$

    private static final String CONFIGURATION_KEY = "configuration"; //$NON-NLS-1$

    public boolean accept(IProject project) throws CoreException {
        boolean accepts = project != null && project.isAccessible();// TODO Nature erkennen && project.hasNature(JavaCore.NATURE_ID);
        return accepts;
    }

    public void convert(IProject project, Model model, IProgressMonitor monitor) throws CoreException {
        if (!accept(project)) {
            return;
        }
        IJavaProject javaProject = null;//TODO JavaCore.create(project);
        if (javaProject == null) {
            return;
        }

        //    log.debug("Applying Jangaroo conversion to " + project.getName()); //$NON-NLS-1$

        configureBuildSourceDirectories(model, javaProject);

        //    //Read existing Eclipse compiler settings
        //    String source = javaProject.getOption(JavaCore.COMPILER_SOURCE, false);
        //    String target = javaProject.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, false);
        //
        //    //We want to keep pom.xml configuration to a minimum so we rely on convention. If the java version == 1.5,
        //    //we shouldn't need to add anything as recent maven-compiler-plugin versions target Java 1.5 by default
        //    if(DEFAULT_JAVA_VERSION.equals(source) && DEFAULT_JAVA_VERSION.equals(target)) {
        //      return;
        //    }
        //
        //    //Configure Java version
        //    boolean useProperties = false;//TODO Use preferences
        //    if(useProperties) {
        //      configureProperties(model, source, target);
        //    } else {
        //      configureCompilerPlugin(model, source, target);
        //    }

    }

    //  private void configureProperties(Model model, String source, String target) {
    //    Properties properties = model.getProperties();
    //    if(properties == null) {
    //      properties = new Properties();
    //      model.setProperties(properties);
    //    }
    //    properties.setProperty("maven.compiler.source", source); //$NON-NLS-1$
    //    properties.setProperty("maven.compiler.target", target); //$NON-NLS-1$
    //  }

    //  private void configureCompilerPlugin(Model model, String source, String target) {
    //    Build build = getOrCreateBuild(model);
    //    model.setBuild(build);
    //
    //    Plugin compiler = getOrCreateCompilerPlugin(build);
    //
    //    Xpp3Dom configuration = (Xpp3Dom) compiler.getConfiguration();
    //    if(configuration == null) {
    //      configuration = new Xpp3Dom(CONFIGURATION_KEY);
    //      compiler.setConfiguration(configuration);
    //    }
    //
    //    Xpp3Dom sourceDom = configuration.getChild(SOURCE_KEY);
    //    if(sourceDom == null) {
    //      sourceDom = new Xpp3Dom(SOURCE_KEY);
    //      configuration.addChild(sourceDom);
    //    }
    //    sourceDom.setValue(source);
    //
    //    Xpp3Dom targetDom = configuration.getChild(TARGET_KEY);
    //    if(targetDom == null) {
    //      targetDom = new Xpp3Dom(TARGET_KEY);
    //      configuration.addChild(targetDom);
    //    }
    //    targetDom.setValue(target);
    //    compiler.setConfiguration(configuration);
    //  }

    //  private Plugin getOrCreateCompilerPlugin(Build build) {
    //    build.flushPluginMap();//We need to force the re-generation of the plugin map as it may be stale
    //    Plugin compiler = build.getPluginsAsMap().get(COMPILER_GROUP_ID + ":" + COMPILER_ARTIFACT_ID); //$NON-NLS-1$  
    //    if(compiler == null) {
    //      compiler = build.getPluginsAsMap().get(COMPILER_ARTIFACT_ID);
    //    }
    //    if(compiler == null) {
    //      compiler = new Plugin();
    //      compiler.setGroupId(COMPILER_GROUP_ID);
    //      compiler.setArtifactId(COMPILER_ARTIFACT_ID);
    //      compiler.setVersion(getCompilerVersion());
    //      build.addPlugin(compiler);
    //    }
    //
    //    return compiler;
    //  }

    private void configureBuildSourceDirectories(Model model, IJavaProject javaProject) throws CoreException {
        IClasspathEntry[] entries = javaProject.getRawClasspath();
        Set<String> sources = new LinkedHashSet<String>();
        Set<String> potentialTestSources = new LinkedHashSet<String>();
        Set<String> potentialResourceDirectories = new LinkedHashSet<String>();
        Set<String> potentialTestResourceDirectories = new LinkedHashSet<String>();
        IPath projectPath = javaProject.getPath();

        for (int i = 0; i < entries.length; i++) {
            if (entries[i].getEntryKind() == IClasspathEntry.CPE_SOURCE) {
                IPath path = entries[i].getPath().makeRelativeTo(projectPath);
                if (path.isAbsolute()) {
                    //We only support paths relative to the project root, so we skip this one
                    continue;
                }
                String portablePath = path.toPortableString();
                boolean isPotentialTestSource = isPotentialTestSource(path);
                boolean isResource = false;
                if (isPotentialTestSource) {
                    //          if(DEFAULT_TEST_RESOURCES.equals(portablePath)) {
                    //            isResource = potentialTestResourceDirectories.add(portablePath);
                    //          } else {
                    //            potentialTestSources.add(portablePath);
                    //          }
                } else {
                    if (DEFAULT_RESOURCES.equals(portablePath)) {
                        isResource = potentialResourceDirectories.add(portablePath);
                    } else {
                        sources.add(portablePath);
                    }
                }

                if (!isResource) {
                    //For source folders not already flagged as resource folder, check if 
                    // they contain non-java sources, so we can add them as resources too
                    boolean hasNonJangarooResources = false;
                    IFolder folder = javaProject.getProject().getFolder(path);
                    if (folder.isAccessible()) {
                        NonJangarooResourceVisitor nonJangarooResourceVisitor = new NonJangarooResourceVisitor();
                        try {
                            folder.accept(nonJangarooResourceVisitor);
                        } catch (NonJangarooResourceFoundException ex) {
                            //Expected
                            hasNonJangarooResources = true;
                        } catch (CoreException ex) {
                            //385666 ResourceException is thrown in Helios
                            if (ex.getCause() instanceof NonJangarooResourceFoundException) {
                                hasNonJangarooResources = true;
                            } else {
                                //                log.error("An error occured while analysing {} : {}", folder, ex.getMessage());
                            }
                        }
                    }

                    if (hasNonJangarooResources) {
                        if (isPotentialTestSource) {
                            potentialTestResourceDirectories.add(portablePath);
                        } else {
                            potentialResourceDirectories.add(portablePath);
                        }
                    }
                }
            }
        }

        Build build = getOrCreateBuild(model);

        if (!sources.isEmpty()) {
            if (sources.size() > 1) {
                //We don't know how to handle multiple sources, i.e. how to map to a resource or test source directory
                //That should be dealt by setting the build-helper-plugin config (http://mojo.codehaus.org/build-helper-maven-plugin/usage.html)
                //        log.warn("{} has multiple source entries, this is not supported yet", model.getArtifactId()); //$NON-NLS-1$
            }
            String sourceDirectory = sources.iterator().next();
            if (!DEFAULT_JANGAROO_SOURCE.equals(sourceDirectory)) {
                build.setSourceDirectory(sourceDirectory);
            }

            for (String resourceDirectory : potentialResourceDirectories) {
                if (!DEFAULT_RESOURCES.equals(resourceDirectory) || potentialResourceDirectories.size() > 1) {
                    build.addResource(createResource(resourceDirectory));
                }
            }
        }

        if (!potentialTestSources.isEmpty()) {
            if (potentialTestSources.size() > 1) {
                //        log.warn("{} has multiple test source entries, this is not supported yet", model.getArtifactId()); //$NON-NLS-1$
            }
            //      String testSourceDirectory = potentialTestSources.iterator().next();
            //      if(!DEFAULT_JAVA_TEST_SOURCE.equals(testSourceDirectory)) {
            //        build.setTestSourceDirectory(testSourceDirectory);
            //      }
            //      for(String resourceDirectory : potentialTestResourceDirectories) {
            //        if(!DEFAULT_TEST_RESOURCES.equals(resourceDirectory) || potentialTestResourceDirectories.size() > 1) {
            //          build.addTestResource(createResource(resourceDirectory));
            //        }
            //      }
        }

        //Ensure we don't attach a new empty build definition to the model
        if (build.getSourceDirectory() != null || build.getTestSourceDirectory() != null
                || !build.getResources().isEmpty() || !build.getTestResources().isEmpty()) {
            model.setBuild(build);
        }
    }

    private Resource createResource(String resourceDirectory) {
        Resource r = new Resource();
        r.setDirectory(resourceDirectory);
        r.addExclude("**/*.as"); //$NON-NLS-1$
        return r;
    }

    /**
     * Checks if a given path has one of its segment ending with test or tests
     */
    private boolean isPotentialTestSource(IPath path) {
        for (String segment : path.segments()) {
            String folderName = segment.toLowerCase();
            if (folderName.matches(".*tests?")) { //$NON-NLS-1$
                return true;
            }
        }
        return false;
        //TODO Maybe check if the folder has actionscript files with a Test or TestSuite suffix? 
    }

    private Build getOrCreateBuild(Model model) {
        Build build = model.getBuild();
        if (build == null) {
            build = new Build();
        }
        return build;
    }

    /**
     * Visitor implementation looking for non-Java resources. as soon as such resource is found, a
     * {@link NonJangarooResourceFoundException} is thrown.
     */
    private static class NonJangarooResourceVisitor implements IResourceVisitor {

        //TODO either declare a complete list of extensions or switch to
        // a different "ignore resource" strategy
        private static final List<String> IGNORED_EXTENSIONS = Arrays.asList(".svn"); //$NON-NLS-1$

        public NonJangarooResourceVisitor() {
        }

        @SuppressWarnings("unused")
        public boolean visit(IResource resource) throws CoreException {
            String resourceName = resource.getProjectRelativePath().lastSegment();
            if (resource.isHidden() || isIgnored(resourceName)) {
                return false;
            }
            if (resource instanceof IFile) {
                IFile file = (IFile) resource;
                if (!"as".equals(file.getFileExtension())) {
                    throw new NonJangarooResourceFoundException();
                }
            }
            return true;
        }

        private boolean isIgnored(String resourceName) {
            for (String extension : IGNORED_EXTENSIONS) {
                if (resourceName.endsWith(extension)) {
                    return true;
                }
            }
            return false;
        }
    }

    private static class NonJangarooResourceFoundException extends RuntimeException {

        private static final long serialVersionUID = 1L;

        public NonJangarooResourceFoundException() {
        }

        @Override
        public Throwable fillInStackTrace() {
            //Overriding fillInStackTrace() reduces the stacktrace creation overhead,
            //unneeded since this exception is used for flow control.
            return this;
        }
    }

    //  private String getCompilerVersion() {
    //    //For test purposes only, must not be considered API behavior.
    //    String version = System.getProperty("org.eclipse.m2e.jdt.conversion.compiler.version");//$NON-NLS-1$
    //    if(version != null) {
    //      return version;
    //    }
    //    return getMostRecentPluginVersion(COMPILER_GROUP_ID, COMPILER_ARTIFACT_ID, DEFAULT_COMPILER_VERSION);
    //  }

    /**
     * Returns the highest, non-snapshot plugin version between the given reference version and the versions found in the
     * Nexus indexes.
     */
    //  @SuppressWarnings("restriction")
    //  //TODO extract as API when stabilized?
    //  private String getMostRecentPluginVersion(String groupId, String artifactId, String referenceVersion) {
    //    Assert.isNotNull(groupId, "groupId can not be null");
    //    Assert.isNotNull(artifactId, "artifactId can not be null");
    //    String version = referenceVersion;
    //    String partialKey = artifactId + " : " + groupId; //$NON-NLS-1$
    //    try {
    //      IIndex index = MavenPlugin.getIndexManager().getAllIndexes();
    //      SearchExpression a = new SourcedSearchExpression(artifactId);
    //
    //      //For some reason, an exact search using : 
    //      //ISearchEngine searchEngine  = M2EUIPluginActivator.getDefault().getSearchEngine(null)
    //      //searchEngine.findVersions(groupId, artifactId, searchExpression, packaging)
    //      //
    //      //doesn't yield the expected results (the latest versions are not returned), so we rely on a fuzzier search
    //      //and refine the results.
    //      Map<String, IndexedArtifact> values = index.search(a, IIndex.SEARCH_PLUGIN);
    //      if(!values.isEmpty()) {
    //        SortedSet<ComparableVersion> versions = new TreeSet<ComparableVersion>();
    //        ComparableVersion referenceComparableVersion = referenceVersion == null ? null : new ComparableVersion(
    //            referenceVersion);
    //
    //        for(Map.Entry<String, IndexedArtifact> e : values.entrySet()) {
    //          if(!(e.getKey().endsWith(partialKey))) {
    //            continue;
    //          }
    //          for(IndexedArtifactFile f : e.getValue().getFiles()) {
    //            if(groupId.equals(f.group) && artifactId.equals(f.artifact) && !f.version.contains("SNAPSHOT")) {
    //              ComparableVersion v = new ComparableVersion(f.version);
    //              if(referenceComparableVersion == null || v.compareTo(referenceComparableVersion) > 0) {
    //                versions.add(v);
    //              }
    //            }
    //          }
    //          if(!versions.isEmpty()) {
    //            List<String> sorted = new ArrayList<String>(versions.size());
    //            for(ComparableVersion v : versions) {
    //              sorted.add(v.toString());
    //            }
    //            Collections.reverse(sorted);
    //            version = sorted.iterator().next();
    //          }
    //        }
    //      }
    //    } catch(CoreException e) {
    //      log.error("Can not retrieve latest version of " + partialKey, e);
    //    }
    //    return version;
    //  }
}