001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package com.sun.midp.io.j2me.file;
028:
029: import java.io.IOException;
030: import java.util.Vector;
031:
032: import com.sun.midp.midlet.MIDletStateHandler;
033: import com.sun.midp.midlet.MIDletSuite;
034:
035: /**
036: * Default file handler.
037: */
038: class DefaultFileHandler implements BaseFileHandler {
039:
040: /*
041: * Placeholder for the file handle from the native layer.
042: * Value of <code>0</code> indicates that file is either closed or
043: * does not exists
044: */
045: /** Read handle. */
046: private int readHandle = 0;
047: /** Write handle. */
048: private int writeHandle = 0;
049:
050: /** File name. */
051: private long fileName = 0;
052: // The dir name is required when checking the fileSystem sizes
053: /** Root directory. */
054: private long rootDir = 0;
055:
056: /** Illegal file name characters. */
057: private static String illegalChars = null;
058:
059: /**
060: * The flag is used for performance optimization.
061: * <code>true</code> stands for it was detected
062: * what private directory exists.
063: */
064: private static boolean privateDirExists = false;
065:
066: /**
067: * Init class info in the native code
068: */
069: static {
070: initialize();
071:
072: illegalChars = illegalFileNameChars0();
073: if (illegalChars == null) {
074: illegalChars = "";
075: }
076: }
077:
078: /**
079: * Connect file handler to the abstract file target. This operation should
080: * not trigger any access to the native filesystem.
081: *
082: * @param rootName The name of the root directory.
083: *
084: * @param fileName Full path to the file to be handled by this handler.
085: *
086: * @throws IllegalArgumentException if filename contains characters
087: * not allowed by the file system. This check should not involve
088: * any actual access to the filesystem.
089: */
090: public void connect(String rootName, String fileName) {
091: if (rootName == null || rootName.length() == 0) {
092: return;
093: }
094: String rootPath = getNativePathForRoot(rootName);
095: if (rootPath != null) {
096: StringBuffer name = new StringBuffer(rootPath);
097: int curr = name.length();
098: this .rootDir = getNativeName(rootPath, this .rootDir);
099:
100: // we add '1' because 'fileName' unlike 'rootName'
101: // has leading '/'
102: int fileNameLen = fileName.length();
103: if (fileName != null && fileNameLen != 0) {
104: name.append(fileName.substring(rootName.length() + 1));
105: }
106: String privateDirURL = System
107: .getProperty("fileconn.dir.private");
108: if (privateDirURL != null) {
109: int privateDirURLLen = privateDirURL.length();
110: if (fileName.regionMatches(true, 0, privateDirURL, 7,
111: privateDirURLLen - 7)) {
112: name.insert(curr + privateDirURLLen
113: - rootName.length() - 8, getSuiteID()
114: + getFileSeparator());
115: }
116: }
117:
118: pathToNativeSeparator(name, curr, name.length() - curr);
119: this .fileName = getNativeName(name.toString(),
120: this .fileName);
121: }
122: }
123:
124: /**
125: * Creates dedicated private working directory for the MIDlet suite.
126: * Does nothing if specified root is not private root or the directory
127: * already exists.
128: *
129: * @param rootName the name of file root
130: */
131: public void createPrivateDir(String rootName) throws IOException {
132: // create private directory if necessary
133: String privateDir = System.getProperty("fileconn.dir.private");
134: if (privateDir != null) {
135: privateDir = privateDir.substring(7);
136: if (!privateDirExists
137: && rootName.regionMatches(true, 0, privateDir, 1,
138: rootName.length())) {
139: BaseFileHandler fh = new DefaultFileHandler();
140: fh.connect(rootName, privateDir);
141: if (!fh.exists()) {
142: fh.mkdir();
143: }
144: privateDirExists = true;
145: }
146: }
147: }
148:
149: /**
150: * Gets a filtered list of files and directories contained in a directory.
151: * The directory is the handler's target as specified in
152: * <code>create()</code>.
153: *
154: * @param filter String against which all files and directories are
155: * matched for retrieval. An asterisk ("*") can be used as a
156: * wildcard to represent 0 or more occurrences of any character.
157: * If null no filtering is performed
158: * @param includeHidden boolean indicating whether files marked as hidden
159: * should be included or not in the list of files and directories
160: * returned.
161: * @return An Enumeration of strings, denoting the files and directories
162: * in the directory matching the filter. Directories are denoted
163: * with a trailing slash "/" in their returned name. The
164: * Enumeration has zero length if the directory is empty or no
165: * files and/or directories are found matching the given filter.
166: * Any current directory indication (".") and any parent directory
167: * indication ("..") is not included in the list of files and
168: * directories returned.
169: * @throws IOException if invoked on a file, the directory does not exist,
170: * the directory is not accessible, or an I/O error occurs.
171: * @throws IllegalArgumentException if filter contains any path
172: * specification or is an invalid filename for the platform
173: * (e.g. contains characters invalid for a filename on their
174: * platform).
175: */
176: public Vector list(String filter, boolean includeHidden)
177: throws IOException {
178:
179: Vector list = new Vector();
180:
181: long dirHandle = openDir();
182:
183: String fname = dirGetNextFile(dirHandle, includeHidden);
184: while (fname != null) {
185: // cleanname is passed to the filter and does not contain trailing
186: // slash denoting directory
187: String cleanname;
188: if (fname.charAt(fname.length() - 1) == '/') {
189: cleanname = fname.substring(0, fname.length() - 1);
190: } else {
191: cleanname = fname;
192: }
193:
194: if (filterAccept(filter, cleanname)) {
195: list.addElement(fname);
196: }
197: fname = dirGetNextFile(dirHandle, includeHidden);
198: }
199:
200: closeDir(dirHandle);
201: return list;
202: }
203:
204: /**
205: * List filesystem roots available on the device. For the description of
206: * the correct root format see <code>FileConnection</code> documentation.
207: * @return array of roots;
208: * empty array is returned if there are no roots available.
209: */
210: public Vector listRoots() {
211: Vector roots = new Vector();
212: String s = getMountedRoots();
213: if (s != null) {
214: String[] rs = com.sun.kvem.midp.pim.formats.FormatSupport
215: .split(s, '\n', 0);
216: for (int i = 0; i < rs.length; i++) {
217: roots.addElement(rs[i]);
218: }
219: }
220: return roots;
221: }
222:
223: /**
224: * Create file corresponding to this file handler. The
225: * file is created immediately on the actual file system upon invocation of
226: * this method. Files are created with zero length and data can be put
227: * into the file through write method after opening the file. This method
228: * does not create any directories specified in the file's path.
229: *
230: * @throws IOException if invoked on the existing file or unexpected error
231: * occurs.
232: */
233: public native void create() throws IOException;
234:
235: /**
236: * Check is file or directory corresponding to this filehandler exists.
237: * @return <code>true</code> if the file/directory exists,
238: * <code>false</code> otherwise.
239: */
240: public native boolean exists();
241:
242: /**
243: * Check is file corresponding to this filehandler exists and is a
244: * directory.
245: * @return <code>true</code> if pathname is a directory
246: */
247: public native boolean isDirectory();
248:
249: /**
250: * Deletes the file or directory associated with this handler.
251: * The file or directory is deleted immediately on
252: * the actual file system upon invocation of this method. Previously open
253: * native file should be closed.The
254: * handler instance object remains connected and available for use.
255: *
256: * @throws IOException If the target is a directory and it is not empty,
257: * the connection target does not exist or is unaccessible, or
258: * an unspecified error occurs preventing deletion of the target.
259: */
260: public native void delete() throws IOException;
261:
262: /**
263: * Renames the selected file or directory to a new name in the same
264: * directory. The file or directory is renamed immediately on the actual
265: * file system upon invocation of this method. No file or directory by the
266: * original name exists after this method call. Previously open native file
267: * should be closed. The handler
268: * instance object remains connected and available for use,
269: * referring now to the file or directory by its new name.
270: *
271: * @param newName The new name of the file or directory. The name must
272: * be the full qualified name of the new file
273: * @throws IOException if the connection's target does not exist, the
274: * connection's target is not accessible, a file or directory
275: * already exists by the <code>newName</code>, or
276: * <code>newName</code> is an invalid filename for the platform
277: * (e.g. contains characters invalid in a filename
278: * on the platform).
279: */
280: public void rename(String newName) throws IOException {
281: // we start search of '/' from '1' to skip leading '/'
282: // that means local machine in URL specification
283: int rootEnd = newName.indexOf('/', 1);
284: String rootName = newName.substring(1, rootEnd + 1);
285:
286: if (rootName.length() == 0) {
287: return;
288: }
289: String rootPath = getNativePathForRoot(rootName);
290: if (rootPath != null) {
291: StringBuffer name = new StringBuffer(rootPath);
292: int curr = name.length();
293:
294: String newNameWORoot = newName.substring(rootEnd + 1);
295: name.append(newNameWORoot);
296:
297: String privateDirURL = System
298: .getProperty("fileconn.dir.private");
299: if (privateDirURL != null) {
300: int privateDirURLLen = privateDirURL.length();
301: if (newName.regionMatches(true, 0, privateDirURL, 7,
302: privateDirURLLen - 7)) {
303: name.insert(curr + privateDirURLLen
304: - rootName.length() - 8, getSuiteID()
305: + getFileSeparator());
306: }
307: }
308:
309: pathToNativeSeparator(name, curr, name.length() - curr);
310: rename0(name.toString());
311: }
312: }
313:
314: /**
315: * Helper method that renames the file.
316: * @param newName new name for the file
317: * @throws IOException if any error occurs
318: */
319: private native void rename0(String newName) throws IOException;
320:
321: /**
322: * Truncates the file, discarding all data from the given byte offset to
323: * the current end of the file. If the byte offset provided is greater
324: * than or equal to the file's current byte count, the method returns
325: * without changing the file.
326: *
327: * @param byteOffset the offset into the file from which truncation
328: * occurs.
329: * @throws IOException if invoked on a directory or the file does not
330: * exist or is not accessible.
331: */
332: public native void truncate(long byteOffset) throws IOException;
333:
334: /**
335: * Determines the size of a file on the file system. The size of a file
336: * always represents the number of bytes contained in the file; there is
337: * no pre-allocated but empty space in a file. Users should perform an
338: * explicit <code>flush()</code> on any open output streams to the file
339: * prior to invoking this method to ensure accurate results.
340: *
341: * @return The size in bytes of the selected file, or -1 if the
342: * file does not exist or is not accessible.
343: * @throws IOException if the method is invoked on a directory.
344: */
345: public native long fileSize() throws IOException;
346:
347: /**
348: * Determines the size in bytes on a file system of all of the files
349: * that are contained in a directory.
350: *
351: * @param includeSubDirs if <code>true</code>, size calculation will
352: * include all subdirectories' size.
353: * @return The size in bytes occupied by the files included in the
354: * directory, or -1 if the directory does not exist or is
355: * not accessible.
356: * @throws IOException if some error occures while accessing the directory.
357: */
358: public native long directorySize(boolean includeSubDirs)
359: throws IOException;
360:
361: /**
362: * Check is file corresponding to this filehandler exists and has a
363: * read permission.
364: * @return <code>true</code> if the file can be read
365: */
366: public native boolean canRead();
367:
368: /**
369: * Check is file corresponding to this filehandler exists and has a
370: * write permission.
371: * @return <code>true</code> if the file can be written
372: */
373: public native boolean canWrite();
374:
375: /**
376: * Check is file corresponding to this filehandler exists and is
377: * hidden.
378: * @return <code>true</code> if the file is not visible
379: */
380: public boolean isHidden() {
381: // Note: ANSI C does not define hidden files.
382: // Sure, on UNIX systems a file is considered to be hidden
383: // if its name begins with a period character ('.'), but we can not
384: // rename files during setHidden() method, so we consider
385: // what hidden files are not supported on UNIX systems, and this method
386: // always returns false on UNIX as it's required by JSR 75 spec.
387: return isHidden0();
388: }
389:
390: /**
391: * Helper method that checks if the file is visible.
392: * @return <code>true</code> if the file is not visible
393: */
394: private native boolean isHidden0();
395:
396: /**
397: * Sets the file or directory readable attribute to the
398: * indicated value. The readable attribute for the file on the actual
399: * file system is set immediately upon invocation of this method. If the
400: * file system doesn't support a settable read attribute, this method is
401: * ignored and <code>canRead()</code> always returns true.
402: *
403: * @param readable The new state of the readable flag of
404: * the selected file.
405: * @throws IOException of the connection's target does not exist or is not
406: * accessible.
407: * @see #canRead
408: */
409: public native void setReadable(boolean readable) throws IOException;
410:
411: /**
412: * Sets the file or directory associated with this file handler writable
413: * attribute to the
414: * indicated value. The writable attribute for the file on the actual
415: * file system is set immediately upon invocation of the method. If the
416: * file system doesn't support a settable write attribute, this method is
417: * ignored and <code>canWrite()</code> always returns true.
418: *
419: * @param writable The new state of the writable flag of the selected
420: * file.
421: * @throws IOException if the connection's target does not exist or is not
422: * accessible.
423: * @see #canWrite
424: */
425: public native void setWritable(boolean writable) throws IOException;
426:
427: /**
428: * Sets the hidden attribute of the file associated with this file handler
429: * to the value provided. The attribute is applied to the file on the
430: * actual file system immediately upon invocation of this method if the
431: * file system
432: * and platform support it. If the file system doesn't support a hidden
433: * attribute, this method is ignored and <code>isHidden()</code> always
434: * returns false. Since the exact definition of hidden is
435: * system-dependent,
436: * this method only works on file systems that support a settable file
437: * attribute. For example, on Win32 and FAT file systems, a file may be
438: * considered hidden if it has been marked as such in the file's
439: * attributes; therefore this method is applicable. However on UNIX
440: * systems a file may be considered to be hidden if its name begins with a
441: * period character ('.'). In the UNIX case, this method may be ignored and
442: * the method to make a file hidden may be the <code>rename()</code>
443: * method.
444: *
445: * @param hidden The new state of the hidden flag of the selected file.
446: * @throws IOException if the connection's target does not exist or is not
447: * accessible.
448: * @see #isHidden
449: */
450: public void setHidden(boolean hidden) throws IOException {
451: setHidden0(hidden);
452: }
453:
454: /**
455: * Helper method that marks the file hidden flag.
456: * @param hidden <code>true</code> to make file as not visible
457: * @throws IOException if any error occurs
458: */
459: private native void setHidden0(boolean hidden) throws IOException;
460:
461: /**
462: * Creates a directory corresponding to the directory
463: * string provided in the connect() method.
464: * The directory is created immediately on the actual
465: * file system upon invocation of this method. Directories in the
466: * specified path are not recursively created and must be explicitly
467: * created before subdirectories can be created.
468: *
469: * @throws IOException if invoked on an existing directory or on any file
470: * (<code>create()</code> is used to create files), the target
471: * file system is not accessible, or an unspecified error occurs
472: * preventing creation of the directory.
473: */
474: public native void mkdir() throws IOException;
475:
476: /**
477: * Determines the free memory that is available on the file system the file
478: * or directory resides on. This may only be an estimate and may vary based
479: * on platform-specific file system blocking and metadata information.
480: *
481: * @return The available size in bytes on a file system, or -1 if an
482: * error occurs.
483: */
484: public native long availableSize();
485:
486: /**
487: * Determines the total size of the file system the connection's target
488: * resides on.
489: *
490: * @return The total size of the file system in bytes, or -1 if an
491: * error occurs.
492: */
493: public native long totalSize();
494:
495: /**
496: * Determines the used memory of a file system the connection's target
497: * resides on. This may only be an estimate and may vary based
498: * on platform-specific file system blocking and metadata information.
499: *
500: * @return The used size of bytes on a file system, or -1 if an
501: * error occurs.
502: */
503: public long usedSize() {
504: return totalSize() - availableSize();
505: }
506:
507: /**
508: * Returns a string that contains all characters forbidden for the use on
509: * the given platform except "/" (forward slash) which is always considered
510: * illegal. If there are no such characters an empty string is returned.
511: * @return string of illegal file name characters
512: */
513: public String illegalFileNameChars() {
514: return illegalChars;
515: }
516:
517: /**
518: * Returns the time that the file denoted by this file handler
519: * was last modified.
520: * @return The time then last modification of the file took place.
521: */
522: public native long lastModified();
523:
524: /**
525: * Opens the file for reading.
526: * @throws IOException if any error occurs during input/output operations.
527: */
528: public native void openForRead() throws IOException;
529:
530: /**
531: * Closes the file for reading.
532: * @throws IOException if any error occurs during input/output operations.
533: */
534: public native void closeForRead() throws IOException;
535:
536: /**
537: * Opens the file for writing.
538: * @throws IOException if any error occurs during input/output operations.
539: */
540: public native void openForWrite() throws IOException;
541:
542: /**
543: * Closes the file for writing.
544: * @throws IOException if any error occurs during input/output operations.
545: */
546: public native void closeForWrite() throws IOException;
547:
548: /**
549: * Closes the file for both reading and writing.
550: * @throws IOException if any error occurs during input/output operations.
551: */
552: public native void closeForReadWrite() throws IOException;
553:
554: /**
555: * Reads data from the file to an array.
556: * @param b array for input data
557: * @param off index in the input array
558: * @param len length of data to read
559: * @return length of data really read
560: * @throws IOException if any error occurs.
561: */
562: public native int read(byte b[], int off, int len)
563: throws IOException;
564:
565: /**
566: * Write data from an array to the file.
567: * @param b array of output data
568: * @param off index in the output array
569: * @param len length of data to write
570: * @return length of data really written
571: * @throws IOException if any error occurs.
572: */
573: public native int write(byte b[], int off, int len)
574: throws IOException;
575:
576: /**
577: * Sets the next write location.
578: * @param offset seek position for next write
579: * @throws IOException if any error occurs.
580: */
581: public native void positionForWrite(long offset) throws IOException;
582:
583: /**
584: * Flushes any output to the file.
585: * @throws IOException if any error occurs.
586: */
587: public native void flush() throws IOException;
588:
589: /**
590: * Close file associated with this handler. Open file and all system
591: * resources should be released by this call. Handler object can be
592: * reused by subsequent call to connect().
593: *
594: * @throws IOException if I/O error occurs
595: */
596: public native void close() throws IOException;
597:
598: /**
599: * Returns ID of the current MIDlet suite in 8-digit reverse hexadecimal
600: * form (the same form is used in native code).
601: *
602: * @return resulting String representation of the MIDlet suite ID
603: */
604: private String getSuiteID() {
605: MIDletSuite midletSuite = MIDletStateHandler
606: .getMidletStateHandler().getMIDletSuite();
607: StringBuffer id = new StringBuffer(Integer
608: .toHexString(midletSuite.getID()));
609: int len = id.length();
610: while (len++ < 8) {
611: id.insert(0, '0');
612: }
613: return id.reverse().toString();
614: }
615:
616: /**
617: * Replace all entries of the "//" with "/" (multiple separators
618: * with single separator) and all "/" with the native separator.
619: *
620: * @param name StringBuffer to process
621: * @param off offset from where to start the conversion
622: * @param len length to convert
623: *
624: * @return the same StringBuffer after the process
625: */
626: private StringBuffer pathToNativeSeparator(StringBuffer name,
627: int off, int len) {
628:
629: int length = off + len;
630: int curr = off;
631: char sep = getFileSeparator();
632:
633: while ((curr + 1) < length) {
634: if (name.charAt(curr) == '/'
635: && name.charAt(curr + 1) == '/') {
636: name.deleteCharAt(curr);
637: length--;
638: continue;
639: } else if (name.charAt(curr) == '/') {
640: name.setCharAt(curr, sep);
641: }
642: curr++;
643: }
644:
645: // trim trailing slash if it exists
646: if (name.charAt(length - 1) == '/') {
647: name.deleteCharAt(length - 1);
648: }
649:
650: return name;
651: }
652:
653: /**
654: * Check that given string matches the given filter. Filter is defined by
655: * the FileConnection spec as follows:
656: * <p>String against which all files and directories are
657: * matched for retrieval. An asterisk ("*") can be used as a
658: * wildcard to represent 0 or more occurrences of any character.
659: * <p>Filter value of null matches any string.
660: *
661: * @param filter string against witch to match
662: * @param str string to be matched
663: *
664: * @return true is str matches the filter of if filter is null,
665: * otherwise false
666: */
667: private boolean filterAccept(String filter, String str) {
668:
669: if (filter == null) {
670: return true;
671: }
672:
673: if (filter.length() == 0) {
674: return false;
675: }
676:
677: int currPos = 0;
678: int currComp = 0, firstSigComp = 0;
679: int idx;
680:
681: // Splitted string does not contain separators themselves
682: String components[] = split(filter, '*', 0);
683:
684: // if filter does not begin with '*' check that string begins with
685: // filter's first component
686: if (filter.charAt(0) != '*') {
687: if (!str.startsWith(components[0])) {
688: return false;
689: } else {
690: currPos += components[0].length();
691: currComp++;
692: firstSigComp = currComp;
693: }
694: }
695:
696: // Run on the string and check that it contains all filter
697: // components sequentially
698: for (; currComp < components.length; currComp++) {
699: if ((idx = str.indexOf(components[currComp], currPos)) != -1) {
700: currPos = idx + components[currComp].length();
701: } else {
702: // run out of the string while filter components remain
703: return false;
704: }
705: }
706:
707: // At this point we run out of filter. First option is that
708: // filter ends with '*', or string is finished,
709: // we are fine then, and accept the string.
710: //
711: // In the other case we check that string ends with the last component
712: // of the filter (given that there was an asterisk before the last
713: // component
714: if (!(filter.charAt(filter.length() - 1) == '*' || currPos == str
715: .length())) {
716: if (components.length > firstSigComp) {
717: // does string end with the last filter component?
718: if (!str.endsWith(components[components.length - 1])) {
719: return false;
720: }
721: } else {
722: // there was no asteric before last filter component
723: return false;
724: }
725: }
726:
727: // If we got here string is accepted
728: return true;
729: }
730:
731: /**
732: * Parses a separated list of strings into a string array.
733: * An escaped separator (backslash followed by separatorChar) is not
734: * treated as a separator.
735: * @param data string to be processed
736: * @param separatorChar the character used to separate items
737: * @param startingPoint Only use the part of the string that follows this
738: * index
739: *
740: * @return a non-null string array containing string elements
741: */
742: private static String[] split(String data, char separatorChar,
743: int startingPoint) {
744:
745: if (startingPoint == data.length()) {
746: return new String[0];
747: }
748: Vector elementList = new Vector();
749:
750: if (data.charAt(startingPoint) == separatorChar) {
751: startingPoint++;
752: }
753:
754: int startSearchAt = startingPoint;
755: int startOfElement = startingPoint;
756:
757: for (int i; (i = data.indexOf(separatorChar, startSearchAt)) != -1;) {
758: if (i != 0 && data.charAt(i - 1) == '\\') {
759: // escaped semicolon. don't treat it as a separator
760: startSearchAt = i + 1;
761: } else {
762: String element = data.substring(startOfElement, i);
763: elementList.addElement(element);
764: startSearchAt = startOfElement = i + 1;
765: }
766: }
767:
768: if (data.length() > startOfElement) {
769: if (elementList.size() == 0) {
770: return new String[] { data.substring(startOfElement) };
771: }
772: elementList.addElement(data.substring(startOfElement));
773: }
774:
775: String[] elements = new String[elementList.size()];
776: for (int i = 0; i < elements.length; i++) {
777: elements[i] = (String) elementList.elementAt(i);
778: }
779: return elements;
780: }
781:
782: /**
783: * Return pointer to the system-dependent file name stored in the native
784: * code.
785: *
786: * @param name a string representing the filename to convert to native
787: * the form
788: * @return A pointer to the system-dependent file name
789: */
790: private native static long getNativeName(String name, long oldName);
791:
792: /**
793: * Gets the system-dependent file separator character.
794: * @return The file separator character.
795: */
796: public native static char getFileSeparator();
797:
798: /**
799: * Opens the directory.
800: * @return native pointer to an opaque filelist structure used by
801: * methods iterating over file list.
802: */
803: private native long openDir();
804:
805: /**
806: * Closes the directory.
807: * @param dirHandle native pointer to an opaque filelist structure
808: * returned by openDir method.
809: */
810: private native void closeDir(long dirHandle);
811:
812: /**
813: * Gets the next file in directory.
814: * @param dirHandle native pointer to a filelist structure
815: * returned by <code>openDir</code>
816: * @param includeHidden determines whether it's necessary
817: * to include hidden files and directories
818: * @return the name of the file.
819: */
820: private native String dirGetNextFile(long dirHandle,
821: boolean includeHidden);
822:
823: /**
824: * Gets the mounted root file systems.
825: * @return A string containing currently mounted roots
826: * separated by '\n' character
827: */
828: private native String getMountedRoots();
829:
830: /**
831: * Gets OS path for the specified file system root.
832: * @param root root name
833: * @return The path to access the root
834: */
835: private native String getNativePathForRoot(String root);
836:
837: /**
838: * Gets the list of illegal characters in file names.
839: * @return A string containing the characters
840: * that are not allowed inside file names.
841: */
842: private native static String illegalFileNameChars0();
843:
844: /**
845: * Initializes native part of file handler.
846: */
847: private native static void initialize();
848:
849: /**
850: * Cleanup after garbage collected instance
851: */
852: private native void finalize();
853: }
|