package io.takari.maven.plugins.compile.jdt.classpath;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
import org.eclipse.jdt.internal.compiler.env.AccessRule;
import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
import org.eclipse.osgi.framework.util.Headers;
import org.eclipse.osgi.util.ManifestElement;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.CharStreams;
import com.google.common.io.LineProcessor;
import io.takari.maven.plugins.exportpackage.ExportPackageMojo;
public abstract class DependencyClasspathEntry implements ClasspathEntry {
protected static final String PATH_EXPORT_PACKAGE = ExportPackageMojo.PATH_EXPORT_PACKAGE;
protected static final String PATH_MANIFESTMF = "META-INF/MANIFEST.MF";
protected final File file;
protected final Set<String> packageNames;
protected final Set<String> exportedPackages;
protected DependencyClasspathEntry(File file, Collection<String> packageNames, Collection<String> exportedPackages) {
this.file = normalize(file);
this.packageNames = ImmutableSet.copyOf(packageNames);
this.exportedPackages = exportedPackages != null ? ImmutableSet.<String>copyOf(exportedPackages) : null;
}
private static File normalize(File file) {
try {
return file.getCanonicalFile();
} catch (IOException e) {
// should not happen as we know that the file exists
return file.getAbsoluteFile();
}
}
protected AccessRestriction getAccessRestriction(String packageName) {
if (exportedPackages != null && !exportedPackages.contains(packageName)) {
AccessRule rule = new AccessRule(null /* pattern */, IProblem.ForbiddenReference, true /* keep looking for accessible type */);
return new AccessRestriction(rule, AccessRestriction.COMMAND_LINE, getEntryName());
}
return null;
}
@Override
public Collection<String> getPackageNames() {
return packageNames;
}
protected static Collection<String> parseExportPackage(InputStream is) throws IOException {
LineProcessor<List<String>> processor = new LineProcessor<List<String>>() {
final List<String> result = new ArrayList<String>();
@Override
public boolean processLine(String line) throws IOException {
result.add(line.replace('.', '/'));
return true; // keep reading
}
@Override
public List<String> getResult() {
return result;
}
};
return CharStreams.readLines(new InputStreamReader(is, Charsets.UTF_8), processor);
}
protected static Collection<String> parseBundleManifest(InputStream is) throws IOException, BundleException {
Headers<String, String> headers = Headers.parseManifest(is);
if (!headers.containsKey(Constants.BUNDLE_SYMBOLICNAME)) {
return null; // not an OSGi bundle
}
String exportPackageHeader = headers.get(Constants.EXPORT_PACKAGE);
if (exportPackageHeader == null) {
return ImmutableSet.of(); // nothing is exported
}
Set<String> packages = new HashSet<>();
for (ManifestElement element : ManifestElement.parseHeader(Constants.EXPORT_PACKAGE, exportPackageHeader)) {
packages.add(element.getValue().replace('.', '/'));
}
return packages;
}
@Override
public String getEntryDescription() {
StringBuilder sb = new StringBuilder(getEntryName());
if (exportedPackages != null) {
sb.append("[");
int idx = 0;
for (String exportedPackage : exportedPackages) {
if (idx++ > 0) {
sb.append(File.pathSeparatorChar);
}
sb.append('+').append(exportedPackage).append("/*");
}
if (idx > 0) {
sb.append(File.pathSeparatorChar);
}
sb.append("?**/*");
sb.append(']');
}
return sb.toString();
}
@Override
public NameEnvironmentAnswer findType(String packageName, String typeName) {
return findType(packageName, typeName, getAccessRestriction(packageName));
}
public abstract NameEnvironmentAnswer findType(String packageName, String typeName, AccessRestriction accessRestriction);
public String getEntryName() {
return file.getAbsolutePath();
}
}