Added
Link Here
|
1 |
/* |
2 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
3 |
* |
4 |
* Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. |
5 |
* |
6 |
* The contents of this file are subject to the terms of either the GNU |
7 |
* General Public License Version 2 only ("GPL") or the Common |
8 |
* Development and Distribution License("CDDL") (collectively, the |
9 |
* "License"). You may not use this file except in compliance with the |
10 |
* License. You can obtain a copy of the License at |
11 |
* http://www.netbeans.org/cddl-gplv2.html |
12 |
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the |
13 |
* specific language governing permissions and limitations under the |
14 |
* License. When distributing the software, include this License Header |
15 |
* Notice in each file and include the License file at |
16 |
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this |
17 |
* particular file as subject to the "Classpath" exception as provided |
18 |
* by Sun in the GPL Version 2 section of the License file that |
19 |
* accompanied this code. If applicable, add the following below the |
20 |
* License Header, with the fields enclosed by brackets [] replaced by |
21 |
* your own identifying information: |
22 |
* "Portions Copyrighted [year] [name of copyright owner]" |
23 |
* |
24 |
* Contributor(s): |
25 |
* |
26 |
* The Original Software is NetBeans. The Initial Developer of the Original |
27 |
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2008 Sun |
28 |
* Microsystems, Inc. All Rights Reserved. |
29 |
* |
30 |
* If you wish your version of this file to be governed by only the CDDL |
31 |
* or only the GPL Version 2, indicate your decision by adding |
32 |
* "[Contributor] elects to include this software in this distribution |
33 |
* under the [CDDL or GPL Version 2] license." If you do not indicate a |
34 |
* single choice of license, a recipient has the option to distribute |
35 |
* your version of this file under either the CDDL, the GPL Version 2 or |
36 |
* to extend the choice of license to its licensees as provided above. |
37 |
* However, if you add GPL Version 2 code and therefore, elected the GPL |
38 |
* Version 2 license, then the option applies only if the new code is |
39 |
* made subject to such option by the copyright holder. |
40 |
*/ |
41 |
|
42 |
package org.netbeans.nbbuild; |
43 |
|
44 |
import java.io.BufferedInputStream; |
45 |
import java.io.ByteArrayInputStream; |
46 |
import java.io.IOException; |
47 |
import java.io.InputStream; |
48 |
import java.net.MalformedURLException; |
49 |
import java.net.URI; |
50 |
import java.net.URISyntaxException; |
51 |
import java.net.URL; |
52 |
import java.text.DateFormat; |
53 |
import java.text.ParseException; |
54 |
import java.text.SimpleDateFormat; |
55 |
import java.util.ArrayList; |
56 |
import java.util.Collection; |
57 |
import java.util.HashMap; |
58 |
import java.util.List; |
59 |
import java.util.Map; |
60 |
import java.util.Stack; |
61 |
import java.util.jar.Manifest; |
62 |
import java.util.logging.Level; |
63 |
import java.util.logging.Logger; |
64 |
import java.util.zip.GZIPInputStream; |
65 |
import javax.xml.parsers.SAXParser; |
66 |
import javax.xml.parsers.SAXParserFactory; |
67 |
import org.apache.tools.ant.Project; |
68 |
import org.apache.tools.ant.Task; |
69 |
import org.xml.sax.Attributes; |
70 |
import org.xml.sax.EntityResolver; |
71 |
import org.xml.sax.InputSource; |
72 |
import org.xml.sax.SAXException; |
73 |
import org.xml.sax.SAXParseException; |
74 |
import org.xml.sax.helpers.DefaultHandler; |
75 |
|
76 |
/** |
77 |
* |
78 |
* @author Jiri Rechtacek |
79 |
*/ |
80 |
class AutoUpdateCatalogParser extends DefaultHandler { |
81 |
private final Map<String, ModuleItem> items; |
82 |
private final URL provider; |
83 |
private final EntityResolver entityResolver; |
84 |
private final URI baseUri; |
85 |
|
86 |
private AutoUpdateCatalogParser (Map<String, ModuleItem> items, URL provider, URI base) { |
87 |
this.items = items; |
88 |
this.provider = provider; |
89 |
this.entityResolver = newEntityResolver(); |
90 |
this.baseUri = base; |
91 |
} |
92 |
|
93 |
private EntityResolver newEntityResolver () { |
94 |
return new EntityResolver() { |
95 |
public InputSource resolveEntity(String string, String string1) throws SAXException, IOException { |
96 |
return new InputSource(new ByteArrayInputStream(new byte[0])); |
97 |
} |
98 |
}; |
99 |
} |
100 |
|
101 |
|
102 |
private static final Logger ERR = Logger.getLogger (AutoUpdateCatalogParser.class.getName ()); |
103 |
|
104 |
private static enum ELEMENTS { |
105 |
module_updates, module_group, notification, module, description, |
106 |
module_notification, external_package, manifest, l10n, license |
107 |
} |
108 |
|
109 |
private static final String MODULE_UPDATES_ATTR_TIMESTAMP = "timestamp"; // NOI18N |
110 |
|
111 |
private static final String MODULE_GROUP_ATTR_NAME = "name"; // NOI18N |
112 |
|
113 |
private static final String NOTIFICATION_ATTR_URL = "url"; // NOI18N |
114 |
|
115 |
private static final String LICENSE_ATTR_NAME = "name"; // NOI18N |
116 |
|
117 |
private static final String MODULE_ATTR_CODE_NAME_BASE = "codenamebase"; // NOI18N |
118 |
private static final String MODULE_ATTR_HOMEPAGE = "homepage"; // NOI18N |
119 |
private static final String MODULE_ATTR_DISTRIBUTION = "distribution"; // NOI18N |
120 |
private static final String MODULE_ATTR_DOWNLOAD_SIZE = "downloadsize"; // NOI18N |
121 |
private static final String MODULE_ATTR_NEEDS_RESTART = "needsrestart"; // NOI18N |
122 |
private static final String MODULE_ATTR_MODULE_AUTHOR = "moduleauthor"; // NOI18N |
123 |
private static final String MODULE_ATTR_RELEASE_DATE = "releasedate"; // NOI18N |
124 |
private static final String MODULE_ATTR_IS_GLOBAL = "global"; // NOI18N |
125 |
private static final String MODULE_ATTR_TARGET_CLUSTER = "targetcluster"; // NOI18N |
126 |
private static final String MODULE_ATTR_EAGER = "eager"; // NOI18N |
127 |
private static final String MODULE_ATTR_AUTOLOAD = "autoload"; // NOI18N |
128 |
private static final String MODULE_ATTR_LICENSE = "license"; // NOI18N |
129 |
private static final String LICENSE_ATTR_URL = "url"; // NOI18N |
130 |
|
131 |
private static final String MANIFEST_ATTR_SPECIFICATION_VERSION = "OpenIDE-Module-Specification-Version"; // NOI18N |
132 |
|
133 |
private static final String TIME_STAMP_FORMAT = "ss/mm/hh/dd/MM/yyyy"; // NOI18N |
134 |
|
135 |
private static final String L10N_ATTR_LOCALE = "langcode"; // NOI18N |
136 |
private static final String L10N_ATTR_BRANDING = "brandingcode"; // NOI18N |
137 |
private static final String L10N_ATTR_MODULE_SPECIFICATION = "module_spec_version"; // NOI18N |
138 |
private static final String L10N_ATTR_MODULE_MAJOR_VERSION = "module_major_version"; // NOI18N |
139 |
private static final String L10N_ATTR_LOCALIZED_MODULE_NAME = "OpenIDE-Module-Name"; // NOI18N |
140 |
private static final String L10N_ATTR_LOCALIZED_MODULE_DESCRIPTION = "OpenIDE-Module-Long-Description"; // NOI18N |
141 |
|
142 |
private static String GZIP_EXTENSION = ".gz"; // NOI18N |
143 |
|
144 |
private static Map<String, ModuleItem> cache; |
145 |
private static URI cacheURI; |
146 |
synchronized static Map<String, ModuleItem> getUpdateItems (URL url, URL provider, Task task) { |
147 |
|
148 |
Map<String, ModuleItem> items = new HashMap<String, ModuleItem> (); |
149 |
URI base; |
150 |
try { |
151 |
if (provider != null) { |
152 |
base = provider.toURI(); |
153 |
} else { |
154 |
base = url.toURI(); |
155 |
} |
156 |
if (cache != null && cacheURI.equals(base)) { |
157 |
task.log("Using existing module item cache " + base, Project.MSG_INFO); |
158 |
return cache; |
159 |
} |
160 |
task.log("Downloading " + base, Project.MSG_INFO); |
161 |
InputSource is = null; |
162 |
try { |
163 |
SAXParserFactory factory = SAXParserFactory.newInstance(); |
164 |
factory.setValidating(false); |
165 |
SAXParser saxParser = factory.newSAXParser(); |
166 |
is = getInputSource(url, provider, base); |
167 |
saxParser.parse(is, new AutoUpdateCatalogParser(items, provider, base)); |
168 |
cacheURI = base; |
169 |
cache = items; |
170 |
} catch (Exception ex) { |
171 |
ERR.log(Level.INFO, "Failed to parse " + base, ex); |
172 |
} finally { |
173 |
if (is != null && is.getByteStream() != null) { |
174 |
try { |
175 |
is.getByteStream().close(); |
176 |
} catch (IOException e) { |
177 |
} |
178 |
} |
179 |
} |
180 |
} catch (URISyntaxException ex) { |
181 |
ERR.log(Level.INFO, null, ex); |
182 |
} |
183 |
return items; |
184 |
} |
185 |
|
186 |
private static boolean isGzip (URL url) { |
187 |
boolean res = false; |
188 |
if (url != null) { |
189 |
res = url.getPath ().toLowerCase ().endsWith (GZIP_EXTENSION); |
190 |
ERR.log (Level.FINER, "Is GZIP " + url + " ? " + res); |
191 |
} else { |
192 |
ERR.log (Level.WARNING, "AutoupdateCatalogProvider has not URL."); |
193 |
} |
194 |
return res; |
195 |
} |
196 |
|
197 |
private static InputSource getInputSource(URL toParse, URL p, URI base) { |
198 |
InputStream is = null; |
199 |
try { |
200 |
is = toParse.openStream (); |
201 |
if (isGzip (p)) { |
202 |
try { |
203 |
is = new GZIPInputStream(is); |
204 |
} catch (IOException e) { |
205 |
ERR.log (Level.INFO, |
206 |
"The file at " + toParse + |
207 |
", corresponding to the catalog at " + p + |
208 |
", does not look like the gzip file, trying to parse it as the pure xml" , e); |
209 |
//#150034 |
210 |
// Sometimes the .xml.gz file is downloaded as the pure .xml file due to the strange content-encoding processing |
211 |
is.close(); |
212 |
is = null; |
213 |
is = toParse.openStream(); |
214 |
} |
215 |
} |
216 |
InputSource src = new InputSource(new BufferedInputStream (is)); |
217 |
src.setSystemId(base.toString()); |
218 |
return src; |
219 |
} catch (IOException ex) { |
220 |
if(is != null) { |
221 |
try { |
222 |
is.close(); |
223 |
} catch (IOException e) { |
224 |
} |
225 |
} |
226 |
ERR.log (Level.SEVERE, "Cannot estabilish input stream for " + toParse , ex); |
227 |
return new InputSource(); |
228 |
} |
229 |
} |
230 |
|
231 |
private Stack<String> currentGroup = new Stack<String> (); |
232 |
private String catalogDate; |
233 |
private Stack<ModuleDescriptor> currentModule = new Stack<ModuleDescriptor> (); |
234 |
private Stack<Map <String,String>> currentLicense = new Stack<Map <String,String>> (); |
235 |
private Stack<String> currentNotificationUrl = new Stack<String> (); |
236 |
private List<String> lines = new ArrayList<String> (); |
237 |
private int bufferInitSize = 0; |
238 |
|
239 |
@Override |
240 |
public void characters (char[] ch, int start, int length) throws SAXException { |
241 |
lines.add (new String(ch, start, length)); |
242 |
bufferInitSize += length; |
243 |
} |
244 |
|
245 |
@Override |
246 |
public void endElement (String uri, String localName, String qName) throws SAXException { |
247 |
switch (ELEMENTS.valueOf (qName)) { |
248 |
case module_updates : |
249 |
break; |
250 |
case module_group : |
251 |
assert ! currentGroup.empty () : "Premature end of module_group " + qName; |
252 |
currentGroup.pop (); |
253 |
break; |
254 |
case module : |
255 |
assert ! currentModule.empty () : "Premature end of module " + qName; |
256 |
currentModule.pop (); |
257 |
break; |
258 |
case l10n : |
259 |
break; |
260 |
case manifest : |
261 |
break; |
262 |
case description : |
263 |
ERR.info ("Not supported yet."); |
264 |
break; |
265 |
case notification : |
266 |
// write catalog notification |
267 |
if (this.provider != null && ! lines.isEmpty ()) { |
268 |
StringBuffer sb = new StringBuffer (bufferInitSize); |
269 |
for (String line : lines) { |
270 |
sb.append (line); |
271 |
} |
272 |
String notification = sb.toString (); |
273 |
String notificationUrl = currentNotificationUrl.peek (); |
274 |
if (notificationUrl != null && notificationUrl.length () > 0) { |
275 |
notification += (notification.length () > 0 ? "<br>" : "") + // NOI18N |
276 |
"<a name=\"autoupdate_catalog_parser\" href=\"" + notificationUrl + "\">" + notificationUrl + "</a>"; // NOI18N |
277 |
} else { |
278 |
notification += (notification.length () > 0 ? "<br>" : "") + |
279 |
"<a name=\"autoupdate_catalog_parser\"/>"; // NOI18N |
280 |
} |
281 |
} |
282 |
currentNotificationUrl.pop (); |
283 |
break; |
284 |
case module_notification : |
285 |
// write module notification |
286 |
if (! lines.isEmpty ()) { |
287 |
ModuleDescriptor md = currentModule.peek (); |
288 |
assert md != null : "ModuleDescriptor found for " + provider; |
289 |
StringBuffer buf = new StringBuffer (bufferInitSize); |
290 |
for (String line : lines) { |
291 |
buf.append (line); |
292 |
} |
293 |
md.appendNotification (buf.toString ()); |
294 |
} |
295 |
break; |
296 |
case external_package : |
297 |
ERR.info ("Not supported yet."); |
298 |
break; |
299 |
case license : |
300 |
assert ! currentLicense.empty () : "Premature end of license " + qName; |
301 |
Map <String, String> curLic = currentLicense.peek (); |
302 |
String licenseName = curLic.keySet().iterator().next(); |
303 |
Collection<String> values = curLic.values(); |
304 |
String licenseUrl = (values.size() > 0) ? values.iterator().next() : null; |
305 |
|
306 |
currentLicense.pop (); |
307 |
break; |
308 |
default: |
309 |
ERR.warning ("Unknown element " + qName); |
310 |
} |
311 |
} |
312 |
|
313 |
@Override |
314 |
public void endDocument () throws SAXException { |
315 |
ERR.fine ("End parsing " + (provider == null ? "" : provider) + " at " + System.currentTimeMillis ()); |
316 |
} |
317 |
|
318 |
@Override |
319 |
public void startDocument () throws SAXException { |
320 |
ERR.fine ("Start parsing " + (provider == null ? "" : provider) + " at " + System.currentTimeMillis ()); |
321 |
} |
322 |
|
323 |
@Override |
324 |
public void startElement (String uri, String localName, String qName, Attributes attributes) throws SAXException { |
325 |
lines.clear(); |
326 |
bufferInitSize = 0; |
327 |
switch (ELEMENTS.valueOf (qName)) { |
328 |
case module_updates : |
329 |
try { |
330 |
catalogDate = ""; |
331 |
DateFormat format = new SimpleDateFormat (TIME_STAMP_FORMAT); |
332 |
String timeStamp = attributes.getValue (MODULE_UPDATES_ATTR_TIMESTAMP); |
333 |
if (timeStamp == null) { |
334 |
ERR.info ("No timestamp is presented in " + (this.provider == null ? "" : this.provider)); |
335 |
} else { |
336 |
//catalogDate = Utilities.formatDate (format.parse (timeStamp)); |
337 |
catalogDate = format.parse (timeStamp).toString(); |
338 |
ERR.finer ("Successfully read time " + timeStamp); // NOI18N |
339 |
} |
340 |
} catch (ParseException pe) { |
341 |
ERR.log (Level.INFO, null, pe); |
342 |
} |
343 |
break; |
344 |
case module_group : |
345 |
currentGroup.push (attributes.getValue (MODULE_GROUP_ATTR_NAME)); |
346 |
break; |
347 |
case module : |
348 |
ModuleDescriptor md = ModuleDescriptor.getModuleDescriptor ( |
349 |
currentGroup.size () > 0 ? currentGroup.peek () : null, /* group */ |
350 |
baseUri, /* base URI */ |
351 |
this.catalogDate); /* catalog date */ |
352 |
md.appendModuleAttributes (attributes); |
353 |
currentModule.push (md); |
354 |
break; |
355 |
case l10n : |
356 |
// construct l10n |
357 |
// XXX |
358 |
break; |
359 |
case manifest : |
360 |
|
361 |
// construct module |
362 |
ModuleDescriptor desc = currentModule.peek (); |
363 |
desc.appendManifest (attributes); |
364 |
ModuleItem m = desc.createUpdateItem (); |
365 |
|
366 |
// put module into UpdateItems |
367 |
items.put (desc.getId (), m); |
368 |
|
369 |
break; |
370 |
case description : |
371 |
ERR.info ("Not supported yet."); |
372 |
break; |
373 |
case module_notification : |
374 |
break; |
375 |
case notification : |
376 |
currentNotificationUrl.push (attributes.getValue (NOTIFICATION_ATTR_URL)); |
377 |
break; |
378 |
case external_package : |
379 |
ERR.info ("Not supported yet."); |
380 |
break; |
381 |
case license : |
382 |
Map <String, String> map = new HashMap<String,String> (); |
383 |
map.put(attributes.getValue (LICENSE_ATTR_NAME), attributes.getValue (LICENSE_ATTR_URL)); |
384 |
currentLicense.push (map); |
385 |
break; |
386 |
default: |
387 |
ERR.warning ("Unknown element " + qName); |
388 |
} |
389 |
} |
390 |
|
391 |
@Override |
392 |
public void warning(SAXParseException e) throws SAXException { |
393 |
parseError(e); |
394 |
} |
395 |
|
396 |
@Override |
397 |
public void error(SAXParseException e) throws SAXException { |
398 |
parseError(e); |
399 |
} |
400 |
|
401 |
@Override |
402 |
public void fatalError(SAXParseException e) throws SAXException { |
403 |
parseError(e); |
404 |
} |
405 |
|
406 |
private void parseError(SAXParseException e) { |
407 |
ERR.warning(e.getSystemId() + ":" + e.getLineNumber() + ":" + e.getColumnNumber() + ": " + e.getLocalizedMessage()); |
408 |
} |
409 |
|
410 |
@Override |
411 |
public InputSource resolveEntity (String publicId, String systemId) throws IOException, SAXException { |
412 |
return entityResolver.resolveEntity (publicId, systemId); |
413 |
} |
414 |
|
415 |
private static class ModuleDescriptor { |
416 |
private String moduleCodeName; |
417 |
private URL distributionURL; |
418 |
private String targetcluster; |
419 |
private String homepage; |
420 |
private String downloadSize; |
421 |
private String author; |
422 |
private String publishDate; |
423 |
private String notification; |
424 |
|
425 |
private Boolean needsRestart; |
426 |
private Boolean isGlobal; |
427 |
private Boolean isEager; |
428 |
private Boolean isAutoload; |
429 |
|
430 |
private String specVersion; |
431 |
private Manifest mf; |
432 |
|
433 |
private String id; |
434 |
|
435 |
private String group; |
436 |
private URI base; |
437 |
private String catalogDate; |
438 |
|
439 |
private static ModuleDescriptor md = null; |
440 |
|
441 |
private ModuleDescriptor () {} |
442 |
|
443 |
public static ModuleDescriptor getModuleDescriptor (String group, URI base, String catalogDate) { |
444 |
if (md == null) { |
445 |
md = new ModuleDescriptor (); |
446 |
} |
447 |
|
448 |
md.group = group; |
449 |
md.base = base; |
450 |
md.catalogDate = catalogDate; |
451 |
|
452 |
return md; |
453 |
} |
454 |
|
455 |
public void appendModuleAttributes (Attributes module) { |
456 |
moduleCodeName = module.getValue (MODULE_ATTR_CODE_NAME_BASE); |
457 |
distributionURL = getDistribution (module.getValue (MODULE_ATTR_DISTRIBUTION), base); |
458 |
targetcluster = module.getValue (MODULE_ATTR_TARGET_CLUSTER); |
459 |
homepage = module.getValue (MODULE_ATTR_HOMEPAGE); |
460 |
downloadSize = module.getValue (MODULE_ATTR_DOWNLOAD_SIZE); |
461 |
author = module.getValue (MODULE_ATTR_MODULE_AUTHOR); |
462 |
publishDate = module.getValue (MODULE_ATTR_RELEASE_DATE); |
463 |
if (publishDate == null || publishDate.length () == 0) { |
464 |
publishDate = catalogDate; |
465 |
} |
466 |
String needsrestart = module.getValue (MODULE_ATTR_NEEDS_RESTART); |
467 |
String global = module.getValue (MODULE_ATTR_IS_GLOBAL); |
468 |
String eager = module.getValue (MODULE_ATTR_EAGER); |
469 |
String autoload = module.getValue (MODULE_ATTR_AUTOLOAD); |
470 |
|
471 |
needsRestart = needsrestart == null || needsrestart.trim ().length () == 0 ? null : Boolean.valueOf (needsrestart); |
472 |
isGlobal = global == null || global.trim ().length () == 0 ? null : Boolean.valueOf (global); |
473 |
isEager = Boolean.parseBoolean (eager); |
474 |
isAutoload = Boolean.parseBoolean (autoload); |
475 |
|
476 |
String licName = module.getValue (MODULE_ATTR_LICENSE); |
477 |
} |
478 |
|
479 |
public void appendManifest (Attributes manifest) { |
480 |
specVersion = manifest.getValue (MANIFEST_ATTR_SPECIFICATION_VERSION); |
481 |
mf = getManifest (manifest); |
482 |
id = moduleCodeName + '_' + specVersion; // NOI18N |
483 |
} |
484 |
|
485 |
public void appendNotification (String notification) { |
486 |
this.notification = notification; |
487 |
} |
488 |
|
489 |
public String getId () { |
490 |
return id; |
491 |
} |
492 |
|
493 |
public ModuleItem createUpdateItem () { |
494 |
ModuleItem res = ModuleItem.createModule ( |
495 |
moduleCodeName, |
496 |
specVersion, |
497 |
distributionURL, |
498 |
author, |
499 |
downloadSize, |
500 |
homepage, |
501 |
publishDate, |
502 |
group, |
503 |
mf, |
504 |
isEager, |
505 |
isAutoload, |
506 |
needsRestart, |
507 |
isGlobal, |
508 |
targetcluster, |
509 |
null); |
510 |
|
511 |
// clean-up ModuleDescriptor |
512 |
cleanUp (); |
513 |
|
514 |
return res; |
515 |
} |
516 |
|
517 |
private void cleanUp (){ |
518 |
this.specVersion = null; |
519 |
this.mf = null; |
520 |
this.notification = null; |
521 |
} |
522 |
} |
523 |
|
524 |
private static URL getDistribution (String distribution, URI base) { |
525 |
URL retval = null; |
526 |
if (distribution != null && distribution.length () > 0) { |
527 |
try { |
528 |
URI distributionURI = new URI (distribution); |
529 |
if (! distributionURI.isAbsolute ()) { |
530 |
if (base != null) { |
531 |
distributionURI = base.resolve (distributionURI); |
532 |
} |
533 |
} |
534 |
retval = distributionURI.toURL (); |
535 |
} catch (MalformedURLException ex) { |
536 |
ERR.log (Level.INFO, null, ex); |
537 |
} catch (URISyntaxException ex) { |
538 |
ERR.log (Level.INFO, null, ex); |
539 |
} |
540 |
} |
541 |
return retval; |
542 |
} |
543 |
|
544 |
private static Manifest getManifest (Attributes attrList) { |
545 |
Manifest mf = new Manifest (); |
546 |
java.util.jar.Attributes mfAttrs = mf.getMainAttributes (); |
547 |
|
548 |
for (int i = 0; i < attrList.getLength (); i++) { |
549 |
mfAttrs.put (new java.util.jar.Attributes.Name (attrList.getQName (i)), attrList.getValue (i)); |
550 |
} |
551 |
return mf; |
552 |
} |
553 |
|
554 |
public static final class ModuleItem { |
555 |
private final String moduleCodeName; |
556 |
private final String specVersion; |
557 |
private final URL distributionURL; |
558 |
public final String targetcluster; |
559 |
|
560 |
private ModuleItem(String moduleCodeName, String specVersion, URL distributionURL, String targetcluster) { |
561 |
this.moduleCodeName = moduleCodeName; |
562 |
this.specVersion = specVersion; |
563 |
this.distributionURL = distributionURL; |
564 |
this.targetcluster = targetcluster; |
565 |
} |
566 |
|
567 |
|
568 |
|
569 |
static ModuleItem createModule( |
570 |
String moduleCodeName, |
571 |
String specVersion, |
572 |
URL distributionURL, |
573 |
String author, |
574 |
String downloadSize, |
575 |
String homepage, |
576 |
String publishDate, |
577 |
String group, |
578 |
Manifest mf, |
579 |
Boolean eager, |
580 |
Boolean autoload, |
581 |
Boolean needsRestart, |
582 |
Boolean global, |
583 |
String targetcluster, |
584 |
Object object |
585 |
) { |
586 |
return new ModuleItem(moduleCodeName, specVersion, distributionURL, targetcluster); |
587 |
} |
588 |
|
589 |
public String getCodeName() { |
590 |
return moduleCodeName; |
591 |
} |
592 |
|
593 |
String getSpecVersion() { |
594 |
return specVersion; |
595 |
} |
596 |
|
597 |
URL getURL() { |
598 |
return distributionURL; |
599 |
} |
600 |
|
601 |
@Override |
602 |
public String toString() { |
603 |
return "[" + moduleCodeName + "@" + specVersion + "(" + targetcluster + ") <- " + distributionURL + "]"; |
604 |
} |
605 |
|
606 |
boolean isNewerThan(String version) { |
607 |
String[] mine = specVersion.split("\\."); |
608 |
String[] its = version.split("\\."); |
609 |
|
610 |
int min = Math.min(mine.length, its.length); |
611 |
for (int i = 0; i < min; i++) { |
612 |
int m = Integer.parseInt(mine[i]); |
613 |
int it = Integer.parseInt(its[i]); |
614 |
|
615 |
if (m > it) { |
616 |
return true; |
617 |
} |
618 |
if (m < it) { |
619 |
return false; |
620 |
} |
621 |
} |
622 |
return mine.length > its.length; |
623 |
} |
624 |
} |
625 |
} |