Source Code Cross Referenced for FtpSession.java in  » IDE » J » org » armedbear » j » 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 » IDE » J » org.armedbear.j 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * FtpSession.java
0003:         *
0004:         * Copyright (C) 1998-2003 Peter Graves
0005:         * $Id: FtpSession.java,v 1.4 2003/05/25 13:43:17 piso Exp $
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
0009:         * as published by the Free Software Foundation; either version 2
0010:         * of the License, or (at your option) any later version.
0011:         *
0012:         * This program is distributed in the hope that it will be useful,
0013:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0015:         * GNU General Public License for more details.
0016:         *
0017:         * You should have received a copy of the GNU General Public License
0018:         * along with this program; if not, write to the Free Software
0019:         * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
0020:         */
0021:
0022:        package org.armedbear.j;
0023:
0024:        import java.io.BufferedReader;
0025:        import java.io.IOException;
0026:        import java.io.InputStream;
0027:        import java.io.InputStreamReader;
0028:        import java.io.OutputStream;
0029:        import java.io.OutputStreamWriter;
0030:        import java.io.StringReader;
0031:        import java.net.InetAddress;
0032:        import java.net.ServerSocket;
0033:        import java.net.Socket;
0034:        import java.net.SocketException;
0035:        import java.util.Random;
0036:        import java.util.StringTokenizer;
0037:        import java.util.Vector;
0038:        import javax.swing.SwingUtilities;
0039:
0040:        public class FtpSession implements  Constants {
0041:            private static final boolean echo = true;
0042:            private static final Vector sessionList = new Vector();
0043:
0044:            private static CleanupThread cleanupThread;
0045:
0046:            private String host;
0047:            private int port;
0048:            private String user;
0049:            private String password;
0050:            private String loginDirectory;
0051:            private String currentDirectory;
0052:            private Socket controlSocket;
0053:            private BufferedReader controlIn;
0054:            private OutputStreamWriter controlOut;
0055:            private ServerSocket serverSocket;
0056:            private Socket dataSocket;
0057:            private InputStream dataIn;
0058:            private OutputStream dataOut;
0059:            private boolean connected;
0060:            private boolean usePassiveMode = true;
0061:            private String errorText;
0062:            private ProgressNotifier progressNotifier;
0063:            private boolean locked;
0064:
0065:            private FtpSession() {
0066:                register(this );
0067:            }
0068:
0069:            private FtpSession(Login login, int port) {
0070:                host = login.host;
0071:                user = login.user;
0072:                password = login.password;
0073:                this .port = port;
0074:                usePassiveMode = Editor.preferences().getBooleanProperty(
0075:                        Property.FTP_USE_PASSIVE_MODE);
0076:                register(this );
0077:            }
0078:
0079:            private static synchronized void register(FtpSession session) {
0080:                sessionList.add(session);
0081:                if (cleanupThread == null) {
0082:                    cleanupThread = new CleanupThread(cleanupRunnable);
0083:                    cleanupThread.start();
0084:                }
0085:            }
0086:
0087:            private static synchronized void unregister(FtpSession session) {
0088:                if (!sessionList.contains(session))
0089:                    Debug.bug();
0090:                sessionList.remove(session);
0091:            }
0092:
0093:            protected Object clone() {
0094:                FtpSession session = new FtpSession();
0095:                session.host = host;
0096:                session.user = user;
0097:                session.password = password;
0098:                session.port = port;
0099:                session.usePassiveMode = usePassiveMode;
0100:                return session;
0101:            }
0102:
0103:            public final String getHost() {
0104:                return host;
0105:            }
0106:
0107:            public final String getErrorText() {
0108:                return errorText;
0109:            }
0110:
0111:            public final String getLoginDirectory() {
0112:                return loginDirectory;
0113:            }
0114:
0115:            public final void setProgressNotifier(
0116:                    ProgressNotifier progressNotifier) {
0117:                this .progressNotifier = progressNotifier;
0118:            }
0119:
0120:            public final boolean isLocked() {
0121:                return locked;
0122:            }
0123:
0124:            private synchronized boolean lock() {
0125:                if (locked)
0126:                    return false;
0127:                locked = true;
0128:                return true;
0129:            }
0130:
0131:            public synchronized void unlock() {
0132:                if (locked) {
0133:                    progressNotifier = null;
0134:                    locked = false;
0135:                } else
0136:                    Debug.bug("FtpSession.unlock session was not locked");
0137:            }
0138:
0139:            private boolean changeDirectory(String dirname) {
0140:                if (dirname.equals(currentDirectory))
0141:                    return true;
0142:                command("CWD " + dirname);
0143:                String s = getReplyString();
0144:                int code = getCode(s);
0145:                if (code == 421) {
0146:                    connect();
0147:                    if (connected) {
0148:                        command("CWD " + dirname);
0149:                        s = getReplyString();
0150:                    } else
0151:                        return false;
0152:                }
0153:                if (getCode(s) == 250) {
0154:                    currentDirectory = dirname;
0155:                    return true;
0156:                }
0157:                return false;
0158:            }
0159:
0160:            public boolean isDirectory(String remotePath) {
0161:                if (changeDirectory(remotePath))
0162:                    return true;
0163:
0164:                return false;
0165:            }
0166:
0167:            public boolean isFile(String remotePath) {
0168:                command("SIZE " + remotePath);
0169:                String s = getReplyString();
0170:                int code = getCode(s);
0171:                if (code == 213)
0172:                    return true;
0173:                if (code == 500) {
0174:                    // "SIZE" command was not recognized.
0175:                    String listing = getDirectoryListingForFile(remotePath);
0176:                    if (listing != null && listing.length() > 0) {
0177:                        char c = listing.charAt(0);
0178:                        if (c == '-' || c == 'l')
0179:                            return true;
0180:                    }
0181:                }
0182:                return false;
0183:            }
0184:
0185:            public boolean exists(String remotePath) {
0186:                if (isDirectory(remotePath))
0187:                    return true;
0188:                else
0189:                    return isFile(remotePath);
0190:            }
0191:
0192:            private long getFileSize(String remotePath) {
0193:                long fileSize = -1;
0194:                command("SIZE " + remotePath);
0195:                String s = getReplyString();
0196:                if (getCode(s) == 213) {
0197:                    s = s.substring(3).trim();
0198:                    try {
0199:                        fileSize = Long.parseLong(s);
0200:                    } catch (NumberFormatException e) {
0201:                        Log.error(e);
0202:                    }
0203:                }
0204:                return fileSize;
0205:            }
0206:
0207:            boolean deleteFile(String remotePath) {
0208:                command("DELE " + remotePath);
0209:                return getReply() == 250;
0210:            }
0211:
0212:            boolean removeDirectory(String remotePath) {
0213:                command("RMD " + remotePath);
0214:                return getReply() == 250;
0215:            }
0216:
0217:            public boolean chmod(FtpFile file, int permissions) {
0218:                if (permissions != 0) {
0219:                    FastStringBuffer sb = new FastStringBuffer("SITE CHMOD ");
0220:                    sb.append(Integer.toString(permissions, 8));
0221:                    sb.append(' ');
0222:                    sb.append(file.canonicalPath());
0223:                    command(sb.toString());
0224:                    return getReply() == 200;
0225:                } else
0226:                    return false;
0227:            }
0228:
0229:            public int getPermissions(FtpFile file) {
0230:                int permissions = 0;
0231:                String listing = getDirectoryListingForFile(file
0232:                        .canonicalPath());
0233:                if (listing != null) {
0234:                    String s = listing.substring(1, 10);
0235:                    Log.debug("s = |" + s + "|");
0236:                    if (s.length() == 9) {
0237:                        if (s.charAt(0) == 'r')
0238:                            permissions += 0400;
0239:                        if (s.charAt(1) == 'w')
0240:                            permissions += 0200;
0241:                        if (s.charAt(2) == 'x')
0242:                            permissions += 0100;
0243:                        if (s.charAt(3) == 'r')
0244:                            permissions += 040;
0245:                        if (s.charAt(4) == 'w')
0246:                            permissions += 020;
0247:                        if (s.charAt(5) == 'x')
0248:                            permissions += 010;
0249:                        if (s.charAt(6) == 'r')
0250:                            permissions += 4;
0251:                        if (s.charAt(7) == 'w')
0252:                            permissions += 2;
0253:                        if (s.charAt(8) == 'x')
0254:                            permissions += 1;
0255:                    }
0256:                }
0257:                return permissions;
0258:            }
0259:
0260:            int getFileStatus(String filename) {
0261:                if (!connected) {
0262:                    connect();
0263:                    if (!connected)
0264:                        return -1;
0265:                }
0266:                if (changeDirectory(filename))
0267:                    return 2; // It's a directory.
0268:                // Not a directory.
0269:                if (!openDataSocket())
0270:                    return -1;
0271:                int status = -1; // Not found or unknown status.
0272:                command("LIST " + filename);
0273:                int code = getReply();
0274:                // 125 Data connection already open, transfer starting
0275:                // 150 Opening ASCII mode data connection for file list
0276:                // 226 Transfer complete
0277:                if (code == 125 || code == 150 || code == 226) {
0278:                    String s = getData();
0279:                    closeDataSocket();
0280:                    // Look for "drwxrwxrwx"...
0281:                    if (s != null && s.length() > 10) {
0282:                        char c = s.charAt(0);
0283:                        if (c == 'd')
0284:                            status = 2; // Shouldn't happen, since changeDirectory failed.
0285:                        else if (c == '-')
0286:                            status = 1;
0287:                        if (status != -1) {
0288:                            // Sanity checking.
0289:                            boolean valid = true;
0290:                            c = s.charAt(1);
0291:                            if (c != 'r' && c != 'w' && c != '-')
0292:                                valid = false;
0293:                            else {
0294:                                c = s.charAt(2);
0295:                                if (c != 'r' && c != 'w' && c != '-')
0296:                                    valid = false;
0297:                            }
0298:                            if (!valid)
0299:                                status = -1;
0300:                        }
0301:                    }
0302:                    // 125 Data connection already open, transfer starting
0303:                    // 150 Opening ASCII mode data connection for file list
0304:                    // 226 Transfer complete
0305:                    if (code == 125 || code == 150)
0306:                        getReply(226);
0307:                }
0308:                return status;
0309:            }
0310:
0311:            public String getDirectoryListing(File file) {
0312:                if (!(file instanceof  FtpFile)) {
0313:                    Debug.bug();
0314:                    return null;
0315:                }
0316:                Debug.assertTrue(isLocked());
0317:                String listing = DirectoryCache.getDirectoryCache().getListing(
0318:                        file);
0319:                if (listing == null) {
0320:                    listing = getDirectoryListing(file.canonicalPath());
0321:                    if (listing != null)
0322:                        DirectoryCache.getDirectoryCache().put(file, listing);
0323:                }
0324:                return listing;
0325:            }
0326:
0327:            public String getDirectoryListing(String dirname) {
0328:                Debug.assertTrue(isLocked());
0329:                String listing = null;
0330:                if (verifyConnected()) {
0331:                    if (changeDirectory(dirname)) {
0332:                        if (openDataSocket()) {
0333:                            command("LIST -la");
0334:                            int code = getReply();
0335:
0336:                            // 125 Data connection already open, transfer starting
0337:                            // 150 Opening ASCII mode data connection for file list
0338:                            // 226 Transfer complete
0339:                            if (code == 125 || code == 150 || code == 226)
0340:                                listing = getData();
0341:
0342:                            closeDataSocket();
0343:                            if (code == 125 || code == 150)
0344:                                getReply(226);
0345:                        }
0346:                    }
0347:                }
0348:                return listing;
0349:            }
0350:
0351:            public String getDirectoryListingForFile(String filename) {
0352:                String listing = null;
0353:                if (connected) {
0354:                    if (openDataSocket()) {
0355:                        command("LIST -la " + filename);
0356:                        int code = getReply();
0357:
0358:                        // 125 Data connection already open, transfer starting
0359:                        // 150 Opening ASCII mode data connection for file list
0360:                        // 226 Transfer complete
0361:                        if (code == 125 || code == 150 || code == 226)
0362:                            listing = getData();
0363:
0364:                        closeDataSocket();
0365:                        if (code == 125 || code == 150)
0366:                            getReply(226);
0367:                    }
0368:                }
0369:
0370:                // With at least some FTP servers (ProFTP 1.2.0pre9) the listing
0371:                // will be empty if any part of the filename contains any space
0372:                // characters, although CWD works fine.
0373:
0374:                // If that happens we CWD into the parent directory, list all the
0375:                // files, and pick out the line of interest with a regular expression.
0376:
0377:                // We check the listing again to make sure the file hasn't changed
0378:                // on the server when we go to write out a modified version.
0379:
0380:                if (listing == null || listing.length() == 0) {
0381:                    int index = filename.lastIndexOf('/');
0382:                    if (index >= 0) {
0383:                        String parent = index == 0 ? "/" : filename.substring(
0384:                                0, index);
0385:                        String name = filename.substring(index + 1);
0386:                        String parentListing = getDirectoryListing(parent);
0387:                        if (parentListing != null) {
0388:                            BufferedReader reader = new BufferedReader(
0389:                                    new StringReader(parentListing));
0390:                            String entry;
0391:                            try {
0392:                                while ((entry = reader.readLine()) != null) {
0393:                                    if (name.equals(DirectoryEntry
0394:                                            .getName(entry))) {
0395:                                        // Found it!
0396:                                        listing = entry;
0397:                                        break;
0398:                                    }
0399:                                }
0400:                            } catch (IOException e) {
0401:                                Log.error(e);
0402:                            }
0403:                        }
0404:                    }
0405:                }
0406:
0407:                Log.debug("getDirectoryListingForFile |" + listing + "|");
0408:                return listing;
0409:            }
0410:
0411:            public int put(File localFile, File remoteFile, long fileSize,
0412:                    boolean saveInPlace) {
0413:                boolean succeeded = false;
0414:                boolean cancelled = false;
0415:                String tempName = null;
0416:
0417:                // Change directory to prove parent directory exists.
0418:                if (changeDirectory(remoteFile.getParent())) {
0419:                    OutputStream out = null;
0420:                    if (saveInPlace) {
0421:                        out = getOutputStreamForFile(remoteFile.canonicalPath());
0422:                    } else {
0423:                        // It would be nice to use STOU here, but most servers don't
0424:                        // implement it.
0425:                        tempName = getUniqueName(remoteFile.getParentFile());
0426:                        Log.debug("tempName = |" + tempName + "|");
0427:                        if (tempName != null)
0428:                            out = getOutputStreamForFile(tempName);
0429:                    }
0430:                    if (out != null) {
0431:                        try {
0432:                            InputStream in = localFile.getInputStream();
0433:                            byte[] bytes = new byte[16384];
0434:                            long totalBytes = 0;
0435:                            int bytesRead;
0436:                            if (progressNotifier != null)
0437:                                progressNotifier.progressStart();
0438:                            while ((bytesRead = in.read(bytes)) > 0) {
0439:                                out.write(bytes, 0, bytesRead);
0440:                                totalBytes += bytesRead;
0441:                                if (progressNotifier != null) {
0442:                                    if (progressNotifier.cancelled()) {
0443:                                        cancelled = true;
0444:                                        break;
0445:                                    }
0446:                                    progressNotifier.progress("Sent ",
0447:                                            totalBytes, fileSize);
0448:                                }
0449:                                // Slow things down for debugging, maybe.
0450:                                Debug.throttle();
0451:                            }
0452:                            if (progressNotifier != null)
0453:                                progressNotifier.progressStop();
0454:                            out.flush();
0455:                            out.close();
0456:                            closeDataSocket();
0457:                            in.close();
0458:                            succeeded = getReply(226);
0459:                            if (cancelled && tempName != null) {
0460:                                command("DELE " + tempName);
0461:                                getReplyString(); // Ignore reply.
0462:                            }
0463:                        } catch (Exception e) {
0464:                            Log.error(e);
0465:                        }
0466:                    }
0467:                }
0468:
0469:                if (succeeded && !cancelled && tempName != null) {
0470:                    do {
0471:                        if (progressNotifier != null)
0472:                            progressNotifier.setText("Renaming temporary file");
0473:                        command("RNFR " + tempName);
0474:                        if (!getReply(350)) {
0475:                            succeeded = false;
0476:                            break;
0477:                        }
0478:                        command("RNTO " + remoteFile.canonicalPath());
0479:                        if (!getReply(250))
0480:                            succeeded = false;
0481:                        break;
0482:                    } while (false);
0483:                }
0484:
0485:                if (progressNotifier != null) {
0486:                    if (cancelled)
0487:                        progressNotifier.setText("Transfer cancelled");
0488:                    else if (succeeded)
0489:                        progressNotifier.setText("Transfer completed");
0490:                    else
0491:                        progressNotifier.setText("Transfer failed");
0492:                }
0493:
0494:                if (cancelled)
0495:                    return CANCELLED;
0496:                else if (succeeded)
0497:                    return SUCCESS;
0498:                else
0499:                    return ERROR;
0500:            }
0501:
0502:            private static Random random;
0503:
0504:            private String getUniqueName(File dir) {
0505:                long now = System.currentTimeMillis();
0506:                if (random == null) {
0507:                    // Use uptime as seed.
0508:                    random = new Random(now - Editor.getStartTimeMillis());
0509:                }
0510:                long n = now + Math.abs(random.nextLong() % now);
0511:                for (int i = 0; i < 100; i++) {
0512:                    File file = File.getInstance(dir, String.valueOf(n));
0513:                    String name = file.canonicalPath();
0514:                    if (!exists(name)) {
0515:                        Log.debug("unique name = |" + name + "|");
0516:                        return name;
0517:                    }
0518:                    n += Math.abs(random.nextLong() % now);
0519:                }
0520:                return null;
0521:            }
0522:
0523:            public int get(File remoteFile, File localFile, long fileSize) {
0524:                boolean succeeded = false;
0525:                boolean cancelled = false;
0526:                if (fileSize == 0) {
0527:                    fileSize = getFileSize(remoteFile.canonicalPath());
0528:                    if (fileSize < 0) // Error.
0529:                        fileSize = 0;
0530:                }
0531:                InputStream in = getInputStreamForFile(remoteFile
0532:                        .canonicalPath());
0533:                if (in == null)
0534:                    return ERROR;
0535:                try {
0536:                    OutputStream out = localFile.getOutputStream();
0537:                    byte[] bytes = new byte[16384];
0538:                    long totalBytes = 0;
0539:
0540:                    if (progressNotifier != null)
0541:                        progressNotifier.progressStart();
0542:
0543:                    while (true) {
0544:                        int bytesRead = 0;
0545:                        try {
0546:                            // We may get an exception here if user cancels.
0547:                            bytesRead = in.read(bytes);
0548:                        } catch (Exception e) {
0549:                            if (progressNotifier == null
0550:                                    || !progressNotifier.cancelled())
0551:                                Log.error(e);
0552:                            else
0553:                                // Exception is expected.
0554:                                Log.debug("FtpSession.get cancelled");
0555:                        }
0556:                        if (bytesRead <= 0)
0557:                            break;
0558:                        out.write(bytes, 0, bytesRead);
0559:                        totalBytes += bytesRead;
0560:                        if (progressNotifier != null) {
0561:                            if (progressNotifier.cancelled()) {
0562:                                cancelled = true;
0563:                                break;
0564:                            }
0565:                            progressNotifier.progress("Received ", totalBytes,
0566:                                    fileSize);
0567:                        }
0568:                        // Slow things down for debugging, maybe.
0569:                        Debug.throttle();
0570:                    }
0571:                    if (progressNotifier != null)
0572:                        progressNotifier.progressStop();
0573:                    // If the user cancels, just close the data connection.
0574:                    // A bit rude, but it seems to work.
0575:                    out.flush();
0576:                    out.close();
0577:                    in.close();
0578:                    closeDataSocket();
0579:                    if (cancelled)
0580:                        localFile.delete();
0581:                    succeeded = getReply(226);
0582:                } catch (SocketException e) {
0583:                    if (cancelled)
0584:                        ; // Exception is expected in this case.
0585:                    else
0586:                        Log.error(e);
0587:                } catch (Exception e) {
0588:                    Log.error(e);
0589:                }
0590:                if (progressNotifier != null) {
0591:                    if (cancelled)
0592:                        progressNotifier.setText("Transfer cancelled");
0593:                    else if (succeeded)
0594:                        progressNotifier.setText("Transfer completed");
0595:                    else
0596:                        progressNotifier.setText("Transfer failed");
0597:                }
0598:                if (cancelled)
0599:                    return CANCELLED;
0600:                else if (succeeded)
0601:                    return SUCCESS;
0602:                else
0603:                    return ERROR;
0604:            }
0605:
0606:            public synchronized boolean verifyConnected() {
0607:                if (connected) {
0608:                    command("NOOP");
0609:                    if (getReply() == 421) {
0610:                        Log.debug("verifyConnected calling connect");
0611:                        connect();
0612:                    }
0613:                } else
0614:                    connect();
0615:                if (connected && progressNotifier != null)
0616:                    progressNotifier.setText("Connected to " + host);
0617:                return connected;
0618:            }
0619:
0620:            private synchronized void connect() {
0621:                if (progressNotifier != null)
0622:                    progressNotifier.setText("Connecting to " + host);
0623:                Log.debug("connecting to " + host);
0624:
0625:                connected = false;
0626:                loginDirectory = null;
0627:                currentDirectory = null;
0628:                errorText = null;
0629:
0630:                SocketConnection sc = new SocketConnection(host, port, 30000,
0631:                        200, progressNotifier);
0632:                controlSocket = sc.connect();
0633:                if (controlSocket == null) {
0634:                    errorText = sc.getErrorText();
0635:                    return;
0636:                }
0637:
0638:                try {
0639:                    controlIn = new BufferedReader(new InputStreamReader(
0640:                            controlSocket.getInputStream()));
0641:                    controlOut = new OutputStreamWriter(controlSocket
0642:                            .getOutputStream());
0643:                } catch (IOException e) {
0644:                    Log.error(e);
0645:                    disconnect();
0646:                    return;
0647:                }
0648:                getReplyString();
0649:                command("USER " + user);
0650:                int code = getReply();
0651:                if (code == 331) {
0652:                    // Password required.
0653:                    if (password != null) {
0654:                        command("PASS " + password);
0655:                        code = getReply();
0656:                        if (code == 530) {
0657:                            errorText = "Login incorrect";
0658:                            user = null;
0659:                            password = null;
0660:                        }
0661:                    }
0662:                }
0663:                if (code != 230) {
0664:                    if (errorText == null || errorText.length() == 0) {
0665:                        if (lastReply != null)
0666:                            errorText = lastReply.substring(3).trim();
0667:                        if (errorText == null || errorText.length() == 0)
0668:                            errorText = "Unable to connect to " + host;
0669:                    }
0670:                    disconnect();
0671:                    return;
0672:                }
0673:
0674:                // Determine login directory.
0675:                command("PWD");
0676:                String s = getReplyString();
0677:                int begin = s.indexOf('"');
0678:                if (begin >= 0) {
0679:                    int end = s.indexOf('"', ++begin);
0680:                    if (end >= 0)
0681:                        loginDirectory = currentDirectory = s.substring(begin,
0682:                                end);
0683:                }
0684:
0685:                command("TYPE I");
0686:                code = getReply();
0687:                if (code != 200) {
0688:                    Log.error("connect didn't get 200");
0689:                    disconnect();
0690:                    return;
0691:                }
0692:
0693:                connected = true;
0694:                Log.debug("connected!");
0695:            }
0696:
0697:            private void command(String s) {
0698:                boolean reconnect = false;
0699:                if (echo)
0700:                    Log.debug("==> " + (s.startsWith("PASS ") ? "PASS" : s));
0701:                try {
0702:                    controlOut.write(s + "\r\n");
0703:                    controlOut.flush();
0704:                    return;
0705:                } catch (Exception e) {
0706:                    Log.error("exception command " + s);
0707:                    reconnect = true;
0708:                }
0709:                if (reconnect) {
0710:                    // Exception may mean we were disconnected by remote host because
0711:                    // of inactivity. Try to reconnect.
0712:                    Log.debug("trying to reconnect...");
0713:                    connect();
0714:                    if (connected) {
0715:                        if (echo)
0716:                            Log.debug("==> "
0717:                                    + (s.startsWith("PASS ") ? "PASS" : s));
0718:                        try {
0719:                            controlOut.write(s + "\r\n");
0720:                            controlOut.flush();
0721:                            return;
0722:                        } catch (Exception e) {
0723:                            Log.error("2nd exception command " + s);
0724:                            reconnect = true;
0725:                        }
0726:                    }
0727:                }
0728:            }
0729:
0730:            private String lastReply;
0731:
0732:            // Returns final line of reply.
0733:            private String getReplyString() {
0734:                String s = null;
0735:                try {
0736:                    do {
0737:                        s = controlIn.readLine();
0738:                        if (echo && s != null)
0739:                            Log.debug("<== " + s);
0740:                    } while (s != null && !isEndOfReply(s));
0741:                } catch (Exception e) {
0742:                }
0743:                lastReply = s;
0744:                return s;
0745:            }
0746:
0747:            private static boolean isEndOfReply(String s) {
0748:                // If it's not the last line of the reply, the 4th char will be '-'.
0749:                if (s != null && s.length() >= 4 && s.charAt(3) == ' '
0750:                        && Character.isDigit(s.charAt(0))
0751:                        && Character.isDigit(s.charAt(1))
0752:                        && Character.isDigit(s.charAt(2))) {
0753:                    return true;
0754:                }
0755:
0756:                return false;
0757:            }
0758:
0759:            private boolean getReply(int required) {
0760:                String s = getReplyString();
0761:                if (s == null)
0762:                    return false;
0763:                return getCode(s) == required;
0764:            }
0765:
0766:            private int getReply() {
0767:                String s = getReplyString();
0768:                if (s == null)
0769:                    return 421;
0770:                return getCode(s);
0771:            }
0772:
0773:            private static int getCode(String reply) {
0774:                int code = -1;
0775:                if (reply != null) {
0776:                    // We do sanity checking when we get the reply string, so we don't
0777:                    // need it here.
0778:                    try {
0779:                        code = Integer.parseInt(reply.substring(0, 3));
0780:                    } catch (NumberFormatException e) {
0781:                        Log.error(e);
0782:                    }
0783:                }
0784:                return code;
0785:            }
0786:
0787:            private String getData() {
0788:                if (!usePassiveMode)
0789:                    acceptConnectionFromServer();
0790:                byte[] buf = new byte[16384];
0791:                FastStringBuffer sb = new FastStringBuffer();
0792:                try {
0793:                    while (true) {
0794:                        int bytesRead = dataIn.read(buf); // Blocks.
0795:                        if (bytesRead < 0)
0796:                            break;
0797:                        sb.append(new String(buf, 0, bytesRead));
0798:                    }
0799:                } catch (IOException e) {
0800:                    Log.error(e);
0801:                }
0802:                return sb.toString();
0803:            }
0804:
0805:            private void closeDataSocket() {
0806:                if (dataSocket != null) {
0807:                    if (dataIn != null) {
0808:                        try {
0809:                            dataIn.close();
0810:                        } catch (IOException e) {
0811:                            Log.error(e);
0812:                        }
0813:                    }
0814:                    if (dataOut != null) {
0815:                        try {
0816:                            dataOut.close();
0817:                        } catch (IOException e) {
0818:                            Log.error(e);
0819:                        }
0820:                    }
0821:                    try {
0822:                        dataSocket.close();
0823:                    } catch (IOException e) {
0824:                        Log.error(e);
0825:                    }
0826:                    dataSocket = null;
0827:                    dataIn = null;
0828:                    dataOut = null;
0829:                }
0830:            }
0831:
0832:            private boolean openDataSocket() {
0833:                if (!connected) {
0834:                    connect();
0835:                    if (!connected)
0836:                        return false;
0837:                }
0838:                closeDataSocket();
0839:                if (usePassiveMode) {
0840:                    command("PASV");
0841:                    String reply;
0842:                    while (true) {
0843:                        reply = getReplyString();
0844:                        if (reply == null) {
0845:                            Log.error("openDataSocket null reply to PASV");
0846:                            return false;
0847:                        }
0848:                        int code = getCode(reply);
0849:                        if (code >= 400)
0850:                            return false; // Error.
0851:                        if (code == 227)
0852:                            break; // The one we want.
0853:                        // Otherwise the reply we received is not a reply to the PASV command.
0854:                        // Loop back and try again.
0855:                    }
0856:                    int begin = reply.indexOf('(');
0857:                    if (begin < 0)
0858:                        return false;
0859:                    int end = reply.indexOf(')');
0860:                    if (end < 0)
0861:                        return false;
0862:                    String s = reply.substring(begin + 1, end);
0863:                    StringTokenizer st = new StringTokenizer(s, ",", false);
0864:                    if (st.countTokens() != 6)
0865:                        return false;
0866:                    String[] addr = new String[4];
0867:                    for (int i = 0; i < 4; i++)
0868:                        addr[i] = st.nextToken();
0869:                    String address = addr[0] + "." + addr[1] + "." + addr[2]
0870:                            + "." + addr[3];
0871:                    try {
0872:                        int hibyte = Integer.parseInt(st.nextToken());
0873:                        int lobyte = Integer.parseInt(st.nextToken());
0874:                        int dataPort = hibyte * 256 + lobyte;
0875:                        Log.debug("opening data socket");
0876:                        dataSocket = new Socket(address, dataPort);
0877:                        dataIn = dataSocket.getInputStream();
0878:                        dataOut = dataSocket.getOutputStream();
0879:                    } catch (NumberFormatException e) {
0880:                        Log.error(e);
0881:                    } catch (IOException ex) {
0882:                        Log.error(ex);
0883:                    }
0884:                    return dataSocket != null;
0885:                } else {
0886:                    // We're not using passive mode.
0887:                    try {
0888:                        InetAddress localHost = controlSocket.getLocalAddress();
0889:                        serverSocket = new ServerSocket(0);
0890:                        int dataPort = serverSocket.getLocalPort();
0891:                        int lobyte = (dataPort & 0x00ff);
0892:                        int hibyte = ((dataPort & 0xff00) >> 8);
0893:                        byte[] addrBytes = localHost.getAddress();
0894:                        int[] addr = new int[4];
0895:                        for (int i = 0; i < 4; i++) {
0896:                            addr[i] = addrBytes[i];
0897:                            if (addr[i] < 0)
0898:                                addr[i] += 256;
0899:                        }
0900:                        String s = "PORT " + addr[0] + "," + addr[1] + ","
0901:                                + addr[2] + "," + addr[3] + "," + hibyte + ","
0902:                                + lobyte;
0903:                        command(s);
0904:                        return getReply(200);
0905:                    } catch (Exception e) {
0906:                        Log.error(e);
0907:                    }
0908:                    return false;
0909:                }
0910:            }
0911:
0912:            private void acceptConnectionFromServer() {
0913:                try {
0914:                    dataSocket = serverSocket.accept();
0915:                    if (dataSocket != null) {
0916:                        dataIn = dataSocket.getInputStream();
0917:                        dataOut = dataSocket.getOutputStream();
0918:                    }
0919:                } catch (Exception e) {
0920:                    Log.error(e);
0921:                }
0922:            }
0923:
0924:            private InputStream getInputStreamForFile(String filename) {
0925:                if (openDataSocket()) {
0926:                    command("RETR " + filename);
0927:                    int code = getCode(getReplyString());
0928:                    if (code > -1 && code < 400) {
0929:                        if (!usePassiveMode)
0930:                            acceptConnectionFromServer();
0931:                        return dataIn;
0932:                    }
0933:                }
0934:                return null;
0935:            }
0936:
0937:            private OutputStream getOutputStreamForFile(String filename) {
0938:                if (filename == null)
0939:                    return null;
0940:                if (openDataSocket()) {
0941:                    command("STOR " + filename);
0942:                    int code = getCode(getReplyString());
0943:                    if (code > -1 && code < 400) {
0944:                        if (!usePassiveMode)
0945:                            acceptConnectionFromServer();
0946:                        return dataOut;
0947:                    }
0948:                    if (code == 550 || code == 553)
0949:                        errorText = "Access denied";
0950:                }
0951:                return null;
0952:            }
0953:
0954:            private static synchronized void cleanup() {
0955:                // Walk buffer list in event dispatch thread.
0956:                if (!SwingUtilities.isEventDispatchThread()) {
0957:                    Debug.bug();
0958:                    return;
0959:                }
0960:                if (sessionList.size() == 0)
0961:                    return; // Nothing to do.
0962:                for (int i = sessionList.size(); i-- > 0;) {
0963:                    FtpSession session = (FtpSession) sessionList.get(i);
0964:                    String host = session.getHost();
0965:                    boolean inUse = false;
0966:                    for (BufferIterator it = new BufferIterator(); it.hasNext();) {
0967:                        Buffer buf = it.nextBuffer();
0968:                        if (buf.getFile() instanceof  FtpFile) {
0969:                            if (host.equals(buf.getFile().getHostName())) {
0970:                                inUse = true;
0971:                                break;
0972:                            }
0973:                        }
0974:                    }
0975:                    if (!inUse) {
0976:                        session.close();
0977:                        unregister(session);
0978:                    }
0979:                }
0980:                if (sessionList.size() == 0) {
0981:                    if (cleanupThread != null) {
0982:                        cleanupThread.cancel();
0983:                        cleanupThread = null;
0984:                    }
0985:                }
0986:            }
0987:
0988:            private static final Runnable cleanupRunnable = new Runnable() {
0989:                public void run() {
0990:                    cleanup();
0991:                }
0992:            };
0993:
0994:            public synchronized void disconnect() {
0995:                Log.debug("disconnect");
0996:                if (controlSocket != null) {
0997:                    Log.debug("closing control socket...");
0998:                    try {
0999:                        controlSocket.close();
1000:                    } catch (IOException e) {
1001:                        Log.error(e);
1002:                    }
1003:                    controlSocket = null;
1004:                    controlIn = null;
1005:                    controlOut = null;
1006:                }
1007:                if (dataSocket != null) {
1008:                    Log.debug("closing data socket...");
1009:                    try {
1010:                        dataSocket.close();
1011:                    } catch (IOException e) {
1012:                        Log.error(e);
1013:                    }
1014:                    dataSocket = null;
1015:                    dataIn = null;
1016:                    dataOut = null;
1017:                }
1018:                connected = false;
1019:            }
1020:
1021:            private void close() {
1022:                Log.debug("FtpSession.close");
1023:                if (connected) {
1024:                    final Editor editor = Editor.currentEditor();
1025:                    editor.setWaitCursor();
1026:                    Runnable r = new Runnable() {
1027:                        public void run() {
1028:                            try {
1029:                                if (echo)
1030:                                    Log.debug("==> QUIT");
1031:                                controlOut.write("QUIT\r\n");
1032:                                controlOut.flush();
1033:                                getReply();
1034:                            } catch (IOException e) {
1035:                            }
1036:                        }
1037:                    };
1038:                    Thread t = new Thread(r);
1039:                    t.start();
1040:                    try {
1041:                        t.join(3000);
1042:                    } catch (InterruptedException e) {
1043:                        Log.error(e);
1044:                    }
1045:                    if (t.isAlive()) {
1046:                        Log.debug("stopping QUIT thread");
1047:                        t.stop();
1048:                    }
1049:                    disconnect();
1050:                    editor.setDefaultCursor();
1051:                }
1052:                Log.debug("leaving close");
1053:            }
1054:
1055:            public static synchronized FtpSession getSession(FtpFile file) {
1056:                if (file == null)
1057:                    return null;
1058:                Login login = new Login(file.getHostName(), file.getUserName(),
1059:                        file.getPassword());
1060:                if (login == null)
1061:                    return null; // Invalid URL.
1062:                // Try to find an idle session for the required host.
1063:                FtpSession session = lockSession(login.host, file.getPort());
1064:                if (session != null) {
1065:                    if (session.checkLogin())
1066:                        return session;
1067:
1068:                    session.unlock();
1069:                    return null;
1070:                }
1071:                // No idle session for this host. Try to find a session to clone.
1072:                session = findSession(login.host, file.getPort());
1073:                if (session != null) {
1074:                    session = (FtpSession) session.clone();
1075:                    if (session.lock()) {
1076:                        if (session.checkLogin())
1077:                            return session;
1078:                        session.unlock();
1079:                    }
1080:                    return null;
1081:                }
1082:                if (login.user == null || login.password == null) {
1083:                    // The URL lacked either a user name or a password or both.
1084:                    final Editor editor = Editor.currentEditor();
1085:                    if (login.user == null) {
1086:                        // No user name in URL. We'll take the first entry in ~/.netrc
1087:                        // for the host in question.
1088:                        Login maybe = Netrc.getLogin(login.host);
1089:                        if (maybe != null) {
1090:                            login.user = maybe.user;
1091:                            login.password = maybe.password;
1092:                        }
1093:                        if (login.user == null) {
1094:                            // Nothing relevant in ~/.netrc.  Ask the user.
1095:                            login.user = InputDialog.showInputDialog(editor,
1096:                                    "Login:", "Login on " + login.host);
1097:                            editor.repaintNow();
1098:                        }
1099:                    }
1100:                    if (login.user == null)
1101:                        return null; // User cancelled.
1102:                    if (login.user.length() == 0)
1103:                        login.user = "anonymous";
1104:                    if (login.password == null) {
1105:                        // We have host and user name but no password.
1106:                        login.password = Netrc.getPassword(login.host,
1107:                                login.user);
1108:                        if (login.password == null) {
1109:                            if (login.user.equals("anonymous"))
1110:                                login.password = Editor
1111:                                        .preferences()
1112:                                        .getStringProperty(
1113:                                                Property.FTP_ANONYMOUS_PASSWORD);
1114:                            if (login.password == null) {
1115:                                // Ask the user.
1116:                                login.password = PasswordDialog
1117:                                        .showPasswordDialog(editor,
1118:                                                "Password:", "Password");
1119:                                editor.repaintNow();
1120:                            }
1121:                        }
1122:                    }
1123:                    // If we don't have a password, give up (it can be blank, but not
1124:                    // null).
1125:                    if (login.password == null)
1126:                        return null;
1127:                }
1128:                // Final sanity check.
1129:                if (login.user.length() == 0)
1130:                    return null;
1131:                // At this point we have non-empty strings for host and user name, and
1132:                // a non-null password.
1133:                session = new FtpSession(login, file.getPort());
1134:                if (session.lock())
1135:                    return session;
1136:                return null;
1137:            }
1138:
1139:            // Make sure the login is comnplete. Get the user to enter the username
1140:            // and/or password if missing. Don't look in .netrc or preferences; we may
1141:            // be here because the information in .netrc or preferences didn't work.
1142:            private boolean checkLogin() {
1143:                final Editor editor = Editor.currentEditor();
1144:                if (user == null) {
1145:                    // Nothing relevant in ~/.netrc.  Ask the user.
1146:                    user = InputDialog.showInputDialog(editor, "Login:",
1147:                            "Login on " + host);
1148:                    editor.repaintNow();
1149:                    if (user == null)
1150:                        return false; // User cancelled.
1151:                }
1152:                if (user.length() == 0)
1153:                    user = "anonymous";
1154:                if (password == null) {
1155:                    // Ask the user.
1156:                    password = PasswordDialog.showPasswordDialog(editor,
1157:                            "Password:", "Password");
1158:                    editor.repaintNow();
1159:                    // If we don't have a password, give up.
1160:                    if (password == null)
1161:                        return false;
1162:                }
1163:                // Final sanity check.
1164:                if (user.length() == 0)
1165:                    return false;
1166:                return true;
1167:            }
1168:
1169:            private static FtpSession lockSession(String host, int port) {
1170:                for (int i = 0; i < sessionList.size(); i++) {
1171:                    FtpSession session = (FtpSession) sessionList.get(i);
1172:                    if (session.host.equals(host) && session.port == port) {
1173:                        if (session.lock())
1174:                            return session;
1175:                    }
1176:                }
1177:                return null;
1178:            }
1179:
1180:            private static FtpSession findSession(String host, int port) {
1181:                for (int i = 0; i < sessionList.size(); i++) {
1182:                    FtpSession session = (FtpSession) sessionList.get(i);
1183:                    if (session.host.equals(host) && session.port == port)
1184:                        return session;
1185:                }
1186:                return null;
1187:            }
1188:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.