Source Code Cross Referenced for FileCmd.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) 


0001:        /*
0002:         * FileCmd.java --
0003:         *
0004:         *	This file contains the Jacl implementation of the built-in Tcl "file"
0005:         *	command.
0006:         *
0007:         * Copyright (c) 1997 Cornell University.
0008:         * Copyright (c) 1997 Sun Microsystems, Inc.
0009:         *
0010:         * See the file "license.terms" for information on usage and
0011:         * redistribution of this file, and for a DISCLAIMER OF ALL
0012:         * WARRANTIES.
0013:         * 
0014:         * RCS: @(#) $Id: FileCmd.java,v 1.10 2005/11/07 07:41:51 mdejong Exp $
0015:         *
0016:         */
0017:
0018:        package tcl.lang;
0019:
0020:        import java.io.*;
0021:        import java.util.*;
0022:        import java.lang.reflect.Array;
0023:        import java.lang.reflect.Method;
0024:        import java.lang.reflect.InvocationTargetException;
0025:
0026:        /*
0027:         * This class implements the built-in "file" command in Tcl.
0028:         */
0029:
0030:        class FileCmd implements  Command {
0031:
0032:            /**
0033:             * Reference to File.listRoots, null when JDK < 1.2
0034:             */
0035:            private static Method listRootsMethod;
0036:
0037:            static {
0038:                // File.listRoots()
0039:                Class[] parameterTypes = new Class[0];
0040:                try {
0041:                    listRootsMethod = File.class.getMethod("listRoots",
0042:                            parameterTypes);
0043:                } catch (NoSuchMethodException e) {
0044:                    listRootsMethod = null;
0045:                }
0046:            }
0047:
0048:            static Class procClass = null;
0049:
0050:            static final private String validCmds[] = { "atime", "attributes",
0051:                    "channels", "copy", "delete", "dirname", "executable",
0052:                    "exists", "extension", "isdirectory", "isfile", "join",
0053:                    "link", "lstat", "mtime", "mkdir", "nativename",
0054:                    "normalize", "owned", "pathtype", "readable", "readlink",
0055:                    "rename", "rootname", "separator", "size", "split", "stat",
0056:                    "system", "tail", "type", "volumes", "writable" };
0057:
0058:            private static final int OPT_ATIME = 0;
0059:            private static final int OPT_ATTRIBUTES = 1;
0060:            private static final int OPT_CHANNELS = 2;
0061:            private static final int OPT_COPY = 3;
0062:            private static final int OPT_DELETE = 4;
0063:            private static final int OPT_DIRNAME = 5;
0064:            private static final int OPT_EXECUTABLE = 6;
0065:            private static final int OPT_EXISTS = 7;
0066:            private static final int OPT_EXTENSION = 8;
0067:            private static final int OPT_ISDIRECTORY = 9;
0068:            private static final int OPT_ISFILE = 10;
0069:            private static final int OPT_JOIN = 11;
0070:            private static final int OPT_LINK = 12;
0071:            private static final int OPT_LSTAT = 13;
0072:            private static final int OPT_MTIME = 14;
0073:            private static final int OPT_MKDIR = 15;
0074:            private static final int OPT_NATIVENAME = 16;
0075:            private static final int OPT_NORMALIZE = 17;
0076:            private static final int OPT_OWNED = 18;
0077:            private static final int OPT_PATHTYPE = 19;
0078:            private static final int OPT_READABLE = 20;
0079:            private static final int OPT_READLINK = 21;
0080:            private static final int OPT_RENAME = 22;
0081:            private static final int OPT_ROOTNAME = 23;
0082:            private static final int OPT_SEPARATOR = 24;
0083:            private static final int OPT_SIZE = 25;
0084:            private static final int OPT_SPLIT = 26;
0085:            private static final int OPT_STAT = 27;
0086:            private static final int OPT_SYSTEM = 28;
0087:            private static final int OPT_TAIL = 29;
0088:            private static final int OPT_TYPE = 30;
0089:            private static final int OPT_VOLUMES = 31;
0090:            private static final int OPT_WRITABLE = 32;
0091:
0092:            private static final String validOptions[] = { "-force", "--" };
0093:
0094:            private static final int OPT_FORCE = 0;
0095:            private static final int OPT_LAST = 1;
0096:
0097:            /*
0098:             *-----------------------------------------------------------------------------
0099:             *
0100:             * cmdProc --
0101:             *
0102:             *	This procedure is invoked to process the "file" Tcl command.
0103:             *	See the user documentation for details on what it does.
0104:             *
0105:             * Results:
0106:             *	None.
0107:             *
0108:             * Side effects:
0109:             *	See the user documentation.
0110:             *
0111:             *-----------------------------------------------------------------------------
0112:             */
0113:
0114:            public void cmdProc(Interp interp, // Current interp to eval the file cmd.
0115:                    TclObject argv[]) // Args passed to the file command.
0116:                    throws TclException {
0117:                if (argv.length < 2) {
0118:                    throw new TclNumArgsException(interp, 1, argv,
0119:                            "option ?arg ...?");
0120:                }
0121:
0122:                int opt = TclIndex.get(interp, argv[1], validCmds, "option", 0);
0123:                String path;
0124:                File fileObj = null;
0125:
0126:                switch (opt) {
0127:                case OPT_ATIME:
0128:                    if (argv.length != 3) {
0129:                        throw new TclNumArgsException(interp, 2, argv, "name");
0130:                    }
0131:
0132:                    // FIXME:  Currently returns the same thing as MTIME.
0133:                    // Java does not support retrieval of access time.
0134:
0135:                    fileObj = FileUtil
0136:                            .getNewFileObj(interp, argv[2].toString());
0137:                    interp.setResult(getMtime(interp, argv[2].toString(),
0138:                            fileObj));
0139:                    return;
0140:
0141:                case OPT_ATTRIBUTES:
0142:                    //FIXME:   not implemented yet
0143:
0144:                    throw new TclException(interp,
0145:                            "sorry, \"file attributes\" is not implemented yet");
0146:
0147:                    //return;
0148:                case OPT_CHANNELS:
0149:                    //FIXME:   not implemented yet
0150:
0151:                    throw new TclException(interp,
0152:                            "sorry, \"file channels\" is not implemented yet");
0153:
0154:                case OPT_COPY:
0155:                    fileCopyRename(interp, argv, true);
0156:                    return;
0157:
0158:                case OPT_DELETE:
0159:                    fileDelete(interp, argv);
0160:                    return;
0161:
0162:                case OPT_DIRNAME:
0163:                    if (argv.length != 3) {
0164:                        throw new TclNumArgsException(interp, 2, argv, "name");
0165:                    }
0166:                    path = argv[2].toString();
0167:
0168:                    // Return all but the last component.  If there is only one
0169:                    // component, return it if the path was non-relative, otherwise
0170:                    // return the current directory.
0171:
0172:                    TclObject splitArrayObj[] = TclList.getElements(interp,
0173:                            FileUtil.splitAndTranslate(interp, path));
0174:                    if (false) {
0175:                        for (int ii = 0; ii < splitArrayObj.length; ii++) {
0176:                            System.out.println("file path index " + ii
0177:                                    + " is \"" + splitArrayObj[ii] + "\"");
0178:                        }
0179:                    }
0180:
0181:                    if (splitArrayObj.length > 1) {
0182:                        interp.setResult(FileUtil.joinPath(interp,
0183:                                splitArrayObj, 0, splitArrayObj.length - 1));
0184:                    } else if ((splitArrayObj.length == 0)
0185:                            || (FileUtil.getPathType(path) == FileUtil.PATH_RELATIVE)) {
0186:                        if (JACL.PLATFORM == JACL.PLATFORM_MAC) {
0187:                            interp.setResult(":");
0188:                        } else {
0189:                            interp.setResult(".");
0190:                        }
0191:                    } else {
0192:                        interp.setResult(splitArrayObj[0].toString());
0193:                    }
0194:                    return;
0195:
0196:                case OPT_EXECUTABLE:
0197:                    if (argv.length != 3) {
0198:                        throw new TclNumArgsException(interp, 2, argv, "name");
0199:                    }
0200:                    boolean isExe = false;
0201:                    fileObj = FileUtil
0202:                            .getNewFileObj(interp, argv[2].toString());
0203:
0204:                    // A file must exist to be executable.  Directories are always
0205:                    // executable. 
0206:
0207:                    if (fileObj.exists()) {
0208:                        isExe = fileObj.isDirectory();
0209:                        if (isExe) {
0210:                            interp.setResult(isExe);
0211:                            return;
0212:                        }
0213:
0214:                        if (Util.isWindows()) {
0215:                            // File that ends with .exe, .com, or .bat is executable.
0216:
0217:                            String fileName = argv[2].toString();
0218:                            isExe = (fileName.endsWith(".exe")
0219:                                    || fileName.endsWith(".com") || fileName
0220:                                    .endsWith(".bat"));
0221:                        } else if (Util.isMac()) {
0222:                            // FIXME:  Not yet implemented on Mac.  For now, return true.
0223:                            // Java does not support executability checking.
0224:
0225:                            isExe = true;
0226:                        } else {
0227:                            // FIXME:  Not yet implemented on Unix.  For now, return true.
0228:                            // Java does not support executability checking.
0229:
0230:                            isExe = true;
0231:                        }
0232:                    }
0233:                    interp.setResult(isExe);
0234:                    return;
0235:
0236:                case OPT_EXISTS:
0237:                    if (argv.length != 3) {
0238:                        throw new TclNumArgsException(interp, 2, argv, "name");
0239:                    }
0240:                    fileObj = FileUtil
0241:                            .getNewFileObj(interp, argv[2].toString());
0242:                    interp.setResult(fileObj.exists());
0243:                    return;
0244:
0245:                case OPT_EXTENSION:
0246:                    if (argv.length != 3) {
0247:                        throw new TclNumArgsException(interp, 2, argv, "name");
0248:                    }
0249:                    interp.setResult(getExtension(argv[2].toString()));
0250:                    return;
0251:
0252:                case OPT_ISDIRECTORY:
0253:                    if (argv.length != 3) {
0254:                        throw new TclNumArgsException(interp, 2, argv, "name");
0255:                    }
0256:                    fileObj = FileUtil
0257:                            .getNewFileObj(interp, argv[2].toString());
0258:                    interp.setResult(fileObj.isDirectory());
0259:                    return;
0260:
0261:                case OPT_ISFILE:
0262:                    if (argv.length != 3) {
0263:                        throw new TclNumArgsException(interp, 2, argv, "name");
0264:                    }
0265:                    fileObj = FileUtil
0266:                            .getNewFileObj(interp, argv[2].toString());
0267:                    interp.setResult(fileObj.isFile());
0268:                    return;
0269:
0270:                case OPT_JOIN:
0271:                    if (argv.length < 3) {
0272:                        throw new TclNumArgsException(interp, 2, argv,
0273:                                "name ?name ...?");
0274:                    }
0275:                    interp.setResult(FileUtil.joinPath(interp, argv, 2,
0276:                            argv.length));
0277:                    return;
0278:
0279:                case OPT_LINK:
0280:                    //FIXME:   not implemented yet
0281:
0282:                    throw new TclException(interp,
0283:                            "sorry, \"file link\" is not implemented yet");
0284:
0285:                case OPT_LSTAT:
0286:                    if (argv.length != 4) {
0287:                        throw new TclNumArgsException(interp, 2, argv,
0288:                                "name varName");
0289:                    }
0290:
0291:                    // FIXME:  Not yet implemented.
0292:                    // Java does not support link access.
0293:
0294:                    throw new TclException(interp, "file command with opt "
0295:                            + argv[1].toString() + " is not yet implemented");
0296:
0297:                case OPT_MTIME:
0298:                    if (argv.length != 3) {
0299:                        throw new TclNumArgsException(interp, 2, argv, "name");
0300:                    }
0301:                    fileObj = FileUtil
0302:                            .getNewFileObj(interp, argv[2].toString());
0303:                    interp.setResult(getMtime(interp, argv[2].toString(),
0304:                            fileObj));
0305:                    return;
0306:
0307:                case OPT_MKDIR:
0308:                    fileMakeDirs(interp, argv);
0309:                    return;
0310:
0311:                case OPT_NATIVENAME:
0312:                    if (argv.length != 3) {
0313:                        throw new TclNumArgsException(interp, 2, argv, "name");
0314:                    }
0315:
0316:                    interp.setResult(FileUtil.translateFileName(interp, argv[2]
0317:                            .toString()));
0318:                    return;
0319:
0320:                case OPT_NORMALIZE:
0321:                    // FIXME:  Not yet implemented.
0322:
0323:                    throw new TclException(interp,
0324:                            "sorry, \"file normalize\" is not implemented yet");
0325:
0326:                case OPT_OWNED:
0327:                    if (argv.length != 3) {
0328:                        throw new TclNumArgsException(interp, 2, argv, "name");
0329:                    }
0330:                    fileObj = FileUtil
0331:                            .getNewFileObj(interp, argv[2].toString());
0332:                    interp.setResult(isOwner(interp, fileObj));
0333:                    return;
0334:
0335:                case OPT_PATHTYPE:
0336:                    if (argv.length != 3) {
0337:                        throw new TclNumArgsException(interp, 2, argv, "name");
0338:                    }
0339:                    switch (FileUtil.getPathType(argv[2].toString())) {
0340:                    case FileUtil.PATH_RELATIVE:
0341:                        interp.setResult("relative");
0342:                        return;
0343:                    case FileUtil.PATH_VOLUME_RELATIVE:
0344:                        interp.setResult("volumerelative");
0345:                        return;
0346:                    case FileUtil.PATH_ABSOLUTE:
0347:                        interp.setResult("absolute");
0348:                    }
0349:                    return;
0350:
0351:                case OPT_READABLE:
0352:                    if (argv.length != 3) {
0353:                        throw new TclNumArgsException(interp, 2, argv, "name");
0354:                    }
0355:                    fileObj = FileUtil
0356:                            .getNewFileObj(interp, argv[2].toString());
0357:                    interp.setResult(fileObj.canRead());
0358:                    return;
0359:
0360:                case OPT_READLINK:
0361:                    if (argv.length != 3) {
0362:                        throw new TclNumArgsException(interp, 2, argv, "name");
0363:                    }
0364:
0365:                    // FIXME:  Not yet implemented.
0366:                    // Java does not support link access.
0367:
0368:                    throw new TclException(interp, "file command with opt "
0369:                            + argv[1].toString() + " is not yet implemented");
0370:
0371:                case OPT_RENAME:
0372:                    fileCopyRename(interp, argv, false);
0373:                    return;
0374:
0375:                case OPT_ROOTNAME:
0376:                    if (argv.length != 3) {
0377:                        throw new TclNumArgsException(interp, 2, argv, "name");
0378:                    }
0379:                    String fileName = argv[2].toString();
0380:                    String extension = getExtension(fileName);
0381:                    int diffLength = fileName.length() - extension.length();
0382:                    interp.setResult(fileName.substring(0, diffLength));
0383:                    return;
0384:
0385:                case OPT_SEPARATOR:
0386:                    // FIXME:  Not yet implemented.
0387:
0388:                    throw new TclException(interp,
0389:                            "sorry, \"file separator\" is not implemented yet");
0390:
0391:                case OPT_SIZE:
0392:                    if (argv.length != 3) {
0393:                        throw new TclNumArgsException(interp, 2, argv, "name");
0394:                    }
0395:                    fileObj = FileUtil
0396:                            .getNewFileObj(interp, argv[2].toString());
0397:                    if (!fileObj.exists()) {
0398:                        throw new TclPosixException(interp,
0399:                                TclPosixException.ENOENT, true,
0400:                                "could not read \"" + argv[2].toString() + "\"");
0401:                    }
0402:                    interp.setResult((int) fileObj.length());
0403:                    return;
0404:
0405:                case OPT_SPLIT:
0406:                    if (argv.length != 3) {
0407:                        throw new TclNumArgsException(interp, 2, argv, "name");
0408:                    }
0409:                    interp.setResult(FileUtil.splitPath(interp, argv[2]
0410:                            .toString()));
0411:                    return;
0412:
0413:                case OPT_STAT:
0414:                    if (argv.length != 4) {
0415:                        throw new TclNumArgsException(interp, 2, argv,
0416:                                "name varName");
0417:                    }
0418:                    getAndStoreStatData(interp, argv[2].toString(), argv[3]
0419:                            .toString());
0420:                    return;
0421:
0422:                case OPT_SYSTEM:
0423:                    //FIXME:   not implemented yet
0424:
0425:                    throw new TclException(interp,
0426:                            "sorry, \"file system\" is not implemented yet");
0427:
0428:                case OPT_TAIL:
0429:                    if (argv.length != 3) {
0430:                        throw new TclNumArgsException(interp, 2, argv, "name");
0431:                    }
0432:                    interp.setResult(getTail(interp, argv[2].toString()));
0433:                    return;
0434:
0435:                case OPT_TYPE:
0436:                    if (argv.length != 3) {
0437:                        throw new TclNumArgsException(interp, 2, argv, "name");
0438:                    }
0439:                    fileObj = FileUtil
0440:                            .getNewFileObj(interp, argv[2].toString());
0441:                    interp.setResult(getType(interp, argv[2].toString(),
0442:                            fileObj));
0443:                    return;
0444:
0445:                case OPT_VOLUMES:
0446:                    if (argv.length != 2) {
0447:                        throw new TclNumArgsException(interp, 2, argv, null);
0448:                    }
0449:
0450:                    // use Java 1.2's File.listRoots() method if available
0451:
0452:                    if (listRootsMethod == null)
0453:                        throw new TclException(interp,
0454:                                "\"file volumes\" is not supported");
0455:
0456:                    try {
0457:                        File[] roots = (File[]) listRootsMethod.invoke(null,
0458:                                new Object[0]);
0459:                        if (roots != null) {
0460:                            TclObject list = TclList.newInstance();
0461:                            for (int i = 0; i < roots.length; i++) {
0462:                                String root = roots[i].getPath();
0463:                                TclList.append(interp, list, TclString
0464:                                        .newInstance(root));
0465:                            }
0466:                            interp.setResult(list);
0467:                        }
0468:                    } catch (IllegalAccessException ex) {
0469:                        throw new TclRuntimeError(
0470:                                "IllegalAccessException in volumes cmd");
0471:                    } catch (IllegalArgumentException ex) {
0472:                        throw new TclRuntimeError(
0473:                                "IllegalArgumentException in volumes cmd");
0474:                    } catch (InvocationTargetException ex) {
0475:                        Throwable t = ex.getTargetException();
0476:
0477:                        if (t instanceof  Error) {
0478:                            throw (Error) t;
0479:                        } else {
0480:                            throw new TclRuntimeError(
0481:                                    "unexected exception in volumes cmd");
0482:                        }
0483:                    }
0484:
0485:                    return;
0486:                case OPT_WRITABLE:
0487:                    if (argv.length != 3) {
0488:                        throw new TclNumArgsException(interp, 2, argv, "name");
0489:                    }
0490:                    fileObj = FileUtil
0491:                            .getNewFileObj(interp, argv[2].toString());
0492:                    interp.setResult(fileObj.canWrite());
0493:                    return;
0494:                default:
0495:                    throw new TclRuntimeError("file command with opt "
0496:                            + argv[1].toString() + " is not implemented");
0497:                }
0498:            }
0499:
0500:            /*-----------------------------------------------------------------------------
0501:             *
0502:             * isOwner --
0503:             *
0504:             *	If "File" is owned by the uid associated with the program, return
0505:             *	true.  Otherwise, return false.
0506:             *
0507:             * Results:
0508:             *	Boolean.
0509:             *
0510:             * Side effects:
0511:             *	None.
0512:             *
0513:             *-----------------------------------------------------------------------------
0514:             */
0515:
0516:            private static boolean isOwner(Interp interp, // Interpreter for error reports. 
0517:                    File fileObj) // File obj whose owner to find.
0518:                    throws TclException // Thrown if unimplemented code segment
0519:            // is reached
0520:            {
0521:                // If the file doesn't exist, return false;
0522:
0523:                if (!fileObj.exists()) {
0524:                    return false;
0525:                }
0526:                boolean owner = true;
0527:
0528:                // For Windows and Macintosh, there are no user ids 
0529:                // associated with a file, so we always return 1.
0530:
0531:                if (Util.isUnix()) {
0532:                    // FIXME:  Not yet implemented on Unix.  Do no checking, for now.
0533:                    // Java does not support ownership checking.
0534:                }
0535:                return owner;
0536:            }
0537:
0538:            /*
0539:             *-----------------------------------------------------------------------------
0540:             *
0541:             * getMtime --
0542:             *
0543:             *	Finds the last modification of file in fileObj.
0544:             *
0545:             * Results:
0546:             *	Returns an int representation of modification time, in seconds.
0547:             *
0548:             * Side effects:
0549:             *	None.
0550:             *
0551:             *-----------------------------------------------------------------------------
0552:             */
0553:
0554:            private static int getMtime(Interp interp, // Interpreter for error reports. 
0555:                    String fileName, // Name of file whose mtime to find.
0556:                    File fileObj) // File obj whose mtime to find.
0557:                    throws TclException // Exceptions thrown as a result of bad
0558:            //   user input.
0559:            {
0560:                if (!fileObj.exists()) {
0561:                    throw new TclPosixException(interp,
0562:                            TclPosixException.ENOENT, true, "could not read \""
0563:                                    + fileName + "\"");
0564:                }
0565:                // Divide to convert msecs to seconds
0566:                return (int) (fileObj.lastModified() / 1000);
0567:            }
0568:
0569:            /*
0570:             *-----------------------------------------------------------------------------
0571:             *
0572:             * getType --
0573:             *
0574:             *	Finds the type of file in fileObj.
0575:             *	WARNING:  Only checks for file and directory status.  If neither file
0576:             *	or direcotry, return link.  Java only supports file and directory
0577:             *	checking.
0578:             *
0579:             * Results:
0580:             *	Returns a string "file", "directory", etc.
0581:             *
0582:             * Side effects:
0583:             *	None.
0584:             *
0585:             *-----------------------------------------------------------------------------
0586:             */
0587:
0588:            private static String getType(Interp interp, // Interpreter for error reports. 
0589:                    String fileName, // Name of file whose owner to find.
0590:                    File fileObj) // File obj whose owner to find.
0591:                    throws TclException // Exceptions thrown as a result of bad
0592:            //   user input.
0593:            {
0594:                if (!fileObj.exists()) {
0595:                    throw new TclPosixException(interp,
0596:                            TclPosixException.ENOENT, true, "could not read \""
0597:                                    + fileName + "\"");
0598:                }
0599:
0600:                if (fileObj.isFile()) {
0601:                    return "file";
0602:                } else if (fileObj.isDirectory()) {
0603:                    return "directory";
0604:                }
0605:                return "link";
0606:            }
0607:
0608:            /*
0609:             *-----------------------------------------------------------------------------
0610:             *
0611:             * getAndStoreStatData --
0612:             *
0613:             *	This is a utility procedure that breaks out the fields of a
0614:             *	"stat" structure and stores them in textual form into the
0615:             *	elements of an associative array.
0616:             *	WARNING: skipping dev, gid, ino, mode, and nlink attributes.
0617:             *	WARNING: ctime and atime are the same as mtime.
0618:             *	Java does not support the above attributes.
0619:             *
0620:             * Results:
0621:             *	Returns a standard Tcl return value.  If an error occurs then
0622:             *	a message is left in interp->result.
0623:             *
0624:             * Side effects:
0625:             *	Elements of the associative array given by "varName" are modified.
0626:             *
0627:             *-----------------------------------------------------------------------------
0628:             */
0629:
0630:            private static void getAndStoreStatData(Interp interp, // Interpreter for error reports. 
0631:                    String fileName, // Name of file whose stats to find.
0632:                    String varName) // Name of associative array variable
0633:                    //   in which to store stat results.
0634:                    throws TclException // Exceptions thrown as a result of bad
0635:            //   user input.
0636:            {
0637:                File fileObj = FileUtil.getNewFileObj(interp, fileName);
0638:
0639:                if (!fileObj.exists()) {
0640:                    throw new TclPosixException(interp,
0641:                            TclPosixException.ENOENT, true, "could not read \""
0642:                                    + fileName + "\"");
0643:                }
0644:
0645:                try {
0646:                    int mtime = getMtime(interp, fileName, fileObj);
0647:                    TclObject mtimeObj = TclInteger.newInstance(mtime);
0648:                    TclObject atimeObj = TclInteger.newInstance(mtime);
0649:                    TclObject ctimeObj = TclInteger.newInstance(mtime);
0650:                    interp.setVar(varName, "atime", atimeObj, 0);
0651:                    interp.setVar(varName, "ctime", ctimeObj, 0);
0652:                    interp.setVar(varName, "mtime", mtimeObj, 0);
0653:                } catch (SecurityException e) {
0654:                    throw new TclException(interp, e.getMessage());
0655:                } catch (TclException e) {
0656:                    throw new TclException(interp, "can't set \"" + varName
0657:                            + "(dev)\": variable isn't array");
0658:                }
0659:
0660:                try {
0661:                    TclObject sizeObj = TclInteger.newInstance((int) fileObj
0662:                            .length());
0663:                    interp.setVar(varName, "size", sizeObj, 0);
0664:                } catch (Exception e) {
0665:                    // Do nothing.
0666:                }
0667:
0668:                try {
0669:                    TclObject typeObj = TclString.newInstance(getType(interp,
0670:                            fileName, fileObj));
0671:                    interp.setVar(varName, "type", typeObj, 0);
0672:                } catch (Exception e) {
0673:                }
0674:
0675:                try {
0676:                    TclObject uidObj = TclBoolean.newInstance(isOwner(interp,
0677:                            fileObj));
0678:                    interp.setVar(varName, "uid", uidObj, 0);
0679:                } catch (TclException e) {
0680:                    // Do nothing.
0681:                }
0682:            }
0683:
0684:            /*
0685:             *-----------------------------------------------------------------------------
0686:             *
0687:             * getExtension --
0688:             *
0689:             *	Return the substring of "path" which represents the file's
0690:             *	extension.  It is necessary to perform system specific 
0691:             *	operations because different systems have different separators.
0692:             *
0693:             * Results:
0694:             *	Returns a file extension String.
0695:             *
0696:             * Side effects:
0697:             *	None.
0698:             *
0699:             *-----------------------------------------------------------------------------
0700:             */
0701:
0702:            private static String getExtension(String path) // Path for which we find extension.
0703:            {
0704:                if (path.length() < 1) {
0705:                    return "";
0706:                }
0707:
0708:                // Set lastSepIndex to the first index in the last component of the path.
0709:
0710:                int lastSepIndex = -1;
0711:                switch (JACL.PLATFORM) {
0712:                case JACL.PLATFORM_WINDOWS:
0713:                    String tmpPath = path.replace('\\', '/').replace(':', '/');
0714:                    lastSepIndex = tmpPath.lastIndexOf('/');
0715:                    break;
0716:                case JACL.PLATFORM_MAC:
0717:                    lastSepIndex = path.lastIndexOf(':');
0718:                    if (lastSepIndex == -1) {
0719:                        lastSepIndex = path.lastIndexOf('/');
0720:                    }
0721:                    break;
0722:                default:
0723:                    lastSepIndex = path.lastIndexOf('/');
0724:                }
0725:                ++lastSepIndex;
0726:
0727:                // Return "" if the last character is a separator.
0728:
0729:                if (lastSepIndex >= path.length()) {
0730:                    return ("");
0731:                }
0732:
0733:                // Find the last dot in the last component of the path.
0734:
0735:                String lastSep = path.substring(lastSepIndex);
0736:                int dotIndex = lastSep.lastIndexOf('.');
0737:
0738:                // Return "" if no dot was found in the file's name.
0739:
0740:                if (dotIndex == -1) {
0741:                    return "";
0742:                }
0743:
0744:                // In earlier versions, we used to back up to the first period in a series
0745:                // so that "foo..o" would be split into "foo" and "..o".  This is a
0746:                // confusing and usually incorrect behavior, so now we split at the last
0747:                // period in the name.
0748:
0749:                return (lastSep.substring(dotIndex));
0750:            }
0751:
0752:            /*
0753:             *-----------------------------------------------------------------------------
0754:             *
0755:             * getTail --
0756:             *
0757:             *	Return the substring of "path" which represents the file's
0758:             *	tail.  It is necessary to perform system specific 
0759:             *	operations because different systems have different separators.
0760:             *
0761:             * Results:
0762:             *	Returns a file tail String.
0763:             *
0764:             * Side effects:
0765:             *	None.
0766:             *
0767:             *-----------------------------------------------------------------------------
0768:             */
0769:
0770:            private static String getTail(Interp interp, // Current interpreter. 
0771:                    String path) // Path for which to find the tail.
0772:                    throws TclException // Thrown if tilde subst, which may be
0773:            // called by splitAndTranslate, fails. 
0774:            {
0775:                // Split the path and return the string form of the last component,
0776:                // unless there is only one component which is the root or an absolute
0777:                // path. 
0778:
0779:                TclObject splitResult = FileUtil
0780:                        .splitAndTranslate(interp, path);
0781:
0782:                int last = TclList.getLength(interp, splitResult) - 1;
0783:
0784:                if (last >= 0) {
0785:                    if ((last > 0)
0786:                            || (FileUtil.getPathType(path) == FileUtil.PATH_RELATIVE)) {
0787:                        TclObject tailObj = TclList.index(interp, splitResult,
0788:                                last);
0789:                        return tailObj.toString();
0790:                    }
0791:                }
0792:                return "";
0793:            }
0794:
0795:            /*
0796:             *-----------------------------------------------------------------------------
0797:             *
0798:             * fileMakeDirs --
0799:             *
0800:             *	This procedure implements the "mkdir" subcommand of the "file"
0801:             *      command.  Filename arguments need to be translated to native
0802:             *	format before being passed to platform-specific code that
0803:             *	implements mkdir functionality.
0804:             *	WARNING:  ignoring links because Java does not support them.
0805:             *	
0806:             * Results:
0807:             *	None.
0808:             *
0809:             * Side effects:
0810:             *	See user documentation.
0811:             *
0812:             *-----------------------------------------------------------------------------
0813:             */
0814:
0815:            private static void fileMakeDirs(Interp interp, // Current interpreter. 
0816:                    TclObject[] argv) // Arguments to "file" command.
0817:                    throws TclException // Thrown as a result of bad user input.
0818:            {
0819:                boolean madeDir = false;
0820:
0821:                for (int currentDir = 2; currentDir < argv.length; currentDir++) {
0822:
0823:                    String dirName = argv[currentDir].toString();
0824:                    if (dirName.length() == 0) {
0825:                        throw new TclPosixException(interp,
0826:                                TclPosixException.ENOENT, true,
0827:                                "can't create directory \"\"");
0828:                    }
0829:                    File dirObj = FileUtil.getNewFileObj(interp, dirName);
0830:                    if (dirObj.exists()) {
0831:                        // If the directory already exists, do nothing.
0832:
0833:                        if (dirObj.isDirectory()) {
0834:                            continue;
0835:                        }
0836:                        throw new TclPosixException(interp,
0837:                                TclPosixException.EEXIST, true,
0838:                                "can't create directory \"" + dirName + "\"");
0839:                    }
0840:                    try {
0841:                        madeDir = dirObj.mkdir();
0842:                        if (!madeDir) {
0843:                            madeDir = dirObj.mkdirs();
0844:                        }
0845:                    } catch (SecurityException e) {
0846:                        throw new TclException(interp, e.getMessage());
0847:                    }
0848:                    if (!madeDir) {
0849:                        throw new TclPosixException(interp,
0850:                                TclPosixException.EACCES, true,
0851:                                "can't create directory \"" + dirName
0852:                                        + "\":  best guess at reason");
0853:                    }
0854:                }
0855:            }
0856:
0857:            /*
0858:             *-----------------------------------------------------------------------------
0859:             *
0860:             * fileDelete --
0861:             *
0862:             *	This procedure implements the "delete" subcommand of the "file"
0863:             *      command.
0864:             *	
0865:             * Results:
0866:             *	None.
0867:             *
0868:             * Side effects:
0869:             *	See user documentation.
0870:             *
0871:             *-----------------------------------------------------------------------------
0872:             */
0873:
0874:            private static void fileDelete(Interp interp, // Current interpreter. 
0875:                    TclObject[] argv) // Arguments to "file" command.
0876:                    throws TclException // Thrown as a result of bad user input.
0877:            {
0878:                boolean force = false;
0879:                int firstSource = 2;
0880:
0881:                for (boolean last = false; (firstSource < argv.length)
0882:                        && (!last); firstSource++) {
0883:
0884:                    if (!argv[firstSource].toString().startsWith("-")) {
0885:                        break;
0886:                    }
0887:                    int opt = TclIndex.get(interp, argv[firstSource],
0888:                            validOptions, "option", 1);
0889:                    switch (opt) {
0890:                    case OPT_FORCE:
0891:                        force = true;
0892:                        break;
0893:                    case OPT_LAST:
0894:                        last = true;
0895:                        break;
0896:                    default:
0897:                        throw new TclRuntimeError(
0898:                                "FileCmd.cmdProc: bad option " + opt
0899:                                        + " index to validOptions");
0900:                    }
0901:                }
0902:
0903:                if (firstSource >= argv.length) {
0904:                    throw new TclNumArgsException(interp, 2, argv,
0905:                            "?options? file ?file ...?");
0906:                }
0907:
0908:                for (int i = firstSource; i < argv.length; i++) {
0909:                    deleteOneFile(interp, argv[i].toString(), force);
0910:                }
0911:            }
0912:
0913:            /*
0914:             *-----------------------------------------------------------------------------
0915:             *
0916:             * deleteOneFile --
0917:             *
0918:             *	After performing error checking, deletes the specified file.
0919:             *	WARNING:  ignoring links because Java does not support them.
0920:             *	
0921:             * Results:
0922:             *	None.
0923:             *
0924:             * Side effects:
0925:             *	See user documentation.
0926:             *
0927:             *-----------------------------------------------------------------------------
0928:             */
0929:
0930:            private static void deleteOneFile(Interp interp, // Current interpreter. 
0931:                    String fileName, // Name of file to delete.
0932:                    boolean force) // Flag tells whether to delete
0933:                    //   recursively.
0934:                    throws TclException // Thrown as a result of bad user input.
0935:            {
0936:                boolean isDeleted = true;
0937:                File fileObj = FileUtil.getNewFileObj(interp, fileName);
0938:
0939:                // Trying to delete a file that does not exist is not
0940:                // considered an error, just a no-op
0941:
0942:                if ((!fileObj.exists()) || (fileName.length() == 0)) {
0943:                    return;
0944:                }
0945:
0946:                // If the file is a non-empty directory, recursively delete its children if
0947:                // the -force option was chosen.  Otherwise, throw an error.
0948:
0949:                if (fileObj.isDirectory() && (fileObj.list().length > 0)) {
0950:                    if (force) {
0951:                        String fileList[] = fileObj.list();
0952:                        for (int i = 0; i < fileList.length; i++) {
0953:
0954:                            TclObject joinArrayObj[] = new TclObject[2];
0955:                            joinArrayObj[0] = TclString.newInstance(fileName);
0956:                            joinArrayObj[1] = TclString
0957:                                    .newInstance(fileList[i]);
0958:
0959:                            String child = FileUtil.joinPath(interp,
0960:                                    joinArrayObj, 0, 2);
0961:                            deleteOneFile(interp, child, force);
0962:                        }
0963:                    } else {
0964:                        throw new TclPosixException(interp,
0965:                                TclPosixException.ENOTEMPTY,
0966:                                "error deleting \"" + fileName
0967:                                        + "\": directory not empty");
0968:                    }
0969:                }
0970:                try {
0971:                    isDeleted = fileObj.delete();
0972:                } catch (SecurityException e) {
0973:                    throw new TclException(interp, e.getMessage());
0974:                }
0975:                if (!isDeleted) {
0976:                    throw new TclPosixException(interp,
0977:                            TclPosixException.EACCES, true, "error deleting \""
0978:                                    + fileName + "\":  best guess at reason");
0979:                }
0980:            }
0981:
0982:            /*
0983:             *-----------------------------------------------------------------------------
0984:             *
0985:             * fileCopyRename --
0986:             *
0987:             *	This procedure implements the "copy" and "rename" subcommands of the
0988:             *	"file" command.  Filename arguments need to be translated to native
0989:             *	format before being passed to platform-specific code that implements 
0990:             *	copy functionality.
0991:             *	
0992:             * Results:
0993:             *	None.
0994:             *
0995:             * Side effects:
0996:             *	Target is overwritten if the force flag is set.  Attempting to
0997:             *	copy/rename a file onto a directory or a directory onto a file
0998:             *	will always result in an error.  
0999:             *	See user documentation.
1000:             *
1001:             *-----------------------------------------------------------------------------
1002:             */
1003:
1004:            private static void fileCopyRename(Interp interp, // Current interpreter. 
1005:                    TclObject[] argv, // Arguments to "file" command.
1006:                    boolean copyFlag) // Flag tells whether to copy or rename.
1007:                    throws TclException // Thrown as a result of bad user input.
1008:            {
1009:                int firstSource = 2;
1010:                boolean force = false;
1011:
1012:                for (boolean last = false; (firstSource < argv.length)
1013:                        && (!last); firstSource++) {
1014:
1015:                    if (!argv[firstSource].toString().startsWith("-")) {
1016:                        break;
1017:                    }
1018:                    int opt = TclIndex.get(interp, argv[firstSource],
1019:                            validOptions, "option", 1);
1020:                    switch (opt) {
1021:                    case OPT_FORCE:
1022:                        force = true;
1023:                        break;
1024:                    case OPT_LAST:
1025:                        last = true;
1026:                        break;
1027:                    default:
1028:                        throw new TclRuntimeError(
1029:                                "FileCmd.cmdProc: bad option " + opt
1030:                                        + " index to validOptions");
1031:                    }
1032:                }
1033:
1034:                if (firstSource >= (argv.length - 1)) {
1035:                    throw new TclNumArgsException(interp, firstSource, argv,
1036:                            "?options? source ?source ...? target");
1037:                }
1038:
1039:                // WARNING:  ignoring links because Java does not support them.
1040:
1041:                int target = argv.length - 1;
1042:                String targetName = argv[target].toString();
1043:
1044:                File targetObj = FileUtil.getNewFileObj(interp, targetName);
1045:                if (targetObj.isDirectory()) {
1046:                    // If the target is a directory, move each source file into target
1047:                    // directory.  Extract the tailname from each source, and append it to
1048:                    // the end of the target path.  
1049:
1050:                    for (int source = firstSource; source < target; source++) {
1051:
1052:                        String sourceName = argv[source].toString();
1053:
1054:                        if (targetName.length() == 0) {
1055:                            copyRenameOneFile(interp, sourceName, targetName,
1056:                                    copyFlag, force);
1057:                        } else {
1058:                            String tailName = getTail(interp, sourceName);
1059:
1060:                            TclObject joinArrayObj[] = new TclObject[2];
1061:                            joinArrayObj[0] = TclString.newInstance(targetName);
1062:                            joinArrayObj[1] = TclString.newInstance(tailName);
1063:
1064:                            String fullTargetName = FileUtil.joinPath(interp,
1065:                                    joinArrayObj, 0, 2);
1066:
1067:                            copyRenameOneFile(interp, sourceName,
1068:                                    fullTargetName, copyFlag, force);
1069:                        }
1070:                    }
1071:                } else {
1072:                    // If there is more than 1 source file and the target is not a
1073:                    // directory, then throw an exception.
1074:
1075:                    if (firstSource + 1 != target) {
1076:                        String action;
1077:                        if (copyFlag) {
1078:                            action = "copying";
1079:                        } else {
1080:                            action = "renaming";
1081:                        }
1082:                        throw new TclPosixException(interp,
1083:                                TclPosixException.ENOTDIR, "error " + action
1084:                                        + ": target \""
1085:                                        + argv[target].toString()
1086:                                        + "\" is not a directory");
1087:                    }
1088:                    String sourceName = argv[firstSource].toString();
1089:                    copyRenameOneFile(interp, sourceName, targetName, copyFlag,
1090:                            force);
1091:                }
1092:            }
1093:
1094:            /*
1095:             *-----------------------------------------------------------------------------
1096:             *
1097:             * copyRenameOneFile --
1098:             *
1099:             *	After performing error checking, performs the copy and rename commands.
1100:             *	WARNING:  ignoring links because Java does not support them.
1101:             *	
1102:             * Results:
1103:             *	None.
1104:             *
1105:             * Side effects:
1106:             *	See user documentation.
1107:             *
1108:             *-----------------------------------------------------------------------------
1109:             */
1110:
1111:            private static void copyRenameOneFile(Interp interp, // Current interpreter. 
1112:                    String sourceName, // Name of source file.
1113:                    String targetName, // Name of target file.
1114:                    boolean copyFlag, // Flag tells whether to copy or rename.
1115:                    boolean force) // Flag tells whether to overwrite.
1116:                    throws TclException // Thrown as a result of bad user input.
1117:            {
1118:                // Copying or renaming a file onto itself is a no-op if force is chosen,
1119:                // otherwise, it will be caught later as an EEXISTS error.
1120:
1121:                if (force && sourceName.equals(targetName)) {
1122:                    return;
1123:                }
1124:
1125:                // Check that the source exists and that if -force was not specified, the
1126:                // target doesn't exist.
1127:                //
1128:                // Prevent copying/renaming a file onto a directory and
1129:                // vice-versa.  This is a policy decision based on the fact that
1130:                // existing implementations of copy and rename on all platforms
1131:                // also prevent this.
1132:
1133:                String action;
1134:                if (copyFlag) {
1135:                    action = "copying";
1136:                } else {
1137:                    action = "renaming";
1138:                }
1139:
1140:                File sourceFileObj = FileUtil.getNewFileObj(interp, sourceName);
1141:                if ((!sourceFileObj.exists()) || (sourceName.length() == 0)) {
1142:                    throw new TclPosixException(interp,
1143:                            TclPosixException.ENOENT, true, "error " + action
1144:                                    + " \"" + sourceName + "\"");
1145:                }
1146:
1147:                if (targetName.length() == 0) {
1148:                    throw new TclPosixException(interp,
1149:                            TclPosixException.ENOENT, true, "error " + action
1150:                                    + " \"" + sourceName + "\" to \""
1151:                                    + targetName + "\"");
1152:                }
1153:                File targetFileObj = FileUtil.getNewFileObj(interp, targetName);
1154:                if (targetFileObj.exists() && !force) {
1155:                    throw new TclPosixException(interp,
1156:                            TclPosixException.EEXIST, true, "error " + action
1157:                                    + " \"" + sourceName + "\" to \""
1158:                                    + targetName + "\"");
1159:                }
1160:
1161:                if (sourceFileObj.isDirectory() && !targetFileObj.isDirectory()) {
1162:                    throw new TclPosixException(interp,
1163:                            TclPosixException.EISDIR, "can't overwrite file \""
1164:                                    + targetName + "\" with directory \""
1165:                                    + sourceName + "\"");
1166:                }
1167:                if (targetFileObj.isDirectory() && !sourceFileObj.isDirectory()) {
1168:                    throw new TclPosixException(interp,
1169:                            TclPosixException.EISDIR,
1170:                            "can't overwrite directory \"" + targetName
1171:                                    + "\" with file \"" + sourceName + "\"");
1172:                }
1173:
1174:                if (!copyFlag) {
1175:                    // Perform the rename procedure.
1176:
1177:                    if (!sourceFileObj.renameTo(targetFileObj)) {
1178:
1179:                        if (targetFileObj.isDirectory()) {
1180:                            throw new TclPosixException(interp,
1181:                                    TclPosixException.EEXIST, true,
1182:                                    "error renaming \"" + sourceName
1183:                                            + "\" to \"" + targetName + "\"");
1184:                        }
1185:
1186:                        throw new TclPosixException(interp,
1187:                                TclPosixException.EACCES, true,
1188:                                "error renaming \"" + sourceName + "\" to \""
1189:                                        + targetName
1190:                                        + "\":  best guess at reason");
1191:                    }
1192:                } else {
1193:                    // Perform the copy procedure.
1194:
1195:                    try {
1196:                        BufferedInputStream bin = new BufferedInputStream(
1197:                                new FileInputStream(sourceFileObj));
1198:                        BufferedOutputStream bout = new BufferedOutputStream(
1199:                                new FileOutputStream(targetFileObj));
1200:
1201:                        final int bsize = 1024;
1202:                        byte[] buff = new byte[bsize];
1203:                        int numChars = bin.read(buff, 0, bsize);
1204:                        while (numChars != -1) {
1205:                            bout.write(buff, 0, numChars);
1206:                            numChars = bin.read(buff, 0, bsize);
1207:                        }
1208:                        bin.close();
1209:                        bout.close();
1210:                    } catch (IOException e) {
1211:                        throw new TclException(interp, "error copying: "
1212:                                + e.getMessage());
1213:                    }
1214:                }
1215:            }
1216:
1217:        } // end FileCmd 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.