| /******************************************************************************* |
| * Copyright (c) 2000, 2010 IBM Corporation and others. |
| * 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: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.update.core.model; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.util.Calendar; |
| import java.util.GregorianCalendar; |
| import java.util.Iterator; |
| import java.util.Locale; |
| import java.util.Stack; |
| import java.util.StringTokenizer; |
| |
| import javax.xml.parsers.DocumentBuilder; |
| import javax.xml.parsers.DocumentBuilderFactory; |
| import javax.xml.parsers.ParserConfigurationException; |
| import javax.xml.parsers.SAXParser; |
| import javax.xml.parsers.SAXParserFactory; |
| |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.MultiStatus; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.update.core.IURLEntry; |
| import org.eclipse.update.core.SiteFeatureReferenceModel; |
| import org.eclipse.update.core.URLEntry; |
| import org.eclipse.update.internal.core.ExtendedSite; |
| import org.eclipse.update.internal.core.Messages; |
| import org.eclipse.update.internal.core.UpdateCore; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.NodeList; |
| import org.xml.sax.Attributes; |
| import org.xml.sax.InputSource; |
| import org.xml.sax.SAXException; |
| import org.xml.sax.SAXParseException; |
| import org.xml.sax.helpers.DefaultHandler; |
| |
| /** |
| * Default site parser. |
| * Parses the site manifest file as defined by the platform. Defers |
| * to a model factory to create the actual concrete model objects. The |
| * update framework supplies two factory implementations: |
| * <ul> |
| * <li>@see org.eclipse.update.core.model.SiteModelFactory |
| * <li>@see org.eclipse.update.core.BaseSiteFactory |
| * </ul> |
| * |
| * <p> |
| * <b>Note:</b> This class/interface is part of an interim API that is still under development and expected to |
| * change significantly before reaching stability. It is being made available at this early stage to solicit feedback |
| * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken |
| * (repeatedly) as the API evolves. |
| * </p> |
| * @since 2.0 |
| * @deprecated The org.eclipse.update component has been replaced by Equinox p2. |
| * This API will be deleted in a future release. See bug 311590 for details. |
| */ |
| public class DefaultSiteParser extends DefaultHandler { |
| |
| private final static SAXParserFactory parserFactory = |
| SAXParserFactory.newInstance(); |
| |
| private SAXParser parser; |
| private SiteModelFactory factory; |
| |
| private MultiStatus status; |
| |
| private boolean DESCRIPTION_SITE_ALREADY_SEEN = false; |
| |
| private static final int STATE_IGNORED_ELEMENT = -1; |
| private static final int STATE_INITIAL = 0; |
| private static final int STATE_SITE = 1; |
| private static final int STATE_FEATURE = 2; |
| private static final int STATE_ARCHIVE = 3; |
| private static final int STATE_CATEGORY = 4; |
| private static final int STATE_CATEGORY_DEF = 5; |
| private static final int STATE_DESCRIPTION_SITE = 6; |
| private static final int STATE_DESCRIPTION_CATEGORY_DEF = 7; |
| private static final String PLUGIN_ID = UpdateCore.getPlugin().getBundle().getSymbolicName(); |
| |
| private static final String SITE = "site"; //$NON-NLS-1$ |
| private static final String FEATURE = "feature"; //$NON-NLS-1$ |
| private static final String ARCHIVE = "archive"; //$NON-NLS-1$ |
| private static final String CATEGORY_DEF = "category-def"; //$NON-NLS-1$ |
| private static final String CATEGORY = "category"; //$NON-NLS-1$ |
| private static final String DESCRIPTION = "description"; //$NON-NLS-1$ |
| private static final String MIRROR = "mirror"; //$NON-NLS-1$ |
| //private static final String ASSOCIATE_SITES = "associateSites"; //$NON-NLS-1$ |
| private static final String ASSOCIATE_SITE = "associateSite"; //$NON-NLS-1$ |
| |
| private static final String DEFAULT_INFO_URL = "index.html"; //$NON-NLS-1$ |
| private static final String FEATURES = "features/"; //$NON-NLS-1$ |
| |
| // Current State Information |
| Stack stateStack = new Stack(); |
| |
| // Current object stack (used to hold the current object we are |
| // populating in this plugin descriptor |
| Stack objectStack = new Stack(); |
| |
| private int currentState; |
| |
| /** |
| * Constructs a site parser. |
| */ |
| public DefaultSiteParser() { |
| super(); |
| try { |
| parserFactory.setNamespaceAware(true); |
| this.parser = parserFactory.newSAXParser(); |
| } catch (ParserConfigurationException e) { |
| UpdateCore.log(e); |
| } catch (SAXException e) { |
| UpdateCore.log(e); |
| } |
| |
| if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_PARSING) |
| debug("Created"); //$NON-NLS-1$ |
| } |
| |
| public void init(SiteModelFactory factory) { |
| // PERF: separate instance creation from parsing |
| this.factory = factory; |
| stateStack = new Stack(); |
| objectStack = new Stack(); |
| status = null; |
| DESCRIPTION_SITE_ALREADY_SEEN = false; |
| } |
| |
| /** |
| * Parses the specified input steam and constructs a site model. |
| * The input stream is not closed as part of this operation. |
| * |
| * @param in input stream |
| * @return site model |
| * @exception SAXException |
| * @exception IOException |
| * @since 2.0 |
| */ |
| public SiteModel parse(InputStream in) throws SAXException, IOException { |
| stateStack.push(Integer.valueOf(STATE_INITIAL)); |
| currentState = ((Integer) stateStack.peek()).intValue(); |
| parser.parse(new InputSource(in), this); |
| if (objectStack.isEmpty()) |
| throw new SAXException(Messages.DefaultSiteParser_NoSiteTag); |
| else { |
| if (objectStack.peek() instanceof SiteModel) { |
| return (SiteModel) objectStack.pop(); |
| } else { |
| String stack = ""; //$NON-NLS-1$ |
| Iterator iter = objectStack.iterator(); |
| while (iter.hasNext()) { |
| stack = stack + iter.next().toString() + "\r\n"; //$NON-NLS-1$ |
| } |
| throw new SAXException(NLS.bind(Messages.DefaultSiteParser_WrongParsingStack, (new String[] { stack }))); |
| } |
| } |
| } |
| |
| /** |
| * Returns all status objects accumulated by the parser. |
| * |
| * @return multi-status containing accumulated status, or <code>null</code>. |
| * @since 2.0 |
| */ |
| public MultiStatus getStatus() { |
| return status; |
| } |
| |
| /** |
| * Handle start of element tags |
| * @see DefaultHandler#startElement(String, String, String, Attributes) |
| * @since 2.0 |
| */ |
| public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { |
| |
| if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_PARSING) { |
| debug("State: " + currentState); //$NON-NLS-1$ |
| debug("Start Element: uri:" + uri + " local Name:" + localName + " qName:" + qName);//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| } |
| |
| switch (currentState) { |
| case STATE_IGNORED_ELEMENT : |
| internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] { localName, getState(currentState) }))); |
| break; |
| case STATE_INITIAL : |
| handleInitialState(localName, attributes); |
| break; |
| |
| case STATE_SITE : |
| handleSiteState(localName, attributes); |
| break; |
| |
| case STATE_FEATURE : |
| handleFeatureState(localName, attributes); |
| break; |
| |
| case STATE_ARCHIVE : |
| handleSiteState(localName, attributes); |
| break; |
| |
| case STATE_CATEGORY : |
| handleCategoryState(localName, attributes); |
| break; |
| |
| case STATE_CATEGORY_DEF : |
| handleCategoryDefState(localName, attributes); |
| break; |
| |
| case STATE_DESCRIPTION_SITE : |
| handleSiteState(localName, attributes); |
| break; |
| |
| case STATE_DESCRIPTION_CATEGORY_DEF : |
| handleSiteState(localName, attributes); |
| break; |
| |
| default : |
| internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownStartState, (new String[] { getState(currentState) }))); |
| break; |
| } |
| int newState = ((Integer) stateStack.peek()).intValue(); |
| if (newState != STATE_IGNORED_ELEMENT) |
| currentState = newState; |
| |
| } |
| |
| /** |
| * Handle end of element tags |
| * @see DefaultHandler#endElement(String, String, String) |
| * @since 2.0 |
| */ |
| public void endElement(String uri, String localName, String qName) { |
| |
| String text = null; |
| URLEntryModel info = null; |
| |
| int state = ((Integer) stateStack.peek()).intValue(); |
| switch (state) { |
| case STATE_IGNORED_ELEMENT : |
| case STATE_ARCHIVE : |
| case STATE_CATEGORY : |
| stateStack.pop(); |
| break; |
| |
| case STATE_INITIAL : |
| internalError(Messages.DefaultSiteParser_ParsingStackBackToInitialState); |
| break; |
| |
| case STATE_SITE : |
| stateStack.pop(); |
| if (objectStack.peek() instanceof String) { |
| text = (String) objectStack.pop(); |
| SiteModel site = (SiteModel) objectStack.peek(); |
| site.getDescriptionModel().setAnnotation(text); |
| } |
| //do not pop the object |
| break; |
| |
| case STATE_FEATURE : |
| stateStack.pop(); |
| objectStack.pop(); |
| break; |
| |
| case STATE_CATEGORY_DEF : |
| stateStack.pop(); |
| if (objectStack.peek() instanceof String) { |
| text = (String) objectStack.pop(); |
| CategoryModel category = (CategoryModel) objectStack.peek(); |
| category.getDescriptionModel().setAnnotation(text); |
| } |
| objectStack.pop(); |
| break; |
| |
| case STATE_DESCRIPTION_SITE : |
| stateStack.pop(); |
| text = ""; //$NON-NLS-1$ |
| while (objectStack.peek() instanceof String) { |
| // add text, preserving at most one space between text fragments |
| String newText = (String) objectStack.pop(); |
| if (trailingSpace(newText) && !leadingSpace(text)) { |
| text = " " + text; //$NON-NLS-1$ |
| } |
| text = newText.trim() + text; |
| if (leadingSpace(newText) && !leadingSpace(text)) { |
| text = " " + text; //$NON-NLS-1$ |
| } |
| } |
| text = text.trim(); |
| |
| info = (URLEntryModel) objectStack.pop(); |
| if (text != null) |
| info.setAnnotation(text); |
| |
| SiteModel siteModel = (SiteModel) objectStack.peek(); |
| // override description. |
| // do not raise error as previous description may be default one |
| // when parsing site tag |
| if (DESCRIPTION_SITE_ALREADY_SEEN) |
| debug(NLS.bind(Messages.DefaultSiteParser_ElementAlreadySet, (new String[] { getState(state) }))); |
| siteModel.setDescriptionModel(info); |
| DESCRIPTION_SITE_ALREADY_SEEN = true; |
| break; |
| |
| case STATE_DESCRIPTION_CATEGORY_DEF : |
| stateStack.pop(); |
| text = ""; //$NON-NLS-1$ |
| while (objectStack.peek() instanceof String) { |
| // add text, preserving at most one space between text fragments |
| String newText = (String) objectStack.pop(); |
| if (trailingSpace(newText) && !leadingSpace(text)) { |
| text = " " + text; //$NON-NLS-1$ |
| } |
| text = newText.trim() + text; |
| if (leadingSpace(newText) && !leadingSpace(text)) { |
| text = " " + text; //$NON-NLS-1$ |
| } |
| } |
| text = text.trim(); |
| |
| info = (URLEntryModel) objectStack.pop(); |
| if (text != null) |
| info.setAnnotation(text); |
| |
| CategoryModel category = (CategoryModel) objectStack.peek(); |
| if (category.getDescriptionModel() != null) |
| internalError(NLS.bind(Messages.DefaultSiteParser_ElementAlreadySet, (new String[] { getState(state), category.getLabel() }))); |
| else |
| category.setDescriptionModel(info); |
| break; |
| |
| default : |
| internalError(NLS.bind(Messages.DefaultSiteParser_UnknownEndState, (new String[] { getState(state) }))); |
| break; |
| } |
| |
| if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_PARSING) |
| debug("End Element:" + uri + ":" + localName + ":" + qName);//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| } |
| |
| /** |
| * Handle character text |
| * @see DefaultHandler#characters(char[], int, int) |
| * @since 2.0 |
| */ |
| public void characters(char[] ch, int start, int length) { |
| String text = new String(ch, start, length); |
| //only push if description |
| int state = ((Integer) stateStack.peek()).intValue(); |
| if (state == STATE_DESCRIPTION_SITE || state == STATE_DESCRIPTION_CATEGORY_DEF) |
| objectStack.push(text); |
| |
| } |
| |
| /** |
| * Handle errors |
| * @see DefaultHandler#error(SAXParseException) |
| * @since 2.0 |
| */ |
| public void error(SAXParseException ex) { |
| logStatus(ex); |
| } |
| |
| /** |
| * Handle fatal errors |
| * @see DefaultHandler#fatalError(SAXParseException) |
| * @exception SAXException |
| * @since 2.0 |
| */ |
| public void fatalError(SAXParseException ex) throws SAXException { |
| logStatus(ex); |
| throw ex; |
| } |
| |
| private void handleInitialState(String elementName, Attributes attributes) throws SAXException { |
| if (elementName.equals(SITE)) { |
| stateStack.push(Integer.valueOf(STATE_SITE)); |
| processSite(attributes); |
| } else { |
| internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] { elementName, getState(currentState) }))); |
| // what we received was not a site.xml, no need to continue |
| throw new SAXException(Messages.DefaultSiteParser_InvalidXMLStream); |
| } |
| |
| } |
| |
| private void handleSiteState(String elementName, Attributes attributes) { |
| if (elementName.equals(DESCRIPTION)) { |
| stateStack.push(Integer.valueOf(STATE_DESCRIPTION_SITE)); |
| processInfo(attributes); |
| } else if (elementName.equals(FEATURE)) { |
| stateStack.push(Integer.valueOf(STATE_FEATURE)); |
| processFeature(attributes); |
| } else if (elementName.equals(ARCHIVE)) { |
| stateStack.push(Integer.valueOf(STATE_ARCHIVE)); |
| processArchive(attributes); |
| } else if (elementName.equals(CATEGORY_DEF)) { |
| stateStack.push(Integer.valueOf(STATE_CATEGORY_DEF)); |
| processCategoryDef(attributes); |
| } else |
| internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] { elementName, getState(currentState) }))); |
| } |
| |
| private void handleFeatureState(String elementName, Attributes attributes) { |
| if (elementName.equals(DESCRIPTION)) { |
| stateStack.push(Integer.valueOf(STATE_DESCRIPTION_SITE)); |
| processInfo(attributes); |
| } else if (elementName.equals(FEATURE)) { |
| stateStack.push(Integer.valueOf(STATE_FEATURE)); |
| processFeature(attributes); |
| } else if (elementName.equals(ARCHIVE)) { |
| stateStack.push(Integer.valueOf(STATE_ARCHIVE)); |
| processArchive(attributes); |
| } else if (elementName.equals(CATEGORY_DEF)) { |
| stateStack.push(Integer.valueOf(STATE_CATEGORY_DEF)); |
| processCategoryDef(attributes); |
| } else if (elementName.equals(CATEGORY)) { |
| stateStack.push(Integer.valueOf(STATE_CATEGORY)); |
| processCategory(attributes); |
| } else |
| internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] { elementName, getState(currentState) }))); |
| } |
| |
| private void handleCategoryDefState(String elementName, Attributes attributes) { |
| if (elementName.equals(FEATURE)) { |
| stateStack.push(Integer.valueOf(STATE_FEATURE)); |
| processFeature(attributes); |
| } else if (elementName.equals(ARCHIVE)) { |
| stateStack.push(Integer.valueOf(STATE_ARCHIVE)); |
| processArchive(attributes); |
| } else if (elementName.equals(CATEGORY_DEF)) { |
| stateStack.push(Integer.valueOf(STATE_CATEGORY_DEF)); |
| processCategoryDef(attributes); |
| } else if (elementName.equals(DESCRIPTION)) { |
| stateStack.push(Integer.valueOf(STATE_DESCRIPTION_CATEGORY_DEF)); |
| processInfo(attributes); |
| } else |
| internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] { elementName, getState(currentState) }))); |
| } |
| |
| private void handleCategoryState(String elementName, Attributes attributes) { |
| if (elementName.equals(DESCRIPTION)) { |
| stateStack.push(Integer.valueOf(STATE_DESCRIPTION_SITE)); |
| processInfo(attributes); |
| } else if (elementName.equals(FEATURE)) { |
| stateStack.push(Integer.valueOf(STATE_FEATURE)); |
| processFeature(attributes); |
| } else if (elementName.equals(ARCHIVE)) { |
| stateStack.push(Integer.valueOf(STATE_ARCHIVE)); |
| processArchive(attributes); |
| } else if (elementName.equals(CATEGORY_DEF)) { |
| stateStack.push(Integer.valueOf(STATE_CATEGORY_DEF)); |
| processCategoryDef(attributes); |
| } else if (elementName.equals(CATEGORY)) { |
| stateStack.push(Integer.valueOf(STATE_CATEGORY)); |
| processCategory(attributes); |
| } else |
| internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] { elementName, getState(currentState) }))); |
| } |
| |
| /* |
| * process site info |
| */ |
| private void processSite(Attributes attributes) throws SAXException { |
| // create site map |
| SiteModel site = factory.createSiteMapModel(); |
| |
| // if URL is specified, it replaces the URL of the site |
| // used to calculate the location of features and archives |
| String siteURL = attributes.getValue("url"); //$NON-NLS-1$ |
| if (siteURL != null && !("".equals(siteURL.trim()))) { //$NON-NLS-1$ |
| if (!siteURL.endsWith("/") && !siteURL.endsWith(File.separator)) { //$NON-NLS-1$ |
| siteURL += "/"; //$NON-NLS-1$ |
| } |
| site.setLocationURLString(siteURL); |
| } |
| |
| // provide default description URL |
| // If <description> is specified, for the site, it takes precedence |
| URLEntryModel description = factory.createURLEntryModel(); |
| description.setURLString(DEFAULT_INFO_URL); |
| site.setDescriptionModel(description); |
| |
| // verify we can parse the site ...if the site has |
| // a different type throw an exception to force reparsing |
| // with the matching parser |
| String type = attributes.getValue("type"); //$NON-NLS-1$ |
| if (!factory.canParseSiteType(type)) { |
| throw new SAXException(new InvalidSiteTypeException(type)); |
| } |
| site.setType(type); |
| |
| // get mirrors, if any |
| String mirrorsURL = attributes.getValue("mirrorsURL"); //$NON-NLS-1$ |
| if (mirrorsURL != null && mirrorsURL.trim().length() > 0) { |
| URLEntryModel[] mirrors = getMirrors(mirrorsURL, factory); |
| if (mirrors != null) |
| site.setMirrorSiteEntryModels(mirrors); |
| else |
| site.setMirrorsURLString(mirrorsURL); |
| } |
| |
| String pack200 = attributes.getValue("pack200"); //$NON-NLS-1$ |
| if(site instanceof ExtendedSite && pack200 != null && new Boolean(pack200).booleanValue()){ |
| ((ExtendedSite) site).setSupportsPack200(true); |
| } |
| |
| if ( (site instanceof ExtendedSite) && (attributes.getValue("digestURL") != null)) { //$NON-NLS-1$ |
| ExtendedSite extendedSite = (ExtendedSite) site; |
| extendedSite.setDigestExist(true); |
| extendedSite.setDigestURL(attributes.getValue("digestURL")); //$NON-NLS-1$ |
| |
| if ( (attributes.getValue("availableLocales") != null) && (!attributes.getValue("availableLocales").trim().equals(""))) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ |
| StringTokenizer locals = new StringTokenizer(attributes.getValue("availableLocales"), ","); //$NON-NLS-1$//$NON-NLS-2$ |
| String[] availableLocals = new String[locals.countTokens()]; |
| int i = 0; |
| while(locals.hasMoreTokens()) { |
| availableLocals[i++] = locals.nextToken(); |
| } |
| extendedSite.setAvailableLocals(availableLocals); |
| } |
| } |
| |
| if ( (site instanceof ExtendedSite) && (attributes.getValue("associateSitesURL") != null)) { //$NON-NLS-1$ |
| IURLEntry[] associateSites = getAssociateSites(attributes.getValue("associateSitesURL"), factory); //$NON-NLS-1$ |
| if (associateSites != null) |
| ((ExtendedSite)site).setAssociateSites(associateSites); |
| else |
| site.setMirrorsURLString(mirrorsURL); |
| } |
| |
| objectStack.push(site); |
| |
| if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_PARSING) |
| debug("End process Site tag: siteURL:" + siteURL + " type:" + type);//$NON-NLS-1$ //$NON-NLS-2$ |
| |
| } |
| |
| /* |
| * process feature info |
| */ |
| private void processFeature(Attributes attributes) { |
| SiteFeatureReferenceModel feature = factory.createFeatureReferenceModel(); |
| |
| // feature location on the site |
| String urlInfo = attributes.getValue("url"); //$NON-NLS-1$ |
| // identifier and version |
| String id = attributes.getValue("id"); //$NON-NLS-1$ |
| String ver = attributes.getValue("version"); //$NON-NLS-1$ |
| |
| boolean noURL = (urlInfo == null || urlInfo.trim().equals("")); //$NON-NLS-1$ |
| boolean noId = (id == null || id.trim().equals("")); //$NON-NLS-1$ |
| boolean noVersion = (ver == null || ver.trim().equals("")); //$NON-NLS-1$ |
| |
| // We need to have id and version, or the url, or both. |
| if (noURL) { |
| if (noId || noVersion) |
| internalError(NLS.bind(Messages.DefaultSiteParser_Missing, (new String[] { "url", getState(currentState) }))); //$NON-NLS-1$ |
| else // default url |
| urlInfo = FEATURES + id + '_' + ver; // |
| } |
| |
| feature.setURLString(urlInfo); |
| |
| String type = attributes.getValue("type"); //$NON-NLS-1$ |
| feature.setType(type); |
| |
| // if one is null, and not the other |
| if (noId ^ noVersion) { |
| String[] values = new String[] { id, ver, getState(currentState)}; |
| UpdateCore.warn(NLS.bind(Messages.DefaultFeatureParser_IdOrVersionInvalid, values)); |
| } else { |
| feature.setFeatureIdentifier(id); |
| feature.setFeatureVersion(ver); |
| } |
| |
| // get label if it exists |
| String label = attributes.getValue("label"); //$NON-NLS-1$ |
| if (label != null) { |
| if ("".equals(label.trim())) //$NON-NLS-1$ |
| label = null; |
| } |
| feature.setLabel(label); |
| |
| // OS |
| String os = attributes.getValue("os"); //$NON-NLS-1$ |
| feature.setOS(os); |
| |
| // WS |
| String ws = attributes.getValue("ws"); //$NON-NLS-1$ |
| feature.setWS(ws); |
| |
| // NL |
| String nl = attributes.getValue("nl"); //$NON-NLS-1$ |
| feature.setNL(nl); |
| |
| // arch |
| String arch = attributes.getValue("arch"); //$NON-NLS-1$ |
| feature.setArch(arch); |
| |
| //patch |
| String patch = attributes.getValue("patch"); //$NON-NLS-1$ |
| feature.setPatch(patch); |
| |
| SiteModel site = (SiteModel) objectStack.peek(); |
| site.addFeatureReferenceModel(feature); |
| feature.setSiteModel(site); |
| |
| objectStack.push(feature); |
| |
| if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_PARSING) |
| debug("End Processing DefaultFeature Tag: url:" + urlInfo + " type:" + type); //$NON-NLS-1$ //$NON-NLS-2$ |
| |
| } |
| |
| /* |
| * process archive info |
| */ |
| private void processArchive(Attributes attributes) { |
| ArchiveReferenceModel archive = factory.createArchiveReferenceModel(); |
| String id = attributes.getValue("path"); //$NON-NLS-1$ |
| if (id == null || id.trim().equals("")) { //$NON-NLS-1$ |
| internalError(NLS.bind(Messages.DefaultSiteParser_Missing, (new String[] { "path", getState(currentState) }))); //$NON-NLS-1$ |
| } |
| |
| archive.setPath(id); |
| |
| String url = attributes.getValue("url"); //$NON-NLS-1$ |
| if (url == null || url.trim().equals("")) { //$NON-NLS-1$ |
| internalError(NLS.bind(Messages.DefaultSiteParser_Missing, (new String[] { "archive", getState(currentState) }))); //$NON-NLS-1$ |
| } else { |
| archive.setURLString(url); |
| |
| SiteModel site = (SiteModel) objectStack.peek(); |
| site.addArchiveReferenceModel(archive); |
| } |
| if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_PARSING) |
| debug("End processing Archive: path:" + id + " url:" + url);//$NON-NLS-1$ //$NON-NLS-2$ |
| |
| } |
| |
| /* |
| * process the Category info |
| */ |
| private void processCategory(Attributes attributes) { |
| String category = attributes.getValue("name"); //$NON-NLS-1$ |
| SiteFeatureReferenceModel feature = (SiteFeatureReferenceModel) objectStack.peek(); |
| feature.addCategoryName(category); |
| |
| if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_PARSING) |
| debug("End processing Category: name:" + category); //$NON-NLS-1$ |
| } |
| |
| /* |
| * process category def info |
| */ |
| private void processCategoryDef(Attributes attributes) { |
| CategoryModel category = factory.createSiteCategoryModel(); |
| String name = attributes.getValue("name"); //$NON-NLS-1$ |
| String label = attributes.getValue("label"); //$NON-NLS-1$ |
| category.setName(name); |
| category.setLabel(label); |
| |
| SiteModel site = (SiteModel) objectStack.peek(); |
| site.addCategoryModel(category); |
| objectStack.push(category); |
| |
| if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_PARSING) |
| debug("End processing CategoryDef: name:" + name + " label:" + label); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| /* |
| * process URL info with element text |
| */ |
| private void processInfo(Attributes attributes) { |
| URLEntryModel inf = factory.createURLEntryModel(); |
| String infoURL = attributes.getValue("url"); //$NON-NLS-1$ |
| inf.setURLString(infoURL); |
| |
| if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_PARSING) |
| debug("Processed Info: url:" + infoURL); //$NON-NLS-1$ |
| |
| objectStack.push(inf); |
| } |
| |
| /* |
| * |
| */ |
| private static void debug(String s) { |
| UpdateCore.debug("DefaultSiteParser" + s); //$NON-NLS-1$ |
| } |
| |
| /* |
| * |
| */ |
| private void logStatus(SAXParseException ex) { |
| String name = ex.getSystemId(); |
| if (name == null) |
| name = ""; //$NON-NLS-1$ |
| else |
| name = name.substring(1 + name.lastIndexOf("/")); //$NON-NLS-1$ |
| |
| String msg; |
| if (name.equals("")) //$NON-NLS-1$ |
| msg = NLS.bind(Messages.DefaultSiteParser_ErrorParsing, (new String[] { ex.getMessage() })); |
| else { |
| String[] values = new String[] { name, Integer.toString(ex.getLineNumber()), Integer.toString(ex.getColumnNumber()), ex.getMessage()}; |
| msg = NLS.bind(Messages.DefaultSiteParser_ErrorlineColumnMessage, values); |
| } |
| error(new Status(IStatus.ERROR, PLUGIN_ID, Platform.PARSE_PROBLEM, msg, ex)); |
| } |
| |
| /* |
| * Handles an error state specified by the status. The collection of all logged status |
| * objects can be accessed using <code>getStatus()</code>. |
| * |
| * @param error a status detailing the error condition |
| */ |
| private void error(IStatus error) { |
| |
| if (status == null) { |
| status = new MultiStatus(PLUGIN_ID, Platform.PARSE_PROBLEM, Messages.DefaultSiteParser_ErrorParsingSite, null); |
| } |
| |
| status.add(error); |
| if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_PARSING) |
| UpdateCore.log(error); |
| } |
| |
| /* |
| * |
| */ |
| private void internalErrorUnknownTag(String msg) { |
| stateStack.push(Integer.valueOf(STATE_IGNORED_ELEMENT)); |
| internalError(msg); |
| } |
| |
| /* |
| * |
| */ |
| private void internalError(String message) { |
| error(new Status(IStatus.ERROR, PLUGIN_ID, IStatus.OK, message, null)); |
| } |
| |
| /* |
| * return the state as String |
| */ |
| private String getState(int state) { |
| |
| switch (state) { |
| case STATE_IGNORED_ELEMENT : |
| return "Ignored"; //$NON-NLS-1$ |
| |
| case STATE_INITIAL : |
| return "Initial"; //$NON-NLS-1$ |
| |
| case STATE_SITE : |
| return "Site"; //$NON-NLS-1$ |
| |
| case STATE_FEATURE : |
| return "Feature"; //$NON-NLS-1$ |
| |
| case STATE_ARCHIVE : |
| return "Archive"; //$NON-NLS-1$ |
| |
| case STATE_CATEGORY : |
| return "Category"; //$NON-NLS-1$ |
| |
| case STATE_CATEGORY_DEF : |
| return "Category Def"; //$NON-NLS-1$ |
| |
| case STATE_DESCRIPTION_CATEGORY_DEF : |
| return "Description / Category Def"; //$NON-NLS-1$ |
| |
| case STATE_DESCRIPTION_SITE : |
| return "Description / Site"; //$NON-NLS-1$ |
| |
| default : |
| return Messages.DefaultSiteParser_UnknownState; |
| } |
| } |
| private boolean leadingSpace(String str) { |
| if (str.length() <= 0) { |
| return false; |
| } |
| return Character.isWhitespace(str.charAt(0)); |
| } |
| private boolean trailingSpace(String str) { |
| if (str.length() <= 0) { |
| return false; |
| } |
| return Character.isWhitespace(str.charAt(str.length() - 1)); |
| } |
| |
| static URLEntryModel[] getMirrors(String mirrorsURL, SiteModelFactory factory) { |
| |
| try { |
| String countryCode = Locale.getDefault().getCountry().toLowerCase(); |
| int timeZone = (new GregorianCalendar()).get(Calendar.ZONE_OFFSET)/(60*60*1000); |
| |
| if (mirrorsURL.indexOf("?") != -1) { //$NON-NLS-1$ |
| mirrorsURL = mirrorsURL + "&"; //$NON-NLS-1$ |
| } else { |
| mirrorsURL = mirrorsURL + "?"; //$NON-NLS-1$ |
| } |
| mirrorsURL = mirrorsURL + "countryCode=" + countryCode + "&timeZone=" + timeZone + "&responseType=xml"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| |
| DocumentBuilderFactory domFactory = |
| DocumentBuilderFactory.newInstance(); |
| DocumentBuilder builder = domFactory.newDocumentBuilder(); |
| Document document = builder.parse(mirrorsURL); |
| if (document == null) |
| return null; |
| NodeList mirrorNodes = document.getElementsByTagName(MIRROR); |
| URLEntryModel[] mirrors = new URLEntryModel[mirrorNodes.getLength()]; |
| for (int i=0; i<mirrorNodes.getLength(); i++) { |
| Element mirrorNode = (Element)mirrorNodes.item(i); |
| mirrors[i] = factory.createURLEntryModel(); |
| String infoURL = mirrorNode.getAttribute("url"); //$NON-NLS-1$ |
| String label = mirrorNode.getAttribute("label"); //$NON-NLS-1$ |
| mirrors[i].setURLString(infoURL); |
| mirrors[i].setAnnotation(label); |
| |
| if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_PARSING) |
| debug("Processed mirror: url:" + infoURL + " label:" + label); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| return mirrors; |
| } |
| catch (Exception e) { |
| // log if absolute url |
| if (mirrorsURL != null && |
| (mirrorsURL.startsWith("http://") //$NON-NLS-1$ |
| || mirrorsURL.startsWith("https://") //$NON-NLS-1$ |
| || mirrorsURL.startsWith("file://") //$NON-NLS-1$ |
| || mirrorsURL.startsWith("ftp://") //$NON-NLS-1$ |
| || mirrorsURL.startsWith("jar://"))) //$NON-NLS-1$ |
| UpdateCore.log(Messages.DefaultSiteParser_mirrors, e); |
| return null; |
| } |
| } |
| |
| private static IURLEntry[] getAssociateSites(String associateSitesURL, SiteModelFactory factory) { |
| |
| try { |
| DocumentBuilderFactory domFactory = |
| DocumentBuilderFactory.newInstance(); |
| DocumentBuilder builder = domFactory.newDocumentBuilder(); |
| Document document = builder.parse(associateSitesURL); |
| if (document == null) |
| return null; |
| NodeList mirrorNodes = document.getElementsByTagName(ASSOCIATE_SITE); |
| URLEntry[] mirrors = new URLEntry[mirrorNodes.getLength()]; |
| for (int i=0; i<mirrorNodes.getLength(); i++) { |
| Element mirrorNode = (Element)mirrorNodes.item(i); |
| mirrors[i] = new URLEntry(); |
| String infoURL = mirrorNode.getAttribute("url"); //$NON-NLS-1$ |
| String label = mirrorNode.getAttribute("label"); //$NON-NLS-1$ |
| mirrors[i].setURLString(infoURL); |
| mirrors[i].setAnnotation(label); |
| |
| if (UpdateCore.DEBUG && UpdateCore.DEBUG_SHOW_PARSING) |
| debug("Processed mirror: url:" + infoURL + " label:" + label); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| return mirrors; |
| } |
| catch (Exception e) { |
| // log if absolute url |
| if (associateSitesURL != null && |
| (associateSitesURL.startsWith("http://") //$NON-NLS-1$ |
| || associateSitesURL.startsWith("https://") //$NON-NLS-1$ |
| || associateSitesURL.startsWith("file://") //$NON-NLS-1$ |
| || associateSitesURL.startsWith("ftp://") //$NON-NLS-1$ |
| || associateSitesURL.startsWith("jar://"))) //$NON-NLS-1$ |
| UpdateCore.log(Messages.DefaultSiteParser_mirrors, e); |
| return null; |
| } |
| } |
| |
| } |