1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage com.android.dx.dex.file;
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
199f0f8b6c64cdff79989be28fff70db39f412de90Jesse Wilsonimport com.android.dx.util.DexException;
204dfe64e94f153ccd8db56bea7b8cdfb02e5bba08Jesse Wilsonimport java.util.Formatter;
214dfe64e94f153ccd8db56bea7b8cdfb02e5bba08Jesse Wilsonimport java.util.Map;
224dfe64e94f153ccd8db56bea7b8cdfb02e5bba08Jesse Wilsonimport java.util.TreeMap;
234dfe64e94f153ccd8db56bea7b8cdfb02e5bba08Jesse Wilsonimport java.util.concurrent.atomic.AtomicInteger;
249f0f8b6c64cdff79989be28fff70db39f412de90Jesse Wilson
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
2699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * Member (field or method) refs list section of a {@code .dex} file.
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic abstract class MemberIdsSection extends UniformItemSection {
299f0f8b6c64cdff79989be28fff70db39f412de90Jesse Wilson    /** The largest addressable member is 0xffff, in the dex spec as field@CCCC or meth@CCCC. */
309f0f8b6c64cdff79989be28fff70db39f412de90Jesse Wilson    private static final int MAX_MEMBERS = 0x10000;
319f0f8b6c64cdff79989be28fff70db39f412de90Jesse Wilson
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs an instance. The file offset is initially unknown.
34de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
3599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param name {@code null-ok;} the name of this instance, for annotation
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * purposes
3799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param file {@code non-null;} file that this instance is part of
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public MemberIdsSection(String name, DexFile file) {
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        super(name, file, 4);
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected void orderItems() {
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int idx = 0;
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
489f0f8b6c64cdff79989be28fff70db39f412de90Jesse Wilson        if (items().size() > MAX_MEMBERS) {
494dfe64e94f153ccd8db56bea7b8cdfb02e5bba08Jesse Wilson            throw new DexException(tooManyMembersMessage());
509f0f8b6c64cdff79989be28fff70db39f412de90Jesse Wilson        }
519f0f8b6c64cdff79989be28fff70db39f412de90Jesse Wilson
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (Object i : items()) {
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ((MemberIdItem) i).setIndex(idx);
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            idx++;
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
574dfe64e94f153ccd8db56bea7b8cdfb02e5bba08Jesse Wilson
584dfe64e94f153ccd8db56bea7b8cdfb02e5bba08Jesse Wilson    private String tooManyMembersMessage() {
594dfe64e94f153ccd8db56bea7b8cdfb02e5bba08Jesse Wilson        Map<String, AtomicInteger> membersByPackage = new TreeMap<String, AtomicInteger>();
604dfe64e94f153ccd8db56bea7b8cdfb02e5bba08Jesse Wilson        for (Object member : items()) {
614dfe64e94f153ccd8db56bea7b8cdfb02e5bba08Jesse Wilson            String packageName = ((MemberIdItem) member).getDefiningClass().getPackageName();
624dfe64e94f153ccd8db56bea7b8cdfb02e5bba08Jesse Wilson            AtomicInteger count = membersByPackage.get(packageName);
634dfe64e94f153ccd8db56bea7b8cdfb02e5bba08Jesse Wilson            if (count == null) {
644dfe64e94f153ccd8db56bea7b8cdfb02e5bba08Jesse Wilson                count = new AtomicInteger();
654dfe64e94f153ccd8db56bea7b8cdfb02e5bba08Jesse Wilson                membersByPackage.put(packageName, count);
664dfe64e94f153ccd8db56bea7b8cdfb02e5bba08Jesse Wilson            }
674dfe64e94f153ccd8db56bea7b8cdfb02e5bba08Jesse Wilson            count.incrementAndGet();
684dfe64e94f153ccd8db56bea7b8cdfb02e5bba08Jesse Wilson        }
694dfe64e94f153ccd8db56bea7b8cdfb02e5bba08Jesse Wilson
704dfe64e94f153ccd8db56bea7b8cdfb02e5bba08Jesse Wilson        Formatter formatter = new Formatter();
714dfe64e94f153ccd8db56bea7b8cdfb02e5bba08Jesse Wilson        String memberType = this instanceof MethodIdsSection ? "methods" : "fields";
724dfe64e94f153ccd8db56bea7b8cdfb02e5bba08Jesse Wilson        formatter.format("Too many %s: %d; max is %d. By package:",
734dfe64e94f153ccd8db56bea7b8cdfb02e5bba08Jesse Wilson                memberType, items().size(), MAX_MEMBERS);
744dfe64e94f153ccd8db56bea7b8cdfb02e5bba08Jesse Wilson        for (Map.Entry<String, AtomicInteger> entry : membersByPackage.entrySet()) {
754dfe64e94f153ccd8db56bea7b8cdfb02e5bba08Jesse Wilson            formatter.format("%n%6d %s", entry.getValue().get(), entry.getKey());
764dfe64e94f153ccd8db56bea7b8cdfb02e5bba08Jesse Wilson        }
774dfe64e94f153ccd8db56bea7b8cdfb02e5bba08Jesse Wilson        return formatter.toString();
784dfe64e94f153ccd8db56bea7b8cdfb02e5bba08Jesse Wilson    }
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
80