Source Code Cross Referenced for Protocol.java in  » 6.0-JDK-Modules » j2me » com » sun » midp » io » j2me » file » 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 » 6.0 JDK Modules » j2me » com.sun.midp.io.j2me.file 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *   
0003:         *
0004:         * Copyright  1990-2007 Sun Microsystems, Inc. All Rights Reserved.
0005:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
0006:         * 
0007:         * This program is free software; you can redistribute it and/or
0008:         * modify it under the terms of the GNU General Public License version
0009:         * 2 only, as published by the Free Software Foundation.
0010:         * 
0011:         * This program is distributed in the hope that it will be useful, but
0012:         * WITHOUT ANY WARRANTY; without even the implied warranty of
0013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0014:         * General Public License version 2 for more details (a copy is
0015:         * included at /legal/license.txt).
0016:         * 
0017:         * You should have received a copy of the GNU General Public License
0018:         * version 2 along with this work; if not, write to the Free Software
0019:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
0020:         * 02110-1301 USA
0021:         * 
0022:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
0023:         * Clara, CA 95054 or visit www.sun.com if you need additional
0024:         * information or have any questions.
0025:         */
0026:
0027:        package com.sun.midp.io.j2me.file;
0028:
0029:        import com.sun.midp.security.Permissions;
0030:        import com.sun.midp.main.Configuration;
0031:        import com.sun.midp.io.*;
0032:
0033:        import javax.microedition.io.file.*;
0034:
0035:        import java.io.IOException;
0036:        import java.io.InterruptedIOException;
0037:        import java.io.UnsupportedEncodingException;
0038:        import java.io.OutputStream;
0039:        import java.io.InputStream;
0040:        import java.io.DataOutputStream;
0041:        import java.io.DataInputStream;
0042:        import java.util.Enumeration;
0043:        import javax.microedition.io.*;
0044:        import com.sun.midp.security.*;
0045:
0046:        import java.util.Vector;
0047:
0048:        import com.sun.midp.midlet.MIDletSuite;
0049:        import com.sun.midp.midlet.Scheduler;
0050:
0051:        /**
0052:         * This class implements the necessary functionality
0053:         * for a File connection.
0054:         */
0055:        public class Protocol extends ConnectionBaseAdapter implements 
0056:                FileConnection {
0057:
0058:            /** Security token for using FileConnection API from PIM */
0059:            private SecurityToken classSecurityToken;
0060:
0061:            /** Stores file connection mode */
0062:            private int mode;
0063:
0064:            /** File name string */
0065:            private String fileName;
0066:
0067:            /** File path string including root filesystem */
0068:            private String filePath;
0069:
0070:            /** Root filesystem for the file */
0071:            private String fileRoot;
0072:
0073:            /** File original URL */
0074:            private String fileURL;
0075:
0076:            /** A peer to the native file */
0077:            private BaseFileHandler fileHandler;
0078:
0079:            /** Indicates if there is a need to try to load alternative file handler */
0080:            private static boolean hasOtherFileHandler = true;
0081:
0082:            /** Input stream associated with this connection */
0083:            InputStream fis;
0084:
0085:            /** Output stream associated with this connection */
0086:            OutputStream fos;
0087:
0088:            /** Separator for file path components */
0089:            private static String sep;
0090:
0091:            /** Static initialization of file separator */
0092:            static {
0093:                char[] t = new char[1];
0094:                t[0] = DefaultFileHandler.getFileSeparator();
0095:                sep = new String(t);
0096:                if (sep == null) {
0097:                    throw new NullPointerException(
0098:                            "Undefined \"file.separator\" property");
0099:                }
0100:            }
0101:
0102:            /**
0103:             * Constructor for file connection implementation.
0104:             */
0105:            public Protocol() {
0106:                connectionOpen = false;
0107:                fileHandler = null;
0108:            }
0109:
0110:            /**
0111:             * Opens the file connection.
0112:             * @param name URL path fragment
0113:             * @param mode access mode
0114:             * @param timeouts flag to indicate that timeouts allowed
0115:             * @return an opened Connection
0116:             * @throws IOException if some other kind of I/O error occurs.
0117:             */
0118:            public Connection openPrim(String name, int mode, boolean timeouts)
0119:                    throws IOException {
0120:                return openPrimImpl(name, mode, timeouts, true);
0121:            }
0122:
0123:            /**
0124:             * Opens the file connection and receive security token.
0125:             * @param token security token from PIM
0126:             * @param name URL path fragment
0127:             * @return an opened Connection
0128:             * @throws IOException if some other kind of I/O error occurs.
0129:             */
0130:            public Connection openPrim(SecurityToken token, String name)
0131:                    throws IOException {
0132:                return openPrim(token, name, Connector.READ_WRITE);
0133:            }
0134:
0135:            /**
0136:             * Opens the file connection and receive security token.
0137:             * @param token security token from PIM
0138:             * @param name URL path fragment
0139:             * @param mode access mode
0140:             * @return an opened Connection
0141:             *  @throws IOException if some other kind of I/O error occurs.
0142:             */
0143:            public Connection openPrim(SecurityToken token, String name,
0144:                    int mode) throws IOException {
0145:                classSecurityToken = token;
0146:                return openPrim(name, mode, false);
0147:            }
0148:
0149:            // JAVADOC COMMENT ELIDED
0150:            public boolean isOpen() {
0151:                return connectionOpen;
0152:            }
0153:
0154:            /**
0155:             * Open and return an input stream for a connection.  The connection's
0156:             * target must already exist and be accessible for the input stream to be
0157:             * created.
0158:             *
0159:             * @return  An open input stream
0160:             * @exception  IOException if an I/O error occurs, if the method is invoked
0161:             *          on a directory, if the connection's target does not
0162:             *          yet exist, or the connection's target is not accessible.
0163:             * @exception  IllegalModeException if the application does have read
0164:             *             access
0165:             *          to the connection's target but has opened the connection in
0166:             *          <code>Connector.WRITE</code> mode.
0167:             * @exception  SecurityException   If the application is not granted read
0168:             *          access to the connection's target.
0169:             *
0170:             */
0171:            public InputStream openInputStream() throws IOException {
0172:
0173:                checkReadPermission();
0174:
0175:                try {
0176:                    ensureOpenAndConnected();
0177:                } catch (ConnectionClosedException e) {
0178:                    throw new IOException(e.getMessage());
0179:                }
0180:
0181:                // IOException when target file doesn't exist
0182:                if (!fileHandler.exists()) {
0183:                    throw new IOException("Target file doesn't exist");
0184:                }
0185:
0186:                if (!fileHandler.canRead()) { // no read access
0187:                    throw new SecurityException("No read access");
0188:                }
0189:
0190:                fileHandler.openForRead();
0191:
0192:                fis = super .openInputStream();
0193:
0194:                return fis;
0195:            }
0196:
0197:            /**
0198:             * Open and return an output stream for a connection. The output stream
0199:             * is positioned at the start of the file. Writing data to the output
0200:             * stream overwrites the contents of the files (i.e. does not insert data).
0201:             * Writing data to output streams beyond the current end of file
0202:             * automatically extends the file size.  The connection's target must
0203:             * already exist and be accessible for the output stream to be created.
0204:             * {@link #openOutputStream(long)} should be used to position an output
0205:             * stream to a different position in the file.
0206:             * <P>
0207:             * Changes made to a file through an output stream may not be immediately
0208:             * made to the actual file residing on the file system because
0209:             * platform and implementation specific use of caching and buffering of the
0210:             * data.  Stream contents and file length extensions are not necessarily
0211:             * visible outside of the application immediately unless
0212:             * <code>flush()</code> is called on the stream.? The returned output
0213:             *  stream is automatically and synchronously flushed when it is closed.
0214:             * </P>
0215:             *
0216:             * @return  An open output stream
0217:             * @exception  IOException  If an I/O error occurs, if the method is
0218:             *             invoked on
0219:             *          a directory, the file does not yet exist, or the connection's
0220:             *          target is not accessible.
0221:             * @exception  IllegalModeException if the application does have write
0222:             *             access
0223:             *          to the connection's target but has opened the connection in
0224:             *          <code>Connector.READ</code> mode.
0225:             * @exception  SecurityException    If the application is not granted write
0226:             *          access to the connection's target.
0227:             * @see #openOutputStream(long)
0228:             *
0229:             */
0230:            public OutputStream openOutputStream() throws IOException {
0231:                return openOutputStream(0);
0232:            }
0233:
0234:            // JAVADOC COMMENT ELIDED
0235:            public OutputStream openOutputStream(long byteOffset)
0236:                    throws IOException {
0237:                if (byteOffset < 0) {
0238:                    throw new IllegalArgumentException(
0239:                            "Offset has a negative value");
0240:                }
0241:
0242:                checkWritePermission();
0243:
0244:                try {
0245:                    ensureOpenAndConnected();
0246:                } catch (ConnectionClosedException e) {
0247:                    throw new IOException(e.getMessage());
0248:                }
0249:
0250:                // IOException when target file doesn't exist
0251:                if (!fileHandler.exists()) {
0252:                    throw new IOException("Target file doesn't exist");
0253:                }
0254:
0255:                if (!fileHandler.canWrite()) {
0256:                    // no write access
0257:                    throw new SecurityException("No write access");
0258:                }
0259:
0260:                fileHandler.openForWrite();
0261:                fileHandler.positionForWrite(byteOffset);
0262:
0263:                fos = super .openOutputStream();
0264:
0265:                return fos;
0266:            }
0267:
0268:            // JAVADOC COMMENT ELIDED
0269:            public long totalSize() {
0270:                long size = -1;
0271:
0272:                try {
0273:                    checkRootReadPermission();
0274:
0275:                    ensureOpenAndConnected();
0276:
0277:                    size = fileHandler.totalSize();
0278:                } catch (IOException e) {
0279:                    size = -1;
0280:                }
0281:
0282:                return size;
0283:            }
0284:
0285:            // JAVADOC COMMENT ELIDED
0286:            public long availableSize() {
0287:                long size = -1;
0288:
0289:                try {
0290:                    checkRootReadPermission();
0291:
0292:                    ensureOpenAndConnected();
0293:
0294:                    size = fileHandler.availableSize();
0295:                } catch (IOException e) {
0296:                    size = -1;
0297:                }
0298:
0299:                return size;
0300:            }
0301:
0302:            // JAVADOC COMMENT ELIDED
0303:            public long usedSize() {
0304:                long size = -1;
0305:
0306:                try {
0307:                    checkRootReadPermission();
0308:
0309:                    ensureOpenAndConnected();
0310:
0311:                    size = fileHandler.usedSize();
0312:                } catch (IOException e) {
0313:                    size = -1;
0314:                }
0315:
0316:                return size;
0317:            }
0318:
0319:            // JAVADOC COMMENT ELIDED
0320:            public long directorySize(boolean includeSubDirs)
0321:                    throws IOException {
0322:                long size = 0;
0323:
0324:                // Permissions and ensureOpenAndConnected called by exists()
0325:                if (exists()) {
0326:                    if (!isDirectory()) {
0327:                        throw new IOException(
0328:                                "directorySize is not invoked on directory");
0329:                    }
0330:                } else {
0331:                    return -1L;
0332:                }
0333:
0334:                try {
0335:                    size = fileHandler.directorySize(includeSubDirs);
0336:                } catch (IOException e) {
0337:                    size = -1;
0338:                }
0339:
0340:                return size;
0341:            }
0342:
0343:            // JAVADOC COMMENT ELIDED
0344:            public long fileSize() throws IOException {
0345:                long size = -1;
0346:
0347:                checkReadPermission();
0348:
0349:                if (isDirectory()) {
0350:                    throw new IOException("fileSize invoked on a directory");
0351:                }
0352:
0353:                try {
0354:                    ensureOpenAndConnected();
0355:
0356:                    size = fileHandler.fileSize();
0357:                } catch (IOException e) {
0358:                    size = -1;
0359:                }
0360:
0361:                return size;
0362:            }
0363:
0364:            // JAVADOC COMMENT ELIDED
0365:            public boolean canRead() {
0366:                boolean res = false;
0367:
0368:                try {
0369:                    checkReadPermission();
0370:
0371:                    ensureOpenAndConnected();
0372:
0373:                    res = fileHandler.canRead();
0374:                } catch (IOException e) {
0375:                    res = false;
0376:                }
0377:
0378:                return res;
0379:            }
0380:
0381:            // JAVADOC COMMENT ELIDED
0382:            public boolean canWrite() {
0383:                boolean res = false;
0384:
0385:                try {
0386:                    checkReadPermission();
0387:
0388:                    ensureOpenAndConnected();
0389:
0390:                    res = fileHandler.canWrite();
0391:                } catch (IOException e) {
0392:                    res = false;
0393:                }
0394:
0395:                return res;
0396:            }
0397:
0398:            // JAVADOC COMMENT ELIDED
0399:            public boolean isHidden() {
0400:                boolean res = false;
0401:
0402:                try {
0403:                    checkReadPermission();
0404:
0405:                    ensureOpenAndConnected();
0406:
0407:                    res = fileHandler.isHidden();
0408:                } catch (IOException e) {
0409:                    res = false;
0410:                }
0411:
0412:                return res;
0413:            }
0414:
0415:            // JAVADOC COMMENT ELIDED
0416:            public void setReadable(boolean readable) throws IOException {
0417:                checkWritePermission();
0418:
0419:                ensureOpenAndConnected();
0420:
0421:                fileHandler.setReadable(readable);
0422:            }
0423:
0424:            // JAVADOC COMMENT ELIDED
0425:            public void setWritable(boolean writable) throws IOException {
0426:                checkWritePermission();
0427:
0428:                ensureOpenAndConnected();
0429:
0430:                fileHandler.setWritable(writable);
0431:            }
0432:
0433:            // JAVADOC COMMENT ELIDED
0434:            public void setHidden(boolean hidden) throws IOException {
0435:                checkWritePermission();
0436:
0437:                ensureOpenAndConnected();
0438:
0439:                fileHandler.setHidden(hidden);
0440:            }
0441:
0442:            // JAVADOC COMMENT ELIDED
0443:            public Enumeration list() throws IOException {
0444:                return listInternal(null, false);
0445:            }
0446:
0447:            // JAVADOC COMMENT ELIDED
0448:            public Enumeration list(String filter, boolean includeHidden)
0449:                    throws IOException {
0450:
0451:                if (filter == null) {
0452:                    throw new NullPointerException("List filter is null");
0453:                }
0454:
0455:                return listInternal(EscapedUtil.getUnescapedString(filter),
0456:                        includeHidden);
0457:            }
0458:
0459:            // JAVADOC COMMENT ELIDED
0460:            public void create() throws IOException {
0461:                checkWritePermission();
0462:
0463:                ensureOpenAndConnected();
0464:
0465:                if (fileName.charAt(fileName.length() - 1) == '/') {
0466:                    throw new IOException("Can not create directory");
0467:                }
0468:
0469:                fileHandler.create();
0470:            }
0471:
0472:            // JAVADOC COMMENT ELIDED
0473:            public void mkdir() throws IOException {
0474:                checkWritePermission();
0475:
0476:                ensureOpenAndConnected();
0477:
0478:                fileHandler.mkdir();
0479:            }
0480:
0481:            // JAVADOC COMMENT ELIDED
0482:            public boolean exists() {
0483:                boolean res = false;
0484:
0485:                try {
0486:                    checkReadPermission();
0487:
0488:                    ensureOpenAndConnected();
0489:
0490:                    res = fileHandler.exists();
0491:                } catch (IOException e) {
0492:                    res = false;
0493:                }
0494:
0495:                return res;
0496:            }
0497:
0498:            // JAVADOC COMMENT ELIDED
0499:            public boolean isDirectory() {
0500:                boolean res = false;
0501:
0502:                try {
0503:                    checkReadPermission();
0504:
0505:                    ensureOpenAndConnected();
0506:
0507:                    res = fileHandler.isDirectory();
0508:                } catch (IOException e) {
0509:                    res = false;
0510:                }
0511:
0512:                return res;
0513:            }
0514:
0515:            // JAVADOC COMMENT ELIDED
0516:            public void delete() throws java.io.IOException {
0517:                checkWritePermission();
0518:
0519:                ensureOpenAndConnected();
0520:
0521:                try {
0522:                    if (fis != null) {
0523:                        fis.close();
0524:                        fis = null;
0525:                    }
0526:                } catch (IOException e) {
0527:                    // Ignore silently
0528:                }
0529:
0530:                try {
0531:                    if (fos != null) {
0532:                        fos.close();
0533:                        fos = null;
0534:                    }
0535:                } catch (IOException e) {
0536:                    // Ignore silently
0537:                }
0538:
0539:                try {
0540:                    fileHandler.closeForReadWrite();
0541:                } catch (IOException e) {
0542:                    // Ignore silently
0543:                }
0544:
0545:                fileHandler.delete();
0546:            }
0547:
0548:            // JAVADOC COMMENT ELIDED
0549:            public void rename(String newName) throws IOException {
0550:                checkWritePermission();
0551:
0552:                newName = EscapedUtil.getUnescapedString(newName);
0553:                // Following line will throw NullPointerException if newName is null
0554:                int dirindex = newName.indexOf('/');
0555:                if (dirindex != -1 && dirindex != (newName.length() - 1)) {
0556:                    throw new IllegalArgumentException(
0557:                            "New name contains path specification");
0558:                }
0559:
0560:                if (!"/".equals(sep) && newName.indexOf(sep) != -1) {
0561:                    throw new IllegalArgumentException(
0562:                            "New name contains path specification");
0563:                }
0564:
0565:                ensureOpenAndConnected();
0566:                checkIllegalChars(newName);
0567:
0568:                try {
0569:                    if (fis != null) {
0570:                        fis.close();
0571:                        fis = null;
0572:                    }
0573:                } catch (IOException e) {
0574:                    // Ignore silently
0575:                }
0576:
0577:                try {
0578:                    if (fos != null) {
0579:                        fos.close();
0580:                        fos = null;
0581:                    }
0582:                } catch (IOException e) {
0583:                    // Ignore silently
0584:                }
0585:
0586:                try {
0587:                    fileHandler.closeForReadWrite();
0588:                } catch (IOException e) {
0589:                    // Ignore silently
0590:                }
0591:
0592:                fileHandler.rename(filePath + newName);
0593:
0594:                fileName = newName;
0595:                fileURL = "file://" + filePath + fileName;
0596:            }
0597:
0598:            // JAVADOC COMMENT ELIDED
0599:            public void truncate(long byteOffset) throws IOException {
0600:                checkWritePermission();
0601:
0602:                ensureOpenAndConnected();
0603:
0604:                if (byteOffset < 0) {
0605:                    throw new IllegalArgumentException("offset is negative");
0606:                }
0607:
0608:                try {
0609:                    if (fos != null) {
0610:                        fos.flush();
0611:                    }
0612:                } catch (IOException e) {
0613:                    // Ignore silently
0614:                }
0615:
0616:                fileHandler.truncate(byteOffset);
0617:            }
0618:
0619:            // JAVADOC COMMENT ELIDED
0620:            public void setFileConnection(String fileName) throws IOException {
0621:                ensureOpenAndConnected();
0622:
0623:                // Note: permissions are checked by openPrim method
0624:
0625:                // Following line will throw NullPointerException if fileName is null
0626:                int dirindex = fileName.indexOf('/');
0627:                if (dirindex != -1 && dirindex != (fileName.length() - 1)) {
0628:                    throw new IllegalArgumentException(
0629:                            "Contains any path specification");
0630:                }
0631:
0632:                if (fileName.equals("..") && this .fileName.length() == 0) {
0633:                    throw new IOException(
0634:                            "Cannot set FileConnection to '..' from a file system root");
0635:                }
0636:
0637:                if (!"/".equals(sep) && fileName.indexOf(sep) != -1) {
0638:                    throw new IllegalArgumentException(
0639:                            "Contains any path specification");
0640:                }
0641:
0642:                checkIllegalChars(fileName);
0643:
0644:                // According to the spec, the current FileConnection object must refer
0645:                // to a directory.
0646:                // Check this right here in order to avoid IllegalModeException instead
0647:                // of IOException.
0648:                if (!fileHandler.isDirectory()) {
0649:                    throw new IOException("Not a directory");
0650:                }
0651:
0652:                String origPath = filePath, origName = this .fileName;
0653:
0654:                String tmp_sep;
0655:                // Note: security checks are performed before any object state changes
0656:                if (fileName.equals("..")) {
0657:                    // go one directory up
0658:                    openPrim("//" + filePath, mode, false);
0659:                } else {
0660:                    int fileNameLen = this .fileName.length();
0661:                    if (fileNameLen == 0
0662:                            || this .fileName.charAt(fileNameLen - 1) == '/') {
0663:                        tmp_sep = "";
0664:                    } else {
0665:                        tmp_sep = "/";
0666:                    }
0667:                    // go deeper in directory structure
0668:                    openPrimImpl("//" + filePath + this .fileName + tmp_sep
0669:                            + fileName, mode, false, false);
0670:                }
0671:
0672:                // Old file connection must be a directory. It can not have open
0673:                // streams so no need to close it. Just reset it to null
0674:                fileHandler = null;
0675:
0676:                // Reconnect to the new target
0677:                ensureOpenAndConnected();
0678:
0679:                // At this point we are already refer to the new file
0680:                if (!fileHandler.exists()) {
0681:                    // Revert to an old file
0682:                    openPrim("//" + origPath + origName, mode, false);
0683:                    fileHandler = null;
0684:
0685:                    throw new IllegalArgumentException(
0686:                            "New target does not exists");
0687:                }
0688:            }
0689:
0690:            /**
0691:             * Spec is not consistent: sometimes it requires IOException
0692:             * and sometimes IllegalArgumentException in case of illegal chars
0693:             * in the filename
0694:             * @param name URL path fragment
0695:             * @throws IOException if name contains unsupported characters
0696:             */
0697:            private void checkIllegalChars(String name) throws IOException {
0698:
0699:                String illegalChars = fileHandler.illegalFileNameChars();
0700:                for (int i = 0; i < illegalChars.length(); i++) {
0701:                    if (name.indexOf(illegalChars.charAt(i)) != -1) {
0702:                        throw new IOException(
0703:                                "Contains characters invalid for a filename");
0704:                    }
0705:                }
0706:            }
0707:
0708:            // JAVADOC COMMENT ELIDED
0709:            public String getName() {
0710:                String name = fileName;
0711:
0712:                try {
0713:                    if (exists()) {
0714:                        int lastPos = name.length() - 1;
0715:                        if (isDirectory()) {
0716:                            if (!name.equals("") && name.charAt(lastPos) != '/')
0717:                                name += '/';
0718:                        } else {
0719:                            if (name.charAt(lastPos) == '/')
0720:                                name = name.substring(0, lastPos);
0721:                        }
0722:                    }
0723:                } catch (SecurityException e) {
0724:                    // According to spec should silently ignore any exceptions
0725:                } catch (IllegalModeException e) {
0726:                    // According to spec should silently ignore any exceptions
0727:                } catch (ConnectionClosedException e) {
0728:                    // According to spec should silently ignore any exceptions
0729:                }
0730:
0731:                return name;
0732:            }
0733:
0734:            // JAVADOC COMMENT ELIDED
0735:            public String getPath() {
0736:                return filePath;
0737:            }
0738:
0739:            // JAVADOC COMMENT ELIDED
0740:            public String getURL() {
0741:                String url = EscapedUtil.getEscapedString(fileURL);
0742:
0743:                try {
0744:                    if (exists()) {
0745:                        int lastPos = url.length() - 1;
0746:                        if (isDirectory()) {
0747:                            if (url.charAt(lastPos) != '/') {
0748:                                url += '/';
0749:                            }
0750:                        } else {
0751:                            if (url.charAt(lastPos) == '/') {
0752:                                url = url.substring(0, lastPos);
0753:                            }
0754:                        }
0755:                    }
0756:                } catch (SecurityException e) {
0757:                    // According to spec should silently ignore any exceptions
0758:                } catch (IllegalModeException e) {
0759:                    // According to spec should silently ignore any exceptions
0760:                } catch (ConnectionClosedException e) {
0761:                    // According to spec should silently ignore any exceptions
0762:                }
0763:
0764:                return url;
0765:            }
0766:
0767:            // JAVADOC COMMENT ELIDED
0768:            public long lastModified() {
0769:                long res = 0;
0770:
0771:                try {
0772:                    checkReadPermission();
0773:
0774:                    ensureOpenAndConnected();
0775:
0776:                    res = fileHandler.lastModified();
0777:                } catch (IOException e) {
0778:                    res = 0;
0779:                }
0780:
0781:                return res;
0782:            }
0783:
0784:            /**
0785:             * Reads up to <code>len</code> bytes of data from the input stream into
0786:             * an array of bytes, blocks until at least one byte is available.
0787:             *
0788:             * @param      b     the buffer into which the data is read.
0789:             * @param      off   the start offset in array <code>b</code>
0790:             *                   at which the data is written.
0791:             * @param      len   the maximum number of bytes to read.
0792:             * @return     the total number of bytes read into the buffer, or
0793:             *             <code>-1</code> if there is no more data because the end of
0794:             *             the stream has been reached.
0795:             * @exception  IOException  if an I/O error occurs.
0796:             */
0797:            protected int readBytes(byte b[], int off, int len)
0798:                    throws IOException {
0799:
0800:                checkReadPermission();
0801:
0802:                ensureConnected();
0803:
0804:                int readBytes = fileHandler.read(b, off, len);
0805:                // return '-1' instead of '0' as stream specification requires
0806:                // in case the end of the stream has been reached
0807:                return (readBytes > 0) ? readBytes : -1;
0808:            }
0809:
0810:            /**
0811:             * Returns the number of bytes that can be read (or skipped over) from
0812:             * this input stream without blocking by the next caller of a method for
0813:             * this input stream.  The next caller might be the same thread or
0814:             * another thread. This classes implementation always returns
0815:             * <code>0</code>. It is up to subclasses to override this method.
0816:             *
0817:             * @return     the number of bytes that can be read from this input stream
0818:             *             without blocking.
0819:             * @exception  IOException  if an I/O error occurs.
0820:             *
0821:             *     public int available() throws IOException {
0822:             *    return 0;
0823:             *}
0824:             */
0825:            /**
0826:             * Writes <code>len</code> bytes from the specified byte array
0827:             * starting at offset <code>off</code> to this output stream.
0828:             * <p>
0829:             * Polling the native code is done here to allow for simple
0830:             * asynchronous native code to be written. Not all implementations
0831:             * work this way (they block in the native code) but the same
0832:             * Java code works for both.
0833:             *
0834:             * @param      b     the data.
0835:             * @param      off   the start offset in the data.
0836:             * @param      len   the number of bytes to write.
0837:             * @return     number of bytes written
0838:             * @exception  IOException  if an I/O error occurs. In particular,
0839:             *             an <code>IOException</code> is thrown if the output
0840:             *             stream is closed.
0841:             */
0842:            protected int writeBytes(byte b[], int off, int len)
0843:                    throws IOException {
0844:                checkWritePermission();
0845:
0846:                ensureConnected();
0847:
0848:                return fileHandler.write(b, off, len);
0849:            }
0850:
0851:            /**
0852:             * Forces any buffered output bytes to be written out.
0853:             * The general contract of <code>flush</code> is
0854:             * that calling it is an indication that, if any bytes previously
0855:             * written that have been buffered by the connection,
0856:             * should immediately be written to their intended destination.
0857:             * <p>
0858:             * The <code>flush</code> method of <code>ConnectionBaseAdapter</code>
0859:             * does nothing.
0860:             *
0861:             * @exception  IOException  if an I/O error occurs.
0862:             */
0863:            protected void flush() throws IOException {
0864:                checkWritePermission();
0865:
0866:                ensureConnected();
0867:
0868:                fileHandler.flush();
0869:            }
0870:
0871:            /**
0872:             * Called once by each child input stream.
0873:             * If the input stream is marked open, it will be marked closed and
0874:             * the if the connection and output stream are closed the disconnect
0875:             * method will be called.
0876:             *
0877:             * @exception IOException if the subclass throws one
0878:             */
0879:            protected void closeInputStream() throws IOException {
0880:                maxIStreams++;
0881:                fileHandler.closeForRead();
0882:                super .closeInputStream();
0883:            }
0884:
0885:            /**
0886:             * Called once by each child output stream.
0887:             * If the output stream is marked open, it will be marked closed and
0888:             * the if the connection and input stream are closed the disconnect
0889:             * method will be called.
0890:             *
0891:             * @exception IOException if the subclass throws one
0892:             */
0893:            protected void closeOutputStream() throws IOException {
0894:                maxOStreams++;
0895:                flush();
0896:                fileHandler.closeForWrite();
0897:                super .closeOutputStream();
0898:            }
0899:
0900:            /**
0901:             * Free up the connection resources.
0902:             *
0903:             * @exception  IOException  if an I/O error occurs.
0904:             */
0905:            protected void disconnect() throws IOException {
0906:                try {
0907:                    if (fileHandler != null) {
0908:                        fileHandler.close();
0909:                    }
0910:                } finally {
0911:                    fileHandler = null;
0912:                }
0913:            }
0914:
0915:            // In order to compile against MIDP's ConnectionBaseAdapter
0916:            /**
0917:             * Establishes the connection.
0918:             * @param name URL path fragment
0919:             * @param mode access mode
0920:             * @param timeouts flag to indicate that timeouts allowed
0921:             * @throws IOException if an error occurs
0922:             */
0923:            protected void connect(String name, int mode, boolean timeouts)
0924:                    throws IOException {
0925:            }
0926:
0927:            /**
0928:             * Checks that the connection is already open.
0929:             * @throws IOException if the connection is closed
0930:             */
0931:            protected void ensureConnected() throws IOException {
0932:                if (!isRoot(fileRoot)) {
0933:                    throw new IOException("Root is not accessible");
0934:                }
0935:
0936:                if (fileHandler == null) {
0937:                    fileHandler = getFileHandler();
0938:
0939:                    fileHandler.connect(fileRoot, filePath + fileName);
0940:
0941:                    fileHandler.createPrivateDir(fileRoot);
0942:                }
0943:            }
0944:
0945:            /**
0946:             * Opens the file connection.
0947:             * @param name URL path fragment
0948:             * @param mode access mode
0949:             * @param timeouts flag to indicate that timeouts allowed
0950:             * @param unescape flag to indicate whether URL must be unescaped
0951:             * @return an opened Connection
0952:             * @throws IOException if some other kind of I/O error occurs.
0953:             */
0954:            private Connection openPrimImpl(String name, int mode,
0955:                    boolean timeouts, boolean unescape) throws IOException {
0956:
0957:                if (!name.startsWith("//")) {
0958:                    throw new IllegalArgumentException(
0959:                            "Missing protocol separator");
0960:                }
0961:
0962:                int rootStart = name.indexOf('/', 2);
0963:
0964:                if (rootStart == -1) {
0965:                    throw new IllegalArgumentException("Malformed File URL");
0966:                }
0967:
0968:                /* The string must be a valid URL path separated by "/" */
0969:
0970:                if (name.indexOf("/../", rootStart) != -1
0971:                        || name.indexOf("/./", rootStart) != -1
0972:                        || name.endsWith("/..") || name.endsWith("/.")
0973:                        || !"/".equals(sep)
0974:                        && name.indexOf(sep, rootStart) != -1
0975:                        || name.indexOf('\\') != -1) {
0976:                    throw new IllegalArgumentException(
0977:                            "/. or /.. is not supported "
0978:                                    + "or other illegal characters found");
0979:                }
0980:
0981:                if (unescape) {
0982:                    name = EscapedUtil.getUnescapedString(name);
0983:                }
0984:                String fileURL = "file:" + name;
0985:
0986:                // Perform security checks before any object state changes since
0987:                // this method is used not only by Connector.open() but
0988:                // by FileConnection.setFileConnection() too.
0989:                switch (mode) {
0990:                case Connector.READ:
0991:                    checkReadPermission(fileURL, mode);
0992:                    maxOStreams = 0;
0993:                    break;
0994:                case Connector.WRITE:
0995:                    checkWritePermission(fileURL, mode);
0996:                    maxIStreams = 0;
0997:                    break;
0998:                case Connector.READ_WRITE:
0999:                    checkReadPermission(fileURL, mode);
1000:                    checkWritePermission(fileURL, mode);
1001:                    break;
1002:                default:
1003:                    throw new IllegalArgumentException("Invalid mode");
1004:                }
1005:
1006:                this .fileURL = fileURL;
1007:                this .mode = mode;
1008:
1009:                int nameLength = name.length();
1010:                int pathStart = name.indexOf('/', rootStart + 1);
1011:
1012:                if (pathStart == -1) {
1013:                    throw new IllegalArgumentException("Root is not specified");
1014:                }
1015:
1016:                if (pathStart == (nameLength - 1)) {
1017:                    fileName = "";
1018:                    fileRoot = name.substring(rootStart + 1);
1019:                    filePath = name.substring(rootStart);
1020:                } else {
1021:                    fileRoot = name.substring(rootStart + 1, pathStart + 1);
1022:
1023:                    int fileStart = name.lastIndexOf('/', nameLength - 2);
1024:
1025:                    if (fileStart <= pathStart) {
1026:                        fileName = name.substring(pathStart + 1);
1027:                        filePath = name.substring(rootStart, pathStart + 1);
1028:                    } else {
1029:                        filePath = name.substring(rootStart, fileStart + 1);
1030:                        fileName = name.substring(fileStart + 1);
1031:                    }
1032:                }
1033:
1034:                connectionOpen = true;
1035:                return this ;
1036:            }
1037:
1038:            /**
1039:             * Checks if path is a root path.
1040:             * @param root path to be checked
1041:             * @return <code>true</code> if path is a root,
1042:             *                <code>false</code> otherwise.
1043:             */
1044:            private boolean isRoot(String root) {
1045:                Vector r = listRoots(); // retrieve up-to-date list of mounted roots
1046:                for (int i = 0; i < r.size(); i++) {
1047:                    String name = (String) r.elementAt(i);
1048:                    if (name.equals(root)) {
1049:                        return true;
1050:                    }
1051:                }
1052:                return false;
1053:            }
1054:
1055:            /**
1056:             * Checks that the connection is already open and connected.
1057:             * @throws ConnectionClosedException if the connection is closed
1058:             * @throws IOException if any error occurs while connecting
1059:             */
1060:            protected void ensureOpenAndConnected() throws IOException {
1061:                if (!isOpen()) {
1062:                    throw new ConnectionClosedException("Connection is closed");
1063:                }
1064:
1065:                ensureConnected();
1066:            }
1067:
1068:            /**
1069:             * Checks that the application has permission to read.
1070:             * @param fileURL complete file URL
1071:             * @param mode access mode
1072:             * @throws InterruptedIOException if the permission dialog is
1073:             *                                terminated before completed
1074:             * @throws SecurityException if read is not allowed
1075:             * @throws IllegalModeException if connection is write only
1076:             */
1077:            private final void checkReadPermission(String fileURL, int mode)
1078:                    throws InterruptedIOException {
1079:
1080:                if (classSecurityToken == null) { // FC permission
1081:                    MIDletSuite suite = Scheduler.getScheduler()
1082:                            .getMIDletSuite();
1083:
1084:                    try {
1085:                        suite.checkForPermission(
1086:                                Permissions.FILE_CONNECTION_READ, fileURL);
1087:                    } catch (InterruptedException ie) {
1088:                        throw new InterruptedIOException(
1089:                                "Interrupted while trying to ask the user permission");
1090:                    }
1091:                } else { // call from PIM
1092:                    classSecurityToken
1093:                            .checkIfPermissionAllowed(Permissions.FILE_CONNECTION_READ);
1094:                }
1095:
1096:                if (mode == Connector.WRITE) {
1097:                    throw new IllegalModeException("Connection is write only");
1098:                }
1099:            }
1100:
1101:            /**
1102:             * Checks that the application has permission to read.
1103:             * @throws InterruptedIOException if the permission dialog is
1104:             *                                terminated before completed
1105:             * @throws SecurityException if read is not allowed
1106:             * @throws IllegalModeException if connection is write only
1107:             */
1108:            protected final void checkReadPermission()
1109:                    throws InterruptedIOException {
1110:                checkReadPermission(fileURL, mode);
1111:            }
1112:
1113:            /**
1114:             * Checks that the application has permission to read the root path.
1115:             * @throws InterruptedIOException if the permission dialog is
1116:             * terminated before completed
1117:             * @throws SecurityException if read is not allowed
1118:             * @throws IllegalModeException if connection is write only
1119:             */
1120:            protected final void checkRootReadPermission()
1121:                    throws InterruptedIOException {
1122:
1123:                if (classSecurityToken == null) { // FC permission
1124:                    MIDletSuite suite = Scheduler.getScheduler()
1125:                            .getMIDletSuite();
1126:
1127:                    try {
1128:                        suite.checkForPermission(
1129:                                Permissions.FILE_CONNECTION_READ, "file://"
1130:                                        + fileRoot);
1131:                    } catch (InterruptedException ie) {
1132:                        throw new InterruptedIOException(
1133:                                "Interrupted while trying to ask the user permission");
1134:                    }
1135:                } else { // call from PIM
1136:                    classSecurityToken
1137:                            .checkIfPermissionAllowed(Permissions.FILE_CONNECTION_READ);
1138:                }
1139:
1140:                if (mode == Connector.WRITE) {
1141:                    throw new IllegalModeException("Connection is write only");
1142:                }
1143:            }
1144:
1145:            /**
1146:             * Checks that the application has permission to write.
1147:             * @param fileURL complete file URL
1148:             * @param mode access mode
1149:             * @throws InterruptedIOException if the permission dialog is
1150:             * terminated before completed
1151:             * @throws SecurityException if write is not allowed
1152:             * @throws IllegalModeException if connection is read only
1153:             */
1154:            private final void checkWritePermission(String fileURL, int mode)
1155:                    throws InterruptedIOException {
1156:
1157:                if (classSecurityToken == null) { // FC permission
1158:                    MIDletSuite suite = Scheduler.getScheduler()
1159:                            .getMIDletSuite();
1160:
1161:                    try {
1162:                        suite.checkForPermission(
1163:                                Permissions.FILE_CONNECTION_WRITE, fileURL);
1164:                    } catch (InterruptedException ie) {
1165:                        throw new InterruptedIOException(
1166:                                "Interrupted while trying to ask the user permission");
1167:                    }
1168:                } else { // call from PIM
1169:                    classSecurityToken
1170:                            .checkIfPermissionAllowed(Permissions.FILE_CONNECTION_WRITE);
1171:                }
1172:
1173:                if (mode == Connector.READ) {
1174:                    throw new IllegalModeException("Connection is read only");
1175:                }
1176:            }
1177:
1178:            /**
1179:             * Checks that the application has permission to write.
1180:             * @throws InterruptedIOException if the permission dialog is
1181:             *                                terminated before completed
1182:             * @throws SecurityException if write is not allowed
1183:             * @throws IllegalModeException if connection is read only
1184:             */
1185:            protected final void checkWritePermission()
1186:                    throws InterruptedIOException {
1187:                checkWritePermission(fileURL, mode);
1188:            }
1189:
1190:            /**
1191:             * Gets an array of file system roots.
1192:             * @return up-to-date array of file system roots;
1193:             *         empty array is returned if there are no roots available.
1194:             */
1195:            public static Vector listRoots() {
1196:                BaseFileHandler fh = getFileHandler();
1197:                return fh.listRoots();
1198:            }
1199:
1200:            /**
1201:             * Gets a filtered list of files and directories contained in a directory.
1202:             * The directory is the connection's target as specified in
1203:             * <code>Connector.open()</code>.
1204:             *
1205:             * @param   filter String against which all files and directories are
1206:             *          matched for retrieval.  An asterisk ("*") can be used as a
1207:             *          wildcard to represent 0 or more occurrences of any character.
1208:             * @param   includeHidden boolean indicating whether files marked as hidden
1209:             *          should be included or not in the list of files and directories
1210:             *          returned.
1211:             * @return  An Enumeration of strings, denoting the files and directories
1212:             *          in the directory matching the filter. Directories are denoted
1213:             *          with a trailing slash "/" in their returned name.  The
1214:             *          Enumeration has zero length if the directory is empty or no
1215:             *      files and/or directories are found matching the given filter.
1216:             *      Any current directory indication (".") and any parent directory
1217:             *      indication ("..") is not included in the list of files and
1218:             *      directories returned.
1219:             * @exception  SecurityException if the security of the application does
1220:             *          not have read access for the directory.
1221:             * @exception  IllegalModeException if the application does have read
1222:             *          access
1223:             *          to the connection's target but has opened the connection in
1224:             *          <code>Connector.WRITE</code> mode.
1225:             * @exception  IOException if invoked on a file, the directory does not
1226:             *      exists, the directory is not accessible, or an I/O error occurs.
1227:             * @exception  ConnectionClosedException if the connection is closed.
1228:             * @exception  IllegalArgumentException if filter contains any path
1229:             *      specification or is an invalid filename for the platform
1230:             *      (e.g. contains characters invalid for a filename on the
1231:             *          platform).
1232:             */
1233:            private Enumeration listInternal(String filter,
1234:                    boolean includeHidden) throws IOException {
1235:                checkReadPermission();
1236:
1237:                ensureOpenAndConnected();
1238:
1239:                if (filter != null) {
1240:                    if (filter.indexOf('/') != -1) {
1241:                        throw new IllegalArgumentException(
1242:                                "Filter contains any path specification");
1243:                    }
1244:
1245:                    String illegalChars = fileHandler.illegalFileNameChars();
1246:                    for (int i = 0; i < illegalChars.length(); i++) {
1247:                        if (filter.indexOf(illegalChars.charAt(i)) != -1) {
1248:                            throw new IllegalArgumentException(
1249:                                    "Filter contains characters "
1250:                                            + "invalid for a filename");
1251:                        }
1252:                    }
1253:                }
1254:
1255:                return fileHandler.list(filter, includeHidden).elements();
1256:            }
1257:
1258:            /**
1259:             * Gets the file handler.
1260:             * @return handle to current file connection
1261:             */
1262:            private static BaseFileHandler getFileHandler() {
1263:                String def = "com.sun.midp.io.j2me.file.DefaultFileHandler";
1264:                String n = null;
1265:                if (hasOtherFileHandler) {
1266:                    n = Configuration
1267:                            .getProperty("com.sun.midp.io.j2me.fileHandlerImpl");
1268:                    if (n == null) {
1269:                        hasOtherFileHandler = false;
1270:                    }
1271:                }
1272:                if (hasOtherFileHandler) {
1273:                    try {
1274:                        return (BaseFileHandler) (Class.forName(n))
1275:                                .newInstance();
1276:                    } catch (ClassNotFoundException e) {
1277:                        hasOtherFileHandler = false;
1278:                    } catch (Error e) {
1279:                        hasOtherFileHandler = false;
1280:                    } catch (IllegalAccessException e) {
1281:                        hasOtherFileHandler = false;
1282:                    } catch (InstantiationException e) {
1283:                        hasOtherFileHandler = false;
1284:                    }
1285:                }
1286:                try {
1287:                    return (BaseFileHandler) (Class.forName(def)).newInstance();
1288:                } catch (ClassNotFoundException e) {
1289:                } catch (Error e) {
1290:                } catch (IllegalAccessException e) {
1291:                } catch (InstantiationException e) {
1292:                }
1293:                throw new Error("Unable to create FileConnection Handler");
1294:            }
1295:        }
1296:
1297:        /**
1298:         * Utility for escaped character handling.
1299:         */
1300:        class EscapedUtil {
1301:            /**
1302:             * Gets the escaped string.
1303:             * @param name string to be processed
1304:             * @return escaped string
1305:             * @throws IllegalArgumentException if encoding not supported
1306:             */
1307:            public static String getEscapedString(String name) {
1308:                try {
1309:                    if (name == null) {
1310:                        return null;
1311:                    }
1312:                    byte newName[] = new byte[name.length() * 12];
1313:                    int nextPlace = 0;
1314:                    for (int i = 0; i < name.length(); i++) {
1315:                        char c = name.charAt(i);
1316:                        if (containsReserved(c)) {
1317:                            char data[] = { c };
1318:                            byte[] reservedBytes = new String(data)
1319:                                    .getBytes("utf-8");
1320:                            for (int j = 0; j < reservedBytes.length; j++) {
1321:                                newName[nextPlace++] = '%';
1322:                                byte upper = (byte) ((reservedBytes[j] >> 4) & 0xF);
1323:                                if (upper <= 9) {
1324:                                    newName[nextPlace++] = (byte) ('0' + upper);
1325:                                } else {
1326:                                    newName[nextPlace++] = (byte) ('A' + (upper - 10));
1327:                                }
1328:                                byte lower = (byte) (reservedBytes[j] & 0xF);
1329:                                if (lower <= 9) {
1330:                                    newName[nextPlace++] = (byte) ('0' + lower);
1331:                                } else {
1332:                                    newName[nextPlace++] = (byte) ('A' + (lower - 10));
1333:                                }
1334:                            }
1335:                        } else {
1336:                            newName[nextPlace++] = (byte) c;
1337:                        }
1338:                    }
1339:                    return new String(newName, 0, nextPlace);
1340:                } catch (UnsupportedEncodingException uee) {
1341:                    throw new IllegalArgumentException(uee.getMessage());
1342:                }
1343:            }
1344:
1345:            /**
1346:             * Gets the unescaped string.
1347:             * <pre>
1348:             *   escaped   = "%" hex hex
1349:             *   hex       = digit | "A" | "B" | "C" | "D" | "E" | "F" |
1350:             *                       "a" | "b" | "c" | "d" | "e" | "f"
1351:             * </pre>
1352:             * @param name string to be processed
1353:             * @return escaped string
1354:             * @throws IllegalArgumentException if encoding not supported
1355:             *
1356:             */
1357:            public static String getUnescapedString(String name) {
1358:                try {
1359:                    if (name == null) {
1360:                        return null;
1361:                    }
1362:                    if (name.indexOf("%") == -1) {
1363:                        return name;
1364:                    } else {
1365:                        byte newName[] = new byte[name.length()];
1366:                        int nextPlace = 0;
1367:                        for (int i = 0; i < name.length(); i++) {
1368:                            char c = name.charAt(i);
1369:                            if (c == '%') {
1370:                                String hexNum = name.substring(i + 1, i + 3)
1371:                                        .toUpperCase();
1372:                                if (isHexCharsLegal(hexNum)) {
1373:                                    c = hexToChar(hexNum);
1374:                                    i = i + 2;
1375:                                } else {
1376:                                    throw new IllegalArgumentException(
1377:                                            "Bad format");
1378:                                }
1379:                            } else if (containsReserved(c)) {
1380:                                throw new IllegalArgumentException(
1381:                                        "Bad escaped format");
1382:                            }
1383:                            newName[nextPlace++] = (byte) c;
1384:                        }
1385:                        return new String(newName, 0, nextPlace, "UTF-8");
1386:                    }
1387:                } catch (UnsupportedEncodingException uee) {
1388:                    throw new IllegalArgumentException(uee.getMessage());
1389:                }
1390:            }
1391:
1392:            /**
1393:             * Checks if the hexadecimal character is valid.
1394:             * @param hexValue string to be checked
1395:             * @return <code>true</code> if all characters are valid
1396:             */
1397:            private static boolean isHexCharsLegal(String hexValue) {
1398:                if ((isDigit(hexValue.charAt(0)) || isABCDEF(hexValue.charAt(0)))
1399:                        && (isDigit(hexValue.charAt(1)) || isABCDEF(hexValue
1400:                                .charAt(1)))) {
1401:                    return true;
1402:                } else {
1403:                    return false;
1404:                }
1405:
1406:            }
1407:
1408:            /**
1409:             * Converts one hexadecimal char.
1410:             * @param hexValue string to be processed
1411:             * @return normalized hex value
1412:             */
1413:            private static char hexToChar(String hexValue) {
1414:                char c = 0;
1415:                if (isDigit(hexValue.charAt(0))) {
1416:                    c += (hexValue.charAt(0) - '0') * 16;
1417:                } else {
1418:                    c += (hexValue.charAt(0) - 'A' + 10) * 16;
1419:                }
1420:
1421:                if (isDigit(hexValue.charAt(1))) {
1422:                    c += (hexValue.charAt(01) - '0');
1423:                } else {
1424:                    c += (hexValue.charAt(1) - 'A' + 10);
1425:                }
1426:                return c;
1427:            }
1428:
1429:            /**
1430:             * Checks if character is decimal digit.
1431:             * @param c character to check
1432:             * @return <code>true</code> if in the range 0..9
1433:             */
1434:            private static boolean isDigit(char c) {
1435:                return (c >= '0' && c <= '9');
1436:            }
1437:
1438:            /**
1439:             * Checks if character is hexadecimal digit.
1440:             * @param c character to check
1441:             * @return  <code>true</code> if in the range A..F
1442:             */
1443:            private static boolean isABCDEF(char c) {
1444:                return (c >= 'A' && c <= 'F');
1445:            }
1446:
1447:            /**
1448:             * Checks if character is from the reserved character set.
1449:             * @param c character to check
1450:             * @return  <code>true</code> if not in the range A..Z,
1451:             * a..z,..9, or punctuation (forward slash, colon, hyphen,
1452:             * under score, period, exclamation, tilde, asterisk, single quote,
1453:             * left paren or right paren).
1454:             */
1455:            private static boolean containsReserved(char c) {
1456:                return !((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')
1457:                        || (c >= '0' && c <= '9') || ("/:-_.!~*'()".indexOf(c) != -1));
1458:            }
1459:
1460:        } // End  of EscapeUtil
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.