SDK Updater: logic to load/save user sources and to delete them.
This commit is contained in:
@@ -47,7 +47,7 @@ import javax.xml.validation.Validator;
|
|||||||
public class RepoSource implements IDescription {
|
public class RepoSource implements IDescription {
|
||||||
|
|
||||||
private final String mUrl;
|
private final String mUrl;
|
||||||
private final boolean mAddonOnly;
|
private final boolean mUserSource;
|
||||||
|
|
||||||
private Package[] mPackages;
|
private Package[] mPackages;
|
||||||
private String mDescription;
|
private String mDescription;
|
||||||
@@ -55,12 +55,18 @@ public class RepoSource implements IDescription {
|
|||||||
/**
|
/**
|
||||||
* Constructs a new source for the given repository URL.
|
* Constructs a new source for the given repository URL.
|
||||||
*/
|
*/
|
||||||
public RepoSource(String url, boolean addonOnly) {
|
public RepoSource(String url, boolean userSource) {
|
||||||
mUrl = url;
|
mUrl = url;
|
||||||
mAddonOnly = addonOnly;
|
mUserSource = userSource;
|
||||||
setDefaultDescription();
|
setDefaultDescription();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns true if this is a user source. We only load addon and extra packages
|
||||||
|
* from a user source and ignore the rest. */
|
||||||
|
public boolean isUserSource() {
|
||||||
|
return mUserSource;
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns the URL of the repository.xml file for this source. */
|
/** Returns the URL of the repository.xml file for this source. */
|
||||||
public String getUrl() {
|
public String getUrl() {
|
||||||
return mUrl;
|
return mUrl;
|
||||||
@@ -138,7 +144,7 @@ public class RepoSource implements IDescription {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setDefaultDescription() {
|
private void setDefaultDescription() {
|
||||||
if (mAddonOnly) {
|
if (mUserSource) {
|
||||||
mDescription = String.format("Add-on Source: %1$s", mUrl);
|
mDescription = String.format("Add-on Source: %1$s", mUrl);
|
||||||
} else {
|
} else {
|
||||||
mDescription = String.format("SDK Source: %1$s", mUrl);
|
mDescription = String.format("SDK Source: %1$s", mUrl);
|
||||||
@@ -274,13 +280,17 @@ public class RepoSource implements IDescription {
|
|||||||
Package p = null;
|
Package p = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// We can load addon and extra packages from all sources, either
|
||||||
|
// internal or user sources.
|
||||||
if (SdkRepository.NODE_ADD_ON.equals(name)) {
|
if (SdkRepository.NODE_ADD_ON.equals(name)) {
|
||||||
p = new AddonPackage(this, child, licenses);
|
p = new AddonPackage(this, child, licenses);
|
||||||
|
|
||||||
} else if (SdkRepository.NODE_EXTRA.equals(name)) {
|
} else if (SdkRepository.NODE_EXTRA.equals(name)) {
|
||||||
p = new ExtraPackage(this, child, licenses);
|
p = new ExtraPackage(this, child, licenses);
|
||||||
|
|
||||||
} else if (!mAddonOnly) {
|
} else if (!mUserSource) {
|
||||||
|
// We only load platform, doc and tool packages from internal
|
||||||
|
// sources, never from user sources.
|
||||||
if (SdkRepository.NODE_PLATFORM.equals(name)) {
|
if (SdkRepository.NODE_PLATFORM.equals(name)) {
|
||||||
p = new PlatformPackage(this, child, licenses);
|
p = new PlatformPackage(this, child, licenses);
|
||||||
} else if (SdkRepository.NODE_DOC.equals(name)) {
|
} else if (SdkRepository.NODE_DOC.equals(name)) {
|
||||||
|
|||||||
@@ -16,13 +16,28 @@
|
|||||||
|
|
||||||
package com.android.sdklib.internal.repository;
|
package com.android.sdklib.internal.repository;
|
||||||
|
|
||||||
|
import com.android.prefs.AndroidLocation;
|
||||||
|
import com.android.prefs.AndroidLocation.AndroidLocationException;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of sdk-repository sources.
|
* A list of sdk-repository sources.
|
||||||
*/
|
*/
|
||||||
public class RepoSources {
|
public class RepoSources {
|
||||||
|
|
||||||
|
private static final String KEY_COUNT = "count";
|
||||||
|
|
||||||
|
private static final String KEY_SRC = "src";
|
||||||
|
|
||||||
|
private static final String SRC_FILENAME = "repositories.cfg"; //$NON-NLS-1$
|
||||||
|
|
||||||
private ArrayList<RepoSource> mSources = new ArrayList<RepoSource>();
|
private ArrayList<RepoSource> mSources = new ArrayList<RepoSource>();
|
||||||
|
|
||||||
public RepoSources() {
|
public RepoSources() {
|
||||||
@@ -35,10 +50,113 @@ public class RepoSources {
|
|||||||
mSources.add(source);
|
mSources.add(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a source from the Sources list.
|
||||||
|
*/
|
||||||
|
public void remove(RepoSource source) {
|
||||||
|
mSources.remove(source);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the sources list array. This is never null.
|
* Returns the sources list array. This is never null.
|
||||||
*/
|
*/
|
||||||
public ArrayList<RepoSource> getSources() {
|
public RepoSource[] getSources() {
|
||||||
return mSources;
|
return mSources.toArray(new RepoSource[mSources.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads all user sources. This <em>replaces</em> all existing user sources
|
||||||
|
* by the ones from the property file.
|
||||||
|
*/
|
||||||
|
public void loadUserSources() {
|
||||||
|
|
||||||
|
// Remove all existing user sources
|
||||||
|
for (Iterator<RepoSource> it = mSources.iterator(); it.hasNext(); ) {
|
||||||
|
RepoSource s = it.next();
|
||||||
|
if (s.isUserSource()) {
|
||||||
|
it.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load new user sources from property file
|
||||||
|
FileInputStream fis = null;
|
||||||
|
try {
|
||||||
|
String folder = AndroidLocation.getFolder();
|
||||||
|
File f = new File(folder, SRC_FILENAME);
|
||||||
|
if (f.exists()) {
|
||||||
|
fis = new FileInputStream(f);
|
||||||
|
|
||||||
|
Properties props = new Properties();
|
||||||
|
props.load(fis);
|
||||||
|
|
||||||
|
int count = Integer.parseInt(props.getProperty(KEY_COUNT, "0"));
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
String url = props.getProperty(String.format("%s%02d", KEY_SRC, count)); //$NON-NLS-1$
|
||||||
|
if (url != null) {
|
||||||
|
mSources.add(new RepoSource(url, true /*userSource*/));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
// TODO print to log
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (AndroidLocationException e) {
|
||||||
|
// TODO print to log
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IOException e) {
|
||||||
|
// TODO print to log
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
if (fis != null) {
|
||||||
|
try {
|
||||||
|
fis.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves all the user sources.
|
||||||
|
*/
|
||||||
|
public void saveUserSources() {
|
||||||
|
FileOutputStream fos = null;
|
||||||
|
try {
|
||||||
|
String folder = AndroidLocation.getFolder();
|
||||||
|
File f = new File(folder, SRC_FILENAME);
|
||||||
|
|
||||||
|
fos = new FileOutputStream(f);
|
||||||
|
|
||||||
|
Properties props = new Properties();
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
for (RepoSource s : mSources) {
|
||||||
|
if (s.isUserSource()) {
|
||||||
|
count++;
|
||||||
|
props.setProperty(String.format("%s%02d", KEY_SRC, count), s.getUrl()); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
props.setProperty(KEY_COUNT, Integer.toString(count));
|
||||||
|
|
||||||
|
props.store( fos, "## User Sources for Android tool"); //$NON-NLS-1$
|
||||||
|
|
||||||
|
} catch (AndroidLocationException e) {
|
||||||
|
// TODO print to log
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IOException e) {
|
||||||
|
// TODO print to log
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
if (fos != null) {
|
||||||
|
try {
|
||||||
|
fos.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import com.android.sdklib.internal.repository.Package;
|
|||||||
import com.android.sdklib.internal.repository.RepoSource;
|
import com.android.sdklib.internal.repository.RepoSource;
|
||||||
import com.android.sdkuilib.internal.repository.UpdaterData.ISdkListener;
|
import com.android.sdkuilib.internal.repository.UpdaterData.ISdkListener;
|
||||||
|
|
||||||
|
import org.eclipse.jface.dialogs.MessageDialog;
|
||||||
import org.eclipse.jface.viewers.CheckStateChangedEvent;
|
import org.eclipse.jface.viewers.CheckStateChangedEvent;
|
||||||
import org.eclipse.jface.viewers.CheckboxTreeViewer;
|
import org.eclipse.jface.viewers.CheckboxTreeViewer;
|
||||||
import org.eclipse.jface.viewers.ICheckStateListener;
|
import org.eclipse.jface.viewers.ICheckStateListener;
|
||||||
@@ -288,7 +289,30 @@ public class RemotePackagesPage extends Composite implements ISdkListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void onRemoveSiteSelected() {
|
private void onRemoveSiteSelected() {
|
||||||
// TODO prompt for removing addon site URL, store, refresh
|
boolean changed = false;
|
||||||
|
|
||||||
|
ISelection sel = mTreeViewerSources.getSelection();
|
||||||
|
if (sel instanceof ITreeSelection) {
|
||||||
|
for (Object c : ((ITreeSelection) sel).toList()) {
|
||||||
|
if (c instanceof RepoSource && ((RepoSource) c).isUserSource()) {
|
||||||
|
RepoSource source = (RepoSource) c;
|
||||||
|
|
||||||
|
String title = "Delete Site?";
|
||||||
|
|
||||||
|
String msg = String.format("Are you sure you want to delete the site '%1$s'?",
|
||||||
|
source.getUrl());
|
||||||
|
|
||||||
|
if (MessageDialog.openQuestion(getShell(), title, msg)) {
|
||||||
|
mUpdaterData.getSources().remove(source);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
onRefreshSelected();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onRefreshSelected() {
|
private void onRefreshSelected() {
|
||||||
@@ -321,19 +345,20 @@ public class RemotePackagesPage extends Composite implements ISdkListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Is there a selected site Source?
|
// Is there a selected site Source?
|
||||||
boolean hasSelectedSource = false;
|
boolean hasSelectedUserSource = false;
|
||||||
ISelection sel = mTreeViewerSources.getSelection();
|
ISelection sel = mTreeViewerSources.getSelection();
|
||||||
if (sel instanceof ITreeSelection) {
|
if (sel instanceof ITreeSelection) {
|
||||||
for (Object c : ((ITreeSelection) sel).toList()) {
|
for (Object c : ((ITreeSelection) sel).toList()) {
|
||||||
if (c instanceof RepoSource) {
|
if (c instanceof RepoSource &&
|
||||||
hasSelectedSource = true;
|
((RepoSource) c).isUserSource()) {
|
||||||
|
hasSelectedUserSource = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mAddSiteButton.setEnabled(true);
|
mAddSiteButton.setEnabled(true);
|
||||||
mDeleteSiteButton.setEnabled(hasSelectedSource);
|
mDeleteSiteButton.setEnabled(hasSelectedUserSource);
|
||||||
mRefreshButton.setEnabled(true);
|
mRefreshButton.setEnabled(true);
|
||||||
mInstallSelectedButton.setEnabled(hasCheckedArchive);
|
mInstallSelectedButton.setEnabled(hasCheckedArchive);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ class RepoSourcesAdapter {
|
|||||||
*/
|
*/
|
||||||
public Object[] getChildren(Object parentElement) {
|
public Object[] getChildren(Object parentElement) {
|
||||||
if (parentElement == RepoSourcesAdapter.this) {
|
if (parentElement == RepoSourcesAdapter.this) {
|
||||||
return mUpdaterData.getSources().getSources().toArray();
|
return mUpdaterData.getSources().getSources();
|
||||||
|
|
||||||
} else if (parentElement instanceof RepoSource) {
|
} else if (parentElement instanceof RepoSource) {
|
||||||
final RepoSource source = (RepoSource) parentElement;
|
final RepoSource source = (RepoSource) parentElement;
|
||||||
|
|||||||
@@ -356,8 +356,8 @@ class UpdaterData {
|
|||||||
|
|
||||||
mTaskFactory.start("Refresh Sources",new ITask() {
|
mTaskFactory.start("Refresh Sources",new ITask() {
|
||||||
public void run(ITaskMonitor monitor) {
|
public void run(ITaskMonitor monitor) {
|
||||||
ArrayList<RepoSource> sources = mSources.getSources();
|
RepoSource[] sources = mSources.getSources();
|
||||||
monitor.setProgressMax(sources.size());
|
monitor.setProgressMax(sources.length);
|
||||||
for (RepoSource source : sources) {
|
for (RepoSource source : sources) {
|
||||||
if (forceFetching || source.getPackages() != null) {
|
if (forceFetching || source.getPackages() != null) {
|
||||||
source.load(monitor.createSubMonitor(1), forceHttp);
|
source.load(monitor.createSubMonitor(1), forceHttp);
|
||||||
@@ -406,7 +406,7 @@ class UpdaterData {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Get all the available archives from all loaded sources
|
// Get all the available archives from all loaded sources
|
||||||
ArrayList<RepoSource> remoteSources = getSources().getSources();
|
RepoSource[] remoteSources = getSources().getSources();
|
||||||
|
|
||||||
for (RepoSource remoteSrc : remoteSources) {
|
for (RepoSource remoteSrc : remoteSources) {
|
||||||
Package[] remotePkgs = remoteSrc.getPackages();
|
Package[] remotePkgs = remoteSrc.getPackages();
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ package com.android.sdkuilib.internal.repository;
|
|||||||
import com.android.sdklib.ISdkLog;
|
import com.android.sdklib.ISdkLog;
|
||||||
import com.android.sdklib.SdkConstants;
|
import com.android.sdklib.SdkConstants;
|
||||||
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 com.android.sdkuilib.internal.repository.icons.ImageFactory;
|
import com.android.sdkuilib.internal.repository.icons.ImageFactory;
|
||||||
|
|
||||||
@@ -93,6 +94,8 @@ public class UpdaterWindowImpl {
|
|||||||
display.sleep();
|
display.sleep();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dispose(); //$hide$
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -215,12 +218,18 @@ public class UpdaterWindowImpl {
|
|||||||
displayPage(0);
|
displayPage(0);
|
||||||
mPageList.setSelection(0);
|
mPageList.setSelection(0);
|
||||||
|
|
||||||
// TODO read add-on sources from some file
|
|
||||||
setupSources();
|
setupSources();
|
||||||
initializeSettings();
|
initializeSettings();
|
||||||
mUpdaterData.notifyListeners();
|
mUpdaterData.notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by the main loop when the window has been disposed.
|
||||||
|
*/
|
||||||
|
private void dispose() {
|
||||||
|
mUpdaterData.getSources().saveUserSources();
|
||||||
|
}
|
||||||
|
|
||||||
// --- page switching ---
|
// --- page switching ---
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -304,17 +313,20 @@ public class UpdaterWindowImpl {
|
|||||||
* Used to initialize the sources.
|
* Used to initialize the sources.
|
||||||
*/
|
*/
|
||||||
private void setupSources() {
|
private void setupSources() {
|
||||||
mUpdaterData.getSources().add(
|
RepoSources sources = mUpdaterData.getSources();
|
||||||
new RepoSource(SdkRepository.URL_GOOGLE_SDK_REPO_SITE, false /* addonOnly */));
|
sources.add(new RepoSource(SdkRepository.URL_GOOGLE_SDK_REPO_SITE, false /*userSource*/));
|
||||||
|
|
||||||
String str = System.getenv("TEMP_SDK_URL"); // TODO STOPSHIP temporary remove before shipping
|
String str = System.getenv("TEMP_SDK_URL"); // TODO STOPSHIP temporary remove before shipping
|
||||||
if (str != null) {
|
if (str != null) {
|
||||||
String[] urls = str.split(";");
|
String[] urls = str.split(";");
|
||||||
for (String url : urls) {
|
for (String url : urls) {
|
||||||
mUpdaterData.getSources().add(new RepoSource(url, false /* addonOnly */));
|
sources.add(new RepoSource(url, false /*userSource*/));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load user sources
|
||||||
|
sources.loadUserSources();
|
||||||
|
|
||||||
mRemotePackagesPage.onSdkChange();
|
mRemotePackagesPage.onSdkChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user