/* | |
* $Id: RepositoryImpl.java 44 2007-07-13 20:49:41Z hargrave@us.ibm.com $ | |
* | |
* Copyright (c) OSGi Alliance (2002, 2006, 2007). All Rights Reserved. | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* 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 org.osgi.impl.bundle.obr.resource; | |
import java.io.*; | |
import java.net.*; | |
import java.util.*; | |
import java.util.zip.*; | |
import org.kxml2.io.KXmlParser; | |
import org.osgi.service.obr.*; | |
import org.xmlpull.v1.*; | |
/** | |
* Implements the basic repository. A repository holds a set of resources. | |
* | |
* | |
* @version $Revision: 44 $ | |
*/ | |
public class RepositoryImpl implements Repository { | |
transient Set resources = new HashSet(); | |
URL url; | |
String date; | |
Set visited = new HashSet(); | |
final static Resource[] EMPTY_RESOURCE = new Resource[0]; | |
String name = "Untitled"; | |
long lastModified; | |
Exception exception; | |
int ranking=0; | |
/** | |
* Each repository is identified by a single URL. | |
* | |
* A repository can hold referrals to other repositories. These referred | |
* repositories are included at the point of referall. | |
* | |
* @param url | |
*/ | |
public RepositoryImpl(URL url) { | |
this.url = url; | |
} | |
/** | |
* Refresh the repository from the URL. | |
* | |
* @throws Exception | |
*/ | |
public boolean refresh() { | |
exception = null; | |
try { | |
resources.clear(); | |
parseDocument(url); | |
visited = null; | |
return true; | |
} | |
catch (Exception e) { | |
e.printStackTrace(); | |
exception = e; | |
} | |
return false; | |
} | |
/** | |
* Parse the repository. | |
* | |
* @param parser | |
* @throws Exception | |
*/ | |
private void parseRepository(XmlPullParser parser) throws Exception { | |
try { | |
parser.require(XmlPullParser.START_DOCUMENT, null, null); | |
parser.nextTag(); | |
if (parser.getName().equals("bundles")) | |
parseOscar(parser); | |
else { | |
parser.require(XmlPullParser.START_TAG, null, "repository"); | |
date = parser.getAttributeValue(null, "lastmodified"); | |
name = parser.getAttributeValue(null, "name"); | |
if (name == null) | |
name = "Untitled"; | |
while (parser.nextTag() == XmlPullParser.START_TAG) { | |
if (parser.getName().equals("resource")) { | |
ResourceImpl resource = new ResourceImpl(this, parser); | |
resources.add(resource); | |
} | |
else if (parser.getName().equals("referral")) | |
referral(parser); | |
else | |
throw new IllegalArgumentException( | |
"Invalid tag in repository: " + url + " " | |
+ parser.getName()); | |
} | |
parser.require(XmlPullParser.END_TAG, null, "repository"); | |
} | |
} | |
catch (XmlPullParserException e) { | |
e.printStackTrace(); | |
throw new IllegalArgumentException("XML unregognized around: " | |
+ e.getLineNumber() + " " + e.getMessage()); | |
} | |
} | |
/** | |
* Parse an old style OBR repository. | |
* | |
* <dtd-version>1.0</dtd-version> <repository> <name>Oscar Bundle | |
* Repository</name> <url>http://oscar-osgi.sourceforge.net/</url> | |
* <date>Fri May 07 16:45:07 CEST 2004</date> <extern-repositories> <!-- | |
* Stefano Lenzi (kismet@interfree.it) --> | |
* <url>http://domoware.isti.cnr.it/osgi-obr/niche-osgi-obr.xml</url> | |
* <!--Manuel Palencia (santillan@dit.upm.es) --> <!-- | |
* <url>http://jmood.forge.os4os.org/repository.xml</url> --> <!-- Enrique | |
* Rodriguez (erodriguez@apache.org) --> | |
* <url>http://update.cainenable.org/repository.xml</url> | |
* </extern-repositories> </repository> <bundle> <bundle-name>Bundle | |
* Repository</bundle-name> <bundle-description> A bundle repository | |
* service for Oscar. </bundle-description> <bundle-updatelocation> | |
* http://oscar-osgi.sf.net/repo/bundlerepository/bundlerepository.jar | |
* </bundle-updatelocation> <bundle-sourceurl> | |
* http://oscar-osgi.sf.net/repo/bundlerepository/bundlerepository-src.jar | |
* </bundle-sourceurl> <bundle-version>1.1.3</bundle-version> | |
* <bundle-docurl> http://oscar-osgi.sf.net/repo/bundlerepository/ | |
* </bundle-docurl> <bundle-category>General</bundle-category> | |
* <import-package package="org.osgi.framework"/> <export-package | |
* package="org.ungoverned.osgi.service.bundlerepository" | |
* specification-version="1.1.0"/> </bundle> * | |
*/ | |
private void parseOscar(XmlPullParser parser) throws Exception { | |
parser.require(XmlPullParser.START_TAG, null, "bundles"); | |
while (true) { | |
int event = parser.next(); | |
// Error .. | |
if (event == XmlPullParser.TEXT) | |
event = parser.next(); | |
if (event != XmlPullParser.START_TAG) | |
break; | |
ResourceImpl resource = new ResourceImpl(this); | |
if (parser.getName().equals("bundle")) { | |
while (parser.nextTag() == XmlPullParser.START_TAG) { | |
String key = parser.getName(); | |
if (key.equals("import-package")) { | |
RequirementImpl requirement = new RequirementImpl( | |
"package"); | |
requirement.setOptional(false); | |
requirement.setMultiple(false); | |
String p = parser.getAttributeValue(null, "package"); | |
StringBuffer sb = new StringBuffer(); | |
sb.append("(&(package="); | |
sb.append(p); | |
sb.append(")"); | |
String version = parser.getAttributeValue(null, | |
"specification-version"); | |
VersionRange v = new VersionRange("0"); | |
if (version != null) { | |
sb.append("(version="); | |
sb.append(v= new VersionRange(version)); | |
sb.append(")"); | |
} | |
sb.append(")"); | |
requirement.setFilter(sb.toString()); | |
requirement.setComment("Import-Package: " + p + ";" + v ); | |
resource.addRequirement(requirement); | |
parser.nextTag(); | |
} | |
else if (key.equals("export-package")) { | |
CapabilityImpl capability = new CapabilityImpl( | |
"package"); | |
capability.addProperty("package", parser | |
.getAttributeValue(null, "package")); | |
String version = parser.getAttributeValue(null, | |
"specification-version"); | |
if (version != null) { | |
capability.addProperty("version", new VersionRange( | |
version)); | |
} | |
resource.addCapability(capability); | |
parser.nextTag(); | |
} | |
else { | |
String value = parser.nextText().trim(); | |
if (key.equals("bundle-sourceurl")) | |
resource.setSource(new URL(value)); | |
else if (key.equals("bundle-docurl")) | |
resource.setDocumentation(new URL(value)); | |
else if (key.equals("bundle-updatelocation")) | |
resource.setURL(new URL(value)); | |
else if (key.equals("bundle-description")) | |
resource.setDescription(value); | |
else if (key.equals("bundle-category")) | |
resource.addCategory(value); | |
else if (key.equals("bundle-name")) { | |
resource.setName(value); | |
resource.setPresentationName(value); | |
} | |
else if (key.equals("bundle-version")) | |
resource.setVersion(new VersionRange(value)); | |
else { | |
resource.put(key, value); | |
} | |
} | |
} | |
resources.add(resource); | |
parser.require(XmlPullParser.END_TAG, null, "bundle"); | |
} | |
else if (parser.getName().equals("repository")) { | |
parser.require(XmlPullParser.START_TAG, null, "repository"); | |
while (parser.nextTag() == XmlPullParser.START_TAG) { | |
String tag = parser.getName(); | |
if (tag.equals("name")) { | |
String name = parser.nextText(); | |
if (this.name == null) | |
this.name = name.trim(); | |
} | |
else if (tag.equals("url")) | |
parser.nextText().trim(); | |
else if (tag.equals("date")) | |
parser.nextText().trim(); | |
else if (tag.equals("extern-repositories")) { | |
parser.require(XmlPullParser.START_TAG, null, | |
"extern-repositories"); | |
while (parser.nextTag() == XmlPullParser.START_TAG) { | |
if (parser.getName().equals("url")) | |
parseDocument(new URL(parser.nextText().trim())); | |
else | |
throw new IllegalArgumentException( | |
"Invalid tag in repository while parsing extern repositories: " | |
+ url + " " + parser.getName()); | |
} | |
parser.require(XmlPullParser.END_TAG, null, | |
"extern-repositories"); | |
} | |
else | |
throw new IllegalArgumentException( | |
"Invalid tag in repository: " + url + " " | |
+ parser.getName()); | |
} | |
parser.require(XmlPullParser.END_TAG, null, "repository"); | |
} | |
else if (parser.getName().equals("dtd-version")) { | |
parser.nextText(); | |
} | |
else | |
throw new IllegalArgumentException( | |
"Invalid tag in repository: " + url + " " | |
+ parser.getName()); | |
} | |
parser.require(XmlPullParser.END_TAG, null, "bundles"); | |
} | |
/** | |
* We have a referral to another repository. Just create another parser and | |
* read it inline. | |
* | |
* @param parser | |
*/ | |
void referral(XmlPullParser parser) { | |
// TODO handle depth! | |
try { | |
parser.require(XmlPullParser.START_TAG, null, "referral"); | |
// String depth = parser.getAttributeValue(null, "depth"); | |
String path = parser.getAttributeValue(null, "url"); | |
URL url = new URL(this.url, path); | |
parseDocument(url); | |
parser.next(); | |
parser.require(XmlPullParser.END_TAG, null, "referral"); | |
} | |
catch (Exception e) { | |
e.printStackTrace(); | |
} | |
} | |
/** | |
* Parse a repository document. | |
* | |
* @param url | |
* @throws IOException | |
* @throws XmlPullParserException | |
* @throws Exception | |
*/ | |
void parseDocument(URL url) throws IOException, XmlPullParserException, | |
Exception { | |
if (!visited.contains(url)) { | |
visited.add(url); | |
try { | |
System.out.println("Visiting: " + url); | |
InputStream in = null; | |
if ( url.getPath().endsWith(".zip")) { | |
ZipInputStream zin = new ZipInputStream( url.openStream() ); | |
ZipEntry entry = zin.getNextEntry(); | |
while ( entry != null ) { | |
if ( entry.getName().equals("repository.xml")) { | |
in = zin; | |
break; | |
} | |
entry = zin.getNextEntry(); | |
} | |
} else { | |
in = url.openStream(); | |
} | |
Reader reader = new InputStreamReader(in); | |
XmlPullParser parser = new KXmlParser(); | |
parser.setInput(reader); | |
parseRepository(parser); | |
} catch( MalformedURLException e ) { | |
System.out.println("Cannot create connection to url"); | |
} | |
} | |
} | |
public URL getURL() { | |
return url; | |
} | |
/** | |
* @return | |
*/ | |
public Collection getResourceList() { | |
return resources; | |
} | |
public Resource[] getResources() { | |
return (Resource[]) getResourceList().toArray(EMPTY_RESOURCE); | |
} | |
public String getName() { | |
return name; | |
} | |
public Resource getResource(String id) { | |
for (Iterator i = getResourceList().iterator(); i.hasNext();) { | |
ResourceImpl resource = (ResourceImpl) i.next(); | |
if (resource.getId().equals(id)) | |
return resource; | |
} | |
return null; | |
} | |
public long getLastModified() { | |
return lastModified; | |
} | |
public int getRanking() { | |
return ranking; | |
} | |
public void setRanking(int ranking) { | |
this.ranking = ranking; | |
} | |
} |