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.dx.command.dexer.Main; 22 23 import java.util.Formatter; 24 import java.util.Map; 25 import java.util.TreeMap; 26 import java.util.concurrent.atomic.AtomicInteger; 27 28 /** 29 * Member (field or method) refs list section of a {@code .dex} file. 30 */ 31 public abstract class MemberIdsSection extends UniformItemSection { 32 33 /** 34 * Constructs an instance. The file offset is initially unknown. 35 * 36 * @param name {@code null-ok;} the name of this instance, for annotation 37 * purposes 38 * @param file {@code non-null;} file that this instance is part of 39 */ 40 public MemberIdsSection(String name, DexFile file) { 41 super(name, file, 4); 42 } 43 44 /** {@inheritDoc} */ 45 @Override 46 protected void orderItems() { 47 int idx = 0; 48 49 if (items().size() > DexFormat.MAX_MEMBER_IDX + 1) { 50 throw new DexException(getTooManyMembersMessage()); 51 } 52 53 for (Object i : items()) { 54 ((MemberIdItem) i).setIndex(idx); 55 idx++; 56 } 57 } 58 59 private String getTooManyMembersMessage() { 60 Map<String, AtomicInteger> membersByPackage = new TreeMap<String, AtomicInteger>(); 61 for (Object member : items()) { 62 String packageName = ((MemberIdItem) member).getDefiningClass().getPackageName(); 63 AtomicInteger count = membersByPackage.get(packageName); 64 if (count == null) { 65 count = new AtomicInteger(); 66 membersByPackage.put(packageName, count); 67 } 68 count.incrementAndGet(); 69 } 70 71 Formatter formatter = new Formatter(); 72 try { 73 String memberType = this instanceof MethodIdsSection ? "method" : "field"; 74 formatter.format("Too many %s references: %d; max is %d.%n" + 75 Main.getTooManyIdsErrorMessage() + "%n" + 76 "References by package:", 77 memberType, items().size(), DexFormat.MAX_MEMBER_IDX + 1); 78 for (Map.Entry<String, AtomicInteger> entry : membersByPackage.entrySet()) { 79 formatter.format("%n%6d %s", entry.getValue().get(), entry.getKey()); 80 } 81 return formatter.toString(); 82 } finally { 83 formatter.close(); 84 } 85 } 86 87 } 88