am 891968b7: Merge change 3557 into donut

Merge commit '891968b78e9604e0c6f06c3b142bb7274c24bc5b'

* commit '891968b78e9604e0c6f06c3b142bb7274c24bc5b':
  SDK Updater: Support local archives
This commit is contained in:
Android (Google) Code Review
2009-06-10 07:46:16 -07:00
committed by The Android Open Source Project
10 changed files with 238 additions and 72 deletions

View File

@@ -76,7 +76,8 @@ public class AddonPackage extends Package {
/** /**
* Creates a new platform package based on an actual {@link IAndroidTarget} (which * Creates a new platform package based on an actual {@link IAndroidTarget} (which
* {@link IAndroidTarget#isPlatform()} false) from the {@link SdkManager}. * {@link IAndroidTarget#isPlatform()} false) from the {@link SdkManager}.
* This is used to list local SDK folders. * This is used to list local SDK folders in which case there is one archive which
* URL is the actual target location.
*/ */
AddonPackage(IAndroidTarget target) { AddonPackage(IAndroidTarget target) {
super( null, //source super( null, //source
@@ -86,9 +87,7 @@ public class AddonPackage extends Package {
null, //descUrl null, //descUrl
Os.getCurrentOs(), //archiveOs Os.getCurrentOs(), //archiveOs
Arch.getCurrentArch(), //archiveArch Arch.getCurrentArch(), //archiveArch
"", //archiveUrl //$NON-NLS-1$ target.getLocation() //archiveOsPath
0, //archiveSize
null //archiveChecksum
); );
mApiLevel = target.getApiVersionNumber(); mApiLevel = target.getApiVersionNumber();

View File

@@ -154,17 +154,43 @@ public class Archive implements IDescription {
private final String mChecksum; private final String mChecksum;
private final ChecksumType mChecksumType = ChecksumType.SHA1; private final ChecksumType mChecksumType = ChecksumType.SHA1;
private final Package mPackage; private final Package mPackage;
private final String mLocalOsPath;
private final boolean mIsLocal;
/** /**
* Creates a new archive. * Creates a new remote archive.
*/ */
Archive(Package pkg, Os os, Arch arch, String url, long size, String checksum) { Archive(Package pkg, Os os, Arch arch, String url, long size, String checksum) {
mPackage = pkg; mPackage = pkg;
mOs = os; mOs = os;
mArch = arch; mArch = arch;
mUrl = url; mUrl = url;
mLocalOsPath = null;
mSize = size; mSize = size;
mChecksum = checksum; mChecksum = checksum;
mIsLocal = false;
}
/**
* Creates a new local archive.
*/
Archive(Package pkg, Os os, Arch arch, String localOsPath) {
mPackage = pkg;
mOs = os;
mArch = arch;
mUrl = null;
mLocalOsPath = localOsPath;
mSize = 0;
mChecksum = "";
mIsLocal = true;
}
/**
* Returns true if this is a locally installed archive.
* Returns false if this is a remote archive that needs to be downloaded.
*/
public boolean isLocal() {
return mIsLocal;
} }
/** /**
@@ -200,12 +226,22 @@ public class Archive implements IDescription {
/** /**
* Returns the download archive URL, either absolute or relative to the repository xml. * Returns the download archive URL, either absolute or relative to the repository xml.
* For a local installed folder, an URL is frabricated from the folder path. * Always return null for a local installed folder.
* @see #getLocalOsPath()
*/ */
public String getUrl() { public String getUrl() {
return mUrl; return mUrl;
} }
/**
* Returns the local OS folder where a local archive is installed.
* Always return null for remote archives.
* @see #getUrl()
*/
public String getLocalOsPath() {
return mLocalOsPath;
}
/** /**
* Returns the archive {@link Os} enum. * Returns the archive {@link Os} enum.
* Can be null for a local installed folder on an unknown OS. * Can be null for a local installed folder on an unknown OS.
@@ -290,6 +326,15 @@ public class Archive implements IDescription {
return true; return true;
} }
/**
* Delete the archive folder if this is a local archive.
*/
public void deleteLocal() {
if (isLocal()) {
deleteFileOrFolder(new File(getLocalOsPath()));
}
}
/** /**
* Install this {@link Archive}s. * Install this {@link Archive}s.
* The archive will be skipped if it is incompatible. * The archive will be skipped if it is incompatible.
@@ -302,7 +347,14 @@ public class Archive implements IDescription {
try { try {
String name = getParentPackage().getShortDescription(); String name = getParentPackage().getShortDescription();
// TODO: we should not see this test fail if we had the filter UI above. if (isLocal()) {
// This should never happen.
monitor.setResult("Skipping already installed archive: %1$s for %2$s",
name,
getOsDescription());
return false;
}
if (!isCompatible()) { if (!isCompatible()) {
monitor.setResult("Skipping incompatible archive: %1$s for %2$s", monitor.setResult("Skipping incompatible archive: %1$s for %2$s",
name, name,

View File

@@ -44,7 +44,8 @@ public class DocPackage extends Package {
/** /**
* Manually create a new package with one archive and the given attributes. * Manually create a new package with one archive and the given attributes.
* This is used to create packages from local directories. * This is used to create packages from local directories in which case there must be
* one archive which URL is the actual target location.
*/ */
DocPackage(RepoSource source, DocPackage(RepoSource source,
int apiLevel, int apiLevel,
@@ -54,9 +55,7 @@ public class DocPackage extends Package {
String descUrl, String descUrl,
Os archiveOs, Os archiveOs,
Arch archiveArch, Arch archiveArch,
String archiveUrl, String archiveOsPath) {
long archiveSize,
String archiveChecksum) {
super(source, super(source,
revision, revision,
license, license,
@@ -64,9 +63,7 @@ public class DocPackage extends Package {
descUrl, descUrl,
archiveOs, archiveOs,
archiveArch, archiveArch,
archiveUrl, archiveOsPath);
archiveSize,
archiveChecksum);
mApiLevel = apiLevel; mApiLevel = apiLevel;
} }

View File

@@ -35,7 +35,6 @@ import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.StringReader; import java.io.StringReader;
import java.net.MalformedURLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
@@ -60,7 +59,7 @@ public class LocalSdkParser {
private Package[] mPackages; private Package[] mPackages;
public LocalSdkParser() { public LocalSdkParser() {
// TODO Auto-generated constructor stub // pass
} }
/** /**
@@ -172,9 +171,7 @@ public class LocalSdkParser {
null, //descUrl null, //descUrl
Os.getCurrentOs(), //archiveOs Os.getCurrentOs(), //archiveOs
Arch.getCurrentArch(), //archiveArch Arch.getCurrentArch(), //archiveArch
"", //archiveUrl //$NON-NLS-1$ toolFolder.getPath() //archiveOsPath
0, //archiveSize
null //archiveChecksum
); );
} }
@@ -219,13 +216,6 @@ public class LocalSdkParser {
// Create a pkg if we don't have one yet. // Create a pkg if we don't have one yet.
if (pkg == null) { if (pkg == null) {
String url = null;
try {
url = docFolder.toURI().toURL().toString();
} catch (MalformedURLException e) {
// ignore
}
pkg = new DocPackage( pkg = new DocPackage(
null, //source null, //source
0, //apiLevel 0, //apiLevel
@@ -235,9 +225,7 @@ public class LocalSdkParser {
null, //descUrl null, //descUrl
Os.getCurrentOs(), //archiveOs Os.getCurrentOs(), //archiveOs
Arch.getCurrentArch(), //archiveArch Arch.getCurrentArch(), //archiveArch
url, //archiveUrl docFolder.getPath() //archiveOsPath
0, //archiveSize
null //archiveChecksum
); );
} }
} }

View File

@@ -62,7 +62,8 @@ public abstract class Package implements IDescription {
/** /**
* Manually create a new package with one archive and the given attributes. * Manually create a new package with one archive and the given attributes.
* This is used to create packages from local directories. * This is used to create packages from local directories in which case there must be
* one archive which URL is the actual target location.
*/ */
public Package(RepoSource source, public Package(RepoSource source,
int revision, int revision,
@@ -71,9 +72,7 @@ public abstract class Package implements IDescription {
String descUrl, String descUrl,
Os archiveOs, Os archiveOs,
Arch archiveArch, Arch archiveArch,
String archiveUrl, String archiveOsPath) {
long archiveSize,
String archiveChecksum) {
mSource = source; mSource = source;
mRevision = revision; mRevision = revision;
mLicense = license; mLicense = license;
@@ -83,9 +82,7 @@ public abstract class Package implements IDescription {
mArchives[0] = new Archive(this, mArchives[0] = new Archive(this,
archiveOs, archiveOs,
archiveArch, archiveArch,
archiveUrl, archiveOsPath);
archiveSize,
archiveChecksum);
} }
/** /**

View File

@@ -49,7 +49,8 @@ public class PlatformPackage extends Package {
/** /**
* Creates a new platform package based on an actual {@link IAndroidTarget} (which * Creates a new platform package based on an actual {@link IAndroidTarget} (which
* must have {@link IAndroidTarget#isPlatform()} true) from the {@link SdkManager}. * must have {@link IAndroidTarget#isPlatform()} true) from the {@link SdkManager}.
* This is used to list local SDK folders. * This is used to list local SDK folders in which case there is one archive which
* URL is the actual target location.
*/ */
PlatformPackage(IAndroidTarget target) { PlatformPackage(IAndroidTarget target) {
super( null, //source super( null, //source
@@ -59,9 +60,7 @@ public class PlatformPackage extends Package {
null, //descUrl null, //descUrl
Os.getCurrentOs(), //archiveOs Os.getCurrentOs(), //archiveOs
Arch.getCurrentArch(), //archiveArch Arch.getCurrentArch(), //archiveArch
"", //archiveUrl //$NON-NLS-1$ target.getLocation() //archiveOsPath
0, //archiveSize
null //archiveChecksum
); );
mApiLevel = target.getApiVersionNumber(); mApiLevel = target.getApiVersionNumber();

View File

@@ -40,7 +40,8 @@ public class ToolPackage extends Package {
/** /**
* Manually create a new package with one archive and the given attributes. * Manually create a new package with one archive and the given attributes.
* This is used to create packages from local directories. * This is used to create packages from local directories in which case there must be
* one archive which URL is the actual target location.
*/ */
ToolPackage(RepoSource source, ToolPackage(RepoSource source,
int revision, int revision,
@@ -49,9 +50,7 @@ public class ToolPackage extends Package {
String descUrl, String descUrl,
Os archiveOs, Os archiveOs,
Arch archiveArch, Arch archiveArch,
String archiveUrl, String archiveOsPath) {
long archiveSize,
String archiveChecksum) {
super(source, super(source,
revision, revision,
license, license,
@@ -59,9 +58,7 @@ public class ToolPackage extends Package {
descUrl, descUrl,
archiveOs, archiveOs,
archiveArch, archiveArch,
archiveUrl, archiveOsPath);
archiveSize,
archiveChecksum);
} }
/** Returns a short description for an {@link IDescription}. */ /** Returns a short description for an {@link IDescription}. */

View File

@@ -16,10 +16,13 @@
package com.android.sdkuilib.internal.repository; package com.android.sdkuilib.internal.repository;
import com.android.sdklib.internal.repository.Archive;
import com.android.sdklib.internal.repository.IDescription; import com.android.sdklib.internal.repository.IDescription;
import com.android.sdklib.internal.repository.ITask; import com.android.sdklib.internal.repository.ITask;
import com.android.sdklib.internal.repository.ITaskMonitor; import com.android.sdklib.internal.repository.ITaskMonitor;
import com.android.sdklib.internal.repository.Package;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TableViewer;
@@ -39,6 +42,8 @@ import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text; import org.eclipse.swt.widgets.Text;
import java.io.File;
/* /*
* TODO list * TODO list
* - select => update desc, enable update + delete, enable home page if url * - select => update desc, enable update + delete, enable home page if url
@@ -49,7 +54,9 @@ import org.eclipse.swt.widgets.Text;
*/ */
public class LocalPackagesPage extends Composite { public class LocalPackagesPage extends Composite {
private UpdaterData mUpdaterData;
private final UpdaterWindowImpl mUpdaterWindow;
private final UpdaterData mUpdaterData;
private Label mSdkLocLabel; private Label mSdkLocLabel;
private Text mSdkLocText; private Text mSdkLocText;
@@ -63,17 +70,22 @@ public class LocalPackagesPage extends Composite {
private Label mPlaceholder1; private Label mPlaceholder1;
private Button mDeleteButton; private Button mDeleteButton;
private Label mPlaceholder2; private Label mPlaceholder2;
private Button mHomePageButton; private Button mRefreshButton;
private Label mDescriptionLabel; private Label mDescriptionLabel;
/** /**
* Create the composite. * Create the composite.
* @param parent The parent of the composite. * @param parent The parent of the composite.
* @param updaterData An instance of {@link UpdaterData}. If null, a local * @param updaterData An instance of {@link UpdaterData}. If null, a local
* one will be allocated just to help with the SWT Designer. * one will be allocated just to help with the SWT Designer.
* @param updaterWindow The parent window.
*/ */
public LocalPackagesPage(Composite parent, UpdaterData updaterData) { public LocalPackagesPage(Composite parent,
UpdaterData updaterData,
UpdaterWindowImpl updaterWindow) {
super(parent, SWT.BORDER); super(parent, SWT.BORDER);
mUpdaterWindow = updaterWindow;
mUpdaterData = updaterData != null ? updaterData : new UpdaterData(); mUpdaterData = updaterData != null ? updaterData : new UpdaterData();
@@ -127,15 +139,27 @@ public class LocalPackagesPage extends Composite {
mPlaceholder1.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1)); mPlaceholder1.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1));
mDeleteButton = new Button(mContainerButtons, SWT.NONE); mDeleteButton = new Button(mContainerButtons, SWT.NONE);
mDeleteButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
onDeleteSelected(); //$hide$ (hide from SWT designer)
}
});
mDeleteButton.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1)); mDeleteButton.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1));
mDeleteButton.setText("Delete..."); mDeleteButton.setText("Delete...");
mPlaceholder2 = new Label(mContainerButtons, SWT.NONE); mPlaceholder2 = new Label(mContainerButtons, SWT.NONE);
mPlaceholder2.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1)); mPlaceholder2.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1));
mHomePageButton = new Button(mContainerButtons, SWT.NONE); mRefreshButton = new Button(mContainerButtons, SWT.NONE);
mHomePageButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); mRefreshButton.addSelectionListener(new SelectionAdapter() {
mHomePageButton.setText("Home Page..."); @Override
public void widgetSelected(SelectionEvent e) {
onRefreshSelected(); //$hide$ (hide from SWT designer)
}
});
mRefreshButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
mRefreshButton.setText("Refresh");
} }
private void createSdkLocation(Composite parent) { private void createSdkLocation(Composite parent) {
@@ -225,25 +249,57 @@ public class LocalPackagesPage extends Composite {
} }
private void onUpdateInstalledPackage() { private void onUpdateInstalledPackage() {
// TODO just a test, needs to be removed later. if (mUpdaterWindow != null) {
new ProgressTask(getShell(), "Test", new ITask() { mUpdaterWindow.updateAll();
public void run(ITaskMonitor monitor) { }
monitor.setDescription("Test"); }
monitor.setProgressMax(100);
int n = 0; private void onDeleteSelected() {
int d = 1; ISelection sel = mTableViewerPackages.getSelection();
while(!monitor.isCancelRequested()) { if (sel instanceof IStructuredSelection) {
monitor.incProgress(d); Object elem = ((IStructuredSelection) sel).getFirstElement();
n += d; if (elem instanceof Package) {
if (n == 0 || n == 100) d = -d;
try { String title = "Delete SDK Package";
Thread.sleep(5); String error = null;
} catch (InterruptedException e) {
// ignore Package p = (Package) elem;
Archive[] archives = p.getArchives();
if (archives.length == 1 && archives[0] != null && archives[0].isLocal()) {
Archive archive = archives[0];
String osPath = archive.getLocalOsPath();
File dir = new File(osPath);
if (dir.isDirectory()) {
String msg = String.format("Are you sure you want to delete '%1$s' at '%2$s'? This cannot be undone.",
p.getShortDescription(), osPath);
if (MessageDialog.openQuestion(getShell(), title, msg)) {
archive.deleteLocal();
// refresh list
onRefreshSelected();
}
} else {
error = "Directory not found for this package";
} }
} else {
error = "No local archive found for this package";
} }
if (error != null) {
MessageDialog.openError(getShell(), title, error);
}
return;
} }
}); }
}
private void onRefreshSelected() {
if (mUpdaterWindow != null) {
mUpdaterWindow.scanLocalSdkFolders();
}
} }
// End of hiding from SWT Designer // End of hiding from SWT Designer

View File

@@ -131,15 +131,33 @@ public class RemotePackagesPage extends Composite {
mDescriptionLabel.setText("Line1\nLine2\nLine3"); mDescriptionLabel.setText("Line1\nLine2\nLine3");
mAddSiteButton = new Button(parent, SWT.NONE); mAddSiteButton = new Button(parent, SWT.NONE);
mAddSiteButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
onAddSiteSelected(); //$hide$
}
});
mAddSiteButton.setText("Add Site..."); mAddSiteButton.setText("Add Site...");
mRemoveSiteButton = new Button(parent, SWT.NONE); mRemoveSiteButton = new Button(parent, SWT.NONE);
mRemoveSiteButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
onRemoveSiteSelected(); //$hide$
}
});
mRemoveSiteButton.setText("Delete Site..."); mRemoveSiteButton.setText("Delete Site...");
mPlaceholder3 = new Label(parent, SWT.NONE); mPlaceholder3 = new Label(parent, SWT.NONE);
mPlaceholder3.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, false, 1, 1)); mPlaceholder3.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, false, 1, 1));
mRefreshButton = new Button(parent, SWT.NONE); mRefreshButton = new Button(parent, SWT.NONE);
mRefreshButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
onRefreshSelected(); //$hide$
}
});
mRefreshButton.setText("Refresh"); mRefreshButton.setText("Refresh");
mInstallSelectedButton = new Button(parent, SWT.NONE); mInstallSelectedButton = new Button(parent, SWT.NONE);
@@ -234,7 +252,21 @@ public class RemotePackagesPage extends Composite {
} }
} }
mUpdaterWindow.installArchives(archives); if (mUpdaterWindow != null) {
mUpdaterWindow.installArchives(archives);
}
}
private void onAddSiteSelected() {
}
private void onRemoveSiteSelected() {
}
private void onRefreshSelected() {
if (mUpdaterWindow != null) {
mUpdaterWindow.refreshSources(false /*forceFetching*/);
}
} }
// End of hiding from SWT Designer // End of hiding from SWT Designer

View File

@@ -23,6 +23,7 @@ import com.android.sdklib.internal.repository.Archive;
import com.android.sdklib.internal.repository.ITask; import com.android.sdklib.internal.repository.ITask;
import com.android.sdklib.internal.repository.ITaskMonitor; import com.android.sdklib.internal.repository.ITaskMonitor;
import com.android.sdklib.internal.repository.RepoSource; import com.android.sdklib.internal.repository.RepoSource;
import com.android.sdklib.internal.repository.RepoSources;
import com.android.sdklib.repository.SdkRepository; import com.android.sdklib.repository.SdkRepository;
import org.eclipse.swt.SWT; import org.eclipse.swt.SWT;
@@ -136,7 +137,7 @@ public class UpdaterWindowImpl {
mStackLayout = new StackLayout(); mStackLayout = new StackLayout();
mPagesRootComposite.setLayout(mStackLayout); mPagesRootComposite.setLayout(mStackLayout);
mLocalPackagePage = new LocalPackagesPage(mPagesRootComposite, mUpdaterData); mLocalPackagePage = new LocalPackagesPage(mPagesRootComposite, mUpdaterData, this);
mRemotePackagesPage = new RemotePackagesPage(mPagesRootComposite, mUpdaterData, this); mRemotePackagesPage = new RemotePackagesPage(mPagesRootComposite, mUpdaterData, this);
mSashForm.setWeights(new int[] {150, 576}); mSashForm.setWeights(new int[] {150, 576});
} }
@@ -327,7 +328,7 @@ public class UpdaterWindowImpl {
/** /**
* Used to scan the local SDK folders the first time. * Used to scan the local SDK folders the first time.
*/ */
private void scanLocalSdkFolders() { public void scanLocalSdkFolders() {
mUpdaterData.getLocalSdkAdapter().setSdkRoot(mUpdaterData.getOsSdkRoot()); mUpdaterData.getLocalSdkAdapter().setSdkRoot(mUpdaterData.getOsSdkRoot());
mLocalPackagePage.setInput(mUpdaterData.getLocalSdkAdapter()); mLocalPackagePage.setInput(mUpdaterData.getLocalSdkAdapter());
@@ -389,6 +390,54 @@ public class UpdaterWindowImpl {
}); });
} }
public void updateAll() {
refreshSources(true);
// TODO have refreshSources reuse the current progress task
// mTaskFactory.start("Update Archives", new ITask() {
// public void run(ITaskMonitor monitor) {
// monitor.setProgressMax(3);
//
// monitor.setDescription("Refresh sources");
// refreshSources(true);
// }
// });
}
/**
* Refresh sources
*
* @param forceFetching When true, load sources that haven't been loaded yet. When
* false, only refresh sources that have been loaded yet.
*/
public void refreshSources(final boolean forceFetching) {
ArrayList<RepoSource> sources = mUpdaterData.getSources().getSources();
for (RepoSource source : sources) {
if (forceFetching || source.getPackages() != null) {
source.load(mTaskFactory);
}
}
// TODO have source.load reuse the current progress task
// mTaskFactory.start("Refresh sources", new ITask() {
// public void run(ITaskMonitor monitor) {
// ArrayList<RepoSource> sources = mUpdaterData.getSources().getSources();
// monitor.setProgressMax(sources.size());
//
// for (RepoSource source : sources) {
// if (forceFetching || source.getPackages() != null) {
// monitor.setDescription(String.format("Refresh %1$s",
// source.getShortDescription()));
// source.load(mTaskFactory);
// }
// monitor.incProgress(1);
// }
// }
// });
}
// End of hiding from SWT Designer // End of hiding from SWT Designer
//$hide<<$ //$hide<<$
} }