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 provides table of the Module attribute. Each entry describes a service 030 * implementation that the parent module provides. 031 * 032 * @see Module 033 * @since 6.4.0 034 */ 035public final class ModuleProvides implements Cloneable, Node { 036 037 private static String getImplementationClassNameAtIndex(final ConstantPool constantPool, final int index, final boolean compactClassName) { 038 final String className = constantPool.getConstantString(index, Const.CONSTANT_Class); 039 if (compactClassName) { 040 return Utility.compactClassName(className, false); 041 } 042 return className; 043 } 044 private final int providesIndex; // points to CONSTANT_Class_info 045 private final int providesWithCount; 046 047 private final int[] providesWithIndex; // points to CONSTANT_Class_info 048 049 /** 050 * Constructs object from file stream. 051 * 052 * @param dataInput Input stream. 053 * @throws IOException if an I/O Exception occurs in readUnsignedShort. 054 */ 055 ModuleProvides(final DataInput dataInput) throws IOException { 056 providesIndex = dataInput.readUnsignedShort(); 057 providesWithIndex = ClassParser.readU2U2Table(dataInput); 058 providesWithCount = providesWithIndex.length; 059 } 060 061 /** 062 * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class. 063 * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects. 064 * 065 * @param v Visitor object. 066 */ 067 @Override 068 public void accept(final Visitor v) { 069 v.visitModuleProvides(this); 070 } 071 072 /** 073 * @return deep copy of this object. 074 */ 075 public ModuleProvides copy() { 076 try { 077 return (ModuleProvides) 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 if an I/O Exception occurs in writeShort. 089 */ 090 public void dump(final DataOutputStream file) throws IOException { 091 file.writeShort(providesIndex); 092 file.writeShort(providesWithCount); 093 for (final int entry : providesWithIndex) { 094 file.writeShort(entry); 095 } 096 } 097 098 /** 099 * Gets the array of implementation class names for this ModuleProvides. 100 * 101 * @param constantPool Array of constants usually obtained from the ClassFile object. 102 * @param compactClassName false for original constant pool value, true to replace '/' with '.'. 103 * @return array of implementation class names. 104 * @since 6.10.0 105 */ 106 public String[] getImplementationClassNames(final ConstantPool constantPool, final boolean compactClassName) { 107 final String[] implementationClassNames = new String[providesWithCount]; 108 for (int i = 0; i < providesWithCount; i++) { 109 implementationClassNames[i] = getImplementationClassNameAtIndex(constantPool, providesWithIndex[i], compactClassName); 110 } 111 return implementationClassNames; 112 } 113 114 /** 115 * Gets the interface name for this ModuleProvides. 116 * 117 * @param constantPool Array of constants usually obtained from the ClassFile object. 118 * @return interface name. 119 * @since 6.10.0 120 */ 121 public String getInterfaceName(final ConstantPool constantPool) { 122 return constantPool.constantToString(providesIndex, Const.CONSTANT_Class); 123 } 124 125 /** 126 * @return String representation. 127 */ 128 @Override 129 public String toString() { 130 return "provides(" + providesIndex + ", " + providesWithCount + ", ...)"; 131 } 132 133 /** 134 * @return Resolved string representation. 135 */ 136 public String toString(final ConstantPool constantPool) { 137 final StringBuilder buf = new StringBuilder(); 138 final String interfaceName = getInterfaceName(constantPool); 139 buf.append(interfaceName); 140 buf.append(", with(").append(providesWithCount).append("):\n"); 141 for (final int index : providesWithIndex) { 142 final String className = getImplementationClassNameAtIndex(constantPool, index, true); 143 buf.append(" ").append(className).append("\n"); 144 } 145 return buf.substring(0, buf.length() - 1); // remove the last newline 146 } 147}