Skip to content

Commit

Permalink
New Content view for jar files
Browse files Browse the repository at this point in the history
Signed-off-by: Phillip Kruger <[email protected]>
  • Loading branch information
phillip-kruger committed Apr 17, 2024
1 parent 5628e7b commit 014e121
Show file tree
Hide file tree
Showing 15 changed files with 1,884 additions and 30 deletions.
2 changes: 1 addition & 1 deletion .locker/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.mvnpm</groupId>
<version>3.0.33-SNAPSHOT</version>
<version>3.0.34-SNAPSHOT</version>
<artifactId>mvnpm-locker</artifactId>
<packaging>pom</packaging>

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ to use it in your local Maven settings add the following to your settings.xml (t

### How does the mvnpm Maven repository work ?

![Schema](src/main/resources/web/static/mvnpm.png)
![Schema](src/main/resources/web/static/how-does-mvnpm-work.png)

* Developer's Maven build requests an npm package from Maven Central.
* Maven Central returns a 404 if the package does not exist.
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>io.mvnpm</groupId>
<artifactId>mvnpm</artifactId>
<version>3.0.33-SNAPSHOT</version>
<version>3.0.34-SNAPSHOT</version>
<name>mvnpm</name>
<description>Maven on NPM</description>
<url>https://mvnpm.org/</url>
Expand Down
43 changes: 43 additions & 0 deletions src/main/java/io/mvnpm/JarAsset.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package io.mvnpm;

import java.util.List;

public class JarAsset {
private String name;
private List<JarAsset> children;
private boolean fileAsset;
private String urlPart;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public List<JarAsset> getChildren() {
return children;
}

public void setChildren(List<JarAsset> children) {
this.children = children;
}

public boolean isFileAsset() {
return fileAsset;
}

public void setFileAsset(boolean fileAsset) {
this.fileAsset = fileAsset;
}

public String getUrlPart() {
return urlPart;
}

public void setUrlPart(String urlPart) {
this.urlPart = urlPart;
}

}
199 changes: 199 additions & 0 deletions src/main/java/io/mvnpm/JarContentsApi.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
package io.mvnpm;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.jar.JarFile;

import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;

import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;

import io.mvnpm.file.FileType;
import io.mvnpm.maven.MavenRepositoryService;
import io.mvnpm.maven.NameVersionType;
import io.mvnpm.maven.UrlPathParser;

/**
* Get the file listing for a jar file
*
* @author Phillip Kruger ([email protected])
*/
@Path("/api")
public class JarContentsApi {

@Inject
MavenRepositoryService mavenRepositoryService;

@GET
@Path("/org/mvnpm/{gavt : (.+)?}.jar")
public JarLibrary getJar(@PathParam("gavt") String gavt) {
NameVersionType nameVersionType = UrlPathParser.parseMavenFile(gavt);
return loadJarLibrary(nameVersionType, FileType.jar);
}

@GET
@Path("/org/mvnpm/{gavt : (.+)?}-sources.jar")
public JarLibrary getSourcesJar(@PathParam("gavt") String gavt) {
NameVersionType nameVersionType = UrlPathParser.parseMavenFile(gavt);
return loadJarLibrary(nameVersionType, FileType.source);
}

@GET
@Path("/org/mvnpm/{gavt : (.+)?}-javadoc.jar")
public JarLibrary getJavadocJar(@PathParam("gavt") String gavt) {
NameVersionType nameVersionType = UrlPathParser.parseMavenFile(gavt);
return loadJarLibrary(nameVersionType, FileType.javadoc);
}

@GET
@Path("/org/mvnpm/{gavt : (.+)?}.tgz")
public JarLibrary getTgz(@PathParam("gavt") String gavt) {
NameVersionType nameVersionType = UrlPathParser.parseMavenFile(gavt);
return loadTarGzLibrary(nameVersionType);
}

private JarLibrary loadJarLibrary(NameVersionType nameVersionType, FileType filetype) {
java.nio.file.Path path = mavenRepositoryService.getPath(nameVersionType.name(), nameVersionType.version(),
filetype);

JarLibrary library = new JarLibrary(nameVersionType.name().displayName);
library.setVersion(nameVersionType.version());
library.setType(filetype.getPostString());

try (JarFile jarFile = new JarFile(path.toString())) {
Map<String, JarAsset> assetMap = new HashMap<>();

// Create a root asset
JarAsset rootAsset = new JarAsset();
rootAsset.setName("/");
rootAsset.setFileAsset(false);
rootAsset.setChildren(new ArrayList<>());
assetMap.put("/", rootAsset);

// Iterate through the entries of the jar file
jarFile.stream().forEach(entry -> {
String name = entry.getName();
boolean isFile = !entry.isDirectory();
String[] parts = name.split("/");
StringBuilder pathBuilder = new StringBuilder("/");

JarAsset currentParent = rootAsset;

// Process each part of the entry's name
for (int i = 0; i < parts.length - (isFile ? 1 : 0); i++) {
pathBuilder.append(parts[i]);
String currentPath = pathBuilder.toString() + "/";

if (!assetMap.containsKey(currentPath)) {
JarAsset newAsset = new JarAsset();
newAsset.setName(parts[i]);
newAsset.setFileAsset(false);
newAsset.setUrlPart(currentPath);
newAsset.setChildren(new ArrayList<>());

currentParent.getChildren().add(newAsset);
assetMap.put(currentPath, newAsset);
}

currentParent = assetMap.get(currentPath);
pathBuilder.append("/");
}

// If it's a file, add it to the current parent directory
if (isFile) {
JarAsset fileAsset = new JarAsset();
fileAsset.setName(parts[parts.length - 1]);
fileAsset.setFileAsset(true);
fileAsset.setUrlPart(name);
currentParent.getChildren().add(fileAsset);
}
});

library.setRootAsset(rootAsset);

} catch (IOException e) {
e.printStackTrace();
}

return library;
}

private JarLibrary loadTarGzLibrary(NameVersionType nameVersionType) {
java.nio.file.Path path = mavenRepositoryService.getPath(nameVersionType.name(), nameVersionType.version(),
FileType.tgz);

JarLibrary library = new JarLibrary(nameVersionType.name().displayName);
library.setVersion(nameVersionType.version());
library.setType(FileType.tgz.getPostString());

Map<String, JarAsset> assetMap = new HashMap<>();
JarAsset rootAsset = new JarAsset();
rootAsset.setName("/");
rootAsset.setFileAsset(false);
rootAsset.setChildren(new ArrayList<>());
assetMap.put("/", rootAsset);

try (FileInputStream fin = new FileInputStream(path.toFile());
GzipCompressorInputStream gzIn = new GzipCompressorInputStream(fin);
TarArchiveInputStream tarIn = new TarArchiveInputStream(gzIn)) {

ArchiveEntry entry;

while ((entry = tarIn.getNextEntry()) != null) {
if (!tarIn.canReadEntryData(entry)) {
continue;
}
String name = entry.getName();
boolean isFile = !((TarArchiveEntry) entry).isDirectory();
String[] parts = name.split("/");
StringBuilder pathBuilder = new StringBuilder("/");

JarAsset currentParent = rootAsset;

// Process each part of the entry's name
for (int i = 0; i < parts.length - (isFile ? 1 : 0); i++) {
pathBuilder.append(parts[i]);
String currentPath = pathBuilder.toString() + "/";

if (!assetMap.containsKey(currentPath)) {
JarAsset newAsset = new JarAsset();
newAsset.setName(parts[i]);
newAsset.setFileAsset(false);
newAsset.setUrlPart(currentPath);
newAsset.setChildren(new ArrayList<>());

currentParent.getChildren().add(newAsset);
assetMap.put(currentPath, newAsset);
}

currentParent = assetMap.get(currentPath);
pathBuilder.append("/");
}

// If it's a file, add it to the current parent directory
if (isFile) {
JarAsset fileAsset = new JarAsset();
fileAsset.setName(parts[parts.length - 1]);
fileAsset.setFileAsset(true);
fileAsset.setUrlPart(name);
currentParent.getChildren().add(fileAsset);
}
}
library.setRootAsset(rootAsset);
} catch (IOException e) {
e.printStackTrace();
}

return library;
}

}
45 changes: 45 additions & 0 deletions src/main/java/io/mvnpm/JarLibrary.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package io.mvnpm;

/**
* Represent the contents of a Jar Library
*
* @author Phillip Kruger ([email protected])
*/
public class JarLibrary {
private final String jarName;
private String version;
private String type;
private JarAsset rootAsset;

public JarLibrary(String jarName) {
this.jarName = jarName;
}

public String getJarName() {
return jarName;
}

public String getVersion() {
return version;
}

public void setVersion(String version) {
this.version = version;
}

public String getType() {
return type;
}

public void setType(String type) {
this.type = type;
}

public JarAsset getRootAsset() {
return rootAsset;
}

public void setRootAsset(JarAsset rootAsset) {
this.rootAsset = rootAsset;
}
}
5 changes: 4 additions & 1 deletion src/main/resources/web/app/mvnpm-doc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ export class MvnpmDoc extends LitElement {
text-decoration: none;
color:var(--lumo-body-text-color);
}
.how{
width: 100%;
}
`;
@state() _dep: string = `
<dependency>
Expand Down Expand Up @@ -156,7 +159,7 @@ export class MvnpmDoc extends LitElement {
</section>
<section>
<h3>How does the mvnpm Maven repository work ?</h3>
<img src="/static/mvnpm.png"/>
<img class="how" src="/static/how-does-mvnpm-work.png"/>
<ul>
<li>Developer's Maven build requests an npm package from Maven Central.</li>
Expand Down
10 changes: 2 additions & 8 deletions src/main/resources/web/app/mvnpm-home.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import '@quarkus-webcomponents/card';
import '@quarkus-webcomponents/badge';
import { Notification } from '@vaadin/notification';
import { marked } from 'marked';
import './mvnpm-jar-view.js';

interface Coordinates {
name: string;
Expand Down Expand Up @@ -631,11 +632,7 @@ export class MvnpmHome extends LitElement {
if(this._codeViewMode){
return html`<qui-code-block mode="${this._codeViewMode}" src='${this._codeViewSrc}'></qui-code-block>`;
}else{
return html`<div class="codeView">
<div class="nopreview">
binary format - no preview
</div>
</div>`;
return html`<mvnpm-jar-view jarName="${this._codeViewSrc}"></mvnpm-jar-view>`;
}
}

Expand Down Expand Up @@ -690,9 +687,6 @@ export class MvnpmHome extends LitElement {

fetch(metadataUrl)
.then((response) => {



if(response.ok){
let contentLength = response.headers.get('Content-Length');
if (contentLength == null || parseInt(contentLength, 10) > 0) {
Expand Down
Loading

0 comments on commit 014e121

Please sign in to comment.