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 file Input stream 050 * @throws IOException if an I/O Exception occurs in readUnsignedShort 051 */ 052 ModuleOpens(final DataInput file) throws IOException { 053 opensIndex = file.readUnsignedShort(); 054 opensFlags = file.readUnsignedShort(); 055 opensToCount = file.readUnsignedShort(); 056 opensToIndex = new int[opensToCount]; 057 for (int i = 0; i < opensToCount; i++) { 058 opensToIndex[i] = file.readUnsignedShort(); 059 } 060 } 061 062 /** 063 * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. 064 * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. 065 * 066 * @param v Visitor object 067 */ 068 @Override 069 public void accept(final Visitor v) { 070 v.visitModuleOpens(this); 071 } 072 073 /** 074 * @return deep copy of this object 075 */ 076 public ModuleOpens copy() { 077 try { 078 return (ModuleOpens) clone(); 079 } catch (final CloneNotSupportedException e) { 080 // TODO should this throw? 081 } 082 return null; 083 } 084 085 /** 086 * Dump table entry to file stream in binary format. 087 * 088 * @param file Output file stream 089 * @throws IOException if an I/O Exception occurs in writeShort 090 */ 091 public void dump(final DataOutputStream file) throws IOException { 092 file.writeShort(opensIndex); 093 file.writeShort(opensFlags); 094 file.writeShort(opensToCount); 095 for (final int entry : opensToIndex) { 096 file.writeShort(entry); 097 } 098 } 099 100 /** 101 * Gets the flags for this ModuleOpens. 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 * @param constantPool the constant pool from the ClassFile 112 * @return the opened package name 113 * @since 6.10.0 114 */ 115 public String getPackageName(final ConstantPool constantPool) { 116 return constantPool.constantToString(opensIndex, Const.CONSTANT_Package); 117 } 118 119 /** 120 * Gets an array of module names for this ModuleOpens. 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}