1 /*
   2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   3  *
   4  * This code is free software; you can redistribute it and/or modify it
   5  * under the terms of the GNU General Public License version 2 only, as
   6  * published by the Free Software Foundation.  Oracle designates this
   7  * particular file as subject to the "Classpath" exception as provided
   8  * by Oracle in the LICENSE file that accompanied this code.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  */
  24 
  25 /*
  26  * This file is available under and governed by the GNU General Public
  27  * License version 2 only, as published by the Free Software Foundation.
  28  * However, the following notice accompanied the original version of this
  29  * file:
  30  *
  31  * ASM: a very small and fast Java bytecode manipulation framework
  32  * Copyright (c) 2000-2011 INRIA, France Telecom
  33  * All rights reserved.
  34  *
  35  * Redistribution and use in source and binary forms, with or without
  36  * modification, are permitted provided that the following conditions
  37  * are met:
  38  * 1. Redistributions of source code must retain the above copyright
  39  *    notice, this list of conditions and the following disclaimer.
  40  * 2. Redistributions in binary form must reproduce the above copyright
  41  *    notice, this list of conditions and the following disclaimer in the
  42  *    documentation and/or other materials provided with the distribution.
  43  * 3. Neither the name of the copyright holders nor the names of its
  44  *    contributors may be used to endorse or promote products derived from
  45  *    this software without specific prior written permission.
  46  *
  47  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  48  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  49  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  50  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  51  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  52  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  53  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  54  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  55  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  56  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  57  * THE POSSIBILITY OF SUCH DAMAGE.
  58  */
  59 
  60 package jdk.internal.org.objectweb.asm;
  61 
  62 /**
  63  * @author Remi Forax
  64  */
  65 final class ModuleWriter extends ModuleVisitor {
  66     /**
  67      * The class writer to which this Module attribute must be added.
  68      */
  69     private final ClassWriter cw;
  70 
  71     /**
  72      * size in byte of the Module attribute.
  73      */
  74     int size;
  75 
  76     /**
  77      * Number of attributes associated with the current module
  78      * (Version, ConcealPackages, etc)
  79      */
  80     int attributeCount;
  81 
  82     /**
  83      * Size in bytes of the attributes associated with the current module
  84      */
  85     int attributesSize;
  86 
  87     /**
  88      * module name index in the constant pool
  89      */
  90     private final int name;
  91 
  92     /**
  93      * module access flags
  94      */
  95     private final int access;
  96 
  97     /**
  98      * module version index in the constant pool or 0
  99      */
 100     private final int version;
 101 
 102     /**
 103      * module main class index in the constant pool or 0
 104      */
 105     private int mainClass;
 106 
 107     /**
 108      * number of packages
 109      */
 110     private int packageCount;
 111 
 112     /**
 113      * The packages in bytecode form. This byte vector only contains
 114      * the items themselves, the number of items is store in packageCount
 115      */
 116     private ByteVector packages;
 117 
 118     /**
 119      * number of requires items
 120      */
 121     private int requireCount;
 122 
 123     /**
 124      * The requires items in bytecode form. This byte vector only contains
 125      * the items themselves, the number of items is store in requireCount
 126      */
 127     private ByteVector requires;
 128 
 129     /**
 130      * number of exports items
 131      */
 132     private int exportCount;
 133 
 134     /**
 135      * The exports items in bytecode form. This byte vector only contains
 136      * the items themselves, the number of items is store in exportCount
 137      */
 138     private ByteVector exports;
 139 
 140     /**
 141      * number of opens items
 142      */
 143     private int openCount;
 144 
 145     /**
 146      * The opens items in bytecode form. This byte vector only contains
 147      * the items themselves, the number of items is store in openCount
 148      */
 149     private ByteVector opens;
 150 
 151     /**
 152      * number of uses items
 153      */
 154     private int useCount;
 155 
 156     /**
 157      * The uses items in bytecode form. This byte vector only contains
 158      * the items themselves, the number of items is store in useCount
 159      */
 160     private ByteVector uses;
 161 
 162     /**
 163      * number of provides items
 164      */
 165     private int provideCount;
 166 
 167     /**
 168      * The uses provides in bytecode form. This byte vector only contains
 169      * the items themselves, the number of items is store in provideCount
 170      */
 171     private ByteVector provides;
 172 
 173     ModuleWriter(final ClassWriter cw, final int name,
 174             final int access, final int version) {
 175         super(Opcodes.ASM6);
 176         this.cw = cw;
 177         this.size = 16;  // name + access + version + 5 counts
 178         this.name = name;
 179         this.access = access;
 180         this.version = version;
 181     }
 182 
 183     @Override
 184     public void visitMainClass(String mainClass) {
 185         if (this.mainClass == 0) { // protect against several calls to visitMainClass
 186             cw.newUTF8("ModuleMainClass");
 187             attributeCount++;
 188             attributesSize += 8;
 189         }
 190         this.mainClass = cw.newClass(mainClass);
 191     }
 192 
 193     @Override
 194     public void visitPackage(String packaze) {
 195         if (packages == null) {
 196             // protect against several calls to visitPackage
 197             cw.newUTF8("ModulePackages");
 198             packages = new ByteVector();
 199             attributeCount++;
 200             attributesSize += 8;
 201         }
 202         packages.putShort(cw.newPackage(packaze));
 203         packageCount++;
 204         attributesSize += 2;
 205     }
 206 
 207     @Override
 208     public void visitRequire(String module, int access, String version) {
 209         if (requires == null) {
 210             requires = new ByteVector();
 211         }
 212         requires.putShort(cw.newModule(module))
 213                 .putShort(access)
 214                 .putShort(version == null? 0: cw.newUTF8(version));
 215         requireCount++;
 216         size += 6;
 217     }
 218 
 219     @Override
 220     public void visitExport(String packaze, int access, String... modules) {
 221         if (exports == null) {
 222             exports = new ByteVector();
 223         }
 224         exports.putShort(cw.newPackage(packaze)).putShort(access);
 225         if (modules == null) {
 226             exports.putShort(0);
 227             size += 6;
 228         } else {
 229             exports.putShort(modules.length);
 230             for(String module: modules) {
 231                 exports.putShort(cw.newModule(module));
 232             }
 233             size += 6 + 2 * modules.length;
 234         }
 235         exportCount++;
 236     }
 237 
 238     @Override
 239     public void visitOpen(String packaze, int access, String... modules) {
 240         if (opens == null) {
 241             opens = new ByteVector();
 242         }
 243         opens.putShort(cw.newPackage(packaze)).putShort(access);
 244         if (modules == null) {
 245             opens.putShort(0);
 246             size += 6;
 247         } else {
 248             opens.putShort(modules.length);
 249             for(String module: modules) {
 250                 opens.putShort(cw.newModule(module));
 251             }
 252             size += 6 + 2 * modules.length;
 253         }
 254         openCount++;
 255     }
 256 
 257     @Override
 258     public void visitUse(String service) {
 259         if (uses == null) {
 260             uses = new ByteVector();
 261         }
 262         uses.putShort(cw.newClass(service));
 263         useCount++;
 264         size += 2;
 265     }
 266 
 267     @Override
 268     public void visitProvide(String service, String... providers) {
 269         if (provides == null) {
 270             provides = new ByteVector();
 271         }
 272         provides.putShort(cw.newClass(service));
 273         provides.putShort(providers.length);
 274         for(String provider: providers) {
 275             provides.putShort(cw.newClass(provider));
 276         }
 277         provideCount++;
 278         size += 4 + 2 * providers.length;
 279     }
 280 
 281     @Override
 282     public void visitEnd() {
 283         // empty
 284     }
 285 
 286     void putAttributes(ByteVector out) {
 287         if (mainClass != 0) {
 288             out.putShort(cw.newUTF8("ModuleMainClass")).putInt(2).putShort(mainClass);
 289         }
 290         if (packages != null) {
 291             out.putShort(cw.newUTF8("ModulePackages"))
 292                .putInt(2 + 2 * packageCount)
 293                .putShort(packageCount)
 294                .putByteArray(packages.data, 0, packages.length);
 295         }
 296     }
 297 
 298     void put(ByteVector out) {
 299         out.putInt(size);
 300         out.putShort(name).putShort(access).putShort(version);
 301         out.putShort(requireCount);
 302         if (requires != null) {
 303             out.putByteArray(requires.data, 0, requires.length);
 304         }
 305         out.putShort(exportCount);
 306         if (exports != null) {
 307             out.putByteArray(exports.data, 0, exports.length);
 308         }
 309         out.putShort(openCount);
 310         if (opens != null) {
 311             out.putByteArray(opens.data, 0, opens.length);
 312         }
 313         out.putShort(useCount);
 314         if (uses != null) {
 315             out.putByteArray(uses.data, 0, uses.length);
 316         }
 317         out.putShort(provideCount);
 318         if (provides != null) {
 319             out.putByteArray(provides.data, 0, provides.length);
 320         }
 321     }
 322 }