1f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn/*
2f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn * Copyright (C) 2011 The Android Open Source Project
3f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn *
4f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License");
5f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn * you may not use this file except in compliance with the License.
6f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn * You may obtain a copy of the License at
7f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn *
8f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn *      http://www.apache.org/licenses/LICENSE-2.0
9f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn *
10f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn * Unless required by applicable law or agreed to in writing, software
11f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS,
12f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn * See the License for the specific language governing permissions and
14f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn * limitations under the License.
15f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn */
16f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn
17f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackbornpackage com.android.server;
18f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn
19f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackbornimport com.android.internal.util.XmlUtils;
20f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn
21f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackbornimport org.xmlpull.v1.XmlPullParser;
22f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackbornimport org.xmlpull.v1.XmlPullParserException;
23f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackbornimport org.xmlpull.v1.XmlSerializer;
24f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn
25f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackbornimport android.content.ComponentName;
26f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackbornimport android.content.IntentFilter;
27f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackbornimport android.content.pm.ActivityInfo;
28f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackbornimport android.content.pm.ResolveInfo;
29f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackbornimport android.util.Slog;
30f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn
31f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackbornimport java.io.IOException;
32f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackbornimport java.io.PrintWriter;
33f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackbornimport java.util.List;
34f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn
35f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackbornpublic class PreferredComponent {
36f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn    public final int mMatch;
37f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn    public final ComponentName mComponent;
38f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn
39f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn    private final String[] mSetPackages;
40f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn    private final String[] mSetClasses;
41f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn    private final String[] mSetComponents;
42f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn    private final String mShortComponent;
43f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn    private String mParseError;
44f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn
45f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn    private final Callbacks mCallbacks;
46f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn
47f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn    public interface Callbacks {
48f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        public boolean onReadTag(String tagName, XmlPullParser parser)
49f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                throws XmlPullParserException, IOException;
50f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn    }
51f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn
52f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn    public PreferredComponent(Callbacks callbacks, int match, ComponentName[] set,
53f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            ComponentName component) {
54f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        mCallbacks = callbacks;
55f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        mMatch = match&IntentFilter.MATCH_CATEGORY_MASK;
56f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        mComponent = component;
57f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        mShortComponent = component.flattenToShortString();
58f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        mParseError = null;
59f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        if (set != null) {
60f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            final int N = set.length;
61f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            String[] myPackages = new String[N];
62f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            String[] myClasses = new String[N];
63f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            String[] myComponents = new String[N];
64f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            for (int i=0; i<N; i++) {
65f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                ComponentName cn = set[i];
66f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                if (cn == null) {
67f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                    mSetPackages = null;
68f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                    mSetClasses = null;
69f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                    mSetComponents = null;
70f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                    return;
71f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                }
72f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                myPackages[i] = cn.getPackageName().intern();
73f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                myClasses[i] = cn.getClassName().intern();
74f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                myComponents[i] = cn.flattenToShortString().intern();
75f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            }
76f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            mSetPackages = myPackages;
77f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            mSetClasses = myClasses;
78f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            mSetComponents = myComponents;
79f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        } else {
80f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            mSetPackages = null;
81f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            mSetClasses = null;
82f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            mSetComponents = null;
83f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        }
84f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn    }
85f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn
86f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn    public PreferredComponent(Callbacks callbacks, XmlPullParser parser)
87f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            throws XmlPullParserException, IOException {
88f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        mCallbacks = callbacks;
89f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        mShortComponent = parser.getAttributeValue(null, "name");
90f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        mComponent = ComponentName.unflattenFromString(mShortComponent);
91f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        if (mComponent == null) {
92f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            mParseError = "Bad activity name " + mShortComponent;
93f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        }
94f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        String matchStr = parser.getAttributeValue(null, "match");
95f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        mMatch = matchStr != null ? Integer.parseInt(matchStr, 16) : 0;
96f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        String setCountStr = parser.getAttributeValue(null, "set");
97f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        int setCount = setCountStr != null ? Integer.parseInt(setCountStr) : 0;
98f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn
99f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        String[] myPackages = setCount > 0 ? new String[setCount] : null;
100f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        String[] myClasses = setCount > 0 ? new String[setCount] : null;
101f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        String[] myComponents = setCount > 0 ? new String[setCount] : null;
102f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn
103f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        int setPos = 0;
104f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn
105f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        int outerDepth = parser.getDepth();
106f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        int type;
107f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
108f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn               && (type != XmlPullParser.END_TAG
109f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                       || parser.getDepth() > outerDepth)) {
110f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            if (type == XmlPullParser.END_TAG
111f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                    || type == XmlPullParser.TEXT) {
112f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                continue;
113f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            }
114f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn
115f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            String tagName = parser.getName();
116f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            //Log.i(TAG, "Parse outerDepth=" + outerDepth + " depth="
117f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            //        + parser.getDepth() + " tag=" + tagName);
118f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            if (tagName.equals("set")) {
119f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                String name = parser.getAttributeValue(null, "name");
120f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                if (name == null) {
121f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                    if (mParseError == null) {
122f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                        mParseError = "No name in set tag in preferred activity "
123f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                            + mShortComponent;
124f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                    }
125f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                } else if (setPos >= setCount) {
126f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                    if (mParseError == null) {
127f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                        mParseError = "Too many set tags in preferred activity "
128f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                            + mShortComponent;
129f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                    }
130f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                } else {
131f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                    ComponentName cn = ComponentName.unflattenFromString(name);
132f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                    if (cn == null) {
133f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                        if (mParseError == null) {
134f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                            mParseError = "Bad set name " + name + " in preferred activity "
135f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                                + mShortComponent;
136f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                        }
137f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                    } else {
138f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                        myPackages[setPos] = cn.getPackageName();
139f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                        myClasses[setPos] = cn.getClassName();
140f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                        myComponents[setPos] = name;
141f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                        setPos++;
142f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                    }
143f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                }
144f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                XmlUtils.skipCurrentTag(parser);
145f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            } else if (!mCallbacks.onReadTag(tagName, parser)) {
146f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                Slog.w("PreferredComponent", "Unknown element: " + parser.getName());
147f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                XmlUtils.skipCurrentTag(parser);
148f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            }
149f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        }
150f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn
151f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        if (setPos != setCount) {
152f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            if (mParseError == null) {
153f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                mParseError = "Not enough set tags (expected " + setCount
154f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                    + " but found " + setPos + ") in " + mShortComponent;
155f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            }
156f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        }
157f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn
158f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        mSetPackages = myPackages;
159f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        mSetClasses = myClasses;
160f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        mSetComponents = myComponents;
161f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn    }
162f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn
163f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn    public String getParseError() {
164f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        return mParseError;
165f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn    }
166f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn
167f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn    public void writeToXml(XmlSerializer serializer) throws IOException {
168f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        final int NS = mSetClasses != null ? mSetClasses.length : 0;
169f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        serializer.attribute(null, "name", mShortComponent);
170f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        if (mMatch != 0) {
171f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            serializer.attribute(null, "match", Integer.toHexString(mMatch));
172f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        }
173f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        serializer.attribute(null, "set", Integer.toString(NS));
174f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        for (int s=0; s<NS; s++) {
175f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            serializer.startTag(null, "set");
176f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            serializer.attribute(null, "name", mSetComponents[s]);
177f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            serializer.endTag(null, "set");
178f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        }
179f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn    }
180f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn
181f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn    public boolean sameSet(List<ResolveInfo> query, int priority) {
182f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        if (mSetPackages == null) return false;
183f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        final int NQ = query.size();
184f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        final int NS = mSetPackages.length;
185f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        int numMatch = 0;
186f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        for (int i=0; i<NQ; i++) {
187f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            ResolveInfo ri = query.get(i);
188f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            if (ri.priority != priority) continue;
189f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            ActivityInfo ai = ri.activityInfo;
190f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            boolean good = false;
191f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            for (int j=0; j<NS; j++) {
192f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                if (mSetPackages[j].equals(ai.packageName)
193f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                        && mSetClasses[j].equals(ai.name)) {
194f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                    numMatch++;
195f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                    good = true;
196f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                    break;
197f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                }
198f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            }
199f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            if (!good) return false;
200f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        }
201f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        return numMatch == NS;
202f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn    }
203f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn
204f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn    public void dump(PrintWriter out, String prefix, Object ident) {
205f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        out.print(prefix); out.print(
206f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                Integer.toHexString(System.identityHashCode(ident)));
207f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                out.print(' ');
208f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                out.print(mComponent.flattenToShortString());
209f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                out.print(" match=0x");
210f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                out.println( Integer.toHexString(mMatch));
211f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        if (mSetComponents != null) {
212f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            out.print(prefix); out.println("  Selected from:");
213f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            for (int i=0; i<mSetComponents.length; i++) {
214f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                out.print(prefix); out.print("    ");
215f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn                        out.println(mSetComponents[i]);
216f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn            }
217f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn        }
218f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn    }
219f8b8a3fa955b545843ca264428c620b67c2a5359Dianne Hackborn}
220