/***
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.springframework.asm;
/**
* @author Remi Forax
*/
final class
ModuleWriter extends
ModuleVisitor {
/**
* The class writer to which this Module attribute must be added.
*/
private final
ClassWriter cw;
/**
* size in byte of the Module attribute.
*/
int
size;
/**
* Number of attributes associated with the current module
* (Version, ConcealPackages, etc)
*/
int
attributeCount;
/**
* Size in bytes of the attributes associated with the current module
*/
int
attributesSize;
/**
* module name index in the constant pool
*/
private final int
name;
/**
* module access flags
*/
private final int
access;
/**
* module version index in the constant pool or 0
*/
private final int
version;
/**
* module main class index in the constant pool or 0
*/
private int
mainClass;
/**
* number of packages
*/
private int
packageCount;
/**
* The packages in bytecode form. This byte vector only contains
* the items themselves, the number of items is store in packageCount
*/
private
ByteVector packages;
/**
* number of requires items
*/
private int
requireCount;
/**
* The requires items in bytecode form. This byte vector only contains
* the items themselves, the number of items is store in requireCount
*/
private
ByteVector requires;
/**
* number of exports items
*/
private int
exportCount;
/**
* The exports items in bytecode form. This byte vector only contains
* the items themselves, the number of items is store in exportCount
*/
private
ByteVector exports;
/**
* number of opens items
*/
private int
openCount;
/**
* The opens items in bytecode form. This byte vector only contains
* the items themselves, the number of items is store in openCount
*/
private
ByteVector opens;
/**
* number of uses items
*/
private int
useCount;
/**
* The uses items in bytecode form. This byte vector only contains
* the items themselves, the number of items is store in useCount
*/
private
ByteVector uses;
/**
* number of provides items
*/
private int
provideCount;
/**
* The uses provides in bytecode form. This byte vector only contains
* the items themselves, the number of items is store in provideCount
*/
private
ByteVector provides;
ModuleWriter(final
ClassWriter cw, final int
name,
final int
access, final int
version) {
super(
Opcodes.
ASM6);
this.
cw =
cw;
this.
size = 16; // name + access + version + 5 counts
this.
name =
name;
this.
access =
access;
this.
version =
version;
}
@
Override
public void
visitMainClass(
String mainClass) {
if (this.
mainClass == 0) { // protect against several calls to visitMainClass
cw.
newUTF8("ModuleMainClass");
attributeCount++;
attributesSize += 8;
}
this.
mainClass =
cw.
newClass(
mainClass);
}
@
Override
public void
visitPackage(
String packaze) {
if (
packages == null) {
// protect against several calls to visitPackage
cw.
newUTF8("ModulePackages");
packages = new
ByteVector();
attributeCount++;
attributesSize += 8;
}
packages.
putShort(
cw.
newPackage(
packaze));
packageCount++;
attributesSize += 2;
}
@
Override
public void
visitRequire(
String module, int
access,
String version) {
if (
requires == null) {
requires = new
ByteVector();
}
requires.
putShort(
cw.
newModule(
module))
.
putShort(
access)
.
putShort(
version == null? 0:
cw.
newUTF8(
version));
requireCount++;
size += 6;
}
@
Override
public void
visitExport(
String packaze, int
access,
String...
modules) {
if (
exports == null) {
exports = new
ByteVector();
}
exports.
putShort(
cw.
newPackage(
packaze)).
putShort(
access);
if (
modules == null) {
exports.
putShort(0);
size += 6;
} else {
exports.
putShort(
modules.length);
for(
String module:
modules) {
exports.
putShort(
cw.
newModule(
module));
}
size += 6 + 2 *
modules.length;
}
exportCount++;
}
@
Override
public void
visitOpen(
String packaze, int
access,
String...
modules) {
if (
opens == null) {
opens = new
ByteVector();
}
opens.
putShort(
cw.
newPackage(
packaze)).
putShort(
access);
if (
modules == null) {
opens.
putShort(0);
size += 6;
} else {
opens.
putShort(
modules.length);
for(
String module:
modules) {
opens.
putShort(
cw.
newModule(
module));
}
size += 6 + 2 *
modules.length;
}
openCount++;
}
@
Override
public void
visitUse(
String service) {
if (
uses == null) {
uses = new
ByteVector();
}
uses.
putShort(
cw.
newClass(
service));
useCount++;
size += 2;
}
@
Override
public void
visitProvide(
String service,
String...
providers) {
if (
provides == null) {
provides = new
ByteVector();
}
provides.
putShort(
cw.
newClass(
service));
provides.
putShort(
providers.length);
for(
String provider:
providers) {
provides.
putShort(
cw.
newClass(
provider));
}
provideCount++;
size += 4 + 2 *
providers.length;
}
@
Override
public void
visitEnd() {
// empty
}
void
putAttributes(
ByteVector out) {
if (
mainClass != 0) {
out.
putShort(
cw.
newUTF8("ModuleMainClass")).
putInt(2).
putShort(
mainClass);
}
if (
packages != null) {
out.
putShort(
cw.
newUTF8("ModulePackages"))
.
putInt(2 + 2 *
packageCount)
.
putShort(
packageCount)
.
putByteArray(
packages.
data, 0,
packages.
length);
}
}
void
put(
ByteVector out) {
out.
putInt(
size);
out.
putShort(
name).
putShort(
access).
putShort(
version);
out.
putShort(
requireCount);
if (
requires != null) {
out.
putByteArray(
requires.
data, 0,
requires.
length);
}
out.
putShort(
exportCount);
if (
exports != null) {
out.
putByteArray(
exports.
data, 0,
exports.
length);
}
out.
putShort(
openCount);
if (
opens != null) {
out.
putByteArray(
opens.
data, 0,
opens.
length);
}
out.
putShort(
useCount);
if (
uses != null) {
out.
putByteArray(
uses.
data, 0,
uses.
length);
}
out.
putShort(
provideCount);
if (
provides != null) {
out.
putByteArray(
provides.
data, 0,
provides.
length);
}
}
}