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

org.codehaus.mevenide.netbeans.CPExtender Maven / Gradle / Ivy

The newest version!
/* ==========================================================================
 * Copyright 2006 Mevenide Team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 * =========================================================================
 */

package org.codehaus.mevenide.netbeans;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.security.NoSuchAlgorithmException;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.Model;
import org.codehaus.mevenide.indexer.api.NBVersionInfo;
import org.codehaus.mevenide.indexer.api.RepositoryInfo;
import org.codehaus.mevenide.indexer.api.RepositoryPreferences;
import org.codehaus.mevenide.indexer.api.RepositoryQueries;
import org.codehaus.mevenide.indexer.api.RepositoryUtil;
import org.codehaus.mevenide.netbeans.api.PluginPropertyUtils;
import org.codehaus.mevenide.netbeans.api.ProjectURLWatcher;
import org.codehaus.mevenide.netbeans.embedder.writer.WriterUtils;
import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.api.java.project.JavaProjectConstants;
import org.netbeans.api.project.SourceGroup;
import org.netbeans.api.project.Sources;
import org.netbeans.api.project.ant.AntArtifact;
import org.netbeans.api.project.libraries.Library;
import org.netbeans.spi.java.project.classpath.ProjectClassPathExtender;
import org.netbeans.spi.java.project.classpath.ProjectClassPathModifierImplementation;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.filesystems.Repository;
import org.openide.filesystems.URLMapper;
import org.openide.util.Exceptions;

/**
 * an implementation of ProjectClassPathModifierImplementation that tried to match 
 * maven dependencies to the way classpath items are added through this api.
 * @author [email protected]
 */
@SuppressWarnings("deprecation")
public class CPExtender extends ProjectClassPathModifierImplementation implements ProjectClassPathExtender {

    private NbMavenProject project;
    private static final String MD5_ATTR = "MD5"; //NOI18N
    private static final String POM_XML = "pom.xml"; //NOI18N
    
    /** Creates a new instance of CPExtender */
    public CPExtender(NbMavenProject project) {
        this.project = project;
    }
    
    public boolean addLibrary(Library library) throws IOException {
        FileObject pom = project.getProjectDirectory().getFileObject(POM_XML);//NOI18N
        Model model = WriterUtils.loadModel(pom);
        boolean added = addLibrary(library, model, null);
        if (added) {
            try {
                WriterUtils.writePomModel(pom, model);
                ProjectURLWatcher.fireMavenProjectReload(project);
                project.getLookup().lookup(ProjectURLWatcher.class).triggerDependencyDownload();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return added;
    }
    
    public boolean addArchiveFile(FileObject arch) throws IOException {
        FileObject file = FileUtil.getArchiveFile(arch);
        if (file.isFolder()) {
            throw new IOException("Cannot add folders to Maven projects as dependencies: " + file.getURL()); //NOI18N
        }
        FileObject fo = project.getProjectDirectory().getFileObject(POM_XML); //NOI18N
        Model model = WriterUtils.loadModel(fo);
        assert model != null;
        boolean added = addArchiveFile(file, model, null);
        if (added) {
            try {
                WriterUtils.writePomModel(fo, model);
                ProjectURLWatcher.fireMavenProjectReload(project);
                project.getLookup().lookup(ProjectURLWatcher.class).triggerDependencyDownload();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return added;
    }

    private boolean addLibrary(Library library, Model model, String scope) throws IOException {
        boolean added = false;
        try {
            added = checkLibraryForPoms(library, model, scope);
        } catch (IllegalArgumentException x) {
            //TODO ignore, remove the catch while maven-pom volume gets into j2se libraries..
            Exceptions.printStackTrace(x);
        }
        if (!added) {
            List urls = library.getContent("classpath"); //NOI18N
            added = urls.size() > 0;
            assert model != null;
            for (URL url : urls) {
                FileObject fo = URLMapper.findFileObject(FileUtil.getArchiveFile(url));
                assert fo != null;
                if (fo.isFolder()) {
                    throw new IOException("Cannot add folders to Maven projects as dependencies: " + fo.getURL()); //NOI18N
                }
                added = added && addArchiveFile(fo, model, scope);
            }
        }
        return added;
    }
    
    private boolean addArchiveFile(FileObject file, Model mdl, String scope) throws IOException {
            
        String[] dep = checkRepositoryIndices(FileUtil.toFile(file));
        //if not found anywhere, add to a custom file:// based repository structure within the project's directory.
        if (dep == null || "unknown.binary".equals(dep[0])) {  //NOI18N
            //also go this route when the artifact was found in local repo but is of unknown.binary groupId.
            dep = new String[3];
            dep[0] = "unknown.binary"; //NOI18N
            dep[1] = file.getName();
            dep[2] = "SNAPSHOT"; //NOI18N
            addJarToPrivateRepo(file, mdl, dep);
        }
        if (dep != null) {
            Dependency dependency = PluginPropertyUtils.checkModelDependency(mdl, dep[0], dep[1], true);
            dependency.setVersion(dep[2]);
            if (scope != null) {
                dependency.setScope(scope);
            }
            return true;
        }
        return false;
    }
    
    private String[] checkRepositoryIndices(File file) {
        List lst = RepositoryQueries.findBySHA1(file);
        for (NBVersionInfo elem : lst) {
            String[] dep = new String[3];
            dep[0] = elem.getGroupId();
            dep[1] = elem.getArtifactId();
            dep[2] = elem.getVersion();
            return dep;
        }
        return null;
    }
    
    private URL[] getRepoURLs() {
        Set urls = new HashSet();
        List ris = RepositoryPreferences.getInstance().getRepositoryInfos();
        for (RepositoryInfo ri : ris) {
            if (ri.getRepositoryUrl() != null) {
                try {
                    urls.add(new URL(ri.getRepositoryUrl()));
                } catch (MalformedURLException ex) {
                    //ignore
                }
            }
        }
        // these 2 urls are essential (together with central) for correct 
        // resolution of maven pom urls in libraries
        try {
            urls.add(new URL("http://repo1.maven.org/maven2"));
            urls.add(new URL("http://download.java.net/maven/2"));
            urls.add(new URL("http://download.java.net/maven/1"));
        } catch (MalformedURLException ex) {
            Exceptions.printStackTrace(ex);
        }
        return urls.toArray(new URL[0]);
    }
    /**
     */ 
    private boolean checkLibraryForPoms(Library library, Model model, String scope) {
        if (!"j2se".equals(library.getType())) {//NOI18N
            //only j2se library supported for now..
            return false;
        }
        List poms = library.getContent("maven-pom"); //NOI18N
        boolean added = false;
        if (poms != null && poms.size() > 0) {
            for (URL pom : poms) {
                URL[] repos = getRepoURLs();
                String[] result = checkLibrary(pom, repos);
                if (result != null) {
                    added = true;
                    //set dependency
                    Dependency dep = PluginPropertyUtils.checkModelDependency(model, result[2], result[3], true);
                    dep.setVersion(result[4]);
                    if (scope != null) {
                        dep.setScope(scope);
                    }
                    //set repository
                    org.apache.maven.model.Repository reposit = PluginPropertyUtils.checkModelRepository(
                            project.getOriginalMavenProject(), model, result[1], true);
                    if (reposit != null) {
                        reposit.setId(library.getName());
                        reposit.setLayout(result[0]);
                        reposit.setName("Repository for library " + library);
                    }
                }
            }
        }
        return added;
    }
    
    static Pattern DEFAULT = Pattern.compile("(.+)[/]{1}(.+)[/]{1}(.+)[/]{1}(.+)\\.pom"); //NOI18N
    static Pattern LEGACY = Pattern.compile("(.+)[/]{1}poms[/]{1}([a-zA-Z\\-_]+)[\\-]{1}([0-9]{1}.+)\\.pom"); //NOI18N
    /**
     * @returns [0] type - default/legacy
     *          [1] repo root
     *          [2] groupId
     *          [3] artifactId
     *          [4] version
     */ 
    
    static String[] checkLibrary(URL pom, URL[] knownRepos) {
        String path = pom.getPath();
        Matcher match = LEGACY.matcher(path);
        boolean def = false;
        if (!match.matches()) {
            match = DEFAULT.matcher(path);
            def = true;
        }
        if (match.matches()) {
            String[] toRet = new String[5];
            toRet[0] = def ? "default" : "legacy"; //NOI18N
            toRet[1] = pom.getProtocol() + "://" + pom.getHost() + (pom.getPort() != -1 ? (":" + pom.getPort()) : ""); //NOI18N
            toRet[2] = match.group(1);
            toRet[3] = match.group(2);
            toRet[4] = match.group(3);
            for (URL repo : knownRepos) {
                String root = repo.getProtocol() + "://" + repo.getHost() + (repo.getPort() != -1 ? (":" + repo.getPort()) : ""); //NOI18N
                if (root.equals(toRet[1]) && toRet[2].startsWith(repo.getPath())) {
                    toRet[1] = toRet[1] + repo.getPath();
                    toRet[2] = toRet[2].substring(repo.getPath().length());
                    break;
                }
            }
            if (toRet[2].startsWith("/")) { //NOI18N
                toRet[2] = toRet[2].substring(1);
            }
            //sort of hack, these 2 are the most probable root paths.
            if (toRet[2].startsWith("maven/")) {
                toRet[1] = toRet[1] + "/maven";
                toRet[2] = toRet[2].substring("maven/".length());
            }
            if (toRet[2].startsWith("maven2/")) {
                toRet[1] = toRet[1] + "/maven2";
                toRet[2] = toRet[2].substring("maven2/".length());
            }
            toRet[2] = toRet[2].replace('/', '.'); //NOI18N
            return toRet;
        }
        return null;
    }
    
    public boolean addAntArtifact(AntArtifact arg0, URI arg1) throws IOException {
        throw new IOException("Cannot add Ant based projects as subprojecs to Maven projects."); //NOI18N
    }
    
    public SourceGroup[] getExtensibleSourceGroups() {
        Sources s = this.project.getLookup().lookup(Sources.class);
        assert s != null;
        return s.getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
    }
    
    public String[] getExtensibleClassPathTypes(SourceGroup arg0) {
        return new String[] {
            ClassPath.COMPILE,
            ClassPath.EXECUTE
        };
    }
    
    public boolean addLibraries(Library[] libraries, SourceGroup grp, String type) throws IOException {
        FileObject pom = project.getProjectDirectory().getFileObject(POM_XML); //NOI18N
        Model model = WriterUtils.loadModel(pom);
        boolean added = libraries.length > 0;
        String scope = ClassPath.EXECUTE.equals(type) ? "runtime" : null; //NOI18N
        for (Library library : libraries) {
            added = added && addLibrary(library, model, scope);
        }
        if (added) {
            try {
                WriterUtils.writePomModel(pom, model);
                ProjectURLWatcher.fireMavenProjectReload(project);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return added;
    }
    
    public boolean removeLibraries(Library[] arg0, SourceGroup arg1,
                                      String arg2) throws IOException,
                                                          UnsupportedOperationException {
        throw new UnsupportedOperationException("Not supported in maven projects.");//NOI18N
    }
    
    public boolean addRoots(URL[] urls, SourceGroup grp, String type) throws IOException {
        FileObject pom = project.getProjectDirectory().getFileObject(POM_XML);//NOI18N
        Model model = WriterUtils.loadModel(pom);
        boolean added = urls.length > 0;
        String scope = ClassPath.EXECUTE.equals(type) ? "runtime" : null;//NOI18N
        for (URL url : urls) {
            URL fileUrl = FileUtil.getArchiveFile(url);
            if (fileUrl != null) {
                FileObject fo  = URLMapper.findFileObject(fileUrl);
                assert fo != null;
                added = added && addArchiveFile(fo, model, scope);
            } else {
                Logger.getLogger(CPExtender.class.getName()).info("Adding non-jar root to Maven projects makes no sense. (" + url + ")"); //NOI18N
            }
        }
        if (added) {
            try {
                WriterUtils.writePomModel(pom, model);
                ProjectURLWatcher.fireMavenProjectReload(project);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return added;
    }
    
    public boolean removeRoots(URL[] arg0, SourceGroup arg1, String arg2) throws IOException,
                                                                                    UnsupportedOperationException {
        throw new UnsupportedOperationException("Not supported yet.");//NOI18N
    }
    
    public boolean addAntArtifacts(AntArtifact[] arg0, URI[] arg1,
                                      SourceGroup arg2, String arg3) throws IOException {
        throw new IOException("Cannot add Ant based projects as subprojecs to Maven projects.");//NOI18N
    }
    
    public boolean removeAntArtifacts(AntArtifact[] arg0, URI[] arg1,
                                         SourceGroup arg2, String arg3) throws IOException {
        return false;
    }
    
    private void addJarToPrivateRepo(FileObject file, Model mdl, String[] dep) throws IOException {
        //first add the local repo to
        Iterator repos = mdl.getRepositories().iterator();
        boolean found = false;
        String path = null;
        while (repos.hasNext()) {
            org.apache.maven.model.Repository repo = (org.apache.maven.model.Repository)repos.next();
            if ("unknown-jars-temp-repo".equals(repo.getId())) { //NOI18N
                found = true;
                String url = repo.getUrl();
                if (url.startsWith("file:${project.basedir}/")) { //NOI18N
                    path = url.substring("file:${project.basedir}/".length()); //NOI18N
                } else {
                    path = "lib"; //NOI18N
                }
                break;
            }
        }
        if (!found) {
            org.apache.maven.model.Repository repo = new org.apache.maven.model.Repository();
            repo.setId("unknown-jars-temp-repo"); //NOI18N
            repo.setName("A temporary repository created by NetBeans for libraries and jars it could not identify. Please replace the dependencies in this repository with correct ones and delete this repository."); //NOI18N
            repo.setUrl("file:${project.basedir}/lib"); //NOI18N
            mdl.addRepository(repo);
            path = "lib"; //NOI18N
        }
        assert path != null;
        FileObject root = FileUtil.createFolder(project.getProjectDirectory(), path);
        FileObject grp = FileUtil.createFolder(root, dep[0].replace('.', '/')); //NOI18N
        FileObject art = FileUtil.createFolder(grp, dep[1]);
        FileObject ver = FileUtil.createFolder(art, dep[2]);
        FileUtil.copyFile(file, ver, dep[1] + "-" + dep[2], "jar"); //NOI18N
    }
    
    
    
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy