Java tutorial
/* * Copyright (C) 2015 The Android Open Source Project * * 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 com.android.sdklib.repository.targets; import com.android.SdkConstants; import com.android.annotations.NonNull; import com.android.annotations.Nullable; import com.android.repository.api.ConsoleProgressIndicator; import com.android.repository.api.LocalPackage; import com.android.repository.api.ProgressIndicator; import com.android.repository.api.RepoManager; import com.android.repository.impl.meta.TypeDetails; import com.android.repository.io.FileOp; import com.android.sdklib.AndroidTargetHash; import com.android.sdklib.AndroidVersion; import com.android.sdklib.IAndroidTarget; import com.android.sdklib.repository.AndroidSdkHandler; import com.android.sdklib.repository.meta.DetailsTypes; import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; import com.google.common.collect.Maps; import java.util.Collection; import java.util.Comparator; import java.util.Map; /** * Finds and allows access to all {@link IAndroidTarget}s in a given SDK. */ public class AndroidTargetManager { /** * Cache of the {@link IAndroidTarget}s we created from platform and addon packages. */ private Map<LocalPackage, IAndroidTarget> mTargets; private final FileOp mFop; private final AndroidSdkHandler mSdkHandler; /** * Map of package paths to errors encountered while loading creating the target. */ private Map<String, String> mLoadErrors; private static final Comparator<LocalPackage> TARGET_COMPARATOR = Comparator .<LocalPackage, AndroidVersion>comparing( localPackage -> ((DetailsTypes.ApiDetailsType) localPackage.getTypeDetails()) .getAndroidVersion()) .thenComparing(LocalPackage::getPath) .thenComparing(localPackage -> localPackage.getTypeDetails().getClass().getName()); /** * Create a manager using the new {@link AndroidSdkHandler}/{@link RepoManager} mechanism for * finding packages. */ public AndroidTargetManager(@NonNull AndroidSdkHandler handler, @NonNull FileOp fop) { mSdkHandler = handler; mFop = fop; } /** * Returns the targets (platforms and addons) that are available in the SDK, sorted in * ascending order by API level. */ @NonNull public Collection<IAndroidTarget> getTargets(@NonNull ProgressIndicator progress) { return getTargetMap(progress).values(); } @NonNull private Map<LocalPackage, IAndroidTarget> getTargetMap(@NonNull ProgressIndicator progress) { if (mTargets == null) { Map<String, String> newErrors = Maps.newHashMap(); RepoManager manager = mSdkHandler.getSdkManager(progress); Map<AndroidVersion, PlatformTarget> platformTargets = Maps.newHashMap(); BiMap<IAndroidTarget, LocalPackage> tempTargetToPackage = HashBiMap.create(); for (LocalPackage p : manager.getPackages().getLocalPackages().values()) { TypeDetails details = p.getTypeDetails(); if (details instanceof DetailsTypes.PlatformDetailsType) { try { PlatformTarget target = new PlatformTarget(p, mSdkHandler, mFop, progress); AndroidVersion androidVersion = target.getVersion(); // If we've already seen a platform with this version, replace the existing // with this if this is the "real" package (with the expected path). // Otherwise, don't create a duplicate. PlatformTarget existing = platformTargets.get(androidVersion); if (existing == null || p.getPath().equals(DetailsTypes.getPlatformPath(androidVersion))) { if (existing != null) { tempTargetToPackage.remove(existing); } platformTargets.put(androidVersion, target); tempTargetToPackage.put(target, p); } } catch (IllegalArgumentException e) { newErrors.put(p.getPath(), e.getMessage()); } } } for (LocalPackage p : manager.getPackages().getLocalPackages().values()) { TypeDetails details = p.getTypeDetails(); if (details instanceof DetailsTypes.AddonDetailsType) { AndroidVersion addonVersion = ((DetailsTypes.AddonDetailsType) details).getAndroidVersion(); PlatformTarget baseTarget = platformTargets.get(addonVersion); if (baseTarget != null) { tempTargetToPackage.put(new AddonTarget(p, baseTarget, mSdkHandler.getSystemImageManager(progress), progress, mFop), p); } } } Map<LocalPackage, IAndroidTarget> result = Maps.newTreeMap(TARGET_COMPARATOR); result.putAll(tempTargetToPackage.inverse()); for (LocalPackage p : manager.getPackages() .getLocalPackagesForPrefix(SdkConstants.FD_ANDROID_SOURCES)) { TypeDetails details = p.getTypeDetails(); if (details instanceof DetailsTypes.ApiDetailsType) { PlatformTarget target = platformTargets .get(((DetailsTypes.ApiDetailsType) details).getAndroidVersion()); if (target != null) { target.setSources(p.getLocation()); } } } mTargets = result; mLoadErrors = newErrors; } return mTargets; } /** * Returns a target from a hash that was generated by {@link IAndroidTarget#hashString()}. * * @param hash the {@link IAndroidTarget} hash string. * @return The matching {@link IAndroidTarget} or null. */ @Nullable public IAndroidTarget getTargetFromHashString(@Nullable String hash, @NonNull ProgressIndicator progress) { if (hash != null) { for (IAndroidTarget target : getTargets(progress)) { if (target != null && hash.equals(AndroidTargetHash.getTargetHashString(target))) { return target; } } } return null; } /** * Returns first target found with API level no lower than the minimum provided. * @param minimumApiLevel minimum api level desired for target. * @param progress progress indicator. * @return a matching {@link IAndroidTarget} or null */ @Nullable public IAndroidTarget getTargetOfAtLeastApiLevel(int minimumApiLevel, @NonNull ProgressIndicator progress) { for (IAndroidTarget target : getTargets(progress)) { if (target.getVersion().getApiLevel() >= minimumApiLevel) { return target; } } return null; } /** * Returns the error, if any, encountered when error creating a target for a package. */ @Nullable public String getErrorForPackage(@NonNull String path) { // We assume we're in here because it's known that there's some error. If mLoadErrors // is null we must reload, so we can say exactly what the problem was (if it persists). if (mLoadErrors == null) { getTargetMap(new ConsoleProgressIndicator()); } return mLoadErrors.get(path); } @Nullable public IAndroidTarget getTargetFromPackage(@NonNull LocalPackage p, @NonNull ProgressIndicator progress) { return getTargetMap(progress).get(p); } }