| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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.netbeans.modules.autoupdate.updateprovider; |
| |
| import java.io.BufferedInputStream; |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.net.*; |
| import java.text.DateFormat; |
| import java.text.ParseException; |
| import java.text.SimpleDateFormat; |
| import java.util.*; |
| import java.util.jar.Manifest; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| import java.util.zip.GZIPInputStream; |
| import javax.xml.parsers.SAXParser; |
| import javax.xml.parsers.SAXParserFactory; |
| import org.netbeans.Module; |
| import org.netbeans.modules.autoupdate.services.Trampoline; |
| import org.netbeans.modules.autoupdate.services.UpdateLicenseImpl; |
| import org.netbeans.modules.autoupdate.services.Utilities; |
| import org.netbeans.spi.autoupdate.UpdateItem; |
| import org.netbeans.spi.autoupdate.UpdateLicense; |
| import org.xml.sax.*; |
| import org.xml.sax.helpers.DefaultHandler; |
| |
| /** |
| * |
| * @author Jiri Rechtacek |
| */ |
| public class AutoupdateCatalogParser extends DefaultHandler { |
| private final Map<String, UpdateItem> items; |
| private final AutoupdateCatalogProvider provider; |
| private final EntityResolver entityResolver; |
| private final URI baseUri; |
| |
| private AutoupdateCatalogParser (Map<String, UpdateItem> items, AutoupdateCatalogProvider provider, URI base) { |
| this.items = items; |
| this.provider = provider; |
| this.entityResolver = newEntityResolver(); |
| this.baseUri = base; |
| } |
| |
| private EntityResolver newEntityResolver () { |
| try { |
| Class.forName("org.netbeans.updater.XMLUtil"); |
| } catch (ClassNotFoundException e) { |
| final File netbeansHomeFile = new File(System.getProperty("netbeans.home")); |
| final File userdir = new File(System.getProperty("netbeans.user")); |
| |
| final String updaterPath = "modules/ext/updater.jar"; |
| final String newUpdaterPath = "update/new_updater/updater.jar"; |
| |
| final File updaterPlatform = new File(netbeansHomeFile, updaterPath); |
| final File updaterUserdir = new File(userdir, updaterPath); |
| |
| final File newUpdaterPlatform = new File(netbeansHomeFile, newUpdaterPath); |
| final File newUpdaterUserdir = new File(userdir, newUpdaterPath); |
| |
| String message = |
| " org.netbeans.updater.XMLUtil is not accessible\n" + |
| " platform dir = " + netbeansHomeFile.getAbsolutePath() + "\n" + |
| " userdir dir = " + userdir.getAbsolutePath() + "\n" + |
| " updater in platform exist = " + updaterInfo(updaterPlatform) + "\n" + |
| " updater in userdir exist = " + updaterInfo(updaterUserdir) + "\n" + |
| " new updater in platform exist = " + updaterInfo(newUpdaterPlatform) + "\n" + |
| " new updater in userdir exist = " + updaterInfo(newUpdaterUserdir) + "\n"; |
| |
| ERR.log(Level.WARNING, message); |
| } |
| return org.netbeans.updater.XMLUtil.createAUResolver (); |
| } |
| |
| |
| private static final Logger ERR = Logger.getLogger (AutoupdateCatalogParser.class.getName ()); |
| |
| private String updaterInfo(final File updaterLocation) { |
| StringBuilder sb = new StringBuilder(); |
| sb.append(updaterLocation.exists()); |
| if (updaterLocation.exists()) { |
| try { |
| sb.append(", length = ").append(updaterLocation.length()).append(" bytes"); |
| URLClassLoader url = new URLClassLoader(new URL[] { updaterLocation.toURI().toURL() }); |
| sb.append(", loading resource: ").append(url.getResource("org/netbeans/updater/XMLUtil.class")); |
| sb.append(", loading class: ").append(url.loadClass("org.netbeans.updater.XMLUtil")); |
| } catch (Throwable ex) { |
| sb.append(", exception: ").append(ex.getMessage()); |
| } |
| } |
| return sb.toString(); |
| } |
| |
| private static enum ELEMENTS { |
| module_updates, module_group, notification, content_description, module, description, |
| module_notification, external_package, manifest, l10n, license |
| } |
| |
| private static final String MODULE_UPDATES_ATTR_TIMESTAMP = "timestamp"; // NOI18N |
| |
| private static final String MODULE_GROUP_ATTR_NAME = "name"; // NOI18N |
| |
| private static final String NOTIFICATION_ATTR_URL = "url"; // NOI18N |
| private static final String CONTENT_DESCRIPTION_ATTR_URL = "url"; // NOI18N |
| |
| private static final String LICENSE_ATTR_NAME = "name"; // NOI18N |
| |
| private static final String MODULE_ATTR_CODE_NAME_BASE = "codenamebase"; // NOI18N |
| private static final String MODULE_ATTR_HOMEPAGE = "homepage"; // NOI18N |
| private static final String MODULE_ATTR_DISTRIBUTION = "distribution"; // NOI18N |
| private static final String MODULE_ATTR_DOWNLOAD_SIZE = "downloadsize"; // NOI18N |
| private static final String MODULE_ATTR_NEEDS_RESTART = "needsrestart"; // NOI18N |
| private static final String MODULE_ATTR_MODULE_AUTHOR = "moduleauthor"; // NOI18N |
| private static final String MODULE_ATTR_RELEASE_DATE = "releasedate"; // NOI18N |
| private static final String MODULE_ATTR_IS_GLOBAL = "global"; // NOI18N |
| private static final String MODULE_ATTR_IS_PREFERRED_UPDATE = "preferredupdate"; |
| private static final String MODULE_ATTR_TARGET_CLUSTER = "targetcluster"; // NOI18N |
| private static final String MODULE_ATTR_EAGER = "eager"; // NOI18N |
| private static final String MODULE_ATTR_AUTOLOAD = "autoload"; // NOI18N |
| private static final String MODULE_ATTR_LICENSE = "license"; // NOI18N |
| private static final String LICENSE_ATTR_URL = "url"; // NOI18N |
| |
| private static final String MANIFEST_ATTR_SPECIFICATION_VERSION = "OpenIDE-Module-Specification-Version"; // NOI18N |
| private static final String MANIFEST_ATTR_FRAGMENT_HOST = "OpenIDE-Module-Fragment-Host"; // NOI18N |
| |
| private static final String TIME_STAMP_FORMAT = "ss/mm/hh/dd/MM/yyyy"; // NOI18N |
| |
| private static final String L10N_ATTR_LOCALE = "langcode"; // NOI18N |
| private static final String L10N_ATTR_BRANDING = "brandingcode"; // NOI18N |
| private static final String L10N_ATTR_MODULE_SPECIFICATION = "module_spec_version"; // NOI18N |
| private static final String L10N_ATTR_MODULE_MAJOR_VERSION = "module_major_version"; // NOI18N |
| private static final String L10N_ATTR_LOCALIZED_MODULE_NAME = "OpenIDE-Module-Name"; // NOI18N |
| private static final String L10N_ATTR_LOCALIZED_MODULE_DESCRIPTION = "OpenIDE-Module-Long-Description"; // NOI18N |
| |
| private static String GZIP_EXTENSION = ".gz"; // NOI18N |
| private static String XML_EXTENSION = ".xml"; // NOI18N |
| private static String GZIP_MIME_TYPE = "application/x-gzip"; // NOI18N |
| |
| public synchronized static Map<String, UpdateItem> getUpdateItems (URL url, AutoupdateCatalogProvider provider) throws IOException { |
| Map<String, UpdateItem> items = new HashMap<String, UpdateItem> (); |
| URI base; |
| try { |
| if (provider != null) { |
| base = provider.getUpdateCenterURL().toURI(); |
| } else { |
| base = url.toURI(); |
| } |
| InputSource is = null; |
| try { |
| SAXParserFactory factory = SAXParserFactory.newInstance(); |
| factory.setValidating(true); |
| SAXParser saxParser = factory.newSAXParser(); |
| is = getInputSource(url, provider, base); |
| saxParser.parse(is, new AutoupdateCatalogParser(items, provider, base)); |
| } catch (Exception ex) { |
| throw new IOException("Failed to parse " + base, ex); |
| } finally { |
| if (is != null && is.getByteStream() != null) { |
| try { |
| is.getByteStream().close(); |
| } catch (IOException e) { |
| } |
| } |
| } |
| } catch (URISyntaxException ex) { |
| ERR.log(Level.INFO, null, ex); |
| } |
| return items; |
| } |
| |
| private static boolean isGzip (AutoupdateCatalogProvider p) { |
| boolean res = false; |
| if (p != null) { |
| URL url = p.getUpdateCenterURL (); |
| if (url != null) { |
| String path = url.getPath ().toLowerCase (); |
| res = path.endsWith (GZIP_EXTENSION); |
| if (! res) { |
| boolean isXML = path.endsWith (XML_EXTENSION); |
| if (! isXML) { |
| try { |
| URLConnection conn = url.openConnection(); |
| String contentType = conn.getContentType(); |
| res = GZIP_MIME_TYPE.equals(contentType); |
| } catch (IOException ex) { |
| ERR.log (Level.INFO, "Cannot read Content-Type HTTP header, using file extension, cause: ", ex); |
| } |
| } |
| } |
| ERR.log (Level.FINER, "Is GZIP " + url + " ? " + res); |
| } else { |
| ERR.log (Level.WARNING, "AutoupdateCatalogProvider has not URL."); |
| } |
| } |
| return res; |
| } |
| |
| private static InputSource getInputSource(URL toParse, AutoupdateCatalogProvider p, URI base) { |
| InputStream is = null; |
| try { |
| is = toParse.openStream (); |
| if (isGzip (p)) { |
| try { |
| is = new GZIPInputStream(is); |
| } catch (IOException e) { |
| ERR.log (Level.INFO, |
| "The file at " + toParse + |
| ", corresponding to the catalog at " + p.getUpdateCenterURL() + |
| ", does not look like the gzip file, trying to parse it as the pure xml" , e); |
| //#150034 |
| // Sometimes the .xml.gz file is downloaded as the pure .xml file due to the strange content-encoding processing |
| is.close(); |
| is = toParse.openStream(); |
| } |
| } |
| InputSource src = new InputSource(new BufferedInputStream (is)); |
| src.setSystemId(base.toString()); |
| return src; |
| } catch (IOException ex) { |
| if(is != null) { |
| try { |
| is.close(); |
| } catch (IOException e) { |
| } |
| } |
| ERR.log (Level.SEVERE, "Cannot estabilish input stream for {0}", toParse); |
| ERR.log (Level.INFO, "Parsing exception", ex); |
| return new InputSource(); |
| } |
| } |
| |
| private Stack<String> currentGroup = new Stack<String> (); |
| private String catalogDate; |
| private Stack<ModuleDescriptor> currentModule = new Stack<ModuleDescriptor> (); |
| private Stack<Map <String,String>> currentLicense = new Stack<Map <String,String>> (); |
| private Stack<String> currentNotificationUrl = new Stack<String> (); |
| private Stack<String> currentContentDescriptionUrl = new Stack<String>(); |
| private Map<String, UpdateLicenseImpl> name2license = new HashMap<String, UpdateLicenseImpl> (); |
| private List<String> lines = new ArrayList<String> (); |
| private int bufferInitSize = 0; |
| |
| @Override |
| public void characters (char[] ch, int start, int length) throws SAXException { |
| lines.add (new String(ch, start, length)); |
| bufferInitSize += length; |
| } |
| |
| @Override |
| public void endElement (String uri, String localName, String qName) throws SAXException { |
| switch (ELEMENTS.valueOf (qName)) { |
| case module_updates : |
| break; |
| case module_group : |
| assert ! currentGroup.empty () : "Premature end of module_group " + qName; |
| currentGroup.pop (); |
| break; |
| case module : |
| assert ! currentModule.empty () : "Premature end of module " + qName; |
| currentModule.pop (); |
| break; |
| case l10n : |
| break; |
| case manifest : |
| break; |
| case description : |
| ERR.info ("Not supported yet."); |
| break; |
| case notification : |
| // write catalog notification |
| if (this.provider != null && ! lines.isEmpty ()) { |
| StringBuilder sb = new StringBuilder (bufferInitSize); |
| for (String line : lines) { |
| sb.append (line); |
| } |
| String notification = sb.toString (); |
| String notificationUrl = currentNotificationUrl.peek (); |
| if (notificationUrl != null && notificationUrl.length () > 0) { |
| notification += (notification.length () > 0 ? "<br>" : "") + // NOI18N |
| "<a name=\"autoupdate_catalog_parser\" href=\"" + notificationUrl + "\">" + notificationUrl + "</a>"; // NOI18N |
| } else { |
| notification += (notification.length () > 0 ? "<br>" : "") + |
| "<a name=\"autoupdate_catalog_parser\"/>"; // NOI18N |
| } |
| provider.setNotification (notification); |
| } |
| currentNotificationUrl.pop (); |
| break; |
| case content_description : |
| // write content description |
| if (this.provider != null && ! lines.isEmpty ()) { |
| StringBuilder sb = new StringBuilder (bufferInitSize); |
| for (String line : lines) { |
| sb.append (line); |
| } |
| String contentDescription = sb.toString (); |
| String contentDescriptionUrl = currentContentDescriptionUrl.peek (); |
| if (contentDescriptionUrl != null && contentDescriptionUrl.length () > 0) { |
| contentDescription = "<a name=\"update_center_content_description\" href=\"" + // NOI18N |
| contentDescriptionUrl + "\">" + contentDescription + "</a>"; // NOI18N |
| } |
| provider.setContentDescription(contentDescription); |
| } |
| currentContentDescriptionUrl.pop(); |
| break; |
| case module_notification : |
| // write module notification |
| if (! lines.isEmpty ()) { |
| ModuleDescriptor md = currentModule.peek (); |
| assert md != null : "ModuleDescriptor found for " + provider; |
| StringBuilder buf = new StringBuilder (bufferInitSize); |
| for (String line : lines) { |
| buf.append (line); |
| } |
| md.appendNotification (buf.toString ()); |
| } |
| break; |
| case external_package : |
| ERR.info ("Not supported yet."); |
| break; |
| case license : |
| assert ! currentLicense.empty () : "Premature end of license " + qName; |
| Map <String, String> curLic = currentLicense.peek (); |
| String licenseName = curLic.keySet().iterator().next(); |
| Collection<String> values = curLic.values(); |
| String licenseUrl = (values.size() > 0) ? values.iterator().next() : null; |
| UpdateLicenseImpl updateLicenseImpl = this.name2license.get (licenseName); |
| if (updateLicenseImpl == null) { |
| ERR.info("Unpaired license " + licenseName + " without any module."); |
| } else { |
| if (!lines.isEmpty()) { |
| // find and fill UpdateLicenseImpl |
| StringBuilder sb = new StringBuilder(bufferInitSize); |
| for (String line : lines) { |
| sb.append(line); |
| } |
| updateLicenseImpl.setAgreement(sb.toString()); |
| } else if (licenseUrl != null) { |
| updateLicenseImpl.setUrl(getDistribution(licenseUrl, baseUri)); |
| } |
| } |
| |
| currentLicense.pop (); |
| break; |
| default: |
| ERR.warning ("Unknown element " + qName); |
| } |
| } |
| |
| @Override |
| public void endDocument () throws SAXException { |
| ERR.fine ("End parsing " + (provider == null ? "" : provider.getUpdateCenterURL ()) + " at " + System.currentTimeMillis ()); |
| } |
| |
| @Override |
| public void startDocument () throws SAXException { |
| ERR.fine ("Start parsing " + (provider == null ? "" : provider.getUpdateCenterURL ()) + " at " + System.currentTimeMillis ()); |
| } |
| |
| @Override |
| public void startElement (String uri, String localName, String qName, Attributes attributes) throws SAXException { |
| lines.clear(); |
| bufferInitSize = 0; |
| final ELEMENTS elem; |
| try { |
| elem = ELEMENTS.valueOf (qName); |
| } catch (IllegalArgumentException ex) { |
| throw new SAXException("Wrong element " + qName); // NOI18N |
| } |
| switch (elem) { |
| case module_updates : |
| try { |
| catalogDate = ""; |
| DateFormat format = new SimpleDateFormat (TIME_STAMP_FORMAT); |
| String timeStamp = attributes.getValue (MODULE_UPDATES_ATTR_TIMESTAMP); |
| if (timeStamp == null) { |
| ERR.info ("No timestamp is presented in " + (this.provider == null ? "" : this.provider.getUpdateCenterURL ())); |
| } else { |
| catalogDate = Utilities.formatDate (format.parse (timeStamp)); |
| ERR.finer ("Successfully read time " + timeStamp); // NOI18N |
| } |
| } catch (ParseException pe) { |
| ERR.log (Level.INFO, null, pe); |
| } |
| break; |
| case module_group : |
| currentGroup.push (attributes.getValue (MODULE_GROUP_ATTR_NAME)); |
| break; |
| case module : |
| ModuleDescriptor md = ModuleDescriptor.getModuleDescriptor ( |
| currentGroup.size () > 0 ? currentGroup.peek () : null, /* group */ |
| baseUri, /* base URI */ |
| this.catalogDate); /* catalog date */ |
| md.appendModuleAttributes (attributes); |
| currentModule.push (md); |
| break; |
| case l10n : |
| // construct l10n |
| // XXX |
| break; |
| case manifest : |
| |
| // construct module |
| ModuleDescriptor desc = currentModule.peek (); |
| desc.appendManifest (attributes); |
| UpdateItem m = desc.createUpdateItem (); |
| |
| // put license impl to map for future refilling |
| UpdateItemImpl impl = Trampoline.SPI.impl (m); |
| String licName = impl.getUpdateLicenseImpl ().getName (); |
| if (this.name2license.keySet ().contains (licName)) { |
| impl.setUpdateLicenseImpl (this.name2license.get (licName)); |
| } else { |
| this.name2license.put (impl.getUpdateLicenseImpl ().getName (), impl.getUpdateLicenseImpl ()); |
| } |
| |
| // put module into UpdateItems |
| items.put (desc.getId (), m); |
| |
| break; |
| case description : |
| ERR.info ("Not supported yet."); |
| break; |
| case module_notification : |
| break; |
| case notification : |
| currentNotificationUrl.push (attributes.getValue (NOTIFICATION_ATTR_URL)); |
| break; |
| case content_description : |
| currentContentDescriptionUrl.push(attributes.getValue (CONTENT_DESCRIPTION_ATTR_URL)); |
| break; |
| case external_package : |
| ERR.info ("Not supported yet."); |
| break; |
| case license : |
| Map <String, String> map = new HashMap<String,String> (); |
| map.put(attributes.getValue (LICENSE_ATTR_NAME), attributes.getValue (LICENSE_ATTR_URL)); |
| currentLicense.push (map); |
| break; |
| default: |
| ERR.warning ("Unknown element " + qName); |
| } |
| } |
| |
| @Override |
| public void warning(SAXParseException e) throws SAXException { |
| parseError(e); |
| } |
| |
| @Override |
| public void error(SAXParseException e) throws SAXException { |
| parseError(e); |
| } |
| |
| @Override |
| public void fatalError(SAXParseException e) throws SAXException { |
| parseError(e); |
| } |
| |
| private void parseError(SAXParseException e) { |
| ERR.warning(e.getSystemId() + ":" + e.getLineNumber() + ":" + e.getColumnNumber() + ": " + e.getLocalizedMessage()); |
| } |
| |
| @Override |
| public InputSource resolveEntity (String publicId, String systemId) throws IOException, SAXException { |
| return entityResolver.resolveEntity (publicId, systemId); |
| } |
| |
| private static class ModuleDescriptor { |
| private String moduleCodeName; |
| private URL distributionURL; |
| private String targetcluster; |
| private String homepage; |
| private String downloadSize; |
| private String author; |
| private String publishDate; |
| private String notification; |
| |
| private Boolean needsRestart; |
| private Boolean isGlobal; |
| private Boolean isEager; |
| private Boolean isAutoload; |
| private Boolean isPreferredUpdate; |
| |
| private String specVersion; |
| private Manifest mf; |
| |
| private String id; |
| |
| private UpdateLicense lic; |
| |
| private String group; |
| private URI base; |
| private String catalogDate; |
| |
| private String fragmentHost; |
| |
| private static ModuleDescriptor md = null; |
| |
| private ModuleDescriptor () {} |
| |
| public static ModuleDescriptor getModuleDescriptor (String group, URI base, String catalogDate) { |
| if (md == null) { |
| md = new ModuleDescriptor (); |
| } |
| |
| md.group = group; |
| md.base = base; |
| md.catalogDate = catalogDate; |
| |
| return md; |
| } |
| |
| public void appendModuleAttributes (Attributes module) { |
| moduleCodeName = module.getValue (MODULE_ATTR_CODE_NAME_BASE); |
| distributionURL = getDistribution (module.getValue (MODULE_ATTR_DISTRIBUTION), base); |
| targetcluster = module.getValue (MODULE_ATTR_TARGET_CLUSTER); |
| homepage = module.getValue (MODULE_ATTR_HOMEPAGE); |
| downloadSize = module.getValue (MODULE_ATTR_DOWNLOAD_SIZE); |
| author = module.getValue (MODULE_ATTR_MODULE_AUTHOR); |
| publishDate = module.getValue (MODULE_ATTR_RELEASE_DATE); |
| if (publishDate == null || publishDate.length () == 0) { |
| publishDate = catalogDate; |
| } |
| String needsrestart = module.getValue (MODULE_ATTR_NEEDS_RESTART); |
| String global = module.getValue (MODULE_ATTR_IS_GLOBAL); |
| String eager = module.getValue (MODULE_ATTR_EAGER); |
| String autoload = module.getValue (MODULE_ATTR_AUTOLOAD); |
| String preferred = module.getValue(MODULE_ATTR_IS_PREFERRED_UPDATE); |
| |
| needsRestart = needsrestart == null || needsrestart.trim ().length () == 0 ? null : Boolean.valueOf (needsrestart); |
| isGlobal = global == null || global.trim ().length () == 0 ? null : Boolean.valueOf (global); |
| isEager = Boolean.parseBoolean (eager); |
| isAutoload = Boolean.parseBoolean (autoload); |
| isPreferredUpdate = Boolean.parseBoolean(preferred); |
| |
| if (isPreferredUpdate) { |
| Utilities.writeFirstClassModule(moduleCodeName); |
| } |
| |
| String licName = module.getValue (MODULE_ATTR_LICENSE); |
| lic = UpdateLicense.createUpdateLicense (licName, null); |
| } |
| |
| public void appendManifest (Attributes manifest) { |
| specVersion = manifest.getValue (MANIFEST_ATTR_SPECIFICATION_VERSION); |
| fragmentHost = manifest.getValue(MANIFEST_ATTR_FRAGMENT_HOST); |
| if (fragmentHost != null && fragmentHost.isEmpty()) { |
| fragmentHost = null; |
| } |
| mf = getManifest (manifest); |
| id = moduleCodeName + '_' + specVersion; // NOI18N |
| } |
| |
| public void appendNotification (String notification) { |
| this.notification = notification; |
| } |
| |
| public String getId () { |
| return id; |
| } |
| |
| public UpdateItem createUpdateItem () { |
| UpdateItem res = UpdateItem.createModule ( |
| moduleCodeName, |
| specVersion, |
| distributionURL, |
| author, |
| downloadSize, |
| homepage, |
| publishDate, |
| group, |
| mf, |
| isEager, |
| isAutoload, |
| needsRestart, |
| isGlobal, |
| isPreferredUpdate, |
| targetcluster, |
| lic); |
| |
| // read module notification |
| UpdateItemImpl impl = Trampoline.SPI.impl(res); |
| ((ModuleItem) impl).setModuleNotification (notification); |
| if (fragmentHost != null) { |
| ((ModuleItem) impl).setFragmentHost (fragmentHost); |
| } |
| // clean-up ModuleDescriptor |
| cleanUp (); |
| |
| return res; |
| } |
| |
| private void cleanUp (){ |
| this.specVersion = null; |
| this.mf = null; |
| this.notification = null; |
| } |
| } |
| |
| private static URL getDistribution (String distribution, URI base) { |
| URL retval = null; |
| if (distribution != null && distribution.length () > 0) { |
| try { |
| URI distributionURI = new URI (distribution); |
| if (! distributionURI.isAbsolute ()) { |
| if (base != null) { |
| distributionURI = base.resolve (distributionURI); |
| } |
| } |
| retval = distributionURI.toURL (); |
| } catch (MalformedURLException ex) { |
| ERR.log (Level.INFO, null, ex); |
| } catch (URISyntaxException ex) { |
| ERR.log (Level.INFO, null, ex); |
| } |
| } |
| return retval; |
| } |
| |
| private static Manifest getManifest (Attributes attrList) { |
| Manifest mf = new Manifest (); |
| java.util.jar.Attributes mfAttrs = mf.getMainAttributes (); |
| |
| for (int i = 0; i < attrList.getLength (); i++) { |
| mfAttrs.put (new java.util.jar.Attributes.Name (attrList.getQName (i)), attrList.getValue (i)); |
| } |
| return mf; |
| } |
| |
| } |