View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   */
17  
18  package org.apache.bcel.classfile;
19  
20  import java.io.DataInput;
21  import java.io.DataOutputStream;
22  import java.io.IOException;
23  
24  import org.apache.bcel.Const;
25  
26  /**
27   * This class is derived from <em>Attribute</em> and represents the list of modules required, exported, opened or provided by a module.
28   * There may be at most one Module attribute in a ClassFile structure.
29   *
30   * @see   Attribute
31   * @since 6.4.0
32   */
33  public final class Module extends Attribute {
34  
35      private final int moduleNameIndex;
36      private final int moduleFlags;
37      private final int moduleVersionIndex;
38  
39      private ModuleRequires[] requiresTable;
40      private ModuleExports[] exportsTable;
41      private ModuleOpens[] opensTable;
42      private final int usesCount;
43      private final int[] usesIndex;
44      private ModuleProvides[] providesTable;
45  
46      /**
47       * Construct object from input stream.
48       * @param name_index Index in constant pool
49       * @param length Content length in bytes
50       * @param input Input stream
51       * @param constant_pool Array of constants
52       * @throws IOException
53       */
54      Module(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) throws IOException {
55          super(Const.ATTR_MODULE, name_index, length, constant_pool);
56  
57          moduleNameIndex = input.readUnsignedShort();
58          moduleFlags = input.readUnsignedShort();
59          moduleVersionIndex = input.readUnsignedShort();
60  
61          final int requires_count = input.readUnsignedShort();
62          requiresTable = new ModuleRequires[requires_count];
63          for (int i = 0; i < requires_count; i++) {
64              requiresTable[i] = new ModuleRequires(input);
65          }
66  
67          final int exports_count = input.readUnsignedShort();
68          exportsTable = new ModuleExports[exports_count];
69          for (int i = 0; i < exports_count; i++) {
70              exportsTable[i] = new ModuleExports(input);
71          }
72  
73          final int opens_count = input.readUnsignedShort();
74          opensTable = new ModuleOpens[opens_count];
75          for (int i = 0; i < opens_count; i++) {
76              opensTable[i] = new ModuleOpens(input);
77          }
78  
79          usesCount = input.readUnsignedShort();
80          usesIndex = new int[usesCount];
81          for (int i = 0; i < usesCount; i++) {
82              usesIndex[i] = input.readUnsignedShort();
83          }
84  
85          final int provides_count = input.readUnsignedShort();
86          providesTable = new ModuleProvides[provides_count];
87          for (int i = 0; i < provides_count; i++) {
88              providesTable[i] = new ModuleProvides(input);
89          }
90      }
91  
92  
93      /**
94       * Called by objects that are traversing the nodes of the tree implicitely
95       * defined by the contents of a Java class. I.e., the hierarchy of methods,
96       * fields, attributes, etc. spawns a tree of objects.
97       *
98       * @param v Visitor object
99       */
100     @Override
101     public void accept( final Visitor v ) {
102         v.visitModule(this);
103     }
104 
105     // TODO add more getters and setters?
106 
107     /**
108      * @return table of required modules
109      * @see ModuleRequires
110      */
111     public ModuleRequires[] getRequiresTable() {
112         return requiresTable;
113     }
114 
115 
116     /**
117      * @return table of exported interfaces
118      * @see ModuleExports
119      */
120     public ModuleExports[] getExportsTable() {
121         return exportsTable;
122     }
123 
124 
125     /**
126      * @return table of provided interfaces
127      * @see ModuleOpens
128      */
129     public ModuleOpens[] getOpensTable() {
130         return opensTable;
131     }
132 
133 
134     /**
135      * @return table of provided interfaces
136      * @see ModuleProvides
137      */
138     public ModuleProvides[] getProvidesTable() {
139         return providesTable;
140     }
141 
142 
143     /**
144      * Dump Module attribute to file stream in binary format.
145      *
146      * @param file Output file stream
147      * @throws IOException
148      */
149     @Override
150     public void dump( final DataOutputStream file ) throws IOException {
151         super.dump(file);
152 
153         file.writeShort(moduleNameIndex);
154         file.writeShort(moduleFlags);
155         file.writeShort(moduleVersionIndex);
156 
157         file.writeShort(requiresTable.length);
158         for (final ModuleRequires entry : requiresTable) {
159             entry.dump(file);
160         }
161 
162         file.writeShort(exportsTable.length);
163         for (final ModuleExports entry : exportsTable) {
164             entry.dump(file);
165         }
166 
167         file.writeShort(opensTable.length);
168         for (final ModuleOpens entry : opensTable) {
169             entry.dump(file);
170         }
171 
172         file.writeShort(usesIndex.length);
173         for (final int entry : usesIndex) {
174             file.writeShort(entry);
175         }
176 
177         file.writeShort(providesTable.length);
178         for (final ModuleProvides entry : providesTable) {
179             entry.dump(file);
180         }
181     }
182 
183 
184     /**
185      * @return String representation, i.e., a list of packages.
186      */
187     @Override
188     public String toString() {
189         final ConstantPool cp = super.getConstantPool();
190         final StringBuilder buf = new StringBuilder();
191         buf.append("Module:\n");
192         buf.append("  name:    ") .append(cp.getConstantString(moduleNameIndex, Const.CONSTANT_Module).replace('/', '.')).append("\n");
193         buf.append("  flags:   ") .append(String.format("%04x", moduleFlags)).append("\n");
194         final String version = moduleVersionIndex == 0 ? "0" : cp.getConstantString(moduleVersionIndex, Const.CONSTANT_Utf8);
195         buf.append("  version: ") .append(version).append("\n");
196 
197         buf.append("  requires(").append(requiresTable.length).append("):\n");
198         for (final ModuleRequires module : requiresTable) {
199             buf.append("    ").append(module.toString(cp)).append("\n");
200         }
201 
202         buf.append("  exports(").append(exportsTable.length).append("):\n");
203         for (final ModuleExports module : exportsTable) {
204             buf.append("    ").append(module.toString(cp)).append("\n");
205         }
206 
207         buf.append("  opens(").append(opensTable.length).append("):\n");
208         for (final ModuleOpens module : opensTable) {
209             buf.append("    ").append(module.toString(cp)).append("\n");
210         }
211 
212         buf.append("  uses(").append(usesIndex.length).append("):\n");
213         for (final int index : usesIndex) {
214             final String class_name = cp.getConstantString(index, Const.CONSTANT_Class);
215             buf.append("    ").append(Utility.compactClassName(class_name, false)).append("\n");
216         }
217 
218         buf.append("  provides(").append(providesTable.length).append("):\n");
219         for (final ModuleProvides module : providesTable) {
220             buf.append("    ").append(module.toString(cp)).append("\n");
221         }
222 
223         return buf.substring(0, buf.length()-1); // remove the last newline
224     }
225 
226 
227     /**
228      * @return deep copy of this attribute
229      */
230     @Override
231     public Attribute copy( final ConstantPool _constant_pool ) {
232         final Moduleref="../../../../org/apache/bcel/classfile/Module.html#Module">Module c = (Module) clone();
233 
234         c.requiresTable = new ModuleRequires[requiresTable.length];
235         for (int i = 0; i < requiresTable.length; i++) {
236             c.requiresTable[i] = requiresTable[i].copy();
237         }
238 
239         c.exportsTable = new ModuleExports[exportsTable.length];
240         for (int i = 0; i < exportsTable.length; i++) {
241             c.exportsTable[i] = exportsTable[i].copy();
242         }
243 
244         c.opensTable = new ModuleOpens[opensTable.length];
245         for (int i = 0; i < opensTable.length; i++) {
246             c.opensTable[i] = opensTable[i].copy();
247         }
248 
249         c.providesTable = new ModuleProvides[providesTable.length];
250         for (int i = 0; i < providesTable.length; i++) {
251             c.providesTable[i] = providesTable[i].copy();
252         }
253 
254         c.setConstantPool(_constant_pool);
255         return c;
256     }
257 }