Commit 80d36e3a authored by Andrey Loskutov's avatar Andrey Loskutov

Use IClassFile.getBytes() added in Eclipse 3.3, see bug 150244

parent 3259e7e0
......@@ -15,14 +15,8 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
......@@ -30,9 +24,6 @@ import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFolder;
......@@ -69,7 +60,6 @@ import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.core.search.SearchPattern;
import org.eclipse.jdt.core.search.TypeNameRequestor;
import org.eclipse.jdt.internal.compiler.util.Util;
import org.eclipse.jdt.internal.core.JavaElement;
import org.eclipse.jface.text.ITextSelection;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.InnerClassNode;
......@@ -858,21 +848,15 @@ public class JdtUtils {
public static InputStream createInputStream(IJavaElement javaElement) {
IClassFile classFile = (IClassFile) javaElement
.getAncestor(IJavaElement.CLASS_FILE);
InputStream is = null;
// existing read-only class files
if (classFile != null) {
IJavaElement jarParent = classFile.getParent();
// TODO dirty hack to be sure, that package is from jar -
// because JarPackageFragment is not public class, we cannot
// use instanceof here
boolean isJar = jarParent != null
&& jarParent.getClass().getName()
.endsWith("JarPackageFragment"); //$NON-NLS-1$
if (isJar) {
is = createStreamFromJar(classFile);
} else {
is = createStreamFromClass(classFile);
byte[] bytes;
try {
bytes = classFile.getBytes();
return new ByteArrayInputStream(bytes);
} catch (JavaModelException e) {
BytecodeOutlinePlugin.log(e, IStatus.ERROR);
}
} else {
// usual eclipse - generated bytecode
......@@ -882,9 +866,11 @@ public class JdtUtils {
return null;
}
String classPath = getByteCodePath(javaElement);
if(classPath.isEmpty()) {
return null;
}
try (FileInputStream fis = new FileInputStream(classPath)){
is = createInMemoryStream(fis);
return createInMemoryStream(fis);
} catch (IOException e) {
// if autobuild is disabled, we get tons of this errors.
// but I think we cannot ignore them, therefore WARNING and not
......@@ -892,124 +878,14 @@ public class JdtUtils {
BytecodeOutlinePlugin.log(e, IStatus.WARNING);
}
}
return is;
}
/**
* Creates stream from external class file from Eclipse classpath (means, that this
* class file is read-only)
* @param classFile
* @return new generated input stream from external class file, or null, if class file
* for this element cannot be found
*/
private static InputStream createStreamFromClass(IClassFile classFile) {
IResource underlyingResource = null;
try {
// to tell the truth, I don't know why that different methods
// are not working in a particular case. But it seems to be better
// to use getResource() with non-java elements (not in model)
// and getUnderlyingResource() with java elements.
if (classFile.exists()) {
underlyingResource = classFile.getUnderlyingResource();
} else {
// this is a class file that is not in java model
underlyingResource = classFile.getResource();
}
if(underlyingResource == null){
// Looks like class folders are different...
underlyingResource = ((JavaElement)classFile).resource();
}
} catch (JavaModelException e) {
BytecodeOutlinePlugin.log(e, IStatus.ERROR);
return null;
}
if(underlyingResource == null) {
return null;
}
IPath rawLocation = underlyingResource.getRawLocation();
// here we should resolve path variables,
// probably existing at first place of "rawLocation" path
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IPathVariableManager pathManager = workspace.getPathVariableManager();
rawLocation = pathManager.resolvePath(rawLocation);
try (FileInputStream fis = new FileInputStream(rawLocation.toOSString())){
return createInMemoryStream(fis);
} catch (IOException e) {
BytecodeOutlinePlugin.log(e, IStatus.ERROR);
}
return null;
}
static InputStream createInMemoryStream(InputStream stream) throws IOException {
private static InputStream createInMemoryStream(InputStream stream) throws IOException {
byte[] array = Util.getInputStreamAsByteArray(stream, -1);
return new ByteArrayInputStream(array);
}
/**
* Creates stream from external class file that is stored in jar file
* @param classFile
* @param javaElement
* @return new generated input stream from external class file that is stored in jar
* file, or null, if class file for this element cannot be found
*/
private static InputStream createStreamFromJar(IClassFile classFile) {
IPath path = null;
IResource resource = classFile.getResource();
// resource == null => this is a external archive
if (resource != null) {
path = resource.getRawLocation();
} else {
path = classFile.getPath();
}
if (path == null) {
return null;
}
// here we should resolve path variables,
// probably existing at first place of path
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IPathVariableManager pathManager = workspace.getPathVariableManager();
path = pathManager.resolvePath(path);
String fullClassName = getFullBytecodeName(classFile);
if (fullClassName == null) {
return null;
}
try (JarFile jar = new JarFile(path.toOSString())) {
JarEntry jarEntry = jar.getJarEntry(fullClassName);
if (jarEntry != null) {
try (InputStream is = jar.getInputStream(jarEntry)){
return createInMemoryStream(is);
}
}
} catch (IOException e) {
BytecodeOutlinePlugin.log(e, IStatus.ERROR);
return null;
}
if(path.lastSegment().equals("jrt-fs.jar")){
// JarEntryFile jef = new JarEntryFile(simpleName)
URL url;
try {
url = Paths.get(path.toOSString()).toUri().toURL();
try (URLClassLoader loader = new URLClassLoader(new URL[]{url});
FileSystem fs = FileSystems.newFileSystem(
URI.create("jrt:/"), Collections.emptyMap(), loader);) {
Path top = fs.getPath("/");
Optional<Path> first = Files.walk(top).filter(Files::isRegularFile).filter(p -> p.endsWith(fullClassName)).findFirst();
if(first.isPresent()){
try (InputStream is = Files.newInputStream(first.get())){
return createInMemoryStream(is);
}
}
}
} catch (IOException e) {
BytecodeOutlinePlugin.log(e, IStatus.ERROR);
}
}
return null;
}
private static boolean isOnClasspath(IJavaElement javaElement) {
IJavaProject project = javaElement.getJavaProject();
if (project != null) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment