001: /*****************************************************************************
002: * Java Plug-in Framework (JPF)
003: * Copyright (C) 2004-2007 Dmitry Olshansky
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: *****************************************************************************/package org.java.plugin.registry.xml;
019:
020: import org.java.plugin.registry.ExtensionMultiplicity;
021: import org.java.plugin.registry.MatchingRule;
022: import org.java.plugin.registry.ParameterMultiplicity;
023: import org.java.plugin.registry.ParameterType;
024: import org.xml.sax.Attributes;
025: import org.xml.sax.EntityResolver;
026: import org.xml.sax.SAXException;
027:
028: /**
029: * @version $Id$
030: */
031: final class ManifestHandler extends BaseHandler {
032: private ModelPluginManifest manifest = null;
033: private ModelDocumentation documentation = null;
034: private ModelPrerequisite prerequisite;
035: private ModelLibrary library;
036: private ModelExtensionPoint extensionPoint;
037: private ModelExtension extension;
038: private StringBuilder docText = null;
039: private SimpleStack<ModelAttribute> attributeStack = null;
040: private ModelAttribute attribute;
041: private SimpleStack<ModelParameterDef> paramDefStack = null;
042: private ModelParameterDef paramDef;
043: private SimpleStack<ModelParameter> paramStack = null;
044: private ModelParameter param;
045: private StringBuilder paramValue = null;
046:
047: ManifestHandler(final EntityResolver anEntityResolver) {
048: super (anEntityResolver);
049: }
050:
051: /**
052: * @see org.xml.sax.ContentHandler#startElement(java.lang.String,
053: * java.lang.String, java.lang.String, org.xml.sax.Attributes)
054: */
055: @Override
056: public void startElement(final String uri, final String localName,
057: final String qName, final Attributes attributes)
058: throws SAXException {
059: if (log.isDebugEnabled()) {
060: log.debug("startElement - [" + uri + "]/[" //$NON-NLS-1$ //$NON-NLS-2$
061: + localName + "]/[" + qName + "]"); //$NON-NLS-1$ //$NON-NLS-2$
062: }
063: String name = qName;
064: if ("plugin".equals(name)) { //$NON-NLS-1$
065: if (manifest != null) {
066: throw new SAXException("unexpected [" + name //$NON-NLS-1$
067: + "] element (manifest already defined)"); //$NON-NLS-1$
068: }
069: manifest = new ModelPluginDescriptor();
070: manifest.setId(attributes.getValue("id")); //$NON-NLS-1$
071: manifest.setVersion(attributes.getValue("version")); //$NON-NLS-1$
072: manifest.setVendor(attributes.getValue("vendor")); //$NON-NLS-1$
073: manifest.setDocsPath(attributes.getValue("docs-path")); //$NON-NLS-1$
074: ((ModelPluginDescriptor) manifest).setClassName(attributes
075: .getValue("class")); //$NON-NLS-1$
076: } else if ("plugin-fragment".equals(name)) { //$NON-NLS-1$
077: if (manifest != null) {
078: throw new SAXException("unexpected [" + name //$NON-NLS-1$
079: + "] element (manifest already defined)"); //$NON-NLS-1$
080: }
081: manifest = new ModelPluginFragment();
082: manifest.setId(attributes.getValue("id")); //$NON-NLS-1$
083: manifest.setVersion(attributes.getValue("version")); //$NON-NLS-1$
084: manifest.setVendor(attributes.getValue("vendor")); //$NON-NLS-1$
085: manifest.setDocsPath(attributes.getValue("docs-path")); //$NON-NLS-1$
086: ((ModelPluginFragment) manifest).setPluginId(attributes
087: .getValue("plugin-id")); //$NON-NLS-1$
088: if (attributes.getValue("plugin-version") != null) { //$NON-NLS-1$
089: ((ModelPluginFragment) manifest)
090: .setPluginVersion(attributes
091: .getValue("plugin-version")); //$NON-NLS-1$
092: }
093: if (attributes.getValue("match") != null) { //$NON-NLS-1$
094: ((ModelPluginFragment) manifest)
095: .setMatchingRule(MatchingRule
096: .fromCode(attributes.getValue("match"))); //$NON-NLS-1$
097: } else {
098: ((ModelPluginFragment) manifest)
099: .setMatchingRule(MatchingRule.COMPATIBLE);
100: }
101: } else if ("doc".equals(name)) { //$NON-NLS-1$
102: documentation = new ModelDocumentation();
103: documentation.setCaption(attributes.getValue("caption")); //$NON-NLS-1$
104: } else if ("doc-ref".equals(name)) { //$NON-NLS-1$
105: if (documentation == null) {
106: if (entityResolver != null) {
107: throw new SAXException("[doc-ref] element found " //$NON-NLS-1$
108: + "outside of [doc] element"); //$NON-NLS-1$
109: }
110: // ignore this element
111: log
112: .warn("[doc-ref] element found outside of [doc] element"); //$NON-NLS-1$
113: return;
114: }
115: ModelDocumentationReference docRef = new ModelDocumentationReference();
116: docRef.setPath(attributes.getValue("path")); //$NON-NLS-1$
117: docRef.setCaption(attributes.getValue("caption")); //$NON-NLS-1$
118: documentation.getReferences().add(docRef);
119: } else if ("doc-text".equals(name)) { //$NON-NLS-1$
120: if (documentation == null) {
121: if (entityResolver != null) {
122: throw new SAXException("[doc-text] element found " //$NON-NLS-1$
123: + "outside of [doc] element"); //$NON-NLS-1$
124: }
125: // ignore this element
126: log
127: .warn("[doc-text] element found outside of [doc] element"); //$NON-NLS-1$
128: return;
129: }
130: docText = new StringBuilder();
131: } else if ("attributes".equals(name)) { //$NON-NLS-1$
132: attributeStack = new SimpleStack<ModelAttribute>();
133: } else if ("attribute".equals(name)) { //$NON-NLS-1$
134: if (attributeStack == null) {
135: if (entityResolver != null) {
136: throw new SAXException("[attribute] element found " //$NON-NLS-1$
137: + "outside of [attributes] element"); //$NON-NLS-1$
138: }
139: // ignore this element
140: log.warn("[attribute] element found " //$NON-NLS-1$
141: + "outside of [attributes] element"); //$NON-NLS-1$
142: return;
143: }
144: if (attribute != null) {
145: attributeStack.push(attribute);
146: }
147: attribute = new ModelAttribute();
148: attribute.setId(attributes.getValue("id")); //$NON-NLS-1$
149: attribute.setValue(attributes.getValue("value")); //$NON-NLS-1$
150: } else if ("requires".equals(name)) { //$NON-NLS-1$
151: // no-op
152: } else if ("import".equals(name)) { //$NON-NLS-1$
153: prerequisite = new ModelPrerequisite();
154: if (attributes.getValue("id") != null) { //$NON-NLS-1$
155: prerequisite.setId(attributes.getValue("id")); //$NON-NLS-1$
156: }
157: prerequisite.setPluginId(attributes.getValue("plugin-id")); //$NON-NLS-1$
158: if (attributes.getValue("plugin-version") != null) { //$NON-NLS-1$
159: prerequisite.setPluginVersion(attributes
160: .getValue("plugin-version")); //$NON-NLS-1$
161: }
162: if (attributes.getValue("match") != null) { //$NON-NLS-1$
163: prerequisite.setMatchingRule(MatchingRule
164: .fromCode(attributes.getValue("match"))); //$NON-NLS-1$
165: } else {
166: prerequisite.setMatchingRule(MatchingRule.COMPATIBLE);
167: }
168: prerequisite.setExported(attributes.getValue("exported")); //$NON-NLS-1$
169: prerequisite.setOptional(attributes.getValue("optional")); //$NON-NLS-1$
170: prerequisite.setReverseLookup(attributes
171: .getValue("reverse-lookup")); //$NON-NLS-1$
172: } else if ("runtime".equals(name)) { //$NON-NLS-1$
173: // no-op
174: } else if ("library".equals(name)) { //$NON-NLS-1$
175: library = new ModelLibrary();
176: library.setId(attributes.getValue("id")); //$NON-NLS-1$
177: library.setPath(attributes.getValue("path")); //$NON-NLS-1$
178: library.setCodeLibrary(attributes.getValue("type")); //$NON-NLS-1$
179: if (attributes.getValue("version") != null) { //$NON-NLS-1$
180: library.setVersion(attributes.getValue("version")); //$NON-NLS-1$
181: }
182: } else if ("export".equals(name)) { //$NON-NLS-1$
183: if (library == null) {
184: if (entityResolver != null) {
185: throw new SAXException("[export] element found " //$NON-NLS-1$
186: + "outside of [library] element"); //$NON-NLS-1$
187: }
188: // ignore this element
189: log
190: .warn("[export] element found outside of [library] element"); //$NON-NLS-1$
191: return;
192: }
193: library.getExports().add(attributes.getValue("prefix")); //$NON-NLS-1$
194: } else if ("extension-point".equals(name)) { //$NON-NLS-1$
195: extensionPoint = new ModelExtensionPoint();
196: extensionPoint.setId(attributes.getValue("id")); //$NON-NLS-1$
197: extensionPoint.setParentPluginId(attributes
198: .getValue("parent-plugin-id")); //$NON-NLS-1$
199: extensionPoint.setParentPointId(attributes
200: .getValue("parent-point-id")); //$NON-NLS-1$
201: if (attributes.getValue("extension-multiplicity") != null) { //$NON-NLS-1$
202: extensionPoint
203: .setExtensionMultiplicity(ExtensionMultiplicity
204: .fromCode(attributes
205: .getValue("extension-multiplicity"))); //$NON-NLS-1$
206: } else {
207: extensionPoint
208: .setExtensionMultiplicity(ExtensionMultiplicity.ANY);
209: }
210: paramDefStack = new SimpleStack<ModelParameterDef>();
211: } else if ("parameter-def".equals(name)) { //$NON-NLS-1$
212: if (extensionPoint == null) {
213: if (entityResolver != null) {
214: throw new SAXException(
215: "[parameter-def] element found " //$NON-NLS-1$
216: + "outside of [extension-point] element"); //$NON-NLS-1$
217: }
218: // ignore this element
219: log.warn("[parameter-def] element found " //$NON-NLS-1$
220: + "outside of [extension-point] element"); //$NON-NLS-1$
221: return;
222: }
223: if (paramDef != null) {
224: paramDefStack.push(paramDef);
225: }
226: paramDef = new ModelParameterDef();
227: paramDef.setId(attributes.getValue("id")); //$NON-NLS-1$
228: if (attributes.getValue("multiplicity") != null) { //$NON-NLS-1$
229: paramDef.setMultiplicity(ParameterMultiplicity
230: .fromCode(attributes.getValue("multiplicity"))); //$NON-NLS-1$
231: } else {
232: paramDef.setMultiplicity(ParameterMultiplicity.ONE);
233: }
234: if (attributes.getValue("type") != null) { //$NON-NLS-1$
235: paramDef.setType(ParameterType.fromCode(attributes
236: .getValue("type"))); //$NON-NLS-1$
237: } else {
238: paramDef.setType(ParameterType.STRING);
239: }
240: paramDef.setCustomData(attributes.getValue("custom-data")); //$NON-NLS-1$
241: paramDef.setDefaultValue(attributes
242: .getValue("default-value")); //$NON-NLS-1$
243: } else if ("extension".equals(name)) { //$NON-NLS-1$
244: extension = new ModelExtension();
245: extension.setId(attributes.getValue("id")); //$NON-NLS-1$
246: extension.setPluginId(attributes.getValue("plugin-id")); //$NON-NLS-1$
247: extension.setPointId(attributes.getValue("point-id")); //$NON-NLS-1$
248: paramStack = new SimpleStack<ModelParameter>();
249: } else if ("parameter".equals(name)) { //$NON-NLS-1$
250: if (extension == null) {
251: if (entityResolver != null) {
252: throw new SAXException("[parameter] element found " //$NON-NLS-1$
253: + "outside of [extension] element"); //$NON-NLS-1$
254: }
255: // ignore this element
256: log.warn("[parameter] element found " //$NON-NLS-1$
257: + "outside of [extension] element"); //$NON-NLS-1$
258: return;
259: }
260: if (param != null) {
261: paramStack.push(param);
262: }
263: param = new ModelParameter();
264: param.setId(attributes.getValue("id")); //$NON-NLS-1$
265: param.setValue(attributes.getValue("value")); //$NON-NLS-1$
266: } else if ("value".equals(name)) { //$NON-NLS-1$
267: if (param == null) {
268: if (entityResolver != null) {
269: throw new SAXException("[value] element found " //$NON-NLS-1$
270: + "outside of [parameter] element"); //$NON-NLS-1$
271: }
272: // ignore this element
273: log.warn("[value] element found " //$NON-NLS-1$
274: + "outside of [parameter] element"); //$NON-NLS-1$
275: return;
276: }
277: paramValue = new StringBuilder();
278: } else {
279: if (entityResolver != null) {
280: throw new SAXException(
281: "unexpected manifest element - [" //$NON-NLS-1$
282: + uri
283: + "]/[" + localName + "]/[" + qName + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
284: }
285: // ignore this element
286: log.warn("unexpected manifest element - [" + uri + "]/[" //$NON-NLS-1$ //$NON-NLS-2$
287: + localName + "]/[" + qName + "]"); //$NON-NLS-1$ //$NON-NLS-2$
288: }
289: }
290:
291: /**
292: * @see org.xml.sax.ContentHandler#endElement(java.lang.String,
293: * java.lang.String, java.lang.String)
294: */
295: @Override
296: public void endElement(final String uri, final String localName,
297: final String qName) {
298: if (log.isDebugEnabled()) {
299: log.debug("endElement - [" + uri + "]/[" + localName //$NON-NLS-1$ //$NON-NLS-2$
300: + "]/[" + qName + "]"); //$NON-NLS-1$ //$NON-NLS-2$
301: }
302: String name = qName;
303: if ("plugin".equals(name)) { //$NON-NLS-1$
304: // no-op
305: } else if ("plugin-fragment".equals(name)) { //$NON-NLS-1$
306: // no-op
307: } else if ("doc".equals(name)) { //$NON-NLS-1$
308: if (param != null) {
309: param.setDocumentation(documentation);
310: } else if (extension != null) {
311: extension.setDocumentation(documentation);
312: } else if (paramDef != null) {
313: paramDef.setDocumentation(documentation);
314: } else if (extensionPoint != null) {
315: extensionPoint.setDocumentation(documentation);
316: } else if (library != null) {
317: library.setDocumentation(documentation);
318: } else if (prerequisite != null) {
319: prerequisite.setDocumentation(documentation);
320: } else if (attribute != null) {
321: attribute.setDocumentation(documentation);
322: } else {
323: manifest.setDocumentation(documentation);
324: }
325: documentation = null;
326: } else if ("doc-ref".equals(name)) { //$NON-NLS-1$
327: // no-op
328: } else if ("doc-text".equals(name)) { //$NON-NLS-1$
329: documentation.setText(docText.toString());
330: docText = null;
331: } else if ("attributes".equals(name)) { //$NON-NLS-1$
332: attributeStack = null;
333: } else if ("attribute".equals(name)) { //$NON-NLS-1$
334: if (attributeStack.size() == 0) {
335: manifest.getAttributes().add(attribute);
336: attribute = null;
337: } else {
338: ModelAttribute temp = attribute;
339: attribute = attributeStack.pop();
340: attribute.getAttributes().add(temp);
341: temp = null;
342: }
343: } else if ("requires".equals(name)) { //$NON-NLS-1$
344: // no-op
345: } else if ("import".equals(name)) { //$NON-NLS-1$
346: manifest.getPrerequisites().add(prerequisite);
347: prerequisite = null;
348: } else if ("runtime".equals(name)) { //$NON-NLS-1$
349: // no-op
350: } else if ("library".equals(name)) { //$NON-NLS-1$
351: manifest.getLibraries().add(library);
352: library = null;
353: } else if ("export".equals(name)) { //$NON-NLS-1$
354: // no-op
355: } else if ("extension-point".equals(name)) { //$NON-NLS-1$
356: manifest.getExtensionPoints().add(extensionPoint);
357: extensionPoint = null;
358: paramDefStack = null;
359: } else if ("parameter-def".equals(name)) { //$NON-NLS-1$
360: if (paramDefStack.size() == 0) {
361: extensionPoint.getParamDefs().add(paramDef);
362: paramDef = null;
363: } else {
364: ModelParameterDef temp = paramDef;
365: paramDef = paramDefStack.pop();
366: paramDef.getParamDefs().add(temp);
367: temp = null;
368: }
369: } else if ("extension".equals(name)) { //$NON-NLS-1$
370: manifest.getExtensions().add(extension);
371: extension = null;
372: paramStack = null;
373: } else if ("parameter".equals(name)) { //$NON-NLS-1$
374: if (paramStack.size() == 0) {
375: extension.getParams().add(param);
376: param = null;
377: } else {
378: ModelParameter temp = param;
379: param = paramStack.pop();
380: param.getParams().add(temp);
381: temp = null;
382: }
383: } else if ("value".equals(name)) { //$NON-NLS-1$
384: param.setValue(paramValue.toString());
385: paramValue = null;
386: } else {
387: // ignore any other element
388: log.warn("ignoring manifest element - [" + uri + "]/[" //$NON-NLS-1$ //$NON-NLS-2$
389: + localName + "]/[" + qName + "]"); //$NON-NLS-1$ //$NON-NLS-2$
390: }
391: }
392:
393: /**
394: * @see org.xml.sax.ContentHandler#characters(char[], int, int)
395: */
396: @Override
397: public void characters(final char[] ch, final int start,
398: final int length) throws SAXException {
399: if (docText != null) {
400: docText.append(ch, start, length);
401: } else if (paramValue != null) {
402: paramValue.append(ch, start, length);
403: } else {
404: if (entityResolver != null) {
405: throw new SAXException("unexpected character data"); //$NON-NLS-1$
406: }
407: // ignore these characters
408: log.warn("ignoring character data - [" //$NON-NLS-1$
409: + new String(ch, start, length) + "]"); //$NON-NLS-1$
410: }
411: }
412:
413: ModelPluginManifest getResult() {
414: return manifest;
415: }
416: }
|