001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019 020package org.apache.bcel.classfile; 021 022import java.io.DataInput; 023import java.io.DataOutputStream; 024import java.io.IOException; 025 026import org.apache.bcel.Const; 027 028/** 029 * This class represents an entry in the opens table of the Module attribute. Each entry describes a package which the 030 * parent module opens. 031 * 032 * @see Module 033 * @since 6.4.0 034 */ 035public final class ModuleOpens implements Cloneable, Node { 036 037 private static String getToModuleNameAtIndex(final ConstantPool constantPool, final int index) { 038 return constantPool.getConstantString(index, Const.CONSTANT_Module); 039 } 040 private final int opensIndex; // points to CONSTANT_Package_info 041 private final int opensFlags; 042 private final int opensToCount; 043 044 private final int[] opensToIndex; // points to CONSTANT_Module_info 045 046 /** 047 * Constructs object from file stream. 048 * 049 * @param dataInput Input stream. 050 * @throws IOException Thrown if an I/O Exception occurs in readUnsignedShort. 051 */ 052 ModuleOpens(final DataInput dataInput) throws IOException { 053 opensIndex = dataInput.readUnsignedShort(); 054 opensFlags = dataInput.readUnsignedShort(); 055 opensToIndex = ClassParser.readU2U2Table(dataInput); 056 opensToCount = opensToIndex.length; 057 } 058 059 /** 060 * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. 061 * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. 062 * 063 * @param v Visitor object. 064 */ 065 @Override 066 public void accept(final Visitor v) { 067 v.visitModuleOpens(this); 068 } 069 070 /** 071 * Creates a deep copy of this object. 072 * 073 * @return deep copy of this object. 074 */ 075 public ModuleOpens copy() { 076 try { 077 return (ModuleOpens) clone(); 078 } catch (final CloneNotSupportedException e) { 079 // TODO should this throw? 080 } 081 return null; 082 } 083 084 /** 085 * Dumps table entry to file stream in binary format. 086 * 087 * @param file Output file stream. 088 * @throws IOException Thrown if an I/O Exception occurs in writeShort. 089 */ 090 public void dump(final DataOutputStream file) throws IOException { 091 file.writeShort(opensIndex); 092 file.writeShort(opensFlags); 093 file.writeShort(opensToCount); 094 for (final int entry : opensToIndex) { 095 file.writeShort(entry); 096 } 097 } 098 099 /** 100 * Gets the flags for this ModuleOpens. 101 * 102 * @return The opensFlags. 103 * @since 6.10.0 104 */ 105 public int getOpensFlags() { 106 return opensFlags; 107 } 108 109 /** 110 * Gets the opened package name. 111 * 112 * @param constantPool The constant pool from the ClassFile. 113 * @return The opened package name. 114 * @since 6.10.0 115 */ 116 public String getPackageName(final ConstantPool constantPool) { 117 return constantPool.constantToString(opensIndex, Const.CONSTANT_Package); 118 } 119 120 /** 121 * Gets an array of module names for this ModuleOpens. 122 * 123 * @param constantPool Array of constants usually obtained from the ClassFile object. 124 * @return array of module names following 'opens to'. 125 * @since 6.10.0 126 */ 127 public String[] getToModuleNames(final ConstantPool constantPool) { 128 final String[] toModuleNames = new String[opensToCount]; 129 for (int i = 0; i < opensToCount; i++) { 130 toModuleNames[i] = getToModuleNameAtIndex(constantPool, opensToIndex[i]); 131 } 132 return toModuleNames; 133 } 134 135 /** 136 * @return String representation. 137 */ 138 @Override 139 public String toString() { 140 return "opens(" + opensIndex + ", " + opensFlags + ", " + opensToCount + ", ...)"; 141 } 142 143 /** 144 * Gets the resolved string representation. 145 * 146 * @param constantPool The constant pool. 147 * @return Resolved string representation. 148 */ 149 public String toString(final ConstantPool constantPool) { 150 final StringBuilder buf = new StringBuilder(); 151 final String packageName = getPackageName(constantPool); 152 buf.append(packageName); 153 buf.append(", ").append(String.format("%04x", opensFlags)); 154 buf.append(", to(").append(opensToCount).append("):\n"); 155 for (final int index : opensToIndex) { 156 final String moduleName = getToModuleNameAtIndex(constantPool, index); 157 buf.append(" ").append(moduleName).append("\n"); 158 } 159 return buf.substring(0, buf.length() - 1); // remove the last newline 160 } 161}