1 11 package org.eclipse.core.runtime.internal.adaptor; 12 13 import java.io.InputStream ; 14 import java.util.*; 15 import javax.xml.parsers.SAXParserFactory ; 16 import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor; 17 import org.eclipse.osgi.framework.log.FrameworkLogEntry; 18 import org.eclipse.osgi.util.NLS; 19 import org.osgi.framework.BundleContext; 20 import org.osgi.framework.Version; 21 import org.osgi.util.tracker.ServiceTracker; 22 import org.xml.sax.*; 23 import org.xml.sax.helpers.DefaultHandler ; 24 25 28 public class PluginParser extends DefaultHandler implements IModel { 29 private static ServiceTracker xmlTracker = null; 30 31 private PluginInfo manifestInfo = new PluginInfo(); 32 private BundleContext context; 33 private FrameworkAdaptor adaptor; 34 private Version target; private static final Version TARGET21 = new Version(2, 1, 0); 36 37 public class PluginInfo implements IPluginInfo { 38 private String schemaVersion; 39 private String pluginId; 40 private String version; 41 private String vendor; 42 43 private ArrayList libraryPaths; 45 private Map libraries; private ArrayList requires; 50 private boolean requiresExpanded = false; private boolean compatibilityFound = false; private String pluginClass; 53 private String masterPluginId; 54 private String masterVersion; 55 private String masterMatch; 56 private Set filters; 57 private String pluginName; 58 private boolean singleton; 59 private boolean fragment; 60 private final static String TARGET21_STRING = "2.1"; private boolean hasExtensionExtensionPoints = false; 62 63 public boolean isFragment() { 64 return fragment; 65 } 66 67 public String toString() { 68 return "plugin-id: " + pluginId + " version: " + version + " libraries: " + libraries + " class:" + pluginClass + " master: " + masterPluginId + " master-version: " + masterVersion + " requires: " + requires + " singleton: " + singleton; } 70 71 public Map getLibraries() { 72 if (libraries == null) 73 return new HashMap(0); 74 return libraries; 75 } 76 77 public ArrayList getRequires() { 78 if (!TARGET21.equals(target) && schemaVersion == null && !requiresExpanded) { 79 requiresExpanded = true; 80 if (requires == null) { 81 requires = new ArrayList(1); 82 requires.add(new Prerequisite(PluginConverterImpl.PI_RUNTIME, TARGET21_STRING, false, false, IModel.PLUGIN_REQUIRES_MATCH_GREATER_OR_EQUAL)); 83 requires.add(new Prerequisite(PluginConverterImpl.PI_RUNTIME_COMPATIBILITY, null, false, false, null)); 84 } else { 85 for (int i = 0; i < requires.size(); i++) { 87 Prerequisite analyzed = (Prerequisite) requires.get(i); 88 if ("org.eclipse.ui".equals(analyzed.getName())) { requires.add(i + 1, new Prerequisite("org.eclipse.ui.workbench.texteditor", null, true, analyzed.isExported(), null)); requires.add(i + 1, new Prerequisite("org.eclipse.jface.text", null, true, analyzed.isExported(), null)); requires.add(i + 1, new Prerequisite("org.eclipse.ui.editors", null, true, analyzed.isExported(), null)); requires.add(i + 1, new Prerequisite("org.eclipse.ui.views", null, true, analyzed.isExported(), null)); requires.add(i + 1, new Prerequisite("org.eclipse.ui.ide", null, true, analyzed.isExported(), null)); } else if ("org.eclipse.help".equals(analyzed.getName())) { requires.add(i + 1, new Prerequisite("org.eclipse.help.base", null, true, analyzed.isExported(), null)); } else if (PluginConverterImpl.PI_RUNTIME.equals(analyzed.getName()) && !compatibilityFound) { 97 requires.add(i + 1, new Prerequisite(PluginConverterImpl.PI_RUNTIME_COMPATIBILITY, null, false, analyzed.isExported(), null)); 98 } 99 } 100 if (!requires.contains(new Prerequisite(PluginConverterImpl.PI_RUNTIME_COMPATIBILITY, null, false, false, null))) { 101 requires.add(new Prerequisite(PluginConverterImpl.PI_RUNTIME_COMPATIBILITY, null, false, false, null)); 102 } 103 Prerequisite runtimePrereq = new Prerequisite(PluginConverterImpl.PI_RUNTIME, null, false, false, null); 106 requires.remove(runtimePrereq); 107 requires.add(new Prerequisite(PluginConverterImpl.PI_RUNTIME, TARGET21_STRING, false, false, IModel.PLUGIN_REQUIRES_MATCH_GREATER_OR_EQUAL)); 108 } 109 } 110 if (requires == null) 111 return requires = new ArrayList(0); 112 113 return requires; 114 } 115 116 public String getMasterId() { 117 return masterPluginId; 118 } 119 120 public String getMasterVersion() { 121 return masterVersion; 122 } 123 124 public String getMasterMatch() { 125 return masterMatch; 126 } 127 128 public String getPluginClass() { 129 return pluginClass; 130 } 131 132 public String getUniqueId() { 133 return pluginId; 134 } 135 136 public String getVersion() { 137 return version; 138 } 139 140 public Set getPackageFilters() { 141 return filters; 142 } 143 144 public String [] getLibrariesName() { 145 if (libraryPaths == null) 146 return new String [0]; 147 return (String []) libraryPaths.toArray(new String [libraryPaths.size()]); 148 } 149 150 public String getPluginName() { 151 return pluginName; 152 } 153 154 public String getProviderName() { 155 return vendor; 156 } 157 158 public boolean isSingleton() { 159 return singleton; 160 } 161 162 public boolean hasExtensionExtensionPoints() { 163 return hasExtensionExtensionPoints; 164 } 165 166 public String getRoot() { 167 return isFragment() ? FRAGMENT : PLUGIN; 168 } 169 170 174 public String validateForm() { 175 if (this.pluginId == null) 176 return NLS.bind(EclipseAdaptorMsg.ECLIPSE_CONVERTER_MISSING_ATTRIBUTE, new String [] {getRoot(), PLUGIN_ID, getRoot()}); 177 if (this.pluginName == null) 178 return NLS.bind(EclipseAdaptorMsg.ECLIPSE_CONVERTER_MISSING_ATTRIBUTE, new String [] {getRoot(), PLUGIN_NAME, getRoot()}); 179 if (this.version == null) 180 return NLS.bind(EclipseAdaptorMsg.ECLIPSE_CONVERTER_MISSING_ATTRIBUTE, new String [] {getRoot(), PLUGIN_VERSION, getRoot()}); 181 if (isFragment() && this.masterPluginId == null) 182 return NLS.bind(EclipseAdaptorMsg.ECLIPSE_CONVERTER_MISSING_ATTRIBUTE, new String [] {getRoot(), FRAGMENT_PLUGIN_ID, getRoot()}); 183 if (isFragment() && this.masterVersion == null) 184 return NLS.bind(EclipseAdaptorMsg.ECLIPSE_CONVERTER_MISSING_ATTRIBUTE, new String [] {getRoot(), FRAGMENT_PLUGIN_VERSION, getRoot()}); 185 return null; 186 } 187 } 188 189 Stack stateStack = new Stack(); 191 192 Stack objectStack = new Stack(); 194 Locator locator = null; 195 196 private static final int IGNORED_ELEMENT_STATE = 0; 198 private static final int INITIAL_STATE = 1; 199 private static final int PLUGIN_STATE = 2; 200 private static final int PLUGIN_RUNTIME_STATE = 3; 201 private static final int PLUGIN_REQUIRES_STATE = 4; 202 private static final int PLUGIN_EXTENSION_POINT_STATE = 5; 203 private static final int PLUGIN_EXTENSION_STATE = 6; 204 private static final int RUNTIME_LIBRARY_STATE = 7; 205 private static final int LIBRARY_EXPORT_STATE = 8; 206 private static final int PLUGIN_REQUIRES_IMPORT_STATE = 9; 207 private static final int FRAGMENT_STATE = 11; 208 209 public PluginParser(FrameworkAdaptor adaptor, BundleContext context, Version target) { 210 super(); 211 this.context = context; 212 this.adaptor = adaptor; 213 this.target = target; 214 } 215 216 229 public void setDocumentLocator(Locator locator) { 230 this.locator = locator; 231 } 232 233 public void endDocument() { 234 } 235 236 public void endElement(String uri, String elementName, String qName) { 237 switch (((Integer ) stateStack.peek()).intValue()) { 238 case IGNORED_ELEMENT_STATE : 239 stateStack.pop(); 240 break; 241 case INITIAL_STATE : 242 break; 245 case PLUGIN_STATE : 246 case FRAGMENT_STATE : 247 break; 248 case PLUGIN_RUNTIME_STATE : 249 if (elementName.equals(RUNTIME)) { 250 stateStack.pop(); 251 } 252 break; 253 case PLUGIN_REQUIRES_STATE : 254 if (elementName.equals(PLUGIN_REQUIRES)) { 255 stateStack.pop(); 256 objectStack.pop(); 257 } 258 break; 259 case PLUGIN_EXTENSION_POINT_STATE : 260 if (elementName.equals(EXTENSION_POINT)) { 261 stateStack.pop(); 262 } 263 break; 264 case PLUGIN_EXTENSION_STATE : 265 if (elementName.equals(EXTENSION)) { 266 stateStack.pop(); 267 } 268 break; 269 case RUNTIME_LIBRARY_STATE : 270 if (elementName.equals(LIBRARY)) { 271 String curLibrary = (String ) objectStack.pop(); 272 if (!curLibrary.trim().equals("")) { Vector exportsVector = (Vector) objectStack.pop(); 274 if (manifestInfo.libraries == null) { 275 manifestInfo.libraries = new HashMap(3); 276 manifestInfo.libraryPaths = new ArrayList(3); 277 } 278 manifestInfo.libraries.put(curLibrary, exportsVector); 279 manifestInfo.libraryPaths.add(curLibrary.replace('\\', '/')); 280 } 281 stateStack.pop(); 282 } 283 break; 284 case LIBRARY_EXPORT_STATE : 285 if (elementName.equals(LIBRARY_EXPORT)) { 286 stateStack.pop(); 287 } 288 break; 289 case PLUGIN_REQUIRES_IMPORT_STATE : 290 if (elementName.equals(PLUGIN_REQUIRES_IMPORT)) { 291 stateStack.pop(); 292 } 293 break; 294 } 295 } 296 297 public void error(SAXParseException ex) { 298 logStatus(ex); 299 } 300 301 public void fatalError(SAXParseException ex) throws SAXException { 302 logStatus(ex); 303 throw ex; 304 } 305 306 public void handleExtensionPointState(String elementName, Attributes attributes) { 307 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 309 manifestInfo.hasExtensionExtensionPoints = true; 310 } 311 312 public void handleExtensionState(String elementName, Attributes attributes) { 313 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 315 manifestInfo.hasExtensionExtensionPoints = true; 316 } 317 318 public void handleInitialState(String elementName, Attributes attributes) { 319 if (elementName.equals(PLUGIN)) { 320 stateStack.push(new Integer (PLUGIN_STATE)); 321 parsePluginAttributes(attributes); 322 } else if (elementName.equals(FRAGMENT)) { 323 manifestInfo.fragment = true; 324 stateStack.push(new Integer (FRAGMENT_STATE)); 325 parseFragmentAttributes(attributes); 326 } else { 327 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 328 internalError(elementName); 329 } 330 } 331 332 public void handleLibraryExportState(String elementName, Attributes attributes) { 333 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 335 } 336 337 public void handleLibraryState(String elementName, Attributes attributes) { 338 if (elementName.equals(LIBRARY_EXPORT)) { 339 stateStack.push(new Integer (LIBRARY_EXPORT_STATE)); 341 String currentLib = (String ) objectStack.peek(); 343 if (attributes == null) 344 return; 345 String maskValue = attributes.getValue("", LIBRARY_EXPORT_MASK); objectStack.pop(); 348 Vector exportMask = (Vector) objectStack.peek(); 349 objectStack.push(currentLib); 351 if (maskValue != null) { 353 StringTokenizer tok = new StringTokenizer(maskValue, ","); while (tok.hasMoreTokens()) { 355 String value = tok.nextToken(); 356 if (!exportMask.contains(maskValue)) 357 exportMask.addElement(value.trim()); 358 } 359 } 360 return; 361 } 362 if (elementName.equals(LIBRARY_PACKAGES)) { 363 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 364 return; 365 } 366 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 367 internalError(elementName); 368 return; 369 } 370 371 public void handlePluginState(String elementName, Attributes attributes) { 372 if (elementName.equals(RUNTIME)) { 373 Object whatIsIt = objectStack.peek(); 375 if ((whatIsIt instanceof PluginInfo) && ((PluginInfo) objectStack.peek()).libraries != null) { 376 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 378 return; 379 } 380 stateStack.push(new Integer (PLUGIN_RUNTIME_STATE)); 381 return; 383 } 384 if (elementName.equals(PLUGIN_REQUIRES)) { 385 stateStack.push(new Integer (PLUGIN_REQUIRES_STATE)); 386 objectStack.push(new Vector()); 388 parseRequiresAttributes(attributes); 389 return; 390 } 391 if (elementName.equals(EXTENSION_POINT)) { 392 manifestInfo.singleton = true; 394 stateStack.push(new Integer (PLUGIN_EXTENSION_POINT_STATE)); 395 return; 396 } 397 if (elementName.equals(EXTENSION)) { 398 manifestInfo.singleton = true; 400 stateStack.push(new Integer (PLUGIN_EXTENSION_STATE)); 401 return; 402 } 403 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 406 internalError(elementName); 407 } 408 409 public void handleRequiresImportState(String elementName, Attributes attributes) { 410 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 412 } 413 414 public void handleRequiresState(String elementName, Attributes attributes) { 415 if (elementName.equals(PLUGIN_REQUIRES_IMPORT)) { 416 parsePluginRequiresImport(attributes); 417 return; 418 } 419 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 422 internalError(elementName); 423 } 424 425 public void handleRuntimeState(String elementName, Attributes attributes) { 426 if (elementName.equals(LIBRARY)) { 427 stateStack.push(new Integer (RUNTIME_LIBRARY_STATE)); 429 parseLibraryAttributes(attributes); 431 return; 432 } 433 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 436 internalError(elementName); 437 } 438 439 private void logStatus(SAXParseException ex) { 440 String name = ex.getSystemId(); 441 if (name == null) 442 name = ""; else 444 name = name.substring(1 + name.lastIndexOf("/")); String msg; 446 if (name.equals("")) msg = NLS.bind(EclipseAdaptorMsg.parse_error, ex.getMessage()); 448 else 449 msg = NLS.bind(EclipseAdaptorMsg.parse_errorNameLineColumn, new String [] {name, Integer.toString(ex.getLineNumber()), Integer.toString(ex.getColumnNumber()), ex.getMessage()}); 450 451 FrameworkLogEntry entry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, msg, 0, ex, null); 452 adaptor.getFrameworkLog().log(entry); 453 } 454 455 synchronized public PluginInfo parsePlugin(InputStream in) throws Exception { 456 SAXParserFactory factory = acquireXMLParsing(context); 457 if (factory == null) { 458 FrameworkLogEntry entry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, EclipseAdaptorMsg.ECLIPSE_CONVERTER_NO_SAX_FACTORY, 0, null, null); 459 adaptor.getFrameworkLog().log(entry); 460 return null; 461 } 462 463 factory.setNamespaceAware(true); 464 factory.setNamespaceAware(true); 465 try { 466 factory.setFeature("http://xml.org/sax/features/string-interning", true); } catch (SAXException se) { 468 } 470 factory.setValidating(false); 471 factory.newSAXParser().parse(in, this); 472 return manifestInfo; 473 } 474 475 public static SAXParserFactory acquireXMLParsing(BundleContext context) { 476 if (xmlTracker == null) { 477 xmlTracker = new ServiceTracker(context, "javax.xml.parsers.SAXParserFactory", null); xmlTracker.open(); 479 } 480 SAXParserFactory result = (SAXParserFactory ) xmlTracker.getService(); 481 if (result != null) 482 return result; 483 return SAXParserFactory.newInstance(); 485 } 486 487 public static void releaseXMLParsing() { 488 if (xmlTracker != null) 489 xmlTracker.close(); 490 } 491 492 public void parseFragmentAttributes(Attributes attributes) { 493 objectStack.push(manifestInfo); 495 int len = attributes.getLength(); 496 for (int i = 0; i < len; i++) { 497 String attrName = attributes.getLocalName(i); 498 String attrValue = attributes.getValue(i).trim(); 499 if (attrName.equals(FRAGMENT_ID)) 500 manifestInfo.pluginId = attrValue; 501 else if (attrName.equals(FRAGMENT_NAME)) 502 manifestInfo.pluginName = attrValue; 503 else if (attrName.equals(FRAGMENT_VERSION)) 504 manifestInfo.version = attrValue; 505 else if (attrName.equals(FRAGMENT_PROVIDER)) 506 manifestInfo.vendor = attrValue; 507 else if (attrName.equals(FRAGMENT_PLUGIN_ID)) 508 manifestInfo.masterPluginId = attrValue; 509 else if (attrName.equals(FRAGMENT_PLUGIN_VERSION)) 510 manifestInfo.masterVersion = attrValue; 511 else if (attrName.equals(FRAGMENT_PLUGIN_MATCH)) 512 manifestInfo.masterMatch = attrValue; 513 } 514 } 515 516 public void parseLibraryAttributes(Attributes attributes) { 517 objectStack.push(new Vector()); 519 String current = attributes.getValue("", LIBRARY_NAME); objectStack.push(current); 521 } 522 523 public void parsePluginAttributes(Attributes attributes) { 524 objectStack.push(manifestInfo); 526 int len = attributes.getLength(); 527 for (int i = 0; i < len; i++) { 528 String attrName = attributes.getLocalName(i); 529 String attrValue = attributes.getValue(i).trim(); 530 if (attrName.equals(PLUGIN_ID)) 531 manifestInfo.pluginId = attrValue; 532 else if (attrName.equals(PLUGIN_NAME)) 533 manifestInfo.pluginName = attrValue; 534 else if (attrName.equals(PLUGIN_VERSION)) 535 manifestInfo.version = attrValue; 536 else if (attrName.equals(PLUGIN_VENDOR) || (attrName.equals(PLUGIN_PROVIDER))) 537 manifestInfo.vendor = attrValue; 538 else if (attrName.equals(PLUGIN_CLASS)) 539 manifestInfo.pluginClass = attrValue; 540 } 541 } 542 543 public class Prerequisite { 544 String name; 545 String version; 546 boolean optional; 547 boolean export; 548 String match; 549 550 public boolean isExported() { 551 return export; 552 } 553 554 public String getMatch() { 555 return match; 556 } 557 558 public String getName() { 559 return name; 560 } 561 562 public boolean isOptional() { 563 return optional; 564 } 565 566 public String getVersion() { 567 return version; 568 } 569 570 public Prerequisite(String preqName, String prereqVersion, boolean isOtional, boolean isExported, String prereqMatch) { 571 name = preqName; 572 version = prereqVersion; 573 optional = isOtional; 574 export = isExported; 575 match = prereqMatch; 576 } 577 578 public String toString() { 579 return name; 580 } 581 582 public boolean equals(Object prereq) { 583 if (!(prereq instanceof Prerequisite)) 584 return false; 585 return name.equals(((Prerequisite) prereq).name); 586 } 587 } 588 589 public void parsePluginRequiresImport(Attributes attributes) { 590 if (manifestInfo.requires == null) { 591 manifestInfo.requires = new ArrayList(); 592 } 596 String plugin = attributes.getValue("", PLUGIN_REQUIRES_PLUGIN); if (plugin == null) 599 return; 600 if (plugin.equals(PluginConverterImpl.PI_BOOT)) 601 return; 602 if (plugin.equals(PluginConverterImpl.PI_RUNTIME_COMPATIBILITY)) 603 manifestInfo.compatibilityFound = true; 604 String version = attributes.getValue("", PLUGIN_REQUIRES_PLUGIN_VERSION); String optional = attributes.getValue("", PLUGIN_REQUIRES_OPTIONAL); String export = attributes.getValue("", PLUGIN_REQUIRES_EXPORT); String match = attributes.getValue("", PLUGIN_REQUIRES_MATCH); manifestInfo.requires.add(new Prerequisite(plugin, version, "true".equalsIgnoreCase(optional) ? true : false, "true".equalsIgnoreCase(export) ? true : false, match)); } 610 611 public void parseRequiresAttributes(Attributes attributes) { 612 } 614 615 static String replace(String s, String from, String to) { 616 String str = s; 617 int fromLen = from.length(); 618 int toLen = to.length(); 619 int ix = str.indexOf(from); 620 while (ix != -1) { 621 str = str.substring(0, ix) + to + str.substring(ix + fromLen); 622 ix = str.indexOf(from, ix + toLen); 623 } 624 return str; 625 } 626 627 public void startDocument() { 628 stateStack.push(new Integer (INITIAL_STATE)); 629 } 630 631 public void startElement(String uri, String elementName, String qName, Attributes attributes) { 632 switch (((Integer ) stateStack.peek()).intValue()) { 633 case INITIAL_STATE : 634 handleInitialState(elementName, attributes); 635 break; 636 case FRAGMENT_STATE : 637 case PLUGIN_STATE : 638 handlePluginState(elementName, attributes); 639 break; 640 case PLUGIN_RUNTIME_STATE : 641 handleRuntimeState(elementName, attributes); 642 break; 643 case PLUGIN_REQUIRES_STATE : 644 handleRequiresState(elementName, attributes); 645 break; 646 case PLUGIN_EXTENSION_POINT_STATE : 647 handleExtensionPointState(elementName, attributes); 648 break; 649 case PLUGIN_EXTENSION_STATE : 650 handleExtensionState(elementName, attributes); 651 break; 652 case RUNTIME_LIBRARY_STATE : 653 handleLibraryState(elementName, attributes); 654 break; 655 case LIBRARY_EXPORT_STATE : 656 handleLibraryExportState(elementName, attributes); 657 break; 658 case PLUGIN_REQUIRES_IMPORT_STATE : 659 handleRequiresImportState(elementName, attributes); 660 break; 661 default : 662 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 663 } 664 } 665 666 public void warning(SAXParseException ex) { 667 logStatus(ex); 668 } 669 670 private void internalError(String elementName) { 671 FrameworkLogEntry error; 672 String message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_CONVERTER_PARSE_UNKNOWNTOP_ELEMENT, elementName); 673 error = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, (manifestInfo.pluginId == null ? message : "Plug-in : " + manifestInfo.pluginId + ", " + message), 0, null, null); adaptor.getFrameworkLog().log(error); 675 } 676 677 public void processingInstruction(String target, String data) throws SAXException { 678 if (target.equalsIgnoreCase("eclipse")) { manifestInfo.schemaVersion = "3.0"; StringTokenizer tokenizer = new StringTokenizer(data, "=\""); while (tokenizer.hasMoreTokens()) { 689 String token = tokenizer.nextToken(); 690 if (token.equalsIgnoreCase("version")) { if (!tokenizer.hasMoreTokens()) { 692 break; 693 } 694 manifestInfo.schemaVersion = tokenizer.nextToken(); 695 break; 696 } 697 } 698 } 699 } 700 } 701 | Popular Tags |