Skip to content
This repository has been archived by the owner on Oct 1, 2020. It is now read-only.

Commit

Permalink
SF #3489951: Don't process class files in team provider folders.
Browse files Browse the repository at this point in the history
  • Loading branch information
marchof committed Feb 24, 2012
1 parent 3a8d6ad commit 8cf5e30
Show file tree
Hide file tree
Showing 5 changed files with 226 additions and 38 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006, 2011 Mountainminds GmbH & Co. KG and Contributors
* Copyright (c) 2006, 2012 Mountainminds GmbH & Co. KG and Contributors
* 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
Expand All @@ -11,9 +11,12 @@
******************************************************************************/
package com.mountainminds.eclemma.core;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;

import junit.framework.Assert;
Expand Down Expand Up @@ -132,6 +135,24 @@ public IPackageFragmentRoot createJAR(String jarsrc, String jarpath,
return packageRoot;
}

public IPackageFragmentRoot createExternalJAR(String jarsrc,
IPath sourceAttachmentPath, IPath sourceAttachmentRootPath)
throws CoreException, IOException {
File jarfile = File.createTempFile("test", ".jar");
InputStream source = openTestResource(new Path(jarsrc));
OutputStream out = new FileOutputStream(jarfile);
byte[] buffer = new byte[1024];
int len;
while ((len = source.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
IPackageFragmentRoot packageRoot = javaProject
.getPackageFragmentRoot(jarfile.getAbsolutePath());
addClassPathEntry(JavaCore.newLibraryEntry(packageRoot.getPath(),
sourceAttachmentPath, sourceAttachmentRootPath));
return packageRoot;
}

public void addProjectReference(JavaProjectKit otherProject)
throws CoreException {
addClassPathEntry(JavaCore.newProjectEntry(otherProject.project
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006, 2011 Mountainminds GmbH & Co. KG and Contributors
* Copyright (c) 2006, 2012 Mountainminds GmbH & Co. KG and Contributors
* 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
Expand Down Expand Up @@ -80,4 +80,15 @@ public void testJar() throws Exception {
assertNotNull(nodes.getClassCoverage("signatureresolver/Samples"));
}

@Test
public void testExternalJar() throws Exception {
final IPackageFragmentRoot root = javaProject.createExternalJAR(
"testdata/bin/signatureresolver.jar", null, null);

JavaProjectKit.waitForBuild();

final AnalyzedNodes nodes = analyzer.analyze(root);
assertNotNull(nodes.getClassCoverage("signatureresolver/Samples"));
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006, 2011 Mountainminds GmbH & Co. KG and Contributors
* Copyright (c) 2006, 2012 Mountainminds GmbH & Co. KG and Contributors
* 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
Expand All @@ -15,7 +15,6 @@
import java.util.Map;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jdt.core.IPackageFragmentRoot;
Expand All @@ -33,61 +32,81 @@
final class PackageFragementRootAnalyzer {

private final ExecutionDataStore executiondata;
private final Map<IPath, AnalyzedNodes> cache;
private final Map<Object, AnalyzedNodes> cache;

PackageFragementRootAnalyzer(final ExecutionDataStore executiondata) {
this.executiondata = executiondata;
this.cache = new HashMap<IPath, AnalyzedNodes>();
this.cache = new HashMap<Object, AnalyzedNodes>();
}

AnalyzedNodes analyze(final IPackageFragmentRoot root) throws CoreException {
final IPath path = getClassfilesLocation(root);
AnalyzedNodes nodes = cache.get(path);
if (nodes == null) {
nodes = analyze(root, path);
cache.put(path, nodes);
if (root.isExternal()) {
return analyzeExternal(root);
} else {
return analyzeInternal(root);
}
return nodes;
}

private AnalyzedNodes analyze(final IPackageFragmentRoot root,
final IPath path) throws CoreException {
final CoverageBuilder builder = new CoverageBuilder();
final Analyzer analyzer = new Analyzer(executiondata, builder);

private AnalyzedNodes analyzeInternal(final IPackageFragmentRoot root)
throws CoreException {
IResource location = null;
try {
analyzer.analyzeAll(path.toFile());
location = getClassfilesLocation(root);

AnalyzedNodes nodes = cache.get(location);
if (nodes != null) {
return nodes;
}

final CoverageBuilder builder = new CoverageBuilder();
final Analyzer analyzer = new Analyzer(executiondata, builder);
new ResourceTreeWalker(analyzer).walk(location);
nodes = new AnalyzedNodes(builder.getClasses(), builder.getSourceFiles());
cache.put(location, nodes);
return nodes;
} catch (Exception e) {
throw new CoreException(EclEmmaStatus.BUNDLE_ANALYSIS_ERROR.getStatus(
root.getElementName(), path, e));
root.getElementName(), location, e));
}

return new AnalyzedNodes(builder.getClasses(), builder.getSourceFiles());
}

private IPath getClassfilesLocation(IPackageFragmentRoot root)
private AnalyzedNodes analyzeExternal(final IPackageFragmentRoot root)
throws CoreException {
IPath location = null;
try {
location = root.getPath();

// 1. Find path depending on root type (source/binary)
IPath path;
if (root.getKind() == IPackageFragmentRoot.K_SOURCE) {
path = root.getRawClasspathEntry().getOutputLocation();
if (path == null) {
path = root.getJavaProject().getOutputLocation();
AnalyzedNodes nodes = cache.get(location);
if (nodes != null) {
return nodes;
}
} else {
path = root.getPath();

final CoverageBuilder builder = new CoverageBuilder();
final Analyzer analyzer = new Analyzer(executiondata, builder);
new ResourceTreeWalker(analyzer).walk(location);
nodes = new AnalyzedNodes(builder.getClasses(), builder.getSourceFiles());
cache.put(location, nodes);
return nodes;
} catch (Exception e) {
throw new CoreException(EclEmmaStatus.BUNDLE_ANALYSIS_ERROR.getStatus(
root.getElementName(), location, e));
}
}

// 2. Determine absolute path
if (path.getDevice() == null) {
final IWorkspace ws = root.getJavaProject().getProject().getWorkspace();
final IResource res = ws.getRoot().findMember(path);
if (res != null) {
return res.getLocation();
}
private IResource getClassfilesLocation(IPackageFragmentRoot root)
throws CoreException {

// For binary roots the underlying resource directly points to class files:
if (root.getKind() == IPackageFragmentRoot.K_BINARY) {
return root.getResource();
}

// For source roots we need to find the corresponding output folder:
IPath path = root.getRawClasspathEntry().getOutputLocation();
if (path == null) {
path = root.getJavaProject().getOutputLocation();
}
return path;
return root.getResource().getWorkspace().getRoot().findMember(path);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/*******************************************************************************
* Copyright (c) 2006, 2012 Mountainminds GmbH & Co. KG and Contributors
* 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
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Marc R. Hoffmann - initial API and implementation
*
******************************************************************************/
package com.mountainminds.eclemma.internal.core.analysis;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.jacoco.core.analysis.Analyzer;

/**
* Internal utility to walk through a resource tree and identify all class
* files.
*/
class ResourceTreeWalker {

private final Analyzer analyzer;

public ResourceTreeWalker(Analyzer analyzer) {
this.analyzer = analyzer;
}

public void walk(IResource resource) throws CoreException, IOException {
if (resource.getType() == IResource.FILE) {
final IFile file = (IFile) resource;
final InputStream in = file.getContents(true);
try {
analyzer.analyzeArchive(in);
} finally {
in.close();
}
} else {
walkResource(resource);
}
}

private void walkResource(IResource resource) throws CoreException,
IOException {
switch (resource.getType()) {
case IResource.FILE:
if (resource.getName().endsWith(".class")) { //$NON-NLS-1$
final IFile file = (IFile) resource;
final InputStream in = file.getContents(true);
try {
analyzer.analyzeAll(in);
} finally {
in.close();
}
}
break;
case IResource.FOLDER:
case IResource.PROJECT:
// Do not traverse into folders like ".svn"
if (isJavaIdentifier(resource.getName())) {
final IContainer container = (IContainer) resource;
for (final IResource child : container.members()) {
walkResource(child);
}
}
break;
}
}

public void walk(IPath path) throws IOException {
final File file = path.toFile();
if (file.isFile()) {
final InputStream in = open(file);
try {
analyzer.analyzeArchive(in);
} finally {
in.close();
}
} else {
walkFile(file);
}
}

private void walkFile(File file) throws IOException {
if (file.isFile()) {
if (file.getName().endsWith(".class")) { //$NON-NLS-1$
final InputStream in = open(file);
try {
analyzer.analyzeAll(in);
} finally {
in.close();
}
}
} else {
// Do not traverse into folders like ".svn"
if (isJavaIdentifier(file.getName())) {
for (final File child : file.listFiles()) {
walkFile(child);
}
}
}
}

private BufferedInputStream open(final File file)
throws FileNotFoundException {
return new BufferedInputStream(new FileInputStream(file));
}

private boolean isJavaIdentifier(String name) {
for (int i = 0; i < name.length(); i++) {
final char c = name.charAt(i);
if (i == 0) {
if (!Character.isJavaIdentifierStart(c)) {
return false;
}
} else {
if (!Character.isJavaIdentifierPart(c)) {
return false;
}
}
}
return true;
}

}
1 change: 1 addition & 0 deletions com.mountainminds.eclemma.doc/pages/changes.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ <h2>Trunk</h2>
<li>Trac #168: New editor for JaCoCo execution data files.</li>
<li>Trac #190: The <i>Coverage</i> view option <i>Hide Unused Types</i> has
been generalized to <i>Hide Unused Elements</i>.</li>
<li>SF #3489951: Don't process class files in team provider folders.</li>
<li>SF #3487904: Avoid NPE in case of new and empty launch configurations.</li>
<li>SF #3477725: Java agent must not be added multiple times to plug-in
launch configurations.</li>
Expand Down

0 comments on commit 8cf5e30

Please sign in to comment.