| /******************************************************************************* |
| * Copyright (c) 2000, 2017 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * Red Hat Inc. - 383795 (bundle element), 406902 (nested categories), |
| * 505808 (platform filters in category.xml) |
| *******************************************************************************/ |
| package org.eclipse.equinox.internal.p2.updatesite; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.net.URI; |
| import java.net.URISyntaxException; |
| import java.util.*; |
| import javax.xml.parsers.*; |
| import org.eclipse.core.runtime.*; |
| import org.eclipse.equinox.internal.p2.core.helpers.*; |
| import org.eclipse.equinox.p2.publisher.eclipse.URLEntry; |
| import org.eclipse.equinox.p2.repository.IRepository; |
| import org.eclipse.equinox.p2.repository.spi.RepositoryReference; |
| import org.eclipse.osgi.util.NLS; |
| import org.xml.sax.*; |
| import org.xml.sax.helpers.DefaultHandler; |
| |
| /** |
| * Parses a category.xml file. |
| * This class was initially copied from org.eclipse.update.core.model.DefaultSiteParser. |
| */ |
| public class CategoryParser extends DefaultHandler { |
| private static final String PLUGIN_ID = Activator.ID; |
| |
| 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 DESCRIPTION = "description"; //$NON-NLS-1$ |
| private static final String FEATURE = "feature"; //$NON-NLS-1$ |
| private static final String BUNDLE = "bundle"; //$NON-NLS-1$ |
| private static final String SITE = "site"; //$NON-NLS-1$ |
| private static final String IU = "iu"; //$NON-NLS-1$ |
| private static final String QUERY = "query"; //$NON-NLS-1$ |
| private static final String EXPRESSION = "expression"; //$NON-NLS-1$ |
| private static final String PARAM = "param"; //$NON-NLS-1$ |
| private static final String REPOSITORY_REF = "repository-reference"; //$NON-NLS-1$ |
| private static final String STATS_URI = "stats"; //$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_BUNDLE = 12; |
| private static final int STATE_IGNORED_ELEMENT = -1; |
| private static final int STATE_INITIAL = 0; |
| private static final int STATE_IU = 8; |
| private static final int STATE_EXPRESSION = 9; |
| private static final int STATE_PARAM = 10; |
| private static final int STATE_QUERY = 11; |
| private static final int STATE_SITE = 1; |
| private static final int STATE_REPOSITORY_REF = 13; |
| private static final int STATE_STATS = 14; |
| |
| private boolean DESCRIPTION_SITE_ALREADY_SEEN = false; |
| // Current object stack (used to hold the current object we are |
| // populating in this plugin descriptor |
| Stack<Object> objectStack = new Stack<>(); |
| |
| private SAXParser parser; |
| |
| // Current State Information |
| Stack<Integer> stateStack = new Stack<>(); |
| |
| // List of string keys for translated strings |
| private final List<String> messageKeys = new ArrayList<>(4); |
| |
| private MultiStatus status; |
| |
| /* |
| * |
| */ |
| private static void debug(String s) { |
| Tracing.debug("CategoryParser: " + s); //$NON-NLS-1$ |
| } |
| |
| static void log(Exception e) { |
| LogHelper.log(new Status(IStatus.ERROR, Activator.ID, "Internal Error", e)); //$NON-NLS-1$ |
| } |
| |
| 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 CategoryParser(URI siteLocation) { |
| super(); |
| stateStack = new Stack<>(); |
| objectStack = new Stack<>(); |
| status = null; |
| DESCRIPTION_SITE_ALREADY_SEEN = false; |
| try { |
| SAXParserFactory parserfactory = SecureXMLUtil.newSecureSAXParserFactory(); |
| 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$ |
| } |
| |
| public int currentState() { |
| Integer state = stateStack.peek(); |
| if (state != null) |
| return state.intValue(); |
| return STATE_IGNORED_ELEMENT; |
| } |
| |
| /** |
| * Handle character text |
| * @see DefaultHandler#characters(char[], int, int) |
| * @since 2.0 |
| */ |
| @Override |
| public void characters(char[] ch, int start, int length) { |
| String text = new String(ch, start, length); |
| //only push if description |
| int state = currentState(); |
| switch (state) { |
| case STATE_DESCRIPTION_SITE : |
| case STATE_DESCRIPTION_CATEGORY_DEF : |
| objectStack.push(text); |
| break; |
| |
| case STATE_EXPRESSION : |
| case STATE_PARAM : |
| text = text.trim(); |
| String existing = null; |
| if (objectStack.peek() instanceof String) |
| existing = (String) objectStack.pop(); |
| if (existing != null) |
| text = existing + text; |
| objectStack.push(text); |
| break; |
| default : |
| break; // nothing |
| } |
| } |
| |
| /** |
| * Handle end of element tags |
| * @see DefaultHandler#endElement(String, String, String) |
| * @since 2.0 |
| */ |
| @Override |
| public void endElement(String uri, String localName, String qName) { |
| |
| String text = null; |
| URLEntry info = null; |
| |
| int state = currentState(); |
| switch (state) { |
| case STATE_IGNORED_ELEMENT : |
| case STATE_ARCHIVE : |
| case STATE_CATEGORY : |
| case STATE_QUERY : |
| 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_BUNDLE : |
| stateStack.pop(); |
| objectStack.pop(); |
| break; |
| |
| case STATE_IU : |
| stateStack.pop(); |
| SiteIU completeIU = (SiteIU) objectStack.pop(); |
| String id = completeIU.getID(); |
| String expression = completeIU.getQueryExpression(); |
| if (id == null && expression == null) |
| internalError("The IU must specify an id or an expression to match against."); //$NON-NLS-1$ |
| break; |
| |
| case STATE_EXPRESSION : |
| stateStack.pop(); |
| if (objectStack.peek() instanceof String) { |
| text = (String) objectStack.pop(); |
| SiteIU iu = (SiteIU) objectStack.peek(); |
| iu.setQueryExpression(text); |
| if (Tracing.DEBUG_GENERATOR_PARSING) |
| debug("Found Expression: " + text); //$NON-NLS-1$ |
| } |
| break; |
| case STATE_PARAM : |
| stateStack.pop(); |
| if (objectStack.peek() instanceof String) { |
| text = (String) objectStack.pop(); |
| SiteIU iu = (SiteIU) objectStack.peek(); |
| iu.addQueryParams(text); |
| if (Tracing.DEBUG_GENERATOR_PARSING) |
| debug("Found Param: " + text); //$NON-NLS-1$ |
| } |
| 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_REPOSITORY_REF : |
| stateStack.pop(); |
| // do not pop object as we did not push the reference |
| break; |
| |
| case STATE_STATS : |
| stateStack.pop(); |
| // do not pop object stack because we didn't push anything |
| 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 { |
| checkTranslated(info.getAnnotation()); |
| 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 |
| */ |
| @Override |
| public void error(SAXParseException ex) { |
| logStatus(ex); |
| } |
| |
| /** |
| * Handle fatal errors |
| * @see DefaultHandler#fatalError(SAXParseException) |
| * @exception SAXException |
| * @since 2.0 |
| */ |
| @Override |
| 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_BUNDLE : |
| return "Bundle"; //$NON-NLS-1$ |
| |
| case STATE_IU : |
| return "IU"; //$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$ |
| |
| case STATE_REPOSITORY_REF : |
| return "Repository Reference"; //$NON-NLS-1$ |
| |
| case STATE_STATS : |
| return "Stats Repository"; //$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) { |
| switch (elementName) { |
| case DESCRIPTION: |
| stateStack.push(Integer.valueOf(STATE_DESCRIPTION_CATEGORY_DEF)); |
| processInfo(attributes); |
| break; |
| case CATEGORY: |
| stateStack.push(Integer.valueOf(STATE_CATEGORY)); |
| processCategory(attributes); |
| break; |
| default: |
| internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState())}))); |
| break; |
| } |
| } |
| |
| private void handleCategoryState(String elementName, Attributes attributes) { |
| internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState())}))); |
| } |
| |
| private void handleFeatureState(String elementName, Attributes attributes) { |
| 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 handleBundleState(String elementName, Attributes attributes) { |
| 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 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) { |
| switch (elementName) { |
| case DESCRIPTION: |
| stateStack.push(Integer.valueOf(STATE_DESCRIPTION_SITE)); |
| processInfo(attributes); |
| break; |
| case FEATURE: |
| stateStack.push(Integer.valueOf(STATE_FEATURE)); |
| processFeature(attributes); |
| break; |
| case BUNDLE: |
| stateStack.push(Integer.valueOf(STATE_BUNDLE)); |
| processBundle(attributes); |
| break; |
| case IU: |
| stateStack.push(Integer.valueOf(STATE_IU)); |
| processIU(attributes); |
| break; |
| case ARCHIVE: |
| stateStack.push(Integer.valueOf(STATE_ARCHIVE)); |
| processArchive(attributes); |
| break; |
| case CATEGORY_DEF: |
| stateStack.push(Integer.valueOf(STATE_CATEGORY_DEF)); |
| processCategoryDef(attributes); |
| break; |
| case REPOSITORY_REF: |
| stateStack.push(Integer.valueOf(STATE_REPOSITORY_REF)); |
| processRepositoryReference(attributes); |
| break; |
| case STATS_URI: |
| stateStack.push(Integer.valueOf(STATE_STATS)); |
| processStatsInfo(attributes); |
| break; |
| default: |
| internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState())}))); |
| break; |
| } |
| } |
| |
| private void handleStatsState(String elementName, Attributes attributes) { |
| switch (elementName) { |
| case FEATURE: |
| stateStack.push(STATE_FEATURE); |
| processStatsFeature(attributes); |
| break; |
| case BUNDLE: |
| stateStack.push(STATE_BUNDLE); |
| processStatsBundle(attributes); |
| break; |
| default: |
| internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState())}))); |
| break; |
| } |
| } |
| |
| private void handleIUState(String elementName, Attributes attributes) { |
| switch (elementName) { |
| case QUERY: |
| stateStack.push(Integer.valueOf(STATE_QUERY)); |
| processQuery(attributes); |
| break; |
| case CATEGORY: |
| stateStack.push(Integer.valueOf(STATE_CATEGORY)); |
| processCategory(attributes); |
| break; |
| default: |
| internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState())}))); |
| break; |
| } |
| } |
| |
| private void handleQueryState(String elementName, Attributes attributes) { |
| switch (elementName) { |
| case EXPRESSION: |
| stateStack.push(Integer.valueOf(STATE_EXPRESSION)); |
| processExpression(attributes); |
| break; |
| case PARAM: |
| stateStack.push(Integer.valueOf(STATE_PARAM)); |
| processParam(attributes); |
| break; |
| default: |
| internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState())}))); |
| break; |
| } |
| } |
| |
| private void handleExpression(String elementName, Attributes attributes) { |
| internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState())}))); |
| } |
| |
| private void handleParamState(String elementName, Attributes attributes) { |
| 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(Integer.valueOf(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(Integer.valueOf(STATE_INITIAL)); |
| parser.parse(new InputSource(in), this); |
| if (objectStack.isEmpty()) |
| throw new SAXException(Messages.DefaultSiteParser_NoSiteTag); |
| if (objectStack.peek() instanceof SiteModel) { |
| SiteModel site = (SiteModel) objectStack.pop(); |
| site.setMessageKeys(messageKeys); |
| return site; |
| } |
| String stack = ""; //$NON-NLS-1$ |
| Iterator<Object> 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) { |
| // don't care about archives in category xml |
| if (Tracing.DEBUG_GENERATOR_PARSING) |
| debug("End processing Archive"); //$NON-NLS-1$ |
| } |
| |
| /* |
| * process the Category info |
| */ |
| private void processCategory(Attributes attributes) { |
| String category = attributes.getValue("name"); //$NON-NLS-1$ |
| Object obj = objectStack.peek(); |
| // TODO could create common class/interface for adding categories |
| if (obj instanceof SiteFeature) { |
| ((SiteFeature) obj).addCategoryName(category); |
| } else if (obj instanceof SiteBundle) { |
| ((SiteBundle) obj).addCategoryName(category); |
| } else if (obj instanceof SiteIU) { |
| ((SiteIU) obj).addCategoryName(category); |
| } else if (obj instanceof SiteCategory) { |
| ((SiteCategory) obj).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$ |
| checkTranslated(label); |
| 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 repository reference info |
| */ |
| private void processRepositoryReference(Attributes attributes) { |
| String location = attributes.getValue("location"); //$NON-NLS-1$ |
| String nickname = attributes.getValue("name"); //$NON-NLS-1$ |
| URI uri; |
| try { |
| uri = URIUtil.fromString(location); |
| boolean enabled = Boolean.parseBoolean(attributes.getValue("enabled")); //$NON-NLS-1$ |
| // First add a metadata repository |
| RepositoryReference metadata = new RepositoryReference(uri, nickname, IRepository.TYPE_METADATA, enabled ? IRepository.ENABLED : IRepository.NONE); |
| // Now a colocated artifact repository |
| RepositoryReference artifact = new RepositoryReference(uri, nickname, IRepository.TYPE_ARTIFACT, enabled ? IRepository.ENABLED : IRepository.NONE); |
| |
| SiteModel site = (SiteModel) objectStack.peek(); |
| site.addRepositoryReference(metadata); |
| site.addRepositoryReference(artifact); |
| // we do not push the references onto the object stack as we do not go deeper, and |
| // references are not SiteModel objects. |
| } catch (URISyntaxException e) { |
| // UI should have already caught this |
| } |
| } |
| |
| /* |
| * process stats top level element |
| */ |
| private void processStatsInfo(Attributes attributes) { |
| String location = attributes.getValue("location"); //$NON-NLS-1$ |
| try { |
| // One final validation but UI should have already done this. |
| URIUtil.fromString(location); |
| SiteModel site = (SiteModel) objectStack.peek(); |
| site.setStatsURIString(location); |
| } catch (URISyntaxException e) { |
| // Ignore if not valid. |
| } |
| |
| if (Tracing.DEBUG_GENERATOR_PARSING) |
| debug("End processing Repository Reference: location:" + location); //$NON-NLS-1$ |
| } |
| |
| /* |
| * process stats feature artifact |
| */ |
| private void processStatsFeature(Attributes attributes) { |
| SiteFeature feature = new SiteFeature(); |
| |
| // identifier and version |
| String id = attributes.getValue("id"); //$NON-NLS-1$ |
| String ver = attributes.getValue("version"); //$NON-NLS-1$ |
| |
| boolean noId = (id == null || id.trim().equals("")); //$NON-NLS-1$ |
| |
| // We need to have id and version, or the url, or both. |
| if (noId) |
| internalError(NLS.bind(Messages.DefaultSiteParser_Missing, (new String[] {"url", getState(currentState())}))); //$NON-NLS-1$ |
| |
| feature.setFeatureIdentifier(id); |
| feature.setFeatureVersion(ver); |
| |
| SiteModel site = (SiteModel) objectStack.peek(); |
| site.addStatsFeature(feature); |
| objectStack.push(feature); |
| feature.setSiteModel(site); |
| |
| if (Tracing.DEBUG_GENERATOR_PARSING) |
| debug("End Processing Stats Feature Tag: id:" + id + " version:" + ver); //$NON-NLS-1$ //$NON-NLS-2$ } |
| } |
| |
| /* |
| * process stats bundle artifact info |
| */ |
| private void processStatsBundle(Attributes attributes) { |
| SiteBundle bundle = new SiteBundle(); |
| |
| // identifier and version |
| String id = attributes.getValue("id"); //$NON-NLS-1$ |
| String ver = attributes.getValue("version"); //$NON-NLS-1$ |
| |
| boolean noId = (id == null || id.trim().equals("")); //$NON-NLS-1$ |
| |
| // We need to have id and version, or the url, or both. |
| if (noId) |
| internalError(NLS.bind(Messages.DefaultSiteParser_Missing, (new String[] {"url", getState(currentState())}))); //$NON-NLS-1$ |
| |
| bundle.setBundleIdentifier(id); |
| bundle.setBundleVersion(ver); |
| |
| SiteModel site = (SiteModel) objectStack.peek(); |
| site.addStatsBundle(bundle); |
| objectStack.push(bundle); |
| bundle.setSiteModel(site); |
| |
| if (Tracing.DEBUG_GENERATOR_PARSING) |
| debug("End Processing Stats Bundle Tag: id:" + id + " version:" + ver); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| /* |
| * process feature info |
| */ |
| private void processFeature(Attributes attributes) { |
| SiteFeature feature = new SiteFeature(); |
| |
| // identifier and version |
| String id = attributes.getValue("id"); //$NON-NLS-1$ |
| String ver = attributes.getValue("version"); //$NON-NLS-1$ |
| String os = attributes.getValue("os"); //$NON-NLS-1$ |
| String ws = attributes.getValue("ws"); //$NON-NLS-1$ |
| String arch = attributes.getValue("arch"); //$NON-NLS-1$ |
| |
| boolean noId = (id == null || id.trim().equals("")); //$NON-NLS-1$ |
| |
| // We need to have id and version, or the url, or both. |
| if (noId) |
| internalError(NLS.bind(Messages.DefaultSiteParser_Missing, (new String[] {"url", getState(currentState())}))); //$NON-NLS-1$ |
| |
| feature.setFeatureIdentifier(id); |
| feature.setFeatureVersion(ver); |
| feature.setOS(os); |
| feature.setWS(ws); |
| feature.setArch(arch); |
| |
| SiteModel site = (SiteModel) objectStack.peek(); |
| site.addFeature(feature); |
| feature.setSiteModel(site); |
| |
| objectStack.push(feature); |
| |
| if (Tracing.DEBUG_GENERATOR_PARSING) |
| debug("End Processing Feature Tag: id:" + id + " version:" + ver); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| /* |
| * process bundle info |
| */ |
| private void processBundle(Attributes attributes) { |
| SiteBundle bundle = new SiteBundle(); |
| |
| // identifier and version |
| String id = attributes.getValue("id"); //$NON-NLS-1$ |
| String ver = attributes.getValue("version"); //$NON-NLS-1$ |
| String os = attributes.getValue("os"); //$NON-NLS-1$ |
| String ws = attributes.getValue("ws"); //$NON-NLS-1$ |
| String arch = attributes.getValue("arch"); //$NON-NLS-1$ |
| |
| boolean noId = (id == null || id.trim().equals("")); //$NON-NLS-1$ |
| |
| // We need to have id and version, or the url, or both. |
| if (noId) |
| internalError(NLS.bind(Messages.DefaultSiteParser_Missing, (new String[] {"url", getState(currentState())}))); //$NON-NLS-1$ |
| |
| bundle.setBundleIdentifier(id); |
| bundle.setBundleVersion(ver); |
| bundle.setOS(os); |
| bundle.setWS(ws); |
| bundle.setArch(arch); |
| |
| SiteModel site = (SiteModel) objectStack.peek(); |
| site.addBundle(bundle); |
| bundle.setSiteModel(site); |
| |
| objectStack.push(bundle); |
| |
| if (Tracing.DEBUG_GENERATOR_PARSING) |
| debug("End Processing Bundle Tag: id:" + id + " version:" + ver); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| /* |
| * process IU info |
| */ |
| private void processIU(Attributes attributes) { |
| SiteIU iu = new SiteIU(); |
| SiteModel site = (SiteModel) objectStack.peek(); |
| |
| // identifier and version |
| String id = attributes.getValue("id"); //$NON-NLS-1$ |
| String range = attributes.getValue("range"); //$NON-NLS-1$ |
| id = id == null ? null : id.trim(); |
| range = range == null ? null : range.trim(); |
| |
| iu.setID(id); |
| iu.setRange(range); |
| |
| site.addIU(iu); |
| objectStack.push(iu); |
| |
| if (Tracing.DEBUG_GENERATOR_PARSING) |
| debug("End processing iu."); //$NON-NLS-1$ |
| } |
| |
| /* |
| * process expression info |
| */ |
| private void processExpression(Attributes attributes) { |
| SiteIU iu = (SiteIU) objectStack.peek(); |
| iu.setQueryType(attributes.getValue("type")); //$NON-NLS-1$ |
| |
| if (Tracing.DEBUG_GENERATOR_PARSING) |
| debug("End processing Expression: " + iu.getQueryType()); //$NON-NLS-1$ |
| } |
| |
| /* |
| * process query info |
| */ |
| private void processQuery(Attributes attributes) { |
| // TODO may have simple attriutes for id and range |
| if (Tracing.DEBUG_GENERATOR_PARSING) |
| debug("End processing Query."); //$NON-NLS-1$ |
| } |
| |
| /* |
| * process param info |
| */ |
| private void processParam(Attributes attributes) { |
| if (Tracing.DEBUG_GENERATOR_PARSING) |
| debug("End processing Param."); //$NON-NLS-1$ |
| } |
| |
| /* |
| * 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(); |
| objectStack.push(site); |
| |
| if (Tracing.DEBUG_GENERATOR_PARSING) |
| debug("End process Site tag."); //$NON-NLS-1$ |
| |
| } |
| |
| /** |
| * Handle start of element tags |
| * @see DefaultHandler#startElement(String, String, String, Attributes) |
| * @since 2.0 |
| */ |
| @Override |
| 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_BUNDLE : |
| handleBundleState(localName, attributes); |
| break; |
| |
| case STATE_IU : |
| handleIUState(localName, attributes); |
| break; |
| |
| case STATE_EXPRESSION : |
| handleExpression(localName, attributes); |
| break; |
| |
| case STATE_QUERY : |
| handleQueryState(localName, attributes); |
| break; |
| |
| case STATE_PARAM : |
| handleParamState(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; |
| |
| case STATE_STATS : |
| handleStatsState(localName, attributes); |
| break; |
| |
| default : |
| internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownStartState, (new String[] {getState(currentState())}))); |
| break; |
| } |
| |
| } |
| |
| private boolean trailingSpace(String str) { |
| if (str.length() <= 0) { |
| return false; |
| } |
| return Character.isWhitespace(str.charAt(str.length() - 1)); |
| } |
| |
| // Add translatable strings from the site.xml |
| // to the list of message keys. |
| private void checkTranslated(String value) { |
| if (value != null && value.length() > 1 && value.startsWith("%")) //$NON-NLS-1$ |
| messageKeys.add(value.substring(1)); |
| } |
| } |