1/*
2 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package com.sun.tools.classfile;
27
28import java.io.IOException;
29
30import com.sun.tools.classfile.ConstantPool.CONSTANT_Module_info;
31
32/**
33 * See Jigsaw.
34 *
35 *  <p><b>This is NOT part of any supported API.
36 *  If you write code that depends on this, you do so at your own risk.
37 *  This code and its internal interfaces are subject to change or
38 *  deletion without notice.</b>
39 */
40public class Module_attribute extends Attribute {
41    public static final int ACC_TRANSITIVE      =   0x20;
42    public static final int ACC_STATIC_PHASE    =   0x40;
43    public static final int ACC_OPEN            =   0x20;
44    public static final int ACC_SYNTHETIC       = 0x1000;
45    public static final int ACC_MANDATED        = 0x8000;
46
47    Module_attribute(ClassReader cr, int name_index, int length) throws IOException {
48        super(name_index, length);
49
50        module_name = cr.readUnsignedShort();
51        module_flags = cr.readUnsignedShort();
52
53        module_version_index = cr.readUnsignedShort();
54
55        requires_count = cr.readUnsignedShort();
56        requires = new RequiresEntry[requires_count];
57        for (int i = 0; i < requires_count; i++)
58            requires[i] = new RequiresEntry(cr);
59
60        exports_count = cr.readUnsignedShort();
61        exports = new ExportsEntry[exports_count];
62        for (int i = 0; i < exports_count; i++)
63            exports[i] = new ExportsEntry(cr);
64
65        opens_count = cr.readUnsignedShort();
66        opens = new OpensEntry[opens_count];
67        for (int i = 0; i < opens_count; i++)
68            opens[i] = new OpensEntry(cr);
69
70        uses_count = cr.readUnsignedShort();
71        uses_index = new int[uses_count];
72        for (int i = 0; i < uses_count; i++)
73            uses_index[i] = cr.readUnsignedShort();
74
75        provides_count = cr.readUnsignedShort();
76        provides = new ProvidesEntry[provides_count];
77        for (int i = 0; i < provides_count; i++)
78            provides[i] = new ProvidesEntry(cr);
79    }
80
81    public Module_attribute(int name_index,
82            int module_name,
83            int module_flags,
84            int module_version_index,
85            RequiresEntry[] requires,
86            ExportsEntry[] exports,
87            OpensEntry[] opens,
88            int[] uses,
89            ProvidesEntry[] provides) {
90        super(name_index, 2);
91        this.module_name = module_name;
92        this.module_flags = module_flags;
93        this.module_version_index = module_version_index;
94        requires_count = requires.length;
95        this.requires = requires;
96        exports_count = exports.length;
97        this.exports = exports;
98        opens_count = opens.length;
99        this.opens = opens;
100        uses_count = uses.length;
101        this.uses_index = uses;
102        provides_count = provides.length;
103        this.provides = provides;
104    }
105
106    public String getUses(int index, ConstantPool constant_pool) throws ConstantPoolException {
107        int i = uses_index[index];
108        return constant_pool.getClassInfo(i).getName();
109    }
110
111    @Override
112    public <R, D> R accept(Visitor<R, D> visitor, D data) {
113        return visitor.visitModule(this, data);
114    }
115
116    public final int module_name;
117    public final int module_flags;
118    public final int module_version_index;
119    public final int requires_count;
120    public final RequiresEntry[] requires;
121    public final int exports_count;
122    public final ExportsEntry[] exports;
123    public final int opens_count;
124    public final OpensEntry[] opens;
125    public final int uses_count;
126    public final int[] uses_index;
127    public final int provides_count;
128    public final ProvidesEntry[] provides;
129
130    public static class RequiresEntry {
131        RequiresEntry(ClassReader cr) throws IOException {
132            requires_index = cr.readUnsignedShort();
133            requires_flags = cr.readUnsignedShort();
134            requires_version_index = cr.readUnsignedShort();
135        }
136
137        public RequiresEntry(int index, int flags, int version_index) {
138            this.requires_index = index;
139            this.requires_flags = flags;
140            this.requires_version_index = version_index;
141        }
142
143        public String getRequires(ConstantPool constant_pool) throws ConstantPoolException {
144            CONSTANT_Module_info info = constant_pool.getModuleInfo(requires_index);
145            return info.getName();
146        }
147
148        public static final int length = 4;
149
150        public final int requires_index;
151        public final int requires_flags;
152        public final int requires_version_index;
153    }
154
155    public static class ExportsEntry {
156        ExportsEntry(ClassReader cr) throws IOException {
157            exports_index = cr.readUnsignedShort();
158            exports_flags = cr.readUnsignedShort();
159            exports_to_count = cr.readUnsignedShort();
160            exports_to_index = new int[exports_to_count];
161            for (int i = 0; i < exports_to_count; i++)
162                exports_to_index[i] = cr.readUnsignedShort();
163        }
164
165        public ExportsEntry(int index, int flags, int[] to) {
166            this.exports_index = index;
167            this.exports_flags = flags;
168            this.exports_to_count = to.length;
169            this.exports_to_index = to;
170        }
171
172        public int length() {
173            return 4 + 2 * exports_to_index.length;
174        }
175
176        public final int exports_index;
177        public final int exports_flags;
178        public final int exports_to_count;
179        public final int[] exports_to_index;
180    }
181
182    public static class OpensEntry {
183        OpensEntry(ClassReader cr) throws IOException {
184            opens_index = cr.readUnsignedShort();
185            opens_flags = cr.readUnsignedShort();
186            opens_to_count = cr.readUnsignedShort();
187            opens_to_index = new int[opens_to_count];
188            for (int i = 0; i < opens_to_count; i++)
189                opens_to_index[i] = cr.readUnsignedShort();
190        }
191
192        public OpensEntry(int index, int flags, int[] to) {
193            this.opens_index = index;
194            this.opens_flags = flags;
195            this.opens_to_count = to.length;
196            this.opens_to_index = to;
197        }
198
199        public int length() {
200            return 4 + 2 * opens_to_index.length;
201        }
202
203        public final int opens_index;
204        public final int opens_flags;
205        public final int opens_to_count;
206        public final int[] opens_to_index;
207    }
208
209    public static class ProvidesEntry {
210        ProvidesEntry(ClassReader cr) throws IOException {
211            provides_index = cr.readUnsignedShort();
212            with_count = cr.readUnsignedShort();
213            with_index = new int[with_count];
214            for (int i = 0; i < with_count; i++)
215                with_index[i] = cr.readUnsignedShort();
216        }
217
218        public ProvidesEntry(int provides, int[] with) {
219            this.provides_index = provides;
220            this.with_count = with.length;
221            this.with_index = with;
222        }
223
224        public static final int length = 4;
225
226        public final int provides_index;
227        public final int with_count;
228        public final int[] with_index;
229    }
230}
231