/*******************************************************************************
* 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.testing.classpath.maven.server;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Paths;
import java.util.stream.Stream;
import org.eclipse.che.ide.ext.java.shared.dto.classpath.ClasspathEntryDto;
import org.eclipse.che.plugin.java.server.rest.ClasspathServiceInterface;
import org.eclipse.che.plugin.testing.classpath.server.TestClasspathProvider;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.JavaModelException;
import com.google.inject.Inject;
/**
* Maven implementation for the test classpath provider.
*
* @author Mirage Abeysekara
* @author David Festal
*/
public class MavenTestClasspathProvider implements TestClasspathProvider {
private ClasspathServiceInterface classpathService;
@Inject
public MavenTestClasspathProvider(ClasspathServiceInterface classpathService) {
this.classpathService = classpathService;
}
/**
* {@inheritDoc}
*/
@Override
public ClassLoader getClassLoader(String projectAbsolutePath, String projectRelativePath, boolean updateClasspath) throws Exception {
try {
return new URLClassLoader(getProjectClasspath(projectAbsolutePath, projectRelativePath, getWorkspaceRoot()), null);
} catch (JavaModelException e) {
throw new Exception("Failed to build the classpath for testing project: " + projectRelativePath, e);
}
}
/**
* {@inheritDoc}
*/
@Override
public String getProjectType() {
return "maven";
}
private Stream<ClasspathEntryDto> toResolvedClassPath(Stream<ClasspathEntryDto> rawClasspath) {
return rawClasspath.flatMap(dto -> {
if (dto.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
return toResolvedClassPath(dto.getExpandedEntries().stream());
} else {
return Stream.of(dto);
}
});
}
private IWorkspaceRoot getWorkspaceRoot() {
return ResourcesPlugin.getWorkspace().getRoot();
}
public URL[] getProjectClasspath(String projectAbsolutePath, String projectRelativePath, IWorkspaceRoot root) throws JavaModelException {
Stream<ClasspathEntryDto> rawClasspath = classpathService.getClasspath(projectRelativePath).stream();
Stream<ClasspathEntryDto> resolvedClasspath = toResolvedClassPath(rawClasspath);
return resolvedClasspath.map(dto -> {
try {
String dtoPath = dto.getPath();
IResource res = root.findMember(new Path(dtoPath));
File path;
switch (dto.getEntryKind()) {
case IClasspathEntry.CPE_LIBRARY:
if (res == null) {
path = new File(dtoPath);
} else {
path = res.getLocation().toFile();
}
break;
case IClasspathEntry.CPE_SOURCE:
IPath relativePathFromProjectRoot = new Path(dtoPath).removeFirstSegments(1);
String relativePathFromProjectRootStr = relativePathFromProjectRoot.toString();
switch (relativePathFromProjectRootStr) {
case "src/main/java":
path = Paths.get(projectAbsolutePath, "target", "classes").toFile();
break;
case "src/test/java":
path = Paths.get(projectAbsolutePath, "target", "test-classes").toFile();
break;
default:
path = Paths.get(projectAbsolutePath, "target", "classes").toFile();
}
break;
default:
path = new File(dtoPath);
}
return path.toURI().toURL();
} catch (MalformedURLException e) {
return null;
}
}).filter(url -> url != null).distinct().toArray(URL[]::new);
}
}