Skip to content
Commits on Source (2)
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry excluding="module-info.java|**/JPMS*.java" kind="src" output="target/classes" path="src/main/java">
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
......@@ -13,7 +13,7 @@
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
......@@ -23,5 +23,10 @@
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/main/resources=UTF-8
encoding/<project>=UTF-8
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=1.8
org.eclipse.jdt.core.compiler.source=1.7
......@@ -88,8 +88,8 @@
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
......@@ -198,12 +198,12 @@
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.21</version>
<version>1.20</version>
</dependency>
</dependencies>
</project>
......@@ -376,7 +376,7 @@ public final class DynamicZip {
int getInternalFileAttributes();
long getExternalFileAttributes();
int getVersionMadeBy();
int getVersionRequired();
......
package fr.gaellalire.maven_jar_exploder;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import fr.gaellalire.maven_jar_exploder.DynamicZip.FileMeta;
public class GeneratedZipFileMeta extends AbstractZipArchiveEntryFileMeta implements FileMeta {
private List<FileMeta> fileMetas;
private boolean zip64;
public GeneratedZipFileMeta(ZipArchiveEntry zipArchiveEntry, String sha512, List<FileMeta> fileMetas) throws IOException {
super(zipArchiveEntry, sha512, null);
if (zipArchiveEntry.getSize() == DynamicZip.calculateZipMeta(fileMetas, true).getSize()) {
zip64 = true;
} else {
if (zipArchiveEntry.getSize() != DynamicZip.calculateZipMeta(fileMetas, false).getSize()) {
throw new IOException("Unable to match size");
}
}
}
@Override
public InputStream getInputStream(long from, long size) throws IOException {
return DynamicZip.getInputStream(fileMetas, from, size, zip64);
}
}
......@@ -11,25 +11,16 @@ import fr.gaellalire.maven_jar_exploder.DynamicZip.FileMeta;
public class MavenRepositoryFileMeta extends AbstractZipArchiveEntryFileMeta implements FileMeta {
private String groupId;
private File file;
private String artifactId;
private String version;
private String extension;
private File localRepository;
public MavenRepositoryFileMeta(ZipArchiveEntry zipArchiveEntry, String sha512, File localRepository) {
public MavenRepositoryFileMeta(ZipArchiveEntry zipArchiveEntry, String sha512, String url, File localRepository) {
super(zipArchiveEntry, sha512, sha512);
file = MavenJarExploder.getFile(localRepository, url);
}
@Override
public InputStream getInputStream(long from, long size) throws IOException {
// already resolved
File file = new File(localRepository,
groupId.replace('.', File.separatorChar) + artifactId + File.separatorChar + version + File.separatorChar + artifactId + "-" + version + "." + extension);
return new SkipAndLimitFilterInputStream(new FileInputStream(file), from, size);
}
......
......@@ -2,69 +2,56 @@ package fr.gaellalire.maven_jar_exploder;
public class MetaAndSha512 {
private String sha512;
private int position;
private String name;
private int position;
private String url;
private String sha512;
private long size;
private long crc32;
private long time;
private long deflatedSize;
private Long externalAttributes;
private String url;
private Long time;
public MetaAndSha512(String sha512, int position, String name, long size, long crc32, long time, long deflatedSize, String url) {
this.sha512 = sha512;
this.position = position;
public MetaAndSha512(String name, int position, String url, String sha512, Long externalAttributes, Long time) {
this.name = name;
this.size = size;
this.crc32 = crc32;
this.time = time;
this.deflatedSize = deflatedSize;
this.position = position;
this.url = url;
this.sha512 = sha512;
this.externalAttributes = externalAttributes;
this.time = time;
}
@Override
public String toString() {
return "MetaAndSha512 [sha512=" + sha512 + ", position=" + position + ", url=" + url + ", name=" + name + ", size=" + size + ", crc32=" + crc32 + ", time="
+ time + ", deflatedSize=" + deflatedSize + "]";
}
public String getSha512() {
return sha512;
public String getName() {
return name;
}
public int getPosition() {
return position;
}
public String getName() {
return name;
public String getUrl() {
return url;
}
public long getSize() {
return size;
public String getSha512() {
return sha512;
}
public long getCrc32() {
return crc32;
public Long getExternalAttributes() {
return externalAttributes;
}
public long getTime() {
public Long getTime() {
return time;
}
public long getDeflatedSize() {
return deflatedSize;
@Override
public String toString() {
return "MetaAndSha512 [name=" + name + ", position=" + position + ", url=" + url + ", sha512=" + sha512 + ", externalAttributes=" + externalAttributes + ", time=" + time
+ "]";
}
public String getUrl() {
return url;
}
}
package fr.gaellalire.maven_jar_exploder;
import java.util.List;
public class RepackagedJar {
private String positions;
private String times;
private String externalAttributesList;
private List<String> excludedURL;
private List<MetaAndSha512> filesToAdd;
private String url;
public RepackagedJar(String positions, String times, String externalAttributesList, List<String> excludedURL, String url, List<MetaAndSha512> filesToAdd) {
this.positions = positions;
this.times = times;
this.externalAttributesList = externalAttributesList;
this.excludedURL = excludedURL;
this.url = url;
this.filesToAdd = filesToAdd;
}
public String getPositions() {
return positions;
}
public String getTimes() {
return times;
}
public String getExternalAttributesList() {
return externalAttributesList;
}
public List<String> getExcludedURL() {
return excludedURL;
}
public String getUrl() {
return url;
}
public List<MetaAndSha512> getFilesToAdd() {
return filesToAdd;
}
}
package fr.gaellalire.maven_jar_exploder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class SubMetaIndexer {
public static final String EMPTY_SHA512 = "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e";
private class MetaAndSubMeta {
MetaAndSha512 meta;
List<MetaAndSha512> subMetas;
public MetaAndSubMeta(MetaAndSha512 meta, List<MetaAndSha512> subMetas) {
this.meta = meta;
this.subMetas = subMetas;
}
public RepackagedJar repackage(List<MetaAndSha512> assembledSubMetas) {
List<String> excludedURL = new ArrayList<String>();
StringBuilder positions = new StringBuilder();
StringBuilder times = new StringBuilder();
StringBuilder externalAttributesSB = new StringBuilder();
List<MetaAndSha512> subMetasUnused = new ArrayList<MetaAndSha512>(this.subMetas);
List<MetaAndSha512> filesToAdd = new ArrayList<MetaAndSha512>();
boolean first = true;
mainl: for (MetaAndSha512 assembledSubMeta : assembledSubMetas) {
String name = assembledSubMeta.getName();
long time = assembledSubMeta.getTime();
long externalAttributes = assembledSubMeta.getExternalAttributes();
// if (name.endsWith("/")) {
// // dir
// continue;
// }
int position = 0;
for (MetaAndSha512 subMeta : this.subMetas) {
position++;
if (!name.equals(subMeta.getName())) {
continue;
}
if (!assembledSubMeta.getSha512().equals(subMeta.getSha512())) {
if ("META-INF/MANIFEST.MF".equalsIgnoreCase(name)) {
// see later
filesToAdd.add(assembledSubMeta);
continue mainl;
}
continue;
}
String timeS = "_";
String externalAttributesS = "_";
if (time != subMeta.getTime()) {
timeS = String.valueOf(time);
}
if (externalAttributes != subMeta.getExternalAttributes()) {
externalAttributesS = String.valueOf(externalAttributes);
}
if (first) {
first = false;
} else {
positions.append(",");
times.append(",");
externalAttributesSB.append(",");
}
positions.append(position);
times.append(timeS);
externalAttributesSB.append(externalAttributesS);
subMetasUnused.remove(subMeta);
continue mainl;
}
// not found
return null;
}
for (MetaAndSha512 subMeta : subMetasUnused) {
MetaAndSha512 metaAndSha512 = metaBySha512.get(subMeta.getSha512());
if (metaAndSha512 == null) {
if ("META-INF/MANIFEST.MF".equalsIgnoreCase(subMeta.getName())) {
// ok to be skipped
continue;
}
return null;
}
String url = metaAndSha512.getUrl();
excludedURL.add(url);
}
return new RepackagedJar(positions.toString(), times.toString(), externalAttributesSB.toString(), excludedURL, meta.getUrl(), filesToAdd);
}
}
private Map<String, MetaAndSha512> metaBySha512;
private Map<String, Set<MetaAndSubMeta>> subMetasMap = new HashMap<String, Set<MetaAndSubMeta>>();
public void setMetaBySha512(Map<String, MetaAndSha512> metaBySha512) {
this.metaBySha512 = metaBySha512;
}
public void add(MetaAndSha512 original, List<MetaAndSha512> subMetas) {
MetaAndSubMeta metaAndSubMeta = new MetaAndSubMeta(original, subMetas);
for (MetaAndSha512 subMeta : subMetas) {
Set<MetaAndSubMeta> list = subMetasMap.get(subMeta.getSha512());
if (list == null) {
list = new HashSet<MetaAndSubMeta>();
String sha512 = subMeta.getSha512();
if (!EMPTY_SHA512.equals(sha512)) {
subMetasMap.put(sha512, list);
}
}
if (!list.contains(metaAndSubMeta)) {
list.add(metaAndSubMeta);
}
}
}
public RepackagedJar search(List<MetaAndSha512> assembledSubMetas) {
Set<MetaAndSubMeta> set = new HashSet<MetaAndSubMeta>();
for (MetaAndSha512 subMeta : assembledSubMetas) {
Set<MetaAndSubMeta> c = subMetasMap.get(subMeta.getSha512());
if (c != null)
set.addAll(c);
}
for (MetaAndSubMeta metaAndSubMeta : set) {
RepackagedJar repackagedJar = metaAndSubMeta.repackage(assembledSubMetas);
if (repackagedJar != null) {
return repackagedJar;
}
}
return null;
}
}
package fr.gaellalire.maven_jar_exploder.utils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
public class CompareContent {
public static void compare(File file1, File file2) throws IOException {
try (ZipArchiveInputStream zis1 = new ZipArchiveInputStream(new FileInputStream(file1));
ZipArchiveInputStream zis2 = new ZipArchiveInputStream(new FileInputStream(file2));) {
do {
ZipArchiveEntry nextEntry1 = zis1.getNextZipEntry();
ZipArchiveEntry nextEntry2 = zis2.getNextZipEntry();
if (nextEntry1 == null || nextEntry2 == null) {
if (nextEntry2 != null || nextEntry2 != null) {
throw new IOException("number of file is different");
}
break;
}
if (nextEntry1.getExternalAttributes() != nextEntry2.getExternalAttributes()) {
throw new IOException(nextEntry1.getName() + " externalAttributes is different");
}
if (nextEntry1.getTime() != nextEntry2.getTime()) {
throw new IOException(nextEntry1.getName() + " time is different");
}
if (!nextEntry1.getName().equals(nextEntry2.getName())) {
throw new IOException(nextEntry1.getName() + " name is different");
}
File subFile1 = File.createTempFile("tmp", ".data");
File subFile2 = File.createTempFile("tmp", ".data");
try {
try (FileOutputStream fos1 = new FileOutputStream(subFile1); FileOutputStream fos2 = new FileOutputStream(subFile2)) {
IOUtils.copy(zis1, fos1);
IOUtils.copy(zis2, fos2);
}
if (!FileUtils.contentEquals(subFile1, subFile2)) {
try {
compare(subFile1, subFile2);
} catch (IOException e) {
throw new IOException(nextEntry1.getName() + " is different", e);
}
}
} finally {
subFile1.delete();
subFile2.delete();
}
} while (true);
}
}
}
package fr.gaellalire.maven_jar_exploder.utils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.TreeSet;
import java.util.regex.Matcher;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.commons.compress.archivers.zip.ZipFile;
import org.apache.commons.io.IOUtils;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.artifact.DefaultArtifact;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.resolution.ArtifactRequest;
import org.eclipse.aether.resolution.ArtifactResolutionException;
import org.eclipse.aether.resolution.ArtifactResult;
import fr.gaellalire.maven_jar_exploder.MavenJarExploder;
public class ContructFromExplodedAssembly {
static class Dep implements Comparable<Dep> {
int position;
String name;
long time;
String url;
long externalAttributes;
String[] positions;
String[] times;
String[] externalAttributesList;
String[] files;
public Dep(int position, String name, long time, long externalAttributes, String[] positions, String[] times, String[] externalAttributesList, String[] files, String url) {
this.position = position;
this.name = name;
this.time = time;
this.externalAttributes = externalAttributes;
this.positions = positions;
this.times = times;
this.externalAttributesList = externalAttributesList;
this.files = files;
this.url = url;
}
@Override
public int compareTo(Dep o) {
return position - o.position;
}
}
static class FileOverride implements Comparable<FileOverride> {
int position;
String name;
String explodedName;
long time;
long externalAttributes;
public FileOverride(int position, String explodedName, String name, long time, long externalAttributes) {
this.position = position;
this.explodedName = explodedName;
this.name = name;
this.time = time;
this.externalAttributes = externalAttributes;
}
@Override
public int compareTo(FileOverride o) {
return position - o.position;
}
}
public static void construct(File explodedAssembly, File destination) throws IOException, ArtifactResolutionException {
File localRepository = new File(System.getProperty("user.home"), ".m2" + File.separator + "repository");
RepositorySystem repositorySystem = MavenJarExploder.newRepositorySystem();
RepositorySystemSession session = MavenJarExploder.newSession(repositorySystem, localRepository);
List<RemoteRepository> repositories = Arrays.asList(new RemoteRepository.Builder("gaellalire-repo", "default", "https://gaellalire.fr/maven/repository/").build(),
new RemoteRepository.Builder("central", "default", "https://repo1.maven.org/maven2/").build());
File tmpFiles = new File("tmpFiles");
tmpFiles.mkdirs();
Properties properties = new Properties();
TreeSet<Dep> depSet = new TreeSet<Dep>();
try (ZipFile zipFile = new ZipFile(explodedAssembly)) {
ZipArchiveEntry entry = zipFile.getEntry("META-INF/exploded-assembly.properties");
properties.load(zipFile.getInputStream(entry));
for (String dep : properties.getProperty("dependencies").split(",")) {
int position = Integer.parseInt(properties.getProperty(dep + ".position"));
String name = properties.getProperty(dep + ".name");
long time = Long.parseLong(properties.getProperty(dep + ".time"));
long externalAttributes = Long.parseLong(properties.getProperty(dep + ".externalAttributes"));
String url = properties.getProperty(dep + ".url");
String property = properties.getProperty(dep + ".repackage.positions");
String[] positions = null;
String[] times = null;
String[] externalAttributesList = null;
String[] files = null;
if (property != null) {
positions = property.split(",");
times = properties.getProperty(dep + ".repackage.times").split(",");
externalAttributesList = properties.getProperty(dep + ".repackage.externalAttributesList").split(",");
property = properties.getProperty(dep + ".repackage.files");
if (property != null) {
files = property.split(",");
for (String fileName : files) {
try (FileOutputStream fos = new FileOutputStream(new File(tmpFiles, fileName))) {
IOUtils.copy(zipFile.getInputStream(zipFile.getEntry("META-INF/exploded-assembly-files/" + fileName)), fos);
}
}
}
}
depSet.add(new Dep(position, name, time, externalAttributes, positions, times, externalAttributesList, files, url));
}
}
int position = 0;
Iterator<Dep> iterator = depSet.iterator();
Dep currentDep = null;
if (iterator.hasNext()) {
currentDep = iterator.next();
}
try (ZipArchiveOutputStream zos = new ZipArchiveOutputStream(new FileOutputStream(destination))) {
try (ZipArchiveInputStream zis = new ZipArchiveInputStream(new FileInputStream(explodedAssembly))) {
ZipArchiveEntry nextEntry = zis.getNextZipEntry();
while (nextEntry != null) {
position++;
while (currentDep != null && position == currentDep.position) {
Matcher matcher = MavenJarExploder.MVN_URL_PATTERN.matcher(currentDep.url);
if (matcher.matches()) {
String extension = matcher.group(4);
if (extension == null) {
extension = "jar";
}
DefaultArtifact artifact = new DefaultArtifact(matcher.group(1), matcher.group(2), matcher.group(5), extension, matcher.group(3));
ArtifactResult resolveArtifact = repositorySystem.resolveArtifact(session, new ArtifactRequest(artifact, repositories, null));
File file = resolveArtifact.getArtifact().getFile();
if (currentDep.positions != null) {
// need to create a new file
File tmpFile = new File("data.zip");
List<FileOverride> fileOverrides = new ArrayList<FileOverride>();
if (currentDep.files != null) {
for (String fileNumber : currentDep.files) {
fileOverrides.add(new FileOverride(Integer.parseInt(properties.getProperty(fileNumber + ".position")), fileNumber,
properties.getProperty(fileNumber + ".name"), Long.parseLong(properties.getProperty(fileNumber + ".time")),
Long.parseLong(properties.getProperty(fileNumber + ".externalAttributes"))));
}
}
FileOverride cFO = null;
Iterator<FileOverride> iteratorFO = fileOverrides.iterator();
if (iteratorFO.hasNext()) {
cFO = iteratorFO.next();
}
try (ZipArchiveOutputStream zosSub = new ZipArchiveOutputStream(new FileOutputStream(tmpFile))) {
int zosPos = 1;
for (int subPos = 0; subPos < currentDep.positions.length; subPos++) {
while (cFO != null && zosPos == cFO.position) {
ZipArchiveEntry zae = new ZipArchiveEntry(cFO.name);
zae.setExternalAttributes(cFO.externalAttributes);
zae.setTime(cFO.time);
zosSub.putArchiveEntry(zae);
try (FileInputStream fis = new FileInputStream(new File(tmpFiles, cFO.explodedName))) {
IOUtils.copy(fis, zosSub);
}
zosSub.closeArchiveEntry();
zosPos++;
if (iteratorFO.hasNext()) {
cFO = iteratorFO.next();
}
}
int depSubPos = Integer.parseInt(currentDep.positions[subPos]);
int currentSubPos = 1;
try (ZipArchiveInputStream zisSub = new ZipArchiveInputStream(new FileInputStream(file))) {
ZipArchiveEntry nextSubEntry = zisSub.getNextZipEntry();
while (currentSubPos != depSubPos) {
currentSubPos++;
nextSubEntry = zisSub.getNextZipEntry();
}
ZipArchiveEntry zae = new ZipArchiveEntry(nextSubEntry.getName());
String s = currentDep.externalAttributesList[subPos];
if (!"_".equals(s)) {
zae.setExternalAttributes(Long.parseLong(s));
} else {
zae.setExternalAttributes(nextSubEntry.getExternalAttributes());
}
s = currentDep.times[subPos];
if (!"_".equals(s)) {
zae.setTime(Long.parseLong(s));
} else {
zae.setTime(nextSubEntry.getTime());
}
zosSub.putArchiveEntry(zae);
IOUtils.copy(zisSub, zosSub);
zosSub.closeArchiveEntry();
zosPos++;
}
}
}
file = tmpFile;
}
ZipArchiveEntry archiveEntry = new ZipArchiveEntry(file, currentDep.name);
archiveEntry.setTime(currentDep.time);
archiveEntry.setExternalAttributes(currentDep.externalAttributes);
zos.putArchiveEntry(archiveEntry);
try (FileInputStream input = new FileInputStream(file)) {
IOUtils.copy(input, zos);
}
zos.closeArchiveEntry();
}
if (iterator.hasNext()) {
currentDep = iterator.next();
}
position++;
}
if ("META-INF/exploded-assembly.properties".equals(nextEntry.getName())) {
// skip exploded-assembly.properties
nextEntry = zis.getNextZipEntry();
continue;
}
zos.putArchiveEntry(nextEntry);
IOUtils.copy(zis, zos);
zos.closeArchiveEntry();
nextEntry = zis.getNextZipEntry();
}
}
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<charset>${console.encoding:-${file.encoding}}</charset>
<pattern>%d{HH:mm:ss.SSS} %level -> %msg%n</pattern>
</encoder>
</appender>
<logger name="fr.gaellalire.maven_jar_exploder" level="INFO" />
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>