View | Details | Raw Unified | Return to bug 101425 | Differences between
and this patch

Collapse All | Expand All

(-)model/org/eclipse/jdt/internal/core/ClasspathEntry.java (-52 / +210 lines)
Lines 10-16 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.jdt.internal.core;
11
package org.eclipse.jdt.internal.core;
12
12
13
import java.io.ByteArrayOutputStream;
13
import java.io.File;
14
import java.io.File;
15
import java.io.OutputStreamWriter;
16
import java.io.UnsupportedEncodingException;
17
import java.util.ArrayList;
14
import java.util.HashMap;
18
import java.util.HashMap;
15
import java.util.HashSet;
19
import java.util.HashSet;
16
import java.util.Map;
20
import java.util.Map;
Lines 39-47 Link Here
39
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
43
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
40
import org.eclipse.jdt.internal.core.util.Messages;
44
import org.eclipse.jdt.internal.core.util.Messages;
41
import org.eclipse.jdt.internal.core.util.Util;
45
import org.eclipse.jdt.internal.core.util.Util;
46
import org.w3c.dom.DOMException;
42
import org.w3c.dom.Element;
47
import org.w3c.dom.Element;
48
import org.w3c.dom.NamedNodeMap;
43
import org.w3c.dom.Node;
49
import org.w3c.dom.Node;
44
import org.w3c.dom.NodeList;
50
import org.w3c.dom.NodeList;
51
import org.w3c.dom.Text;
45
52
46
/**
53
/**
47
 * @see IClasspathEntry
54
 * @see IClasspathEntry
Lines 119-124 Link Here
119
	private String rootID;
126
	private String rootID;
120
	private AccessRuleSet accessRuleSet;
127
	private AccessRuleSet accessRuleSet;
121
	
128
	
129
	
130
	static class UnknownXmlElements {
131
		String[] attributes;
132
		ArrayList children;
133
	}
134
	
122
	/*
135
	/*
123
	 * Default inclusion pattern set
136
	 * Default inclusion pattern set
124
	 */
137
	 */
Lines 278-287 Link Here
278
		return result;
291
		return result;
279
	}
292
	}
280
293
281
	static IClasspathAttribute[] decodeExtraAttributes(Element element) {
294
	static IClasspathAttribute[] decodeExtraAttributes(NodeList attributes) {
282
		Node extra = element.getElementsByTagName(TAG_ATTRIBUTES).item(0);
283
		if (extra == null) return NO_EXTRA_ATTRIBUTES;
284
		NodeList attributes = element.getElementsByTagName(TAG_ATTRIBUTE);
285
		if (attributes == null) return NO_EXTRA_ATTRIBUTES;
295
		if (attributes == null) return NO_EXTRA_ATTRIBUTES;
286
		int length = attributes.getLength();
296
		int length = attributes.getLength();
287
		if (length == 0) return NO_EXTRA_ATTRIBUTES;
297
		if (length == 0) return NO_EXTRA_ATTRIBUTES;
Lines 303-333 Link Here
303
		return result;
313
		return result;
304
	}
314
	}
305
	
315
	
306
	static IAccessRule[] decodeAccessRules(Element element) {
316
	static IAccessRule[] decodeAccessRules(NodeList list) {
307
		Node accessRules = element.getElementsByTagName(TAG_ACCESS_RULES).item(0);
317
		if (list == null) return null;
308
		if (accessRules == null || accessRules.getNodeType() != Node.ELEMENT_NODE) return null;
309
		NodeList list = ((Element) accessRules).getElementsByTagName(TAG_ACCESS_RULE);
310
		int length = list.getLength();
318
		int length = list.getLength();
311
		if (length == 0) return null;
319
		if (length == 0) return null;
312
		IAccessRule[] result = new IAccessRule[length];
320
		IAccessRule[] result = new IAccessRule[length];
313
		int index = 0;
321
		int index = 0;
314
		for (int i = 0; i < length; i++) {
322
		for (int i = 0; i < length; i++) {
315
			Node accessRule = list.item(i);
323
			Node accessRule = list.item(i);
316
			if (accessRule == null || accessRule.getNodeType() != Node.ELEMENT_NODE) return null;
324
			if (accessRule.getNodeType() == Node.ELEMENT_NODE) {
317
			Element elementAccessRule = (Element) accessRule;
325
				Element elementAccessRule = (Element) accessRule;
318
			String pattern = elementAccessRule.getAttribute(TAG_PATTERN);
326
				String pattern = elementAccessRule.getAttribute(TAG_PATTERN);
319
			if (pattern == null) continue;
327
				if (pattern == null) continue;
320
			String tagKind =  elementAccessRule.getAttribute(TAG_KIND);
328
				String tagKind =  elementAccessRule.getAttribute(TAG_KIND);
321
			int kind;
329
				int kind;
322
			if (TAG_ACCESSIBLE.equals(tagKind))
330
				if (TAG_ACCESSIBLE.equals(tagKind))
323
				kind = IAccessRule.K_ACCESSIBLE;
331
					kind = IAccessRule.K_ACCESSIBLE;
324
			else if (TAG_NON_ACCESSIBLE.equals(tagKind))
332
				else if (TAG_NON_ACCESSIBLE.equals(tagKind))
325
				kind = IAccessRule.K_NON_ACCESSIBLE;
333
					kind = IAccessRule.K_NON_ACCESSIBLE;
326
			else if (TAG_DISCOURAGED.equals(tagKind))
334
				else if (TAG_DISCOURAGED.equals(tagKind))
327
				kind = IAccessRule.K_DISCOURAGED;
335
					kind = IAccessRule.K_DISCOURAGED;
328
			else
336
				else
329
				continue;
337
					continue;
330
			result[index++] = new ClasspathAccessRule(new Path(pattern), kind);
338
				result[index++] = new ClasspathAccessRule(new Path(pattern), kind);
339
			}
331
		}
340
		}
332
		if (index != length)
341
		if (index != length)
333
			System.arraycopy(result, 0, result = new IAccessRule[index], 0, index);
342
			System.arraycopy(result, 0, result = new IAccessRule[index], 0, index);
Lines 337-344 Link Here
337
	/**
346
	/**
338
	 * Decode some element tag containing a sequence of patterns into IPath[]
347
	 * Decode some element tag containing a sequence of patterns into IPath[]
339
	 */
348
	 */
340
	private static IPath[] decodePatterns(Element element, String tag) {
349
	private static IPath[] decodePatterns(NamedNodeMap nodeMap, String tag) {
341
		String sequence = element.getAttribute(tag);
350
		String sequence = removeAttribute(tag, nodeMap);
342
		if (!sequence.equals("")) { //$NON-NLS-1$ 
351
		if (!sequence.equals("")) { //$NON-NLS-1$ 
343
			char[][] patterns = CharOperation.splitOn('|', sequence.toCharArray());
352
			char[][] patterns = CharOperation.splitOn('|', sequence.toCharArray());
344
			int patternCount;
353
			int patternCount;
Lines 352-357 Link Here
352
		}
361
		}
353
		return null;
362
		return null;
354
	}
363
	}
364
	
365
	private static void decodeUnknownNode(Node node, StringBuffer buffer, IJavaProject project) {
366
		ByteArrayOutputStream s = new ByteArrayOutputStream();
367
		OutputStreamWriter writer;
368
		try {
369
			writer = new OutputStreamWriter(s, "UTF8"); //$NON-NLS-1$
370
			XMLWriter xmlWriter = new XMLWriter(writer, project, false/*don't print XML version*/);
371
			decodeUnknownNode(node, xmlWriter, true/*insert new line*/);
372
			xmlWriter.flush();
373
			xmlWriter.close();
374
			buffer.append(s.toString("UTF8")); //$NON-NLS-1$
375
		} catch (UnsupportedEncodingException e) {
376
			// ignore (UTF8 is always supported)
377
		} 
378
	}
379
380
	private static void decodeUnknownNode(Node node, XMLWriter xmlWriter, boolean insertNewLine) {
381
		switch (node.getNodeType()) {
382
		case Node.ELEMENT_NODE:
383
			NamedNodeMap attributes = node.getAttributes();
384
			HashMap parameters = new HashMap();
385
			for (int i = 0, length = attributes == null ? 0 : attributes.getLength(); i < length; i++) {
386
				Node attribute = attributes.item(i);
387
				parameters.put(attribute.getNodeName(), attribute.getNodeValue());
388
			}
389
			NodeList children = node.getChildNodes();
390
			int childrenLength = children.getLength();
391
			String nodeName = node.getNodeName();
392
			xmlWriter.printTag(nodeName, parameters, false/*don't insert tab*/, false/*don't insert new line*/, childrenLength == 0/*close tag if no children*/);
393
			if (childrenLength > 0) {
394
				for (int i = 0; i < childrenLength; i++) {
395
					decodeUnknownNode(children.item(i), xmlWriter, false/*don't insert new line*/);
396
				}
397
				xmlWriter.endTag(nodeName, false/*don't insert tab*/, insertNewLine);
398
			}
399
			break;
400
		case Node.TEXT_NODE:
401
			String data = ((Text) node).getData();
402
			xmlWriter.printString(data, false/*don't insert tab*/, false/*don't insert new line*/);
403
			break;
404
		}
405
	}
406
	
355
	/*
407
	/*
356
	 * Returns a char based representation of the exclusions patterns full path.
408
	 * Returns a char based representation of the exclusions patterns full path.
357
	 */
409
	 */
Lines 389-395 Link Here
389
	/**
441
	/**
390
	 * Returns the XML encoding of the class path.
442
	 * Returns the XML encoding of the class path.
391
	 */
443
	 */
392
	public void elementEncode(XMLWriter writer, IPath projectPath, boolean indent, boolean newLine) {
444
	public void elementEncode(XMLWriter writer, IPath projectPath, boolean indent, boolean newLine, Map unknownElements) {
393
		HashMap parameters = new HashMap();
445
		HashMap parameters = new HashMap();
394
		
446
		
395
		parameters.put(TAG_KIND, ClasspathEntry.kindToString(this.entryKind));
447
		parameters.put(TAG_KIND, ClasspathEntry.kindToString(this.entryKind));
Lines 433-438 Link Here
433
			parameters.put(TAG_COMBINE_ACCESS_RULES, "false"); //$NON-NLS-1$
485
			parameters.put(TAG_COMBINE_ACCESS_RULES, "false"); //$NON-NLS-1$
434
		
486
		
435
		
487
		
488
		// unknown attributes
489
		UnknownXmlElements unknownXmlElements = unknownElements == null ? null : (UnknownXmlElements) unknownElements.get(this.path);
490
		String[] unknownAttributes;
491
		if (unknownXmlElements != null && (unknownAttributes = unknownXmlElements.attributes) != null)
492
			for (int i = 0, length = unknownAttributes.length; i < length; i+=2) {
493
				String tagName = unknownAttributes[i];
494
				String tagValue = unknownAttributes[i+1];
495
				parameters.put(tagName, tagValue);
496
			}
497
		
436
		if (this.specificOutputLocation != null) {
498
		if (this.specificOutputLocation != null) {
437
			IPath outputLocation = this.specificOutputLocation.removeFirstSegments(1);
499
			IPath outputLocation = this.specificOutputLocation.removeFirstSegments(1);
438
			outputLocation = outputLocation.makeRelative();
500
			outputLocation = outputLocation.makeRelative();
Lines 441-456 Link Here
441
503
442
		boolean hasExtraAttributes = this.extraAttributes.length != 0;
504
		boolean hasExtraAttributes = this.extraAttributes.length != 0;
443
		boolean hasRestrictions = getAccessRuleSet() != null; // access rule set is null if no access rules
505
		boolean hasRestrictions = getAccessRuleSet() != null; // access rule set is null if no access rules
444
		writer.printTag(TAG_CLASSPATHENTRY, parameters, indent, newLine, !hasExtraAttributes && !hasRestrictions /*close tag if no extra attributes and no restriction*/);
506
		ArrayList unknownChildren = unknownXmlElements != null ? unknownXmlElements.children : null;
507
		boolean hasUnknownChildren = unknownChildren != null;
508
		writer.printTag(
509
			TAG_CLASSPATHENTRY, 
510
			parameters, 
511
			indent, 
512
			newLine, 
513
			!hasExtraAttributes && !hasRestrictions && !hasUnknownChildren/*close tag if no extra attributes, no restriction and no unknown children*/);
445
		
514
		
446
		if (hasExtraAttributes)
515
		if (hasExtraAttributes)
447
			encodeExtraAttributes(writer, indent, newLine);
516
			encodeExtraAttributes(writer, indent, newLine);
448
	
517
	
449
		if (hasRestrictions)
518
		if (hasRestrictions)
450
			encodeAccessRules(writer, indent, newLine);
519
			encodeAccessRules(writer, indent, newLine);
520
		
521
		if (hasUnknownChildren)
522
			encodeUnknownChildren(writer, indent, newLine, unknownChildren);
451
523
452
		if (hasExtraAttributes || hasRestrictions)
524
		if (hasExtraAttributes || hasRestrictions || hasUnknownChildren)
453
			writer.endTag(TAG_CLASSPATHENTRY, indent);
525
			writer.endTag(TAG_CLASSPATHENTRY, indent, true/*insert new line*/);
454
	}
526
	}
455
	
527
	
456
	void encodeExtraAttributes(XMLWriter writer, boolean indent, boolean newLine) {
528
	void encodeExtraAttributes(XMLWriter writer, boolean indent, boolean newLine) {
Lines 462-468 Link Here
462
			parameters.put(TAG_ATTRIBUTE_VALUE, attribute.getValue());
534
			parameters.put(TAG_ATTRIBUTE_VALUE, attribute.getValue());
463
			writer.printTag(TAG_ATTRIBUTE, parameters, indent, newLine, true);
535
			writer.printTag(TAG_ATTRIBUTE, parameters, indent, newLine, true);
464
		}
536
		}
465
		writer.endTag(TAG_ATTRIBUTES, indent);
537
		writer.endTag(TAG_ATTRIBUTES, indent, true/*insert new line*/);
466
	}
538
	}
467
	
539
	
468
	void encodeAccessRules(XMLWriter writer, boolean indent, boolean newLine) {
540
	void encodeAccessRules(XMLWriter writer, boolean indent, boolean newLine) {
Lines 472-478 Link Here
472
		for (int i = 0, length = rules.length; i < length; i++) {
544
		for (int i = 0, length = rules.length; i < length; i++) {
473
			encodeAccessRule(rules[i], writer, indent, newLine);
545
			encodeAccessRule(rules[i], writer, indent, newLine);
474
		}
546
		}
475
		writer.endTag(TAG_ACCESS_RULES, indent);
547
		writer.endTag(TAG_ACCESS_RULES, indent, true/*insert new line*/);
476
	}
548
	}
477
	
549
	
478
	private void encodeAccessRule(AccessRule accessRule, XMLWriter writer, boolean indent, boolean newLine) {
550
	private void encodeAccessRule(AccessRule accessRule, XMLWriter writer, boolean indent, boolean newLine) {
Lines 496-506 Link Here
496
568
497
	}
569
	}
498
	
570
	
499
	public static IClasspathEntry elementDecode(Element element, IJavaProject project) {
571
	private void encodeUnknownChildren(XMLWriter writer, boolean indent, boolean newLine, ArrayList unknownChildren) {
572
		for (int i = 0, length = unknownChildren.size(); i < length; i++) {
573
			String child = (String) unknownChildren.get(i);
574
			writer.printString(child, indent, false/*don't insert new line*/);
575
		}
576
	}
577
	
578
	public static IClasspathEntry elementDecode(Element element, IJavaProject project, Map unknownElements) {
500
	
579
	
501
		IPath projectPath = project.getProject().getFullPath();
580
		IPath projectPath = project.getProject().getFullPath();
502
		String kindAttr = element.getAttribute(TAG_KIND);
581
		NamedNodeMap attributes = element.getAttributes();
503
		String pathAttr = element.getAttribute(TAG_PATH);
582
		NodeList children = element.getChildNodes();
583
		boolean[] foundChildren = new boolean[children.getLength()];
584
		String kindAttr = removeAttribute(TAG_KIND, attributes);
585
		String pathAttr = removeAttribute(TAG_PATH, attributes);
504
586
505
		// ensure path is absolute
587
		// ensure path is absolute
506
		IPath path = new Path(pathAttr); 		
588
		IPath path = new Path(pathAttr); 		
Lines 511-539 Link Here
511
		// source attachment info (optional)
593
		// source attachment info (optional)
512
		IPath sourceAttachmentPath = 
594
		IPath sourceAttachmentPath = 
513
			element.hasAttribute(TAG_SOURCEPATH)	
595
			element.hasAttribute(TAG_SOURCEPATH)	
514
			? new Path(element.getAttribute(TAG_SOURCEPATH))
596
			? new Path(removeAttribute(TAG_SOURCEPATH, attributes))
515
			: null;
597
			: null;
516
		if (kind != IClasspathEntry.CPE_VARIABLE && sourceAttachmentPath != null && !sourceAttachmentPath.isAbsolute()) {
598
		if (kind != IClasspathEntry.CPE_VARIABLE && sourceAttachmentPath != null && !sourceAttachmentPath.isAbsolute()) {
517
			sourceAttachmentPath = projectPath.append(sourceAttachmentPath);
599
			sourceAttachmentPath = projectPath.append(sourceAttachmentPath);
518
		}
600
		}
519
		IPath sourceAttachmentRootPath = 
601
		IPath sourceAttachmentRootPath = 
520
			element.hasAttribute(TAG_ROOTPATH)
602
			element.hasAttribute(TAG_ROOTPATH)
521
			? new Path(element.getAttribute(TAG_ROOTPATH))
603
			? new Path(removeAttribute(TAG_ROOTPATH, attributes))
522
			: null;
604
			: null;
523
		
605
		
524
		// exported flag (optional)
606
		// exported flag (optional)
525
		boolean isExported = element.getAttribute(TAG_EXPORTED).equals("true"); //$NON-NLS-1$
607
		boolean isExported = removeAttribute(TAG_EXPORTED, attributes).equals("true"); //$NON-NLS-1$
526
608
527
		// inclusion patterns (optional)
609
		// inclusion patterns (optional)
528
		IPath[] inclusionPatterns = decodePatterns(element, TAG_INCLUDING);
610
		IPath[] inclusionPatterns = decodePatterns(attributes, TAG_INCLUDING);
529
		if (inclusionPatterns == null) inclusionPatterns = INCLUDE_ALL;
611
		if (inclusionPatterns == null) inclusionPatterns = INCLUDE_ALL;
530
		
612
		
531
		// exclusion patterns (optional)
613
		// exclusion patterns (optional)
532
		IPath[] exclusionPatterns = decodePatterns(element, TAG_EXCLUDING);
614
		IPath[] exclusionPatterns = decodePatterns(attributes, TAG_EXCLUDING);
533
		if (exclusionPatterns == null) exclusionPatterns = EXCLUDE_NONE;
615
		if (exclusionPatterns == null) exclusionPatterns = EXCLUDE_NONE;
534
		
616
		
535
		// access rules (optional)
617
		// access rules (optional)
536
		IAccessRule[] accessRules = decodeAccessRules(element);
618
		NodeList attributeList = getChildAttributes(TAG_ACCESS_RULES, children, foundChildren);
619
		IAccessRule[] accessRules = decodeAccessRules(attributeList);
537
		
620
		
538
		// backward compatibility
621
		// backward compatibility
539
		if (accessRules == null) {
622
		if (accessRules == null) {
Lines 541-565 Link Here
541
		}
624
		}
542
625
543
		// combine access rules (optional)
626
		// combine access rules (optional)
544
		boolean combineAccessRestrictions = !element.getAttribute(TAG_COMBINE_ACCESS_RULES).equals("false"); //$NON-NLS-1$
627
		boolean combineAccessRestrictions = !removeAttribute(TAG_COMBINE_ACCESS_RULES, attributes).equals("false"); //$NON-NLS-1$
545
		
628
		
546
		// extra attributes (optional)
629
		// extra attributes (optional)
547
		IClasspathAttribute[] extraAttributes = decodeExtraAttributes(element);
630
		attributeList = getChildAttributes(TAG_ATTRIBUTES, children, foundChildren);
631
		IClasspathAttribute[] extraAttributes = decodeExtraAttributes(attributeList);
548
		
632
		
549
		// custom output location
633
		// custom output location
550
		IPath outputLocation = element.hasAttribute(TAG_OUTPUT) ? projectPath.append(element.getAttribute(TAG_OUTPUT)) : null;
634
		IPath outputLocation = element.hasAttribute(TAG_OUTPUT) ? projectPath.append(removeAttribute(TAG_OUTPUT, attributes)) : null;
635
		
636
		String[] unknownAttributes = null;
637
		ArrayList unknownChildren = null;
638
639
		if (unknownElements != null) {
640
			// unknown attributes
641
			int unknownAttributeLength = attributes.getLength();
642
			if (unknownAttributeLength != 0) {
643
				unknownAttributes = new String[unknownAttributeLength*2];
644
				for (int i = 0; i < unknownAttributeLength; i++) {
645
					Node attribute = attributes.item(i);
646
					unknownAttributes[i*2] = attribute.getNodeName();
647
					unknownAttributes[i*2 + 1] = attribute.getNodeValue();
648
				}
649
			}
650
			
651
			// unknown children
652
			for (int i = 0, length = foundChildren.length; i < length; i++) {
653
				if (!foundChildren[i]) {
654
					Node node = children.item(i);
655
					if (node.getNodeType() != Node.ELEMENT_NODE) continue;
656
					if (unknownChildren == null)
657
						unknownChildren = new ArrayList();
658
					StringBuffer buffer = new StringBuffer();
659
					decodeUnknownNode(node, buffer, project);
660
					unknownChildren.add(buffer.toString());
661
				}
662
			}
663
		}
551
		
664
		
552
		// recreate the CP entry
665
		// recreate the CP entry
553
		IClasspathEntry entry = null;
666
		IClasspathEntry entry = null;
554
		switch (kind) {
667
		switch (kind) {
555
668
556
			case IClasspathEntry.CPE_PROJECT :
669
			case IClasspathEntry.CPE_PROJECT :
557
				entry = JavaCore.newProjectEntry(
670
				entry = new ClasspathEntry(
558
												path, 
671
				IPackageFragmentRoot.K_SOURCE,
559
												accessRules,
672
				IClasspathEntry.CPE_PROJECT,
560
												combineAccessRestrictions,
673
				path,
561
												extraAttributes,
674
				ClasspathEntry.INCLUDE_ALL, // inclusion patterns
562
												isExported);
675
				ClasspathEntry.EXCLUDE_NONE, // exclusion patterns
676
				null, // source attachment
677
				null, // source attachment root
678
				null, // specific output folder
679
				isExported,
680
				accessRules,
681
				combineAccessRestrictions,
682
				extraAttributes);
563
				break;				
683
				break;				
564
			case IClasspathEntry.CPE_LIBRARY :
684
			case IClasspathEntry.CPE_LIBRARY :
565
				entry = JavaCore.newLibraryEntry(
685
				entry = JavaCore.newLibraryEntry(
Lines 574-580 Link Here
574
				// must be an entry in this project or specify another project
694
				// must be an entry in this project or specify another project
575
				String projSegment = path.segment(0);
695
				String projSegment = path.segment(0);
576
				if (projSegment != null && projSegment.equals(project.getElementName())) { // this project
696
				if (projSegment != null && projSegment.equals(project.getElementName())) { // this project
577
					return JavaCore.newSourceEntry(path, inclusionPatterns, exclusionPatterns, outputLocation, extraAttributes);
697
					entry = JavaCore.newSourceEntry(path, inclusionPatterns, exclusionPatterns, outputLocation, extraAttributes);
578
				} else { 
698
				} else { 
579
					if (path.segmentCount() == 1) {
699
					if (path.segmentCount() == 1) {
580
						// another project
700
						// another project
Lines 586-592 Link Here
586
												isExported);
706
												isExported);
587
					} else {
707
					} else {
588
						// an invalid source folder
708
						// an invalid source folder
589
						return JavaCore.newSourceEntry(path, inclusionPatterns, exclusionPatterns, outputLocation, extraAttributes);
709
						entry = JavaCore.newSourceEntry(path, inclusionPatterns, exclusionPatterns, outputLocation, extraAttributes);
590
					}
710
					}
591
				}
711
				}
592
				break;
712
				break;
Lines 608-614 Link Here
608
				break;
728
				break;
609
			case ClasspathEntry.K_OUTPUT :
729
			case ClasspathEntry.K_OUTPUT :
610
				if (!path.isAbsolute()) return null;
730
				if (!path.isAbsolute()) return null;
611
				return new ClasspathEntry(
731
				entry = new ClasspathEntry(
612
						ClasspathEntry.K_OUTPUT,
732
						ClasspathEntry.K_OUTPUT,
613
						IClasspathEntry.CPE_LIBRARY,
733
						IClasspathEntry.CPE_LIBRARY,
614
						path,
734
						path,
Lines 621-631 Link Here
621
						null, // no access rules
741
						null, // no access rules
622
						false, // no accessible files to combine
742
						false, // no accessible files to combine
623
						NO_EXTRA_ATTRIBUTES);
743
						NO_EXTRA_ATTRIBUTES);
744
				break;
624
			default :
745
			default :
625
				throw new Assert.AssertionFailedException(Messages.bind(Messages.classpath_unknownKind, kindAttr)); 
746
				throw new Assert.AssertionFailedException(Messages.bind(Messages.classpath_unknownKind, kindAttr)); 
626
		}
747
		}
748
		
749
		if (unknownAttributes != null || unknownChildren != null) {
750
			UnknownXmlElements unknownXmlElements = new UnknownXmlElements();
751
			unknownXmlElements.attributes = unknownAttributes;
752
			unknownXmlElements.children = unknownChildren;
753
			unknownElements.put(path, unknownXmlElements);
754
		}
755
		
627
		return entry;
756
		return entry;
628
	}
757
	}
758
	
759
	public static NodeList getChildAttributes(String childName, NodeList children, boolean[] foundChildren) {
760
		for (int i = 0, length = foundChildren.length; i < length; i++) {
761
			Node node = children.item(i);
762
			if (childName.equals(node.getNodeName())) {
763
				foundChildren[i] = true;
764
				return node.getChildNodes();
765
			}
766
		}
767
		return null;
768
	}
769
770
	
771
	private static String removeAttribute(String nodeName, NamedNodeMap nodeMap) {
772
		Node node = removeNode(nodeName, nodeMap);
773
		if (node == null)
774
			return ""; // //$NON-NLS-1$
775
		return node.getNodeValue();
776
	}
777
	
778
	private static Node removeNode(String nodeName, NamedNodeMap nodeMap) {
779
		try {
780
			return nodeMap.removeNamedItem(nodeName);
781
		} catch (DOMException e) {
782
			if (e.code != DOMException.NOT_FOUND_ERR)
783
				throw e;
784
			return null;
785
		}
786
	}
629
787
630
	/**
788
	/**
631
	 * Encode some patterns into XML parameter tag
789
	 * Encode some patterns into XML parameter tag
(-)model/org/eclipse/jdt/internal/core/JavaModelManager.java (-1 / +2 lines)
Lines 2278-2284 Link Here
2278
							containerString = ((JavaProject)project).encodeClasspath(
2278
							containerString = ((JavaProject)project).encodeClasspath(
2279
									entries, 
2279
									entries, 
2280
									null, 
2280
									null, 
2281
									false);
2281
									false,
2282
									null/*not interested in unknown elements*/);
2282
						}
2283
						}
2283
					} catch(JavaModelException e){
2284
					} catch(JavaModelException e){
2284
						// could not encode entry: will not persist
2285
						// could not encode entry: will not persist
(-)model/org/eclipse/jdt/internal/core/JavaProject.java (-8 / +20 lines)
Lines 796-801 Link Here
796
	 * Reads and decode an XML classpath string
796
	 * Reads and decode an XML classpath string
797
	 */
797
	 */
798
	protected IClasspathEntry[] decodeClasspath(String xmlClasspath, boolean createMarker, boolean logProblems) {
798
	protected IClasspathEntry[] decodeClasspath(String xmlClasspath, boolean createMarker, boolean logProblems) {
799
		return decodeClasspath(xmlClasspath, createMarker, logProblems, null/*not interested in unknown elements*/);
800
	}
801
	
802
	/**
803
	 * Reads and decode an XML classpath string
804
	 */
805
	protected IClasspathEntry[] decodeClasspath(String xmlClasspath, boolean createMarker, boolean logProblems, Map unknownElements) {
799
806
800
		ArrayList paths = new ArrayList();
807
		ArrayList paths = new ArrayList();
801
		IClasspathEntry defaultOutput = null;
808
		IClasspathEntry defaultOutput = null;
Lines 825-831 Link Here
825
			for (int i = 0; i < length; ++i) {
832
			for (int i = 0; i < length; ++i) {
826
				Node node = list.item(i);
833
				Node node = list.item(i);
827
				if (node.getNodeType() == Node.ELEMENT_NODE) {
834
				if (node.getNodeType() == Node.ELEMENT_NODE) {
828
					IClasspathEntry entry = ClasspathEntry.elementDecode((Element)node, this);
835
					IClasspathEntry entry = ClasspathEntry.elementDecode((Element)node, this, unknownElements);
829
					if (entry != null){
836
					if (entry != null){
830
						if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) { 
837
						if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) { 
831
							defaultOutput = entry; // separate output
838
							defaultOutput = entry; // separate output
Lines 901-915 Link Here
901
	/**
908
	/**
902
	 * Returns the XML String encoding of the class path.
909
	 * Returns the XML String encoding of the class path.
903
	 */
910
	 */
904
	protected String encodeClasspath(IClasspathEntry[] classpath, IPath outputLocation, boolean indent) throws JavaModelException {
911
	protected String encodeClasspath(IClasspathEntry[] classpath, IPath outputLocation, boolean indent, Map unknownElements) throws JavaModelException {
905
		try {
912
		try {
906
			ByteArrayOutputStream s = new ByteArrayOutputStream();
913
			ByteArrayOutputStream s = new ByteArrayOutputStream();
907
			OutputStreamWriter writer = new OutputStreamWriter(s, "UTF8"); //$NON-NLS-1$
914
			OutputStreamWriter writer = new OutputStreamWriter(s, "UTF8"); //$NON-NLS-1$
908
			XMLWriter xmlWriter = new XMLWriter(writer, this);
915
			XMLWriter xmlWriter = new XMLWriter(writer, this, true/*print XML version*/);
909
			
916
			
910
			xmlWriter.startTag(ClasspathEntry.TAG_CLASSPATH, indent);
917
			xmlWriter.startTag(ClasspathEntry.TAG_CLASSPATH, indent);
911
			for (int i = 0; i < classpath.length; ++i) {
918
			for (int i = 0; i < classpath.length; ++i) {
912
				((ClasspathEntry)classpath[i]).elementEncode(xmlWriter, this.project.getFullPath(), indent, true);
919
				((ClasspathEntry)classpath[i]).elementEncode(xmlWriter, this.project.getFullPath(), indent, true, unknownElements);
913
			}
920
			}
914
	
921
	
915
			if (outputLocation != null) {
922
			if (outputLocation != null) {
Lines 921-927 Link Here
921
				xmlWriter.printTag(ClasspathEntry.TAG_CLASSPATHENTRY, parameters, indent, true, true);
928
				xmlWriter.printTag(ClasspathEntry.TAG_CLASSPATHENTRY, parameters, indent, true, true);
922
			}
929
			}
923
	
930
	
924
			xmlWriter.endTag(ClasspathEntry.TAG_CLASSPATH, indent);
931
			xmlWriter.endTag(ClasspathEntry.TAG_CLASSPATH, indent, true/*insert new line*/);
925
			writer.flush();
932
			writer.flush();
926
			writer.close();
933
			writer.close();
927
			return s.toString("UTF8");//$NON-NLS-1$
934
			return s.toString("UTF8");//$NON-NLS-1$
Lines 2537-2542 Link Here
2537
	 * Returns INVALID_CLASSPATH if it has a format problem.
2544
	 * Returns INVALID_CLASSPATH if it has a format problem.
2538
	 */
2545
	 */
2539
	protected IClasspathEntry[] readClasspathFile(boolean createMarker, boolean logProblems) {
2546
	protected IClasspathEntry[] readClasspathFile(boolean createMarker, boolean logProblems) {
2547
		return readClasspathFile(createMarker, logProblems, null/*not interested in unknown elements*/);
2548
	}
2549
	
2550
	protected IClasspathEntry[] readClasspathFile(boolean createMarker, boolean logProblems, Map unknownElements) {
2540
2551
2541
		try {
2552
		try {
2542
			String xmlClasspath = getSharedProperty(CLASSPATH_FILENAME);
2553
			String xmlClasspath = getSharedProperty(CLASSPATH_FILENAME);
Lines 2548-2554 Link Here
2548
				}
2559
				}
2549
				return null;
2560
				return null;
2550
			}
2561
			}
2551
			return decodeClasspath(xmlClasspath, createMarker, logProblems);
2562
			return decodeClasspath(xmlClasspath, createMarker, logProblems, unknownElements);
2552
		} catch(CoreException e) {
2563
		} catch(CoreException e) {
2553
			// file does not exist (or not accessible)
2564
			// file does not exist (or not accessible)
2554
			if (createMarker && this.project.isAccessible()) {
2565
			if (createMarker && this.project.isAccessible()) {
Lines 2653-2659 Link Here
2653
2664
2654
		if (!this.project.isAccessible()) return false;
2665
		if (!this.project.isAccessible()) return false;
2655
2666
2656
		IClasspathEntry[] fileEntries = readClasspathFile(false /*don't create markers*/, false/*don't log problems*/);
2667
		Map unknownElements = new HashMap();
2668
		IClasspathEntry[] fileEntries = readClasspathFile(false /*don't create markers*/, false/*don't log problems*/, unknownElements);
2657
		if (fileEntries != null && isClasspathEqualsTo(newClasspath, newOutputLocation, fileEntries)) {
2669
		if (fileEntries != null && isClasspathEqualsTo(newClasspath, newOutputLocation, fileEntries)) {
2658
			// no need to save it, it is the same
2670
			// no need to save it, it is the same
2659
			return false;
2671
			return false;
Lines 2661-2667 Link Here
2661
2673
2662
		// actual file saving
2674
		// actual file saving
2663
		try {
2675
		try {
2664
			setSharedProperty(CLASSPATH_FILENAME, encodeClasspath(newClasspath, newOutputLocation, true));
2676
			setSharedProperty(CLASSPATH_FILENAME, encodeClasspath(newClasspath, newOutputLocation, true, unknownElements));
2665
			return true;
2677
			return true;
2666
		} catch (CoreException e) {
2678
		} catch (CoreException e) {
2667
			throw new JavaModelException(e);
2679
			throw new JavaModelException(e);
(-)model/org/eclipse/jdt/internal/core/UserLibrary.java (-5 / +9 lines)
Lines 99-105 Link Here
99
	/* package */  String serialize() throws IOException {
99
	/* package */  String serialize() throws IOException {
100
		ByteArrayOutputStream s = new ByteArrayOutputStream();
100
		ByteArrayOutputStream s = new ByteArrayOutputStream();
101
		OutputStreamWriter writer = new OutputStreamWriter(s, "UTF8"); //$NON-NLS-1$
101
		OutputStreamWriter writer = new OutputStreamWriter(s, "UTF8"); //$NON-NLS-1$
102
		XMLWriter xmlWriter = new XMLWriter(writer, null/*use the workspace line delimiter*/);
102
		XMLWriter xmlWriter = new XMLWriter(writer, null/*use the workspace line delimiter*/, true/*print XML version*/);
103
		
103
		
104
		HashMap library = new HashMap();
104
		HashMap library = new HashMap();
105
		library.put(TAG_VERSION, String.valueOf(CURRENT_VERSION));
105
		library.put(TAG_VERSION, String.valueOf(CURRENT_VERSION));
Lines 134-143 Link Here
134
134
135
			// write archive end tag if necessary
135
			// write archive end tag if necessary
136
			if (hasExtraAttributes || hasRestrictions) {
136
			if (hasExtraAttributes || hasRestrictions) {
137
				xmlWriter.endTag(TAG_ARCHIVE, true);
137
				xmlWriter.endTag(TAG_ARCHIVE, true/*insert tab*/, true/*insert new line*/);
138
			}
138
			}
139
		}	
139
		}	
140
		xmlWriter.endTag(TAG_USERLIBRARY, true);
140
		xmlWriter.endTag(TAG_USERLIBRARY, true/*insert tab*/, true/*insert new line*/);
141
		writer.flush();
141
		writer.flush();
142
		writer.close();
142
		writer.close();
143
		return s.toString("UTF8");//$NON-NLS-1$
143
		return s.toString("UTF8");//$NON-NLS-1$
Lines 177-184 Link Here
177
					String path = element.getAttribute(TAG_PATH);
177
					String path = element.getAttribute(TAG_PATH);
178
					IPath sourceAttach= element.hasAttribute(TAG_SOURCEATTACHMENT) ? new Path(element.getAttribute(TAG_SOURCEATTACHMENT)) : null;
178
					IPath sourceAttach= element.hasAttribute(TAG_SOURCEATTACHMENT) ? new Path(element.getAttribute(TAG_SOURCEATTACHMENT)) : null;
179
					IPath sourceAttachRoot= element.hasAttribute(TAG_SOURCEATTACHMENTROOT) ? new Path(element.getAttribute(TAG_SOURCEATTACHMENTROOT)) : null;
179
					IPath sourceAttachRoot= element.hasAttribute(TAG_SOURCEATTACHMENTROOT) ? new Path(element.getAttribute(TAG_SOURCEATTACHMENTROOT)) : null;
180
					IClasspathAttribute[] extraAttributes = ClasspathEntry.decodeExtraAttributes(element);
180
					NodeList children = element.getElementsByTagName("*"); //$NON-NLS-1$
181
					IAccessRule[] accessRules = ClasspathEntry.decodeAccessRules(element);
181
					boolean[] foundChildren = new boolean[children.getLength()];
182
					NodeList attributeList = ClasspathEntry.getChildAttributes(ClasspathEntry.TAG_ATTRIBUTES, children, foundChildren);
183
					IClasspathAttribute[] extraAttributes = ClasspathEntry.decodeExtraAttributes(attributeList);
184
					attributeList = ClasspathEntry.getChildAttributes(ClasspathEntry.TAG_ACCESS_RULES, children, foundChildren);
185
					IAccessRule[] accessRules = ClasspathEntry.decodeAccessRules(attributeList);
182
					IClasspathEntry entry = JavaCore.newLibraryEntry(new Path(path), sourceAttach, sourceAttachRoot, accessRules, extraAttributes, false/*not exported*/);
186
					IClasspathEntry entry = JavaCore.newLibraryEntry(new Path(path), sourceAttach, sourceAttachRoot, accessRules, extraAttributes, false/*not exported*/);
183
					res.add(entry);
187
					res.add(entry);
184
				}
188
				}
(-)model/org/eclipse/jdt/internal/core/XMLWriter.java (-9 / +14 lines)
Lines 58-73 Link Here
58
	}
58
	}
59
	private int tab;
59
	private int tab;
60
	private String lineSeparator;
60
	private String lineSeparator;
61
	public XMLWriter(Writer writer, IJavaProject project) {
61
	public XMLWriter(Writer writer, IJavaProject project, boolean printXmlVersion) {
62
		super(writer);
62
		super(writer);
63
		this.tab= 0;
63
		this.tab= 0;
64
		this.lineSeparator = Util.getLineSeparator((String) null, project);
64
		this.lineSeparator = Util.getLineSeparator((String) null, project);
65
		print(XML_VERSION);
65
		if (printXmlVersion) {
66
		print(this.lineSeparator);
66
			print(XML_VERSION);
67
			print(this.lineSeparator);
68
		}
67
	}
69
	}
68
	public void endTag(String name, boolean insertTab) {
70
	public void endTag(String name, boolean insertTab, boolean insertNewLine) {
69
		this.tab --;
71
		this.tab --;
70
		printTag('/' + name, null/*no parameters*/, insertTab, true/*insert new line*/, false/*don't close tag*/);
72
		printTag('/' + name, null/*no parameters*/, insertTab, insertNewLine, false/*don't close tag*/);
71
	}
73
	}
72
	private void printTabulation() {
74
	private void printTabulation() {
73
		for (int i= 0; i < tab; i++)
75
		for (int i= 0; i < tab; i++)
Lines 92-107 Link Here
92
		} else {
94
		} else {
93
			sb.append(">"); //$NON-NLS-1$
95
			sb.append(">"); //$NON-NLS-1$
94
		}
96
		}
97
		printString(sb.toString(), insertTab, insertNewLine);
98
		if (parameters != null && !closeTag)
99
			this.tab++;
100
101
	}
102
	public void printString(String string, boolean insertTab, boolean insertNewLine) {
95
		if (insertTab) {
103
		if (insertTab) {
96
			printTabulation();
104
			printTabulation();
97
		}
105
		}
98
		print(sb.toString());
106
		print(string);
99
		if (insertNewLine) {
107
		if (insertNewLine) {
100
			print(this.lineSeparator);
108
			print(this.lineSeparator);
101
		}
109
		}
102
		if (parameters != null && !closeTag)
103
			this.tab++;
104
105
	}
110
	}
106
	public void startTag(String name, boolean insertTab) {
111
	public void startTag(String name, boolean insertTab) {
107
		printTag(name, null/*no parameters*/, insertTab, true/*insert new line*/, false/*don't close tag*/);
112
		printTag(name, null/*no parameters*/, insertTab, true/*insert new line*/, false/*don't close tag*/);

Return to bug 101425