/*******************************************************************************
* Copyright 2012 Google Inc. All Rights Reserved.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* 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.google.gdt.eclipse.platform.update;
import org.eclipse.core.runtime.ILog;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.equinox.internal.p2.ui.IProvHelpContextIds;
import org.eclipse.equinox.internal.p2.ui.ProvUIActivator;
import org.eclipse.equinox.internal.p2.ui.dialogs.AvailableIUGroup;
import org.eclipse.equinox.internal.p2.ui.dialogs.AvailableIUsPage;
import org.eclipse.equinox.internal.p2.ui.dialogs.InstallWizard;
import org.eclipse.equinox.internal.p2.ui.dialogs.ProvisioningWizardDialog;
import org.eclipse.equinox.internal.p2.ui.dialogs.RepositorySelectionGroup;
import org.eclipse.equinox.internal.p2.ui.sdk.InstallNewSoftwareHandler;
import org.eclipse.equinox.p2.ui.LoadMetadataRepositoryJob;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.PlatformUI;
import java.lang.reflect.Field;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/*
* This is based off of the E35 version, but updated for E42 APIs.
*/
/**
* Opens the P2 install new software wizard with defaults suitable for updating
* for the GWT Eclipse Plugin.
*/
@SuppressWarnings("restriction")
public class UpdateDetailsPresenter implements IUpdateDetailsPresenter {
/**
* Derived from {@link InstallNewSoftwareHandler}.
*/
private static class InstallUpdateHandler extends InstallNewSoftwareHandler {
// These are taken from AvailableIUsPage
private static final String DIALOG_SETTINGS_SECTION = "AvailableIUsPage"; //$NON-NLS-1$
private static final String SHOW_LATEST_VERSIONS_ONLY = "ShowLatestVersionsOnly"; //$NON-NLS-1$
private static final String HIDE_INSTALLED_IUS = "HideInstalledContent"; //$NON-NLS-1$
private static final String RESOLVE_ALL = "ResolveInstallWithAllSites"; //$NON-NLS-1$
private static final String[] SETTINGS_TO_SAVE = {
SHOW_LATEST_VERSIONS_ONLY, HIDE_INSTALLED_IUS, RESOLVE_ALL};
/**
* Opens the wizard dialog.
*/
public static void launch(String updateSiteUrl) throws Exception {
InstallUpdateHandler handler = new InstallUpdateHandler(updateSiteUrl);
handler.execute(null);
}
private final Map<String, Boolean> savedSettingValues = new HashMap<String, Boolean>();
private final String updateSiteUrl;
private InstallUpdateHandler(String updateSiteUrl) {
this.updateSiteUrl = updateSiteUrl;
}
@Override
protected void doExecute(LoadMetadataRepositoryJob job) {
try {
// Save the global settings that we will modify
saveSettings();
// Modify those settings
prepareWizardSettings();
// Boilerplate for opening the wizard
InstallWizard wizard = new InstallWizard(getProvisioningUI(), null,
null, job);
WizardDialog dialog = new ProvisioningWizardDialog(getShell(), wizard);
dialog.create();
PlatformUI.getWorkbench().getHelpSystem().setHelp(dialog.getShell(),
IProvHelpContextIds.INSTALL_WIZARD);
prepareWizard(wizard);
// Open it
dialog.open();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
// Restore the settings which we touched
restoreSettings();
}
}
private AvailableIUGroup findAvailableIuGroup(AvailableIUsPage page)
throws NoSuchFieldException, IllegalAccessException {
Field field = AvailableIUsPage.class.getDeclaredField("availableIUGroup");
field.setAccessible(true);
return (AvailableIUGroup) field.get(page);
}
/**
* Finds the repository for the update site (matching the update site
* value that this plugin was compiled with.)
*/
private URI findRepoUri() throws Exception {
URI updateSiteUri = URI.create(updateSiteUrl);
Path updateSitePath = getPath(updateSiteUri);
URI[] repos = getProvisioningUI().getRepositoryTracker().getKnownRepositories(
getProvisioningUI().getSession());
for (URI repo : repos) {
if (repo != null && repo.getHost() != null
&& repo.getHost().equalsIgnoreCase(updateSiteUri.getHost())
&& getPath(repo).equals(updateSitePath)) {
return repo;
}
}
throw new Exception("Could not find repository (" + updateSiteUrl + ")");
}
private RepositorySelectionGroup findRepositorySelectionGroup(
AvailableIUsPage page) throws NoSuchFieldException,
IllegalAccessException {
Field field = AvailableIUsPage.class.getDeclaredField("repoSelector");
field.setAccessible(true);
return (RepositorySelectionGroup) field.get(page);
}
private IDialogSettings getDialogSettings() {
IDialogSettings settings = ProvUIActivator.getDefault().getDialogSettings();
IDialogSettings section = settings.getSection(DIALOG_SETTINGS_SECTION);
return section;
}
private Path getPath(URI uri) {
String path = uri.getPath();
return new Path(path != null ? path : "");
}
private void prepareWizard(InstallWizard wizard) throws Exception {
AvailableIUsPage page = (AvailableIUsPage) wizard.getPage("AvailableSoftwarePage");
if (page == null) {
throw new Exception(
"Could not find the available software page in the install wizard");
}
RepositorySelectionGroup repoSelector = findRepositorySelectionGroup(page);
repoSelector.setRepositorySelection(AvailableIUGroup.AVAILABLE_SPECIFIED,
findRepoUri());
setCheckedToAvailableUpdates(page);
}
/**
* Sets the "hide installed", "resolve all update sites", and
* "show latest versions only" checkboxes. Ideally, we would provide a
* {@link org.eclipse.equinox.p2.ui.Policy} to the {@link InstallWizard},
* but the P2 implementation gives higher priority to the user settings.
* So, we save the user settings, set them to values suitable for
* updating, show the dialog, and restore the user settings.
*/
private void prepareWizardSettings() {
IDialogSettings section = getDialogSettings();
if (section != null) {
section.put(HIDE_INSTALLED_IUS, true);
section.put(RESOLVE_ALL, true);
section.put(SHOW_LATEST_VERSIONS_ONLY, true);
}
}
private void restoreSettings() {
IDialogSettings section = getDialogSettings();
if (section != null) {
for (String setting : savedSettingValues.keySet()) {
section.put(setting, savedSettingValues.get(setting).booleanValue());
}
}
}
private void saveSettings() {
IDialogSettings section = getDialogSettings();
if (section != null) {
for (String setting : SETTINGS_TO_SAVE) {
savedSettingValues.put(setting, section.getBoolean(setting));
}
}
}
/**
* Places a checkmark next to all the available updates.
*/
private void setCheckedToAvailableUpdates(AvailableIUsPage page)
throws NoSuchFieldException, IllegalAccessException {
AvailableIUGroup group = findAvailableIuGroup(page);
TreeItem[] items = group.getTree().getItems();
List<Object> elements = new ArrayList<Object>();
for (TreeItem item : items) {
elements.add(item.getData());
}
group.setChecked(elements.toArray());
}
}
@Override
public void presentUpdateDetails(Shell shell, String updateSiteUrl, ILog log,
String pluginId) {
try {
InstallUpdateHandler.launch(updateSiteUrl);
} catch (Throwable t) {
// Log, and fallback on dialog
log.log(new Status(IStatus.WARNING, pluginId,
"Could not open install wizard", t));
MessageDialog.openInformation(
shell,
DEFAULT_DIALOG_TITLE,
"An update is available for the GWT Plugin for Eclipse. Go to \"Help > Install New Software\" to install it.");
}
}
}