/* * Copyright (C) 2013 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.descriptors; import com.android.annotations.NonNull; import com.android.annotations.Nullable; import com.android.sdklib.AndroidVersion; import com.android.sdklib.repository.License; import com.android.sdklib.repository.FullRevision; import com.android.sdklib.repository.MajorRevision; /** * Implementation detail of {@link IPkgDescExtra} for extra packages. */ public final class PkgDescExtra extends PkgDesc implements IPkgDescExtra { private final String[] mOldPaths; private final String mNameDisplay; PkgDescExtra(@NonNull PkgType type, @Nullable License license, @Nullable String listDisplay, @Nullable String descriptionShort, @Nullable String descriptionUrl, boolean isObsolete, @Nullable FullRevision fullRevision, @Nullable MajorRevision majorRevision, @Nullable AndroidVersion androidVersion, @Nullable String path, @Nullable IdDisplay tag, @Nullable IdDisplay vendor, @Nullable FullRevision minToolsRev, @Nullable FullRevision minPlatformToolsRev, @Nullable String nameDisplay, @Nullable final String[] oldPaths) { super(type, license, listDisplay, descriptionShort, descriptionUrl, isObsolete, fullRevision, majorRevision, androidVersion, path, tag, vendor, minToolsRev, minPlatformToolsRev, null, //customIsUpdateFor null); //customPath mNameDisplay = nameDisplay; mOldPaths = oldPaths != null ? oldPaths : new String[0]; } @NonNull @Override public String[] getOldPaths() { return mOldPaths; } @NonNull @Override public String getNameDisplay() { return mNameDisplay == null ? String.format("Unknown (%s)", getInstallId()) : mNameDisplay; } // ---- Helpers ---- /** * Helper method that converts the old_paths property string into the * an old paths array. * * @param oldPathsProperty A possibly-null old_path property string. * @return A list of old paths split by their separator. Can be empty but not null. */ @NonNull public static String[] convertOldPaths(@Nullable String oldPathsProperty) { if (oldPathsProperty == null || oldPathsProperty.isEmpty()) { return new String[0]; } return oldPathsProperty.split(";"); //$NON-NLS-1$ } /** * Helper to computhe whether the extra path of both {@link IPkgDescExtra}s * are compatible with each other, which means they are either equal or are * matched between existing path and the potential old paths list. * <p/> * This also covers backward compatibility -- in earlier schemas the vendor id was * merged into the path string when reloading installed extras. * * @param lhs A non-null {@link IPkgDescExtra}. * @param rhs Another non-null {@link IPkgDescExtra}. * @return true if the paths are compatible. */ public static boolean compatibleVendorAndPath( @NonNull IPkgDescExtra lhs, @NonNull IPkgDescExtra rhs) { String[] epOldPaths = rhs.getOldPaths(); int lenEpOldPaths = epOldPaths.length; for (int indexEp = -1; indexEp < lenEpOldPaths; indexEp++) { if (sameVendorAndPath( lhs.getVendor().getId(), lhs.getPath(), rhs.getVendor().getId(), indexEp < 0 ? rhs.getPath() : epOldPaths[indexEp])) { return true; } } String[] thisOldPaths = lhs.getOldPaths(); int lenThisOldPaths = thisOldPaths.length; for (int indexThis = -1; indexThis < lenThisOldPaths; indexThis++) { if (sameVendorAndPath( lhs.getVendor().getId(), indexThis < 0 ? lhs.getPath() : thisOldPaths[indexThis], rhs.getVendor().getId(), rhs.getPath())) { return true; } } return false; } private static boolean sameVendorAndPath( @Nullable String thisVendor, @Nullable String thisPath, @Nullable String otherVendor, @Nullable String otherPath) { // To be backward compatible, we need to support the old vendor-path form // in either the current or the remote package. // // The vendor test below needs to account for an old installed package // (e.g. with an install path of vendor-name) that has then been updated // in-place and thus when reloaded contains the vendor name in both the // path and the vendor attributes. if (otherPath != null && thisPath != null && thisVendor != null) { if (otherPath.equals(thisVendor + '-' + thisPath) && (otherVendor == null || otherVendor.isEmpty() || otherVendor.equals(thisVendor))) { return true; } } if (thisPath != null && otherPath != null && otherVendor != null) { if (thisPath.equals(otherVendor + '-' + otherPath) && (thisVendor == null || thisVendor.isEmpty() || thisVendor.equals(otherVendor))) { return true; } } if (thisPath != null && thisPath.equals(otherPath)) { if ((thisVendor == null && otherVendor == null) || (thisVendor != null && thisVendor.equals(otherVendor))) { return true; } } return false; } }