package bndtools.editor.contents;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
import org.bndtools.api.ILogger;
import org.bndtools.api.Logger;
import org.eclipse.core.resources.IProject;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.osgi.framework.Version;
import aQute.lib.io.IO;
/**
* Models the three available styles for versioning exported packages.
*/
public enum PackageInfoStyle {
/**
* The legacy, flat file format supported by bnd. This is still used for Java 4 (and earlier) projects).
*/
Legacy("packageinfo", "version %s%n", null),
/**
* Annotated package-info.java, using the bnd annotations.
*/
BndAnnotation("package-info.java", "@aQute.bnd.annotation.Version(\"%s\")%npackage %s;%n", "aQute.bnd.annotation.Version"),
/**
* Annotated package-info.java, using the OSGi spec annotations from R6.
*/
SpecAnnotation("package-info.java", "@org.osgi.annotation.versioning.Version(\"%s\")%npackage %s;%n", "org.osgi.annotation.versioning.Version");
private static final ILogger logger = Logger.getLogger(PackageInfoStyle.class);
private static final Set<String> PRE_JAVA5_VERSIONS;
static {
PRE_JAVA5_VERSIONS = new HashSet<String>();
PRE_JAVA5_VERSIONS.add(JavaCore.VERSION_CLDC_1_1);
PRE_JAVA5_VERSIONS.add(JavaCore.VERSION_1_1);
PRE_JAVA5_VERSIONS.add(JavaCore.VERSION_1_2);
PRE_JAVA5_VERSIONS.add(JavaCore.VERSION_1_3);
PRE_JAVA5_VERSIONS.add(JavaCore.VERSION_1_4);
}
private final String fileName;
private final String contentPattern;
private final String annotationTypeName;
private final Pattern searchRegex;
PackageInfoStyle(String fileName, String contentPattern, String annotationTypeName) {
this.fileName = fileName;
this.contentPattern = contentPattern;
this.annotationTypeName = annotationTypeName;
this.searchRegex = annotationTypeName != null ? Pattern.compile("\\Q" + annotationTypeName + "\\E") : null;
}
public String getFileName() {
return fileName;
}
public String format(Version version, String packageName) {
return String.format(contentPattern, version, packageName);
}
public static PackageInfoStyle findExisting(File dir) throws IOException {
File packageInfoJava = new File(dir, SpecAnnotation.fileName);
if (packageInfoJava.exists()) {
String content = IO.collect(packageInfoJava);
if (SpecAnnotation.searchRegex.matcher(content).find())
return SpecAnnotation;
if (BndAnnotation.searchRegex.matcher(content).find())
return BndAnnotation;
return null;
}
File legacyPackageInfo = new File(dir, Legacy.fileName);
if (legacyPackageInfo.exists())
return Legacy;
return null;
}
public static PackageInfoStyle calculatePackageInfoStyle(IProject project) {
IJavaProject javaProject = JavaCore.create(project);
if (javaProject == null)
return Legacy;
// JDK Compliance and Java Source level must both be at least 1.5 to support
// annotated package-info.java
String compliance = javaProject.getOption(JavaCore.COMPILER_COMPLIANCE, true);
if (compliance == null || PRE_JAVA5_VERSIONS.contains(compliance))
return Legacy;
String sourceLevel = javaProject.getOption(JavaCore.COMPILER_SOURCE, true);
if (sourceLevel == null || PRE_JAVA5_VERSIONS.contains(sourceLevel))
return Legacy;
try {
IType specAnnotation = javaProject.findType(SpecAnnotation.annotationTypeName);
if (specAnnotation != null)
return SpecAnnotation;
IType bndAnnotation = javaProject.findType(BndAnnotation.annotationTypeName);
if (bndAnnotation != null)
return BndAnnotation;
} catch (JavaModelException e) {
logger.logError("Could not determine classpath visibility for versioning annotations.", e);
}
return Legacy;
}
}