de.spricom.dessert.classfile.attribute.ModuleAttribute Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dessert-core Show documentation
Show all versions of dessert-core Show documentation
A library for unit-tests to check the dependencies between classes.
The newest version!
package de.spricom.dessert.classfile.attribute;
/*-
* #%L
* Dessert Dependency Assertion Library for Java
* %%
* Copyright (C) 2017 - 2023 Hans Jörg Heßmann
* %%
* 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
*
* http://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.
* #L%
*/
import de.spricom.dessert.classfile.constpool.ConstantPool;
import java.io.DataInputStream;
import java.io.IOException;
/**
* Represents a
*
* Java Virtual Machine Specification: 4.7.25. The Module Attribute.
*/
public class ModuleAttribute extends AttributeInfo {
// Module flags
public static final int ACC_OPEN = 0x0020; // Indicates that this module is open.
public static final int ACC_SYNTHETIC = 0x1000; // Indicates that this module was not explicitly or implicitly declared.
public static final int ACC_MANDATED = 0x8000; // Indicates that this module was implicitly declared.
// Requires flags
public static final int ACC_TRANSITIVE = 0x0020; // Indicates that any module which depends on the current module, implicitly declares a dependence on the module indicated by this entry.
public static final int ACC_STATIC_PHASE = 0x0040; // Indicates that this dependence is mandatory in the static phase, i.e., at compile time, but is optional in the dynamic phase, i.e., at run time.
public static class Require {
private final String moduleName;
private final int flags;
private final String version;
private Require(DataInputStream is, ConstantPool constantPool) throws IOException {
moduleName = constantPool.getModuleName(is.readUnsignedShort());
flags = is.readUnsignedShort();
int versionIndex = is.readUnsignedShort();
version = versionIndex == 0 ? null : constantPool.getUtf8String(versionIndex);
}
public String getModuleName() {
return moduleName;
}
public int getFlags() {
return flags;
}
public String getVersion() {
return version;
}
public boolean isTransitive() {
return (flags & ACC_TRANSITIVE) != 0;
}
public boolean isStaticPhase() {
return (flags & ACC_STATIC_PHASE) != 0;
}
public boolean isSynthetic() {
return (flags & ACC_SYNTHETIC) != 0;
}
public boolean isMandated() {
return (flags & ACC_MANDATED) != 0;
}
public String toString() {
StringBuilder sb = new StringBuilder();
appendString(sb);
return sb.toString();
}
void appendString(StringBuilder sb) {
sb.append("requires ");
if (isMandated()) {
sb.append("mandated ");
}
if (isSynthetic()) {
sb.append("synthetic ");
}
if (isTransitive()) {
sb.append("transitive ");
}
if (isStaticPhase()) {
sb.append("static ");
}
sb.append(moduleName);
if (version != null) {
sb.append("[").append(version).append("]");
}
}
}
public static class Export {
private final String packageName;
private final int flags;
private final String[] exportsTo;
private Export(DataInputStream is, ConstantPool constantPool) throws IOException {
packageName = constantPool.getPackageName(is.readUnsignedShort());
flags = is.readUnsignedShort();
exportsTo = new String[is.readUnsignedShort()];
for (int i = 0; i < exportsTo.length; i++) {
exportsTo[i] = constantPool.getModuleName(is.readUnsignedShort());
}
}
public String getPackageName() {
return packageName;
}
public int getFlags() {
return flags;
}
public String[] getExportsTo() {
return exportsTo;
}
public boolean isUnqualified() {
return exportsTo.length == 0;
}
public boolean isSynthetic() {
return (flags & ACC_SYNTHETIC) != 0;
}
public boolean isMandated() {
return (flags & ACC_MANDATED) != 0;
}
public String toString() {
StringBuilder sb = new StringBuilder();
appendString(sb);
return sb.toString();
}
void appendString(StringBuilder sb) {
sb.append("exports ");
if (isMandated()) {
sb.append("mandated ");
}
if (isSynthetic()) {
sb.append("synthetic ");
}
sb.append(packageName);
String separator = " to ";
for (String to : exportsTo) {
sb.append(separator).append(to);
separator = ", ";
}
}
}
public static class Open {
private final String packageName;
private final int flags;
private final String[] opensTo;
private Open(DataInputStream is, ConstantPool constantPool) throws IOException {
packageName = constantPool.getPackageName(is.readUnsignedShort());
flags = is.readUnsignedShort();
opensTo = new String[is.readUnsignedShort()];
for (int i = 0; i < opensTo.length; i++) {
opensTo[i] = constantPool.getModuleName(is.readUnsignedShort());
}
}
public String getPackageName() {
return packageName;
}
public int getFlags() {
return flags;
}
public String[] getOpensTo() {
return opensTo;
}
public boolean isUnqualified() {
return opensTo.length == 0;
}
public boolean isSynthetic() {
return (flags & ACC_SYNTHETIC) != 0;
}
public boolean isMandated() {
return (flags & ACC_MANDATED) != 0;
}
public String toString() {
StringBuilder sb = new StringBuilder();
appendString(sb);
return sb.toString();
}
void appendString(StringBuilder sb) {
sb.append("opens ");
if (isMandated()) {
sb.append("mandated ");
}
if (isSynthetic()) {
sb.append("synthetic ");
}
sb.append(packageName);
String separator = " to ";
for (String to : opensTo) {
sb.append(separator).append(to);
separator = ", ";
}
}
}
public static class Use {
private final String className;
private Use(DataInputStream is, ConstantPool constantPool) throws IOException {
className = constantPool.getConstantClassName(is.readUnsignedShort());
}
public String getClassName() {
return className;
}
public String toString() {
return "uses " + className;
}
}
public static class Provide {
private final String className;
private final String[] providesWith;
private Provide(DataInputStream is, ConstantPool constantPool) throws IOException {
className = constantPool.getConstantClassName(is.readUnsignedShort());
providesWith = new String[is.readUnsignedShort()];
for (int i = 0; i < providesWith.length; i++) {
providesWith[i] = constantPool.getConstantClassName(is.readUnsignedShort());
}
}
public String getClassName() {
return className;
}
public String[] getProvidesWith() {
return providesWith;
}
public String toString() {
StringBuilder sb = new StringBuilder();
appendString(sb);
return sb.toString();
}
void appendString(StringBuilder sb) {
sb.append("provides ");
sb.append(className);
String separator = " with ";
for (String with : providesWith) {
sb.append(separator).append(with);
separator = ", ";
}
}
}
private final String moduleName;
private final int moduleFlags;
private final String moduleVersion;
private final Require[] requires;
private final Export[] exports;
private final Open[] opens;
private final Use[] uses;
private final Provide[] provides;
public ModuleAttribute(String name, DataInputStream is, ConstantPool constantPool) throws IOException {
super(name);
skipLength(is);
moduleName = constantPool.getModuleName(is.readUnsignedShort());
moduleFlags = is.readUnsignedShort();
int versionIndex = is.readUnsignedShort();
moduleVersion = versionIndex == 0 ? null : constantPool.getUtf8String(versionIndex);
requires = new Require[is.readUnsignedShort()];
for (int i = 0; i < requires.length; i++) {
requires[i] = new Require(is, constantPool);
}
exports = new Export[is.readUnsignedShort()];
for (int i = 0; i < exports.length; i++) {
exports[i] = new Export(is, constantPool);
}
opens = new Open[is.readUnsignedShort()];
for (int i = 0; i < opens.length; i++) {
opens[i] = new Open(is, constantPool);
}
uses = new Use[is.readUnsignedShort()];
for (int i = 0; i < uses.length; i++) {
uses[i] = new Use(is, constantPool);
}
provides = new Provide[is.readUnsignedShort()];
for (int i = 0; i < provides.length; i++) {
provides[i] = new Provide(is, constantPool);
}
}
public String getModuleName() {
return moduleName;
}
public int getModuleFlags() {
return moduleFlags;
}
public String getModuleVersion() {
return moduleVersion;
}
public Require[] getRequires() {
return requires;
}
public Export[] getExports() {
return exports;
}
public Open[] getOpens() {
return opens;
}
public Use[] getUses() {
return uses;
}
public Provide[] getProvides() {
return provides;
}
public boolean isOpen() {
return (moduleFlags & ACC_OPEN) != 0;
}
public boolean isSynthetic() {
return (moduleFlags & ACC_SYNTHETIC) != 0;
}
public boolean isMandated() {
return (moduleFlags & ACC_MANDATED) != 0;
}
public String toString() {
StringBuilder sb = new StringBuilder(super.toString());
sb.append(":\n");
if (isMandated()) {
sb.append("mandated ");
}
if (isSynthetic()) {
sb.append("synthetic ");
}
if (isOpen()) {
sb.append("open ");
}
sb.append("module ");
sb.append(moduleName);
if (moduleVersion != null) {
sb.append("[").append(moduleVersion).append("]");
}
sb.append(" {\n");
for (Require require : requires) {
sb.append(" ");
require.appendString(sb);
sb.append(";\n");
}
for (Export export : exports) {
sb.append(" ");
export.appendString(sb);
sb.append(";\n");
}
for (Open open : opens) {
sb.append(" ");
open.appendString(sb);
sb.append(";\n");
}
for (Use use : uses) {
sb.append(" ").append(use).append(";\n");
}
for (Provide provide : provides) {
sb.append(" ");
provide.appendString(sb);
sb.append(";\n");
}
sb.append("}\n");
return sb.toString();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy