Merge branch 'eclipse-2023-12-tests' of https://github.com/Rawi01/lombok into Rawi01-eclipse-2023-12-tests

This commit is contained in:
Reinier Zwitserloot
2024-01-12 00:44:22 +01:00
12 changed files with 438 additions and 198 deletions
+2
View File
@@ -101,9 +101,11 @@ jobs:
- eclipse-202006-jdk8
- eclipse-202212
- eclipse-202309
- eclipse-202312
- eclipse-oxygen-full
- eclipse-2022-03-full
- eclipse-2023-09-full
- eclipse-2023-12-full
- ecj11
- ecj14
- ecj16
+15
View File
@@ -32,6 +32,7 @@
<conf name="eclipse-202006" />
<conf name="eclipse-202212" />
<conf name="eclipse-202309" />
<conf name="eclipse-202312" />
<conf name="mapstruct" />
</configurations>
@@ -64,6 +65,7 @@
<dependency org="org.freemarker" name="freemarker" rev="2.3.28" conf="buildtools->default" />
<dependency org="com.sparkjava" name="spark-core" rev="2.9.2" conf="buildtools->default" />
<dependency org="software.amazon.awssdk" name="s3" rev="2.19.29" conf="buildtools->default" />
<dependency org="com.sun.xml.bind" name="jaxb-impl" rev="2.3.9" conf="buildtools->default" />
<!-- javacs -->
<dependency org="net.java.openjdk.custom" name="javac6" rev="1.6.0.18" conf="javac6->runtime" />
@@ -132,6 +134,19 @@
<dependency org="org.eclipse.platform" name="org.eclipse.osgi" rev="3.18.500" conf="eclipse-202309->default" transitive="false" />
<dependency org="org.eclipse.platform" name="org.eclipse.text" rev="3.13.100" conf="eclipse-202309->default" transitive="false" />
<dependency org="org.eclipse.platform" name="org.eclipse.core.runtime" rev="3.30.0" conf="eclipse-202312->default" transitive="false" />
<dependency org="org.eclipse.jdt" name="org.eclipse.jdt.core" rev="3.36.0" conf="eclipse-202312->default" transitive="false" />
<dependency org="org.eclipse.jdt" name="org.eclipse.jdt.ui" rev="3.31.0" conf="eclipse-202312->default" transitive="false" />
<dependency org="org.eclipse.jdt" name="ecj" rev="3.36.0" conf="eclipse-202312->default" transitive="false" />
<dependency org="org.eclipse.platform" name="org.eclipse.equinox.common" rev="3.18.200" conf="eclipse-202312->default" transitive="false" />
<dependency org="org.eclipse.platform" name="org.eclipse.equinox.registry" rev="3.11.400" conf="eclipse-202312->default" transitive="false" />
<dependency org="org.eclipse.platform" name="org.eclipse.equinox.app" rev="1.6.400" conf="eclipse-202312->default" transitive="false" />
<dependency org="org.eclipse.platform" name="org.eclipse.core.resources" rev="3.20.0" conf="eclipse-202312->default" transitive="false" />
<dependency org="org.eclipse.platform" name="org.eclipse.core.contenttype" rev="3.9.200" conf="eclipse-202312->default" transitive="false" />
<dependency org="org.eclipse.platform" name="org.eclipse.core.jobs" rev="3.15.100" conf="eclipse-202312->default" transitive="false" />
<dependency org="org.eclipse.platform" name="org.eclipse.osgi" rev="3.18.600" conf="eclipse-202312->default" transitive="false" />
<dependency org="org.eclipse.platform" name="org.eclipse.text" rev="3.13.100" conf="eclipse-202312->default" transitive="false" />
<!-- integration with other libraries -->
<dependency org="org.mapstruct" name="mapstruct-processor" rev="1.3.1.Final" conf="mapstruct->default" transitive="false" />
</dependencies>
+50 -152
View File
@@ -45,25 +45,21 @@ This buildfile is part of projectlombok.org. It sets up the build itself.
<property name="exe.curl" value="curl" />
<property name="exe.git" value="git" />
<condition property="os.specific.native-swt-lib" value="org.eclipse.swt.gtk.linux.aarch64">
<os name="Linux" arch="aarch64" />
<condition property="os.supported">
<and>
<or>
<os family="unix" />
<os family="windows" />
<os name="Mac OS X" />
</or>
<or>
<os arch="aarch64" />
<os arch="x86-64" />
<os arch="amd64" />
</or>
</and>
</condition>
<condition property="os.specific.native-swt-lib" value="org.eclipse.swt.gtk.linux.x86_64">
<os name="Linux" />
</condition>
<condition property="os.specific.native-swt-lib" value="org.eclipse.swt.cocoa.macosx.aarch64">
<os name="Mac OS X" arch="aarch64" />
</condition>
<condition property="os.specific.native-swt-lib" value="org.eclipse.swt.cocoa.macosx.x86_64">
<os name="Mac OS X" />
</condition>
<condition property="os.specific.native-swt-lib" value="org.eclipse.swt.win32.win32.aarch64">
<os family="windows" arch="aarch64" />
</condition>
<condition property="os.specific.native-swt-lib" value="org.eclipse.swt.win32.win32.x86_64">
<os family="windows" />
</condition>
<fail unless="os.specific.native-swt-lib">Full eclipse testing requires downloading a native SWT binding. This script knows how to download for OS = [mac, linux, or windows] and architecture = [aarch64 or x86-64]. You have something different, you unique snowflake you. Your OS: "${os.name}", Your arch: "${os.arch}".</fail>
<fail unless="os.supported">Full eclipse testing requires downloading a native SWT binding. This script knows how to download for OS = [mac, linux, or windows] and architecture = [aarch64 or x86-64]. You have something different, you unique snowflake you. Your OS: "${os.name}", Your arch: "${os.arch}".</fail>
<target name="-autoclean.check">
<available type="dir" file="build" property="existingbuild.present" />
@@ -160,15 +156,23 @@ This buildfile is part of projectlombok.org. It sets up the build itself.
</target>
<target name="deps.eclipse.oxygen" depends="deps.rtstubs18, compile.support">
<fetchdep.eclipse.osgi name="oxygen" version="4.7/R-4.7-201706120950" />
<fetchdep.eclipse.osgi name="oxygen" version="4.7" />
</target>
<target name="deps.eclipse.2022-03" depends="deps.rtstubs18, compile.support">
<fetchdep.eclipse.osgi name="2022-03" version="4.23/R-4.23-202203080310" />
<fetchdep.eclipse.osgi name="2022-03" version="4.23" />
</target>
<target name="deps.eclipse.2023-09" depends="deps.rtstubs18, compile.support">
<fetchdep.eclipse.osgi name="2023-09" version="4.29/R-4.29-202309031000" />
<fetchdep.eclipse.osgi name="2023-09" version="4.29" />
</target>
<target name="deps.eclipse.2023-12" depends="deps.rtstubs18, compile.support">
<fetchdep.eclipse.osgi name="2023-12" version="4.30" />
</target>
<target name="deps.eclipse.integration" depends="deps.rtstubs18, compile.support">
<fetchdep.eclipse.osgi name="I-build" version="I-builds" />
</target>
<macrodef name="fetchdep.ecj">
@@ -192,13 +196,31 @@ This buildfile is part of projectlombok.org. It sets up the build itself.
</macrodef>
<macrodef name="fetchdep.eclipse.osgi">
<attribute name="target" default="testenv" />
<attribute name="name" />
<attribute name="version" />
<sequential>
<condition property="@{name}.isoxygen">
<equals arg1="@{name}" arg2="oxygen"/>
</condition>
<fetchdep.eclipse.updatesite name="@{name}" version="@{version}">
<bundles>
<!-- Ambiguous + osgi.extender dependecies -->
<arg value="osgi.bundle:javax.el-api" />
<arg value="osgi.bundle:org.apache.felix.scr" />
<arg value="osgi.bundle:org.apache.aries.spifly.dynamic.bundle" />
<arg value="osgi.bundle:org.apache.commons.commons-io" />
<!-- Real dependencies -->
<arg value="osgi.bundle:org.eclipse.jdt.core" />
<arg value="osgi.bundle:org.eclipse.jdt.ui" />
</bundles>
</fetchdep.eclipse.updatesite>
</sequential>
</macrodef>
<macrodef name="fetchdep.eclipse.updatesite">
<attribute name="target" default="testenv" />
<attribute name="name" />
<attribute name="version" />
<attribute name="resolveDependencies" default="true" />
<element name="bundles" />
<sequential>
<java classname="lombok.eclipse.dependencies.DownloadEclipseDependencies" failonerror="true">
<classpath>
<path refid="cp.buildtools" />
@@ -206,133 +228,9 @@ This buildfile is part of projectlombok.org. It sets up the build itself.
</classpath>
<arg value="@{target}" />
<arg value="eclipse-@{name}" />
<arg value="https://download.eclipse.org/eclipse/updates/@{version}/plugins/" />
<arg value="bcpg" />
<arg value="bcprov" />
<arg value="com.ibm.icu" />
<arg value="com.sun.jna" />
<arg value="com.sun.jna.platform" />
<arg value="jakarta.inject.jakarta.inject-api" />
<arg value="jakarta.annotation-api" />
<arg value="jakarta.servlet-api" />
<arg value="javax.annotation" />
<arg value="javax.inject" />
<arg value="javax.el-api" />
<arg value="javax.servlet.jsp-api" />
<arg value="org.apache.batik.constants" />
<arg value="org.apache.batik.css" />
<arg value="org.apache.batik.i18n" />
<arg value="org.apache.batik.util" />
<arg value="org.apache.commons.collections" />
<arg value="org.apache.commons.commons-beanutils" />
<arg value="org.apache.commons.commons-io" />
<arg value="org.apache.commons.io" />
<arg value="org.apache.commons.jxpath" />
<arg value="org.apache.commons.logging" />
<arg value="org.apache.felix.scr" />
<arg value="org.apache.xmlgraphics" />
<arg value="org.bouncycastle.bcpg" />
<arg value="org.bouncycastle.bcprov" />
<arg value="org.eclipse.compare" />
<arg value="org.eclipse.compare.core" />
<arg value="org.eclipse.core.commands" />
<arg value="org.eclipse.core.contenttype" />
<arg value="org.eclipse.core.databinding" />
<arg value="org.eclipse.core.databinding.observable" />
<arg value="org.eclipse.core.databinding.property" />
<arg value="org.eclipse.core.expressions" />
<arg value="org.eclipse.core.filebuffers" />
<arg value="org.eclipse.core.filesystem" />
<arg value="org.eclipse.core.jobs" />
<arg value="org.eclipse.core.resources" />
<arg value="org.eclipse.core.runtime" />
<arg value="org.eclipse.core.variables" />
<arg value="org.eclipse.debug.core" />
<arg value="org.eclipse.debug.ui" />
<arg value="org.eclipse.e4.core.commands" />
<arg value="org.eclipse.e4.core.contexts" />
<arg value="org.eclipse.e4.core.di" />
<arg value="org.eclipse.e4.core.di.annotations" />
<arg value="org.eclipse.e4.core.di.extensions" />
<arg value="org.eclipse.e4.core.di.extensions.supplier" />
<arg value="org.eclipse.e4.core.services" />
<arg value="org.eclipse.e4.emf.xpath" />
<arg value="org.eclipse.e4.ui.bindings" />
<arg value="org.eclipse.e4.ui.css.core" />
<arg value="org.eclipse.e4.ui.css.swt" />
<arg value="org.eclipse.e4.ui.css.swt.theme" />
<arg value="org.eclipse.e4.ui.di" />
<arg value="org.eclipse.e4.ui.dialogs" />
<arg value="org.eclipse.e4.ui.ide" />
<arg value="org.eclipse.e4.ui.model.workbench" />
<arg value="org.eclipse.e4.ui.services" />
<arg value="org.eclipse.e4.ui.widgets" />
<arg value="org.eclipse.e4.ui.workbench" />
<arg value="org.eclipse.e4.ui.workbench.addons.swt" />
<arg value="org.eclipse.e4.ui.workbench.renderers.swt" />
<arg value="org.eclipse.e4.ui.workbench.swt" />
<arg value="org.eclipse.e4.ui.workbench3" />
<arg value="org.eclipse.emf.common" />
<arg value="org.eclipse.emf.ecore" />
<arg value="org.eclipse.emf.ecore.change" />
<arg value="org.eclipse.emf.ecore.xmi" />
<arg value="org.eclipse.equinox.app" />
<arg value="org.eclipse.equinox.bidi" />
<arg value="org.eclipse.equinox.common" />
<arg value="org.eclipse.equinox.p2.artifact.repository" />
<arg value="org.eclipse.equinox.p2.core" />
<arg value="org.eclipse.equinox.p2.engine" />
<arg value="org.eclipse.equinox.p2.jarprocessor" />
<arg value="org.eclipse.equinox.p2.metadata" />
<arg value="org.eclipse.equinox.p2.metadata.repository" />
<arg value="org.eclipse.equinox.p2.repository" />
<arg value="org.eclipse.equinox.preferences" />
<arg value="org.eclipse.equinox.registry" />
<arg value="org.eclipse.equinox.security" />
<arg value="org.eclipse.help" />
<arg value="org.eclipse.jdt.core" />
<arg value="org.eclipse.jdt.core.compiler.batch" unless:set="@{name}.isoxygen" />
<arg value="org.eclipse.jdt.core.manipulation" />
<arg value="org.eclipse.jdt.debug" />
<arg value="org.eclipse.jdt.launching" />
<arg value="org.eclipse.jdt.ui" />
<arg value="org.eclipse.jface" />
<arg value="org.eclipse.jface.databinding" />
<arg value="org.eclipse.jface.text" />
<arg value="org.eclipse.ltk.core.refactoring" />
<arg value="org.eclipse.ltk.ui.refactoring" />
<arg value="org.eclipse.osgi" />
<arg value="org.eclipse.osgi.services" />
<arg value="org.eclipse.osgi.util" />
<arg value="org.eclipse.search" />
<arg value="org.eclipse.swt" />
<arg value="${os.specific.native-swt-lib}" />
<arg value="org.eclipse.team.core" />
<arg value="org.eclipse.team.ui" />
<arg value="org.eclipse.text" />
<arg value="org.eclipse.ui" />
<arg value="org.eclipse.ui.console" />
<arg value="org.eclipse.ui.editors" />
<arg value="org.eclipse.ui.forms" />
<arg value="org.eclipse.ui.ide" />
<arg value="org.eclipse.ui.navigator" />
<arg value="org.eclipse.ui.navigator.resources" />
<arg value="org.eclipse.ui.views" />
<arg value="org.eclipse.ui.views.properties.tabbed" />
<arg value="org.eclipse.ui.workbench" />
<arg value="org.eclipse.ui.workbench.texteditor" />
<arg value="org.eclipse.urischeme" />
<arg value="org.jdom" />
<arg value="org.osgi.service.prefs" />
<arg value="org.osgi.service.event" />
<arg value="org.osgi.service.component" />
<arg value="org.osgi.util.function" />
<arg value="org.osgi.util.promise" />
<arg value="org.tukaani.xz" />
<arg value="org.w3c.css.sac" />
<arg value="org.w3c.dom.events" />
<arg value="org.w3c.dom.smil" />
<arg value="org.w3c.dom.svg" />
<arg value="https://download.eclipse.org/eclipse/updates/@{version}/" />
<arg value="@{resolveDependencies}" />
<bundles />
</java>
</sequential>
</macrodef>
+38
View File
@@ -218,6 +218,36 @@ This buildfile is part of projectlombok.org. It takes care of compiling and runn
<test.eclipse-X version="202309" />
</target>
<target name="test.eclipse-202312" depends="test.compile, test.formatter.compile" description="runs the tests on your default VM, testing the 2023-12 release of eclipse">
<fetchdep.eclipse version="202312" />
<test.eclipse-X version="202312" />
</target>
<target name="test.eclipse-I-build" depends="test.compile, test.formatter.compile, deps.rtstubs18, compile.support" description="runs the tests on your default VM, testing the latest integration build of eclipse">
<fetchdep.eclipse.updatesite name="I-build" version="I-builds" target="lib/" resolveDependencies="false">
<bundles>
<arg value="osgi.bundle:org.eclipse.core.runtime" />
<arg value="osgi.bundle:org.eclipse.jdt.core" />
<arg value="osgi.bundle:org.eclipse.jdt.ui" />
<arg value="osgi.bundle:org.eclipse.jdt.core.compiler.batch" />
<arg value="osgi.bundle:org.eclipse.equinox.common" />
<arg value="osgi.bundle:org.eclipse.equinox.registry" />
<arg value="osgi.bundle:org.eclipse.equinox.app" />
<arg value="osgi.bundle:org.eclipse.core.resources" />
<arg value="osgi.bundle:org.eclipse.core.contenttype" />
<arg value="osgi.bundle:org.eclipse.core.jobs" />
<arg value="osgi.bundle:org.eclipse.osgi" />
<arg value="osgi.bundle:org.eclipse.text" />
</bundles>
</fetchdep.eclipse.updatesite>
<path id="cp.eclipse-I-build">
<fileset dir="lib/eclipse-I-build/plugins">
<include name="*.jar" />
</fileset>
</path>
<test.eclipse-X version="I-build" />
</target>
<macrodef name="test.eclipse-X-full">
<attribute name="version" />
<sequential>
@@ -261,6 +291,14 @@ This buildfile is part of projectlombok.org. It takes care of compiling and runn
<test.eclipse-X-full version="2023-09" />
</target>
<target name="test.eclipse-2023-12-full" depends="test.eclipse.compile, test.formatter.compile, deps.eclipse.2023-12" description="runs the full eclipse tests on your default VM, testing the 2023-12 release of eclipse">
<test.eclipse-X-full version="2023-12" />
</target>
<target name="test.eclipse-I-build-full" depends="test.eclipse.compile, test.formatter.compile, deps.eclipse.integration" description="runs the full eclipse tests on your default VM, testing the latest integration build of eclipse">
<test.eclipse-X-full version="I-build" />
</target>
<macrodef name="test.ecj-X">
<attribute name="version" />
<sequential>
@@ -0,0 +1,8 @@
package lombok.eclipse.dependencies;
import javax.xml.bind.annotation.XmlAttribute;
public class Child {
@XmlAttribute
String location;
}
@@ -7,71 +7,57 @@ import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.List;
import java.util.Set;
/**
* Download eclipse bundles.
*/
public class DownloadEclipseDependencies {
public static void main(String[] args) throws IOException {
public static void main(String[] args) throws Exception {
String target = args[0];
String eclipseVersion = args[1];
String updatePage = args[2];
String[] packages = Arrays.copyOfRange(args, 3, args.length);
String updateSiteUrl = args[2];
boolean resolveDependencies = Boolean.parseBoolean(args[3]);
List<String> bundles = Arrays.asList(Arrays.copyOfRange(args, 4, args.length));
UpdateSite updateSite = new UpdateSite();
updateSite.read(updateSiteUrl);
final Set<String> artifacts;
if (resolveDependencies) {
artifacts = updateSite.resolveWithDependencies(bundles);
} else {
artifacts = updateSite.resolveWithoutDependencies(bundles);
}
String pluginTarget = target + "/" + eclipseVersion + "/plugins/";
String pluginSource = updateSite.getResolvedUrl() + "/plugins/";
String indexData = readUrlAsString(updatePage);
for (String pkg : packages) {
Matcher matcher = Pattern.compile("(" + pkg.replace(".", "\\.") + "_.*?\\.jar)").matcher(indexData);
if (matcher.find()) {
String path = matcher.group(1);
try {
downloadFile(path, updatePage, pluginTarget);
} catch (Exception e) {
}
int index = path.lastIndexOf("_");
String source = path.substring(0, index) + ".source" + path.substring(index);
if (indexData.contains(source)) {
try {
downloadFile(source, updatePage, pluginTarget);
} catch (Exception e) {
}
}
} else {
System.out.println("Bundle \"" + pkg + "\" not found");
for (String artifact : artifacts) {
try {
downloadFile(artifact, pluginSource, pluginTarget);
} catch (Exception e) {
}
int index = artifact.lastIndexOf("_");
String source = artifact.substring(0, index) + ".source" + artifact.substring(index);
try {
downloadFile(source, pluginSource, pluginTarget);
} catch (Exception e) {
}
}
writeEclipseLibrary(target, eclipseVersion);
}
private static String readUrlAsString(String url) throws MalformedURLException, IOException {
InputStream in = getStreamForUrl(url);
StringBuilder sb = new StringBuilder();
int bufferSize = 1024;
char[] buffer = new char[bufferSize];
InputStreamReader reader = new InputStreamReader(in, "UTF-8");
for (int count = 0; (count = reader.read(buffer, 0, bufferSize)) > 0;) {
sb.append(buffer, 0, count);
}
return sb.toString();
}
private static void downloadFile(String filename, String repositoryUrl, String target) throws IOException {
new File(target).mkdirs();
File targetFile = new File(target, filename);
@@ -87,10 +73,13 @@ public class DownloadEclipseDependencies {
out = new FileOutputStream(targetFile);
copy(in, out);
System.out.println("[done]");
} catch(IOException e) {
} catch (IOException e) {
System.out.println("[error]");
} finally {
if (in != null) try { in.close(); } catch (Exception ignore) {}
if (in != null) try {
in.close();
} catch (Exception ignore) {
}
if (out != null) out.close();
}
}
@@ -111,7 +100,7 @@ public class DownloadEclipseDependencies {
InputStream in = new BufferedInputStream(connection.getInputStream());
return in;
}
private static void writeEclipseLibrary(String target, String eclipseVersion) throws IOException {
StringBuilder sb = new StringBuilder();
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
@@ -121,7 +110,8 @@ public class DownloadEclipseDependencies {
sb.append("\" systemlibrary=\"false\">\n");
File[] files = new File(new File(target, eclipseVersion), "plugins").listFiles(new FilenameFilter() {
@Override public boolean accept(File dir, String name) {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".jar") && !name.contains(".source_");
}
});
@@ -0,0 +1,12 @@
package lombok.eclipse.dependencies;
import javax.xml.bind.annotation.XmlAttribute;
public class Provided {
@XmlAttribute
String namespace;
@XmlAttribute
String name;
@XmlAttribute
String version;
}
@@ -0,0 +1,18 @@
package lombok.eclipse.dependencies;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Repository {
@XmlElementWrapper(name = "children")
@XmlElement(name="child")
List<Child> children;
@XmlElementWrapper(name = "units")
@XmlElement(name="unit")
List<Unit> units;
}
@@ -0,0 +1,17 @@
package lombok.eclipse.dependencies;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
public class Required {
@XmlAttribute
String namespace;
@XmlAttribute
String name;
@XmlAttribute
String range;
@XmlAttribute
boolean optional;
@XmlElement
String filter;
}
@@ -0,0 +1,21 @@
package lombok.eclipse.dependencies;
import java.util.ArrayDeque;
import java.util.HashSet;
import java.util.Set;
/**
* A incomplete implementation of a queue that maintains a history of all queued items and ensures unique elements.
* Elements cannot be added to the queue if they already exist in the history.
*/
public class UniqueQueue<T> extends ArrayDeque<T> {
private Set<T> added = new HashSet<>();
@Override
public boolean add(T e) {
if (added.add(e)) {
return super.add(e);
}
return false;
}
}
@@ -0,0 +1,27 @@
package lombok.eclipse.dependencies;
import java.util.List;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
public class Unit {
@XmlAttribute
String id;
@XmlAttribute
String version;
@XmlElementWrapper(name = "provides")
@XmlElement(name="provided")
List<Provided> provides;
@XmlElementWrapper(name = "requires")
@XmlElement(name="required")
List<Required> requires;
@Override
public String toString() {
return id + "_" + version;
}
}
@@ -0,0 +1,194 @@
package lombok.eclipse.dependencies;
import java.io.BufferedInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.Source;
import javax.xml.transform.sax.SAXSource;
import org.xml.sax.InputSource;
public class UpdateSite {
private static final String OS_NAME = System.getProperty("os.name").toLowerCase();
private static final String OSGI_OS = OS_NAME.contains("windows") ? "windows" : OS_NAME.contains("mac") ? "mac" : "linux";
private static final String OS_ARCH = System.getProperty("os.arch");
private static final String OSGI_ARCH = OS_ARCH.equals("aarch64") ? "aarch64" : "x86_64";
private JAXBContext jaxbContext;
private Repository repository;
private Map<String, List<Unit>> providesIndex;
private String resolvedUrl;
private SAXParserFactory saxParserFactory;
public UpdateSite() throws Exception {
jaxbContext = JAXBContext.newInstance(Repository.class);
providesIndex = new HashMap<>();
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
spf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
spf.setXIncludeAware(false);
saxParserFactory = spf;
}
public void read(String url) throws Exception {
String currentUrl = url;
try {
while (true) {
String child = resolveNextChild(currentUrl);
if (child.startsWith("https://")) {
currentUrl = child;
} else {
currentUrl += child;
}
}
} catch (FileNotFoundException e) {
// Found the real repository
}
resolvedUrl = currentUrl;
try (InputStream inputStream = readJarOrXml(resolvedUrl, "content")) {
repository = unmarshalRepository(inputStream);
// Build index
for (Unit unit : repository.units) {
for (Provided provides : unit.provides) {
providesIndex.computeIfAbsent(provides.namespace + ":" + provides.name, k -> new ArrayList<>()).add(unit);
}
}
}
;
}
public Set<String> resolveWithoutDependencies(List<String> dependencies) {
return resolve(dependencies, false);
}
public Set<String> resolveWithDependencies(List<String> dependencies) {
return resolve(dependencies, true);
}
private Set<String> resolve(List<String> dependencies, boolean withDependencies) {
Queue<String> toResolve = new UniqueQueue<>();
for (String dependency : dependencies) {
toResolve.add(dependency);
}
Set<Unit> resolved = new HashSet<>();
while (!toResolve.isEmpty()) {
String next = toResolve.poll();
List<Unit> providedUnits = providesIndex.get(next);
// Skip unknown
if (providedUnits == null) {
System.out.println("Skipping unknown unit " + next);
continue;
}
// Remove a.jre.javase dependency
List<Unit> filteredProvidedUnits = providedUnits.stream()
.filter(u -> !u.id.equals("a.jre.javase")) // Remove
.collect(Collectors.toList());
if (filteredProvidedUnits.size() == 0) {
// This is a JDK only dependency, skip
continue;
}
// Skip ambiguous (we could use version ranges to solve that...)
if (filteredProvidedUnits.size() > 1) {
boolean alreadyResolved = filteredProvidedUnits.stream().anyMatch(resolved::contains);
if (!alreadyResolved) {
System.out.println("Ambiguous resolution for " + next + ": " + filteredProvidedUnits.toString());
continue;
}
}
Unit unit = filteredProvidedUnits.get(0);
resolved.add(unit);
if (withDependencies && unit.requires != null) {
for (Required required : unit.requires) {
if (required.optional) continue;
if (!matchesFilter(required.filter)) continue;
toResolve.add(required.namespace + ":" + required.name);
}
}
}
return resolved.stream().map(u -> u.toString() + ".jar").collect(Collectors.toSet());
}
// Dummy implementation
private boolean matchesFilter(String filter) {
if (filter == null) {
return true;
}
if (filter.contains("osgi.arch=") && !filter.contains("osgi.arch=" + OSGI_ARCH)) {
return false;
}
if (filter.contains("osgi.os=") && !filter.contains("osgi.os=" + OSGI_OS)) {
return false;
}
return true;
}
private String resolveNextChild(String currentUrl) throws Exception {
try (InputStream inputStream = readJarOrXml(currentUrl, "compositeContent")) {
Repository repository = unmarshalRepository(inputStream);
Child lastChild = repository.children.get(repository.children.size() - 1);
return lastChild.location;
}
}
private Repository unmarshalRepository(InputStream inputStream) throws Exception {
Source source = new SAXSource(saxParserFactory.newSAXParser().getXMLReader(), new InputSource(inputStream));
Repository repository = (Repository) jaxbContext.createUnmarshaller().unmarshal(source);
return repository;
}
private InputStream readJarOrXml(String url, String name) throws Exception {
try {
return getStreamForUrl(url + "/" + name + ".xml");
} catch (FileNotFoundException e) {
System.out.println("Not found, trying jar");
}
ZipInputStream zipInputStream = new ZipInputStream(getStreamForUrl(url + "/" + name + ".jar"));
ZipEntry entry;
while ((entry = zipInputStream.getNextEntry()) != null) {
if (entry.getName().equals(name + ".xml")) {
return zipInputStream;
}
}
throw new FileNotFoundException();
}
private static InputStream getStreamForUrl(String url) throws Exception {
System.out.println("Reading " + url);
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.setRequestProperty("User-Agent", "lombok");
connection.setRequestProperty("Accept", "*/*");
InputStream in = new BufferedInputStream(connection.getInputStream());
return in;
}
public String getResolvedUrl() {
return resolvedUrl;
}
}