/******************************************************************************* * Copyright (c) 2012-2017 Codenvy, S.A. * 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: * Codenvy, S.A. - initial API and implementation *******************************************************************************/ package org.eclipse.che.plugin.maven.server.core.classpath; import com.google.inject.Inject; import com.google.inject.Singleton; import com.google.inject.name.Named; import org.eclipse.che.plugin.maven.server.MavenServerWrapper; import org.eclipse.che.plugin.maven.server.MavenWrapperManager; import org.eclipse.che.plugin.maven.server.core.MavenClasspathContainer; import org.eclipse.che.plugin.maven.server.core.MavenProgressNotifier; import org.eclipse.che.plugin.maven.server.core.MavenProjectManager; import org.eclipse.che.plugin.maven.server.core.project.MavenProject; import org.eclipse.che.maven.data.MavenArtifact; import org.eclipse.che.maven.data.MavenArtifactKey; import org.eclipse.che.maven.server.MavenTerminal; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.jdt.core.IClassFile; import org.eclipse.jdt.core.IClasspathAttribute; import org.eclipse.jdt.core.IClasspathContainer; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.internal.core.JavaModelManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.util.Collections; import java.util.List; /** * @author Evgen Vidolob */ @Singleton public class ClasspathManager { public static final String GROUP_ID_ATTRIBUTE = "maven.groupId"; public static final String ARTIFACT_ID_ATTRIBUTE = "maven.artifactId"; public static final String VERSION_ATTRIBUTE = "maven.version"; public static final String CLASSIFIER_ATTRIBUTE = "maven.classifier"; public static final String PACKAGING_ATTRIBUTE = "maven.packaging"; public static final String SCOPE_ATTRIBUTE = "maven.scope"; private static final String SOURCES = "sources"; private static final Logger LOG = LoggerFactory.getLogger(ClasspathManager.class); private final String workspacePath; private final MavenWrapperManager wrapperManager; private final MavenProjectManager projectManager; private final MavenTerminal terminal; private final MavenProgressNotifier notifier; private File localRepository; @Inject public ClasspathManager(@Named("che.user.workspaces.storage") String workspacePath, MavenWrapperManager wrapperManager, MavenProjectManager projectManager, MavenTerminal terminal, MavenProgressNotifier notifier) { this.workspacePath = workspacePath; this.wrapperManager = wrapperManager; this.projectManager = projectManager; this.terminal = terminal; this.notifier = notifier; MavenServerWrapper mavenServer = wrapperManager.getMavenServer(MavenWrapperManager.ServerType.DOWNLOAD); try { localRepository = mavenServer.getLocalRepository(); } catch (RuntimeException e) { // We can got this exception if maven not install in system // This is temporary solution will be fix more accurate in https://jira.codenvycorp.com/browse/CHE-1120 LOG.warn("Maven server not started looks like you don't have Maven in your path"); } finally { wrapperManager.release(mavenServer); } } public void updateClasspath(MavenProject mavenProject) { IJavaProject javaProject = JavaCore.create(mavenProject.getProject()); if (javaProject != null) { IClasspathEntry[] entries = getClasspath(mavenProject); MavenClasspathContainer container = new MavenClasspathContainer(entries); try { JavaCore.setClasspathContainer(new Path(MavenClasspathContainer.CONTAINER_ID), new IJavaProject[]{javaProject}, new IClasspathContainer[]{container}, new NullProgressMonitor()); } catch (JavaModelException e) { LOG.error(e.getMessage(), e); } } } private IClasspathEntry[] getClasspath(MavenProject mavenProject) { ClasspathHelper helper = new ClasspathHelper(true); List<MavenArtifact> dependencies = mavenProject.getDependencies(); for (MavenArtifact dependency : dependencies) { File file = dependency.getFile(); if (file == null) { continue; } ClasspathEntryHelper entry; if (file.getPath().endsWith("pom.xml")) { String path = file.getParentFile().getPath(); entry = helper.addProjectEntry(new Path(path.substring(workspacePath.length()))); } else { entry = helper.addLibraryEntry(new Path(file.getPath())); } if (entry != null) { MavenArtifactKey artifactKey = new MavenArtifactKey(dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion(), dependency.getExtension(), dependency.getClassifier()); entry.setArtifactKey(artifactKey); attachSources(entry); } } return helper.getEntries(); } private void attachSources(ClasspathEntryHelper entry) { MavenArtifactKey artifactKey = entry.getArtifactKey(); if (artifactKey != null) { File artifact = MavenLocalRepositoryUtil .getFileForArtifact(localRepository, artifactKey.getGroupId(), artifactKey.getArtifactId(), artifactKey.getVersion(), SOURCES, artifactKey.getPackaging()); if(artifact.exists()){ entry.setSourcePath(new Path(artifact.getAbsolutePath())); } } } public boolean downloadSources(String projectPath, String fqn) { IJavaProject javaProject = JavaModelManager.getJavaModelManager().getJavaModel().getJavaProject(projectPath); try { IType type = javaProject.findType(fqn); if (type != null && type.isBinary()) { IClassFile classFile = type.getClassFile(); if (classFile.getSourceRange() == null) { IJavaElement element = classFile; while (element.getParent() != null) { element = element.getParent(); if (element instanceof IPackageFragmentRoot) { IPackageFragmentRoot root = (IPackageFragmentRoot)element; if (root.getSourceAttachmentPath() == null) { return downloadSources(root); } } } } } } catch (JavaModelException e) { LOG.error(e.getMessage(), e); } return false; } private boolean downloadSources(IPackageFragmentRoot fragmentRoot) throws JavaModelException { fragmentRoot.getAdapter(MavenArtifactKey.class); IClasspathEntry classpathEntry = fragmentRoot.getResolvedClasspathEntry(); MavenArtifactKey artifactKey = getArtifactKey(classpathEntry); if (artifactKey != null) { MavenServerWrapper mavenServer = wrapperManager.getMavenServer(MavenWrapperManager.ServerType.DOWNLOAD); try { mavenServer.customize(projectManager.copyWorkspaceCache(), terminal, notifier, false, false); MavenArtifactKey sourceKey = new MavenArtifactKey(artifactKey.getGroupId(), artifactKey.getArtifactId(), artifactKey.getVersion(), artifactKey.getPackaging(), SOURCES); MavenArtifact mavenArtifact = mavenServer.resolveArtifact(sourceKey, Collections.emptyList()); if (mavenArtifact.isResolved()) { updateClasspath(projectManager.findMavenProject(fragmentRoot.getJavaProject().getProject())); } return mavenArtifact.isResolved(); } finally { wrapperManager.release(mavenServer); } } return false; } private MavenArtifactKey getArtifactKey(IClasspathEntry classpathEntry) { IClasspathAttribute[] attributes = classpathEntry.getExtraAttributes(); String groupId = null; String artifactId = null; String version = null; String packaging = null; String classifier = null; for (IClasspathAttribute attribute : attributes) { if (ClasspathManager.GROUP_ID_ATTRIBUTE.equals(attribute.getName())) { groupId = attribute.getValue(); } else if (ClasspathManager.ARTIFACT_ID_ATTRIBUTE.equals(attribute.getName())) { artifactId = attribute.getValue(); } else if (ClasspathManager.VERSION_ATTRIBUTE.equals(attribute.getName())) { version = attribute.getValue(); } else if (ClasspathManager.PACKAGING_ATTRIBUTE.equals(attribute.getName())) { packaging = attribute.getValue(); } else if (ClasspathManager.CLASSIFIER_ATTRIBUTE.equals(attribute.getName())) { classifier = attribute.getValue(); } } if (groupId != null && artifactId != null && version != null) { return new MavenArtifactKey(groupId, artifactId, version, packaging, classifier); } return null; } }