d634382e4739e4e4cc20acddd52eed3e3c888fbb
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / core / ClasspathEntry.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2003 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.core;
12
13 import java.util.HashMap;
14
15 import net.sourceforge.phpdt.core.IClasspathEntry;
16 import net.sourceforge.phpdt.core.IJavaProject;
17 import net.sourceforge.phpdt.core.IPackageFragmentRoot;
18 import net.sourceforge.phpdt.core.JavaCore;
19 import net.sourceforge.phpdt.core.JavaModelException;
20 import net.sourceforge.phpdt.core.compiler.CharOperation;
21 import net.sourceforge.phpdt.internal.core.util.Util;
22 import net.sourceforge.phpdt.internal.corext.Assert;
23
24 import org.eclipse.core.runtime.IPath;
25 import org.eclipse.core.runtime.Path;
26 import net.sourceforge.phpdt.internal.core.XMLWriter;
27 import org.w3c.dom.Document;
28 import org.w3c.dom.Element;
29
30 /**
31  * @see IClasspathEntry
32  */
33 public class ClasspathEntry implements IClasspathEntry {
34
35         /**
36          * Describes the kind of classpath entry - one of 
37          * CPE_PROJECT, CPE_LIBRARY, CPE_SOURCE, CPE_VARIABLE or CPE_CONTAINER
38          */
39         public int entryKind;
40
41         /**
42          * Describes the kind of package fragment roots found on
43          * this classpath entry - either K_BINARY or K_SOURCE or
44          * K_OUTPUT.
45          */
46         public int contentKind;
47
48         /**
49          * The meaning of the path of a classpath entry depends on its entry kind:<ul>
50          *      <li>Source code in the current project (<code>CPE_SOURCE</code>) -  
51          *      The path associated with this entry is the absolute path to the root folder. </li>
52          *      <li>A binary library in the current project (<code>CPE_LIBRARY</code>) - the path
53          *              associated with this entry is the absolute path to the JAR (or root folder), and 
54          *              in case it refers to an external JAR, then there is no associated resource in 
55          *              the workbench.
56          *      <li>A required project (<code>CPE_PROJECT</code>) - the path of the entry denotes the
57          *              path to the corresponding project resource.</li>
58          *  <li>A variable entry (<code>CPE_VARIABLE</code>) - the first segment of the path 
59          *      is the name of a classpath variable. If this classpath variable
60          *              is bound to the path <it>P</it>, the path of the corresponding classpath entry
61          *              is computed by appending to <it>P</it> the segments of the returned
62          *              path without the variable.</li>
63          *  <li> A container entry (<code>CPE_CONTAINER</code>) - the first segment of the path is denoting
64          *     the unique container identifier (for which a <code>ClasspathContainerInitializer</code> could be
65          *      registered), and the remaining segments are used as additional hints for resolving the container entry to
66          *      an actual <code>IClasspathContainer</code>.</li>
67          */
68         public IPath path;
69
70         /**
71          * Patterns allowing to exclude portions of the resource tree denoted by this entry path.
72          */
73         
74         public IPath[] exclusionPatterns;
75         private char[][] fullCharExclusionPatterns;
76         private final static char[][] UNINIT_PATTERNS = new char[][] { "Non-initialized yet".toCharArray() }; //$NON-NLS-1$
77
78         private String rootID;
79         
80         /**
81          * Default exclusion pattern set
82          */
83         public final static IPath[] NO_EXCLUSION_PATTERNS = {};
84                                 
85         /**
86          * Describes the path to the source archive associated with this
87          * classpath entry, or <code>null</code> if this classpath entry has no
88          * source attachment.
89          * <p>
90          * Only library and variable classpath entries may have source attachments.
91          * For library classpath entries, the result path (if present) locates a source
92          * archive. For variable classpath entries, the result path (if present) has
93          * an analogous form and meaning as the variable path, namely the first segment 
94          * is the name of a classpath variable.
95          */
96         public IPath sourceAttachmentPath;
97
98         /**
99          * Describes the path within the source archive where package fragments
100          * are located. An empty path indicates that packages are located at
101          * the root of the source archive. Returns a non-<code>null</code> value
102          * if and only if <code>getSourceAttachmentPath</code> returns 
103          * a non-<code>null</code> value.
104          */
105         public IPath sourceAttachmentRootPath;
106
107         /**
108          * Specific output location (for this source entry)
109          */
110         public IPath specificOutputLocation;
111         
112         /**
113          * A constant indicating an output location.
114          */
115         public static final int K_OUTPUT = 10;
116
117         /**
118          * The export flag
119          */
120         public boolean isExported;
121
122         /**
123          * Creates a class path entry of the specified kind with the given path.
124          */
125         public ClasspathEntry(
126                 int contentKind,
127                 int entryKind,
128                 IPath path,
129                 IPath[] exclusionPatterns,
130                 IPath sourceAttachmentPath,
131                 IPath sourceAttachmentRootPath,
132                 IPath specificOutputLocation,
133                 boolean isExported) {
134
135                 this.contentKind = contentKind;
136                 this.entryKind = entryKind;
137                 this.path = path;
138                 this.exclusionPatterns = exclusionPatterns;
139                 if (exclusionPatterns.length > 0) {
140                         this.fullCharExclusionPatterns = UNINIT_PATTERNS;
141                 }
142                 this.sourceAttachmentPath = sourceAttachmentPath;
143                 this.sourceAttachmentRootPath = sourceAttachmentRootPath;
144                 this.specificOutputLocation = specificOutputLocation;
145                 this.isExported = isExported;
146         }
147         
148         /*
149          * Returns a char based representation of the exclusions patterns full path.
150          */
151         public char[][] fullExclusionPatternChars() {
152
153                 if (this.fullCharExclusionPatterns == UNINIT_PATTERNS) {
154                         int length = this.exclusionPatterns.length;
155                         this.fullCharExclusionPatterns = new char[length][];
156                         IPath prefixPath = path.removeTrailingSeparator();
157                         for (int i = 0; i < length; i++) {
158                                 this.fullCharExclusionPatterns[i] = 
159                                         prefixPath.append(this.exclusionPatterns[i]).toString().toCharArray();
160                         }
161                 }
162                 return this.fullCharExclusionPatterns;
163         }
164         
165         /**
166          * Returns the XML encoding of the class path.
167          */
168         public Element elementEncode(
169                 Document document,
170                 IPath projectPath)
171                 throws JavaModelException {
172
173                 Element element = document.createElement("classpathentry"); //$NON-NLS-1$
174                 element.setAttribute("kind", kindToString(this.entryKind));     //$NON-NLS-1$
175                 IPath xmlPath = this.path;
176                 if (this.entryKind != IClasspathEntry.CPE_VARIABLE && this.entryKind != IClasspathEntry.CPE_CONTAINER) {
177                         // translate to project relative from absolute (unless a device path)
178                         if (xmlPath.isAbsolute()) {
179                                 if (projectPath != null && projectPath.isPrefixOf(xmlPath)) {
180                                         if (xmlPath.segment(0).equals(projectPath.segment(0))) {
181                                                 xmlPath = xmlPath.removeFirstSegments(1);
182                                                 xmlPath = xmlPath.makeRelative();
183                                         } else {
184                                                 xmlPath = xmlPath.makeAbsolute();
185                                         }
186                                 }
187                         }
188                 }
189                 element.setAttribute("path", xmlPath.toString()); //$NON-NLS-1$
190                 if (this.sourceAttachmentPath != null) {
191                         element.setAttribute("sourcepath", this.sourceAttachmentPath.toString()); //$NON-NLS-1$
192                 }
193                 if (this.sourceAttachmentRootPath != null) {
194                         element.setAttribute("rootpath", this.sourceAttachmentRootPath.toString()); //$NON-NLS-1$
195                 }
196                 if (this.isExported) {
197                         element.setAttribute("exported", "true"); //$NON-NLS-1$ //$NON-NLS-2$
198                 }
199                 
200                 if (this.exclusionPatterns.length > 0) {
201                         StringBuffer excludeRule = new StringBuffer(10);
202                         for (int i = 0, max = this.exclusionPatterns.length; i < max; i++){
203                                 if (i > 0) excludeRule.append('|');
204                                 excludeRule.append(this.exclusionPatterns[i]);
205                         }
206                         element.setAttribute("excluding", excludeRule.toString());  //$NON-NLS-1$
207                 }
208                 
209                 if (this.specificOutputLocation != null) {
210                         IPath outputLocation = this.specificOutputLocation.removeFirstSegments(1);
211                         outputLocation = outputLocation.makeRelative();
212                         element.setAttribute("output", outputLocation.toString()); //$NON-NLS-1$ 
213                 }
214                 return element;
215         }
216         
217         public static IClasspathEntry elementDecode(Element element, IJavaProject project) {
218         
219                 IPath projectPath = project.getProject().getFullPath();
220                 String kindAttr = element.getAttribute("kind"); //$NON-NLS-1$
221                 String pathAttr = element.getAttribute("path"); //$NON-NLS-1$
222
223                 // ensure path is absolute
224                 IPath path = new Path(pathAttr);                
225                 int kind = kindFromString(kindAttr);
226                 if (kind != IClasspathEntry.CPE_VARIABLE && kind != IClasspathEntry.CPE_CONTAINER && !path.isAbsolute()) {
227                         path = projectPath.append(path);
228                 }
229                 // source attachment info (optional)
230                 IPath sourceAttachmentPath = 
231                         element.hasAttribute("sourcepath")      //$NON-NLS-1$
232                         ? new Path(element.getAttribute("sourcepath")) //$NON-NLS-1$
233                         : null;
234                 IPath sourceAttachmentRootPath = 
235                         element.hasAttribute("rootpath") //$NON-NLS-1$
236                         ? new Path(element.getAttribute("rootpath")) //$NON-NLS-1$
237                         : null;
238                 
239                 // exported flag (optional)
240                 boolean isExported = element.getAttribute("exported").equals("true"); //$NON-NLS-1$ //$NON-NLS-2$
241
242                 // exclusion patterns (optional)
243                 String exclusion = element.getAttribute("excluding"); //$NON-NLS-1$ 
244                 IPath[] exclusionPatterns = ClasspathEntry.NO_EXCLUSION_PATTERNS;
245                 if (!exclusion.equals("")) { //$NON-NLS-1$ 
246                         char[][] patterns = CharOperation.splitOn('|', exclusion.toCharArray());
247                         int patternCount;
248                         if ((patternCount  = patterns.length) > 0) {
249                                 exclusionPatterns = new IPath[patternCount];
250                                 for (int j = 0; j < patterns.length; j++){
251                                         exclusionPatterns[j] = new Path(new String(patterns[j]));
252                                 }
253                         }
254                 }
255
256                 // custom output location
257                 IPath outputLocation = element.hasAttribute("output") ? projectPath.append(element.getAttribute("output")) : null; //$NON-NLS-1$ //$NON-NLS-2$
258                 
259                 // recreate the CP entry
260                 switch (kind) {
261
262                         case IClasspathEntry.CPE_PROJECT :
263                                 return JavaCore.newProjectEntry(path, isExported);
264                                 
265 //                      case IClasspathEntry.CPE_LIBRARY :
266 //                              return JavaCore.newLibraryEntry(
267 //                                                                                              path,
268 //                                                                                              sourceAttachmentPath,
269 //                                                                                              sourceAttachmentRootPath,
270 //                                                                                              isExported);
271                                 
272                         case IClasspathEntry.CPE_SOURCE :
273                                 // must be an entry in this project or specify another project
274                                 String projSegment = path.segment(0);
275                                 if (projSegment != null && projSegment.equals(project.getElementName())) { // this project
276                                         return JavaCore.newSourceEntry(path, exclusionPatterns, outputLocation);
277                                 } else { // another project
278                                         return JavaCore.newProjectEntry(path, isExported);
279                                 }
280
281 //                      case IClasspathEntry.CPE_VARIABLE :
282 //                              return PHPCore.newVariableEntry(
283 //                                              path,
284 //                                              sourceAttachmentPath,
285 //                                              sourceAttachmentRootPath, 
286 //                                              isExported);
287                                 
288                         case IClasspathEntry.CPE_CONTAINER :
289                                 return JavaCore.newContainerEntry(
290                                                 path,
291                                                 isExported);
292
293                         case ClasspathEntry.K_OUTPUT :
294                                 if (!path.isAbsolute()) return null;
295                                 return new ClasspathEntry(
296                                                 ClasspathEntry.K_OUTPUT,
297                                                 IClasspathEntry.CPE_LIBRARY,
298                                                 path,
299                                                 ClasspathEntry.NO_EXCLUSION_PATTERNS, 
300                                                 null, // source attachment
301                                                 null, // source attachment root
302                                                 null, // custom output location
303                                                 false);
304                         default :
305                                 throw new Assert.AssertionFailedException(Util.bind("classpath.unknownKind", kindAttr)); //$NON-NLS-1$
306                 }
307         }
308
309         /**
310          * Returns true if the given object is a classpath entry
311          * with equivalent attributes.
312          */
313         public boolean equals(Object object) {
314                 if (this == object)
315                         return true;
316                 if (object instanceof IClasspathEntry) {
317                         IClasspathEntry otherEntry = (IClasspathEntry) object;
318
319                         if (this.contentKind != otherEntry.getContentKind())
320                                 return false;
321
322                         if (this.entryKind != otherEntry.getEntryKind())
323                                 return false;
324
325                         if (this.isExported != otherEntry.isExported())
326                                 return false;
327
328                         if (!this.path.equals(otherEntry.getPath()))
329                                 return false;
330
331                         IPath otherPath = otherEntry.getSourceAttachmentPath();
332                         if (this.sourceAttachmentPath == null) {
333                                 if (otherPath != null)
334                                         return false;
335                         } else {
336                                 if (!this.sourceAttachmentPath.equals(otherPath))
337                                         return false;
338                         }
339
340                         otherPath = otherEntry.getSourceAttachmentRootPath();
341                         if (this.sourceAttachmentRootPath == null) {
342                                 if (otherPath != null)
343                                         return false;
344                         } else {
345                                 if (!this.sourceAttachmentRootPath.equals(otherPath))
346                                         return false;
347                         }
348
349                         IPath[] otherExcludes = otherEntry.getExclusionPatterns();
350                         if (this.exclusionPatterns != otherExcludes){
351                                 int excludeLength = this.exclusionPatterns.length;
352                                 if (otherExcludes.length != excludeLength) 
353                                         return false;
354                                 for (int i = 0; i < excludeLength; i++) {
355                                         // compare toStrings instead of IPaths 
356                                         // since IPath.equals is specified to ignore trailing separators
357                                         if (!this.exclusionPatterns[i].toString().equals(otherExcludes[i].toString()))
358                                                 return false;
359                                 }
360                         }
361                         
362                         otherPath = otherEntry.getOutputLocation();
363                         if (this.specificOutputLocation == null) {
364                                 if (otherPath != null)
365                                         return false;
366                         } else {
367                                 if (!this.specificOutputLocation.equals(otherPath))
368                                         return false;
369                         }
370                         return true;
371                 } else {
372                         return false;
373                 }
374         }
375
376         /**
377          * @see IClasspathEntry
378          */
379         public int getContentKind() {
380                 return this.contentKind;
381         }
382
383         /**
384          * @see IClasspathEntry
385          */
386         public int getEntryKind() {
387                 return this.entryKind;
388         }
389
390         /**
391          * @see IClasspathEntry#getExclusionPatterns()
392          */
393         public IPath[] getExclusionPatterns() {
394                 return this.exclusionPatterns;
395         }
396
397         /**
398          * @see IClasspathEntry#getOutputLocation()
399          */
400         public IPath getOutputLocation() {
401                 return this.specificOutputLocation;
402         }
403
404         /**
405          * @see IClasspathEntry
406          */
407         public IPath getPath() {
408                 return this.path;
409         }
410
411         /**
412          * @see IClasspathEntry
413          */
414         public IPath getSourceAttachmentPath() {
415                 return this.sourceAttachmentPath;
416         }
417
418         /**
419          * @see IClasspathEntry
420          */
421         public IPath getSourceAttachmentRootPath() {
422                 return this.sourceAttachmentRootPath;
423         }
424
425         /**
426          * Returns the hash code for this classpath entry
427          */
428         public int hashCode() {
429                 return this.path.hashCode();
430         }
431
432         /**
433          * @see IClasspathEntry#isExported()
434          */
435         public boolean isExported() {
436                 return this.isExported;
437         }
438
439         /**
440          * Returns the kind of a <code>PackageFragmentRoot</code> from its <code>String</code> form.
441          */
442         static int kindFromString(String kindStr) {
443
444                 if (kindStr.equalsIgnoreCase("prj")) //$NON-NLS-1$
445                         return IClasspathEntry.CPE_PROJECT;
446                 if (kindStr.equalsIgnoreCase("var")) //$NON-NLS-1$
447                         return IClasspathEntry.CPE_VARIABLE;
448                 if (kindStr.equalsIgnoreCase("con")) //$NON-NLS-1$
449                         return IClasspathEntry.CPE_CONTAINER;
450                 if (kindStr.equalsIgnoreCase("src")) //$NON-NLS-1$
451                         return IClasspathEntry.CPE_SOURCE;
452                 if (kindStr.equalsIgnoreCase("lib")) //$NON-NLS-1$
453                         return IClasspathEntry.CPE_LIBRARY;
454                 if (kindStr.equalsIgnoreCase("output")) //$NON-NLS-1$
455                         return ClasspathEntry.K_OUTPUT;
456                 return -1;
457         }
458
459         /**
460          * Returns a <code>String</code> for the kind of a class path entry.
461          */
462         static String kindToString(int kind) {
463
464                 switch (kind) {
465                         case IClasspathEntry.CPE_PROJECT :
466                                 return "src"; // backward compatibility //$NON-NLS-1$
467                         case IClasspathEntry.CPE_SOURCE :
468                                 return "src"; //$NON-NLS-1$
469                         case IClasspathEntry.CPE_LIBRARY :
470                                 return "lib"; //$NON-NLS-1$
471                         case IClasspathEntry.CPE_VARIABLE :
472                                 return "var"; //$NON-NLS-1$
473                         case IClasspathEntry.CPE_CONTAINER :
474                                 return "con"; //$NON-NLS-1$
475                         case ClasspathEntry.K_OUTPUT :
476                                 return "output"; //$NON-NLS-1$
477                         default :
478                                 return "unknown"; //$NON-NLS-1$
479                 }
480         }
481
482         /**
483          * Returns a printable representation of this classpath entry.
484          */
485         public String toString() {
486                 StringBuffer buffer = new StringBuffer();
487                 buffer.append(getPath().toString());
488                 buffer.append('[');
489                 switch (getEntryKind()) {
490                         case IClasspathEntry.CPE_LIBRARY :
491                                 buffer.append("CPE_LIBRARY"); //$NON-NLS-1$
492                                 break;
493                         case IClasspathEntry.CPE_PROJECT :
494                                 buffer.append("CPE_PROJECT"); //$NON-NLS-1$
495                                 break;
496                         case IClasspathEntry.CPE_SOURCE :
497                                 buffer.append("CPE_SOURCE"); //$NON-NLS-1$
498                                 break;
499                         case IClasspathEntry.CPE_VARIABLE :
500                                 buffer.append("CPE_VARIABLE"); //$NON-NLS-1$
501                                 break;
502                         case IClasspathEntry.CPE_CONTAINER :
503                                 buffer.append("CPE_CONTAINER"); //$NON-NLS-1$
504                                 break;
505                 }
506                 buffer.append("]["); //$NON-NLS-1$
507                 switch (getContentKind()) {
508                         case IPackageFragmentRoot.K_BINARY :
509                                 buffer.append("K_BINARY"); //$NON-NLS-1$
510                                 break;
511                         case IPackageFragmentRoot.K_SOURCE :
512                                 buffer.append("K_SOURCE"); //$NON-NLS-1$
513                                 break;
514                         case ClasspathEntry.K_OUTPUT :
515                                 buffer.append("K_OUTPUT"); //$NON-NLS-1$
516                                 break;
517                 }
518                 buffer.append(']');
519                 if (getSourceAttachmentPath() != null) {
520                         buffer.append("[sourcePath:"); //$NON-NLS-1$
521                         buffer.append(getSourceAttachmentPath());
522                         buffer.append(']');
523                 }
524                 if (getSourceAttachmentRootPath() != null) {
525                         buffer.append("[rootPath:"); //$NON-NLS-1$
526                         buffer.append(getSourceAttachmentRootPath());
527                         buffer.append(']');
528                 }
529                 buffer.append("[isExported:"); //$NON-NLS-1$
530                 buffer.append(this.isExported);
531                 buffer.append(']');
532                 IPath[] patterns = getExclusionPatterns();
533                 int length;
534                 if ((length = patterns.length) > 0) {
535                         buffer.append("[excluding:"); //$NON-NLS-1$
536                         for (int i = 0; i < length; i++) {
537                                 buffer.append(patterns[i]);
538                                 if (i != length-1) {
539                                         buffer.append('|');
540                                 }
541                         }
542                         buffer.append(']');
543                 }
544                 if (getOutputLocation() != null) {
545                         buffer.append("[output:"); //$NON-NLS-1$
546                         buffer.append(getOutputLocation());
547                         buffer.append(']');
548                 }
549                 return buffer.toString();
550         }
551         
552         /**
553          * Answers an ID which is used to distinguish entries during package
554          * fragment root computations
555          */
556         public String rootID(){
557
558                 if (this.rootID == null) {
559                         switch(this.entryKind){
560                                 case IClasspathEntry.CPE_LIBRARY :
561                                         this.rootID = "[LIB]"+this.path;  //$NON-NLS-1$
562                                         break;
563                                 case IClasspathEntry.CPE_PROJECT :
564                                         this.rootID = "[PRJ]"+this.path;  //$NON-NLS-1$
565                                         break;
566                                 case IClasspathEntry.CPE_SOURCE :
567                                         this.rootID = "[SRC]"+this.path;  //$NON-NLS-1$
568                                         break;
569                                 case IClasspathEntry.CPE_VARIABLE :
570                                         this.rootID = "[VAR]"+this.path;  //$NON-NLS-1$
571                                         break;
572                                 case IClasspathEntry.CPE_CONTAINER :
573                                         this.rootID = "[CON]"+this.path;  //$NON-NLS-1$
574                                         break;
575                                 default :
576                                         this.rootID = "";  //$NON-NLS-1$
577                                         break;
578                         }
579                 }
580                 return this.rootID;
581         }
582         
583         /**
584          * @see IClasspathEntry
585          * @deprecated
586          */
587         public IClasspathEntry getResolvedEntry() {
588         
589                 return JavaCore.getResolvedClasspathEntry(this);
590         }
591         /**
592          * Returns the XML encoding of the class path.
593          */
594         public void elementEncode(XMLWriter writer, IPath projectPath, boolean indent, boolean newLine) {
595                 HashMap parameters = new HashMap();
596                 
597                 parameters.put("kind", ClasspathEntry.kindToString(this.entryKind));//$NON-NLS-1$
598                 
599                 IPath xmlPath = this.path;
600                 if (this.entryKind != IClasspathEntry.CPE_VARIABLE && this.entryKind != IClasspathEntry.CPE_CONTAINER) {
601                         // translate to project relative from absolute (unless a device path)
602                         if (xmlPath.isAbsolute()) {
603                                 if (projectPath != null && projectPath.isPrefixOf(xmlPath)) {
604                                         if (xmlPath.segment(0).equals(projectPath.segment(0))) {
605                                                 xmlPath = xmlPath.removeFirstSegments(1);
606                                                 xmlPath = xmlPath.makeRelative();
607                                         } else {
608                                                 xmlPath = xmlPath.makeAbsolute();
609                                         }
610                                 }
611                         }
612                 }
613                 parameters.put("path", String.valueOf(xmlPath));//$NON-NLS-1$
614                 
615                 if (this.sourceAttachmentPath != null) {
616                         xmlPath = this.sourceAttachmentPath;
617                         // translate to project relative from absolute 
618                         if (this.entryKind != IClasspathEntry.CPE_VARIABLE && projectPath != null && projectPath.isPrefixOf(xmlPath)) {
619                                 if (xmlPath.segment(0).equals(projectPath.segment(0))) {
620                                         xmlPath = xmlPath.removeFirstSegments(1);
621                                         xmlPath = xmlPath.makeRelative();
622                                 }
623                         }
624                         parameters.put("sourcepath", String.valueOf(xmlPath));//$NON-NLS-1$
625                 }
626                 if (this.sourceAttachmentRootPath != null) {
627                         parameters.put("rootpath", String.valueOf(this.sourceAttachmentRootPath));//$NON-NLS-1$
628                 }
629                 if (this.isExported) {
630                         parameters.put("exported", "true");//$NON-NLS-1$//$NON-NLS-2$
631                 }
632 //              if (this.inclusionPatterns != null && this.inclusionPatterns.length > 0) {
633 //                      StringBuffer includeRule = new StringBuffer(10);
634 //                      for (int i = 0, max = this.inclusionPatterns.length; i < max; i++){
635 //                              if (i > 0) includeRule.append('|');
636 //                              includeRule.append(this.inclusionPatterns[i]);
637 //                      }
638 //                      parameters.put("including", String.valueOf(includeRule));//$NON-NLS-1$
639 //              }
640                 if (this.exclusionPatterns != null && this.exclusionPatterns.length > 0) {
641                         StringBuffer excludeRule = new StringBuffer(10);
642                         for (int i = 0, max = this.exclusionPatterns.length; i < max; i++){
643                                 if (i > 0) excludeRule.append('|');
644                                 excludeRule.append(this.exclusionPatterns[i]);
645                         }
646                         parameters.put("excluding", String.valueOf(excludeRule));//$NON-NLS-1$
647                 }
648                 
649                 if (this.specificOutputLocation != null) {
650                         IPath outputLocation = this.specificOutputLocation.removeFirstSegments(1);
651                         outputLocation = outputLocation.makeRelative();
652                         parameters.put("output", String.valueOf(outputLocation));//$NON-NLS-1$
653                 }
654
655                 writer.printTag("classpathentry", parameters, indent, newLine, true);//$NON-NLS-1$
656         }
657 }