| /******************************************************************************* |
| * Copyright (c) 2000, 2008 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.equinox.internal.p2.metadata.generator.features; |
| |
| import java.io.*; |
| import java.util.*; |
| import javax.xml.parsers.*; |
| import org.eclipse.core.runtime.*; |
| import org.eclipse.equinox.internal.p2.core.helpers.LogHelper; |
| import org.eclipse.equinox.internal.p2.core.helpers.Tracing; |
| import org.eclipse.equinox.internal.p2.metadata.repository.Activator; |
| import org.eclipse.equinox.internal.provisional.p2.metadata.generator.URLEntry; |
| import org.eclipse.osgi.util.NLS; |
| import org.w3c.dom.*; |
| import org.xml.sax.*; |
| import org.xml.sax.helpers.DefaultHandler; |
| |
| /** |
| * Parses a site.xml file. |
| * This class was initially copied from org.eclipse.update.core.model.DefaultSiteParser. |
| */ |
| public class DefaultSiteParser extends DefaultHandler { |
| |
| private static final String ARCHIVE = "archive"; //$NON-NLS-1$ |
| private static final String CATEGORY = "category"; //$NON-NLS-1$ |
| private static final String CATEGORY_DEF = "category-def"; //$NON-NLS-1$ |
| |
| private static final String ASSOCIATE_SITES_URL = "associateSitesURL"; //$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 DESCRIPTION = "description"; //$NON-NLS-1$ |
| private static final String FEATURE = "feature"; //$NON-NLS-1$ |
| private static final String FEATURES = "features/"; //$NON-NLS-1$ |
| private static final String MIRROR = "mirror"; //$NON-NLS-1$ |
| private final static SAXParserFactory parserFactory = SAXParserFactory.newInstance(); |
| private static final String PLUGIN_ID = Activator.ID; |
| private static final String SITE = "site"; //$NON-NLS-1$ |
| |
| 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_CATEGORY_DEF = 7; |
| private static final int STATE_DESCRIPTION_SITE = 6; |
| private static final int STATE_FEATURE = 2; |
| private static final int STATE_IGNORED_ELEMENT = -1; |
| private static final int STATE_INITIAL = 0; |
| private static final int STATE_SITE = 1; |
| |
| private int currentState; |
| |
| private boolean DESCRIPTION_SITE_ALREADY_SEEN = false; |
| // Current object stack (used to hold the current object we are |
| // populating in this plugin descriptor |
| Stack objectStack = new Stack(); |
| |
| private SAXParser parser; |
| |
| // Current State Information |
| Stack stateStack = new Stack(); |
| |
| private MultiStatus status; |
| |
| /* |
| * |
| */ |
| private static void debug(String s) { |
| Tracing.debug("DefaultSiteParser: " + s); //$NON-NLS-1$ |
| } |
| |
| private static URLEntry[] getAssociateSites(String associateSitesURL) { |
| |
| 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].setURL(infoURL); |
| mirrors[i].setAnnotation(label); |
| |
| if (Tracing.DEBUG_GENERATOR_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$ |
| log(Messages.DefaultSiteParser_mirrors, e); |
| return null; |
| } |
| } |
| |
| static URLEntry[] getMirrors(String mirrorsURL) { |
| |
| 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); |
| 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].setURL(infoURL); |
| mirrors[i].setAnnotation(label); |
| |
| if (Tracing.DEBUG_GENERATOR_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$ |
| LogHelper.log(new Status(IStatus.ERROR, Activator.ID, Messages.DefaultSiteParser_mirrors, e)); |
| return null; |
| } |
| } |
| |
| static void log(Exception e) { |
| LogHelper.log(new Status(IStatus.ERROR, Activator.ID, "Internal Error", e)); //$NON-NLS-1$ |
| } |
| |
| static void log(IStatus error) { |
| LogHelper.log(error); |
| } |
| |
| static void log(String message) { |
| LogHelper.log(new Status(IStatus.WARNING, Activator.ID, message, null)); |
| } |
| |
| static void log(String message, Exception e) { |
| LogHelper.log(new Status(IStatus.WARNING, Activator.ID, message, e)); |
| } |
| |
| /** |
| * Constructs a site parser. |
| */ |
| public DefaultSiteParser() { |
| super(); |
| stateStack = new Stack(); |
| objectStack = new Stack(); |
| status = null; |
| DESCRIPTION_SITE_ALREADY_SEEN = false; |
| try { |
| parserFactory.setNamespaceAware(true); |
| this.parser = parserFactory.newSAXParser(); |
| } catch (ParserConfigurationException e) { |
| log(e); |
| } catch (SAXException e) { |
| log(e); |
| } |
| |
| if (Tracing.DEBUG_GENERATOR_PARSING) |
| debug("Created"); //$NON-NLS-1$ |
| } |
| |
| /** |
| * 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 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; |
| URLEntry 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.getDescription().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(); |
| SiteCategory category = (SiteCategory) objectStack.peek(); |
| category.setDescription(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 = (URLEntry) 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.setDescription(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 = (URLEntry) objectStack.pop(); |
| if (text != null) |
| info.setAnnotation(text); |
| |
| SiteCategory category = (SiteCategory) objectStack.peek(); |
| if (category.getDescription() != null) |
| internalError(NLS.bind(Messages.DefaultSiteParser_ElementAlreadySet, (new String[] {getState(state), category.getLabel()}))); |
| else |
| category.setDescription(info.getAnnotation()); |
| break; |
| |
| default : |
| internalError(NLS.bind(Messages.DefaultSiteParser_UnknownEndState, (new String[] {getState(state)}))); |
| break; |
| } |
| |
| if (Tracing.DEBUG_GENERATOR_PARSING) |
| debug("End Element:" + uri + ":" + localName + ":" + qName);//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| } |
| |
| /* |
| * 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, 0, Messages.DefaultSiteParser_ErrorParsingSite, null); |
| } |
| |
| status.add(error); |
| if (Tracing.DEBUG_GENERATOR_PARSING) |
| LogHelper.log(error); |
| } |
| |
| /** |
| * 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; |
| } |
| |
| /* |
| * 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; |
| } |
| } |
| |
| /** |
| * 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; |
| } |
| |
| private void handleCategoryDefState(String elementName, Attributes attributes) { |
| if (elementName.equals(FEATURE)) { |
| stateStack.push(new Integer(STATE_FEATURE)); |
| processFeature(attributes); |
| } else if (elementName.equals(ARCHIVE)) { |
| stateStack.push(new Integer(STATE_ARCHIVE)); |
| processArchive(attributes); |
| } else if (elementName.equals(CATEGORY_DEF)) { |
| stateStack.push(new Integer(STATE_CATEGORY_DEF)); |
| processCategoryDef(attributes); |
| } else if (elementName.equals(DESCRIPTION)) { |
| stateStack.push(new Integer(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(new Integer(STATE_DESCRIPTION_SITE)); |
| processInfo(attributes); |
| } else if (elementName.equals(FEATURE)) { |
| stateStack.push(new Integer(STATE_FEATURE)); |
| processFeature(attributes); |
| } else if (elementName.equals(ARCHIVE)) { |
| stateStack.push(new Integer(STATE_ARCHIVE)); |
| processArchive(attributes); |
| } else if (elementName.equals(CATEGORY_DEF)) { |
| stateStack.push(new Integer(STATE_CATEGORY_DEF)); |
| processCategoryDef(attributes); |
| } else if (elementName.equals(CATEGORY)) { |
| stateStack.push(new Integer(STATE_CATEGORY)); |
| processCategory(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(new Integer(STATE_DESCRIPTION_SITE)); |
| processInfo(attributes); |
| } else if (elementName.equals(FEATURE)) { |
| stateStack.push(new Integer(STATE_FEATURE)); |
| processFeature(attributes); |
| } else if (elementName.equals(ARCHIVE)) { |
| stateStack.push(new Integer(STATE_ARCHIVE)); |
| processArchive(attributes); |
| } else if (elementName.equals(CATEGORY_DEF)) { |
| stateStack.push(new Integer(STATE_CATEGORY_DEF)); |
| processCategoryDef(attributes); |
| } else if (elementName.equals(CATEGORY)) { |
| stateStack.push(new Integer(STATE_CATEGORY)); |
| processCategory(attributes); |
| } else |
| internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState)}))); |
| } |
| |
| private void handleInitialState(String elementName, Attributes attributes) throws SAXException { |
| if (elementName.equals(SITE)) { |
| stateStack.push(new Integer(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(new Integer(STATE_DESCRIPTION_SITE)); |
| processInfo(attributes); |
| } else if (elementName.equals(FEATURE)) { |
| stateStack.push(new Integer(STATE_FEATURE)); |
| processFeature(attributes); |
| } else if (elementName.equals(ARCHIVE)) { |
| stateStack.push(new Integer(STATE_ARCHIVE)); |
| processArchive(attributes); |
| } else if (elementName.equals(CATEGORY_DEF)) { |
| stateStack.push(new Integer(STATE_CATEGORY_DEF)); |
| processCategoryDef(attributes); |
| } else |
| internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState)}))); |
| } |
| |
| /* |
| * |
| */ |
| private void internalError(String message) { |
| error(new Status(IStatus.ERROR, PLUGIN_ID, IStatus.OK, message, null)); |
| } |
| |
| /* |
| * |
| */ |
| private void internalErrorUnknownTag(String msg) { |
| stateStack.push(new Integer(STATE_IGNORED_ELEMENT)); |
| internalError(msg); |
| } |
| |
| private boolean leadingSpace(String str) { |
| if (str.length() <= 0) { |
| return false; |
| } |
| return Character.isWhitespace(str.charAt(0)); |
| } |
| |
| /* |
| * |
| */ |
| 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, msg, ex)); |
| } |
| |
| /** |
| * 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(new Integer(STATE_INITIAL)); |
| currentState = ((Integer) stateStack.peek()).intValue(); |
| parser.parse(new InputSource(in), this); |
| if (objectStack.isEmpty()) |
| throw new SAXException(Messages.DefaultSiteParser_NoSiteTag); |
| if (objectStack.peek() instanceof SiteModel) { |
| return (SiteModel) objectStack.pop(); |
| } |
| 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}))); |
| } |
| |
| /* |
| * process archive info |
| */ |
| private void processArchive(Attributes attributes) { |
| URLEntry archive = new URLEntry(); |
| 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.setAnnotation(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.setURL(url); |
| |
| SiteModel site = (SiteModel) objectStack.peek(); |
| site.addArchive(archive); |
| } |
| if (Tracing.DEBUG_GENERATOR_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$ |
| SiteFeature feature = (SiteFeature) objectStack.peek(); |
| feature.addCategoryName(category); |
| |
| if (Tracing.DEBUG_GENERATOR_PARSING) |
| debug("End processing Category: name:" + category); //$NON-NLS-1$ |
| } |
| |
| /* |
| * process category def info |
| */ |
| private void processCategoryDef(Attributes attributes) { |
| SiteCategory category = new SiteCategory(); |
| 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.addCategory(category); |
| objectStack.push(category); |
| |
| if (Tracing.DEBUG_GENERATOR_PARSING) |
| debug("End processing CategoryDef: name:" + name + " label:" + label); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| /* |
| * process feature info |
| */ |
| private void processFeature(Attributes attributes) { |
| SiteFeature feature = new SiteFeature(); |
| |
| // 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)}; |
| log(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.addFeature(feature); |
| feature.setSiteModel(site); |
| |
| objectStack.push(feature); |
| |
| if (Tracing.DEBUG_GENERATOR_PARSING) |
| debug("End Processing DefaultFeature Tag: url:" + urlInfo + " type:" + type); //$NON-NLS-1$ //$NON-NLS-2$ |
| |
| } |
| |
| /* |
| * process URL info with element text |
| */ |
| private void processInfo(Attributes attributes) { |
| URLEntry inf = new URLEntry(); |
| String infoURL = attributes.getValue("url"); //$NON-NLS-1$ |
| inf.setURL(infoURL); |
| |
| if (Tracing.DEBUG_GENERATOR_PARSING) |
| debug("Processed Info: url:" + infoURL); //$NON-NLS-1$ |
| |
| objectStack.push(inf); |
| } |
| |
| /* |
| * process site info |
| */ |
| private void processSite(Attributes attributes) { |
| // create site map |
| SiteModel site = new SiteModel(); |
| |
| // 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 |
| URLEntry description = new URLEntry(); |
| description.setURL(DEFAULT_INFO_URL); |
| site.setDescription(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$ |
| site.setType(type); |
| |
| // get mirrors, if any |
| String mirrorsURL = attributes.getValue("mirrorsURL"); //$NON-NLS-1$ |
| if (mirrorsURL != null && mirrorsURL.trim().length() > 0) { |
| // URLEntry[] mirrors = getMirrors(mirrorsURL); |
| // if (mirrors != null) |
| // site.setMirrors(mirrors); |
| // else |
| |
| //Since we are parsing the site at p2 generation time and the |
| //mirrors may change, there is no point doing the mirror expansion now |
| site.setMirrorsURLString(mirrorsURL); |
| } |
| |
| String pack200 = attributes.getValue("pack200"); //$NON-NLS-1$ |
| if (pack200 != null && new Boolean(pack200).booleanValue()) { |
| site.setSupportsPack200(true); |
| } |
| |
| String digestURL = attributes.getValue("digestURL"); |
| if (digestURL != null) |
| site.setDigestURLString(digestURL); |
| |
| // TODO: Digest locales |
| // 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 (attributes.getValue(ASSOCIATE_SITES_URL) != null) |
| site.setAssociateSites(getAssociateSites(attributes.getValue(ASSOCIATE_SITES_URL))); |
| |
| objectStack.push(site); |
| |
| if (Tracing.DEBUG_GENERATOR_PARSING) |
| debug("End process Site tag: siteURL:" + siteURL + " type:" + type);//$NON-NLS-1$ //$NON-NLS-2$ |
| |
| } |
| |
| /** |
| * 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 (Tracing.DEBUG_GENERATOR_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; |
| |
| } |
| |
| private boolean trailingSpace(String str) { |
| if (str.length() <= 0) { |
| return false; |
| } |
| return Character.isWhitespace(str.charAt(str.length() - 1)); |
| } |
| |
| } |