Skip to content

Commit

Permalink
feat(core): Add module commands
Browse files Browse the repository at this point in the history
  • Loading branch information
aalmiray committed Feb 3, 2023
1 parent f78e945 commit 1dcf1b4
Show file tree
Hide file tree
Showing 20 changed files with 493 additions and 30 deletions.
27 changes: 24 additions & 3 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ Options:
-V, --version Print version information and exit.
Commands:
bytecode Commands for the JAR's bytecode
manifest Commands for the JAR's manifest
services Commands for declarative services
bytecode Commands for the JAR's bytecode.
manifest Commands for the JAR's manifest.
module Commands for modular JARs.
services Commands for declarative services.
generate-completion Generate bash/zsh completion script for jarviz.
Documentation found at https://github.com/kordamp/jarviz
Expand Down Expand Up @@ -114,6 +115,26 @@ $ jarviz manifest query --gav org.kordamp.maven:pomchecker-toolprovider:1.4.0 \
org.kordamp.maven.pomchecker
----

=== Module

.name

[source]
----
$ jarviz module name --gav org.slf4j:slf4j-api:1.7.36
name: org.slf4j
automatic: manifest
valid: true
----

[source]
----
$ jarviz module name --gav org.slf4j:slf4j-api:2.0.6
name: org.slf4j
automatic: no
valid: true
----

=== Services

.list
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@
*/
public interface Constants {
String ATTR_BYTECODE_VERSION = "Bytecode-Version";
String ATTR_AUTOMATIC_MODULE_NAME = "Automatic-Module-Name";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright 2022-2023 The Jarviz authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.kordamp.jarviz.core;

import java.util.jar.JarFile;

/**
* @author Andres Almiray
* @since 0.2.0
*/
public interface JarFileAnalyzer<R> extends JarAnalyzer<R> {
void handle(JarFile jarFile);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright 2022-2023 The Jarviz authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.kordamp.jarviz.core;

import java.nio.file.Path;

/**
* @author Andres Almiray
* @since 0.2.0
*/
public interface JarPathAnalyzer<R> extends JarAnalyzer<R> {
void handle(Path path);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright 2022-2023 The Jarviz authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.kordamp.jarviz.core.analyzers;

import org.kordamp.jarviz.core.JarPathAnalyzer;
import org.kordamp.jarviz.core.model.ModuleName;

import java.lang.module.FindException;
import java.lang.module.InvalidModuleDescriptorException;
import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleFinder;
import java.lang.module.ModuleReference;
import java.nio.file.Path;
import java.util.Optional;

import static org.kordamp.jarviz.util.StringUtils.isBlank;
import static org.kordamp.jarviz.util.StringUtils.isNotBlank;

/**
* @author Andres Almiray
* @since 0.2.0
*/
public class ModuleNameJarPathAnalyzer implements JarPathAnalyzer<ModuleName> {
private final String automaticModuleNameByManifest;
private final String automaticModuleNameByFilename;
private ModuleName moduleName;

public ModuleNameJarPathAnalyzer(String automaticModuleNameByManifest, String automaticModuleNameByFilename) {
this.automaticModuleNameByManifest = automaticModuleNameByManifest;
this.automaticModuleNameByFilename = automaticModuleNameByFilename;
}

@Override
public ModuleName getResult() {
return moduleName;
}

@Override
public void handle(Path path) {
if (isNotBlank(automaticModuleNameByManifest)) {
moduleName = ModuleName.fromAutomaticByManifest(automaticModuleNameByManifest,
isAutomaticNameValid(automaticModuleNameByManifest).orElse(null));
}

try {
moduleName = ModuleFinder.of(path).findAll().stream()
.map(ModuleReference::descriptor)
.map(this::toModuleName)
.findFirst()
.get();
} catch (FindException fe) {
// automatic by filename
moduleName = ModuleName.fromAutomaticByFilename(automaticModuleNameByFilename, fe.getCause().getMessage());
} catch (InvalidModuleDescriptorException imde) {
// explicit
// TODO: read module name from [versioned] module-info.class
moduleName = ModuleName.fromModuleDescriptor("", imde.getMessage());
}
}

private ModuleName toModuleName(ModuleDescriptor moduleDescriptor) {
return ModuleName.fromModuleDescriptor(moduleDescriptor.name(),
moduleDescriptor.isAutomatic() && isNotBlank(automaticModuleNameByManifest),
moduleDescriptor.isAutomatic() && isBlank(automaticModuleNameByManifest) && isNotBlank(automaticModuleNameByFilename),
isValid(moduleDescriptor.name()).orElse(null));
}

private Optional<String> isAutomaticNameValid(String name) {
try {
ModuleDescriptor.newAutomaticModule(name);
return Optional.empty();
} catch (IllegalArgumentException exception) {
return Optional.of(exception.getMessage());
}
}

private Optional<String> isValid(String name) {
try {
ModuleDescriptor.newModule(name);
return Optional.empty();
} catch (IllegalArgumentException exception) {
return Optional.of(exception.getMessage());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.kordamp.jarviz.util.JarUtils;

import java.util.Enumeration;
import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
import java.util.jar.JarEntry;
Expand Down Expand Up @@ -54,17 +55,19 @@ public BytecodeVersions getResult() {
BytecodeVersions bytecodeVersions = new BytecodeVersions();

JarFile jarFile = jarFileResolver.resolveJarFile();
Manifest manifest = JarUtils.getManifest(jarFile);
Optional<Manifest> manifest = JarUtils.getManifest(jarFile);

QueryJarManifestAnalyzer analyzer = new QueryJarManifestAnalyzer(ATTR_BYTECODE_VERSION);
analyzer.handle(jarFile, manifest);
analyzer.getResult().ifPresent(v -> {
Set<Integer> set = new TreeSet<>();
stream(v.split(","))
.map(Integer::parseInt)
.forEach(set::add);
bytecodeVersions.setManifestBytecode(set);
});
if (manifest.isPresent()) {
QueryJarManifestAnalyzer analyzer = new QueryJarManifestAnalyzer(ATTR_BYTECODE_VERSION);
analyzer.handle(jarFile, manifest.get());
analyzer.getResult().ifPresent(v -> {
Set<Integer> set = new TreeSet<>();
stream(v.split(","))
.map(Integer::parseInt)
.forEach(set::add);
bytecodeVersions.setManifestBytecode(set);
});
}

Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright 2022-2023 The Jarviz authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.kordamp.jarviz.core.model;

/**
* @author Andres Almiray
* @since 0.2.0
*/
public class ModuleName {
private final String moduleName;
private final boolean automaticByManifest;
private final boolean automaticByFilename;
private final boolean valid;
private final String reason;

private ModuleName(String moduleName, boolean automaticByManifest, boolean automaticByFilename, String reason) {
this.moduleName = moduleName;
this.automaticByManifest = automaticByManifest;
this.automaticByFilename = automaticByFilename;
this.valid = null == reason;
this.reason = reason;
}

public boolean isAutomatic() {
return automaticByManifest || automaticByFilename;
}

public String getModuleName() {
return moduleName;
}

public boolean isAutomaticByManifest() {
return automaticByManifest;
}

public boolean isAutomaticByFilename() {
return automaticByFilename;
}

public boolean isValid() {
return valid;
}

public String getReason() {
return reason;
}

public static ModuleName fromAutomaticByManifest(String moduleName, String reason) {
return new ModuleName(moduleName, true, false, reason);
}

public static ModuleName fromAutomaticByFilename(String moduleName, String reason) {
return new ModuleName(moduleName, false, true, reason);
}

public static ModuleName fromModuleDescriptor(String moduleName, String reason) {
return fromModuleDescriptor(moduleName, false, false, reason);
}

public static ModuleName fromModuleDescriptor(String moduleName, boolean automaticByManifest, boolean automaticByFilename, String reason) {
return new ModuleName(moduleName, automaticByManifest, automaticByFilename, reason);
}
}
Loading

0 comments on commit 1dcf1b4

Please sign in to comment.