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