1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Licensed to the Apache Software Foundation (ASF) under one or more
   7  * contributor license agreements.  See the NOTICE file distributed with
   8  * this work for additional information regarding copyright ownership.
   9  * The ASF licenses this file to You under the Apache License, Version 2.0
  10  * (the "License"); you may not use this file except in compliance with
  11  * the License.  You may obtain a copy of the License at
  12  *
  13  *      http://www.apache.org/licenses/LICENSE-2.0
  14  *
  15  *  Unless required by applicable law or agreed to in writing, software
  16  *  distributed under the License is distributed on an "AS IS" BASIS,
  17  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18  *  See the License for the specific language governing permissions and
  19  *  limitations under the License.
  20  */
  21 
  22 package com.sun.org.apache.bcel.internal.classfile;
  23 
  24 import java.io.DataInput;
  25 import java.io.DataOutputStream;
  26 import java.io.IOException;
  27 
  28 import com.sun.org.apache.bcel.internal.Const;
  29 
  30 /**
  31  * This class is derived from <em>Attribute</em> and represents the list of packages that are exported or opened by the Module attribute.
  32  * There may be at most one ModulePackages attribute in a ClassFile structure.
  33  *
  34  * @see     Attribute
  35  */
  36 public final class ModulePackages extends Attribute {
  37 
  38     private int[] package_index_table;
  39 
  40 
  41     /**
  42      * Initialize from another object. Note that both objects use the same
  43      * references (shallow copy). Use copy() for a physical copy.
  44      */
  45     public ModulePackages(final ModulePackages c) {
  46         this(c.getNameIndex(), c.getLength(), c.getPackageIndexTable(), c.getConstantPool());
  47     }
  48 
  49 
  50     /**
  51      * @param name_index Index in constant pool
  52      * @param length Content length in bytes
  53      * @param package_index_table Table of indices in constant pool
  54      * @param constant_pool Array of constants
  55      */
  56     public ModulePackages(final int name_index, final int length, final int[] package_index_table,
  57             final ConstantPool constant_pool) {
  58         super(Const.ATTR_MODULE_PACKAGES, name_index, length, constant_pool);
  59         this.package_index_table = package_index_table != null ? package_index_table : new int[0];
  60     }
  61 
  62 
  63     /**
  64      * Construct object from input stream.
  65      * @param name_index Index in constant pool
  66      * @param length Content length in bytes
  67      * @param input Input stream
  68      * @param constant_pool Array of constants
  69      * @throws IOException
  70      */
  71     ModulePackages(final int name_index, final int length, final DataInput input, final ConstantPool constant_pool) throws IOException {
  72         this(name_index, length, (int[]) null, constant_pool);
  73         final int number_of_packages = input.readUnsignedShort();
  74         package_index_table = new int[number_of_packages];
  75         for (int i = 0; i < number_of_packages; i++) {
  76             package_index_table[i] = input.readUnsignedShort();
  77         }
  78     }
  79 
  80 
  81     /**
  82      * Called by objects that are traversing the nodes of the tree implicitely
  83      * defined by the contents of a Java class. I.e., the hierarchy of methods,
  84      * fields, attributes, etc. spawns a tree of objects.
  85      *
  86      * @param v Visitor object
  87      */
  88     @Override
  89     public void accept( final Visitor v ) {
  90         v.visitModulePackages(this);
  91     }
  92 
  93 
  94     /**
  95      * Dump ModulePackages attribute to file stream in binary format.
  96      *
  97      * @param file Output file stream
  98      * @throws IOException
  99      */
 100     @Override
 101     public void dump( final DataOutputStream file ) throws IOException {
 102         super.dump(file);
 103         file.writeShort(package_index_table.length);
 104         for (final int index : package_index_table) {
 105             file.writeShort(index);
 106         }
 107     }
 108 
 109 
 110     /**
 111      * @return array of indices into constant pool of package names.
 112      */
 113     public int[] getPackageIndexTable() {
 114         return package_index_table;
 115     }
 116 
 117 
 118     /**
 119      * @return Length of package table.
 120      */
 121     public int getNumberOfPackages() {
 122         return package_index_table == null ? 0 : package_index_table.length;
 123     }
 124 
 125 
 126     /**
 127      * @return string array of package names
 128      */
 129     public String[] getPackageNames() {
 130         final String[] names = new String[package_index_table.length];
 131         for (int i = 0; i < package_index_table.length; i++) {
 132             names[i] = super.getConstantPool().getConstantString(package_index_table[i],
 133                     Const.CONSTANT_Package).replace('/', '.');
 134         }
 135         return names;
 136     }
 137 
 138 
 139     /**
 140      * @param package_index_table the list of package indexes
 141      * Also redefines number_of_packages according to table length.
 142      */
 143     public void setPackageIndexTable( final int[] package_index_table ) {
 144         this.package_index_table = package_index_table != null ? package_index_table : new int[0];
 145     }
 146 
 147 
 148     /**
 149      * @return String representation, i.e., a list of packages.
 150      */
 151     @Override
 152     public String toString() {
 153         final StringBuilder buf = new StringBuilder();
 154         buf.append("ModulePackages(");
 155         buf.append(package_index_table.length);
 156         buf.append("):\n");
 157         for (final int index : package_index_table) {
 158             final String package_name = super.getConstantPool().getConstantString(index, Const.CONSTANT_Package);
 159             buf.append("  ").append(Utility.compactClassName(package_name, false)).append("\n");
 160         }
 161         return buf.substring(0, buf.length()-1); // remove the last newline
 162     }
 163 
 164 
 165     /**
 166      * @return deep copy of this attribute
 167      */
 168     @Override
 169     public Attribute copy( final ConstantPool _constant_pool ) {
 170         final ModulePackages c = (ModulePackages) clone();
 171         if (package_index_table != null) {
 172             c.package_index_table = new int[package_index_table.length];
 173             System.arraycopy(package_index_table, 0, c.package_index_table, 0,
 174                     package_index_table.length);
 175         }
 176         c.setConstantPool(_constant_pool);
 177         return c;
 178     }
 179 }