All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jboss.jandex.IndexReaderV1 Maven / Gradle / Ivy

There is a newer version: 1.3.3
Show newest version
/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2013 Red Hat, Inc., and individual contributors
 * as indicated by the @author tags.
 *
 * 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.jboss.jandex;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Reads a Jandex index file and returns the saved index. See {@link org.jboss.jandex.Indexer}
 * for a thorough description of how the Index data is produced.
 *
 * 

* An IndexReader loads the stream passed to it's constructor and applies the * appropriate buffering. The Jandex index format is designed for efficient * reading and low final memory storage. * *

* Thread-Safety *

* IndexReader is not thread-safe and can not be shared between concurrent * threads. The resulting index, however, is. * * @author Jason T. Greene */ final class IndexReaderV1 extends IndexReaderImpl { static final int MIN_VERSION = 2; static final int MAX_VERSION = 3; private static final byte FIELD_TAG = 1; private static final byte METHOD_TAG = 2; private static final byte METHOD_PARAMATER_TAG = 3; private static final byte CLASS_TAG = 4; private static final int AVALUE_BYTE = 1; private static final int AVALUE_SHORT = 2; private static final int AVALUE_INT = 3; private static final int AVALUE_CHAR = 4; private static final int AVALUE_FLOAT = 5; private static final int AVALUE_DOUBLE = 6; private static final int AVALUE_LONG = 7; private static final int AVALUE_BOOLEAN = 8; private static final int AVALUE_STRING = 9; private static final int AVALUE_CLASS = 10; private static final int AVALUE_ENUM = 11; private static final int AVALUE_ARRAY = 12; private static final int AVALUE_NESTED = 13; private PackedDataInputStream input; private DotName[] classTable; private String[] stringTable; private HashMap> masterAnnotations; /** * Constructs a new IndedReader using the passed stream. The stream is not * read from until the read method is called. * * @param input a stream which points to a jandex index file */ IndexReaderV1(PackedDataInputStream input) { this.input = input; } /** * Read the index at the associated stream of this reader. This method can be called multiple * times if the stream contains multiple index files. * * @return the Index contained in the stream * @throws java.io.IOException if an I/O error occurs * @throws IllegalArgumentException if the stream does not point to Jandex index data * @throws org.jboss.jandex.UnsupportedVersion if the index data is tagged with a version not known to this reader */ Index read(int version) throws IOException { try { PackedDataInputStream stream = this.input; masterAnnotations = new HashMap>(); readClassTable(stream); readStringTable(stream); return readClasses(stream, version); } finally { classTable = null; stringTable = null; masterAnnotations = null; } } private Index readClasses(PackedDataInputStream stream, int version) throws IOException { int entries = stream.readPackedU32(); HashMap> subclasses = new HashMap>(); HashMap> implementors = new HashMap>(); HashMap classes = new HashMap(); masterAnnotations = new HashMap>(); for (int i = 0; i < entries; i++) { DotName name = classTable[stream.readPackedU32()]; DotName superName = classTable[stream.readPackedU32()]; short flags = stream.readShort(); // No copyParameters supported in version 3+ boolean hasNoArgsConstructor = version >= 3 && stream.readBoolean(); int numIntfs = stream.readPackedU32(); List interfaces = new ArrayList(numIntfs); for (int j = 0; j < numIntfs; j++) { interfaces.add(new ClassType(classTable[stream.readPackedU32()])); } Type[] interfaceTypes = interfaces.toArray(new Type[interfaces.size()]); Map> annotations = new HashMap>(); Type superClassType = superName == null ? null : new ClassType(superName); ClassInfo clazz = new ClassInfo(name, superClassType, flags, interfaceTypes, annotations, hasNoArgsConstructor); classes.put(name, clazz); addClassToMap(subclasses, superName, clazz); for (Type interfaceName : interfaces) { addClassToMap(implementors, interfaceName.name(), clazz); } readAnnotations(stream, annotations, clazz); } return Index.create(masterAnnotations, subclasses, implementors, classes); } private void readAnnotations(PackedDataInputStream stream, Map> annotations, ClassInfo clazz) throws IOException { int numAnnotations = stream.readPackedU32(); for (int j = 0; j < numAnnotations; j++) { DotName annotationName = classTable[stream.readPackedU32()]; int numTargets = stream.readPackedU32(); for (int k = 0; k < numTargets; k++) { int tag = stream.readPackedU32(); AnnotationTarget target; switch (tag) { case FIELD_TAG: { String name = stringTable[stream.readPackedU32()]; Type type = readType(stream); short flags = stream.readShort(); target = new FieldInfo(clazz, Utils.toUTF8(name), type, flags); break; } case METHOD_TAG: { target = readMethod(clazz, stream); break; } case METHOD_PARAMATER_TAG: { MethodInfo method = readMethod(clazz, stream); target = new MethodParameterInfo(method, (short)stream.readPackedU32()); break; } case CLASS_TAG: { target = clazz; break; } default: throw new UnsupportedOperationException(); } AnnotationValue[] values = readAnnotationValues(stream); AnnotationInstance instance = new AnnotationInstance(annotationName, target, values); recordAnnotation(masterAnnotations, annotationName, instance); recordAnnotation(annotations, annotationName, instance); } } } private AnnotationValue[] readAnnotationValues(PackedDataInputStream stream) throws IOException { int numValues = stream.readPackedU32(); AnnotationValue[] values = new AnnotationValue[numValues]; for (int i = 0; i < numValues; i++) { String name = stringTable[stream.readPackedU32()]; int tag = stream.readByte(); AnnotationValue value; switch (tag) { case AVALUE_BYTE: value = new AnnotationValue.ByteValue(name, stream.readByte()); break; case AVALUE_SHORT: value = new AnnotationValue.ShortValue(name, (short) stream.readPackedU32()); break; case AVALUE_INT: value = new AnnotationValue.IntegerValue(name, stream.readPackedU32()); break; case AVALUE_CHAR: value = new AnnotationValue.CharacterValue(name, (char) stream.readPackedU32()); break; case AVALUE_FLOAT: value = new AnnotationValue.FloatValue(name, stream.readFloat()); break; case AVALUE_DOUBLE: value = new AnnotationValue.DoubleValue(name, stream.readDouble()); break; case AVALUE_LONG: value = new AnnotationValue.LongValue(name, stream.readLong()); break; case AVALUE_BOOLEAN: value = new AnnotationValue.BooleanValue(name, stream.readBoolean()); break; case AVALUE_STRING: value = new AnnotationValue.StringValue(name, stringTable[stream.readPackedU32()]); break; case AVALUE_CLASS: value = new AnnotationValue.ClassValue(name, readType(stream)); break; case AVALUE_ENUM: value = new AnnotationValue.EnumValue(name, classTable[stream.readPackedU32()], stringTable[stream.readPackedU32()]); break; case AVALUE_ARRAY: value = new AnnotationValue.ArrayValue(name, readAnnotationValues(stream)); break; case AVALUE_NESTED: { DotName nestedName = classTable[stream.readPackedU32()]; AnnotationInstance nestedInstance = new AnnotationInstance(nestedName, null, readAnnotationValues(stream)); value = new AnnotationValue.NestedAnnotation(name, nestedInstance); break; } default: throw new IllegalStateException("Invalid annotation value tag:" + tag); } values[i] = value; } return values; } private MethodInfo readMethod(ClassInfo clazz, PackedDataInputStream stream) throws IOException { String name = stringTable[stream.readPackedU32()]; int numArgs = stream.readPackedU32(); List args = new ArrayList(numArgs); for (int i = 0; i < numArgs; i ++) { args.add(readType(stream)); } Type[] parameters = args.toArray(new Type[args.size()]); Type returnType = readType(stream); short flags = stream.readShort(); byte[] bytes = Utils.toUTF8(name); return new MethodInfo(clazz, bytes, parameters, returnType, flags); } private void recordAnnotation(Map> annotations, DotName annotation, AnnotationInstance instance) { List list = annotations.get(annotation); if (list == null) { list = new ArrayList(); annotations.put(annotation, list); } list.add(instance); } private void addClassToMap(HashMap> map, DotName name, ClassInfo currentClass) { List list = map.get(name); if (list == null) { list = new ArrayList(); map.put(name, list); } list.add(currentClass); } private Type readType(PackedDataInputStream stream) throws IOException { Type.Kind kind = Type.Kind.fromOrdinal(stream.readByte()); DotName name = classTable[stream.readPackedU32()]; return Type.create(name, kind); } private void readStringTable(PackedDataInputStream stream) throws IOException { int entries = stream.readPackedU32(); stringTable = new String[entries]; for (int i = 0; i < entries; i++) { stringTable[i] = stream.readUTF(); } } private void readClassTable(PackedDataInputStream stream) throws IOException { int entries = stream.readPackedU32(); int lastDepth = -1; DotName curr = null; // Null is the implicit first entry classTable = new DotName[++entries]; for (int i = 1; i < entries; i++) { int depth = stream.readPackedU32(); String local = stream.readUTF(); if (depth <= lastDepth) { while (lastDepth-- >= depth) curr = curr.prefix(); } classTable[i] = curr = new DotName(curr, local, true, false); lastDepth = depth; } } int toDataVersion(int version) { // From 1 to 3, every version changed the available data return version; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy