| /******************************************************************************* |
| * Copyright (c) 2010 The Eclipse Foundation and others. |
| * 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 |
| * |
| * Contributors: |
| * Yatta Solutions - initial API and implementation, public API (bug 432803) |
| *******************************************************************************/ |
| package org.eclipse.epp.internal.mpc.ui.wizards; |
| |
| import java.io.UnsupportedEncodingException; |
| import java.lang.reflect.InvocationTargetException; |
| import java.net.URI; |
| import java.net.URISyntaxException; |
| import java.net.URLDecoder; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.epp.internal.mpc.core.MarketplaceClientCore; |
| import org.eclipse.epp.internal.mpc.ui.MarketplaceClientUi; |
| import org.eclipse.epp.internal.mpc.ui.catalog.MarketplaceCategory; |
| import org.eclipse.epp.internal.mpc.ui.wizards.MarketplaceViewer.ContentType; |
| import org.eclipse.epp.mpc.core.model.ICategory; |
| import org.eclipse.epp.mpc.core.model.IMarket; |
| import org.eclipse.epp.mpc.core.model.INode; |
| import org.eclipse.epp.mpc.ui.CatalogDescriptor; |
| import org.eclipse.epp.mpc.ui.Operation; |
| import org.eclipse.equinox.internal.p2.discovery.model.CatalogCategory; |
| import org.eclipse.jface.operation.IRunnableWithProgress; |
| import org.eclipse.jface.viewers.StructuredSelection; |
| import org.eclipse.jface.wizard.IWizardPage; |
| import org.eclipse.swt.SWTException; |
| import org.eclipse.swt.browser.LocationEvent; |
| import org.eclipse.swt.browser.LocationListener; |
| import org.eclipse.swt.browser.ProgressEvent; |
| import org.eclipse.swt.browser.ProgressListener; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.ui.statushandlers.StatusManager; |
| |
| /** |
| * @author Carsten Reckord |
| */ |
| public class NewsUrlHandler extends MarketplaceUrlHandler implements LocationListener, ProgressListener { |
| |
| private final Set<String> documentLinks = new HashSet<String>(); |
| |
| private final NewsViewer viewer; |
| |
| public NewsUrlHandler(NewsViewer viewer) { |
| this.viewer = viewer; |
| } |
| |
| public void changed(LocationEvent event) { |
| updatePageLinks(); |
| } |
| |
| private void updatePageLinks() { |
| viewer.getControl().getDisplay().asyncExec(new Runnable() { |
| |
| public void run() { |
| // Links should open in external browser. |
| // Since explicit HREF targets interfere with that, |
| // we'll just remove them. |
| Object[] links = null; |
| try { |
| links = (Object[]) viewer.getBrowser().evaluate( // |
| "return (function() {" + //$NON-NLS-1$ |
| " var links = document.links;" + //$NON-NLS-1$ |
| " var hrefs = Array();" + //$NON-NLS-1$ |
| " for (var i=0; i<links.length; i++) {" + //$NON-NLS-1$ |
| " links[i].target='_self';" + //$NON-NLS-1$ |
| " hrefs[i]=links[i].href;" + //$NON-NLS-1$ |
| " };" + //$NON-NLS-1$ |
| " return hrefs;" + //$NON-NLS-1$ |
| "})();"); //$NON-NLS-1$ |
| } catch (SWTException ex) { |
| MarketplaceClientUi.log(IStatus.WARNING, |
| "Failed to process link targets on news page. Some links might not open in external browser.", //$NON-NLS-1$ |
| ex); |
| documentLinks.clear(); |
| } |
| // Remember document links for navigation handling since we |
| // don't want to deal with URLs from dynamic loading events |
| if (links != null) { |
| documentLinks.clear(); |
| for (Object link : links) { |
| documentLinks.add(link.toString()); |
| } |
| } |
| } |
| |
| }); |
| } |
| |
| public void changing(LocationEvent event) { |
| if (!event.doit) { |
| return; |
| } |
| String newLocation = event.location; |
| boolean handled = handleUri(newLocation); |
| if (handled) { |
| event.doit = false; |
| } else { |
| String currentLocation = viewer.getBrowser().getUrl(); |
| if (isNavigation(currentLocation, newLocation)) { |
| event.doit = false; |
| viewer.getWizard().openUrl(newLocation); |
| } |
| } |
| } |
| |
| private boolean isNavigation(String currentLocation, String newLocation) { |
| if (eq(currentLocation, newLocation) || newLocation.startsWith("javascript:") || //$NON-NLS-1$ |
| "about:blank".equals(newLocation) || "about:blank".equals(currentLocation)) { //$NON-NLS-1$//$NON-NLS-2$ |
| return false; |
| } |
| if (!documentLinks.isEmpty() && !documentLinks.contains(newLocation)) { |
| return false; |
| } |
| return !isSameLocation(currentLocation, newLocation); |
| } |
| |
| static boolean isSameLocation(String currentLocation, String newLocation) { |
| try { |
| URI currentUri = new URI(currentLocation); |
| URI newUri = new URI(newLocation); |
| return equalsHostAndPath(currentUri, newUri); |
| } catch (URISyntaxException e) { |
| return false; |
| } |
| } |
| |
| static boolean equalsHostAndPath(URI currentLocation, URI newLocation) { |
| return eq(currentLocation.getHost(), newLocation.getHost()) |
| && equalsIgnoreTrailingSlash(currentLocation.getPath(), newLocation.getPath()); |
| } |
| |
| static boolean equalsIgnoreTrailingSlash(String path1, String path2) { |
| if (path1.endsWith("/") && !path2.endsWith("/")) { //$NON-NLS-1$//$NON-NLS-2$ |
| path1 = path1.substring(0, path1.length() - 1); |
| } else if (!path1.endsWith("/") && path2.endsWith("/")) { //$NON-NLS-1$ //$NON-NLS-2$ |
| path2 = path2.substring(0, path2.length() - 1); |
| } |
| return eq(path1, path2); |
| } |
| |
| static boolean eq(String s1, String s2) { |
| return s1 == s2 || (s1 != null && s1.equals(s2)); |
| } |
| |
| @Override |
| protected boolean handleSearch(CatalogDescriptor descriptor, String url, String searchString, |
| Map<String, String> params) { |
| MarketplaceWizard marketplaceWizard = viewer.getWizard(); |
| |
| String filterParam = params.get("filter"); //$NON-NLS-1$ |
| String[] filters = filterParam.split(" "); //$NON-NLS-1$ |
| ICategory searchCategory = null; |
| IMarket searchMarket = null; |
| for (String filter : filters) { |
| if (filter.startsWith("tid:")) { //$NON-NLS-1$ |
| String id = filter.substring("tid:".length()); //$NON-NLS-1$ |
| List<CatalogCategory> catalogCategories = marketplaceWizard.getCatalog().getCategories(); |
| for (CatalogCategory catalogCategory : catalogCategories) { |
| if (catalogCategory instanceof MarketplaceCategory) { |
| MarketplaceCategory marketplaceCategory = (MarketplaceCategory) catalogCategory; |
| List<? extends IMarket> markets = marketplaceCategory.getMarkets(); |
| for (IMarket market : markets) { |
| if (id.equals(market.getId())) { |
| searchMarket = market; |
| } else { |
| final List<? extends ICategory> categories = market.getCategory(); |
| for (ICategory category : categories) { |
| if (id.equals(category.getId())) { |
| searchCategory = category; |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| marketplaceWizard.getCatalogPage().search(descriptor, searchMarket, searchCategory, searchString); |
| return true; |
| } |
| |
| @Override |
| protected boolean handleRecent(CatalogDescriptor descriptor, String url) { |
| viewer.getWizard().getCatalogPage().show(descriptor, MarketplaceViewer.ContentType.RECENT); |
| return true; |
| } |
| |
| @Override |
| protected boolean handlePopular(CatalogDescriptor descriptor, String url) { |
| viewer.getWizard().getCatalogPage().show(descriptor, MarketplaceViewer.ContentType.POPULAR); |
| return true; |
| } |
| |
| @Override |
| protected boolean handleNode(CatalogDescriptor descriptor, String url, INode node) { |
| viewer.getWizard().getCatalogPage().show(descriptor, Collections.singleton(node)); |
| return true; |
| } |
| |
| @Override |
| protected boolean handleInstallRequest(final SolutionInstallationInfo installInfo, String url) { |
| final String installId = installInfo.getInstallId(); |
| if (installId == null) { |
| return false; |
| } |
| final MarketplaceWizard wizard = viewer.getWizard(); |
| try { |
| wizard.getContainer().run(true, true, new IRunnableWithProgress() { |
| |
| public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { |
| Map<String, Operation> nodeIdToOperation = new HashMap<String, Operation>(); |
| try { |
| nodeIdToOperation.put(URLDecoder.decode(installId, UTF_8), Operation.INSTALL); |
| } catch (UnsupportedEncodingException e) { |
| //should be unreachable |
| throw new IllegalStateException(); |
| } |
| |
| final SelectionModel selectionModel = viewer.getWizard().getSelectionModel(); |
| SelectionModelStateSerializer stateSerializer = new SelectionModelStateSerializer( |
| wizard.getCatalog(), selectionModel); |
| stateSerializer.deserialize(installId, nodeIdToOperation, monitor); |
| |
| if (selectionModel.getItemToSelectedOperation().size() > 0) { |
| Display display = wizard.getShell().getDisplay(); |
| if (!display.isDisposed()) { |
| display.asyncExec(new Runnable() { |
| |
| public void run() { |
| MarketplacePage catalogPage = wizard.getCatalogPage(); |
| IWizardPage currentPage = wizard.getContainer().getCurrentPage(); |
| if (catalogPage == currentPage) { |
| catalogPage.getViewer().setSelection( |
| new StructuredSelection(selectionModel.getSelectedCatalogItems() |
| .toArray())); |
| catalogPage.show(installInfo.getCatalogDescriptor(), ContentType.SELECTION); |
| IWizardPage nextPage = catalogPage.getNextPage(); |
| if (nextPage != null && catalogPage.isPageComplete()) { |
| wizard.getContainer().showPage(nextPage); |
| } |
| } |
| } |
| }); |
| } |
| } |
| } |
| }); |
| return true; |
| } catch (InvocationTargetException e) { |
| IStatus status = MarketplaceClientCore.computeStatus(e, Messages.MarketplaceViewer_unexpectedException); |
| MarketplaceClientUi.handle(status, StatusManager.SHOW | StatusManager.BLOCK | StatusManager.LOG); |
| } catch (InterruptedException e) { |
| // action canceled, but this still counts as handled |
| return true; |
| } |
| return false; |
| } |
| |
| public void completed(ProgressEvent event) { |
| updatePageLinks(); |
| } |
| |
| public void changed(ProgressEvent event) { |
| // ignore |
| } |
| } |