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 Thrown 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 * Creates a deep copy of this object. 074 * 075 * @return deep copy of this object. 076 */ 077 public ModuleProvides copy() { 078 try { 079 return (ModuleProvides) clone(); 080 } catch (final CloneNotSupportedException e) { 081 // TODO should this throw? 082 } 083 return null; 084 } 085 086 /** 087 * Dumps table entry to file stream in binary format. 088 * 089 * @param file Output file stream. 090 * @throws IOException Thrown if an I/O Exception occurs in writeShort. 091 */ 092 public void dump(final DataOutputStream file) throws IOException { 093 file.writeShort(providesIndex); 094 file.writeShort(providesWithCount); 095 for (final int entry : providesWithIndex) { 096 file.writeShort(entry); 097 } 098 } 099 100 /** 101 * Gets the array of implementation class names for this ModuleProvides. 102 * 103 * @param constantPool Array of constants usually obtained from the ClassFile object. 104 * @param compactClassName false for original constant pool value, true to replace '/' with '.'. 105 * @return array of implementation class names. 106 * @since 6.10.0 107 */ 108 public String[] getImplementationClassNames(final ConstantPool constantPool, final boolean compactClassName) { 109 final String[] implementationClassNames = new String[providesWithCount]; 110 for (int i = 0; i < providesWithCount; i++) { 111 implementationClassNames[i] = getImplementationClassNameAtIndex(constantPool, providesWithIndex[i], compactClassName); 112 } 113 return implementationClassNames; 114 } 115 116 /** 117 * Gets the interface name for this ModuleProvides. 118 * 119 * @param constantPool Array of constants usually obtained from the ClassFile object. 120 * @return interface name. 121 * @since 6.10.0 122 */ 123 public String getInterfaceName(final ConstantPool constantPool) { 124 return constantPool.constantToString(providesIndex, Const.CONSTANT_Class); 125 } 126 127 /** 128 * @return String representation. 129 */ 130 @Override 131 public String toString() { 132 return "provides(" + providesIndex + ", " + providesWithCount + ", ...)"; 133 } 134 135 /** 136 * Gets the resolved string representation. 137 * 138 * @param constantPool The constant pool. 139 * @return Resolved string representation. 140 */ 141 public String toString(final ConstantPool constantPool) { 142 final StringBuilder buf = new StringBuilder(); 143 final String interfaceName = getInterfaceName(constantPool); 144 buf.append(interfaceName); 145 buf.append(", with(").append(providesWithCount).append("):\n"); 146 for (final int index : providesWithIndex) { 147 final String className = getImplementationClassNameAtIndex(constantPool, index, true); 148 buf.append(" ").append(className).append("\n"); 149 } 150 return buf.substring(0, buf.length() - 1); // remove the last newline 151 } 152}