Source Code Cross Referenced for GlobCmd.java in  » Scripting » jacl » tcl » lang » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Scripting » jacl » tcl.lang 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * GlobCmd.java
003:         *
004:         *	This file contains the Jacl implementation of the built-in Tcl "glob"
005:         *	command.
006:         *
007:         * Copyright (c) 1997-1998 Sun Microsystems, Inc.
008:         *
009:         * See the file "license.terms" for information on usage and
010:         * redistribution of this file, and for a DISCLAIMER OF ALL
011:         * WARRANTIES.
012:         * 
013:         * RCS: @(#) $Id: GlobCmd.java,v 1.6 2006/02/08 23:53:47 mdejong Exp $
014:         *
015:         */
016:
017:        package tcl.lang;
018:
019:        import java.util.*;
020:        import java.io.File;
021:        import java.lang.reflect.Array;
022:
023:        /*
024:         * This class implements the built-in "glob" command in Tcl.
025:         */
026:
027:        class GlobCmd implements  Command {
028:
029:            /*
030:             * Special characters that are used for string matching. 
031:             */
032:
033:            private static final char[] specCharArr = { '*', '[', ']', '?',
034:                    '\\' };
035:
036:            /*
037:             * Options to the glob command.
038:             */
039:
040:            static final private String validOptions[] = { "-nocomplain", "--" };
041:            static final private int OPT_NOCOMPLAIN = 0;
042:            static final private int OPT_LAST = 1;
043:
044:            /*
045:             *-----------------------------------------------------------------------------
046:             *
047:             * cmdProc --
048:             *
049:             *	This procedure is invoked to process the "glob" Tcl command.
050:             *	See the user documentation for details on what it does.
051:             *
052:             * Results:
053:             *	None.
054:             *
055:             * Side effects:
056:             *	See the user documentation.
057:             *
058:             *-----------------------------------------------------------------------------
059:             */
060:
061:            public void cmdProc(Interp interp, // Current interp to eval the file cmd.
062:                    TclObject argv[]) // Args passed to the glob command.
063:                    throws TclException {
064:                boolean noComplain = false; // If false, error msg will be returned 
065:                int index; // index of the char just after the end 
066:                //   of the user name 
067:                int firstArg = 1; // index of the first non-switch arg 
068:                int i; // generic index 
069:                String arg; // generic arg string 
070:                String head = ""; // abs path of user name if provided 
071:                String tail = ""; // the remaining file path and pattern 
072:                TclObject resultList; // list of files that match the pattern
073:
074:                for (boolean last = false; (firstArg < argv.length) && (!last); firstArg++) {
075:
076:                    if (!argv[firstArg].toString().startsWith("-")) {
077:                        break;
078:                    }
079:                    int opt = TclIndex.get(interp, argv[firstArg],
080:                            validOptions, "switch", 1);
081:                    switch (opt) {
082:                    case OPT_NOCOMPLAIN:
083:                        noComplain = true;
084:                        break;
085:                    case OPT_LAST:
086:                        last = true;
087:                        break;
088:                    default:
089:                        throw new TclException(interp,
090:                                "GlobCmd.cmdProc: bad option " + opt
091:                                        + " index to validOptions");
092:                    }
093:                }
094:
095:                if (firstArg >= argv.length) {
096:                    throw new TclNumArgsException(interp, 1, argv,
097:                            "?switches? name ?name ...?");
098:                }
099:
100:                resultList = TclList.newInstance();
101:                resultList.preserve();
102:
103:                for (i = firstArg; i < argv.length; i++) {
104:                    arg = argv[i].toString();
105:
106:                    String separators; // The system-specific file separators
107:                    switch (JACL.PLATFORM) {
108:                    case JACL.PLATFORM_WINDOWS:
109:                        separators = "/\\:";
110:                        break;
111:                    case JACL.PLATFORM_MAC:
112:                        if (arg.indexOf(':') == -1) {
113:                            separators = "/";
114:                        } else {
115:                            separators = ":";
116:                        }
117:                        break;
118:                    default:
119:                        separators = "/";
120:                    }
121:
122:                    // Perform tilde substitution, if needed.
123:
124:                    index = 0;
125:                    if (arg.startsWith("~")) {
126:                        // Find the first path separator after the tilde.
127:
128:                        for (; index < arg.length(); index++) {
129:                            char c = arg.charAt(index);
130:                            if (c == '\\') {
131:                                if (separators.indexOf(arg.charAt(index + 1)) != -1) {
132:                                    break;
133:                                }
134:                            } else if (separators.indexOf(c) != -1) {
135:                                break;
136:                            }
137:                        }
138:
139:                        // Determine the home directory for the specified user.  Note 
140:                        // that we don't allow special characters in the user name.
141:
142:                        if (strpbrk(arg.substring(1, index).toCharArray(),
143:                                specCharArr) < 0) {
144:                            try {
145:                                head = FileUtil.doTildeSubst(interp, arg
146:                                        .substring(1, index));
147:                            } catch (TclException e) {
148:                                if (noComplain) {
149:                                    head = null;
150:                                } else {
151:                                    throw new TclException(interp, e
152:                                            .getMessage());
153:                                }
154:                            }
155:                        } else {
156:                            if (!noComplain) {
157:                                throw new TclException(interp,
158:                                        "globbing characters not supported in user names");
159:                            }
160:                            head = null;
161:                        }
162:
163:                        if (head == null) {
164:                            if (noComplain) {
165:                                interp.setResult("");
166:                                return;
167:                            } else {
168:                                return;
169:                            }
170:                        }
171:                        if (index != arg.length()) {
172:                            index++;
173:                        }
174:                    }
175:
176:                    tail = arg.substring(index);
177:
178:                    try {
179:                        doGlob(interp, separators, new StringBuffer(head),
180:                                tail, resultList);
181:                    } catch (TclException e) {
182:                        if (noComplain) {
183:                            continue;
184:                        } else {
185:                            throw new TclException(interp, e.getMessage());
186:                        }
187:                    }
188:                }
189:
190:                // If the list is empty and the nocomplain switch was not set then
191:                // generate and throw an exception.  Always release the TclList upon
192:                // completion.
193:
194:                try {
195:                    if ((TclList.getLength(interp, resultList) == 0)
196:                            && !noComplain) {
197:                        String sep = "";
198:                        StringBuffer ret = new StringBuffer();
199:
200:                        ret.append("no files matched glob pattern");
201:                        ret.append((argv.length == 2) ? " \"" : "s \"");
202:
203:                        for (i = firstArg; i < argv.length; i++) {
204:                            ret.append(sep + argv[i].toString());
205:                            if (i == firstArg) {
206:                                sep = " ";
207:                            }
208:                        }
209:                        ret.append("\"");
210:                        throw new TclException(interp, ret.toString());
211:                    } else if (TclList.getLength(interp, resultList) > 0) {
212:                        interp.setResult(resultList);
213:                    }
214:                } finally {
215:                    resultList.release();
216:                }
217:            }
218:
219:            /*
220:             *-----------------------------------------------------------------------------
221:             *
222:             * SkipToChar --
223:             *
224:             *	This function traverses a glob pattern looking for the next
225:             *	unquoted occurance of the specified character at the same braces
226:             *	nesting level.
227:             *
228:             * Results:
229:             *	Returns -1 if no match is made.  Otherwise returns the index in str in
230:             *	which the match is found.
231:             *
232:             * Side effects:
233:             *	None.
234:             *
235:             *-----------------------------------------------------------------------------
236:             */
237:
238:            private static int SkipToChar(String str, // Strubg to check.
239:                    int sIndex, // Index in str to begin search.
240:                    char match) // Ccharacter to find.
241:            {
242:                int level, length, i;
243:                boolean quoted = false;
244:                char c;
245:
246:                level = 0;
247:
248:                for (i = sIndex, length = str.length(); i < length; i++) {
249:                    if (quoted) {
250:                        quoted = false;
251:                        continue;
252:                    }
253:                    c = str.charAt(i);
254:                    if ((level == 0) && (c == match)) {
255:                        return i;
256:                    }
257:                    if (c == '{') {
258:                        level++;
259:                    } else if (c == '}') {
260:                        level--;
261:                    } else if (c == '\\') {
262:                        quoted = true;
263:                    }
264:                }
265:                return -1;
266:            }
267:
268:            /*
269:             *-----------------------------------------------------------------------------
270:             *
271:             * TclDoGlob --
272:             *
273:             *	This recursive procedure forms the heart of the globbing
274:             *	code.  It performs a depth-first traversal of the tree
275:             *	given by the path name to be globbed.  The directory and
276:             *	remainder are assumed to be native format paths.
277:             *
278:             * Results:
279:             *	None.
280:             *
281:             * Side effects:
282:             *	None.
283:             *
284:             *-----------------------------------------------------------------------------
285:             */
286:
287:            private static final void doGlob(Interp interp, // Interpreter to use for error reporting
288:                    String separators, // String containing separator characters
289:                    StringBuffer headBuf, // Completely expanded prefix.
290:                    String tail, // The unexpanded remainder of the path.
291:                    TclObject resultList) // list of files that match the pattern
292:                    throws TclException {
293:                int count = 0; // Counts the number of leading file 
294:                //   spearators for the tail. 
295:                int pIndex; // Current index into tail 
296:                int tailIndex; // First char after initial file 
297:                //   separators of the tail 
298:                int tailLen = tail.length(); // Cache the length of the tail 
299:                int headLen = headBuf.length(); // Cache the length of the head 
300:                int baseLen; // Len of the substring from tailIndex
301:                //   to the current specChar []*?{}\\ 
302:                int openBraceIndex; // Index of the current open brace 
303:                int closeBraceIndex; // Index of the current closed brace 
304:                int firstSpecCharIndex; // Index of the FSC, if any 
305:                char lastChar = 0; // Used to see if last char is a file
306:                //   separator. 
307:                char ch; // Generic storage variable 
308:                boolean quoted; // True if a char is '\\' 
309:
310:                if (headLen > 0) {
311:                    lastChar = headBuf.charAt(headLen - 1);
312:                }
313:
314:                // Consume any leading directory separators, leaving tailIndex
315:                // just past the last initial separator.
316:
317:                String name = tail;
318:                for (tailIndex = 0; tailIndex < tailLen; tailIndex++) {
319:                    char c = tail.charAt(tailIndex);
320:                    if ((c == '\\')
321:                            && ((tailIndex + 1) < tailLen)
322:                            && (separators.indexOf(tail.charAt(tailIndex + 1)) != -1)) {
323:                        tailIndex++;
324:                    } else if (separators.indexOf(c) == -1) {
325:                        break;
326:                    }
327:                    count++;
328:                }
329:
330:                // Deal with path separators.  On the Mac, we have to watch out
331:                // for multiple separators, since they are special in Mac-style
332:                // paths.
333:
334:                switch (JACL.PLATFORM) {
335:                case JACL.PLATFORM_MAC:
336:
337:                    if (separators.charAt(0) == '/') {
338:                        if (((headLen == 0) && (count == 0))
339:                                || ((headLen > 0) && (lastChar != ':'))) {
340:                            headBuf.append(":");
341:                        }
342:                    } else {
343:                        if (count == 0) {
344:                            if ((headLen > 0) && (lastChar != ':')) {
345:                                headBuf.append(":");
346:                            }
347:                        } else {
348:                            if (lastChar == ':') {
349:                                count--;
350:                            }
351:                            while (count-- > 0) {
352:                                headBuf.append(":");
353:                            }
354:                        }
355:                    }
356:                    break;
357:
358:                case JACL.PLATFORM_WINDOWS:
359:                    // If this is a drive relative path, add the colon and the
360:                    // trailing slash if needed.  Otherwise add the slash if
361:                    // this is the first absolute element, or a later relative
362:                    // element.  Add an extra slash if this is a UNC path.
363:                    if (name.startsWith(":")) {
364:                        headBuf.append(":");
365:                        if (count > 1) {
366:                            headBuf.append("/");
367:                        }
368:                    } else if ((tailIndex < tailLen)
369:                            && (((headLen > 0) && (separators.indexOf(lastChar) == -1)) || ((headLen == 0) && (count > 0)))) {
370:                        headBuf.append("/");
371:                        if ((headLen == 0) && (count > 1)) {
372:                            headBuf.append("/");
373:                        }
374:                    }
375:                    break;
376:                default:
377:                    // Add a separator if this is the first absolute element, or
378:                    // a later relative element.
379:
380:                    if ((tailIndex < tailLen)
381:                            && (((headLen > 0) && (separators.indexOf(lastChar) == -1)) || ((headLen == 0) && (count > 0)))) {
382:                        headBuf.append("/");
383:                    }
384:                }
385:
386:                // Look for the first matching pair of braces or the first
387:                // directory separator that is not inside a pair of braces.
388:
389:                openBraceIndex = closeBraceIndex = -1;
390:                quoted = false;
391:
392:                for (pIndex = tailIndex; pIndex != tailLen; pIndex++) {
393:                    ch = tail.charAt(pIndex);
394:                    if (quoted) {
395:                        quoted = false;
396:                    } else if (ch == '\\') {
397:                        quoted = true;
398:                        if (((pIndex + 1) < tailLen)
399:                                && (separators.indexOf(tail.charAt(pIndex + 1)) != -1)) {
400:                            // Quoted directory separator. 
401:
402:                            break;
403:                        }
404:                    } else if (separators.indexOf(ch) != -1) {
405:                        // Unquoted directory separator. 
406:
407:                        break;
408:                    } else if (ch == '{') {
409:                        openBraceIndex = pIndex;
410:                        pIndex++;
411:                        if ((closeBraceIndex = SkipToChar(tail, pIndex, '}')) != -1) {
412:                            break;
413:                        }
414:                        throw new TclException(interp,
415:                                "unmatched open-brace in file name");
416:                    } else if (ch == '}') {
417:                        throw new TclException(interp,
418:                                "unmatched close-brace in file name");
419:                    }
420:                }
421:
422:                // Substitute the alternate patterns from the braces and recurse.
423:
424:                if (openBraceIndex != -1) {
425:                    int nextIndex;
426:                    StringBuffer baseBuf = new StringBuffer();
427:
428:                    // For each element within in the outermost pair of braces,
429:                    // append the element and the remainder to the fixed portion
430:                    // before the first brace and recursively call doGlob.
431:
432:                    baseBuf.append(tail.substring(tailIndex, openBraceIndex));
433:                    baseLen = baseBuf.length();
434:                    headLen = headBuf.length();
435:
436:                    for (pIndex = openBraceIndex; pIndex < closeBraceIndex;) {
437:                        pIndex++;
438:                        nextIndex = SkipToChar(tail, pIndex, ',');
439:                        if (nextIndex == -1 || nextIndex > closeBraceIndex) {
440:                            nextIndex = closeBraceIndex;
441:                        }
442:
443:                        headBuf.setLength(headLen);
444:                        baseBuf.setLength(baseLen);
445:
446:                        baseBuf.append(tail.substring(pIndex, nextIndex));
447:                        baseBuf.append(tail.substring(closeBraceIndex + 1));
448:
449:                        pIndex = nextIndex;
450:                        doGlob(interp, separators, headBuf, baseBuf.toString(),
451:                                resultList);
452:                    }
453:                    return;
454:                }
455:
456:                // At this point, there are no more brace substitutions to perform on
457:                // this path component.  The variable p is pointing at a quoted or
458:                // unquoted directory separator or the end of the string.  So we need
459:                // to check for special globbing characters in the current pattern.
460:                // We avoid modifying tail if p is pointing at the end of the string.
461:
462:                if (pIndex < tailLen) {
463:                    firstSpecCharIndex = strpbrk(tail.substring(0, pIndex)
464:                            .toCharArray(), specCharArr);
465:                } else {
466:                    firstSpecCharIndex = strpbrk(tail.substring(tailIndex)
467:                            .toCharArray(), specCharArr);
468:                }
469:
470:                if (firstSpecCharIndex != -1) {
471:                    // Look for matching files in the current directory.  matchFiles
472:                    // may recursively call TclDoGlob.  For each file that matches,
473:                    // it will add the match onto the interp->result, or call TclDoGlob
474:                    // if there are more characters to be processed.
475:
476:                    matchFiles(interp, separators, headBuf.toString(), tail
477:                            .substring(tailIndex), (pIndex - tailIndex),
478:                            resultList);
479:                    return;
480:                }
481:                headBuf.append(tail.substring(tailIndex, pIndex));
482:                if (pIndex < tailLen) {
483:                    doGlob(interp, separators, headBuf, tail.substring(pIndex),
484:                            resultList);
485:                    return;
486:                }
487:
488:                // There are no more wildcards in the pattern and no more unprocessed
489:                // characters in the tail, so now we can construct the path and verify
490:                // the existence of the file.
491:
492:                String head;
493:                switch (JACL.PLATFORM) {
494:                case JACL.PLATFORM_MAC:
495:                    if (headBuf.toString().indexOf(':') == -1) {
496:                        headBuf.append(":");
497:                    }
498:                    head = headBuf.toString();
499:                    break;
500:                case JACL.PLATFORM_WINDOWS:
501:                    if (headBuf.length() == 0) {
502:                        if (((name.length() > 1) && (name.charAt(0) == '\\') && ((name
503:                                .charAt(1) == '/') || (name.charAt(1) == '\\')))
504:                                || ((name.length() > 0) && (name.charAt(0) == '/'))) {
505:                            headBuf.append("\\");
506:                        } else {
507:                            headBuf.append(".");
508:                        }
509:                    }
510:                    head = headBuf.toString().replace('\\', '/');
511:                    break;
512:                default:
513:                    if (headBuf.length() == 0) {
514:                        if (name.startsWith("\\/") || name.startsWith("/")) {
515:                            headBuf.append("/");
516:                        } else {
517:                            headBuf.append(".");
518:                        }
519:                    }
520:                    head = headBuf.toString();
521:                }
522:                addFileToResult(interp, head, separators, resultList);
523:            }
524:
525:            /*
526:             *-----------------------------------------------------------------------------
527:             *
528:             * matchFiles --
529:             *
530:             *	This routine is used by the globbing code to search a
531:             *	directory for all files which match a given pattern.
532:             *	This is a routine contains platform-specific code.
533:             *
534:             * Results: 
535:             *	If the tail argument is NULL, then the matching files are
536:             *	added to the result list.  Otherwise, TclDoGlob is called
537:             *	recursively for each matching subdirectory.
538:             *
539:             * Side effects:
540:             *	None.
541:             *
542:             *-----------------------------------------------------------------------------
543:             */
544:
545:            private static final void matchFiles(Interp interp, // Interpreter to use for error reporting
546:                    String separators, // String containing separator characters
547:                    String dirName, // Path of directory to search.
548:                    String pattern, // Pattern to match against.
549:                    int pIndex, // Index of end of pattern.
550:                    TclObject resultList) // list of files that match the pattern
551:                    throws TclException {
552:                boolean matchHidden; // True if were matching hidden file 
553:                int patternEnd = pIndex; // Stores end index of the pattern 
554:                int dirLen = dirName.length(); // Caches the len of the dirName 
555:                int patLen = pattern.length(); // Caches the len of the pattern 
556:                String[] dirListing; // Listing of files in dirBuf 
557:                File dirObj; // File object of dirBuf 
558:                StringBuffer dirBuf = new StringBuffer();
559:                // Converts the dirName to string 
560:                //   buffer or initializes it with '.' 
561:
562:                switch (JACL.PLATFORM) {
563:                case JACL.PLATFORM_WINDOWS:
564:                    // Convert the path to normalized form since some interfaces only
565:                    // accept backslashes.  Also, ensure that the directory ends with
566:                    // a separator character.
567:
568:                    if (dirLen == 0) {
569:                        dirBuf.append("./");
570:                    } else {
571:                        dirBuf.append(dirName);
572:                        char c = dirBuf.charAt(dirLen - 1);
573:                        if (((c == ':') && (dirLen == 2))
574:                                || (separators.indexOf(c) == -1)) {
575:                            dirBuf.append("/");
576:                        }
577:                    }
578:
579:                    // All comparisons should be case insensitive on Windows.
580:
581:                    pattern = pattern.toLowerCase();
582:                    break;
583:                case JACL.PLATFORM_MAC:
584:                    // Fall through to unix case--mac is not yet implemented.
585:
586:                default:
587:                    // Make sure that the directory part of the name really is a
588:                    // directory.  If the directory name is "", use the name "."
589:                    // instead, because some UNIX systems don't treat "" like "."
590:                    // automatically.  Keep the "" for use in generating file names,
591:                    // otherwise "glob foo.c" would return "./foo.c".
592:
593:                    if (dirLen == 0) {
594:                        dirBuf.append(".");
595:                    } else {
596:                        dirBuf.append(dirName);
597:                    }
598:                }
599:
600:                dirObj = createAbsoluteFileObj(interp, dirBuf.toString());
601:                if (!dirObj.isDirectory()) {
602:                    return;
603:                }
604:
605:                // Check to see if the pattern needs to compare with hidden files.
606:                // Get a list of the directory's contents.
607:
608:                if (pattern.startsWith(".") || pattern.startsWith("\\.")) {
609:                    matchHidden = true;
610:                    dirListing = addHiddenToDirList(dirObj);
611:                } else {
612:                    matchHidden = false;
613:                    dirListing = dirObj.list();
614:                }
615:
616:                // Iterate over the directory's contents.
617:
618:                if (dirListing.length == 0) {
619:                    // Strip off a trailing '/' if necessary, before reporting 
620:                    // the error.
621:
622:                    if (dirName.endsWith("/")) {
623:                        dirName = dirName.substring(0, (dirLen - 1));
624:                    }
625:                }
626:
627:                // Clean up the end of the pattern and the tail pointer.  Leave
628:                // the tail pointing to the first character after the path 
629:                // separator following the pattern, or NULL.  Also, ensure that
630:                // the pattern is null-terminated.
631:
632:                if ((pIndex < patLen) && (pattern.charAt(pIndex) == '\\')) {
633:                    pIndex++;
634:                }
635:                if (pIndex < (patLen - 1)) {
636:                    pIndex++;
637:                }
638:
639:                for (int i = 0; i < dirListing.length; i++) {
640:                    // Don't match names starting with "." unless the "." is
641:                    // present in the pattern.
642:
643:                    if (!matchHidden && (dirListing[i].startsWith("."))) {
644:                        continue;
645:                    }
646:
647:                    // Now check to see if the file matches.  If there are more
648:                    // characters to be processed, then ensure matching files are
649:                    // directories before calling TclDoGlob. Otherwise, just add
650:                    // the file to the resultList.
651:
652:                    String tmp = dirListing[i];
653:                    if (JACL.PLATFORM == JACL.PLATFORM_WINDOWS) {
654:                        tmp = tmp.toLowerCase();
655:                    }
656:                    if (Util.stringMatch(tmp, pattern.substring(0, patternEnd))) {
657:
658:                        dirBuf.setLength(dirLen);
659:                        dirBuf.append(dirListing[i]);
660:                        if (pIndex == pattern.length()) {
661:                            addFileToResult(interp, dirBuf.toString(),
662:                                    separators, resultList);
663:                        } else {
664:                            dirObj = createAbsoluteFileObj(interp, dirBuf
665:                                    .toString());
666:                            if (dirObj.isDirectory()) {
667:                                dirBuf.append("/");
668:                                doGlob(interp, separators, dirBuf, pattern
669:                                        .substring(patternEnd + 1), resultList);
670:                            }
671:                        }
672:                    }
673:                }
674:            }
675:
676:            /*
677:             *-----------------------------------------------------------------------------
678:             *
679:             * strpbrk --
680:             *
681:             *	Returns the index into src of the first occurrence in
682:             *	array src of any character from the array matches, or 
683:             *	a -1 if no character from matches exists in src.
684:             *
685:             * Results: 
686:             *	Returns the index of first occurence of a match or -1 if no match
687:             *	found.
688:             *
689:             * Side effects:
690:             *	None.
691:             *
692:             *-----------------------------------------------------------------------------
693:             */
694:
695:            private static final int strpbrk(char[] src, // The char array to search.
696:                    char[] matches) // The chars to search for in src.
697:            {
698:                for (int i = 0; i < src.length; i++) {
699:                    for (int j = 0; j < matches.length; j++) {
700:                        if (src[i] == matches[j]) {
701:                            return (i);
702:                        }
703:                    }
704:                }
705:                return -1;
706:            }
707:
708:            /*
709:             *-----------------------------------------------------------------------------
710:             *
711:             * addHiddenToDirList --
712:             *
713:             *	The method dirObj.list() returns a list of files in the directory.
714:             *	This method adds the files "." and ".." to create a full list.
715:             *
716:             * Results: 
717:             *	Retruns the full list of files in the directory dirObj.
718:             *
719:             * Side effects:
720:             *	None.
721:             *
722:             *-----------------------------------------------------------------------------
723:             */
724:
725:            private static final String[] addHiddenToDirList(File dirObj) // File object to list contents of
726:            {
727:                String[] dirListing; // Listing of files in dirObj
728:                String[] fullListing; // dirListing + .. and .
729:                int i, arrayLen;
730:
731:                dirListing = dirObj.list();
732:                arrayLen = Array.getLength(dirListing);
733:
734:                try {
735:                    fullListing = (String[]) Array.newInstance(String.class,
736:                            arrayLen + 2);
737:                } catch (Exception e) {
738:                    return dirListing;
739:                }
740:                for (i = 0; i < arrayLen; i++) {
741:                    fullListing[i] = dirListing[i];
742:                }
743:                fullListing[arrayLen] = ".";
744:                fullListing[arrayLen + 1] = "..";
745:
746:                return fullListing;
747:            }
748:
749:            /*
750:             *-----------------------------------------------------------------------------
751:             *
752:             * addFileToResult --
753:             *
754:             *	This recursive procedure forms the heart of the globbing
755:             *	code.  It performs a depth-first traversal of the tree
756:             *	given by the path name to be globbed.  The directory and
757:             *	remainder are assumed to be native format paths.
758:             *
759:             * Results:
760:             *	None.
761:             *
762:             * Side effects:
763:             *	Appends a string to TclObject resultList.
764:             *
765:             *-----------------------------------------------------------------------------
766:             */
767:
768:            private static void addFileToResult(Interp interp, // Interpreter to use for error reporting
769:                    String fileName, // Name of file to add to result list
770:                    String separators, // String containing separator characters
771:                    TclObject resultList) // list of files that match the pattern
772:
773:                    throws TclException {
774:                String prettyFileName = fileName;
775:                int prettyLen = fileName.length();
776:
777:                // Java IO reuqires Windows volumes [A-Za-z]: to be followed by '\\'.
778:
779:                if ((JACL.PLATFORM == JACL.PLATFORM_WINDOWS)
780:                        && (prettyLen >= 2) && (fileName.charAt(1) == ':')) {
781:                    if (prettyLen == 2) {
782:                        fileName = fileName + '\\';
783:                    } else if (fileName.charAt(2) != '\\') {
784:                        fileName = fileName.substring(0, 2) + '\\'
785:                                + fileName.substring(2);
786:                    }
787:                }
788:
789:                TclObject arrayObj[] = TclList.getElements(interp, FileUtil
790:                        .splitAndTranslate(interp, fileName));
791:                fileName = FileUtil.joinPath(interp, arrayObj, 0,
792:                        arrayObj.length);
793:
794:                File f;
795:                if (FileUtil.getPathType(fileName) == FileUtil.PATH_ABSOLUTE) {
796:                    f = FileUtil.getNewFileObj(interp, fileName);
797:                } else {
798:                    f = new File(interp.getWorkingDir(), fileName);
799:                }
800:
801:                // If the last character is a spearator, make sure the file is an
802:                // existing directory, otherwise check that the file exists.
803:
804:                if ((prettyLen > 0)
805:                        && (separators.indexOf(prettyFileName
806:                                .charAt(prettyLen - 1)) != -1)) {
807:                    if (f.isDirectory()) {
808:                        TclList.append(interp, resultList, TclString
809:                                .newInstance(prettyFileName));
810:                    }
811:                } else if (f.exists()) {
812:                    TclList.append(interp, resultList, TclString
813:                            .newInstance(prettyFileName));
814:                }
815:            }
816:
817:            /*
818:             *-----------------------------------------------------------------------------
819:             *
820:             * createAbsoluteFileObj --
821:             *
822:             *	Creates and returns a File object from the String fileName.  If
823:             *	fileName is not null, it verifies that the file path is absolute, 
824:             *	setting it if it is not.
825:             *
826:             * Results:
827:             *	Returns the fully qualified File object.
828:             *
829:             * Side effects:
830:             *	None.
831:             *
832:             *-----------------------------------------------------------------------------
833:             */
834:
835:            private static final File createAbsoluteFileObj(Interp interp, // Interpreter for error reports. 
836:                    String fileName) // Name of file.
837:                    throws TclException {
838:                if (fileName.equals("")) {
839:                    return (interp.getWorkingDir());
840:                }
841:
842:                if ((JACL.PLATFORM == JACL.PLATFORM_WINDOWS)
843:                        && (fileName.length() >= 2)
844:                        && (fileName.charAt(1) == ':')) {
845:                    String tmp = null;
846:                    if (fileName.length() == 2) {
847:                        tmp = fileName.substring(0, 2) + '\\';
848:                    } else if (fileName.charAt(2) != '\\') {
849:                        tmp = fileName.substring(0, 2) + '\\'
850:                                + fileName.substring(2);
851:                    }
852:                    if (tmp != null) {
853:                        return FileUtil.getNewFileObj(interp, tmp);
854:                    }
855:                }
856:
857:                return FileUtil.getNewFileObj(interp, fileName);
858:            }
859:
860:        } // end GlobCmd class
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.