1 11 package org.eclipse.core.runtime.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.osgi.framework.BundleContext; 19 import org.osgi.util.tracker.ServiceTracker; 20 import org.xml.sax.*; 21 import org.xml.sax.helpers.DefaultHandler ; 22 23 26 public class PluginParser extends DefaultHandler implements IModel { 27 private static ServiceTracker xmlTracker = null; 28 29 private PluginInfo manifestInfo = new PluginInfo(); 30 private BundleContext context; 31 private String target; 33 public class PluginInfo implements IPluginInfo { 34 private String schemaVersion; 35 private String pluginId; 36 private String version; 37 private String vendor; 38 39 private ArrayList libraryPaths; 41 private Map libraries; private ArrayList requires; 46 private boolean requiresExpanded = false; private boolean compatibilityFound = false; private String pluginClass; 49 private String masterPluginId; 50 private String masterVersion; 51 private String masterMatch; 52 private Set filters; 53 private String pluginName; 54 private boolean singleton; 55 private boolean fragment; 56 private static final String TARGET21 = "2.1"; 58 public boolean isFragment() { 59 return fragment; 60 } 61 62 public String toString() { 63 return "plugin-id: " + pluginId + " version: " + version + " libraries: " + libraries + " class:" + pluginClass + " master: " + masterPluginId + " master-version: " + masterVersion + " requires: " + requires + " singleton: " + singleton; } 65 66 public Map getLibraries() { 67 if (libraries == null) 68 return new HashMap(0); 69 return libraries; 70 } 71 72 public ArrayList getRequires() { 73 if (!TARGET21.equals(target) && schemaVersion == null && !requiresExpanded) { 74 requiresExpanded = true; 75 if (requires == null) { 76 requires = new ArrayList(1); 77 requires.add(new Prerequisite(PluginConverterImpl.PI_RUNTIME, TARGET21, false, false, IModel.PLUGIN_REQUIRES_MATCH_GREATER_OR_EQUAL)); 78 requires.add(new Prerequisite(PluginConverterImpl.PI_RUNTIME_COMPATIBILITY, null, false, false, null)); 79 } else { 80 for (int i = 0; i < requires.size(); i++) { 82 Prerequisite analyzed = (Prerequisite) requires.get(i); 83 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) { 92 requires.add(i + 1, new Prerequisite(PluginConverterImpl.PI_RUNTIME_COMPATIBILITY, null, false, analyzed.isExported(), null)); 93 } 94 } 95 if (!requires.contains(new Prerequisite(PluginConverterImpl.PI_RUNTIME_COMPATIBILITY, null, false, false, null))) { 96 requires.add(new Prerequisite(PluginConverterImpl.PI_RUNTIME_COMPATIBILITY, null, false, false, null)); 97 } 98 Prerequisite runtimePrereq = new Prerequisite(PluginConverterImpl.PI_RUNTIME, null, false, false, null); 101 requires.remove(runtimePrereq); 102 requires.add(new Prerequisite(PluginConverterImpl.PI_RUNTIME, TARGET21, false, false, IModel.PLUGIN_REQUIRES_MATCH_GREATER_OR_EQUAL)); 103 } 104 } 105 if (requires == null) 106 return requires = new ArrayList(0); 107 108 return requires; 109 } 110 111 public String getMasterId() { 112 return masterPluginId; 113 } 114 115 public String getMasterVersion() { 116 return masterVersion; 117 } 118 119 public String getMasterMatch() { 120 return masterMatch; 121 } 122 123 public String getPluginClass() { 124 return pluginClass; 125 } 126 127 public String getUniqueId() { 128 return pluginId; 129 } 130 131 public String getVersion() { 132 return version; 133 } 134 135 public Set getPackageFilters() { 136 return filters; 137 } 138 139 public String [] getLibrariesName() { 140 if (libraryPaths == null) 141 return new String [0]; 142 return (String []) libraryPaths.toArray(new String [libraryPaths.size()]); 143 } 144 145 public String getPluginName() { 146 return pluginName; 147 } 148 149 public String getProviderName() { 150 return vendor; 151 } 152 153 public boolean isSingleton() { 154 return singleton; 155 } 156 157 public String getRoot() { 158 return isFragment() ? FRAGMENT : PLUGIN; 159 } 160 161 165 public String validateForm() { 166 if (this.pluginId == null) 167 return EclipseAdaptorMsg.formatter.getString("ECLIPSE_CONVERTER_MISSING_ATTRIBUTE", new String [] {getRoot(), PLUGIN_ID, getRoot()}); if (this.pluginName == null) 169 return EclipseAdaptorMsg.formatter.getString("ECLIPSE_CONVERTER_MISSING_ATTRIBUTE", new String [] {getRoot(), PLUGIN_NAME, getRoot()}); if (this.version == null) 171 return EclipseAdaptorMsg.formatter.getString("ECLIPSE_CONVERTER_MISSING_ATTRIBUTE", new String [] {getRoot(), PLUGIN_VERSION, getRoot()}); if (isFragment() && this.masterPluginId == null) 173 return EclipseAdaptorMsg.formatter.getString("ECLIPSE_CONVERTER_MISSING_ATTRIBUTE", new String [] {getRoot(), FRAGMENT_PLUGIN_ID, getRoot()}); if (isFragment() && this.masterVersion == null) 175 return EclipseAdaptorMsg.formatter.getString("ECLIPSE_CONVERTER_MISSING_ATTRIBUTE", new String [] {getRoot(), FRAGMENT_PLUGIN_VERSION, getRoot()}); return null; 177 } 178 } 179 180 Stack stateStack = new Stack(); 182 183 Stack objectStack = new Stack(); 185 Locator locator = null; 186 187 private static final int IGNORED_ELEMENT_STATE = 0; 189 private static final int INITIAL_STATE = 1; 190 private static final int PLUGIN_STATE = 2; 191 private static final int PLUGIN_RUNTIME_STATE = 3; 192 private static final int PLUGIN_REQUIRES_STATE = 4; 193 private static final int PLUGIN_EXTENSION_POINT_STATE = 5; 194 private static final int PLUGIN_EXTENSION_STATE = 6; 195 private static final int RUNTIME_LIBRARY_STATE = 7; 196 private static final int LIBRARY_EXPORT_STATE = 8; 197 private static final int PLUGIN_REQUIRES_IMPORT_STATE = 9; 198 private static final int FRAGMENT_STATE = 11; 199 200 public PluginParser(BundleContext context, String target) { 201 super(); 202 this.context = context; 203 this.target = target; 204 } 205 206 219 public void setDocumentLocator(Locator locator) { 220 this.locator = locator; 221 } 222 223 public void endDocument() { 224 } 225 226 public void endElement(String uri, String elementName, String qName) { 227 switch (((Integer ) stateStack.peek()).intValue()) { 228 case IGNORED_ELEMENT_STATE : 229 stateStack.pop(); 230 break; 231 case INITIAL_STATE : 232 break; 235 case PLUGIN_STATE : 236 case FRAGMENT_STATE : 237 break; 238 case PLUGIN_RUNTIME_STATE : 239 if (elementName.equals(RUNTIME)) { 240 stateStack.pop(); 241 } 242 break; 243 case PLUGIN_REQUIRES_STATE : 244 if (elementName.equals(PLUGIN_REQUIRES)) { 245 stateStack.pop(); 246 objectStack.pop(); 247 } 248 break; 249 case PLUGIN_EXTENSION_POINT_STATE : 250 if (elementName.equals(EXTENSION_POINT)) { 251 stateStack.pop(); 252 } 253 break; 254 case PLUGIN_EXTENSION_STATE : 255 if (elementName.equals(EXTENSION)) { 256 stateStack.pop(); 257 } 258 break; 259 case RUNTIME_LIBRARY_STATE : 260 if (elementName.equals(LIBRARY)) { 261 String curLibrary = (String ) objectStack.pop(); 262 if (!curLibrary.trim().equals("")) { Vector exportsVector = (Vector) objectStack.pop(); 264 if (manifestInfo.libraries == null) { 265 manifestInfo.libraries = new HashMap(3); 266 manifestInfo.libraryPaths = new ArrayList(3); 267 } 268 manifestInfo.libraries.put(curLibrary, exportsVector); 269 manifestInfo.libraryPaths.add(curLibrary.replace('\\', '/')); 270 } 271 stateStack.pop(); 272 } 273 break; 274 case LIBRARY_EXPORT_STATE : 275 if (elementName.equals(LIBRARY_EXPORT)) { 276 stateStack.pop(); 277 } 278 break; 279 case PLUGIN_REQUIRES_IMPORT_STATE : 280 if (elementName.equals(PLUGIN_REQUIRES_IMPORT)) { 281 stateStack.pop(); 282 } 283 break; 284 } 285 } 286 287 public void error(SAXParseException ex) { 288 logStatus(ex); 289 } 290 291 public void fatalError(SAXParseException ex) throws SAXException { 292 logStatus(ex); 293 throw ex; 294 } 295 296 public void handleExtensionPointState(String elementName, Attributes attributes) { 297 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 299 } 300 301 public void handleExtensionState(String elementName, Attributes attributes) { 302 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 304 } 305 306 public void handleInitialState(String elementName, Attributes attributes) { 307 if (elementName.equals(PLUGIN)) { 308 stateStack.push(new Integer (PLUGIN_STATE)); 309 parsePluginAttributes(attributes); 310 } else if (elementName.equals(FRAGMENT)) { 311 manifestInfo.fragment = true; 312 stateStack.push(new Integer (FRAGMENT_STATE)); 313 parseFragmentAttributes(attributes); 314 } else { 315 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 316 internalError(elementName); 317 } 318 } 319 320 public void handleLibraryExportState(String elementName, Attributes attributes) { 321 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 323 } 324 325 public void handleLibraryState(String elementName, Attributes attributes) { 326 if (elementName.equals(LIBRARY_EXPORT)) { 327 stateStack.push(new Integer (LIBRARY_EXPORT_STATE)); 329 String currentLib = (String ) objectStack.peek(); 331 if (attributes == null) 332 return; 333 String maskValue = attributes.getValue("", LIBRARY_EXPORT_MASK); objectStack.pop(); 336 Vector exportMask = (Vector) objectStack.peek(); 337 objectStack.push(currentLib); 339 if (maskValue != null) { 341 StringTokenizer tok = new StringTokenizer(maskValue, ","); while (tok.hasMoreTokens()) { 343 String value = tok.nextToken(); 344 if (!exportMask.contains(maskValue)) 345 exportMask.addElement(value.trim()); 346 } 347 } 348 return; 349 } 350 if (elementName.equals(LIBRARY_PACKAGES)) { 351 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 352 return; 353 } 354 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 355 internalError(elementName); 356 return; 357 } 358 359 public void handlePluginState(String elementName, Attributes attributes) { 360 if (elementName.equals(RUNTIME)) { 361 Object whatIsIt = objectStack.peek(); 363 if ((whatIsIt instanceof PluginInfo) && ((PluginInfo) objectStack.peek()).libraries != null) { 364 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 366 return; 367 } 368 stateStack.push(new Integer (PLUGIN_RUNTIME_STATE)); 369 return; 371 } 372 if (elementName.equals(PLUGIN_REQUIRES)) { 373 stateStack.push(new Integer (PLUGIN_REQUIRES_STATE)); 374 objectStack.push(new Vector()); 376 parseRequiresAttributes(attributes); 377 return; 378 } 379 if (elementName.equals(EXTENSION_POINT)) { 380 manifestInfo.singleton = true; 382 stateStack.push(new Integer (PLUGIN_EXTENSION_POINT_STATE)); 383 return; 384 } 385 if (elementName.equals(EXTENSION)) { 386 manifestInfo.singleton = true; 388 stateStack.push(new Integer (PLUGIN_EXTENSION_STATE)); 389 return; 390 } 391 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 394 internalError(elementName); 395 } 396 397 public void handleRequiresImportState(String elementName, Attributes attributes) { 398 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 400 } 401 402 public void handleRequiresState(String elementName, Attributes attributes) { 403 if (elementName.equals(PLUGIN_REQUIRES_IMPORT)) { 404 parsePluginRequiresImport(attributes); 405 return; 406 } 407 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 410 internalError(elementName); 411 } 412 413 public void handleRuntimeState(String elementName, Attributes attributes) { 414 if (elementName.equals(LIBRARY)) { 415 stateStack.push(new Integer (RUNTIME_LIBRARY_STATE)); 417 parseLibraryAttributes(attributes); 419 return; 420 } 421 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 424 internalError(elementName); 425 } 426 427 private void logStatus(SAXParseException ex) { 428 String name = ex.getSystemId(); 429 if (name == null) 430 name = ""; else 432 name = name.substring(1 + name.lastIndexOf("/")); String msg; 434 if (name.equals("")) msg = EclipseAdaptorMsg.formatter.getString("parse.error", ex.getMessage()); else 437 msg = EclipseAdaptorMsg.formatter.getString("parse.errorNameLineColumn", new String [] {name, Integer.toString(ex.getLineNumber()), Integer.toString(ex.getColumnNumber()), ex.getMessage()}); 439 FrameworkLogEntry entry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, msg, 0, ex, null); 440 EclipseAdaptor.getDefault().getFrameworkLog().log(entry); 441 } 442 443 synchronized public PluginInfo parsePlugin(InputStream in) throws Exception { 444 SAXParserFactory factory = acquireXMLParsing(context); 445 if (factory == null) { 446 FrameworkLogEntry entry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, EclipseAdaptorMsg.formatter.getString("ECLIPSE_CONVERTER_NO_SAX_FACTORY"), 0, null, null); EclipseAdaptor.getDefault().getFrameworkLog().log(entry); 448 return null; 449 } 450 451 factory.setNamespaceAware(true); 452 factory.setNamespaceAware(true); 453 try { 454 factory.setFeature("http://xml.org/sax/features/string-interning", true); } catch (SAXException se) { 456 } 458 factory.setValidating(false); 459 factory.newSAXParser().parse(in, this); 460 return manifestInfo; 461 } 462 463 public static SAXParserFactory acquireXMLParsing(BundleContext context) { 464 if (xmlTracker == null) { 465 xmlTracker = new ServiceTracker(context, "javax.xml.parsers.SAXParserFactory", null); 466 xmlTracker.open(); 467 } 468 return (SAXParserFactory ) xmlTracker.getService(); 469 } 470 471 public static void releaseXMLParsing() { 472 if (xmlTracker != null) 473 xmlTracker.close(); 474 } 475 476 public void parseFragmentAttributes(Attributes attributes) { 477 objectStack.push(manifestInfo); 479 int len = attributes.getLength(); 480 for (int i = 0; i < len; i++) { 481 String attrName = attributes.getLocalName(i); 482 String attrValue = attributes.getValue(i).trim(); 483 if (attrName.equals(FRAGMENT_ID)) 484 manifestInfo.pluginId = attrValue; 485 else if (attrName.equals(FRAGMENT_NAME)) 486 manifestInfo.pluginName = attrValue; 487 else if (attrName.equals(FRAGMENT_VERSION)) 488 manifestInfo.version = attrValue; 489 else if (attrName.equals(FRAGMENT_PROVIDER)) 490 manifestInfo.vendor = attrValue; 491 else if (attrName.equals(FRAGMENT_PLUGIN_ID)) 492 manifestInfo.masterPluginId = attrValue; 493 else if (attrName.equals(FRAGMENT_PLUGIN_VERSION)) 494 manifestInfo.masterVersion = attrValue; 495 else if (attrName.equals(FRAGMENT_PLUGIN_MATCH)) 496 manifestInfo.masterMatch = attrValue; 497 } 498 } 499 500 public void parseLibraryAttributes(Attributes attributes) { 501 objectStack.push(new Vector()); 503 String current = attributes.getValue("", LIBRARY_NAME); objectStack.push(current); 505 } 506 507 public void parsePluginAttributes(Attributes attributes) { 508 objectStack.push(manifestInfo); 510 int len = attributes.getLength(); 511 for (int i = 0; i < len; i++) { 512 String attrName = attributes.getLocalName(i); 513 String attrValue = attributes.getValue(i).trim(); 514 if (attrName.equals(PLUGIN_ID)) 515 manifestInfo.pluginId = attrValue; 516 else if (attrName.equals(PLUGIN_NAME)) 517 manifestInfo.pluginName = attrValue; 518 else if (attrName.equals(PLUGIN_VERSION)) 519 manifestInfo.version = attrValue; 520 else if (attrName.equals(PLUGIN_VENDOR) || (attrName.equals(PLUGIN_PROVIDER))) 521 manifestInfo.vendor = attrValue; 522 else if (attrName.equals(PLUGIN_CLASS)) 523 manifestInfo.pluginClass = attrValue; 524 } 525 } 526 527 public class Prerequisite { 528 String name; 529 String version; 530 boolean optional; 531 boolean export; 532 String match; 533 534 public boolean isExported() { 535 return export; 536 } 537 538 public String getMatch() { 539 return match; 540 } 541 542 public String getName() { 543 return name; 544 } 545 546 public boolean isOptional() { 547 return optional; 548 } 549 550 public String getVersion() { 551 return version; 552 } 553 554 public Prerequisite(String preqName, String prereqVersion, boolean isOtional, boolean isExported, String prereqMatch) { 555 name = preqName; 556 version = prereqVersion; 557 optional = isOtional; 558 export = isExported; 559 match = prereqMatch; 560 } 561 562 public String toString() { 563 return name; 564 } 565 566 public boolean equals(Object prereq) { 567 if (!(prereq instanceof Prerequisite)) 568 return false; 569 return name.equals(((Prerequisite) prereq).name); 570 } 571 } 572 573 public void parsePluginRequiresImport(Attributes attributes) { 574 if (manifestInfo.requires == null) { 575 manifestInfo.requires = new ArrayList(); 576 } 580 String plugin = attributes.getValue("", PLUGIN_REQUIRES_PLUGIN); if (plugin == null) 583 return; 584 if (plugin.equals(PluginConverterImpl.PI_BOOT)) return; 586 if (plugin.equals(PluginConverterImpl.PI_RUNTIME_COMPATIBILITY)) 587 manifestInfo.compatibilityFound = true; 588 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)); } 594 595 public void parseRequiresAttributes(Attributes attributes) { 596 } 598 599 static String replace(String s, String from, String to) { 600 String str = s; 601 int fromLen = from.length(); 602 int toLen = to.length(); 603 int ix = str.indexOf(from); 604 while (ix != -1) { 605 str = str.substring(0, ix) + to + str.substring(ix + fromLen); 606 ix = str.indexOf(from, ix + toLen); 607 } 608 return str; 609 } 610 611 public void startDocument() { 612 stateStack.push(new Integer (INITIAL_STATE)); 613 } 614 615 public void startElement(String uri, String elementName, String qName, Attributes attributes) { 616 switch (((Integer ) stateStack.peek()).intValue()) { 617 case INITIAL_STATE : 618 handleInitialState(elementName, attributes); 619 break; 620 case FRAGMENT_STATE : 621 case PLUGIN_STATE : 622 handlePluginState(elementName, attributes); 623 break; 624 case PLUGIN_RUNTIME_STATE : 625 handleRuntimeState(elementName, attributes); 626 break; 627 case PLUGIN_REQUIRES_STATE : 628 handleRequiresState(elementName, attributes); 629 break; 630 case PLUGIN_EXTENSION_POINT_STATE : 631 handleExtensionPointState(elementName, attributes); 632 break; 633 case PLUGIN_EXTENSION_STATE : 634 handleExtensionState(elementName, attributes); 635 break; 636 case RUNTIME_LIBRARY_STATE : 637 handleLibraryState(elementName, attributes); 638 break; 639 case LIBRARY_EXPORT_STATE : 640 handleLibraryExportState(elementName, attributes); 641 break; 642 case PLUGIN_REQUIRES_IMPORT_STATE : 643 handleRequiresImportState(elementName, attributes); 644 break; 645 default : 646 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 647 } 648 } 649 650 public void warning(SAXParseException ex) { 651 logStatus(ex); 652 } 653 654 private void internalError(String elementName) { 655 FrameworkLogEntry error; 656 String message = EclipseAdaptorMsg.formatter.getString("ECLIPSE_CONVERTER_PARSE_UNKNOWNTOP_ELEMENT", elementName); error = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, (manifestInfo.pluginId == null ? message : "Plug-in : " + manifestInfo.pluginId + ", " + message), 0, null, null); EclipseAdaptor.getDefault().getFrameworkLog().log(error); 659 } 660 661 public void processingInstruction(String target, String data) throws SAXException { 662 if (target.equalsIgnoreCase("eclipse")) { manifestInfo.schemaVersion = "3.0"; StringTokenizer tokenizer = new StringTokenizer(data, "=\""); while (tokenizer.hasMoreTokens()) { 673 String token = tokenizer.nextToken(); 674 if (token.equalsIgnoreCase("version")) { if (!tokenizer.hasMoreTokens()) { 676 break; 677 } 678 manifestInfo.schemaVersion = tokenizer.nextToken(); 679 break; 680 } 681 } 682 } 683 } 684 } | Popular Tags |