Home | History | Annotate | Download | only in file
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.dx.dex.file;
     18 
     19 import com.android.dex.DexException;
     20 import com.android.dex.DexFormat;
     21 import com.android.dex.DexIndexOverflowException;
     22 import com.android.dx.command.dexer.Main;
     23 import com.android.dx.rop.cst.Constant;
     24 import com.android.dx.rop.cst.CstType;
     25 import com.android.dx.rop.type.Type;
     26 import com.android.dx.util.AnnotatedOutput;
     27 import com.android.dx.util.Hex;
     28 
     29 import java.util.Collection;
     30 import java.util.TreeMap;
     31 
     32 /**
     33  * Type identifiers list section of a {@code .dex} file.
     34  */
     35 public final class TypeIdsSection extends UniformItemSection {
     36     /**
     37      * {@code non-null;} map from types to {@link TypeIdItem} instances
     38      */
     39     private final TreeMap<Type, TypeIdItem> typeIds;
     40 
     41     /**
     42      * Constructs an instance. The file offset is initially unknown.
     43      *
     44      * @param file {@code non-null;} file that this instance is part of
     45      */
     46     public TypeIdsSection(DexFile file) {
     47         super("type_ids", file, 4);
     48 
     49         typeIds = new TreeMap<Type, TypeIdItem>();
     50     }
     51 
     52     /** {@inheritDoc} */
     53     @Override
     54     public Collection<? extends Item> items() {
     55         return typeIds.values();
     56     }
     57 
     58     /** {@inheritDoc} */
     59     @Override
     60     public IndexedItem get(Constant cst) {
     61         if (cst == null) {
     62             throw new NullPointerException("cst == null");
     63         }
     64 
     65         throwIfNotPrepared();
     66 
     67         Type type = ((CstType) cst).getClassType();
     68         IndexedItem result = typeIds.get(type);
     69 
     70         if (result == null) {
     71             throw new IllegalArgumentException("not found: " + cst);
     72         }
     73 
     74         return result;
     75     }
     76 
     77     /**
     78      * Writes the portion of the file header that refers to this instance.
     79      *
     80      * @param out {@code non-null;} where to write
     81      */
     82     public void writeHeaderPart(AnnotatedOutput out) {
     83         throwIfNotPrepared();
     84 
     85         int sz = typeIds.size();
     86         int offset = (sz == 0) ? 0 : getFileOffset();
     87 
     88         if (sz > DexFormat.MAX_TYPE_IDX + 1) {
     89             throw new DexIndexOverflowException("Too many type references: " + sz +
     90                     "; max is " + (DexFormat.MAX_TYPE_IDX + 1) + ".\n" +
     91                     Main.getTooManyIdsErrorMessage());
     92         }
     93 
     94         if (out.annotates()) {
     95             out.annotate(4, "type_ids_size:   " + Hex.u4(sz));
     96             out.annotate(4, "type_ids_off:    " + Hex.u4(offset));
     97         }
     98 
     99         out.writeInt(sz);
    100         out.writeInt(offset);
    101     }
    102 
    103     /**
    104      * Interns an element into this instance.
    105      *
    106      * @param type {@code non-null;} the type to intern
    107      * @return {@code non-null;} the interned reference
    108      */
    109     public synchronized TypeIdItem intern(Type type) {
    110         if (type == null) {
    111             throw new NullPointerException("type == null");
    112         }
    113 
    114         throwIfPrepared();
    115 
    116         TypeIdItem result = typeIds.get(type);
    117 
    118         if (result == null) {
    119             result = new TypeIdItem(new CstType(type));
    120             typeIds.put(type, result);
    121         }
    122 
    123         return result;
    124     }
    125 
    126     /**
    127      * Interns an element into this instance.
    128      *
    129      * @param type {@code non-null;} the type to intern
    130      * @return {@code non-null;} the interned reference
    131      */
    132     public synchronized TypeIdItem intern(CstType type) {
    133         if (type == null) {
    134             throw new NullPointerException("type == null");
    135         }
    136 
    137         throwIfPrepared();
    138 
    139         Type typePerSe = type.getClassType();
    140         TypeIdItem result = typeIds.get(typePerSe);
    141 
    142         if (result == null) {
    143             result = new TypeIdItem(type);
    144             typeIds.put(typePerSe, result);
    145         }
    146 
    147         return result;
    148     }
    149 
    150     /**
    151      * Gets the index of the given type, which must have
    152      * been added to this instance.
    153      *
    154      * @param type {@code non-null;} the type to look up
    155      * @return {@code >= 0;} the reference's index
    156      */
    157     public int indexOf(Type type) {
    158         if (type == null) {
    159             throw new NullPointerException("type == null");
    160         }
    161 
    162         throwIfNotPrepared();
    163 
    164         TypeIdItem item = typeIds.get(type);
    165 
    166         if (item == null) {
    167             throw new IllegalArgumentException("not found: " + type);
    168         }
    169 
    170         return item.getIndex();
    171     }
    172 
    173     /**
    174      * Gets the index of the given type, which must have
    175      * been added to this instance.
    176      *
    177      * @param type {@code non-null;} the type to look up
    178      * @return {@code >= 0;} the reference's index
    179      */
    180     public int indexOf(CstType type) {
    181         if (type == null) {
    182             throw new NullPointerException("type == null");
    183         }
    184 
    185         return indexOf(type.getClassType());
    186     }
    187 
    188     /** {@inheritDoc} */
    189     @Override
    190     protected void orderItems() {
    191         int idx = 0;
    192 
    193         for (Object i : items()) {
    194             ((TypeIdItem) i).setIndex(idx);
    195             idx++;
    196         }
    197     }
    198 }
    199