1 11 package org.eclipse.pde.internal.core.converter; 12 13 import java.io.InputStream ; 14 import java.util.*; 15 import javax.xml.parsers.SAXParserFactory ; 16 17 import org.eclipse.osgi.util.NLS; 18 import org.eclipse.pde.internal.core.PDECoreMessages; 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 PluginConverterParser extends DefaultHandler implements IModel { 29 private static ServiceTracker xmlTracker = null; 30 31 private PluginInfo manifestInfo = new PluginInfo(); 32 private BundleContext context; 33 private Version target; private static final Version TARGET21 = new Version(2, 1, 0); 35 36 public class PluginInfo { 37 private String schemaVersion; 38 private String pluginId; 39 private String version; 40 private String vendor; 41 42 private ArrayList libraryPaths; 44 private Map libraries; private ArrayList requires; 49 private boolean requiresExpanded = false; private boolean compatibilityFound = false; private String pluginClass; 52 private String masterPluginId; 53 private String masterVersion; 54 private String masterMatch; 55 private Set filters; 56 private String pluginName; 57 private boolean singleton; 58 private boolean fragment; 59 private final static String TARGET21_STRING = "2.1"; private boolean hasExtensionExtensionPoints = false; 61 62 public boolean isFragment() { 63 return fragment; 64 } 65 66 public String toString() { 67 return "plugin-id: " + pluginId + " version: " + version + " libraries: " + libraries + " class:" + pluginClass + " master: " + masterPluginId + " master-version: " + masterVersion + " requires: " + requires + " singleton: " + singleton; } 69 70 public Map getLibraries() { 71 if (libraries == null) 72 return new HashMap(0); 73 return libraries; 74 } 75 76 public ArrayList getRequires() { 77 if (!TARGET21.equals(target) && schemaVersion == null && !requiresExpanded) { 78 requiresExpanded = true; 79 if (requires == null) { 80 requires = new ArrayList(1); 81 requires.add(new Prerequisite(PluginConverter.PI_RUNTIME, TARGET21_STRING, false, false, IModel.PLUGIN_REQUIRES_MATCH_GREATER_OR_EQUAL)); 82 requires.add(new Prerequisite(PluginConverter.PI_RUNTIME_COMPATIBILITY, null, false, false, null)); 83 } else { 84 for (int i = 0; i < requires.size(); i++) { 86 Prerequisite analyzed = (Prerequisite) requires.get(i); 87 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 (PluginConverter.PI_RUNTIME.equals(analyzed.getName()) && !compatibilityFound) { 96 requires.add(i + 1, new Prerequisite(PluginConverter.PI_RUNTIME_COMPATIBILITY, null, false, analyzed.isExported(), null)); 97 } 98 } 99 if (!requires.contains(new Prerequisite(PluginConverter.PI_RUNTIME_COMPATIBILITY, null, false, false, null))) { 100 requires.add(new Prerequisite(PluginConverter.PI_RUNTIME_COMPATIBILITY, null, false, false, null)); 101 } 102 Prerequisite runtimePrereq = new Prerequisite(PluginConverter.PI_RUNTIME, null, false, false, null); 105 requires.remove(runtimePrereq); 106 requires.add(new Prerequisite(PluginConverter.PI_RUNTIME, TARGET21_STRING, false, false, IModel.PLUGIN_REQUIRES_MATCH_GREATER_OR_EQUAL)); 107 } 108 } 109 if (requires == null) 110 return requires = new ArrayList(0); 111 112 return requires; 113 } 114 115 public String getMasterId() { 116 return masterPluginId; 117 } 118 119 public String getMasterVersion() { 120 return masterVersion; 121 } 122 123 public String getMasterMatch() { 124 return masterMatch; 125 } 126 127 public String getPluginClass() { 128 return pluginClass; 129 } 130 131 public String getUniqueId() { 132 return pluginId; 133 } 134 135 public String getVersion() { 136 return version; 137 } 138 139 public Set getPackageFilters() { 140 return filters; 141 } 142 143 public String [] getLibrariesName() { 144 if (libraryPaths == null) 145 return new String [0]; 146 return (String []) libraryPaths.toArray(new String [libraryPaths.size()]); 147 } 148 149 public String getPluginName() { 150 return pluginName; 151 } 152 153 public String getProviderName() { 154 return vendor; 155 } 156 157 public boolean isSingleton() { 158 return singleton; 159 } 160 161 public boolean hasExtensionExtensionPoints() { 162 return hasExtensionExtensionPoints; 163 } 164 165 public String getRoot() { 166 return isFragment() ? FRAGMENT : PLUGIN; 167 } 168 169 173 public String validateForm() { 174 if (this.pluginId == null) { 175 return NLS.bind(PDECoreMessages.PluginParser_EclipseConverterMissingAttribute, new String [] {getRoot(), PLUGIN_ID, getRoot()}); 176 } 177 if (this.pluginName == null) { 178 return NLS.bind(PDECoreMessages.PluginParser_EclipseConverterMissingAttribute, new String [] {getRoot(), PLUGIN_NAME, getRoot()}); 179 } 180 if (this.version == null) { 181 return NLS.bind(PDECoreMessages.PluginParser_EclipseConverterMissingAttribute, new String [] {getRoot(), PLUGIN_VERSION, getRoot()}); 182 } 183 if (isFragment() && this.masterPluginId == null) { 184 return NLS.bind(PDECoreMessages.PluginParser_EclipseConverterMissingAttribute, new String [] {getRoot(), FRAGMENT_PLUGIN_ID, getRoot()}); 185 } 186 if (isFragment() && this.masterVersion == null) { 187 return NLS.bind(PDECoreMessages.PluginParser_EclipseConverterMissingAttribute, new String [] {getRoot(), FRAGMENT_PLUGIN_VERSION, getRoot()}); 188 } 189 return null; 190 } 191 } 192 193 Stack stateStack = new Stack(); 195 196 Stack objectStack = new Stack(); 198 Locator locator = null; 199 200 private static final int IGNORED_ELEMENT_STATE = 0; 202 private static final int INITIAL_STATE = 1; 203 private static final int PLUGIN_STATE = 2; 204 private static final int PLUGIN_RUNTIME_STATE = 3; 205 private static final int PLUGIN_REQUIRES_STATE = 4; 206 private static final int PLUGIN_EXTENSION_POINT_STATE = 5; 207 private static final int PLUGIN_EXTENSION_STATE = 6; 208 private static final int RUNTIME_LIBRARY_STATE = 7; 209 private static final int LIBRARY_EXPORT_STATE = 8; 210 private static final int PLUGIN_REQUIRES_IMPORT_STATE = 9; 211 private static final int FRAGMENT_STATE = 11; 212 213 public PluginConverterParser(BundleContext context, Version target) { 214 super(); 215 this.context = context; 216 this.target = target; 217 } 218 219 232 public void setDocumentLocator(Locator locator) { 233 this.locator = locator; 234 } 235 236 public void endDocument() { 237 } 238 239 public void endElement(String uri, String elementName, String qName) { 240 switch (((Integer ) stateStack.peek()).intValue()) { 241 case IGNORED_ELEMENT_STATE : 242 stateStack.pop(); 243 break; 244 case INITIAL_STATE : 245 break; 248 case PLUGIN_STATE : 249 case FRAGMENT_STATE : 250 break; 251 case PLUGIN_RUNTIME_STATE : 252 if (elementName.equals(RUNTIME)) { 253 stateStack.pop(); 254 } 255 break; 256 case PLUGIN_REQUIRES_STATE : 257 if (elementName.equals(PLUGIN_REQUIRES)) { 258 stateStack.pop(); 259 objectStack.pop(); 260 } 261 break; 262 case PLUGIN_EXTENSION_POINT_STATE : 263 if (elementName.equals(EXTENSION_POINT)) { 264 stateStack.pop(); 265 } 266 break; 267 case PLUGIN_EXTENSION_STATE : 268 if (elementName.equals(EXTENSION)) { 269 stateStack.pop(); 270 } 271 break; 272 case RUNTIME_LIBRARY_STATE : 273 if (elementName.equals(LIBRARY)) { 274 String curLibrary = (String ) objectStack.pop(); 275 if (!curLibrary.trim().equals("")) { Vector exportsVector = (Vector) objectStack.pop(); 277 if (manifestInfo.libraries == null) { 278 manifestInfo.libraries = new HashMap(3); 279 manifestInfo.libraryPaths = new ArrayList(3); 280 } 281 manifestInfo.libraries.put(curLibrary, exportsVector); 282 manifestInfo.libraryPaths.add(curLibrary.replace('\\', '/')); 283 } 284 stateStack.pop(); 285 } 286 break; 287 case LIBRARY_EXPORT_STATE : 288 if (elementName.equals(LIBRARY_EXPORT)) { 289 stateStack.pop(); 290 } 291 break; 292 case PLUGIN_REQUIRES_IMPORT_STATE : 293 if (elementName.equals(PLUGIN_REQUIRES_IMPORT)) { 294 stateStack.pop(); 295 } 296 break; 297 } 298 } 299 300 public void handleExtensionPointState(String elementName, Attributes attributes) { 301 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 303 manifestInfo.hasExtensionExtensionPoints = true; 304 } 305 306 public void handleExtensionState(String elementName, Attributes attributes) { 307 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 309 manifestInfo.hasExtensionExtensionPoints = true; 310 } 311 312 public void handleInitialState(String elementName, Attributes attributes) { 313 if (elementName.equals(PLUGIN)) { 314 stateStack.push(new Integer (PLUGIN_STATE)); 315 parsePluginAttributes(attributes); 316 } else if (elementName.equals(FRAGMENT)) { 317 manifestInfo.fragment = true; 318 stateStack.push(new Integer (FRAGMENT_STATE)); 319 parseFragmentAttributes(attributes); 320 } else { 321 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 322 internalError(elementName); 323 } 324 } 325 326 public void handleLibraryExportState(String elementName, Attributes attributes) { 327 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 329 } 330 331 public void handleLibraryState(String elementName, Attributes attributes) { 332 if (elementName.equals(LIBRARY_EXPORT)) { 333 stateStack.push(new Integer (LIBRARY_EXPORT_STATE)); 335 String currentLib = (String ) objectStack.peek(); 337 if (attributes == null) 338 return; 339 String maskValue = attributes.getValue("", LIBRARY_EXPORT_MASK); objectStack.pop(); 342 Vector exportMask = (Vector) objectStack.peek(); 343 objectStack.push(currentLib); 345 if (maskValue != null) { 347 StringTokenizer tok = new StringTokenizer(maskValue, ","); while (tok.hasMoreTokens()) { 349 String value = tok.nextToken(); 350 if (!exportMask.contains(maskValue)) 351 exportMask.addElement(value.trim()); 352 } 353 } 354 return; 355 } 356 if (elementName.equals(LIBRARY_PACKAGES)) { 357 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 358 return; 359 } 360 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 361 internalError(elementName); 362 return; 363 } 364 365 public void handlePluginState(String elementName, Attributes attributes) { 366 if (elementName.equals(RUNTIME)) { 367 Object whatIsIt = objectStack.peek(); 369 if ((whatIsIt instanceof PluginInfo) && ((PluginInfo) objectStack.peek()).libraries != null) { 370 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 372 return; 373 } 374 stateStack.push(new Integer (PLUGIN_RUNTIME_STATE)); 375 return; 377 } 378 if (elementName.equals(PLUGIN_REQUIRES)) { 379 stateStack.push(new Integer (PLUGIN_REQUIRES_STATE)); 380 objectStack.push(new Vector()); 382 parseRequiresAttributes(attributes); 383 return; 384 } 385 if (elementName.equals(EXTENSION_POINT)) { 386 manifestInfo.singleton = true; 388 stateStack.push(new Integer (PLUGIN_EXTENSION_POINT_STATE)); 389 return; 390 } 391 if (elementName.equals(EXTENSION)) { 392 manifestInfo.singleton = true; 394 stateStack.push(new Integer (PLUGIN_EXTENSION_STATE)); 395 return; 396 } 397 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 400 internalError(elementName); 401 } 402 403 public void handleRequiresImportState(String elementName, Attributes attributes) { 404 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 406 } 407 408 public void handleRequiresState(String elementName, Attributes attributes) { 409 if (elementName.equals(PLUGIN_REQUIRES_IMPORT)) { 410 parsePluginRequiresImport(attributes); 411 return; 412 } 413 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 416 internalError(elementName); 417 } 418 419 public void handleRuntimeState(String elementName, Attributes attributes) { 420 if (elementName.equals(LIBRARY)) { 421 stateStack.push(new Integer (RUNTIME_LIBRARY_STATE)); 423 parseLibraryAttributes(attributes); 425 return; 426 } 427 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 430 internalError(elementName); 431 } 432 433 synchronized public PluginInfo parsePlugin(InputStream in) throws Exception { 434 SAXParserFactory factory = acquireXMLParsing(context); 435 if (factory == null) { 436 return null; 439 } 440 441 factory.setNamespaceAware(true); 442 factory.setNamespaceAware(true); 443 try { 444 factory.setFeature("http://xml.org/sax/features/string-interning", true); } catch (SAXException se) { 446 } 448 factory.setValidating(false); 449 factory.newSAXParser().parse(in, this); 450 return manifestInfo; 451 } 452 453 public static SAXParserFactory acquireXMLParsing(BundleContext context) { 454 if (xmlTracker == null) { 455 xmlTracker = new ServiceTracker(context, "javax.xml.parsers.SAXParserFactory", null); xmlTracker.open(); 457 } 458 SAXParserFactory result = (SAXParserFactory ) xmlTracker.getService(); 459 if (result != null) 460 return result; 461 return SAXParserFactory.newInstance(); 463 } 464 465 public static void releaseXMLParsing() { 466 if (xmlTracker != null) 467 xmlTracker.close(); 468 } 469 470 public void parseFragmentAttributes(Attributes attributes) { 471 objectStack.push(manifestInfo); 473 int len = attributes.getLength(); 474 for (int i = 0; i < len; i++) { 475 String attrName = attributes.getLocalName(i); 476 String attrValue = attributes.getValue(i).trim(); 477 if (attrName.equals(FRAGMENT_ID)) 478 manifestInfo.pluginId = attrValue; 479 else if (attrName.equals(FRAGMENT_NAME)) 480 manifestInfo.pluginName = attrValue; 481 else if (attrName.equals(FRAGMENT_VERSION)) 482 manifestInfo.version = attrValue; 483 else if (attrName.equals(FRAGMENT_PROVIDER)) 484 manifestInfo.vendor = attrValue; 485 else if (attrName.equals(FRAGMENT_PLUGIN_ID)) 486 manifestInfo.masterPluginId = attrValue; 487 else if (attrName.equals(FRAGMENT_PLUGIN_VERSION)) 488 manifestInfo.masterVersion = attrValue; 489 else if (attrName.equals(FRAGMENT_PLUGIN_MATCH)) 490 manifestInfo.masterMatch = attrValue; 491 } 492 } 493 494 public void parseLibraryAttributes(Attributes attributes) { 495 objectStack.push(new Vector()); 497 String current = attributes.getValue("", LIBRARY_NAME); objectStack.push(current); 499 } 500 501 public void parsePluginAttributes(Attributes attributes) { 502 objectStack.push(manifestInfo); 504 int len = attributes.getLength(); 505 for (int i = 0; i < len; i++) { 506 String attrName = attributes.getLocalName(i); 507 String attrValue = attributes.getValue(i).trim(); 508 if (attrName.equals(PLUGIN_ID)) 509 manifestInfo.pluginId = attrValue; 510 else if (attrName.equals(PLUGIN_NAME)) 511 manifestInfo.pluginName = attrValue; 512 else if (attrName.equals(PLUGIN_VERSION)) 513 manifestInfo.version = attrValue; 514 else if (attrName.equals(PLUGIN_VENDOR) || (attrName.equals(PLUGIN_PROVIDER))) 515 manifestInfo.vendor = attrValue; 516 else if (attrName.equals(PLUGIN_CLASS)) 517 manifestInfo.pluginClass = attrValue; 518 } 519 } 520 521 public class Prerequisite { 522 String name; 523 String version; 524 boolean optional; 525 boolean export; 526 String match; 527 528 public boolean isExported() { 529 return export; 530 } 531 532 public String getMatch() { 533 return match; 534 } 535 536 public String getName() { 537 return name; 538 } 539 540 public boolean isOptional() { 541 return optional; 542 } 543 544 public String getVersion() { 545 return version; 546 } 547 548 public Prerequisite(String preqName, String prereqVersion, boolean isOtional, boolean isExported, String prereqMatch) { 549 name = preqName; 550 version = prereqVersion; 551 optional = isOtional; 552 export = isExported; 553 match = prereqMatch; 554 } 555 556 public String toString() { 557 return name; 558 } 559 560 public boolean equals(Object prereq) { 561 if (!(prereq instanceof Prerequisite)) 562 return false; 563 return name.equals(((Prerequisite) prereq).name); 564 } 565 } 566 567 public void parsePluginRequiresImport(Attributes attributes) { 568 if (manifestInfo.requires == null) { 569 manifestInfo.requires = new ArrayList(); 570 } 574 String plugin = attributes.getValue("", PLUGIN_REQUIRES_PLUGIN); if (plugin == null) 577 return; 578 if (plugin.equals(PluginConverter.PI_BOOT)) 579 return; 580 if (plugin.equals(PluginConverter.PI_RUNTIME_COMPATIBILITY)) 581 manifestInfo.compatibilityFound = true; 582 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)); } 588 589 public void parseRequiresAttributes(Attributes attributes) { 590 } 592 593 static String replace(String s, String from, String to) { 594 String str = s; 595 int fromLen = from.length(); 596 int toLen = to.length(); 597 int ix = str.indexOf(from); 598 while (ix != -1) { 599 str = str.substring(0, ix) + to + str.substring(ix + fromLen); 600 ix = str.indexOf(from, ix + toLen); 601 } 602 return str; 603 } 604 605 public void startDocument() { 606 stateStack.push(new Integer (INITIAL_STATE)); 607 } 608 609 public void startElement(String uri, String elementName, String qName, Attributes attributes) { 610 switch (((Integer ) stateStack.peek()).intValue()) { 611 case INITIAL_STATE : 612 handleInitialState(elementName, attributes); 613 break; 614 case FRAGMENT_STATE : 615 case PLUGIN_STATE : 616 handlePluginState(elementName, attributes); 617 break; 618 case PLUGIN_RUNTIME_STATE : 619 handleRuntimeState(elementName, attributes); 620 break; 621 case PLUGIN_REQUIRES_STATE : 622 handleRequiresState(elementName, attributes); 623 break; 624 case PLUGIN_EXTENSION_POINT_STATE : 625 handleExtensionPointState(elementName, attributes); 626 break; 627 case PLUGIN_EXTENSION_STATE : 628 handleExtensionState(elementName, attributes); 629 break; 630 case RUNTIME_LIBRARY_STATE : 631 handleLibraryState(elementName, attributes); 632 break; 633 case LIBRARY_EXPORT_STATE : 634 handleLibraryExportState(elementName, attributes); 635 break; 636 case PLUGIN_REQUIRES_IMPORT_STATE : 637 handleRequiresImportState(elementName, attributes); 638 break; 639 default : 640 stateStack.push(new Integer (IGNORED_ELEMENT_STATE)); 641 } 642 } 643 644 private void internalError(String elementName) { 645 } 649 650 public void processingInstruction(String target, String data) throws SAXException { 651 if (target.equalsIgnoreCase("eclipse")) { manifestInfo.schemaVersion = "3.0"; StringTokenizer tokenizer = new StringTokenizer(data, "=\""); while (tokenizer.hasMoreTokens()) { 662 String token = tokenizer.nextToken(); 663 if (token.equalsIgnoreCase("version")) { if (!tokenizer.hasMoreTokens()) { 665 break; 666 } 667 manifestInfo.schemaVersion = tokenizer.nextToken(); 668 break; 669 } 670 } 671 } 672 } 673 } 674 | Popular Tags |