/* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php * * 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.ide.eclipse.adt.internal.actions; import com.android.SdkConstants; import com.android.annotations.Nullable; import com.android.ide.eclipse.adt.AdtConstants; import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.AdtUtils; import com.android.ide.eclipse.adt.internal.sdk.AdtConsoleSdkLog; import com.android.ide.eclipse.adt.internal.sdk.ProjectState; import com.android.ide.eclipse.adt.internal.sdk.Sdk; import com.android.sdklib.SdkManager; import com.android.sdklib.internal.project.ProjectProperties; import com.android.sdklib.internal.project.ProjectProperties.PropertyType; import com.android.sdklib.internal.project.ProjectPropertiesWorkingCopy; import com.android.sdklib.io.FileOp; import com.android.sdkuilib.internal.repository.ui.AdtUpdateDialog; import com.android.utils.NullLogger; import com.android.utils.Pair; import org.eclipse.core.filesystem.EFS; import org.eclipse.core.filesystem.IFileStore; import org.eclipse.core.filesystem.IFileSystem; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jface.action.IAction; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.IObjectActionDelegate; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.IWorkbenchWindowActionDelegate; import java.io.File; import java.io.IOException; import java.util.Iterator; import java.util.Map; /** * An action to add the android-support-v4.jar support library * to the selected project. *
* This should be used by the GLE. The action itself is currently more * like an example of how to invoke the new {@link AdtUpdateDialog}. * * TODO: make this more configurable. */ public class AddSupportJarAction implements IObjectActionDelegate { /** The vendor ID of the support library. */ private static final String VENDOR_ID = "android"; //$NON-NLS-1$ /** The path ID of the support library. */ private static final String SUPPORT_ID = "support"; //$NON-NLS-1$ /** The path ID of the compatibility library (which was its id for releases 1-3). */ private static final String COMPATIBILITY_ID = "compatibility"; //$NON-NLS-1$ private static final String FD_GRIDLAYOUT = "gridlayout"; //$NON-NLS-1$ private static final String FD_V7 = "v7"; //$NON-NLS-1$ private static final String FD_V4 = "v4"; //$NON-NLS-1$ private static final String FD_V13 = "v13"; //$NON-NLS-1$ private static final String FD_APPCOMPAT = "appcompat"; //$NON-NLS-1$ private static final String FD_LIBS = "libs"; //$NON-NLS-1$ private static final String ANDROID_SUPPORT_V4_JAR = "android-support-v4.jar"; //$NON-NLS-1$ private static final String ANDROID_SUPPORT_V13_JAR = "android-support-v13.jar";//$NON-NLS-1$ private static final String APPCOMPAT_V7_JAR = "android-support-v7-appcompat.jar";//$NON-NLS-1$ private static final String APP_COMPAT_LIB_NAME = "appcompat_v7"; //$NON-NLS-1$ private ISelection mSelection; /** * @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart) */ @Override public void setActivePart(IAction action, IWorkbenchPart targetPart) { } @Override public void run(IAction action) { if (mSelection instanceof IStructuredSelection) { for (Iterator> it = ((IStructuredSelection) mSelection).iterator(); it.hasNext();) { Object element = it.next(); IProject project = null; if (element instanceof IProject) { project = (IProject) element; } else if (element instanceof IAdaptable) { project = (IProject) ((IAdaptable) element) .getAdapter(IProject.class); } if (project != null) { install(project); } } } } @Override public void selectionChanged(IAction action, ISelection selection) { mSelection = selection; } /** * Install the support jar into the given project. * * @param project The Android project to install the support jar into * @return true if the installation was successful */ public static boolean install(final IProject project) { File jarPath = installSupport(-1); if (jarPath != null) { try { return copyJarIntoProject(project, jarPath) != null; } catch (Exception e) { AdtPlugin.log(e, null); } } return false; } /** * Installs the Android Support library into the SDK extras/ folder. If a minimum * revision number is specified, this method will check whether the package is already * installed, and if the installed revision is at least as high as the requested revision, * this method will exit without performing an update. * * @param minimumRevision a minimum revision, or -1 to upgrade * unconditionally. Note that this does NOT specify which * revision to install; the latest version will always be * installed. * @return the location of the support jar file, or null if something went * wrong */ @Nullable public static File installSupport(int minimumRevision) { final Sdk sdk = Sdk.getCurrent(); if (sdk == null) { AdtPlugin.printErrorToConsole( AddSupportJarAction.class.getSimpleName(), // tag "Error: Android SDK is not loaded yet."); //$NON-NLS-1$ return null; } String sdkLocation = sdk.getSdkOsLocation(); if (minimumRevision > 0) { File path = getSupportJarFile(); if (path != null) { assert path.exists(); // guaranteed by the getSupportJarFile call int installedRevision = getInstalledRevision(); if (installedRevision != -1 && minimumRevision <= installedRevision) { return path; } } } // TODO: For the generic action, check the library isn't in the project already. // First call the package manager to make sure the package is installed // and get the installation path of the library. AdtUpdateDialog window = new AdtUpdateDialog( AdtPlugin.getShell(), new AdtConsoleSdkLog(), sdkLocation); PairwaitForFinish
is false, if the installation is
* likely to be successful - e.g. the user has at least agreed to
* all installation prompts.)
*/
public static boolean installGridLayoutLibrary(final IProject project, boolean waitForFinish) {
final IJavaProject javaProject = JavaCore.create(project);
if (javaProject != null) {
File supportPath = getSupportPackageDir();
if (!supportPath.isDirectory()) {
File path = installSupport(8); // GridLayout arrived in rev 7 and fixed in rev 8
if (path == null) {
return false;
}
assert path.equals(supportPath);
}
File libraryPath = new File(supportPath, FD_V7 + File.separator + FD_GRIDLAYOUT);
if (!libraryPath.isDirectory()) {
// Upgrade support package: it's out of date. The SDK manager will
// perform an upgrade to the latest version if the package is already installed.
File path = installSupport(-1);
if (path == null) {
return false;
}
assert path.equals(libraryPath) : path;
}
// Create workspace copy of the project and add library dependency
IProject libraryProject = createLibraryProject(libraryPath, project,
"gridlayout_v7", waitForFinish); //$NON-NLS-1$
if (libraryProject != null) {
return addLibraryDependency(libraryProject, project, waitForFinish);
}
}
return false;
}
/**
* Similar to {@link #install}, but rather than copy a jar into the given
* project, it creates a new library project in the workspace for the
* support library, and adds a library dependency on the newly
* installed library from the given project.
*
* @param project the project to add a dependency on the library to
* @param waitForFinish If true, block until the task has finished
* @return true if the installation was successful (or if
* waitForFinish
is false, if the installation is
* likely to be successful - e.g. the user has at least agreed to
* all installation prompts.)
*/
public static boolean installAppCompatLibrary(final IProject project, boolean waitForFinish) {
final IJavaProject javaProject = JavaCore.create(project);
if (javaProject != null) {
// Don't add in the library if it already exists
ProjectState state = Sdk.getProjectState(project);
ProjectPropertiesWorkingCopy copy = state.getProperties().makeWorkingCopy();
for (String property : copy.keySet()) {
if (property.startsWith(ProjectProperties.PROPERTY_LIB_REF)) {
String libraryReference = copy.getProperty(property);
if (libraryReference != null && libraryReference.contains(APP_COMPAT_LIB_NAME)) {
return true;
}
}
}
File supportPath = getSupportPackageDir();
if (!supportPath.isDirectory()) {
File path = installSupport(7);
if (path == null) {
return false;
}
assert path.equals(supportPath);
}
File libraryPath = new File(supportPath, FD_V7 + File.separator + FD_APPCOMPAT);
if (!libraryPath.isDirectory()) {
// Upgrade support package: it's out of date. The SDK manager will
// perform an upgrade to the latest version if the package is already installed.
File path = installSupport(-1);
if (path == null) {
return false;
}
assert path.equals(libraryPath) : path;
}
// Check to see if there's already a version of the library available
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IWorkspaceRoot root = workspace.getRoot();
IProject libraryProject = root.getProject(APP_COMPAT_LIB_NAME);
if (!libraryProject.exists()) {
// Create workspace copy of the project and add library dependency
libraryProject = createLibraryProject(libraryPath, project,
APP_COMPAT_LIB_NAME, waitForFinish);
}
if (libraryProject != null) {
return addLibraryDependency(libraryProject, project, waitForFinish);
}
}
return false;
}
/**
* Returns the directory containing the support libraries (v4, v7, v13,
* ...), which may or may not exist
*
* @return a path to the support library or null
*/
private static File getSupportPackageDir() {
final Sdk sdk = Sdk.getCurrent();
if (sdk != null) {
String sdkLocation = sdk.getSdkOsLocation();
SdkManager manager = SdkManager.createManager(sdkLocation, NullLogger.getLogger());
Map