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 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 * @return deep copy of this object. 072 */ 073 public ModuleOpens copy() { 074 try { 075 return (ModuleOpens) clone(); 076 } catch (final CloneNotSupportedException e) { 077 // TODO should this throw? 078 } 079 return null; 080 } 081 082 /** 083 * Dumps table entry to file stream in binary format. 084 * 085 * @param file Output file stream. 086 * @throws IOException if an I/O Exception occurs in writeShort. 087 */ 088 public void dump(final DataOutputStream file) throws IOException { 089 file.writeShort(opensIndex); 090 file.writeShort(opensFlags); 091 file.writeShort(opensToCount); 092 for (final int entry : opensToIndex) { 093 file.writeShort(entry); 094 } 095 } 096 097 /** 098 * Gets the flags for this ModuleOpens. 099 * 100 * @return the opensFlags. 101 * @since 6.10.0 102 */ 103 public int getOpensFlags() { 104 return opensFlags; 105 } 106 107 /** 108 * Gets the opened package name. 109 * 110 * @param constantPool the constant pool from the ClassFile. 111 * @return the opened package name. 112 * @since 6.10.0 113 */ 114 public String getPackageName(final ConstantPool constantPool) { 115 return constantPool.constantToString(opensIndex, Const.CONSTANT_Package); 116 } 117 118 /** 119 * Gets an array of module names for this ModuleOpens. 120 * 121 * @param constantPool Array of constants usually obtained from the ClassFile object. 122 * @return array of module names following 'opens to'. 123 * @since 6.10.0 124 */ 125 public String[] getToModuleNames(final ConstantPool constantPool) { 126 final String[] toModuleNames = new String[opensToCount]; 127 for (int i = 0; i < opensToCount; i++) { 128 toModuleNames[i] = getToModuleNameAtIndex(constantPool, opensToIndex[i]); 129 } 130 return toModuleNames; 131 } 132 133 /** 134 * @return String representation. 135 */ 136 @Override 137 public String toString() { 138 return "opens(" + opensIndex + ", " + opensFlags + ", " + opensToCount + ", ...)"; 139 } 140 141 /** 142 * @return Resolved string representation. 143 */ 144 public String toString(final ConstantPool constantPool) { 145 final StringBuilder buf = new StringBuilder(); 146 final String packageName = getPackageName(constantPool); 147 buf.append(packageName); 148 buf.append(", ").append(String.format("%04x", opensFlags)); 149 buf.append(", to(").append(opensToCount).append("):\n"); 150 for (final int index : opensToIndex) { 151 final String moduleName = getToModuleNameAtIndex(constantPool, index); 152 buf.append(" ").append(moduleName).append("\n"); 153 } 154 return buf.substring(0, buf.length() - 1); // remove the last newline 155 } 156}