1 11 package org.eclipse.jdt.internal.core; 12 13 import java.io.ByteArrayOutputStream ; 14 import java.io.File ; 15 import java.io.OutputStreamWriter ; 16 import java.io.UnsupportedEncodingException ; 17 import java.util.ArrayList ; 18 import java.util.HashMap ; 19 import java.util.HashSet ; 20 import java.util.Map ; 21 22 import org.eclipse.core.resources.IProject; 23 import org.eclipse.core.resources.IResource; 24 import org.eclipse.core.resources.IWorkspaceRoot; 25 import org.eclipse.core.resources.ResourcesPlugin; 26 import org.eclipse.core.runtime.AssertionFailedException; 27 import org.eclipse.core.runtime.CoreException; 28 import org.eclipse.core.runtime.IPath; 29 import org.eclipse.core.runtime.IStatus; 30 import org.eclipse.core.runtime.Path; 31 import org.eclipse.jdt.core.IAccessRule; 32 import org.eclipse.jdt.core.IClasspathAttribute; 33 import org.eclipse.jdt.core.IClasspathContainer; 34 import org.eclipse.jdt.core.IClasspathEntry; 35 import org.eclipse.jdt.core.IJavaModelStatus; 36 import org.eclipse.jdt.core.IJavaModelStatusConstants; 37 import org.eclipse.jdt.core.IJavaProject; 38 import org.eclipse.jdt.core.IPackageFragmentRoot; 39 import org.eclipse.jdt.core.JavaCore; 40 import org.eclipse.jdt.core.JavaModelException; 41 import org.eclipse.jdt.core.compiler.CharOperation; 42 import org.eclipse.jdt.core.compiler.IProblem; 43 import org.eclipse.jdt.internal.compiler.env.AccessRuleSet; 44 import org.eclipse.jdt.internal.compiler.env.AccessRule; 45 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; 46 import org.eclipse.jdt.internal.core.util.Messages; 47 import org.eclipse.jdt.internal.core.util.Util; 48 import org.w3c.dom.DOMException ; 49 import org.w3c.dom.Element ; 50 import org.w3c.dom.NamedNodeMap ; 51 import org.w3c.dom.Node ; 52 import org.w3c.dom.NodeList ; 53 import org.w3c.dom.Text ; 54 55 58 public class ClasspathEntry implements IClasspathEntry { 59 60 public static final String TAG_CLASSPATH = "classpath"; public static final String TAG_CLASSPATHENTRY = "classpathentry"; public static final String TAG_OUTPUT = "output"; public static final String TAG_KIND = "kind"; public static final String TAG_PATH = "path"; public static final String TAG_SOURCEPATH = "sourcepath"; public static final String TAG_ROOTPATH = "rootpath"; public static final String TAG_EXPORTED = "exported"; public static final String TAG_INCLUDING = "including"; public static final String TAG_EXCLUDING = "excluding"; public static final String TAG_ATTRIBUTES = "attributes"; public static final String TAG_ATTRIBUTE = "attribute"; public static final String TAG_ATTRIBUTE_NAME = "name"; public static final String TAG_ATTRIBUTE_VALUE = "value"; public static final String TAG_COMBINE_ACCESS_RULES = "combineaccessrules"; public static final String TAG_ACCESS_RULES = "accessrules"; public static final String TAG_ACCESS_RULE = "accessrule"; public static final String TAG_PATTERN = "pattern"; public static final String TAG_ACCESSIBLE = "accessible"; public static final String TAG_NON_ACCESSIBLE = "nonaccessible"; public static final String TAG_DISCOURAGED = "discouraged"; public static final String TAG_IGNORE_IF_BETTER = "ignoreifbetter"; 83 87 public int entryKind; 88 89 94 public int contentKind; 95 96 116 public IPath path; 117 118 121 private IPath[] inclusionPatterns; 122 private char[][] fullInclusionPatternChars; 123 private IPath[] exclusionPatterns; 124 private char[][] fullExclusionPatternChars; 125 private final static char[][] UNINIT_PATTERNS = new char[][] { "Non-initialized yet".toCharArray() }; 127 private boolean combineAccessRules; 128 129 private String rootID; 130 private AccessRuleSet accessRuleSet; 131 132 133 static class UnknownXmlElements { 134 String [] attributes; 135 ArrayList children; 136 } 137 138 141 public final static IPath[] INCLUDE_ALL = {}; 142 143 146 public final static IPath[] EXCLUDE_NONE = {}; 147 148 151 public final static IClasspathAttribute[] NO_EXTRA_ATTRIBUTES = {}; 152 153 156 public final static IAccessRule[] NO_ACCESS_RULES = {}; 157 158 169 public IPath sourceAttachmentPath; 170 171 178 public IPath sourceAttachmentRootPath; 179 180 183 public IPath specificOutputLocation; 184 185 188 public static final int K_OUTPUT = 10; 189 190 193 public boolean isExported; 194 195 198 IClasspathAttribute[] extraAttributes; 199 200 203 public ClasspathEntry( 204 int contentKind, 205 int entryKind, 206 IPath path, 207 IPath[] inclusionPatterns, 208 IPath[] exclusionPatterns, 209 IPath sourceAttachmentPath, 210 IPath sourceAttachmentRootPath, 211 IPath specificOutputLocation, 212 boolean isExported, 213 IAccessRule[] accessRules, 214 boolean combineAccessRules, 215 IClasspathAttribute[] extraAttributes) { 216 217 this.contentKind = contentKind; 218 this.entryKind = entryKind; 219 this.path = path; 220 this.inclusionPatterns = inclusionPatterns; 221 this.exclusionPatterns = exclusionPatterns; 222 223 int length; 224 if (accessRules != null && (length = accessRules.length) > 0) { 225 AccessRule[] rules = new AccessRule[length]; 226 System.arraycopy(accessRules, 0, rules, 0, length); 227 this.accessRuleSet = new AccessRuleSet(rules, getMessageTemplates()); 228 } 229 233 this.combineAccessRules = combineAccessRules; 234 this.extraAttributes = extraAttributes; 235 236 if (inclusionPatterns != INCLUDE_ALL && inclusionPatterns.length > 0) { 237 this.fullInclusionPatternChars = UNINIT_PATTERNS; 238 } 239 if (exclusionPatterns.length > 0) { 240 this.fullExclusionPatternChars = UNINIT_PATTERNS; 241 } 242 this.sourceAttachmentPath = sourceAttachmentPath; 243 this.sourceAttachmentRootPath = sourceAttachmentRootPath; 244 this.specificOutputLocation = specificOutputLocation; 245 this.isExported = isExported; 246 } 247 248 public boolean combineAccessRules() { 249 return this.combineAccessRules; 250 } 251 252 255 public ClasspathEntry combineWith(ClasspathEntry referringEntry) { 256 if (referringEntry == null) return this; 257 if (referringEntry.isExported() || referringEntry.getAccessRuleSet() != null ) { 258 boolean combine = this.entryKind == CPE_SOURCE || referringEntry.combineAccessRules(); 259 return new ClasspathEntry( 260 getContentKind(), 261 getEntryKind(), 262 getPath(), 263 this.inclusionPatterns, 264 this.exclusionPatterns, 265 getSourceAttachmentPath(), 266 getSourceAttachmentRootPath(), 267 getOutputLocation(), 268 referringEntry.isExported() || this.isExported, combine(referringEntry.getAccessRules(), getAccessRules(), combine), 270 this.combineAccessRules, 271 this.extraAttributes); 272 } 273 return this; 275 } 276 277 private IAccessRule[] combine(IAccessRule[] referringRules, IAccessRule[] rules, boolean combine) { 278 if (!combine) return rules; 279 if (rules == null || rules.length == 0) return referringRules; 280 281 int referringRulesLength = referringRules.length; 283 int accessRulesLength = rules.length; 284 int rulesLength = referringRulesLength + accessRulesLength; 285 IAccessRule[] result = new IAccessRule[rulesLength]; 286 System.arraycopy(referringRules, 0, result, 0, referringRulesLength); 287 System.arraycopy(rules, 0, result, referringRulesLength, accessRulesLength); 288 289 return result; 290 } 291 292 static IClasspathAttribute[] decodeExtraAttributes(NodeList attributes) { 293 if (attributes == null) return NO_EXTRA_ATTRIBUTES; 294 int length = attributes.getLength(); 295 if (length == 0) return NO_EXTRA_ATTRIBUTES; 296 IClasspathAttribute[] result = new IClasspathAttribute[length]; 297 int index = 0; 298 for (int i = 0; i < length; ++i) { 299 Node node = attributes.item(i); 300 if (node.getNodeType() == Node.ELEMENT_NODE) { 301 Element attribute = (Element )node; 302 String name = attribute.getAttribute(TAG_ATTRIBUTE_NAME); 303 if (name == null) continue; 304 String value = attribute.getAttribute(TAG_ATTRIBUTE_VALUE); 305 if (value == null) continue; 306 result[index++] = new ClasspathAttribute(name, value); 307 } 308 } 309 if (index != length) 310 System.arraycopy(result, 0, result = new IClasspathAttribute[index], 0, index); 311 return result; 312 } 313 314 static IAccessRule[] decodeAccessRules(NodeList list) { 315 if (list == null) return null; 316 int length = list.getLength(); 317 if (length == 0) return null; 318 IAccessRule[] result = new IAccessRule[length]; 319 int index = 0; 320 for (int i = 0; i < length; i++) { 321 Node accessRule = list.item(i); 322 if (accessRule.getNodeType() == Node.ELEMENT_NODE) { 323 Element elementAccessRule = (Element ) accessRule; 324 String pattern = elementAccessRule.getAttribute(TAG_PATTERN); 325 if (pattern == null) continue; 326 String tagKind = elementAccessRule.getAttribute(TAG_KIND); 327 int kind; 328 if (TAG_ACCESSIBLE.equals(tagKind)) 329 kind = IAccessRule.K_ACCESSIBLE; 330 else if (TAG_NON_ACCESSIBLE.equals(tagKind)) 331 kind = IAccessRule.K_NON_ACCESSIBLE; 332 else if (TAG_DISCOURAGED.equals(tagKind)) 333 kind = IAccessRule.K_DISCOURAGED; 334 else 335 continue; 336 boolean ignoreIfBetter = "true".equals(elementAccessRule.getAttribute(TAG_IGNORE_IF_BETTER)); result[index++] = new ClasspathAccessRule(new Path(pattern), ignoreIfBetter ? kind | IAccessRule.IGNORE_IF_BETTER : kind); 338 } 339 } 340 if (index != length) 341 System.arraycopy(result, 0, result = new IAccessRule[index], 0, index); 342 return result; 343 } 344 345 348 private static IPath[] decodePatterns(NamedNodeMap nodeMap, String tag) { 349 String sequence = removeAttribute(tag, nodeMap); 350 if (!sequence.equals("")) { char[][] patterns = CharOperation.splitOn('|', sequence.toCharArray()); 352 int patternCount; 353 if ((patternCount = patterns.length) > 0) { 354 IPath[] paths = new IPath[patternCount]; 355 int index = 0; 356 for (int j = 0; j < patternCount; j++) { 357 char[] pattern = patterns[j]; 358 if (pattern.length == 0) continue; paths[index++] = new Path(new String (pattern)); 360 } 361 if (index < patternCount) 362 System.arraycopy(paths, 0, paths = new IPath[index], 0, index); 363 return paths; 364 } 365 } 366 return null; 367 } 368 369 private static void decodeUnknownNode(Node node, StringBuffer buffer, IJavaProject project) { 370 ByteArrayOutputStream s = new ByteArrayOutputStream (); 371 OutputStreamWriter writer; 372 try { 373 writer = new OutputStreamWriter (s, "UTF8"); XMLWriter xmlWriter = new XMLWriter(writer, project, false); 375 decodeUnknownNode(node, xmlWriter, true); 376 xmlWriter.flush(); 377 xmlWriter.close(); 378 buffer.append(s.toString("UTF8")); } catch (UnsupportedEncodingException e) { 380 } 382 } 383 384 private static void decodeUnknownNode(Node node, XMLWriter xmlWriter, boolean insertNewLine) { 385 switch (node.getNodeType()) { 386 case Node.ELEMENT_NODE: 387 NamedNodeMap attributes; 388 HashMap parameters = null; 389 if ((attributes = node.getAttributes()) != null) { 390 int length = attributes.getLength(); 391 if (length > 0) { 392 parameters = new HashMap (); 393 for (int i = 0; i < length; i++) { 394 Node attribute = attributes.item(i); 395 parameters.put(attribute.getNodeName(), attribute.getNodeValue()); 396 } 397 } 398 } 399 NodeList children = node.getChildNodes(); 400 int childrenLength = children.getLength(); 401 String nodeName = node.getNodeName(); 402 xmlWriter.printTag(nodeName, parameters, false, false, childrenLength == 0); 403 if (childrenLength > 0) { 404 for (int i = 0; i < childrenLength; i++) { 405 decodeUnknownNode(children.item(i), xmlWriter, false); 406 } 407 xmlWriter.endTag(nodeName, false, insertNewLine); 408 } 409 break; 410 case Node.TEXT_NODE: 411 String data = ((Text ) node).getData(); 412 xmlWriter.printString(data, false, false); 413 break; 414 } 415 } 416 417 420 public char[][] fullExclusionPatternChars() { 421 422 if (this.fullExclusionPatternChars == UNINIT_PATTERNS) { 423 int length = this.exclusionPatterns.length; 424 this.fullExclusionPatternChars = new char[length][]; 425 IPath prefixPath = this.path.removeTrailingSeparator(); 426 for (int i = 0; i < length; i++) { 427 this.fullExclusionPatternChars[i] = 428 prefixPath.append(this.exclusionPatterns[i]).toString().toCharArray(); 429 } 430 } 431 return this.fullExclusionPatternChars; 432 } 433 434 437 public char[][] fullInclusionPatternChars() { 438 439 if (this.fullInclusionPatternChars == UNINIT_PATTERNS) { 440 int length = this.inclusionPatterns.length; 441 this.fullInclusionPatternChars = new char[length][]; 442 IPath prefixPath = this.path.removeTrailingSeparator(); 443 for (int i = 0; i < length; i++) { 444 this.fullInclusionPatternChars[i] = 445 prefixPath.append(this.inclusionPatterns[i]).toString().toCharArray(); 446 } 447 } 448 return this.fullInclusionPatternChars; 449 } 450 451 454 public void elementEncode(XMLWriter writer, IPath projectPath, boolean indent, boolean newLine, Map unknownElements) { 455 HashMap parameters = new HashMap (); 456 457 parameters.put(TAG_KIND, ClasspathEntry.kindToString(this.entryKind)); 458 459 IPath xmlPath = this.path; 460 if (this.entryKind != IClasspathEntry.CPE_VARIABLE && this.entryKind != IClasspathEntry.CPE_CONTAINER) { 461 if (xmlPath.isAbsolute()) { 463 if (projectPath != null && projectPath.isPrefixOf(xmlPath)) { 464 if (xmlPath.segment(0).equals(projectPath.segment(0))) { 465 xmlPath = xmlPath.removeFirstSegments(1); 466 xmlPath = xmlPath.makeRelative(); 467 } else { 468 xmlPath = xmlPath.makeAbsolute(); 469 } 470 } 471 } 472 } 473 parameters.put(TAG_PATH, String.valueOf(xmlPath)); 474 475 if (this.sourceAttachmentPath != null) { 476 xmlPath = this.sourceAttachmentPath; 477 if (this.entryKind != IClasspathEntry.CPE_VARIABLE && projectPath != null && projectPath.isPrefixOf(xmlPath)) { 479 if (xmlPath.segment(0).equals(projectPath.segment(0))) { 480 xmlPath = xmlPath.removeFirstSegments(1); 481 xmlPath = xmlPath.makeRelative(); 482 } 483 } 484 parameters.put(TAG_SOURCEPATH, String.valueOf(xmlPath)); 485 } 486 if (this.sourceAttachmentRootPath != null) { 487 parameters.put(TAG_ROOTPATH, String.valueOf(this.sourceAttachmentRootPath)); 488 } 489 if (this.isExported) { 490 parameters.put(TAG_EXPORTED, "true"); } 492 encodePatterns(this.inclusionPatterns, TAG_INCLUDING, parameters); 493 encodePatterns(this.exclusionPatterns, TAG_EXCLUDING, parameters); 494 if (this.entryKind == CPE_PROJECT && !this.combineAccessRules) 495 parameters.put(TAG_COMBINE_ACCESS_RULES, "false"); 497 498 UnknownXmlElements unknownXmlElements = unknownElements == null ? null : (UnknownXmlElements) unknownElements.get(this.path); 500 String [] unknownAttributes; 501 if (unknownXmlElements != null && (unknownAttributes = unknownXmlElements.attributes) != null) 502 for (int i = 0, length = unknownAttributes.length; i < length; i+=2) { 503 String tagName = unknownAttributes[i]; 504 String tagValue = unknownAttributes[i+1]; 505 parameters.put(tagName, tagValue); 506 } 507 508 if (this.specificOutputLocation != null) { 509 IPath outputLocation = this.specificOutputLocation.removeFirstSegments(1); 510 outputLocation = outputLocation.makeRelative(); 511 parameters.put(TAG_OUTPUT, String.valueOf(outputLocation)); 512 } 513 514 boolean hasExtraAttributes = this.extraAttributes.length != 0; 515 boolean hasRestrictions = getAccessRuleSet() != null; ArrayList unknownChildren = unknownXmlElements != null ? unknownXmlElements.children : null; 517 boolean hasUnknownChildren = unknownChildren != null; 518 writer.printTag( 519 TAG_CLASSPATHENTRY, 520 parameters, 521 indent, 522 newLine, 523 !hasExtraAttributes && !hasRestrictions && !hasUnknownChildren); 524 525 if (hasExtraAttributes) 526 encodeExtraAttributes(writer, indent, newLine); 527 528 if (hasRestrictions) 529 encodeAccessRules(writer, indent, newLine); 530 531 if (hasUnknownChildren) 532 encodeUnknownChildren(writer, indent, newLine, unknownChildren); 533 534 if (hasExtraAttributes || hasRestrictions || hasUnknownChildren) 535 writer.endTag(TAG_CLASSPATHENTRY, indent, true); 536 } 537 538 void encodeExtraAttributes(XMLWriter writer, boolean indent, boolean newLine) { 539 writer.startTag(TAG_ATTRIBUTES, indent); 540 for (int i = 0; i < this.extraAttributes.length; i++) { 541 IClasspathAttribute attribute = this.extraAttributes[i]; 542 HashMap parameters = new HashMap (); 543 parameters.put(TAG_ATTRIBUTE_NAME, attribute.getName()); 544 parameters.put(TAG_ATTRIBUTE_VALUE, attribute.getValue()); 545 writer.printTag(TAG_ATTRIBUTE, parameters, indent, newLine, true); 546 } 547 writer.endTag(TAG_ATTRIBUTES, indent, true); 548 } 549 550 void encodeAccessRules(XMLWriter writer, boolean indent, boolean newLine) { 551 552 writer.startTag(TAG_ACCESS_RULES, indent); 553 AccessRule[] rules = getAccessRuleSet().getAccessRules(); 554 for (int i = 0, length = rules.length; i < length; i++) { 555 encodeAccessRule(rules[i], writer, indent, newLine); 556 } 557 writer.endTag(TAG_ACCESS_RULES, indent, true); 558 } 559 560 private void encodeAccessRule(AccessRule accessRule, XMLWriter writer, boolean indent, boolean newLine) { 561 562 HashMap parameters = new HashMap (); 563 parameters.put(TAG_PATTERN, new String (accessRule.pattern)); 564 565 switch (accessRule.getProblemId()) { 566 case IProblem.ForbiddenReference: 567 parameters.put(TAG_KIND, TAG_NON_ACCESSIBLE); 568 break; 569 case IProblem.DiscouragedReference: 570 parameters.put(TAG_KIND, TAG_DISCOURAGED); 571 break; 572 default: 573 parameters.put(TAG_KIND, TAG_ACCESSIBLE); 574 break; 575 } 576 if (accessRule.ignoreIfBetter()) 577 parameters.put(TAG_IGNORE_IF_BETTER, "true"); 579 writer.printTag(TAG_ACCESS_RULE, parameters, indent, newLine, true); 580 581 } 582 583 private void encodeUnknownChildren(XMLWriter writer, boolean indent, boolean newLine, ArrayList unknownChildren) { 584 for (int i = 0, length = unknownChildren.size(); i < length; i++) { 585 String child = (String ) unknownChildren.get(i); 586 writer.printString(child, indent, false); 587 } 588 } 589 590 public static IClasspathEntry elementDecode(Element element, IJavaProject project, Map unknownElements) { 591 592 IPath projectPath = project.getProject().getFullPath(); 593 NamedNodeMap attributes = element.getAttributes(); 594 NodeList children = element.getChildNodes(); 595 boolean[] foundChildren = new boolean[children.getLength()]; 596 String kindAttr = removeAttribute(TAG_KIND, attributes); 597 String pathAttr = removeAttribute(TAG_PATH, attributes); 598 599 IPath path = new Path(pathAttr); 601 int kind = kindFromString(kindAttr); 602 if (kind != IClasspathEntry.CPE_VARIABLE && kind != IClasspathEntry.CPE_CONTAINER && !path.isAbsolute()) { 603 path = projectPath.append(path); 604 } 605 IPath sourceAttachmentPath = 607 element.hasAttribute(TAG_SOURCEPATH) 608 ? new Path(removeAttribute(TAG_SOURCEPATH, attributes)) 609 : null; 610 if (kind != IClasspathEntry.CPE_VARIABLE && sourceAttachmentPath != null && !sourceAttachmentPath.isAbsolute()) { 611 sourceAttachmentPath = projectPath.append(sourceAttachmentPath); 612 } 613 IPath sourceAttachmentRootPath = 614 element.hasAttribute(TAG_ROOTPATH) 615 ? new Path(removeAttribute(TAG_ROOTPATH, attributes)) 616 : null; 617 618 boolean isExported = removeAttribute(TAG_EXPORTED, attributes).equals("true"); 621 IPath[] inclusionPatterns = decodePatterns(attributes, TAG_INCLUDING); 623 if (inclusionPatterns == null) inclusionPatterns = INCLUDE_ALL; 624 625 IPath[] exclusionPatterns = decodePatterns(attributes, TAG_EXCLUDING); 627 if (exclusionPatterns == null) exclusionPatterns = EXCLUDE_NONE; 628 629 NodeList attributeList = getChildAttributes(TAG_ACCESS_RULES, children, foundChildren); 631 IAccessRule[] accessRules = decodeAccessRules(attributeList); 632 633 if (accessRules == null) { 635 accessRules = getAccessRules(inclusionPatterns, exclusionPatterns); 636 } 637 638 boolean combineAccessRestrictions = !removeAttribute(TAG_COMBINE_ACCESS_RULES, attributes).equals("false"); 641 attributeList = getChildAttributes(TAG_ATTRIBUTES, children, foundChildren); 643 IClasspathAttribute[] extraAttributes = decodeExtraAttributes(attributeList); 644 645 IPath outputLocation = element.hasAttribute(TAG_OUTPUT) ? projectPath.append(removeAttribute(TAG_OUTPUT, attributes)) : null; 647 648 String [] unknownAttributes = null; 649 ArrayList unknownChildren = null; 650 651 if (unknownElements != null) { 652 int unknownAttributeLength = attributes.getLength(); 654 if (unknownAttributeLength != 0) { 655 unknownAttributes = new String [unknownAttributeLength*2]; 656 for (int i = 0; i < unknownAttributeLength; i++) { 657 Node attribute = attributes.item(i); 658 unknownAttributes[i*2] = attribute.getNodeName(); 659 unknownAttributes[i*2 + 1] = attribute.getNodeValue(); 660 } 661 } 662 663 for (int i = 0, length = foundChildren.length; i < length; i++) { 665 if (!foundChildren[i]) { 666 Node node = children.item(i); 667 if (node.getNodeType() != Node.ELEMENT_NODE) continue; 668 if (unknownChildren == null) 669 unknownChildren = new ArrayList (); 670 StringBuffer buffer = new StringBuffer (); 671 decodeUnknownNode(node, buffer, project); 672 unknownChildren.add(buffer.toString()); 673 } 674 } 675 } 676 677 IClasspathEntry entry = null; 679 switch (kind) { 680 681 case IClasspathEntry.CPE_PROJECT : 682 entry = new ClasspathEntry( 683 IPackageFragmentRoot.K_SOURCE, 684 IClasspathEntry.CPE_PROJECT, 685 path, 686 ClasspathEntry.INCLUDE_ALL, ClasspathEntry.EXCLUDE_NONE, null, null, null, isExported, 692 accessRules, 693 combineAccessRestrictions, 694 extraAttributes); 695 break; 696 case IClasspathEntry.CPE_LIBRARY : 697 entry = JavaCore.newLibraryEntry( 698 path, 699 sourceAttachmentPath, 700 sourceAttachmentRootPath, 701 accessRules, 702 extraAttributes, 703 isExported); 704 break; 705 case IClasspathEntry.CPE_SOURCE : 706 String projSegment = path.segment(0); 708 if (projSegment != null && projSegment.equals(project.getElementName())) { entry = JavaCore.newSourceEntry(path, inclusionPatterns, exclusionPatterns, outputLocation, extraAttributes); 710 } else { 711 if (path.segmentCount() == 1) { 712 entry = JavaCore.newProjectEntry( 714 path, 715 accessRules, 716 combineAccessRestrictions, 717 extraAttributes, 718 isExported); 719 } else { 720 entry = JavaCore.newSourceEntry(path, inclusionPatterns, exclusionPatterns, outputLocation, extraAttributes); 722 } 723 } 724 break; 725 case IClasspathEntry.CPE_VARIABLE : 726 entry = JavaCore.newVariableEntry( 727 path, 728 sourceAttachmentPath, 729 sourceAttachmentRootPath, 730 accessRules, 731 extraAttributes, 732 isExported); 733 break; 734 case IClasspathEntry.CPE_CONTAINER : 735 entry = JavaCore.newContainerEntry( 736 path, 737 accessRules, 738 extraAttributes, 739 isExported); 740 break; 741 case ClasspathEntry.K_OUTPUT : 742 if (!path.isAbsolute()) return null; 743 entry = new ClasspathEntry( 744 ClasspathEntry.K_OUTPUT, 745 IClasspathEntry.CPE_LIBRARY, 746 path, 747 INCLUDE_ALL, 748 EXCLUDE_NONE, 749 null, null, null, false, 753 null, false, NO_EXTRA_ATTRIBUTES); 756 break; 757 default : 758 throw new AssertionFailedException(Messages.bind(Messages.classpath_unknownKind, kindAttr)); 759 } 760 761 if (unknownAttributes != null || unknownChildren != null) { 762 UnknownXmlElements unknownXmlElements = new UnknownXmlElements(); 763 unknownXmlElements.attributes = unknownAttributes; 764 unknownXmlElements.children = unknownChildren; 765 unknownElements.put(path, unknownXmlElements); 766 } 767 768 return entry; 769 } 770 771 public static NodeList getChildAttributes(String childName, NodeList children, boolean[] foundChildren) { 772 for (int i = 0, length = foundChildren.length; i < length; i++) { 773 Node node = children.item(i); 774 if (childName.equals(node.getNodeName())) { 775 foundChildren[i] = true; 776 return node.getChildNodes(); 777 } 778 } 779 return null; 780 } 781 782 783 private static String removeAttribute(String nodeName, NamedNodeMap nodeMap) { 784 Node node = removeNode(nodeName, nodeMap); 785 if (node == null) 786 return ""; return node.getNodeValue(); 788 } 789 790 private static Node removeNode(String nodeName, NamedNodeMap nodeMap) { 791 try { 792 return nodeMap.removeNamedItem(nodeName); 793 } catch (DOMException e) { 794 if (e.code != DOMException.NOT_FOUND_ERR) 795 throw e; 796 return null; 797 } 798 } 799 800 803 private static void encodePatterns(IPath[] patterns, String tag, Map parameters) { 804 if (patterns != null && patterns.length > 0) { 805 StringBuffer rule = new StringBuffer (10); 806 for (int i = 0, max = patterns.length; i < max; i++){ 807 if (i > 0) rule.append('|'); 808 rule.append(patterns[i]); 809 } 810 parameters.put(tag, String.valueOf(rule)); 811 } 812 } 813 814 818 public boolean equals(Object object) { 819 if (this == object) 820 return true; 821 if (object instanceof ClasspathEntry) { 822 ClasspathEntry otherEntry = (ClasspathEntry) object; 823 824 if (this.contentKind != otherEntry.getContentKind()) 825 return false; 826 827 if (this.entryKind != otherEntry.getEntryKind()) 828 return false; 829 830 if (this.isExported != otherEntry.isExported()) 831 return false; 832 833 if (!this.path.equals(otherEntry.getPath())) 834 return false; 835 836 IPath otherPath = otherEntry.getSourceAttachmentPath(); 837 if (this.sourceAttachmentPath == null) { 838 if (otherPath != null) 839 return false; 840 } else { 841 if (!this.sourceAttachmentPath.equals(otherPath)) 842 return false; 843 } 844 845 otherPath = otherEntry.getSourceAttachmentRootPath(); 846 if (this.sourceAttachmentRootPath == null) { 847 if (otherPath != null) 848 return false; 849 } else { 850 if (!this.sourceAttachmentRootPath.equals(otherPath)) 851 return false; 852 } 853 854 if (!equalPatterns(this.inclusionPatterns, otherEntry.getInclusionPatterns())) 855 return false; 856 if (!equalPatterns(this.exclusionPatterns, otherEntry.getExclusionPatterns())) 857 return false; 858 AccessRuleSet otherRuleSet = otherEntry.getAccessRuleSet(); 859 if (getAccessRuleSet() != null) { 860 if (!getAccessRuleSet().equals(otherRuleSet)) 861 return false; 862 } else if (otherRuleSet != null) 863 return false; 864 if (this.combineAccessRules != otherEntry.combineAccessRules()) 865 return false; 866 otherPath = otherEntry.getOutputLocation(); 867 if (this.specificOutputLocation == null) { 868 if (otherPath != null) 869 return false; 870 } else { 871 if (!this.specificOutputLocation.equals(otherPath)) 872 return false; 873 } 874 if (!equalAttributes(this.extraAttributes, otherEntry.getExtraAttributes())) 875 return false; 876 return true; 877 } else { 878 return false; 879 } 880 } 881 882 private static boolean equalAttributes(IClasspathAttribute[] firstAttributes, IClasspathAttribute[] secondAttributes) { 883 if (firstAttributes != secondAttributes){ 884 if (firstAttributes == null) return false; 885 int length = firstAttributes.length; 886 if (secondAttributes == null || secondAttributes.length != length) 887 return false; 888 for (int i = 0; i < length; i++) { 889 if (!firstAttributes[i].equals(secondAttributes[i])) 890 return false; 891 } 892 } 893 return true; 894 } 895 896 private static boolean equalPatterns(IPath[] firstPatterns, IPath[] secondPatterns) { 897 if (firstPatterns != secondPatterns){ 898 if (firstPatterns == null) return false; 899 int length = firstPatterns.length; 900 if (secondPatterns == null || secondPatterns.length != length) 901 return false; 902 for (int i = 0; i < length; i++) { 903 if (!firstPatterns[i].toString().equals(secondPatterns[i].toString())) 906 return false; 907 } 908 } 909 return true; 910 } 911 912 915 public IAccessRule[] getAccessRules() { 916 if (this.accessRuleSet == null) return NO_ACCESS_RULES; 917 AccessRule[] rules = this.accessRuleSet.getAccessRules(); 918 int length = rules.length; 919 if (length == 0) return NO_ACCESS_RULES; 920 IAccessRule[] result = new IAccessRule[length]; 921 System.arraycopy(rules, 0, result, 0, length); 922 return result; 923 } 924 925 public AccessRuleSet getAccessRuleSet() { 926 return this.accessRuleSet; 927 } 928 929 932 public int getContentKind() { 933 return this.contentKind; 934 } 935 936 939 public int getEntryKind() { 940 return this.entryKind; 941 } 942 943 946 public IPath[] getExclusionPatterns() { 947 return this.exclusionPatterns; 948 } 949 950 public IClasspathAttribute[] getExtraAttributes() { 951 return this.extraAttributes; 952 } 953 954 private String [] getMessageTemplates() { 955 JavaModelManager manager = JavaModelManager.getJavaModelManager(); 956 String [] result = new String [AccessRuleSet.MESSAGE_TEMPLATES_LENGTH]; 957 if (this.entryKind == CPE_PROJECT || this.entryKind == CPE_SOURCE) { result[0] = manager.intern(Messages.bind( 959 org.eclipse.jdt.internal.core.util.Messages.restrictedAccess_project, 960 new String [] {"{0}", getPath().segment(0)})); result[1] = manager.intern(Messages.bind( 962 org.eclipse.jdt.internal.core.util.Messages.restrictedAccess_constructor_project, 963 new String [] {"{0}", getPath().segment(0)})); result[2] = manager.intern(Messages.bind( 965 org.eclipse.jdt.internal.core.util.Messages.restrictedAccess_method_project, 966 new String [] {"{0}", "{1}", getPath().segment(0)})); result[3] = manager.intern(Messages.bind( 968 org.eclipse.jdt.internal.core.util.Messages.restrictedAccess_field_project, 969 new String [] {"{0}", "{1}", getPath().segment(0)})); } else { 971 IPath libPath = getPath(); 972 Object target = JavaModel.getTarget(ResourcesPlugin.getWorkspace().getRoot(), libPath, false); 973 String pathString; 974 if (target instanceof java.io.File ) 975 pathString = libPath.toOSString(); 976 else 977 pathString = libPath.makeRelative().toString(); 978 result[0] = manager.intern(Messages.bind( 979 org.eclipse.jdt.internal.core.util.Messages.restrictedAccess_library, 980 new String [] {"{0}", pathString})); result[1] = manager.intern(Messages.bind( 982 org.eclipse.jdt.internal.core.util.Messages.restrictedAccess_constructor_library, 983 new String [] {"{0}", pathString})); result[2] = manager.intern(Messages.bind( 985 org.eclipse.jdt.internal.core.util.Messages.restrictedAccess_method_library, 986 new String [] {"{0}", "{1}", pathString})); result[3] = manager.intern(Messages.bind( 988 org.eclipse.jdt.internal.core.util.Messages.restrictedAccess_field_library, 989 new String [] {"{0}", "{1}", pathString})); } 991 return result; 992 } 993 994 997 public IPath[] getInclusionPatterns() { 998 return this.inclusionPatterns; 999 } 1000 1001 1004 public IPath getOutputLocation() { 1005 return this.specificOutputLocation; 1006 } 1007 1008 1011 public IPath getPath() { 1012 return this.path; 1013 } 1014 1015 1018 public IPath getSourceAttachmentPath() { 1019 return this.sourceAttachmentPath; 1020 } 1021 1022 1025 public IPath getSourceAttachmentRootPath() { 1026 return this.sourceAttachmentRootPath; 1027 } 1028 1029 1032 public int hashCode() { 1033 return this.path.hashCode(); 1034 } 1035 1036 1039 public boolean isExported() { 1040 return this.isExported; 1041 } 1042 1043 public boolean isOptional() { 1044 for (int i = 0, length = this.extraAttributes.length; i < length; i++) { 1045 IClasspathAttribute attribute = this.extraAttributes[i]; 1046 if (IClasspathAttribute.OPTIONAL.equals(attribute.getName()) && "true".equals(attribute.getValue())) return true; 1048 } 1049 return false; 1050 } 1051 1052 1055 static int kindFromString(String kindStr) { 1056 1057 if (kindStr.equalsIgnoreCase("prj")) return IClasspathEntry.CPE_PROJECT; 1059 if (kindStr.equalsIgnoreCase("var")) return IClasspathEntry.CPE_VARIABLE; 1061 if (kindStr.equalsIgnoreCase("con")) return IClasspathEntry.CPE_CONTAINER; 1063 if (kindStr.equalsIgnoreCase("src")) return IClasspathEntry.CPE_SOURCE; 1065 if (kindStr.equalsIgnoreCase("lib")) return IClasspathEntry.CPE_LIBRARY; 1067 if (kindStr.equalsIgnoreCase("output")) return ClasspathEntry.K_OUTPUT; 1069 return -1; 1070 } 1071 1072 1075 static String kindToString(int kind) { 1076 1077 switch (kind) { 1078 case IClasspathEntry.CPE_PROJECT : 1079 return "src"; case IClasspathEntry.CPE_SOURCE : 1081 return "src"; case IClasspathEntry.CPE_LIBRARY : 1083 return "lib"; case IClasspathEntry.CPE_VARIABLE : 1085 return "var"; case IClasspathEntry.CPE_CONTAINER : 1087 return "con"; case ClasspathEntry.K_OUTPUT : 1089 return "output"; default : 1091 return "unknown"; } 1093 } 1094 1095 1098 public static IAccessRule[] getAccessRules(IPath[] accessibleFiles, IPath[] nonAccessibleFiles) { 1099 int accessibleFilesLength = accessibleFiles == null ? 0 : accessibleFiles.length; 1100 int nonAccessibleFilesLength = nonAccessibleFiles == null ? 0 : nonAccessibleFiles.length; 1101 int length = accessibleFilesLength + nonAccessibleFilesLength; 1102 if (length == 0) return null; 1103 IAccessRule[] accessRules = new IAccessRule[length]; 1104 for (int i = 0; i < accessibleFilesLength; i++) { 1105 accessRules[i] = JavaCore.newAccessRule(accessibleFiles[i], IAccessRule.K_ACCESSIBLE); 1106 } 1107 for (int i = 0; i < nonAccessibleFilesLength; i++) { 1108 accessRules[accessibleFilesLength + i] = JavaCore.newAccessRule(nonAccessibleFiles[i], IAccessRule.K_NON_ACCESSIBLE); 1109 } 1110 return accessRules; 1111 } 1112 1113 1116 public String toString() { 1117 StringBuffer buffer = new StringBuffer (); 1118 buffer.append(String.valueOf(getPath())); 1119 buffer.append('['); 1120 switch (getEntryKind()) { 1121 case IClasspathEntry.CPE_LIBRARY : 1122 buffer.append("CPE_LIBRARY"); break; 1124 case IClasspathEntry.CPE_PROJECT : 1125 buffer.append("CPE_PROJECT"); break; 1127 case IClasspathEntry.CPE_SOURCE : 1128 buffer.append("CPE_SOURCE"); break; 1130 case IClasspathEntry.CPE_VARIABLE : 1131 buffer.append("CPE_VARIABLE"); break; 1133 case IClasspathEntry.CPE_CONTAINER : 1134 buffer.append("CPE_CONTAINER"); break; 1136 } 1137 buffer.append("]["); switch (getContentKind()) { 1139 case IPackageFragmentRoot.K_BINARY : 1140 buffer.append("K_BINARY"); break; 1142 case IPackageFragmentRoot.K_SOURCE : 1143 buffer.append("K_SOURCE"); break; 1145 case ClasspathEntry.K_OUTPUT : 1146 buffer.append("K_OUTPUT"); break; 1148 } 1149 buffer.append(']'); 1150 if (getSourceAttachmentPath() != null) { 1151 buffer.append("[sourcePath:"); buffer.append(getSourceAttachmentPath()); 1153 buffer.append(']'); 1154 } 1155 if (getSourceAttachmentRootPath() != null) { 1156 buffer.append("[rootPath:"); buffer.append(getSourceAttachmentRootPath()); 1158 buffer.append(']'); 1159 } 1160 buffer.append("[isExported:"); buffer.append(this.isExported); 1162 buffer.append(']'); 1163 IPath[] patterns = this.inclusionPatterns; 1164 int length; 1165 if ((length = patterns == null ? 0 : patterns.length) > 0) { 1166 buffer.append("[including:"); for (int i = 0; i < length; i++) { 1168 buffer.append(patterns[i]); 1169 if (i != length-1) { 1170 buffer.append('|'); 1171 } 1172 } 1173 buffer.append(']'); 1174 } 1175 patterns = this.exclusionPatterns; 1176 if ((length = patterns == null ? 0 : patterns.length) > 0) { 1177 buffer.append("[excluding:"); for (int i = 0; i < length; i++) { 1179 buffer.append(patterns[i]); 1180 if (i != length-1) { 1181 buffer.append('|'); 1182 } 1183 } 1184 buffer.append(']'); 1185 } 1186 if (this.accessRuleSet != null) { 1187 buffer.append('['); 1188 buffer.append(this.accessRuleSet.toString(false)); 1189 buffer.append(']'); 1190 } 1191 if (this.entryKind == CPE_PROJECT) { 1192 buffer.append("[combine access rules:"); buffer.append(this.combineAccessRules); 1194 buffer.append(']'); 1195 } 1196 if (getOutputLocation() != null) { 1197 buffer.append("[output:"); buffer.append(getOutputLocation()); 1199 buffer.append(']'); 1200 } 1201 if ((length = this.extraAttributes == null ? 0 : this.extraAttributes.length) > 0) { 1202 buffer.append("[attributes:"); for (int i = 0; i < length; i++) { 1204 buffer.append(this.extraAttributes[i]); 1205 if (i != length-1) { 1206 buffer.append(','); 1207 } 1208 } 1209 buffer.append(']'); 1210 } 1211 return buffer.toString(); 1212 } 1213 1214 1218 public String rootID(){ 1219 1220 if (this.rootID == null) { 1221 switch(this.entryKind){ 1222 case IClasspathEntry.CPE_LIBRARY : 1223 this.rootID = "[LIB]"+this.path; break; 1225 case IClasspathEntry.CPE_PROJECT : 1226 this.rootID = "[PRJ]"+this.path; break; 1228 case IClasspathEntry.CPE_SOURCE : 1229 this.rootID = "[SRC]"+this.path; break; 1231 case IClasspathEntry.CPE_VARIABLE : 1232 this.rootID = "[VAR]"+this.path; break; 1234 case IClasspathEntry.CPE_CONTAINER : 1235 this.rootID = "[CON]"+this.path; break; 1237 default : 1238 this.rootID = ""; break; 1240 } 1241 } 1242 return this.rootID; 1243 } 1244 1245 1249 public IClasspathEntry getResolvedEntry() { 1250 1251 return JavaCore.getResolvedClasspathEntry(this); 1252 } 1253 1254 1284 public static IJavaModelStatus validateClasspath(IJavaProject javaProject, IClasspathEntry[] rawClasspath, IPath projectOutputLocation) { 1285 1286 IProject project = javaProject.getProject(); 1287 IPath projectPath= project.getFullPath(); 1288 String projectName = javaProject.getElementName(); 1289 1290 1291 if (projectOutputLocation == null) { 1292 return new JavaModelStatus(IJavaModelStatusConstants.NULL_PATH); 1293 } 1294 if (projectOutputLocation.isAbsolute()) { 1295 if (!projectPath.isPrefixOf(projectOutputLocation)) { 1296 return new JavaModelStatus(IJavaModelStatusConstants.PATH_OUTSIDE_PROJECT, javaProject, projectOutputLocation.toString()); 1297 } 1298 } else { 1299 return new JavaModelStatus(IJavaModelStatusConstants.RELATIVE_PATH, projectOutputLocation); 1300 } 1301 1302 boolean hasSource = false; 1303 boolean hasLibFolder = false; 1304 1305 1306 if (rawClasspath == null) 1308 return JavaModelStatus.VERIFIED_OK; 1309 1310 IClasspathEntry[] classpath; 1312 try { 1313 classpath = ((JavaProject)javaProject).resolveClasspath(rawClasspath); 1314 } catch(JavaModelException e){ 1315 return e.getJavaModelStatus(); 1316 } 1317 int length = classpath.length; 1318 1319 int outputCount = 1; 1320 IPath[] outputLocations = new IPath[length+1]; 1321 boolean[] allowNestingInOutputLocations = new boolean[length+1]; 1322 outputLocations[0] = projectOutputLocation; 1323 1324 IPath potentialNestedOutput = null; int sourceEntryCount = 0; 1327 boolean disableExclusionPatterns = JavaCore.DISABLED.equals(javaProject.getOption(JavaCore.CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS, true)); 1328 boolean disableCustomOutputLocations = JavaCore.DISABLED.equals(javaProject.getOption(JavaCore.CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS, true)); 1329 1330 for (int i = 0 ; i < length; i++) { 1331 IClasspathEntry resolvedEntry = classpath[i]; 1332 if (disableExclusionPatterns && 1333 ((resolvedEntry.getInclusionPatterns() != null && resolvedEntry.getInclusionPatterns().length > 0) 1334 || (resolvedEntry.getExclusionPatterns() != null && resolvedEntry.getExclusionPatterns().length > 0))) { 1335 return new JavaModelStatus(IJavaModelStatusConstants.DISABLED_CP_EXCLUSION_PATTERNS, javaProject, resolvedEntry.getPath()); 1336 } 1337 switch(resolvedEntry.getEntryKind()){ 1338 case IClasspathEntry.CPE_SOURCE : 1339 sourceEntryCount++; 1340 1341 IPath customOutput; 1342 if ((customOutput = resolvedEntry.getOutputLocation()) != null) { 1343 1344 if (disableCustomOutputLocations) { 1345 return new JavaModelStatus(IJavaModelStatusConstants.DISABLED_CP_MULTIPLE_OUTPUT_LOCATIONS, javaProject, resolvedEntry.getPath()); 1346 } 1347 if (customOutput.isAbsolute()) { 1349 if (!javaProject.getPath().isPrefixOf(customOutput)) { 1350 return new JavaModelStatus(IJavaModelStatusConstants.PATH_OUTSIDE_PROJECT, javaProject, customOutput.toString()); 1351 } 1352 } else { 1353 return new JavaModelStatus(IJavaModelStatusConstants.RELATIVE_PATH, customOutput); 1354 } 1355 1356 if (Util.indexOfMatchingPath(customOutput, outputLocations, outputCount) != -1) { 1359 continue; } 1361 outputLocations[outputCount++] = customOutput; 1363 } 1364 } 1365 } 1366 for (int i = 1 ; i < outputCount; i++) { 1368 IPath customOutput = outputLocations[i]; 1369 int index; 1370 if ((index = Util.indexOfEnclosingPath(customOutput, outputLocations, outputCount)) != -1 && index != i) { 1372 if (index == 0) { 1373 if (potentialNestedOutput == null) potentialNestedOutput = customOutput; 1376 } else { 1377 return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_cannotNestOutputInOutput, new String [] {customOutput.makeRelative().toString(), outputLocations[index].makeRelative().toString()})); 1378 } 1379 } 1380 } 1381 if (sourceEntryCount <= outputCount-1) { 1383 allowNestingInOutputLocations[0] = true; 1384 } else if (potentialNestedOutput != null) { 1385 return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_cannotNestOutputInOutput, new String [] {potentialNestedOutput.makeRelative().toString(), outputLocations[0].makeRelative().toString()})); 1386 } 1387 1388 for (int i = 0 ; i < length; i++) { 1389 IClasspathEntry resolvedEntry = classpath[i]; 1390 IPath path = resolvedEntry.getPath(); 1391 int index; 1392 switch(resolvedEntry.getEntryKind()){ 1393 1394 case IClasspathEntry.CPE_SOURCE : 1395 hasSource = true; 1396 if ((index = Util.indexOfMatchingPath(path, outputLocations, outputCount)) != -1){ 1397 allowNestingInOutputLocations[index] = true; 1398 } 1399 break; 1400 1401 case IClasspathEntry.CPE_LIBRARY: 1402 hasLibFolder |= !org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(path.lastSegment()); 1403 if ((index = Util.indexOfMatchingPath(path, outputLocations, outputCount)) != -1){ 1404 allowNestingInOutputLocations[index] = true; 1405 } 1406 break; 1407 } 1408 } 1409 if (!hasSource && !hasLibFolder) { for (int i = 0; i < outputCount; i++) allowNestingInOutputLocations[i] = true; 1411 } 1412 1413 HashSet pathes = new HashSet (length); 1414 1415 for (int i = 0 ; i < length; i++) { 1417 IClasspathEntry entry = classpath[i]; 1418 if (entry == null) continue; 1419 IPath entryPath = entry.getPath(); 1420 int kind = entry.getEntryKind(); 1421 1422 boolean isProjectRelative = projectName.equals(entryPath.segment(0)); 1424 String entryPathMsg = isProjectRelative ? entryPath.removeFirstSegments(1).toString() : entryPath.makeRelative().toString(); 1425 1426 if (!pathes.add(entryPath)){ 1428 return new JavaModelStatus(IJavaModelStatusConstants.NAME_COLLISION, Messages.bind(Messages.classpath_duplicateEntryPath, new String [] {entryPathMsg, projectName})); 1429 } 1430 if (entryPath.equals(projectPath)){ 1432 if (kind == IClasspathEntry.CPE_PROJECT){ 1434 return new JavaModelStatus(IJavaModelStatusConstants.INVALID_PATH, Messages.bind(Messages.classpath_cannotReferToItself, entryPath.makeRelative().toString())); 1435 } 1436 continue; 1438 } 1439 1440 if (kind == IClasspathEntry.CPE_SOURCE 1442 || (kind == IClasspathEntry.CPE_LIBRARY && !org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(entryPath.lastSegment()))){ 1443 for (int j = 0; j < classpath.length; j++){ 1444 IClasspathEntry otherEntry = classpath[j]; 1445 if (otherEntry == null) continue; 1446 int otherKind = otherEntry.getEntryKind(); 1447 IPath otherPath = otherEntry.getPath(); 1448 if (entry != otherEntry 1449 && (otherKind == IClasspathEntry.CPE_SOURCE 1450 || (otherKind == IClasspathEntry.CPE_LIBRARY 1451 && !org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(otherPath.lastSegment())))){ 1452 char[][] inclusionPatterns, exclusionPatterns; 1453 if (otherPath.isPrefixOf(entryPath) 1454 && !otherPath.equals(entryPath) 1455 && !Util.isExcluded(entryPath.append("*"), inclusionPatterns = ((ClasspathEntry)otherEntry).fullInclusionPatternChars(), exclusionPatterns = ((ClasspathEntry)otherEntry).fullExclusionPatternChars(), false)) { String exclusionPattern = entryPath.removeFirstSegments(otherPath.segmentCount()).segment(0); 1457 if (Util.isExcluded(entryPath, inclusionPatterns, exclusionPatterns, false)) { 1458 return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_mustEndWithSlash, new String [] {exclusionPattern, entryPath.makeRelative().toString()})); 1459 } else { 1460 if (otherKind == IClasspathEntry.CPE_SOURCE) { 1461 exclusionPattern += '/'; 1462 if (!disableExclusionPatterns) { 1463 return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_cannotNestEntryInEntry, new String [] {entryPath.makeRelative().toString(), otherEntry.getPath().makeRelative().toString(), exclusionPattern})); 1464 } else { 1465 return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_cannotNestEntryInEntryNoExclusion, new String [] {entryPath.makeRelative().toString(), otherEntry.getPath().makeRelative().toString(), exclusionPattern})); 1466 } 1467 } else { 1468 return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_cannotNestEntryInLibrary, new String [] {entryPath.makeRelative().toString(), otherEntry.getPath().makeRelative().toString()})); 1469 } 1470 } 1471 } 1472 } 1473 } 1474 } 1475 1476 char[][] inclusionPatterns = ((ClasspathEntry)entry).fullInclusionPatternChars(); 1478 char[][] exclusionPatterns = ((ClasspathEntry)entry).fullExclusionPatternChars(); 1479 for (int j = 0; j < outputCount; j++){ 1480 IPath currentOutput = outputLocations[j]; 1481 if (entryPath.equals(currentOutput)) continue; 1482 if (entryPath.isPrefixOf(currentOutput)) { 1483 if (kind != IClasspathEntry.CPE_SOURCE || !Util.isExcluded(currentOutput, inclusionPatterns, exclusionPatterns, true)) { 1484 return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_cannotNestOutputInEntry, new String [] {currentOutput.makeRelative().toString(), entryPath.makeRelative().toString()})); 1485 } 1486 } 1487 } 1488 1489 for (int j = 0; j < outputCount; j++){ 1491 if (allowNestingInOutputLocations[j]) continue; 1492 IPath currentOutput = outputLocations[j]; 1493 if (currentOutput.isPrefixOf(entryPath)) { 1494 return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_cannotNestEntryInOutput, new String [] {entryPath.makeRelative().toString(), currentOutput.makeRelative().toString()})); 1495 } 1496 } 1497 } 1498 for (int i = 0 ; i < length; i++) { 1504 IClasspathEntry entry = classpath[i]; 1505 if (entry == null) continue; 1506 IPath entryPath = entry.getPath(); 1507 int kind = entry.getEntryKind(); 1508 1509 boolean isProjectRelative = projectName.equals(entryPath.segment(0)); 1511 String entryPathMsg = isProjectRelative ? entryPath.removeFirstSegments(1).toString() : entryPath.makeRelative().toString(); 1512 1513 if (kind == IClasspathEntry.CPE_SOURCE) { 1514 IPath output = entry.getOutputLocation(); 1515 if (output == null) continue; for (int j = 0; j < length; j++) { 1518 IClasspathEntry otherEntry = classpath[j]; 1519 if (otherEntry == entry) continue; 1520 1521 boolean opStartsWithProject = projectName.equals(otherEntry.getPath().segment(0)); 1523 String otherPathMsg = opStartsWithProject ? otherEntry.getPath().removeFirstSegments(1).toString() : otherEntry.getPath().makeRelative().toString(); 1524 1525 switch (otherEntry.getEntryKind()) { 1526 case IClasspathEntry.CPE_SOURCE : 1527 if (otherEntry.getPath().equals(output)) { 1528 return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_cannotUseDistinctSourceFolderAsOutput, new String [] {entryPathMsg, otherPathMsg, projectName})); 1529 } 1530 break; 1531 case IClasspathEntry.CPE_LIBRARY : 1532 if (otherEntry.getPath().equals(output)) { 1533 return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_cannotUseLibraryAsOutput, new String [] {entryPathMsg, otherPathMsg, projectName})); 1534 } 1535 } 1536 } 1537 } 1538 } 1539 return JavaModelStatus.VERIFIED_OK; 1540 } 1541 1542 1553 public static IJavaModelStatus validateClasspathEntry(IJavaProject project, IClasspathEntry entry, boolean checkSourceAttachment, boolean recurseInContainers){ 1554 1555 IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); 1556 IPath path = entry.getPath(); 1557 1558 String projectName = project.getElementName(); 1560 boolean pathStartsWithProject = projectName.equals(path.segment(0)); 1561 String entryPathMsg = pathStartsWithProject ? path.removeFirstSegments(1).makeRelative().toString() : path.toString(); 1562 1563 switch(entry.getEntryKind()){ 1564 1565 case IClasspathEntry.CPE_CONTAINER : 1567 if (path.segmentCount() >= 1){ 1568 try { 1569 IClasspathContainer container = JavaModelManager.getJavaModelManager().getClasspathContainer(path, project); 1570 if (container == null){ 1572 return new JavaModelStatus(IJavaModelStatusConstants.CP_CONTAINER_PATH_UNBOUND, project, path); 1573 } else if (container == JavaModelManager.CONTAINER_INITIALIZATION_IN_PROGRESS) { 1574 IClasspathAttribute[] extraAttributes = entry.getExtraAttributes(); 1576 if (extraAttributes != null) { 1577 int length = extraAttributes.length; 1578 HashSet set = new HashSet (length); 1579 for (int i=0; i<length; i++) { 1580 String attName = extraAttributes[i].getName(); 1581 if (!set.add(attName)) { 1582 return new JavaModelStatus(IJavaModelStatusConstants.NAME_COLLISION, Messages.bind(Messages.classpath_duplicateEntryExtraAttribute, new String [] {attName, entryPathMsg, projectName})); 1583 } 1584 } 1585 } 1586 return JavaModelStatus.VERIFIED_OK; 1588 } 1589 IClasspathEntry[] containerEntries = container.getClasspathEntries(); 1590 if (containerEntries != null){ 1591 for (int i = 0, length = containerEntries.length; i < length; i++){ 1592 IClasspathEntry containerEntry = containerEntries[i]; 1593 int kind = containerEntry == null ? 0 : containerEntry.getEntryKind(); 1594 if (containerEntry == null 1595 || kind == IClasspathEntry.CPE_SOURCE 1596 || kind == IClasspathEntry.CPE_VARIABLE 1597 || kind == IClasspathEntry.CPE_CONTAINER){ 1598 String description = container.getDescription(); 1599 if (description == null) description = path.makeRelative().toString(); 1600 return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CP_CONTAINER_ENTRY, project, path); 1601 } 1602 if (recurseInContainers) { 1603 IJavaModelStatus containerEntryStatus = validateClasspathEntry(project, containerEntry, checkSourceAttachment, recurseInContainers); 1604 if (!containerEntryStatus.isOK()){ 1605 return containerEntryStatus; 1606 } 1607 } 1608 } 1609 } 1610 } catch(JavaModelException e){ 1611 return new JavaModelStatus(e); 1612 } 1613 } else { 1614 return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_illegalContainerPath, new String [] {entryPathMsg, projectName})); 1615 } 1616 break; 1617 1618 case IClasspathEntry.CPE_VARIABLE : 1620 if (path.segmentCount() >= 1){ 1621 try { 1622 entry = JavaCore.getResolvedClasspathEntry(entry); 1623 } catch (AssertionFailedException e) { 1624 return new JavaModelStatus(IJavaModelStatusConstants.INVALID_PATH, e.getMessage()); 1627 } 1628 if (entry == null){ 1629 return new JavaModelStatus(IJavaModelStatusConstants.CP_VARIABLE_PATH_UNBOUND, project, path); 1630 } 1631 1632 IJavaModelStatus status = validateClasspathEntry(project, entry, checkSourceAttachment, recurseInContainers); 1634 if (!status.isOK()) return status; 1635 1636 String variableName = path.segment(0); 1638 String deprecatedMessage = JavaCore.getClasspathVariableDeprecationMessage(variableName); 1639 if (deprecatedMessage != null) { 1640 return new JavaModelStatus(IStatus.WARNING, IJavaModelStatusConstants.DEPRECATED_VARIABLE, project, path, deprecatedMessage); 1641 } 1642 return status; 1643 } else { 1644 return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_illegalVariablePath, new String [] {entryPathMsg, projectName})); 1645 } 1646 1647 case IClasspathEntry.CPE_LIBRARY : 1649 if (path.isAbsolute() && !path.isEmpty()) { 1650 IPath sourceAttachment = entry.getSourceAttachmentPath(); 1651 Object target = JavaModel.getTarget(workspaceRoot, path, true); 1652 if (target != null && !JavaCore.IGNORE.equals(project.getOption(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL, true))) { 1653 long projectTargetJDK = CompilerOptions.versionToJdkLevel(project.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, true)); 1654 long libraryJDK = Util.getJdkLevel(target); 1655 if (libraryJDK != 0 && libraryJDK > projectTargetJDK) { 1656 return new JavaModelStatus(IJavaModelStatusConstants.INCOMPATIBLE_JDK_LEVEL, project, path, CompilerOptions.versionFromJdkLevel(libraryJDK)); 1657 } 1658 } 1659 if (target instanceof IResource){ 1660 IResource resolvedResource = (IResource) target; 1661 switch(resolvedResource.getType()){ 1662 case IResource.FILE : 1663 if (org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(resolvedResource.getName())) { 1664 if (checkSourceAttachment 1665 && sourceAttachment != null 1666 && !sourceAttachment.isEmpty() 1667 && JavaModel.getTarget(workspaceRoot, sourceAttachment, true) == null){ 1668 return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundSourceAttachment, new String [] {sourceAttachment.toString(), path.toString(), projectName})); 1669 } 1670 } else { 1671 return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_illegalLibraryArchive, new String [] {entryPathMsg, projectName})); 1672 } 1673 break; 1674 case IResource.FOLDER : if (checkSourceAttachment 1676 && sourceAttachment != null 1677 && !sourceAttachment.isEmpty() 1678 && JavaModel.getTarget(workspaceRoot, sourceAttachment, true) == null){ 1679 return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundSourceAttachment, new String [] {sourceAttachment.toString(), path.toString(), projectName})); 1680 } 1681 } 1682 } else if (target instanceof File ){ 1683 File file = JavaModel.getFile(target); 1684 if (file == null) { 1685 return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_illegalExternalFolder, new String [] {path.toOSString(), projectName})); 1686 } else if (!org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(file.getName())) { 1687 return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_illegalLibraryArchive, (new String [] {path.toOSString(), projectName}))); 1688 } else if (checkSourceAttachment 1689 && sourceAttachment != null 1690 && !sourceAttachment.isEmpty() 1691 && JavaModel.getTarget(workspaceRoot, sourceAttachment, true) == null){ 1692 return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundSourceAttachment, new String [] {sourceAttachment.toString(), path.toOSString(), projectName})); 1693 } 1694 } else { 1695 boolean isExternal = path.getDevice() != null || !workspaceRoot.getProject(path.segment(0)).exists(); 1696 if (isExternal) { 1697 return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundLibrary, new String [] {path.toOSString(), projectName})); 1698 } else { 1699 return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundLibrary, new String [] {entryPathMsg, projectName})); 1700 } 1701 } 1702 } else { 1703 return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_illegalLibraryPath, new String [] {entryPathMsg, projectName})); 1704 } 1705 break; 1706 1707 case IClasspathEntry.CPE_PROJECT : 1709 if (path.isAbsolute() && path.segmentCount() == 1) { 1710 IProject prereqProjectRsc = workspaceRoot.getProject(path.segment(0)); 1711 IJavaProject prereqProject = JavaCore.create(prereqProjectRsc); 1712 try { 1713 if (!prereqProjectRsc.exists() || !prereqProjectRsc.hasNature(JavaCore.NATURE_ID)){ 1714 return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundProject, new String [] {path.segment(0), projectName})); 1715 } 1716 if (!prereqProjectRsc.isOpen()){ 1717 return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_closedProject, new String [] {path.segment(0)})); 1718 } 1719 if (!JavaCore.IGNORE.equals(project.getOption(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL, true))) { 1720 long projectTargetJDK = CompilerOptions.versionToJdkLevel(project.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, true)); 1721 long prereqProjectTargetJDK = CompilerOptions.versionToJdkLevel(prereqProject.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, true)); 1722 if (prereqProjectTargetJDK > projectTargetJDK) { 1723 return new JavaModelStatus(IJavaModelStatusConstants.INCOMPATIBLE_JDK_LEVEL, project, path, CompilerOptions.versionFromJdkLevel(prereqProjectTargetJDK)); 1724 } 1725 } 1726 } catch (CoreException e){ 1727 return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundProject, new String [] {path.segment(0), projectName})); 1728 } 1729 } else { 1730 return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_illegalProjectPath, new String [] {path.toString(), projectName})); 1731 } 1732 break; 1733 1734 case IClasspathEntry.CPE_SOURCE : 1736 if (((entry.getInclusionPatterns() != null && entry.getInclusionPatterns().length > 0) 1737 || (entry.getExclusionPatterns() != null && entry.getExclusionPatterns().length > 0)) 1738 && JavaCore.DISABLED.equals(project.getOption(JavaCore.CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS, true))) { 1739 return new JavaModelStatus(IJavaModelStatusConstants.DISABLED_CP_EXCLUSION_PATTERNS, project, path); 1740 } 1741 if (entry.getOutputLocation() != null && JavaCore.DISABLED.equals(project.getOption(JavaCore.CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS, true))) { 1742 return new JavaModelStatus(IJavaModelStatusConstants.DISABLED_CP_MULTIPLE_OUTPUT_LOCATIONS, project, path); 1743 } 1744 if (path.isAbsolute() && !path.isEmpty()) { 1745 IPath projectPath= project.getProject().getFullPath(); 1746 if (!projectPath.isPrefixOf(path) || JavaModel.getTarget(workspaceRoot, path, true) == null){ 1747 return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundSourceFolder, new String [] {entryPathMsg, projectName})); 1748 } 1749 } else { 1750 return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_illegalSourceFolderPath, new String [] {entryPathMsg, projectName})); 1751 } 1752 break; 1753 } 1754 1755 IClasspathAttribute[] extraAttributes = entry.getExtraAttributes(); 1757 if (extraAttributes != null) { 1758 int length = extraAttributes.length; 1759 HashSet set = new HashSet (length); 1760 for (int i=0; i<length; i++) { 1761 String attName = extraAttributes[i].getName(); 1762 if (!set.add(attName)) { 1763 return new JavaModelStatus(IJavaModelStatusConstants.NAME_COLLISION, Messages.bind(Messages.classpath_duplicateEntryExtraAttribute, new String [] {attName, entryPathMsg, projectName})); 1764 } 1765 } 1766 } 1767 1768 return JavaModelStatus.VERIFIED_OK; 1769 } 1770} 1771 | Popular Tags |