blob: c349ac71fd49e8677e6e7ffb9c69c84f0bebfe3c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 23.04.2012 Aaron Digulla.
* 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:
* Aaron Digulla - initial API and implementation and/or initial documentation
*******************************************************************************/
package m4e.p2
import groovy.util.Node;
import java.io.File;
import java.net.URL;
import java.util.jar.JarFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class P2RepoLoader {
static final Logger log = LoggerFactory.getLogger( P2RepoLoader )
File workDir
private URL url
void setUrl( URL url ) {
if( !url.path.endsWith( '/' ) ) {
url = new URL( url.toExternalForm() + '/' )
}
this.url = url
}
URL getUrl() {
return url
}
IP2Repo load() {
return load( new Downloader( cacheRoot: new File( workDir, 'p2' ) ) )
}
Downloader downloader
IP2Repo load( Downloader downloader ) {
this.downloader = downloader
File contentXmlFile
try {
def p2indexFile = downloader.download( new URL( url, 'p2.index' ) )
def p2index = new P2Index( p2indexFile )
return loadP2Index( p2index )
} catch( P2DownloadException e ) {
return loadContent()
}
}
IP2Repo loadContent() {
File contentXmlFile
try {
def contentJarFile = downloader.download( new URL( url, 'content.jar' ) )
contentXmlFile = unpackContentJar( contentJarFile )
} catch( P2DownloadException e ) {
try {
contentXmlFile = downloader.download( new URL( url, 'content.xml' ) )
} catch( P2DownloadException e2 ) {
// Last frantic attempt. Example: http://download.eclipse.org/modeling/emft/mwe/updates/releases/helios/compositeContent.xml
return loadCompositeContentXmlFile( 'compositeContent.jar', 'compositeContent.xml' )
}
}
P2Repo repo = new P2Repo( workDir: workDir, url: url )
repo.downloader = downloader
log.debug( 'Parsing {}', contentXmlFile )
def parser = new ContentXmlParser( repo: repo )
parser.parseXml( contentXmlFile )
return repo
}
IP2Repo loadP2Index( P2Index p2index ) {
return loadCompositeContentXmlFile( p2index.contentJarName, p2index.contentXmlName )
}
IP2Repo loadCompositeContentXmlFile( contentJarName, contentXmlName ) {
File contentXmlFile
try {
def contentJarFile = downloader.download( new URL( url, contentJarName ) )
contentXmlFile = unpackContentJar( contentJarFile )
} catch( P2DownloadException e2 ) {
contentXmlFile = downloader.download( new URL( url, contentXmlName ) )
}
P2Repo repo = new P2Repo( workDir: workDir, url: url )
repo.downloader = downloader
log.debug( 'Parsing {}', contentXmlFile )
def parser = new ContentXmlParser( repo: repo )
try {
parser.parseXml( contentXmlFile )
} catch( CompositeRepoException e ) {
return loadCompositeRepo( contentXmlFile )
}
return repo
}
IP2Repo loadCompositeRepo( File compositeContentXmlFile ) {
def doc = new XmlParser().parse( compositeContentXmlFile )
try {
return parse( doc )
} catch( Exception e ) {
throw new P2Exception( "Error parsing ${compositeContentXmlFile}: ${e}", e )
}
}
IP2Repo parse( Node doc ) {
def result = new MergedP2Repo( url: url )
def children = doc.get( 'children' )
for( Node node : children.child ) {
def location = node.'@location'
P2RepoLoader sub = new P2RepoLoader( workDir: workDir, url: new URL( url, location ) )
result.add( sub.load() )
}
return result
}
private File unpackContentJar( File contentJarFile ) {
String name = contentJarFile.name.removeEnd( '.jar' ) + '.xml'
File contentXmlFile = new File( contentJarFile.parentFile, name )
if( contentXmlFile.exists() ) {
if( contentXmlFile.lastModified() >= contentJarFile.lastModified() ) {
return contentXmlFile
}
contentXmlFile.usefulDelete()
}
def jar = new JarFile( contentJarFile )
def entry = jar.getEntry( name )
if( ! entry ) {
throw new P2Exception( "Missing ${name} in ${contentJarFile}" )
}
def input = jar.getInputStream( entry )
input.withStream { it ->
contentXmlFile << it
}
return contentXmlFile
}
}
class CompositeRepoException extends RuntimeException {}