Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.bndtools.builder.handlers.baseline.BaselineErrorHandler Maven / Gradle / Ivy
package org.bndtools.builder.handlers.baseline;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.bndtools.api.BndtoolsConstants;
import org.bndtools.api.ILogger;
import org.bndtools.api.Logger;
import org.bndtools.build.api.AbstractBuildErrorDetailsHandler;
import org.bndtools.build.api.MarkerData;
import org.bndtools.builder.utils.MemberValuePairLocationRetriever;
import org.bndtools.utils.jdt.ASTUtil;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.IAnnotation;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaModelMarker;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageDeclaration;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.ISourceRange;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jface.text.contentassist.CompletionProposal;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.ui.IMarkerResolution;
import org.osgi.util.function.Predicate;
import aQute.bnd.build.Project;
import aQute.bnd.differ.Baseline.Info;
import aQute.bnd.properties.IRegion;
import aQute.bnd.properties.LineType;
import aQute.bnd.properties.PropertiesLineReader;
import aQute.bnd.service.diff.Delta;
import aQute.bnd.service.diff.Diff;
import aQute.bnd.service.diff.Tree;
import aQute.bnd.service.diff.Type;
import aQute.lib.io.IO;
import aQute.service.reporter.Report.Location;
public class BaselineErrorHandler extends AbstractBuildErrorDetailsHandler {
private static final String PACKAGEINFO = "packageinfo";
private static final String PACKAGEINFOJAVA = "package-info.java";
private static final String PROP_SUGGESTED_VERSION = "suggestedVersion";
private static final String ANNOTATION_VERSION_BND_PKG = "aQute.bnd.annotation";
private static final String ANNOTATION_VERSION_OSGI_PKG = "org.osgi.annotation.versioning";
private static final String ANNOTATION_VERSION_NO_PKG = "Version";
private static final String ANNOTATION_VERSION_BND = ANNOTATION_VERSION_BND_PKG + "." + ANNOTATION_VERSION_NO_PKG;
private static final String ANNOTATION_VERSION_OSGI = ANNOTATION_VERSION_OSGI_PKG + "." + ANNOTATION_VERSION_NO_PKG;
private static final ILogger logger = Logger.getLogger(BaselineErrorHandler.class);
@Override
public List generateMarkerData(IProject project, Project model, Location location) throws Exception {
List result = new LinkedList();
Info baselineInfo = (Info) location.details;
IJavaProject javaProject = JavaCore.create(project);
result.addAll(generatePackageInfoMarkers(baselineInfo, javaProject, location.message));
result.addAll(generateStructuralChangeMarkers(baselineInfo, javaProject));
return result;
}
List generatePackageInfoMarkers(Info baselineInfo, IJavaProject javaProject, String message) throws JavaModelException {
List markers = new LinkedList<>();
for (IClasspathEntry entry : javaProject.getRawClasspath()) {
if (IClasspathEntry.CPE_SOURCE == entry.getEntryKind()) {
IPath entryPath = entry.getPath();
IPath pkgPath = entryPath.append(baselineInfo.packageName.replace('.', '/'));
// Find in packageinfo file
IPath pkgInfoPath = pkgPath.append(PACKAGEINFO);
IFile pkgInfoFile = javaProject.getProject()
.getWorkspace()
.getRoot()
.getFile(pkgInfoPath);
if (pkgInfoFile != null && pkgInfoFile.exists()) {
Map attribs = new HashMap();
attribs.put(IMarker.MESSAGE, message.trim());
attribs.put(PROP_SUGGESTED_VERSION, baselineInfo.suggestedVersion.toString());
LineLocation lineLoc = findVersionLocation(pkgInfoFile.getLocation()
.toFile());
if (lineLoc != null) {
attribs.put(IMarker.LINE_NUMBER, lineLoc.lineNum);
attribs.put(IMarker.CHAR_START, lineLoc.start);
attribs.put(IMarker.CHAR_END, lineLoc.end);
}
markers.add(new MarkerData(pkgInfoFile, attribs, true));
}
// Find in package-info.java
IPackageFragment pkg = javaProject.findPackageFragment(pkgPath);
if (pkg != null) {
ICompilationUnit pkgInfoJava = pkg.getCompilationUnit(PACKAGEINFOJAVA);
if (pkgInfoJava != null && pkgInfoJava.exists()) {
ISourceRange range = findPackageInfoJavaVersionLocation(baselineInfo.packageName, pkgInfoJava);
Map attribs = new HashMap();
attribs.put(IMarker.MESSAGE, message.trim());
attribs.put(IJavaModelMarker.ID, 8088);
attribs.put(PROP_SUGGESTED_VERSION, baselineInfo.suggestedVersion.toString());
if (range != null) {
attribs.put(IMarker.CHAR_START, range.getOffset());
attribs.put(IMarker.CHAR_END, range.getOffset() + range.getLength());
markers.add(new MarkerData(pkgInfoJava.getResource(), attribs, true, BndtoolsConstants.MARKER_JAVA_BASELINE));
}
}
}
}
}
return markers;
}
ISourceRange findPackageInfoJavaVersionLocation(String packageName, ICompilationUnit compUnit) throws JavaModelException {
ISourceRange range = null;
IPackageDeclaration[] pkgDecls = compUnit.getPackageDeclarations();
if (pkgDecls != null) {
for (IPackageDeclaration pkgDecl : pkgDecls) {
if (packageName.equals(pkgDecl.getElementName())) {
IAnnotation[] annots = pkgDecl.getAnnotations();
for (IAnnotation annot : annots) {
String name = annot.getElementName();
if (ANNOTATION_VERSION_NO_PKG.equals(name) || ANNOTATION_VERSION_OSGI.equals(name) || ANNOTATION_VERSION_BND.equals(name)) {
ASTParser parser = ASTParser.newParser(AST.JLS10);
parser.setKind(ASTParser.K_COMPILATION_UNIT);
parser.setSource(compUnit);
parser.setResolveBindings(true);
CompilationUnit ast = (CompilationUnit) parser.createAST(null);
if (ast != null) {
MemberValuePairLocationRetriever mvpRetriever = new MemberValuePairLocationRetriever(annot, new Predicate() {
@Override
public boolean test(String t) {
return ANNOTATION_VERSION_BND.equals(t) || ANNOTATION_VERSION_OSGI.equals(t);
}
}, "value");
ast.accept(mvpRetriever);
range = mvpRetriever.getMemberValuePairSourceRange();
}
}
}
}
}
}
return range;
}
List generateStructuralChangeMarkers(Info baselineInfo, IJavaProject javaProject) throws JavaModelException {
List markers = new LinkedList();
Delta packageDelta = baselineInfo.packageDiff.getDelta();
// Iterate into the package member diffs
for (Diff pkgMemberDiff : baselineInfo.packageDiff.getChildren()) {
// Skip deltas that have lesser significance than the overall package delta
if (pkgMemberDiff.getDelta()
.ordinal() < packageDelta.ordinal())
continue;
if (Delta.ADDED == pkgMemberDiff.getDelta()) {
@SuppressWarnings("unused")
Tree pkgMember = pkgMemberDiff.getNewer();
// markers.addAll(generateAddedTypeMarker(javaProject, pkgMember.getName(), pkgMember.ifAdded()));
} else if (Delta.REMOVED == pkgMemberDiff.getDelta()) {
} else {
Tree pkgMember = pkgMemberDiff.getOlder();
if (pkgMember != null && (Type.INTERFACE == pkgMember.getType() || Type.CLASS == pkgMember.getType())) {
String className = pkgMember.getName();
// Iterate into the class member diffs
for (Diff classMemberDiff : pkgMemberDiff.getChildren()) {
// Skip deltas that have lesser significance than the overall package delta (again)
if (classMemberDiff.getDelta()
.ordinal() < packageDelta.ordinal())
continue;
if (Delta.ADDED == classMemberDiff.getDelta()) {
Tree classMember = classMemberDiff.getNewer();
if (Type.METHOD == classMember.getType())
markers.addAll(generateAddedMethodMarker(javaProject, className, classMember.getName(), classMember.ifAdded()));
} else if (Delta.REMOVED == classMemberDiff.getDelta()) {
Tree classMember = classMemberDiff.getOlder();
if (Type.METHOD == classMember.getType()) {
markers.addAll(generateRemovedMethodMarker(javaProject, className, classMember.getName(), classMember.ifRemoved()));
}
}
}
}
}
}
return markers;
}
/*
* List generateAddedTypeMarker(IJavaProject javaProject, String name, Delta ifAdded) { // TODO
* Auto-generated method stub return null; }
*/
List generateAddedMethodMarker(IJavaProject javaProject, String className, final String methodName, final Delta requiresDelta) throws JavaModelException {
final List markers = new LinkedList();
final CompilationUnit ast = createAST(javaProject, className);
if (ast != null) {
ast.accept(new ASTVisitor() {
@Override
public boolean visit(MethodDeclaration methodDecl) {
String signature = ASTUtil.buildMethodSignature(methodDecl);
if (signature.equals(methodName)) {
// Create the marker attribs here
Map attribs = new HashMap();
attribs.put(IMarker.CHAR_START, methodDecl.getStartPosition());
attribs.put(IMarker.CHAR_END, methodDecl.getStartPosition() + methodDecl.getLength());
String message = String.format("This method was added, which requires a %s change to the package.", requiresDelta);
attribs.put(IMarker.MESSAGE, message);
markers.add(new MarkerData(ast.getJavaElement()
.getResource(), attribs, false));
}
return false;
}
});
}
return markers;
}
List generateRemovedMethodMarker(IJavaProject javaProject, final String className, final String methodName, final Delta requiresDelta) throws JavaModelException {
final List markers = new LinkedList();
final CompilationUnit ast = createAST(javaProject, className);
if (ast != null) {
ast.accept(new ASTVisitor() {
@Override
public boolean visit(TypeDeclaration typeDecl) {
ITypeBinding typeBinding = typeDecl.resolveBinding();
if (typeBinding != null) {
if (typeBinding.getBinaryName()
.equals(className)) {
Map attribs = new HashMap();
SimpleName nameNode = typeDecl.getName();
attribs.put(IMarker.CHAR_START, nameNode.getStartPosition());
attribs.put(IMarker.CHAR_END, nameNode.getStartPosition() + nameNode.getLength());
String message = String.format("The method '%s' was removed, which requires a %s change to the package.", methodName, requiresDelta);
attribs.put(IMarker.MESSAGE, message);
markers.add(new MarkerData(ast.getJavaElement()
.getResource(), attribs, false));
return false;
}
}
return true;
}
});
}
return markers;
}
@Override
public List getResolutions(IMarker marker) {
List result = new LinkedList();
final String suggestedVersion = marker.getAttribute(PROP_SUGGESTED_VERSION, null);
if (suggestedVersion != null) {
result.add(new IMarkerResolution() {
@Override
public void run(IMarker marker) {
final IFile file = (IFile) marker.getResource();
final IWorkspace workspace = file.getWorkspace();
try {
workspace.run(new IWorkspaceRunnable() {
@Override
public void run(IProgressMonitor monitor) throws CoreException {
String input = "version " + suggestedVersion;
ByteArrayInputStream stream = new ByteArrayInputStream(input.getBytes());
file.setContents(stream, false, true, monitor);
}
}, null);
} catch (CoreException e) {
logger.logError("Error applying baseline version quickfix.", e);
}
}
@Override
public String getLabel() {
return "Change package version to " + suggestedVersion;
}
});
}
return result;
}
@Override
public List getProposals(IMarker marker) {
List proposals = new LinkedList();
String suggestedVersion = marker.getAttribute(PROP_SUGGESTED_VERSION, null);
int start = marker.getAttribute(IMarker.CHAR_START, 0);
int end = marker.getAttribute(IMarker.CHAR_END, 0);
CompletionProposal proposal = new CompletionProposal("version " + suggestedVersion, start, end - start, end, null, "Change package version to " + suggestedVersion, null, null);
proposals.add(proposal);
return proposals;
}
private LineLocation findVersionLocation(File file) {
String content;
try {
content = IO.collect(file);
PropertiesLineReader reader = new PropertiesLineReader(content);
int lineNum = 1;
LineType type = reader.next();
while (type != LineType.eof) {
if (type == LineType.entry) {
String key = reader.key();
if ("version".equals(key)) {
LineLocation loc = new LineLocation();
loc.lineNum = lineNum;
IRegion region = reader.region();
loc.start = region.getOffset();
loc.end = region.getOffset() + region.getLength();
return loc;
}
}
type = reader.next();
lineNum++;
}
} catch (Exception e) {
// ignore
}
return null;
}
}