blob: 0dfac5bb2fe56712135a3cf1c9c3149a4165c2b7 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.equinox.internal.p2.artifact.repository.simple;
import java.net.*;
import java.util.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.equinox.internal.p2.artifact.repository.Activator;
import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactRepository;
import org.eclipse.equinox.internal.provisional.p2.core.repository.IRepository;
import org.w3c.dom.*;
/**
* Mirror support class for {@link SimpleArtifactRepository}. This class implements
* mirror support equivalent to update manager. A mirror URL returns an XML document
* containing a list of mirrors, sorted geographically with closer mirrors first.
*/
public class Mirrors {
URI baseURI;
URL[] locations;
private final IArtifactRepository repository;
/**
* Parses the given mirror URL to obtain the list of mirrors. Returns the mirrors,
* or null if mirrors could not be computed.
*
* Originally copied from DefaultSiteParser.getMirrors in org.eclipse.update.core
*/
static URL[] computeMirrors(String mirrorsURL) {
try {
String countryCode = Locale.getDefault().getCountry().toLowerCase();
int timeZone = (new GregorianCalendar()).get(Calendar.ZONE_OFFSET) / (60 * 60 * 1000);
if (mirrorsURL.indexOf('?') != -1) {
mirrorsURL = mirrorsURL + '&';
} else {
mirrorsURL = mirrorsURL + '?';
}
mirrorsURL = mirrorsURL + "countryCode=" + countryCode + "&timeZone=" + timeZone + "&responseType=xml"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document document = builder.parse(mirrorsURL);
if (document == null)
return null;
NodeList mirrorNodes = document.getElementsByTagName("mirror"); //$NON-NLS-1$
URL[] mirrors = new URL[mirrorNodes.getLength()];
for (int i = 0; i < mirrorNodes.getLength(); i++) {
Element mirrorNode = (Element) mirrorNodes.item(i);
String infoURL = mirrorNode.getAttribute("url"); //$NON-NLS-1$
mirrors[i] = new URL(infoURL);
}
return mirrors;
} catch (Exception e) {
// log if absolute url
if (mirrorsURL != null && (mirrorsURL.startsWith("http://") //$NON-NLS-1$
|| mirrorsURL.startsWith("https://") //$NON-NLS-1$
|| mirrorsURL.startsWith("file://") //$NON-NLS-1$
|| mirrorsURL.startsWith("ftp://") //$NON-NLS-1$
|| mirrorsURL.startsWith("jar://"))) //$NON-NLS-1$
log("Error processing mirrors URL: " + mirrorsURL, e); //$NON-NLS-1$
return null;
}
}
private static void log(String message, Throwable exception) {
LogHelper.log(new Status(IStatus.ERROR, Activator.ID, message, exception));
}
public Mirrors(IArtifactRepository repository) {
this.repository = repository;
try {
this.baseURI = repository.getLocation().toURI();
} catch (URISyntaxException e) {
log("Error initializing mirrors for: " + repository.getLocation(), e); //$NON-NLS-1$
}
}
/**
* Returns an equivalent location for the given artifact location in the base
* repository. Always falls back to the given input location in case of failure
* to compute mirrors.
*/
public String getMirrorLocation(String inputLocation) {
URI relativeLocation = null;
try {
relativeLocation = baseURI.relativize(new URI(inputLocation));
} catch (URISyntaxException e) {
log("Unable to make location relative: " + inputLocation, e); //$NON-NLS-1$
}
//if we failed to relativize the location, we can't select a mirror
if (relativeLocation == null || relativeLocation.isAbsolute())
return inputLocation;
URL[] mirrorLocations = getMirrorLocations();
if (mirrorLocations == null)
return inputLocation;
URL selectedMirror = selectMirror(mirrorLocations);
if (selectedMirror == null)
return inputLocation;
try {
return new URL(selectedMirror, relativeLocation.getPath()).toExternalForm();
} catch (MalformedURLException e) {
log("Unable to make location " + inputLocation + " relative to mirror " + selectedMirror.toExternalForm(), e); //$NON-NLS-1$ //$NON-NLS-2$
}
return inputLocation;
}
/**
* Returns the mirror locations for this repository, or <code>null</code> if
* they could not be computed.
*/
private URL[] getMirrorLocations() {
if (locations != null)
return locations;
String mirrorsURL = (String) repository.getProperties().get(IRepository.PROP_MIRRORS_URL);
if (mirrorsURL != null && baseURI != null)
locations = computeMirrors(mirrorsURL);
return locations;
}
/**
* Selects a mirror from the given list of mirrors
*/
private URL selectMirror(URL[] mirrorLocations) {
//TODO mirror weighting and dynamic selection
return mirrorLocations[0];
}
}