blob: b7ebeb40525e8eefbdbe9f613207cb5b15ba1cb7 [file] [log] [blame]
Stuart McCullochde5fbec2008-12-03 12:03:12 +00001/*
2 * $Id: RepositoryImpl.java 44 2007-07-13 20:49:41Z hargrave@us.ibm.com $
3 *
4 * Copyright (c) OSGi Alliance (2002, 2006, 2007). All Rights Reserved.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19package org.osgi.impl.bundle.obr.resource;
20
21import java.io.*;
22import java.net.*;
23import java.util.*;
24import java.util.zip.*;
25
26import org.kxml2.io.KXmlParser;
27import org.osgi.service.obr.*;
28import org.xmlpull.v1.*;
29
30/**
31 * Implements the basic repository. A repository holds a set of resources.
32 *
33 *
34 * @version $Revision: 44 $
35 */
36public class RepositoryImpl implements Repository {
37 transient Set resources = new HashSet();
38 URL url;
39 String date;
40 Set visited = new HashSet();
41 final static Resource[] EMPTY_RESOURCE = new Resource[0];
42 String name = "Untitled";
43 long lastModified;
44 Exception exception;
45 int ranking=0;
46
47 /**
48 * Each repository is identified by a single URL.
49 *
50 * A repository can hold referrals to other repositories. These referred
51 * repositories are included at the point of referall.
52 *
53 * @param url
54 */
55 public RepositoryImpl(URL url) {
56 this.url = url;
57 }
58
59 /**
60 * Refresh the repository from the URL.
61 *
62 * @throws Exception
63 */
64 public boolean refresh() {
65 exception = null;
66 try {
67 resources.clear();
68 parseDocument(url);
69 visited = null;
70 return true;
71 }
72 catch (Exception e) {
73 e.printStackTrace();
74 exception = e;
75 }
76 return false;
77 }
78
79 /**
80 * Parse the repository.
81 *
82 * @param parser
83 * @throws Exception
84 */
85 private void parseRepository(XmlPullParser parser) throws Exception {
86 try {
87 parser.require(XmlPullParser.START_DOCUMENT, null, null);
88 parser.nextTag();
89 if (parser.getName().equals("bundles"))
90 parseOscar(parser);
91 else {
92 parser.require(XmlPullParser.START_TAG, null, "repository");
93 date = parser.getAttributeValue(null, "lastmodified");
94 name = parser.getAttributeValue(null, "name");
95 if (name == null)
96 name = "Untitled";
97
98 while (parser.nextTag() == XmlPullParser.START_TAG) {
99 if (parser.getName().equals("resource")) {
100 ResourceImpl resource = new ResourceImpl(this, parser);
101 resources.add(resource);
102 }
103 else if (parser.getName().equals("referral"))
104 referral(parser);
105 else
106 throw new IllegalArgumentException(
107 "Invalid tag in repository: " + url + " "
108 + parser.getName());
109 }
110 parser.require(XmlPullParser.END_TAG, null, "repository");
111 }
112 }
113 catch (XmlPullParserException e) {
114 e.printStackTrace();
115 throw new IllegalArgumentException("XML unregognized around: "
116 + e.getLineNumber() + " " + e.getMessage());
117 }
118 }
119
120 /**
121 * Parse an old style OBR repository.
122 *
123 * <dtd-version>1.0</dtd-version> <repository> <name>Oscar Bundle
124 * Repository</name> <url>http://oscar-osgi.sourceforge.net/</url>
125 * <date>Fri May 07 16:45:07 CEST 2004</date> <extern-repositories> <!--
126 * Stefano Lenzi (kismet@interfree.it) -->
127 * <url>http://domoware.isti.cnr.it/osgi-obr/niche-osgi-obr.xml</url>
128 * <!--Manuel Palencia (santillan@dit.upm.es) --> <!--
129 * <url>http://jmood.forge.os4os.org/repository.xml</url> --> <!-- Enrique
130 * Rodriguez (erodriguez@apache.org) -->
131 * <url>http://update.cainenable.org/repository.xml</url>
132 * </extern-repositories> </repository> <bundle> <bundle-name>Bundle
133 * Repository</bundle-name> <bundle-description> A bundle repository
134 * service for Oscar. </bundle-description> <bundle-updatelocation>
135 * http://oscar-osgi.sf.net/repo/bundlerepository/bundlerepository.jar
136 * </bundle-updatelocation> <bundle-sourceurl>
137 * http://oscar-osgi.sf.net/repo/bundlerepository/bundlerepository-src.jar
138 * </bundle-sourceurl> <bundle-version>1.1.3</bundle-version>
139 * <bundle-docurl> http://oscar-osgi.sf.net/repo/bundlerepository/
140 * </bundle-docurl> <bundle-category>General</bundle-category>
141 * <import-package package="org.osgi.framework"/> <export-package
142 * package="org.ungoverned.osgi.service.bundlerepository"
143 * specification-version="1.1.0"/> </bundle> *
144 */
145 private void parseOscar(XmlPullParser parser) throws Exception {
146 parser.require(XmlPullParser.START_TAG, null, "bundles");
147 while (true) {
148 int event = parser.next();
149
150 // Error ..
151 if (event == XmlPullParser.TEXT)
152 event = parser.next();
153
154 if (event != XmlPullParser.START_TAG)
155 break;
156
157 ResourceImpl resource = new ResourceImpl(this);
158
159 if (parser.getName().equals("bundle")) {
160 while (parser.nextTag() == XmlPullParser.START_TAG) {
161 String key = parser.getName();
162 if (key.equals("import-package")) {
163 RequirementImpl requirement = new RequirementImpl(
164 "package");
165
166 requirement.setOptional(false);
167 requirement.setMultiple(false);
168
169 String p = parser.getAttributeValue(null, "package");
170 StringBuffer sb = new StringBuffer();
171 sb.append("(&(package=");
172 sb.append(p);
173 sb.append(")");
174 String version = parser.getAttributeValue(null,
175 "specification-version");
176 VersionRange v = new VersionRange("0");
177 if (version != null) {
178 sb.append("(version=");
179 sb.append(v= new VersionRange(version));
180 sb.append(")");
181 }
182 sb.append(")");
183 requirement.setFilter(sb.toString());
184 requirement.setComment("Import-Package: " + p + ";" + v );
185 resource.addRequirement(requirement);
186
187 parser.nextTag();
188 }
189 else if (key.equals("export-package")) {
190 CapabilityImpl capability = new CapabilityImpl(
191 "package");
192 capability.addProperty("package", parser
193 .getAttributeValue(null, "package"));
194 String version = parser.getAttributeValue(null,
195 "specification-version");
196 if (version != null) {
197 capability.addProperty("version", new VersionRange(
198 version));
199 }
200 resource.addCapability(capability);
201 parser.nextTag();
202 }
203 else {
204 String value = parser.nextText().trim();
205 if (key.equals("bundle-sourceurl"))
206 resource.setSource(new URL(value));
207 else if (key.equals("bundle-docurl"))
208 resource.setDocumentation(new URL(value));
209 else if (key.equals("bundle-updatelocation"))
210 resource.setURL(new URL(value));
211 else if (key.equals("bundle-description"))
212 resource.setDescription(value);
213 else if (key.equals("bundle-category"))
214 resource.addCategory(value);
215 else if (key.equals("bundle-name")) {
216 resource.setName(value);
217 resource.setPresentationName(value);
218 }
219 else if (key.equals("bundle-version"))
220 resource.setVersion(new VersionRange(value));
221 else {
222 resource.put(key, value);
223 }
224 }
225 }
226 resources.add(resource);
227 parser.require(XmlPullParser.END_TAG, null, "bundle");
228 }
229 else if (parser.getName().equals("repository")) {
230 parser.require(XmlPullParser.START_TAG, null, "repository");
231 while (parser.nextTag() == XmlPullParser.START_TAG) {
232 String tag = parser.getName();
233 if (tag.equals("name")) {
234 String name = parser.nextText();
235 if (this.name == null)
236 this.name = name.trim();
237 }
238 else if (tag.equals("url"))
239 parser.nextText().trim();
240 else if (tag.equals("date"))
241 parser.nextText().trim();
242 else if (tag.equals("extern-repositories")) {
243 parser.require(XmlPullParser.START_TAG, null,
244 "extern-repositories");
245 while (parser.nextTag() == XmlPullParser.START_TAG) {
246 if (parser.getName().equals("url"))
247 parseDocument(new URL(parser.nextText().trim()));
248 else
249 throw new IllegalArgumentException(
250 "Invalid tag in repository while parsing extern repositories: "
251 + url + " " + parser.getName());
252 }
253 parser.require(XmlPullParser.END_TAG, null,
254 "extern-repositories");
255 }
256 else
257 throw new IllegalArgumentException(
258 "Invalid tag in repository: " + url + " "
259 + parser.getName());
260 }
261 parser.require(XmlPullParser.END_TAG, null, "repository");
262 }
263 else if (parser.getName().equals("dtd-version")) {
264 parser.nextText();
265 }
266 else
267 throw new IllegalArgumentException(
268 "Invalid tag in repository: " + url + " "
269 + parser.getName());
270 }
271 parser.require(XmlPullParser.END_TAG, null, "bundles");
272 }
273
274 /**
275 * We have a referral to another repository. Just create another parser and
276 * read it inline.
277 *
278 * @param parser
279 */
280 void referral(XmlPullParser parser) {
281 // TODO handle depth!
282 try {
283 parser.require(XmlPullParser.START_TAG, null, "referral");
284 // String depth = parser.getAttributeValue(null, "depth");
285 String path = parser.getAttributeValue(null, "url");
286 URL url = new URL(this.url, path);
287 parseDocument(url);
288 parser.next();
289 parser.require(XmlPullParser.END_TAG, null, "referral");
290 }
291 catch (Exception e) {
292 e.printStackTrace();
293 }
294 }
295
296 /**
297 * Parse a repository document.
298 *
299 * @param url
300 * @throws IOException
301 * @throws XmlPullParserException
302 * @throws Exception
303 */
304 void parseDocument(URL url) throws IOException, XmlPullParserException,
305 Exception {
306 if (!visited.contains(url)) {
307 visited.add(url);
308 try {
309 System.out.println("Visiting: " + url);
310 InputStream in = null;
311
312 if ( url.getPath().endsWith(".zip")) {
313 ZipInputStream zin = new ZipInputStream( url.openStream() );
314 ZipEntry entry = zin.getNextEntry();
315 while ( entry != null ) {
316 if ( entry.getName().equals("repository.xml")) {
317 in = zin;
318 break;
319 }
320 entry = zin.getNextEntry();
321 }
322 } else {
323 in = url.openStream();
324 }
325 Reader reader = new InputStreamReader(in);
326 XmlPullParser parser = new KXmlParser();
327 parser.setInput(reader);
328 parseRepository(parser);
329 } catch( MalformedURLException e ) {
330 System.out.println("Cannot create connection to url");
331 }
332 }
333 }
334
335 public URL getURL() {
336 return url;
337 }
338
339 /**
340 * @return
341 */
342 public Collection getResourceList() {
343 return resources;
344 }
345
346 public Resource[] getResources() {
347 return (Resource[]) getResourceList().toArray(EMPTY_RESOURCE);
348 }
349
350 public String getName() {
351 return name;
352 }
353
354 public Resource getResource(String id) {
355 for (Iterator i = getResourceList().iterator(); i.hasNext();) {
356 ResourceImpl resource = (ResourceImpl) i.next();
357 if (resource.getId().equals(id))
358 return resource;
359 }
360 return null;
361 }
362
363 public long getLastModified() {
364 return lastModified;
365 }
366
367 public int getRanking() {
368 return ranking;
369 }
370
371 public void setRanking(int ranking) {
372 this.ranking = ranking;
373 }
374
375}