| /* |
| * Copyright 2000-2014 JetBrains s.r.o. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.jetbrains.java.decompiler.struct; |
| |
| import org.jetbrains.java.decompiler.code.CodeConstants; |
| import org.jetbrains.java.decompiler.struct.consts.ConstantPool; |
| import org.jetbrains.java.decompiler.struct.consts.PrimitiveConstant; |
| import org.jetbrains.java.decompiler.struct.lazy.LazyLoader; |
| import org.jetbrains.java.decompiler.util.DataInputFullStream; |
| import org.jetbrains.java.decompiler.util.InterpreterUtil; |
| import org.jetbrains.java.decompiler.util.VBStyleCollection; |
| |
| import java.io.IOException; |
| |
| /* |
| class_file { |
| u4 magic; |
| u2 minor_version; |
| u2 major_version; |
| u2 constant_pool_count; |
| cp_info constant_pool[constant_pool_count-1]; |
| u2 access_flags; |
| u2 this_class; |
| u2 super_class; |
| u2 interfaces_count; |
| u2 interfaces[interfaces_count]; |
| u2 fields_count; |
| field_info fields[fields_count]; |
| u2 methods_count; |
| method_info methods[methods_count]; |
| u2 attributes_count; |
| attribute_info attributes[attributes_count]; |
| } |
| */ |
| public class StructClass extends StructMember { |
| |
| public final String qualifiedName; |
| public final PrimitiveConstant superClass; |
| |
| private final boolean own; |
| private final LazyLoader loader; |
| private final int minorVersion; |
| private final int majorVersion; |
| private final int[] interfaces; |
| private final String[] interfaceNames; |
| private final VBStyleCollection<StructField, String> fields; |
| private final VBStyleCollection<StructMethod, String> methods; |
| |
| private ConstantPool pool; |
| |
| public StructClass(byte[] bytes, boolean own, LazyLoader loader) throws IOException { |
| this(new DataInputFullStream(bytes), own, loader); |
| } |
| |
| public StructClass(DataInputFullStream in, boolean own, LazyLoader loader) throws IOException { |
| this.own = own; |
| this.loader = loader; |
| |
| in.discard(4); |
| |
| minorVersion = in.readUnsignedShort(); |
| majorVersion = in.readUnsignedShort(); |
| |
| pool = new ConstantPool(in); |
| |
| accessFlags = in.readUnsignedShort(); |
| int thisClassIdx = in.readUnsignedShort(); |
| int superClassIdx = in.readUnsignedShort(); |
| qualifiedName = pool.getPrimitiveConstant(thisClassIdx).getString(); |
| superClass = pool.getPrimitiveConstant(superClassIdx); |
| |
| // interfaces |
| int length = in.readUnsignedShort(); |
| interfaces = new int[length]; |
| interfaceNames = new String[length]; |
| for (int i = 0; i < length; i++) { |
| interfaces[i] = in.readUnsignedShort(); |
| interfaceNames[i] = pool.getPrimitiveConstant(interfaces[i]).getString(); |
| } |
| |
| // fields |
| length = in.readUnsignedShort(); |
| fields = new VBStyleCollection<StructField, String>(); |
| for (int i = 0; i < length; i++) { |
| StructField field = new StructField(in, this); |
| fields.addWithKey(field, InterpreterUtil.makeUniqueKey(field.getName(), field.getDescriptor())); |
| } |
| |
| // methods |
| length = in.readUnsignedShort(); |
| methods = new VBStyleCollection<StructMethod, String>(); |
| for (int i = 0; i < length; i++) { |
| StructMethod method = new StructMethod(in, this); |
| methods.addWithKey(method, InterpreterUtil.makeUniqueKey(method.getName(), method.getDescriptor())); |
| } |
| |
| // attributes |
| attributes = readAttributes(in, pool); |
| |
| releaseResources(); |
| } |
| |
| public boolean hasField(String name, String descriptor) { |
| return getField(name, descriptor) != null; |
| } |
| |
| public StructField getField(String name, String descriptor) { |
| return fields.getWithKey(InterpreterUtil.makeUniqueKey(name, descriptor)); |
| } |
| |
| public StructMethod getMethod(String key) { |
| return methods.getWithKey(key); |
| } |
| |
| public StructMethod getMethod(String name, String descriptor) { |
| return methods.getWithKey(InterpreterUtil.makeUniqueKey(name, descriptor)); |
| } |
| |
| public String getInterface(int i) { |
| return interfaceNames[i]; |
| } |
| |
| public void releaseResources() { |
| if (loader != null) { |
| pool = null; |
| } |
| } |
| |
| public ConstantPool getPool() { |
| if (pool == null && loader != null) { |
| pool = loader.loadPool(qualifiedName); |
| } |
| return pool; |
| } |
| |
| public int[] getInterfaces() { |
| return interfaces; |
| } |
| |
| public String[] getInterfaceNames() { |
| return interfaceNames; |
| } |
| |
| public VBStyleCollection<StructMethod, String> getMethods() { |
| return methods; |
| } |
| |
| public VBStyleCollection<StructField, String> getFields() { |
| return fields; |
| } |
| |
| public boolean isOwn() { |
| return own; |
| } |
| |
| public LazyLoader getLoader() { |
| return loader; |
| } |
| |
| public boolean isVersionGE_1_5() { |
| return (majorVersion > 48 || (majorVersion == 48 && minorVersion > 0)); // FIXME: check second condition |
| } |
| |
| public boolean isVersionGE_1_7() { |
| return (majorVersion >= 51); |
| } |
| |
| public int getBytecodeVersion() { |
| switch (majorVersion) { |
| case 52: |
| return CodeConstants.BYTECODE_JAVA_8; |
| case 51: |
| return CodeConstants.BYTECODE_JAVA_7; |
| case 50: |
| return CodeConstants.BYTECODE_JAVA_6; |
| case 49: |
| return CodeConstants.BYTECODE_JAVA_5; |
| } |
| |
| return CodeConstants.BYTECODE_JAVA_LE_4; |
| } |
| } |