Source Code Cross Referenced for CVSClient.java in  » Source-Control » jcvsweb » com » ice » cvsc » 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 » Source Control » jcvsweb » com.ice.cvsc 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         ** Java cvs client library package.
0003:         ** Copyright (c) 1997-2003 by Timothy Gerard Endres
0004:         ** 
0005:         ** This program is free software.
0006:         ** 
0007:         ** You may redistribute it and/or modify it under the terms of the GNU
0008:         ** Library General Public License (LGPL) as published by the Free Software
0009:         ** Foundation.
0010:         **
0011:         ** Version 2 of the license should be included with this distribution in
0012:         ** the file LICENSE.txt, as well as License.html. If the license is not
0013:         ** included	with this distribution, you may find a copy at the FSF web
0014:         ** site at 'www.gnu.org' or 'www.fsf.org', or you may write to the Free
0015:         ** Software Foundation at 59 Temple Place - Suite 330, Boston, MA 02111 USA.
0016:         **
0017:         ** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND,
0018:         ** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR
0019:         ** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY
0020:         ** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR
0021:         ** REDISTRIBUTION OF THIS SOFTWARE. 
0022:         ** 
0023:         */
0024:
0025:        package com.ice.cvsc;
0026:
0027:        import java.io.*;
0028:        import java.net.*;
0029:        import java.awt.*;
0030:        import java.awt.event.*;
0031:        import java.util.*;
0032:        import java.util.zip.*;
0033:        import java.applet.*;
0034:
0035:        import com.sshtools.j2ssh.SshClient;
0036:        import com.sshtools.j2ssh.session.SessionChannelClient;
0037:        import com.sshtools.j2ssh.authentication.AuthenticationProtocolState;
0038:        import com.sshtools.j2ssh.authentication.PasswordAuthenticationClient;
0039:        import com.sshtools.j2ssh.configuration.SshConnectionProperties;
0040:        import com.sshtools.j2ssh.transport.HostKeyVerification;
0041:        import com.sshtools.j2ssh.transport.TransportProtocolException;
0042:        import com.sshtools.j2ssh.transport.publickey.SshPublicKey;
0043:
0044:        /**
0045:         * Implements the client side of the CVS server-client protocol.
0046:         * This object is used by a CVSProject object to implement the
0047:         * protocols required to communicate with the CVS server and
0048:         * complete CVS requests. CVSClient's use TCP communications
0049:         * to a specified host and port (default is 2401). CVSClients
0050:         * <em>can</em> stand on their own, however, there is not much
0051:         * interesting that can be accomplished without the information
0052:         * contained in a CVSProject. Typically, you use a CVSClient
0053:         * by handing it a CVSRequest, and it will hand back a CVSResponse.
0054:         *
0055:         * Thanks to Wes Sonnenreich <wes@sonnenreich.com> for his original
0056:         * attempt at the integration of MindBright's SSH package into this
0057:         * client. The effort was most helpful in understanding the package.
0058:         *
0059:         * @version $Revision: 2.20 $
0060:         * @author Timothy Gerard Endres, <a href="mailto:time@ice.com">time@ice.com</a>.
0061:         * @see CVSRequest
0062:         * @see CVSResponse
0063:         * @see CVSProject
0064:         */
0065:
0066:        //
0067:        // NOTES in code:
0068:        //
0069:        // EH-null-ui  Etienne-Hugues Fortin <ehfortin@sympatico.ca>
0070:        //   Added a new "NullCVSUI" to ensure that the CVS UI interface is
0071:        //   always established.
0072:        //
0073:        // SW-flush-out  Shawn Willden <shawn@willden.org>
0074:        //   Since out GZIP stream was wrapped in a BufferedOutputStream
0075:        //   we need to flush() to move it all out. Otherwise, the command
0076:        //   data sat buffered and the server never responded.
0077:        //
0078:
0079:        public class CVSClient extends Object implements  HostKeyVerification {
0080:            static public final String RCS_ID = "$Id: CVSClient.java,v 2.20 2003/07/27 04:32:56 time Exp $";
0081:            static public final String RCS_REV = "$Revision: 2.20 $";
0082:
0083:            public static final int DEFAULT_SSH_PORT = 22;
0084:            public static final int DEFAULT_RSH_PORT = 514;
0085:            public static final int DEFAULT_CVS_PORT = 2401;
0086:            public static final int DEFAULT_DIR_PORT = 2402;
0087:            public static final String DEFAULT_TEMP_PATH = ".";
0088:
0089:            /**
0090:             * Used to indicate that an ascii file is being transferred.
0091:             */
0092:            public static final int TRANSLATE_NONE = 0;
0093:            /**
0094:             * Used to indicate that a binary file is being transferred.
0095:             */
0096:            public static final int TRANSLATE_ASCII = 1;
0097:
0098:            /**
0099:             * The minimum size before a file is gzip-ed in 'gzip-file-contents' mode.
0100:             */
0101:            private static final int MIN_GZIP_SIZE = 1024;
0102:
0103:            private static final int MAX_FILE_SIZE = 1000000;
0104:            private static final boolean LIMIT_FILE_SIZE = false;
0105:
0106:            private Object canLock;
0107:            private boolean canceled;
0108:
0109:            private String hostName;
0110:            private int port;
0111:            private int tempCounter;
0112:
0113:            private boolean usingGZIP;
0114:            private boolean serverIsOpen;
0115:            private boolean tracingTCPData;
0116:
0117:            private Process process;
0118:            private Socket socket;
0119:            private InputStream instream;
0120:            private OutputStream outstream;
0121:
0122:            private String tempPath;
0123:            private String reason;
0124:            private String recentEntryRepository;
0125:
0126:            /**
0127:             * Hashtable of all 'Directory' commands that we have sent
0128:             * to above sending redundant commands.
0129:             */
0130:            private Hashtable dirHash;
0131:
0132:            /**
0133:             * Flag that determines whether or not we make the extra effort
0134:             * to support multiple interface machines. The means we use to
0135:             * determine the correct interface involves multiple socket opens,
0136:             * which is expensive, so we only do it if necessary.
0137:             *
0138:             */
0139:            private boolean supportMultipleInterfaces = false;
0140:
0141:            /**
0142:             * SSH supporting fields
0143:             */
0144:            SshClient sshClient = null;
0145:            SessionChannelClient sshSession = null;
0146:
0147:            /**
0148:             * Creates a CVS client.
0149:             * The client is unusable, however, until
0150:             * the hostname and port number are established.
0151:             *
0152:             * @param adminDirPath The pathname of the admin ('CVS') directory.
0153:             */
0154:            public CVSClient() {
0155:                super ();
0156:
0157:                InitFields();
0158:            }
0159:
0160:            /**
0161:             * Creates a CVS client using the provided hostname and port number.
0162:             *
0163:             * @param hostName The hostname of the cvs server.
0164:             * @param port The port number of the cvs server (typically 2401).
0165:             */
0166:            public CVSClient(String hostName, int port) {
0167:                super ();
0168:
0169:                InitFields();
0170:
0171:                this .port = port;
0172:                this .hostName = hostName;
0173:            }
0174:
0175:            /**
0176:             * Common initializer for all our contructors.
0177:             */
0178:            private void InitFields() {
0179:                this .canceled = false;
0180:                this .canLock = new Object();
0181:
0182:                this .hostName = null;
0183:
0184:                this .port = CVSClient.DEFAULT_CVS_PORT;
0185:
0186:                this .tempPath = CVSClient.DEFAULT_TEMP_PATH;
0187:
0188:                this .tempCounter = (int) (System.currentTimeMillis() % (long) 0x0FFFFFFF);
0189:
0190:                this .serverIsOpen = false;
0191:                this .tracingTCPData = false;
0192:
0193:                this .socket = null;
0194:                this .instream = null;
0195:                this .outstream = null;
0196:
0197:                this .reason = "";
0198:                this .recentEntryRepository = "";
0199:            }
0200:
0201:            /**
0202:             * Returns the hostname of the cvs server.
0203:             */
0204:            public String getHostName() {
0205:                return this .hostName;
0206:            }
0207:
0208:            /**
0209:             * Sets the hostname of the cvs server.
0210:             *
0211:             * @param hostName The hostname of the cvs server.
0212:             */
0213:            public void setHostName(String hostName) {
0214:                this .hostName = hostName;
0215:            }
0216:
0217:            /**
0218:             * Returns the port number of the cvs server.
0219:             */
0220:            public int getPort() {
0221:                return this .port;
0222:            }
0223:
0224:            /**
0225:             * Sets the port number of the cvs server.
0226:             *
0227:             * @param port The port number of the cvs server (typically 2401).
0228:             */
0229:            public void setPort(int port) {
0230:                this .port = port;
0231:            }
0232:
0233:            /**
0234:             * Returns the port number of the cvs server.
0235:             */
0236:            public boolean getMultipleInterfaceSupport() {
0237:                return this .supportMultipleInterfaces;
0238:            }
0239:
0240:            /**
0241:             * Sets the port number of the cvs server.
0242:             *
0243:             * @param port The port number of the cvs server (typically 2401).
0244:             */
0245:            public void setMultipleInterfaceSupport(boolean flag) {
0246:                this .supportMultipleInterfaces = flag;
0247:                CVSTracer.traceIf(flag, "Supporting multiple interfaces.");
0248:            }
0249:
0250:            /**
0251:             * Returns the pathname of the directory in which temporary files are created.
0252:             */
0253:            public String getTempDirectory() {
0254:                return this .tempPath;
0255:            }
0256:
0257:            /**
0258:             * Sets the pathname of the directory in which temporary files are created.
0259:             *
0260:             * @param tempPath The full pathname of the temporary directory.
0261:             */
0262:            public void setTempDirectory(String tempPath) {
0263:                this .tempPath = tempPath;
0264:            }
0265:
0266:            //
0267:            // REVIEW
0268:            // UNDONE
0269:            // Should we use a StringBuffer for reason, and provide
0270:            // a "appendReason()" method?
0271:            //
0272:
0273:            /**
0274:             * Returns the reason for the last error.
0275:             */
0276:            public String getReason() {
0277:                return this .reason;
0278:            }
0279:
0280:            /**
0281:             * Sets the resaon for the last error.
0282:             *
0283:             * @param reason The string describing the reason.
0284:             */
0285:            public void setReason(String reason) {
0286:                this .reason = reason;
0287:            }
0288:
0289:            /**
0290:             * Indicates whether or not the connection to the server is established.
0291:             */
0292:            public boolean isServerOpen() {
0293:                return this .serverIsOpen;
0294:            }
0295:
0296:            public boolean sendCVSRootDirectory(CVSRequest request) {
0297:                boolean result = true;
0298:
0299:                result = this .sendLine("Root " + request.getRootDirectory());
0300:
0301:                return result;
0302:            }
0303:
0304:            /**
0305:             * Send the "root" of our repository. Since all of our commands
0306:             * now work with the assumption that everything is relative to
0307:             * "./", we need to properly establish 'Directory .' for the
0308:             * module that we are working with.
0309:             *
0310:             */
0311:
0312:            public boolean sendRootRepository(CVSRequest request) {
0313:                boolean result = true;
0314:
0315:                result = this .sendLine("Directory .");
0316:                result = this .sendLine(request.getRootRepository());
0317:
0318:                return result;
0319:            }
0320:
0321:            /**
0322:             * This method is used to send the 'Directory' command before
0323:             * an entry is sent, to set the "context" of the entry (i.e.,
0324:             * the entry's directory).
0325:             *
0326:             * <strong>Note</strong> that jCVS has a peculiarity. We only
0327:             * send the entries the user has selected in many cases. Thus,
0328:             * if we refer to a file 'com/ice/cvsc/CVSLog.java', we send
0329:             * that 'Directory' command, but none for the directories 'com',
0330:             * and 'ice'. In most cases, this is not an issue, but for a top
0331:             * level command like Update, this causes entire branches of the
0332:             * project hierarchy to be skipped because we had not sent the
0333:             * 'Directory' command for that level. To solve this, whenever
0334:             * we send a 'Directory' command, we send all of the intermediate
0335:             * levels as well. In order to minimize the redundancy, we keep
0336:             * a list of what has already been sent in 'this.dirHash'.
0337:             *
0338:             * @param request The current request.
0339:             * @param entry The entry for which to send the command.
0340:             * @return True if successful, else failure.
0341:             */
0342:
0343:            public boolean sendEntryRepository(CVSRequest request,
0344:                    CVSEntry entry) {
0345:                boolean result = true;
0346:
0347:                CVSTracer.traceIf(request.traceRequest, "sendEntryRepository: "
0348:                        + entry.dumpString());
0349:
0350:                String localDir = CVSCUtilities.stripFinalSlash(entry
0351:                        .getLocalDirectory());
0352:
0353:                CVSTracer.traceIf(request.traceRequest,
0354:                        "sendEntryRepository: localDir = '" + localDir + "'");
0355:
0356:                if (!localDir.equals(this .recentEntryRepository)) {
0357:                    String stickyStr;
0358:                    String dirStr = localDir;
0359:                    String repStr = entry.getRepository();
0360:
0361:                    CVSTracer.traceIf(request.traceRequest,
0362:                            "sendEntryRepository: INITIAL \n" + "  dirStr = '"
0363:                                    + dirStr + "'\n" + "  repStr = '" + repStr
0364:                                    + "'");
0365:
0366:                    Vector v = new Vector();
0367:                    stickyStr = this .getStickTag(request, dirStr);
0368:                    if (stickyStr.length() > 0)
0369:                        v.addElement(stickyStr);
0370:                    v.addElement(entry.getRepository());
0371:                    v.addElement("Directory " + localDir);
0372:                    this .dirHash.put(localDir, entry.getRepository());
0373:
0374:                    for (int pi = 0;; ++pi) {
0375:                        int idxD = dirStr.lastIndexOf("/");
0376:                        int idxR = repStr.lastIndexOf("/");
0377:
0378:                        if (idxD < 0 || idxR < 0) {
0379:                            for (int i = v.size() - 1; i >= 0; --i) {
0380:                                result = this .sendLine((String) v.elementAt(i));
0381:                            }
0382:                            break;
0383:                        } else {
0384:                            dirStr = dirStr.substring(0, idxD);
0385:                            repStr = repStr.substring(0, idxR);
0386:
0387:                            CVSTracer.traceIf(request.traceRequest,
0388:                                    "sendEntryRepository: PART [" + pi + "]\n"
0389:                                            + "  dirStr = '" + dirStr + "'\n"
0390:                                            + "  repStr = '" + repStr + "'");
0391:
0392:                            if (this .dirHash.get(dirStr) == null) {
0393:                                // NOTE These MUST be in reverse order!!!
0394:                                stickyStr = this .getStickTag(request, dirStr);
0395:                                if (stickyStr.length() > 0)
0396:                                    v.addElement(stickyStr);
0397:                                v.addElement(repStr);
0398:                                v.addElement("Directory " + dirStr);
0399:                                this .dirHash.put(dirStr, repStr);
0400:                            }
0401:                        }
0402:                    }
0403:
0404:                    result = this .sendSticky(request, entry);
0405:                    result = this .sendStatic(request, entry);
0406:
0407:                    this .recentEntryRepository = localDir;
0408:                }
0409:
0410:                return result;
0411:            }
0412:
0413:            public boolean sendCVSArgument(String argument) {
0414:                boolean result = true;
0415:
0416:                result = this .sendLine("Argument " + argument);
0417:
0418:                return result;
0419:            }
0420:
0421:            // REVIEW
0422:            // Should be be computing it via the rootRepository and
0423:            // rootDirectory?
0424:            //
0425:            public boolean sendCVSModule(CVSRequest request) {
0426:                boolean result = true;
0427:
0428:                result = this .sendCVSArgument(".");
0429:
0430:                return result;
0431:            }
0432:
0433:            public boolean sendSetVariables(CVSRequest request) {
0434:                boolean result = true;
0435:
0436:                String[] vars = request.getSetVariables();
0437:
0438:                if (vars != null)
0439:                    for (int i = 0; result && i < vars.length; ++i)
0440:                        result = this .sendLine("Set " + vars[i]);
0441:
0442:                return result;
0443:            }
0444:
0445:            public boolean sendModified(CVSRequest request, CVSEntry entry,
0446:                    File entryFile, boolean empty, int trans) {
0447:                boolean result = true;
0448:
0449:                result = this .sendEntryRepository(request, entry);
0450:
0451:                if (result)
0452:                    result = this .sendLine("Modified " + entry.getName());
0453:
0454:                if (result)
0455:                    result = this .sendLine(entry.getModeLine());
0456:
0457:                if (result) {
0458:                    if (empty) {
0459:                        result = this .sendLine("0");
0460:                    } else
0461:                        switch (trans) {
0462:                        case CVSClient.TRANSLATE_ASCII:
0463:                            result = this .sendFileAscii(entry, entryFile,
0464:                                    request.gzipFileMode);
0465:                            break;
0466:
0467:                        default:
0468:                            result = this .sendFileRaw(entry, entryFile,
0469:                                    request.gzipFileMode);
0470:                            break;
0471:                        }
0472:                }
0473:
0474:                if (!result) {
0475:                    CVSLog
0476:                            .logMsg("CVSClient.sendModified: ERROR sending file: "
0477:                                    + this .getReason());
0478:                }
0479:
0480:                return result;
0481:            }
0482:
0483:            public boolean sendLostEntry(CVSRequest request, CVSEntry entry,
0484:                    boolean useUnchanged) {
0485:                boolean result = true;
0486:
0487:                CVSTracer.trace("sendLostEntry: '" + entry.getName() + "'");
0488:                //
0489:                // if ( request.useUnchanged == false )
0490:                // If 'UseUnchanged' has NOT been sent, then lost
0491:                // entries _must_ have a 'Lost' request sent.
0492:                //
0493:                // if ( request.useUnchanged == true )
0494:                // If 'UseUnchanged' has been sent, then lost
0495:                // entries are indicated by nothing being sent.
0496:                //
0497:                if (!useUnchanged) {
0498:                    result = this .sendEntryRepository(request, entry);
0499:                    if (result) {
0500:                        result = this .sendLine("Lost " + entry.getName());
0501:                    }
0502:                }
0503:
0504:                return result;
0505:            }
0506:
0507:            public boolean sendUnchangedEntry(CVSRequest request,
0508:                    CVSEntry entry, boolean useUnchanged) {
0509:                boolean result = true;
0510:
0511:                CVSTracer
0512:                        .trace("sendUnchangedEntry: '" + entry.getName() + "'");
0513:
0514:                //
0515:                // if ( request.useUnchanged == true )
0516:                // If 'UseUnchanged' has been sent, then unchanged
0517:                // entries _must_ have an 'Unchanged' request sent.
0518:                //
0519:                // if ( request.useUnchanged == false )
0520:                // If 'UseUnchanged' has NOT been sent, then the
0521:                // 'Unchanged' line is verbotten, and unchanged
0522:                // entries are indicated by nothing being sent.
0523:                //
0524:                if (useUnchanged) {
0525:                    result = this .sendEntryRepository(request, entry);
0526:                    if (result)
0527:                        result = this .sendLine("Unchanged " + entry.getName());
0528:                }
0529:
0530:                return result;
0531:            }
0532:
0533:            public boolean sendCVSEntry(CVSRequest request, CVSEntry entry,
0534:                    File entryFile) {
0535:                boolean result = true;
0536:                boolean fileExists = false;
0537:                boolean fileIsModified = false;
0538:
0539:                CVSTracer.traceIf(request.traceRequest, "sendCVSEntry: "
0540:                        + entry.dumpString());
0541:
0542:                // SPECIAL CASE for directories. This is currently only used when we
0543:                // are adding directories, usually to support adding new files.
0544:
0545:                if (entry.isDirectory()) {
0546:                    result = this .sendEntryRepository(request, entry);
0547:
0548:                    if (result) {
0549:                        //
0550:                        // SPECIAL CASE
0551:                        // In the case of directories, we do not send 'Entry'.
0552:                        // We send the 'Directory' command, which is the equivalent
0553:                        // of 'Entry' for directories.
0554:                        //
0555:                        result = this .sendLine("Directory "
0556:                                + CVSCUtilities.stripFinalSlash(entry
0557:                                        .getFullName()));
0558:
0559:                        if (result) {
0560:                            String localDir = CVSCUtilities
0561:                                    .stripFinalSlash(entry.getLocalDirectory());
0562:
0563:                            result = this .sendLine(entry.getRepository());
0564:                            result = this .sendSticky(request, localDir);
0565:                        }
0566:
0567:                        this .recentEntryRepository = entry.getFullName();
0568:                    }
0569:
0570:                    return result;
0571:                }
0572:
0573:                if (entryFile.exists()) {
0574:                    fileExists = true;
0575:                    fileIsModified = entry.isLocalFileModified(entryFile);
0576:                }
0577:
0578:                int trans = CVSCUtilities.computeTranslation(entry);
0579:
0580:                // SPECIAL CASE when no 'Entry' lines go up...
0581:
0582:                if (!request.sendEntries) {
0583:                    // If no 'Entry' lines, the only thing that _can_
0584:                    // happen is 'Modified's...
0585:                    if (fileIsModified || entry.isNewUserFile()
0586:                            || request.forceModifieds) {
0587:                        if (request.sendModifieds || request.forceModifieds) {
0588:                            result = this .sendEntryRepository(request, entry);
0589:
0590:                            if (result) {
0591:                                request.getUserInterface()
0592:                                        .uiDisplayProgressMsg(
0593:                                                "Uploading file '"
0594:                                                        + entry.getFullName()
0595:                                                        + "'...");
0596:
0597:                                result = this 
0598:                                        .sendModified(request, entry,
0599:                                                entryFile,
0600:                                                request.sendEmptyMods, trans);
0601:                            }
0602:                        }
0603:                    }
0604:
0605:                    return result;
0606:                }
0607:
0608:                // Normal case...
0609:
0610:                String entryStr = entry.getServerEntryLine(entryFile.exists(),
0611:                        fileIsModified);
0612:
0613:                result = this .sendEntryRepository(request, entry);
0614:
0615:                if (result) {
0616:                    result = this .sendLine("Entry " + entryStr);
0617:                }
0618:
0619:                if (result) {
0620:                    if (fileExists) {
0621:                        if (fileIsModified || entry.isNewUserFile()
0622:                                || request.forceModifieds) {
0623:                            if (request.sendModifieds || entry.isNewUserFile()
0624:                                    || request.forceModifieds) {
0625:                                request.getUserInterface()
0626:                                        .uiDisplayProgressMsg(
0627:                                                "Uploading file '"
0628:                                                        + entry.getName()
0629:                                                        + "'...");
0630:
0631:                                //
0632:                                // REVIEW
0633:                                // Here we override the 'Special Mods' flag
0634:                                // when there is a conflict, which appears
0635:                                // to be the only case where this optimization
0636:                                // does not work properly. However, we better
0637:                                // make a more thorough analysis to be certain.
0638:                                //
0639:                                boolean sendEmpties = request.sendEmptyMods;
0640:                                if (entry.isInConflict())
0641:                                    sendEmpties = false;
0642:
0643:                                result = this .sendModified(request, entry,
0644:                                        entryFile, sendEmpties, trans);
0645:                            } else {
0646:                                result = this .sendUnchangedEntry(request,
0647:                                        entry, request.useUnchanged);
0648:                            }
0649:                        } else {
0650:                            result = this .sendUnchangedEntry(request, entry,
0651:                                    request.useUnchanged);
0652:                        }
0653:                    } else {
0654:                        result = this .sendLostEntry(request, entry,
0655:                                request.useUnchanged);
0656:                    }
0657:                }
0658:
0659:                return result;
0660:            }
0661:
0662:            public boolean sendCVSEntries(CVSRequest request) {
0663:                int i, count;
0664:                File entryFile;
0665:                CVSEntry entry;
0666:                CVSEntryVector entries;
0667:                boolean result = true;
0668:
0669:                count = request.getEntries().size();
0670:                entries = request.getEntries();
0671:
0672:                for (i = 0; result && i < count; ++i) {
0673:                    entry = (CVSEntry) entries.elementAt(i);
0674:
0675:                    entryFile = request.getLocalFile(entry);
0676:
0677:                    result = this .sendCVSEntry(request, entry, entryFile);
0678:
0679:                    if (this .isCanceled())
0680:                        break;
0681:                }
0682:
0683:                return result;
0684:            }
0685:
0686:            public String getStickTag(CVSRequest request, String localDir) {
0687:                String result = "";
0688:                Hashtable stickys = request.getStickys();
0689:                if (stickys != null)
0690:                    result = (String) stickys.get(localDir);
0691:                return (result == null ? "" : result);
0692:            }
0693:
0694:            public boolean sendSticky(CVSRequest request, CVSEntry entry) {
0695:                return this .sendSticky(request, entry.getLocalDirectory());
0696:            }
0697:
0698:            public boolean sendSticky(CVSRequest request, String localDir) {
0699:                boolean result = true;
0700:
0701:                Hashtable stickys = request.getStickys();
0702:
0703:                if (stickys != null) {
0704:                    String tagSpec = (String) stickys.get(localDir);
0705:                    if (tagSpec != null && tagSpec.length() > 1) {
0706:                        result = this .sendLine("Sticky " + tagSpec);
0707:                    }
0708:                }
0709:
0710:                return result;
0711:            }
0712:
0713:            public boolean sendStatic(CVSRequest request, CVSEntry entry) {
0714:                boolean result = true;
0715:
0716:                Hashtable statics = request.getStatics();
0717:                if (statics != null) {
0718:                    String isStatic = (String) statics.get(entry
0719:                            .getLocalDirectory());
0720:
0721:                    if (isStatic != null) {
0722:                        result = this .sendLine("Static-directory");
0723:                    }
0724:                }
0725:
0726:                return result;
0727:            }
0728:
0729:            public boolean sendGlobalArguments(CVSArgumentVector arguments) {
0730:                int i;
0731:                boolean result = true;
0732:
0733:                for (i = 0; i < arguments.size(); ++i) {
0734:                    String argStr = arguments.argumentAt(i);
0735:                    result = this .sendLine("Global_option " + argStr);
0736:                }
0737:
0738:                return result;
0739:            }
0740:
0741:            public boolean sendArguments(CVSArgumentVector arguments) {
0742:                int i;
0743:                String argLine;
0744:                boolean xArg = false;
0745:                boolean result = true;
0746:
0747:                for (i = 0; i < arguments.size(); ++i) {
0748:                    String argStr = arguments.argumentAt(i);
0749:
0750:                    if (argStr.indexOf('\n') < 0) {
0751:                        result = this .sendLine("Argument " + argStr);
0752:                    } else {
0753:                        xArg = false;
0754:
0755:                        StringTokenizer toker = new StringTokenizer(argStr,
0756:                                "\n");
0757:
0758:                        for (; result;) {
0759:                            try {
0760:                                argLine = toker.nextToken();
0761:                            } catch (NoSuchElementException ex) {
0762:                                break;
0763:                            }
0764:
0765:                            String prefix = (xArg ? "Argumentx " : "Argument ");
0766:
0767:                            result = this .sendLine(prefix + argLine);
0768:                            xArg = true;
0769:                        }
0770:                    }
0771:                }
0772:
0773:                return result;
0774:            }
0775:
0776:            public boolean sendEntriesArguments(CVSRequest request) {
0777:                int i;
0778:                CVSEntry entry;
0779:                boolean result = true;
0780:
0781:                CVSArgumentVector args;
0782:                CVSEntryVector entries = request.getEntries();
0783:
0784:                if (entries.size() < 1)
0785:                    return true;
0786:
0787:                args = new CVSArgumentVector(entries.size());
0788:
0789:                for (i = 0; i < entries.size(); ++i) {
0790:                    entry = (CVSEntry) entries.elementAt(i);
0791:
0792:                    String argName = request.execInCurDir ? entry.getName()
0793:                            : entry.getArgumentName();
0794:
0795:                    // NOTE, if we leave the trailing slash on dir
0796:                    //       names (e.g. './subdir/'), then the server
0797:                    //       sends use names with double slashes '//'
0798:                    //       in the responses.
0799:                    //
0800:                    argName = CVSCUtilities.stripFinalSlash(argName);
0801:
0802:                    args.addElement(argName);
0803:                }
0804:
0805:                result = sendArguments(args);
0806:
0807:                return result;
0808:            }
0809:
0810:            public boolean sendNotifies(CVSRequest request) {
0811:                String lastWDir = "";
0812:                boolean result = true;
0813:                int num = request.notifies.size();
0814:
0815:                for (int i = 0; result && i < num; ++i) {
0816:                    CVSNotifyItem notify = (CVSNotifyItem) request.notifies
0817:                            .elementAt(i);
0818:
0819:                    String dir = notify.getWorkingDirectory();
0820:                    if (dir.endsWith("/"))
0821:                        dir = dir.substring(0, dir.length() - 1);
0822:
0823:                    if (!lastWDir.equals(dir)) {
0824:                        lastWDir = dir;
0825:                        result = this .sendLine("Directory .");
0826:                        result = this .sendLine(notify.getRepository());
0827:                    }
0828:
0829:                    result = this .sendLine("Notify " + notify.getName());
0830:
0831:                    if (result)
0832:                        result = this .sendLine(notify.getServerExtra());
0833:                }
0834:
0835:                return result;
0836:            }
0837:
0838:            public CVSResponse buildErrorResponse(CVSRequest request,
0839:                    CVSResponse response, String message) {
0840:                response.setStatus(CVSResponse.ERROR);
0841:
0842:                response.appendStderr("The CVS Request failed.\n");
0843:
0844:                if (message.length() > 0) {
0845:                    response.appendStderr(message + "\n");
0846:                }
0847:
0848:                if (this .getReason().length() > 0) {
0849:                    response.appendStderr(this .getReason() + "\n");
0850:                }
0851:
0852:                CVSTracer.traceIf(request.traceRequest,
0853:                        "CVSClient.buildErrorReponse: " + response.getStderr());
0854:
0855:                return response;
0856:            }
0857:
0858:            public boolean performLogin(CVSRequest request) {
0859:                CVSTracer.traceIf(request.traceRequest,
0860:                        "AUTHENTICATE: verifyOnly? '"
0861:                                + request.verificationOnly + "' userName '"
0862:                                + request.getUserName() + "' password '"
0863:                                + request.getPassword() + "'");
0864:
0865:                this .sendLine("BEGIN "
0866:                        + (request.verificationOnly ? "VERIFICATION" : "AUTH")
0867:                        + " REQUEST");
0868:
0869:                this .sendLine(request.getRootDirectory());
0870:                this .sendLine(request.getUserName());
0871:                this .sendLine(request.getPassword());
0872:
0873:                this .sendLine("END "
0874:                        + (request.verificationOnly ? "VERIFICATION" : "AUTH")
0875:                        + " REQUEST");
0876:
0877:                String reply = this .readLine();
0878:
0879:                CVSTracer.traceIf(request.traceRequest,
0880:                        "AUTHENTICATE: REPLY: '" + reply + "'");
0881:
0882:                if (reply != null)
0883:                    if (reply.startsWith("I LOVE YOU"))
0884:                        return true;
0885:
0886:                if (reply != null && reply.length() > 0) {
0887:                    this .setReason(reply);
0888:                }
0889:
0890:                return false;
0891:            }
0892:
0893:            public boolean requestValidRequests(CVSRequest request) {
0894:                boolean result = true;
0895:
0896:                request.validRequests = null;
0897:                request.useUnchanged = false;
0898:                request.useDirectory = true;
0899:
0900:                this .sendLine("valid-requests");
0901:
0902:                // REVIEW
0903:                // Should we clone the request and work with a copy?!
0904:                //
0905:                boolean saveQueue = request.queueResponse;
0906:                request.queueResponse = true;
0907:
0908:                CVSResponse validResponse = new CVSResponse();
0909:
0910:                this .readAndParseResponse(request, validResponse);
0911:
0912:                request.queueResponse = saveQueue;
0913:
0914:                if (validResponse.getStatus() == CVSResponse.OK) {
0915:                    CVSResponseItem item = validResponse
0916:                            .getFirstItemByType(CVSResponseItem.VALID_REQUESTS);
0917:
0918:                    if (item == null) {
0919:                        CVSTracer
0920:                                .traceIf(false,
0921:                                        "REQUEST-VALID-REQUESTS: NO VALID-REQUESTS ITEM!!");
0922:                    } else {
0923:                        String valids = item.getValidRequests();
0924:                        request.validRequests = valids;
0925:
0926:                        int index;
0927:
0928:                        index = valids.indexOf("Directory");
0929:                        if (index >= 0) {
0930:                            request.useDirectory = true;
0931:                        } else {
0932:                            result = false;
0933:                            CVSTracer
0934:                                    .traceIf(
0935:                                            true,
0936:                                            "WARNING: This server does not support "
0937:                                                    + "the 'Directory' request.\n"
0938:                                                    + "jCVS will not operate properly with this server.\n"
0939:                                                    + "Please update your cvs server to release "
0940:                                                    + "1.9 or later.");
0941:                        }
0942:
0943:                        index = valids.indexOf("UseUnchanged");
0944:                        if (index >= 0) {
0945:                            request.useUnchanged = true;
0946:                        }
0947:                    }
0948:                } else {
0949:                    request.useDirectory = true;
0950:                    CVSTracer
0951:                            .traceIf(
0952:                                    true,
0953:                                    "Recevied an error from the cvs server while\n"
0954:                                            + "requesting 'valid-requests'. This is not a good sign.\n\n"
0955:                                            + validResponse.getStdout() + "\n"
0956:                                            + validResponse.getStderr());
0957:                }
0958:
0959:                return result;
0960:            }
0961:
0962:            /**
0963:             * This method is the <em>heart</em> of the CVSClient class.
0964:             * Given a CVSRequest, this method will perform all of the
0965:             * processing required to open the connection, authenticate,
0966:             * send all requests, read all responses, and package the
0967:             * responses into a CVSResponse object, which is returned
0968:             * as the result of this method. The result is guaranteed
0969:             * to not be null, and will have its status set to indicate
0970:             * the status of the reuest. The resulting response object
0971:             * should be handed into the CVSProject's processCVSResponse()
0972:             * method to process the server's reponses on the local
0973:             * project contents.
0974:             *
0975:             * @param request The CVSRequest describing our request.
0976:             */
0977:            public CVSResponse processCVSRequest(CVSRequest request) {
0978:                return this .processCVSRequest(request, new CVSResponse());
0979:            }
0980:
0981:            public boolean isCanceled() {
0982:                synchronized (this .canLock) {
0983:                    return this .canceled;
0984:                }
0985:            }
0986:
0987:            public void setCanceled(boolean can) {
0988:                synchronized (this .canLock) {
0989:                    this .canceled = can;
0990:                }
0991:            }
0992:
0993:            public boolean checkForCancel(CVSResponse response) {
0994:                if (this .isCanceled()) {
0995:                    response.setStatus(CVSResponse.ERROR);
0996:                    response
0997:                            .appendStderr("\n*** The CVS request was canceled.\n");
0998:                    if (this .serverIsOpen)
0999:                        this .closeServer();
1000:                    return true;
1001:                } else {
1002:                    return false;
1003:                }
1004:            }
1005:
1006:            public CVSResponse processCVSRequest(CVSRequest request,
1007:                    CVSResponse response) {
1008:                this .setCanceled(false);
1009:
1010:                boolean isok = true;
1011:                CVSEntryVector entries;
1012:                CVSArgumentVector arguments;
1013:                CVSArgumentVector globalargs;
1014:
1015:                String[] vars = request.getSetVariables();
1016:
1017:                this .usingGZIP = false;
1018:                this .setReason("");
1019:                this .recentEntryRepository = "";
1020:                this .dirHash = new Hashtable();
1021:
1022:                CVSUserInterface ui = request.getUserInterface();
1023:
1024:                // EH-null-ui  Etienne-Hugues Fortin <ehfortin@sympatico.ca>
1025:                if (ui == null) {
1026:                    ui = this .new NullCVSUI();
1027:                }
1028:
1029:                this .tracingTCPData = request.traceTCPData;
1030:
1031:                entries = request.getEntries();
1032:                arguments = request.getArguments();
1033:                globalargs = request.getGlobalArguments();
1034:
1035:                if (request.traceRequest) {
1036:                    CVSTracer.traceIf(true, "========================"
1037:                            + " CVSClient.processCVSRequest "
1038:                            + "========================");
1039:                    CVSTracer.traceIf(true, "   Command:        "
1040:                            + request.getCommand());
1041:                    CVSTracer.traceIf(true, "   Repository:     "
1042:                            + request.getRepository());
1043:                    CVSTracer.traceIf(true, "   RootRepository: "
1044:                            + request.getRootRepository());
1045:                    CVSTracer.traceIf(true, "   CVSServer:      "
1046:                            + request.getPort() + "@" + request.getHostName());
1047:                    CVSTracer.traceIf(true, "   RootDirectory:  "
1048:                            + request.getRootDirectory());
1049:                    CVSTracer.traceIf(true, "   LocalDirectory: "
1050:                            + request.getLocalDirectory());
1051:                    CVSTracer
1052:                            .traceIf(
1053:                                    true,
1054:                                    "   Connect Method: "
1055:                                            + (request.getConnectionMethod() == CVSRequest.METHOD_RSH ? "RSH"
1056:                                                    : (request
1057:                                                            .getConnectionMethod() == CVSRequest.METHOD_SSH ? "SSH"
1058:                                                            : "INETD")));
1059:                    CVSTracer.traceIf(true, "   Rsh Command:    "
1060:                            + request.getRshProcess());
1061:                    CVSTracer.traceIf(true, "   Server Command: "
1062:                            + request.getServerCommand());
1063:                    CVSTracer.traceIf(true, "   isPServer?      '"
1064:                            + (request.isPServer() ? "true " : "false") + "'"
1065:                            + "   user '" + request.getUserName() + "'"
1066:                            + "   pass '" + request.getPassword() + "'");
1067:                    CVSTracer.traceIf(true, "   There are "
1068:                            + (vars == null ? "no" : ("" + vars.length))
1069:                            + " user set variables.");
1070:                    CVSTracer.traceIf(true, "   NumEntries:      "
1071:                            + (entries == null ? 0 : entries.size())
1072:                            + "        NumArguments:     "
1073:                            + (arguments == null ? 0 : arguments.size()));
1074:                    CVSTracer.traceIf(true, "   GlobalOptions:   "
1075:                            + (globalargs == null ? 0 : globalargs.size())
1076:                            + "        GzipStreamLevel:  "
1077:                            + request.getGzipStreamLevel());
1078:                    CVSTracer.traceIf(true, "   redirectOutput  '"
1079:                            + (request.redirectOutput ? "true " : "false")
1080:                            + "'" + "   execInCurDir    '"
1081:                            + (request.execInCurDir ? "true " : "false") + "'");
1082:                    CVSTracer.traceIf(true, "   sendEntries     '"
1083:                            + (request.sendEntries ? "true " : "false") + "'"
1084:                            + "   sendEntryfiles  '"
1085:                            + (request.sendEntryFiles ? "true " : "false")
1086:                            + "'");
1087:                    CVSTracer
1088:                            .traceIf(true, "   sendModifieds   '"
1089:                                    + (request.sendModifieds ? "true "
1090:                                            : "false")
1091:                                    + "'"
1092:                                    + "   sendEmptyMods   '"
1093:                                    + (request.sendEmptyMods ? "true "
1094:                                            : "false") + "'");
1095:                    CVSTracer.traceIf(true, "   sendArguments   '"
1096:                            + (request.sendArguments ? "true " : "false") + "'"
1097:                            + "   ignoreResult    '"
1098:                            + (request.ignoreResult ? "true " : "false") + "'");
1099:                    CVSTracer.traceIf(true, "   sendModule      '"
1100:                            + (request.sendModule ? "true " : "false") + "'"
1101:                            + "   allowOverWrites '"
1102:                            + (request.allowOverWrites ? "true " : "false")
1103:                            + "'");
1104:                    CVSTracer
1105:                            .traceIf(true, "   displayReponse  '"
1106:                                    + (request.displayReponse ? "true "
1107:                                            : "false")
1108:                                    + "'"
1109:                                    + "   handleUpdated   '"
1110:                                    + (request.handleUpdated ? "true "
1111:                                            : "false") + "'");
1112:                    CVSTracer.traceIf(true, "   handleMerged    '"
1113:                            + (request.handleMerged ? "true " : "false") + "'"
1114:                            + "   handleCopyFile  '"
1115:                            + (request.handleCopyFile ? "true " : "false")
1116:                            + "'");
1117:                    CVSTracer.traceIf(true, "   handleEntries   '"
1118:                            + (request.handleEntries ? "true " : "false") + "'"
1119:                            + "   handleFlags     '"
1120:                            + (request.handleFlags ? "true " : "false") + "'");
1121:                    CVSTracer.traceIf(true, "   queueResponse   '"
1122:                            + (request.queueResponse ? "true " : "false")
1123:                            + "'"
1124:                            + "   responseHandler '"
1125:                            + (request.responseHandler == null ? "null "
1126:                                    : request.responseHandler.getClass()
1127:                                            .getName()) + "'");
1128:                    CVSTracer.traceIf(true, "   includeNotifies '"
1129:                            + (request.includeNotifies ? "true " : "false")
1130:                            + "'"
1131:                            + "   notifiesSize    '"
1132:                            + (request.notifies == null ? "null"
1133:                                    : ("" + request.notifies.size())) + "'");
1134:
1135:                    CVSTracer.traceIf(request.traceRequest,
1136:                            "***************************************"
1137:                                    + "**************************************");
1138:                } // if ( request.traceRequest )
1139:
1140:                // SPECIAL HACKS
1141:                //
1142:                // For the "ci" command (commit), if the user has provided
1143:                // the '-f' option, then we need to force all files to go
1144:                // up as 'Modified'.
1145:                //
1146:                if ("ci".equals(request.getCommand())) {
1147:                    if (request.getArguments().containsArgument("-f")) {
1148:                        CVSTracer.traceIf(request.traceRequest,
1149:                                "SPECIAL CASE: Forcing all files to be "
1150:                                        + "'Modified' for '-f' commit.");
1151:                        request.forceModifieds = true;
1152:                    }
1153:                }
1154:
1155:                int portNum = request.getPort();
1156:
1157:                if (portNum == 0) {
1158:                    CVSTracer.traceIf(request.traceRequest,
1159:                            "CVSRequest: default port number to '" + this .port
1160:                                    + "'");
1161:                    portNum = this .port;
1162:                }
1163:
1164:                if (this .checkForCancel(response)) {
1165:                    return response;
1166:                }
1167:
1168:                CVSTracer.traceIf(request.traceRequest,
1169:                        "CVSRequest: opening server...");
1170:
1171:                ui.uiDisplayProgressMsg("Opening server '" + request.getPort()
1172:                        + "@" + request.getHostName() + "'...");
1173:
1174:                isok = this .openServer(request);
1175:
1176:                CVSTracer.traceIf(request.traceRequest,
1177:                        "CVSRequest: server is " + (isok ? "" : "not ")
1178:                                + "open.");
1179:
1180:                if (!isok) {
1181:                    String why = this .getReason();
1182:
1183:                    this .buildErrorResponse(request, response,
1184:                            "Failed to open socket to connect to cvs server '"
1185:                                    + request.getPort() + "@"
1186:                                    + request.getHostName() + "'.\n" + why);
1187:
1188:                    ui.uiDisplayProgressMsg("Failed to open '"
1189:                            + request.getPort() + "@" + request.getHostName()
1190:                            + "'.");
1191:
1192:                    return response;
1193:                }
1194:
1195:                if (this .checkForCancel(response)) {
1196:                    return response;
1197:                }
1198:
1199:                if (request.isPServer()) {
1200:                    if (request.getUserName() == null
1201:                            || request.getPassword() == null) {
1202:                        this 
1203:                                .buildErrorResponse(
1204:                                        request,
1205:                                        response,
1206:                                        "Attempted to connect to a password"
1207:                                                + " cvs server without a "
1208:                                                + ((request.getUserName() == null) ? "username"
1209:                                                        : "password") + ".\n");
1210:
1211:                        ui
1212:                                .uiDisplayProgressMsg("Incomplete login. Request canceled.");
1213:
1214:                        return response;
1215:                    }
1216:
1217:                    ui.uiDisplayProgressMsg("Authenticating '"
1218:                            + request.getUserName() + "@"
1219:                            + request.getHostName() + "'...");
1220:
1221:                    if (!this .performLogin(request)) {
1222:                        this .buildErrorResponse(request, response,
1223:                                "Failed authentication with the user name '"
1224:                                        + request.getUserName() + "'.\n");
1225:
1226:                        ui.uiDisplayProgressMsg("Authentication of '"
1227:                                + request.getUserName() + "@"
1228:                                + request.getHostName() + "' failed.");
1229:
1230:                        return response;
1231:                    }
1232:                }
1233:
1234:                if (request.verificationOnly) {
1235:                    String authResultStr = "Authentication of '"
1236:                            + request.getUserName() + "@"
1237:                            + request.getHostName() + "' succeeded.";
1238:
1239:                    ui.uiDisplayProgressMsg(authResultStr);
1240:
1241:                    response.setStatus(CVSResponse.OK);
1242:                    response.appendStderr(authResultStr);
1243:
1244:                    this .closeServer();
1245:
1246:                    return response;
1247:                }
1248:
1249:                if (this .checkForCancel(response)) {
1250:                    return response;
1251:                }
1252:
1253:                if (isok) {
1254:                    isok = this .requestValidRequests(request);
1255:                }
1256:
1257:                CVSTracer.traceIf(request.traceRequest,
1258:                        "Valid Requests:  useUnchanged '"
1259:                                + (request.useUnchanged ? "true" : "false")
1260:                                + "'" + "   useDirectory '"
1261:                                + (request.useDirectory ? "true" : "false")
1262:                                + "'");
1263:
1264:                if (this .checkForCancel(response)) {
1265:                    return response;
1266:                }
1267:
1268:                if (isok && request.sendRootDirectory) {
1269:                    CVSTracer.traceIf(request.traceRequest,
1270:                            "CVSRequest: send root directory...");
1271:
1272:                    // SPECIAL-CASE (?)
1273:                    // If there's no rootDirectory, then don't
1274:                    // send the command. This is only used by the
1275:                    // 'noop' used by the Test Connection dialog.
1276:                    //
1277:                    if (request.getRootDirectory().length() > 0) {
1278:                        isok = this .sendCVSRootDirectory(request);
1279:                    }
1280:                }
1281:
1282:                // Establish GzipStream is requested (level > 0).
1283:                //
1284:                if (isok && request.gzipStreamLevel > 0
1285:                        && request.validRequests != null
1286:                        && request.validRequests.indexOf("Gzip-stream") >= 0) {
1287:                    CVSTracer.traceIf(request.traceRequest,
1288:                            "Utilitizing Gzip-stream mode at level 6.");
1289:                    this .usingGZIP = true;
1290:                    this .sendLine("Gzip-stream 6");
1291:                    this .instream = new InflaterInputStream(this .instream);
1292:                    this .outstream = new DeflaterOutputStream(this .outstream);
1293:                }
1294:
1295:                if (isok) {
1296:                    isok = this .sendSetVariables(request);
1297:                }
1298:
1299:                ui.uiDisplayProgressMsg("Negotiating cvs protocol...");
1300:
1301:                this .sendValidResponses(request, "");
1302:
1303:                ui.uiDisplayProgressMsg("Sending command request, '"
1304:                        + request.getCommand() + "'...");
1305:
1306:                if (isok
1307:                        && request.allowGzipFileMode
1308:                        && (!this .usingGZIP)
1309:                        && request.validRequests != null
1310:                        && request.validRequests.indexOf("gzip-file-contents") >= 0) {
1311:                    CVSTracer.traceIf(request.traceRequest,
1312:                            "Utilitizing gzip-file-contents mode at level 6.");
1313:
1314:                    this .sendLine("gzip-file-contents 6");
1315:                    request.gzipFileMode = true;
1316:                }
1317:
1318:                if (this .checkForCancel(response)) {
1319:                    return response;
1320:                }
1321:
1322:                CVSArgumentVector globalArgs = request.getGlobalArguments();
1323:                if (isok & globalArgs != null && globalArgs.size() > 0) {
1324:                    isok = this .sendGlobalArguments(globalArgs);
1325:                }
1326:
1327:                if (isok & request.notifies != null
1328:                        && request.notifies.size() > 0) {
1329:                    isok = this .sendNotifies(request);
1330:                }
1331:
1332:                // NOTE The "request.sendEntries" flag is not checked here!
1333:                //      It is utilized inside sendCVSEntries().
1334:                if (isok) {
1335:                    CVSTracer.traceIf(request.traceRequest,
1336:                            "CVSRequest: send entries...");
1337:                    isok = this .sendCVSEntries(request);
1338:                }
1339:
1340:                if (this .checkForCancel(response)) {
1341:                    return response;
1342:                }
1343:
1344:                if (isok && request.sendRootDirectory) {
1345:                    if (request.execInCurDir && request.getDirEntry() != null) {
1346:                        // Set the 'current directory'...
1347:                        CVSTracer.traceIf(request.traceRequest,
1348:                                "CVSRequest: send 'current' directory...");
1349:                        this .recentEntryRepository = ""; // make sure it goes...
1350:                        isok = this .sendEntryRepository(request, request
1351:                                .getDirEntry());
1352:                    } else {
1353:                        // Reset the 'current directory' to the top level...
1354:                        CVSTracer.traceIf(request.traceRequest,
1355:                                "CVSRequest: send root repository...");
1356:
1357:                        isok = this .sendRootRepository(request);
1358:                    }
1359:                }
1360:
1361:                if (this .checkForCancel(response)) {
1362:                    return response;
1363:                }
1364:
1365:                if (isok && request.sendArguments) {
1366:                    CVSTracer.traceIf(request.traceRequest,
1367:                            "CVSRequest: send arguments...");
1368:                    isok = this .sendArguments(request.getArguments());
1369:                }
1370:
1371:                if (this .checkForCancel(response)) {
1372:                    return response;
1373:                }
1374:
1375:                if (isok && request.sendEntryFiles) {
1376:                    CVSTracer.traceIf(request.traceRequest,
1377:                            "CVSRequest: send files...");
1378:                    isok = this .sendEntriesArguments(request);
1379:                }
1380:
1381:                if (this .checkForCancel(response)) {
1382:                    return response;
1383:                }
1384:
1385:                if (isok && request.sendModule) {
1386:                    CVSTracer.traceIf(request.traceRequest,
1387:                            "CVSRequest: send module name...");
1388:                    isok = this .sendCVSModule(request);
1389:                }
1390:
1391:                if (isok) {
1392:                    CVSTracer.traceIf(request.traceRequest,
1393:                            "CVSRequest: send command '" + request.getCommand()
1394:                                    + "'");
1395:
1396:                    isok = this .sendLine(request.getCommand());
1397:                }
1398:
1399:                if (this .checkForCancel(response)) {
1400:                    return response;
1401:                }
1402:
1403:                try {
1404:                    if (usingGZIP) {
1405:                        ((DeflaterOutputStream) this .outstream).finish();
1406:
1407:                        // SW-flush-output
1408:                        // Since out GZIP stream was wrapped in a BufferedOutputStream
1409:                        // we need to flush() to move it all out.
1410:                        //
1411:                        outstream.flush();
1412:                    }
1413:                } catch (IOException ex) {
1414:                    ex.printStackTrace();
1415:                }
1416:
1417:                if (isok) {
1418:                    CVSTracer.traceIf(request.traceRequest,
1419:                            "CVSRequest: reading response...");
1420:
1421:                    ui.uiDisplayProgressMsg("Reading server response...");
1422:
1423:                    this .readAndParseResponse(request, response);
1424:                } else {
1425:                    CVSTracer.traceIf(request.traceRequest,
1426:                            "CVSRequest: Error sending command request.");
1427:
1428:                    ui.uiDisplayProgressMsg("Error sending command request...");
1429:
1430:                    this 
1431:                            .buildErrorResponse(
1432:                                    request,
1433:                                    response,
1434:                                    "during processing of cvs request"
1435:                                            + ((this .getReason().length() < 1) ? ""
1436:                                                    : (": {" + this .getReason() + "}")));
1437:                }
1438:
1439:                ui.uiDisplayProgressMsg("Closing CVS server connection.");
1440:
1441:                this .closeServer();
1442:
1443:                if (this .checkForCancel(response)) {
1444:                    return response;
1445:                }
1446:
1447:                CVSTracer.traceIf(request.traceRequest,
1448:                        "**====================================="
1449:                                + "====================================**");
1450:
1451:                ui.uiDisplayProgressMsg("Command completed with '"
1452:                        + (response.getStatus() == CVSResponse.OK ? "ok"
1453:                                : "error") + "' status.");
1454:
1455:                return response;
1456:            }
1457:
1458:            private String generateTempName() {
1459:                this .tempCounter++;
1460:
1461:                String randStr = Long
1462:                        .toHexString(this .tempCounter % 0x0FFFFFFF);
1463:
1464:                if (randStr.length() > 7) {
1465:                    randStr = randStr.substring(randStr.length() - 7);
1466:                }
1467:
1468:                String result = "T" + randStr + ".cvs";
1469:
1470:                CVSTracer.traceIf(false, "TEMPFILE: counter '"
1471:                        + this .tempCounter + "' name '" + result + "'");
1472:
1473:                return result;
1474:            }
1475:
1476:            public String generateTempPath() {
1477:                String path = null;
1478:
1479:                for (;;) {
1480:                    path = this .tempPath + "/" + this .generateTempName();
1481:
1482:                    File tFile = new File(path);
1483:
1484:                    if (!tFile.exists())
1485:                        break;
1486:
1487:                    if (true)
1488:                        CVSTracer
1489:                                .traceWithStack("CVSClient.generateTempPath: ERROR '"
1490:                                        + path + "' exists!");
1491:                }
1492:
1493:                return path;
1494:            }
1495:
1496:            private boolean requestIsQueued(CVSRequest request) {
1497:                return (request.queueResponse || request.responseHandler == null);
1498:            }
1499:
1500:            private boolean processResponseItem(CVSRequest request,
1501:                    CVSResponse response, CVSResponseItem item) {
1502:                boolean result = true;
1503:
1504:                // NOTE
1505:                // SPECIAL CASE
1506:                // We need to handle the local directories returned when we use
1507:                // the "exec in directory" feature. This is because the  paths
1508:                // being returned are relative to this directory, and correcting
1509:                // the path here is the simplest and best way to fix it.
1510:                //
1511:                if (request.execInCurDir && request.getDirEntry() != null) {
1512:                    String itemPath = item.getPathName();
1513:                    String pfxPath = request.getDirEntry().getLocalPathName();
1514:
1515:                    if (itemPath != null) {
1516:                        if (itemPath.startsWith("./"))
1517:                            itemPath = pfxPath + itemPath.substring(2);
1518:                        else
1519:                            itemPath = pfxPath + itemPath;
1520:
1521:                        item.setPathName(itemPath);
1522:                    }
1523:                }
1524:
1525:                if (this .requestIsQueued(request)) {
1526:                    response.addResponseItem(item);
1527:                } else {
1528:                    result = request.responseHandler.handleResponseItem(
1529:                            request, response, item);
1530:                }
1531:
1532:                return result;
1533:            }
1534:
1535:            public CVSResponse readAndParseResponse(CVSRequest request,
1536:                    CVSResponse response) {
1537:                boolean isok;
1538:                int status = CVSResponse.OK;
1539:                boolean gotStatus = false;
1540:                int fileSize;
1541:                int index;
1542:                String line = null;
1543:
1544:                CVSResponseItem currItem = null;
1545:
1546:                for (isok = true; isok;) {
1547:                    if (this .isCanceled())
1548:                        break;
1549:
1550:                    line = this .readLine();
1551:
1552:                    if (line == null) {
1553:                        CVSTracer.traceIf(request.traceResponse,
1554:                                "PARSE: End of file on input stream.");
1555:                        break;
1556:                    }
1557:
1558:                    CVSTracer.traceIf(false,
1559:                            "CVSClient.readAndParseResponse: INLINE '"
1560:                                    + line
1561:                                    + "' currItem '"
1562:                                    + (currItem == null ? "(null)" : currItem
1563:                                            .toString()) + "'");
1564:
1565:                    if (currItem != null) {
1566:                        int itemType = currItem.getType();
1567:
1568:                        if (currItem.getAddState() == CVSResponseItem.GET_FULL_PATH) {
1569:                            CVSTracer.traceIf(request.traceResponse,
1570:                                    "PARSE: FullPath '" + line + "'");
1571:
1572:                            if (line.endsWith("/./")) {
1573:                                // SPECIAL CASE
1574:                                // When the user does something like "-d ." on
1575:                                // an update or checkout, we will get repository
1576:                                // names that look like "/usr/cvsroot/path/./".
1577:                                // This confuses our code, so we adjust here...
1578:                                line = line.substring(0, line.length() - 2);
1579:                                CVSTracer.traceIf(request.traceResponse,
1580:                                        "PARSE: Adjusted FullPath '" + line
1581:                                                + "'");
1582:                            }
1583:
1584:                            currItem.setRepositoryName(line);
1585:                        } else if (currItem.getAddState() == CVSResponseItem.GET_ENTRIES_LINE) {
1586:                            CVSTracer.traceIf(request.traceResponse,
1587:                                    "PARSE: Entry '" + line + "'");
1588:                            currItem.setEntriesLine(line);
1589:                        } else if (currItem.getAddState() == CVSResponseItem.GET_MODE_LINE) {
1590:                            CVSTracer.traceIf(request.traceResponse,
1591:                                    "PARSE: Mode '" + line + "'");
1592:                            currItem.setModeLine(line);
1593:                        } else if (currItem.getAddState() == CVSResponseItem.GET_TAG_SPEC) {
1594:                            CVSTracer.traceIf(request.traceResponse,
1595:                                    "PARSE: Tag Spec '" + line + "'");
1596:                            currItem.setTagSpec(line);
1597:                        } else if (currItem.getAddState() == CVSResponseItem.GET_PROGRAM) {
1598:                            CVSTracer.traceIf(request.traceResponse,
1599:                                    "PARSE: Program Name '" + line + "'");
1600:                            currItem.setProgram(line);
1601:                        } else if (currItem.getAddState() == CVSResponseItem.GET_NEW_NAME) {
1602:                            CVSTracer.traceIf(request.traceResponse,
1603:                                    "PARSE: New Name '" + line + "'");
1604:                            currItem.setNewName(line);
1605:                        }
1606:
1607:                        switch (itemType) {
1608:                        case CVSResponseItem.CREATED:
1609:                        case CVSResponseItem.MERGED:
1610:                        case CVSResponseItem.PATCHED:
1611:                        case CVSResponseItem.UPDATED:
1612:                        case CVSResponseItem.UPDATE_EXISTING:
1613:                            String itemCmdName = (itemType == CVSResponseItem.CREATED ? "Created"
1614:                                    : (itemType == CVSResponseItem.MERGED ? "Merged"
1615:                                            : (itemType == CVSResponseItem.PATCHED ? "Patched"
1616:                                                    : (itemType == CVSResponseItem.UPDATED ? "Updated"
1617:                                                            : "Update-existing"))));
1618:
1619:                            switch (currItem.getAddState()) {
1620:                            case CVSResponseItem.GET_FULL_PATH:
1621:                                currItem
1622:                                        .setAddState(CVSResponseItem.GET_ENTRIES_LINE);
1623:                                break;
1624:
1625:                            case CVSResponseItem.GET_ENTRIES_LINE:
1626:                                currItem
1627:                                        .setAddState(CVSResponseItem.GET_MODE_LINE);
1628:                                break;
1629:
1630:                            case CVSResponseItem.GET_MODE_LINE:
1631:                                currItem.setAddState(CVSResponseItem.GET_FILE);
1632:
1633:                                File file = new File(this .generateTempPath());
1634:
1635:                                String name = currItem.getRepositoryName();
1636:                                index = name.lastIndexOf('/');
1637:                                if (index >= 0)
1638:                                    name = name.substring(index + 1);
1639:                                name = currItem.getPathName() + name;
1640:
1641:                                // Only display this when queue-ing, since
1642:                                // the processing typically follows immediately
1643:                                // with its own message...
1644:                                if (this .requestIsQueued(request))
1645:                                    request.getUserInterface()
1646:                                            .uiDisplayProgressMsg(
1647:                                                    "Downloading file '" + name
1648:                                                            + "'...");
1649:
1650:                                if (this .retrieveFile(currItem, file)) {
1651:                                    currItem.setFile(file);
1652:                                    isok = this .processResponseItem(request,
1653:                                            response, currItem);
1654:                                } else {
1655:                                    response.appendStdErr("ERROR downloading '"
1656:                                            + itemCmdName + "' file '" + name
1657:                                            + "'\n      into temporary file '"
1658:                                            + file.getPath() + "'.\n");
1659:                                    response.appendStdErr("REASON "
1660:                                            + this .getReason() + "\n");
1661:
1662:                                    status = CVSResponse.ERROR;
1663:                                }
1664:
1665:                                currItem = null;
1666:                                break;
1667:                            }
1668:                            break;
1669:
1670:                        case CVSResponseItem.CHECKED_IN:
1671:                        case CVSResponseItem.NEW_ENTRY:
1672:                            if (currItem.getAddState() == CVSResponseItem.GET_FULL_PATH) {
1673:                                currItem
1674:                                        .setAddState(CVSResponseItem.GET_ENTRIES_LINE);
1675:                            } else {
1676:                                isok = this .processResponseItem(request,
1677:                                        response, currItem);
1678:                                currItem = null;
1679:                            }
1680:                            break;
1681:
1682:                        case CVSResponseItem.COPY_FILE:
1683:                            if (currItem.getAddState() == CVSResponseItem.GET_FULL_PATH) {
1684:                                currItem
1685:                                        .setAddState(CVSResponseItem.GET_NEW_NAME);
1686:                            } else {
1687:                                isok = this .processResponseItem(request,
1688:                                        response, currItem);
1689:                                currItem = null;
1690:                            }
1691:                            break;
1692:
1693:                        case CVSResponseItem.SET_STICKY:
1694:                            if (currItem.getAddState() == CVSResponseItem.GET_FULL_PATH) {
1695:                                currItem
1696:                                        .setAddState(CVSResponseItem.GET_TAG_SPEC);
1697:                            } else {
1698:                                isok = this .processResponseItem(request,
1699:                                        response, currItem);
1700:                                currItem = null;
1701:                            }
1702:                            break;
1703:
1704:                        case CVSResponseItem.NOTIFIED:
1705:                        case CVSResponseItem.REMOVED:
1706:                        case CVSResponseItem.REMOVE_ENTRY:
1707:
1708:                        case CVSResponseItem.SET_CHECKIN_PROG:
1709:                        case CVSResponseItem.SET_UPDATE_PROG:
1710:
1711:                        case CVSResponseItem.CLEAR_STICKY:
1712:                        case CVSResponseItem.SET_STATIC_DIR:
1713:                        case CVSResponseItem.CLEAR_STATIC_DIR:
1714:
1715:                            isok = this .processResponseItem(request, response,
1716:                                    currItem);
1717:                            currItem = null;
1718:
1719:                            break;
1720:
1721:                        default:
1722:                            CVSLog
1723:                                    .logMsg("PARSE: ERROR unknown currentItem type '"
1724:                                            + currItem.getType() + "'");
1725:                            break;
1726:                        }
1727:                    } else if (line.startsWith("ok")) {
1728:                        CVSTracer.traceIf(request.traceResponse, "PARSE: ok");
1729:                        response.setStatus(CVSResponse.OK);
1730:                        gotStatus = true;
1731:                        break;
1732:                    } else if (line.startsWith("error")) {
1733:                        CVSTracer.traceIf(request.traceResponse,
1734:                                "PARSE: error '" + line + "'");
1735:
1736:                        gotStatus = true;
1737:
1738:                        String errCodeStr = "";
1739:                        String errTextStr = "";
1740:
1741:                        if (line.length() > 6) {
1742:                            line = line.substring(6);
1743:
1744:                            if (line.startsWith(" ")) {
1745:                                errCodeStr = "";
1746:                                errTextStr = line.substring(1);
1747:                            } else {
1748:                                index = line.indexOf(' ');
1749:                                if (index > 0) {
1750:                                    errCodeStr = line.substring(0, index);
1751:                                    errTextStr = line.substring(index + 1);
1752:                                } else {
1753:                                    errCodeStr = "";
1754:                                    errTextStr = line;
1755:                                }
1756:                            }
1757:                        }
1758:
1759:                        response.setErrorStatus(errCodeStr, errTextStr);
1760:
1761:                        break;
1762:                    } else if (line.startsWith("I LOVE YOU")) {
1763:                        // NOTE
1764:                        // We pick up these here, since there might be a
1765:                        // case where we failed to recognize we're a pserver?
1766:                        CVSLog.logMsg("PARSE: GOT LOVE MESSAGE '" + line + "'");
1767:                        // continue on, since we are loved
1768:                    } else if (line.startsWith("I HATE YOU")) {
1769:                        // NOTE
1770:                        // We pick up these here, since there might be a
1771:                        // case where we failed to recognize we're a pserver?
1772:                        CVSLog.logMsg("PARSE: GOT HATE MESSAGE '" + line + "'");
1773:
1774:                        gotStatus = true;
1775:                        response.setErrorStatus("-1", "INVALID LOGIN");
1776:
1777:                        // We SHOULD break, since there may never be more data... 
1778:                        break;
1779:                    } else if (line.startsWith("Updated ")) {
1780:                        String pathName = line.substring(8);
1781:                        CVSTracer.traceIf(request.traceResponse,
1782:                                "PARSE: Update '" + pathName + "'");
1783:
1784:                        CVSResponseItem newItem = new CVSResponseItem(
1785:                                CVSResponseItem.UPDATED);
1786:
1787:                        newItem.setPathName(pathName);
1788:
1789:                        newItem
1790:                                .setAddState(request.useDirectory ? CVSResponseItem.GET_FULL_PATH
1791:                                        : CVSResponseItem.GET_ENTRIES_LINE);
1792:
1793:                        // UNDONE - its an ERROR IF currentItem is NOT NULL!!
1794:                        currItem = newItem;
1795:                    } else if (line.startsWith("Merged ")) {
1796:                        String pathName = line.substring(7);
1797:                        CVSTracer.traceIf(request.traceResponse,
1798:                                "PARSE: Merged '" + pathName + "'");
1799:
1800:                        CVSResponseItem newItem = new CVSResponseItem(
1801:                                CVSResponseItem.MERGED);
1802:
1803:                        newItem.setPathName(pathName);
1804:
1805:                        newItem
1806:                                .setAddState(request.useDirectory ? CVSResponseItem.GET_FULL_PATH
1807:                                        : CVSResponseItem.GET_ENTRIES_LINE);
1808:
1809:                        currItem = newItem;
1810:                    } else if (line.startsWith("Update-existing ")) {
1811:                        String pathName = line.substring(16);
1812:                        CVSTracer.traceIf(request.traceResponse,
1813:                                "PARSE: Update-existing '" + pathName + "'");
1814:
1815:                        CVSResponseItem newItem = new CVSResponseItem(
1816:                                CVSResponseItem.UPDATE_EXISTING);
1817:
1818:                        newItem.setPathName(pathName);
1819:
1820:                        newItem
1821:                                .setAddState(request.useDirectory ? CVSResponseItem.GET_FULL_PATH
1822:                                        : CVSResponseItem.GET_ENTRIES_LINE);
1823:
1824:                        currItem = newItem;
1825:                    } else if (line.startsWith("Created ")) {
1826:                        String pathName = line.substring(8);
1827:                        CVSTracer.traceIf(request.traceResponse,
1828:                                "PARSE: Created '" + pathName + "'");
1829:
1830:                        CVSResponseItem newItem = new CVSResponseItem(
1831:                                CVSResponseItem.CREATED);
1832:
1833:                        newItem.setPathName(pathName);
1834:
1835:                        newItem
1836:                                .setAddState(request.useDirectory ? CVSResponseItem.GET_FULL_PATH
1837:                                        : CVSResponseItem.GET_ENTRIES_LINE);
1838:
1839:                        currItem = newItem;
1840:                    } else if (line.startsWith("Patched ")) {
1841:                        String pathName = line.substring(8);
1842:                        CVSTracer.traceIf(request.traceResponse,
1843:                                "PARSE: Patched '" + pathName + "'");
1844:
1845:                        CVSResponseItem newItem = new CVSResponseItem(
1846:                                CVSResponseItem.PATCHED);
1847:
1848:                        newItem.setPathName(pathName);
1849:
1850:                        newItem
1851:                                .setAddState(request.useDirectory ? CVSResponseItem.GET_FULL_PATH
1852:                                        : CVSResponseItem.GET_ENTRIES_LINE);
1853:
1854:                        currItem = newItem;
1855:                    } else if (line.startsWith("Checksum ")) {
1856:                        String sumStr = line.substring(9);
1857:                        CVSTracer.traceIf(request.traceResponse,
1858:                                "PARSE: Checksum '" + sumStr + "'");
1859:
1860:                        CVSResponseItem newItem = new CVSResponseItem(
1861:                                CVSResponseItem.CHECKSUM);
1862:
1863:                        newItem.setChecksum(sumStr);
1864:
1865:                        isok = this .processResponseItem(request, response,
1866:                                newItem);
1867:                    } else if (line.startsWith("Module-expansion ")) {
1868:                        String pathName = line.substring(17);
1869:                        CVSTracer.traceIf(request.traceResponse,
1870:                                "PARSE: Module-expansion '" + pathName + "'");
1871:
1872:                        CVSResponseItem newItem = new CVSResponseItem(
1873:                                CVSResponseItem.MODULE_EXPANSION);
1874:
1875:                        newItem.setPathName(pathName);
1876:                        //
1877:                        // UNDONE
1878:                        // REVIEW
1879:                        // If module-expansions send two line pathnames when
1880:                        // 'Directory' is in use, we will be out of sync!!!
1881:                        //
1882:                        isok = this .processResponseItem(request, response,
1883:                                newItem);
1884:                    } else if (line.startsWith("Notified ")) {
1885:                        String pathName = line.substring(9);
1886:                        CVSTracer.traceIf(request.traceResponse,
1887:                                "PARSE: Notified '" + pathName + "'");
1888:
1889:                        CVSResponseItem newItem = new CVSResponseItem(
1890:                                CVSResponseItem.NOTIFIED);
1891:
1892:                        newItem.setPathName(pathName);
1893:
1894:                        if (request.useDirectory) {
1895:                            currItem = newItem;
1896:                            newItem.setAddState(CVSResponseItem.GET_FULL_PATH);
1897:                        } else {
1898:                            isok = this .processResponseItem(request, response,
1899:                                    newItem);
1900:                        }
1901:                    } else if (line.startsWith("Removed ")) {
1902:                        String pathName = line.substring(8);
1903:                        CVSTracer.traceIf(request.traceResponse,
1904:                                "PARSE: Removed '" + pathName + "'");
1905:
1906:                        CVSResponseItem newItem = new CVSResponseItem(
1907:                                CVSResponseItem.REMOVED);
1908:
1909:                        newItem.setPathName(pathName);
1910:
1911:                        if (request.useDirectory) {
1912:                            currItem = newItem;
1913:                            newItem.setAddState(CVSResponseItem.GET_FULL_PATH);
1914:                        } else {
1915:                            isok = this .processResponseItem(request, response,
1916:                                    newItem);
1917:                        }
1918:                    } else if (line.startsWith("Remove-entry ")) {
1919:                        String pathName = line.substring(13);
1920:                        CVSTracer.traceIf(request.traceResponse,
1921:                                "PARSE: Remove-entry '" + pathName + "'");
1922:
1923:                        CVSResponseItem newItem = new CVSResponseItem(
1924:                                CVSResponseItem.REMOVE_ENTRY);
1925:
1926:                        newItem.setPathName(pathName);
1927:
1928:                        if (request.useDirectory) {
1929:                            currItem = newItem;
1930:                            newItem.setAddState(CVSResponseItem.GET_FULL_PATH);
1931:                        } else {
1932:                            isok = this .processResponseItem(request, response,
1933:                                    newItem);
1934:                        }
1935:                    } else if (line.startsWith("Checked-in ")) {
1936:                        String pathName = line.substring(11);
1937:                        CVSTracer.traceIf(request.traceResponse,
1938:                                "PARSE: Checked-in '" + pathName + "'");
1939:
1940:                        CVSResponseItem newItem = new CVSResponseItem(
1941:                                CVSResponseItem.CHECKED_IN);
1942:
1943:                        newItem.setPathName(pathName);
1944:
1945:                        newItem
1946:                                .setAddState(request.useDirectory ? CVSResponseItem.GET_FULL_PATH
1947:                                        : CVSResponseItem.GET_ENTRIES_LINE);
1948:
1949:                        currItem = newItem;
1950:                    } else if (line.startsWith("New-entry ")) {
1951:                        String pathName = line.substring(10);
1952:                        CVSTracer.traceIf(request.traceResponse,
1953:                                "PARSE: New-entry '" + pathName + "'");
1954:
1955:                        CVSResponseItem newItem = new CVSResponseItem(
1956:                                CVSResponseItem.NEW_ENTRY);
1957:
1958:                        newItem.setPathName(pathName);
1959:
1960:                        newItem
1961:                                .setAddState(request.useDirectory ? CVSResponseItem.GET_FULL_PATH
1962:                                        : CVSResponseItem.GET_ENTRIES_LINE);
1963:
1964:                        currItem = newItem;
1965:                    } else if (line.startsWith("Copy-file ")) {
1966:                        String pathName = line.substring(10);
1967:                        CVSTracer.traceIf(request.traceResponse,
1968:                                "PARSE: Copy-file '" + pathName + "'");
1969:
1970:                        CVSResponseItem newItem = new CVSResponseItem(
1971:                                CVSResponseItem.COPY_FILE);
1972:
1973:                        newItem.setPathName(pathName);
1974:
1975:                        newItem
1976:                                .setAddState(request.useDirectory ? CVSResponseItem.GET_FULL_PATH
1977:                                        : CVSResponseItem.GET_NEW_NAME);
1978:
1979:                        currItem = newItem;
1980:                    } else if (line.startsWith("Set-sticky ")) {
1981:                        String pathName = line.substring(11);
1982:                        CVSTracer.traceIf(request.traceResponse,
1983:                                "PARSE: Set-sticky '" + pathName + "'");
1984:
1985:                        CVSResponseItem newItem = new CVSResponseItem(
1986:                                CVSResponseItem.SET_STICKY);
1987:
1988:                        newItem.setPathName(pathName);
1989:
1990:                        newItem
1991:                                .setAddState(request.useDirectory ? CVSResponseItem.GET_FULL_PATH
1992:                                        : CVSResponseItem.GET_TAG_SPEC);
1993:
1994:                        currItem = newItem;
1995:                    } else if (line.startsWith("Clear-sticky ")) {
1996:                        String pathName = line.substring(13);
1997:                        CVSTracer.traceIf(request.traceResponse,
1998:                                "PARSE: Clear-sticky '" + pathName + "'");
1999:
2000:                        CVSResponseItem newItem = new CVSResponseItem(
2001:                                CVSResponseItem.CLEAR_STICKY);
2002:
2003:                        newItem.setPathName(pathName);
2004:
2005:                        if (request.useDirectory) {
2006:                            currItem = newItem;
2007:                            newItem.setAddState(CVSResponseItem.GET_FULL_PATH);
2008:                        } else {
2009:                            isok = this .processResponseItem(request, response,
2010:                                    newItem);
2011:                        }
2012:                    } else if (line.startsWith("Set-static-directory ")) {
2013:                        String pathName = line.substring(21);
2014:                        CVSTracer.traceIf(request.traceResponse,
2015:                                "PARSE: Set-static-directory '" + pathName
2016:                                        + "'");
2017:
2018:                        CVSResponseItem newItem = new CVSResponseItem(
2019:                                CVSResponseItem.SET_STATIC_DIR);
2020:
2021:                        newItem.setPathName(pathName);
2022:
2023:                        if (request.useDirectory) {
2024:                            currItem = newItem;
2025:                            newItem.setAddState(CVSResponseItem.GET_FULL_PATH);
2026:                        } else {
2027:                            isok = this .processResponseItem(request, response,
2028:                                    newItem);
2029:                        }
2030:                    } else if (line.startsWith("Clear-static-directory ")) {
2031:                        String pathName = line.substring(23);
2032:                        CVSTracer.traceIf(request.traceResponse,
2033:                                "PARSE: Clear-static-directory '" + pathName
2034:                                        + "'");
2035:
2036:                        CVSResponseItem newItem = new CVSResponseItem(
2037:                                CVSResponseItem.CLEAR_STATIC_DIR);
2038:
2039:                        newItem.setPathName(pathName);
2040:
2041:                        if (request.useDirectory) {
2042:                            currItem = newItem;
2043:                            newItem.setAddState(CVSResponseItem.GET_FULL_PATH);
2044:                        } else {
2045:                            isok = this .processResponseItem(request, response,
2046:                                    newItem);
2047:                        }
2048:                    } else if (line.startsWith("Set-checkin-prog ")) {
2049:                        String pathName = line.substring(17);
2050:                        CVSTracer.traceIf(request.traceResponse,
2051:                                "PARSE: Set-checkin-prog '" + pathName + "'");
2052:
2053:                        CVSResponseItem newItem = new CVSResponseItem(
2054:                                CVSResponseItem.SET_CHECKIN_PROG);
2055:
2056:                        newItem.setPathName(pathName);
2057:
2058:                        newItem.setAddState(CVSResponseItem.GET_PROGRAM);
2059:
2060:                        currItem = newItem;
2061:                    } else if (line.startsWith("Set-update-prog ")) {
2062:                        String pathName = line.substring(16);
2063:                        CVSTracer.traceIf(request.traceResponse,
2064:                                "PARSE: Set-update-prog '" + pathName + "'");
2065:
2066:                        CVSResponseItem newItem = new CVSResponseItem(
2067:                                CVSResponseItem.SET_UPDATE_PROG);
2068:
2069:                        newItem.setPathName(pathName);
2070:
2071:                        newItem.setAddState(CVSResponseItem.GET_PROGRAM);
2072:
2073:                        currItem = newItem;
2074:                    }
2075:                    // REVIEW should these two be passed to 'responseHandler'?
2076:                    else if (line.startsWith("E ")) {
2077:                        //	response.appendStdErr( line.substring(2) + "\n" );
2078:                        if (request.isRedirected()) {
2079:                            request.redirectLine(line.substring(2));
2080:                        } else {
2081:                            response.appendStdErr(line.substring(2) + "\n");
2082:                        }
2083:                    } else if (line.startsWith("M ")) {
2084:                        if (request.isRedirected()) {
2085:                            request.redirectLine(line.substring(2));
2086:                        } else {
2087:                            response.appendStdOut(line.substring(2) + "\n");
2088:                        }
2089:                    } else if (line.startsWith("Valid-requests ")) {
2090:                        CVSResponseItem newItem = new CVSResponseItem(
2091:                                CVSResponseItem.VALID_REQUESTS);
2092:
2093:                        newItem.setValidRequests(line.substring(15));
2094:
2095:                        isok = this .processResponseItem(request, response,
2096:                                newItem);
2097:                    } else {
2098:                        response.appendStdErr("WARNING: stray line:\n   '"
2099:                                + line + "'\n");
2100:                    }
2101:                }
2102:
2103:                if (!this .isCanceled()) {
2104:                    if (gotStatus) {
2105:                        if (status != CVSResponse.OK) {
2106:                            response.setStatus(CVSResponse.ERROR);
2107:                        }
2108:                    } else {
2109:                        response
2110:                                .appendStdErr("\n"
2111:                                        + this .getReason()
2112:                                        + "\nShort response, no status response from server.\n");
2113:                        response.setStatus(CVSResponse.ERROR);
2114:                    }
2115:                }
2116:
2117:                return response;
2118:            }
2119:
2120:            public boolean retrieveFile(CVSResponseItem item, File file) {
2121:                boolean ok = true;
2122:                boolean use_gzip = false;
2123:
2124:                FileOutputStream out = null;
2125:
2126:                int fileSize = 0;
2127:                int bytes = 0;
2128:                int length;
2129:
2130:                String line = null;
2131:
2132:                line = this .readLine();
2133:
2134:                if (line == null) {
2135:                    this 
2136:                            .setReason("CVSClient.retrieveFile: ERROR size line is null!");
2137:                    CVSLog.logMsg(this .getReason());
2138:                    ok = false;
2139:                }
2140:
2141:                if (ok) {
2142:                    if (line.startsWith("z")) {
2143:                        item.setGZIPed(true);
2144:                        line = line.substring(1);
2145:                    }
2146:
2147:                    try {
2148:                        fileSize = Integer.valueOf(line).intValue();
2149:                    } catch (NumberFormatException ex) {
2150:                        this 
2151:                                .setReason("CVSClient.retrieveFile: ERROR size line is invalid '"
2152:                                        + line + "'");
2153:                        CVSLog.logMsg(this .getReason());
2154:                        ok = false;
2155:                    }
2156:                }
2157:
2158:                if (CVSClient.LIMIT_FILE_SIZE) {
2159:                    if (ok) {
2160:                        if (fileSize > CVSClient.MAX_FILE_SIZE) {
2161:                            this 
2162:                                    .setReason("CVSClient.retrieveFile: ERROR size limit of '"
2163:                                            + CVSClient.MAX_FILE_SIZE
2164:                                            + "' exceeded by '"
2165:                                            + fileSize
2166:                                            + "'");
2167:                            CVSLog.logMsg(this .getReason());
2168:                            ok = false;
2169:                        }
2170:                    }
2171:                }
2172:
2173:                if (ok) {
2174:                    try {
2175:                        out = new FileOutputStream(file);
2176:                    } catch (IOException ex) {
2177:                        this 
2178:                                .setReason("CVSClient.retrieveFile: ERROR opening output file '"
2179:                                        + file.getPath()
2180:                                        + "'\n    "
2181:                                        + ex.getMessage());
2182:                        CVSLog.logMsg(this .getReason());
2183:
2184:                        // NOTE we do not set 'ok = false;' here, as we need
2185:                        // to process the downcoming data!!! So, we will have
2186:                        // to overload with 'out == null' for closure.
2187:                    }
2188:                }
2189:
2190:                if (ok) {
2191:                    int i;
2192:                    byte[] buffer;
2193:                    buffer = new byte[8192];
2194:
2195:                    for (length = fileSize; length > 0;) {
2196:                        bytes = (length > 8192 ? 8192 : length);
2197:
2198:                        try {
2199:                            bytes = this .instream.read(buffer, 0, bytes);
2200:                        } catch (IOException ex) {
2201:                            ok = false;
2202:                            this .setReason("CVSClient.retrieveFile: "
2203:                                    + "ERROR reading file data:\n   "
2204:                                    + ex.getMessage());
2205:                            CVSLog.logMsg(this .getReason());
2206:                            break;
2207:                        }
2208:
2209:                        if (bytes < 0)
2210:                            break;
2211:
2212:                        length -= bytes;
2213:
2214:                        if (out != null) {
2215:                            try {
2216:                                out.write(buffer, 0, bytes);
2217:                            } catch (IOException ex) {
2218:                                ok = false;
2219:                                this .setReason("CVSClient.retrieveFile: "
2220:                                        + "ERROR writing output file:\n   "
2221:                                        + ex.getMessage());
2222:                                CVSLog.logMsg(this .getReason());
2223:
2224:                                try {
2225:                                    out.close();
2226:                                } catch (IOException ex2) {
2227:                                }
2228:
2229:                                out = null;
2230:
2231:                                break;
2232:                            }
2233:                        }
2234:
2235:                        if (this .isCanceled())
2236:                            break;
2237:                    }
2238:
2239:                    if (out != null) {
2240:                        // Do NOT set out to null here! See NOTE above.
2241:                        try {
2242:                            out.close();
2243:                        } catch (IOException ex) {
2244:                            this .setReason("CVSClient.retrieveFile: "
2245:                                    + "ERROR closing output file:\n   "
2246:                                    + ex.getMessage());
2247:                            CVSLog.logMsg(this .getReason());
2248:                            ok = false;
2249:                        }
2250:                    }
2251:                }
2252:
2253:                // If out is null, an error occurred!
2254:                return ((ok && (out != null)) ? true : false);
2255:            }
2256:
2257:            public boolean sendFileContents(InputStream in) {
2258:                int bytes;
2259:                boolean result = true;
2260:                byte[] buffer = new byte[16 * 1024];
2261:
2262:                for (; result;) {
2263:                    try {
2264:                        bytes = in.read(buffer, 0, buffer.length);
2265:                    } catch (IOException ex) {
2266:                        result = false;
2267:                        this 
2268:                                .setReason("sendFileRaw: ERROR reading input file: "
2269:                                        + ex.getMessage());
2270:                        CVSLog.logMsg(this .getReason());
2271:                        break;
2272:                    }
2273:
2274:                    if (bytes < 0)
2275:                        break;
2276:
2277:                    try {
2278:                        this .outstream.write(buffer, 0, bytes);
2279:                    } catch (IOException ex) {
2280:                        result = false;
2281:                        this .setReason("sendFileRaw: ERROR writing file data: "
2282:                                + ex.getMessage());
2283:                        CVSLog.logMsg(this .getReason());
2284:                        break;
2285:                    }
2286:
2287:                    if (this .isCanceled())
2288:                        break;
2289:                }
2290:
2291:                try {
2292:                    this .outstream.flush();
2293:                } catch (IOException ex) {
2294:                    result = false;
2295:                    this 
2296:                            .setReason("sendFileRaw: ERROR flushing server connection: "
2297:                                    + ex.getMessage());
2298:                    CVSLog.logMsg(this .getReason());
2299:                }
2300:
2301:                try {
2302:                    in.close();
2303:                } catch (IOException ex) {
2304:                    result = false;
2305:                    this .setReason("sendFileRaw: ERROR closing input file: "
2306:                            + ex.getMessage());
2307:                    CVSLog.logMsg(this .getReason());
2308:                }
2309:
2310:                return result;
2311:            }
2312:
2313:            public boolean sendFileRaw(CVSEntry entry, File entryFile,
2314:                    boolean useGzipFile) {
2315:                int bytes;
2316:                Long sizeLong;
2317:                long fileSize, length;
2318:                boolean result = true;
2319:                boolean usingGzip = false;
2320:                File gzipFile = null;
2321:                BufferedInputStream in = null;
2322:                byte[] buffer = new byte[16 * 1024];
2323:
2324:                fileSize = entryFile.length();
2325:                long beginMillis = System.currentTimeMillis();
2326:
2327:                try {
2328:                    in = new BufferedInputStream(new FileInputStream(entryFile));
2329:                } catch (IOException ex) {
2330:                    result = false;
2331:                }
2332:
2333:                usingGzip = (useGzipFile && (fileSize > MIN_GZIP_SIZE));
2334:
2335:                if (result && usingGzip) {
2336:                    try {
2337:                        gzipFile = new File(this .generateTempPath());
2338:
2339:                        BufferedOutputStream out = new BufferedOutputStream(
2340:                                new GZIPOutputStream(new FileOutputStream(
2341:                                        gzipFile)));
2342:
2343:                        for (;;) {
2344:                            bytes = in.read(buffer, 0, buffer.length);
2345:                            if (bytes < 0)
2346:                                break;
2347:
2348:                            out.write(buffer, 0, bytes);
2349:
2350:                            if (this .isCanceled())
2351:                                break;
2352:                        }
2353:
2354:                        in.close();
2355:                        out.close();
2356:
2357:                        in = new BufferedInputStream(new FileInputStream(
2358:                                gzipFile));
2359:
2360:                        fileSize = gzipFile.length();
2361:                    } catch (IOException ex) {
2362:                        ex.printStackTrace(System.err);
2363:                        result = false;
2364:                    }
2365:                }
2366:
2367:                long endMillis = System.currentTimeMillis();
2368:
2369:                if (false)
2370:                    System.err.println("CVSClient.sendFileRaw: TIME = '"
2371:                            + (endMillis - beginMillis) + "' millis.");
2372:
2373:                if (result) {
2374:                    sizeLong = new Long(fileSize);
2375:                    String sizeStr = sizeLong.toString();
2376:
2377:                    if (usingGzip)
2378:                        sizeStr = "z" + sizeStr;
2379:
2380:                    result = this .sendLine(sizeStr);
2381:                    if (result) {
2382:                        result = this .sendFileContents(in);
2383:                    } else {
2384:                        this .setReason("sendFileRaw: ERROR writing file size: "
2385:                                + this .getReason());
2386:                        CVSLog.logMsg(this .getReason());
2387:                    }
2388:                }
2389:
2390:                if (usingGzip && gzipFile != null && gzipFile.exists()) {
2391:                    try {
2392:                        gzipFile.delete();
2393:                    } catch (SecurityException ex) {
2394:                        // we will leave result, since upload has succeeded...
2395:                        CVSLog
2396:                                .logMsg("sendFileRaw: WARNING deleting temp file: "
2397:                                        + ex.getMessage());
2398:                    }
2399:                }
2400:
2401:                return result;
2402:            }
2403:
2404:            public boolean sendFileAscii(CVSEntry entry, File entryFile,
2405:                    boolean gzipFileMode) {
2406:                String inLine;
2407:                File tempFile;
2408:                BufferedReader in = null;
2409:                BufferedOutputStream out = null;
2410:                boolean usingGzip = false;
2411:                boolean result = true;
2412:
2413:                long beginMillis = System.currentTimeMillis();
2414:
2415:                try {
2416:                    in = new BufferedReader(new FileReader(entryFile));
2417:                } catch (IOException ex) {
2418:                    this .setReason("sendFileAscii: can not open input file '"
2419:                            + entryFile.getPath() + "' " + ex.getMessage());
2420:                    result = false;
2421:                }
2422:
2423:                tempFile = new File(this .generateTempPath());
2424:
2425:                try {
2426:                    if (gzipFileMode && (entryFile.length() > MIN_GZIP_SIZE)) {
2427:                        usingGzip = true;
2428:                        out = new BufferedOutputStream(new GZIPOutputStream(
2429:                                new FileOutputStream(tempFile)));
2430:                    } else {
2431:                        out = new BufferedOutputStream(new FileOutputStream(
2432:                                tempFile));
2433:                    }
2434:                } catch (IOException ex) {
2435:                    result = false;
2436:                    this .setReason("sendFileAscii: can not open output file '"
2437:                            + tempFile.getPath() + "' " + ex.getMessage());
2438:                    CVSLog.logMsg(this .getReason());
2439:                }
2440:
2441:                if (result) {
2442:                    for (;;) {
2443:                        try {
2444:                            //	inLine = in.readLine();
2445:                            inLine = this .readAsciiLine(in);
2446:                            if (inLine == null)
2447:                                break;
2448:
2449:                            out.write(inLine.getBytes());
2450:                            out.write('\012');
2451:                        } catch (IOException ex) {
2452:                            result = false;
2453:                            this 
2454:                                    .setReason("sendFileAscii: failed converting into temp file '"
2455:                                            + tempFile.getPath()
2456:                                            + "' "
2457:                                            + ex.getMessage());
2458:                            CVSLog.logMsg(this .getReason());
2459:                        }
2460:
2461:                        if (this .isCanceled())
2462:                            break;
2463:                    }
2464:
2465:                    try {
2466:                        in.close();
2467:                    } catch (IOException ex) {
2468:                        result = false;
2469:                        this 
2470:                                .setReason("sendFileAscii: ERROR closing input file: "
2471:                                        + ex.getMessage());
2472:                        CVSLog.logMsg(this .getReason());
2473:                    }
2474:                    try {
2475:                        out.close();
2476:                    } catch (IOException ex) {
2477:                        result = false;
2478:                        this 
2479:                                .setReason("sendFileAscii: ERROR closing input file: "
2480:                                        + ex.getMessage());
2481:                        CVSLog.logMsg(this .getReason());
2482:                    }
2483:
2484:                    long endMillis = System.currentTimeMillis();
2485:
2486:                    if (false)
2487:                        System.err.println("CVSClient.sendFileAscii: TIME = '"
2488:                                + (endMillis - beginMillis) + "' millis.");
2489:
2490:                    if (result) {
2491:                        Long sizeLong = new Long(tempFile.length());
2492:                        String sizeStr = sizeLong.toString();
2493:
2494:                        if (usingGzip)
2495:                            sizeStr = "z" + sizeStr;
2496:
2497:                        result = this .sendLine(sizeStr);
2498:                        if (result) {
2499:                            try {
2500:                                BufferedInputStream content = new BufferedInputStream(
2501:                                        new FileInputStream(tempFile));
2502:
2503:                                result = this .sendFileContents(content);
2504:                            } catch (FileNotFoundException ex) {
2505:                                result = false;
2506:                                this 
2507:                                        .setReason("sendFileAscii: failed re-opening temp file '"
2508:                                                + tempFile.getPath()
2509:                                                + "' "
2510:                                                + ex.getMessage());
2511:                                CVSLog.logMsg(this .getReason());
2512:                            }
2513:                        } else {
2514:                            this 
2515:                                    .setReason("sendFileRaw: ERROR writing file size: "
2516:                                            + this .getReason());
2517:                            CVSLog.logMsg(this .getReason());
2518:                        }
2519:
2520:                        try {
2521:                            tempFile.delete();
2522:                        } catch (SecurityException ex) {
2523:                            // we will leave result, since upload has succeeded...
2524:                            CVSLog
2525:                                    .logMsg("sendFileAscii: WARNING deleting temp file: "
2526:                                            + ex.getMessage());
2527:                        }
2528:                    }
2529:                }
2530:
2531:                return result;
2532:            }
2533:
2534:            public String readAsciiLine(Reader in) {
2535:                String ls = System.getProperty("line.separator");
2536:
2537:                int lineSepIdx = 0;
2538:                int lineSepLen = ls.length();
2539:
2540:                char[] lineSep = new char[lineSepLen];
2541:                ls.getChars(0, lineSepLen, lineSep, 0);
2542:
2543:                char ch;
2544:                StringBuffer line = new StringBuffer(132);
2545:
2546:                try {
2547:                    for (;;) {
2548:                        int inByte = in.read();
2549:                        if (inByte == -1) {
2550:                            // Be sure to grab anything in the lineSep buf...
2551:                            for (int i = 0; i < lineSepIdx; ++i)
2552:                                line.append(lineSep[i]);
2553:
2554:                            if (line.length() == 0)
2555:                                line = null;
2556:
2557:                            break;
2558:                        }
2559:
2560:                        ch = (char) inByte;
2561:                        if (ch == lineSep[lineSepIdx]) {
2562:                            // check for completed line separator.
2563:                            if (++lineSepIdx >= lineSepLen)
2564:                                break;
2565:                        } else {
2566:                            // Append any buffered separator chars
2567:                            for (int i = 0; i < lineSepIdx; ++i)
2568:                                line.append(lineSep[i]);
2569:
2570:                            // Reset line separator index
2571:                            lineSepIdx = 0;
2572:
2573:                            if (ch == lineSep[lineSepIdx]) {
2574:                                // check for completed line separator.
2575:                                if (++lineSepIdx >= lineSepLen)
2576:                                    break;
2577:                            } else {
2578:                                // Append read char
2579:                                line.append(ch);
2580:                            }
2581:                        }
2582:                    }
2583:                } catch (IOException ex) {
2584:                    line = null;
2585:                }
2586:
2587:                return (line != null ? line.toString() : null);
2588:            }
2589:
2590:            public boolean sendValidResponses(CVSRequest request,
2591:                    String additional) {
2592:                boolean result = true;
2593:
2594:                result = this .sendLine("Valid-responses "
2595:                        + "E M ok error Valid-requests "
2596:                        + "Created Merged Updated Update-existing "
2597:                        + "Removed Remove-entry New-entry "
2598:                        + "Checked-in Checksum Copy-file Notified "
2599:                        + "Clear-sticky Set-sticky "
2600:                        + "Clear-static-directory Set-static-directory "
2601:                        + additional);
2602:
2603:                if (request.useUnchanged) {
2604:                    this .sendLine("UseUnchanged");
2605:                }
2606:
2607:                return result;
2608:            }
2609:
2610:            public boolean sendString(String string) {
2611:                boolean result = true;
2612:
2613:                CVSTracer.traceIf(this .tracingTCPData,
2614:                        "CVSClient.SENDString: '" + string + "'");
2615:
2616:                try {
2617:                    this .outstream.write(string.getBytes());
2618:                    this .outstream.flush();
2619:                } catch (IOException ex) {
2620:                    result = false;
2621:                }
2622:
2623:                return result;
2624:            }
2625:
2626:            public boolean sendLine(String line) {
2627:                boolean result = true;
2628:
2629:                CVSTracer.traceIf(this .tracingTCPData, "CVSClient.SENDLine: '"
2630:                        + line + "'");
2631:
2632:                try {
2633:                    this .outstream.write((line + "\012").getBytes());
2634:                    this .outstream.flush();
2635:                } catch (IOException ex) {
2636:                    CVSTracer.traceException("SENDLINE: " + line, ex);
2637:                    result = false;
2638:                }
2639:
2640:                return result;
2641:            }
2642:
2643:            public String readLine() {
2644:                char ch;
2645:                StringBuffer line = new StringBuffer(512); // REVIEW Better number? Avg?
2646:
2647:                try {
2648:                    for (;;) {
2649:                        int inByte = this .instream.read();
2650:                        if (inByte == -1) {
2651:                            if (line.length() == 0)
2652:                                line = null;
2653:                            break;
2654:                        }
2655:
2656:                        ch = (char) inByte;
2657:                        if (ch == '\012') {
2658:                            break;
2659:                        }
2660:
2661:                        line.append(ch);
2662:                    }
2663:                } catch (IOException ex) {
2664:                    line = null;
2665:                }
2666:
2667:                CVSTracer.traceIf(this .tracingTCPData, "CVSClient.READLine: '"
2668:                        + ((line == null) ? "(null)" : line.toString()) + "'");
2669:
2670:                return (line != null ? line.toString() : null);
2671:            }
2672:
2673:            public String readResponse() {
2674:                String line;
2675:                StringBuffer result = new StringBuffer("");
2676:
2677:                for (;;) {
2678:                    line = this .readLine();
2679:
2680:                    if (line == null)
2681:                        break;
2682:
2683:                    CVSTracer.traceIf(this .tracingTCPData,
2684:                            "CVSClient.READLine: '" + line + "'");
2685:
2686:                    result.append(line);
2687:                    result.append("\n");
2688:
2689:                    if (line.startsWith("ok")) {
2690:                        break;
2691:                    }
2692:
2693:                    if (line.startsWith("error")) {
2694:                        break;
2695:                    }
2696:                }
2697:
2698:                return result.toString();
2699:            }
2700:
2701:            private InetAddress getInterfaceAddress(String host, int port)
2702:                    throws IOException {
2703:                InetAddress interfaceAddress = null;
2704:
2705:                //
2706:                // The following code is used for the case where we have
2707:                // multiple interfaces on the system. When there is more
2708:                // than one interface, InetAddress.getLocalHost() may not
2709:                // return the interface that we need to route to the cvs
2710:                // server. Thus, we instead first make a connection, then
2711:                // we use that connection to determine the interface, and
2712:                // ergo the ip address to use, that routes to the server.
2713:                //
2714:                // REVIEW
2715:                // This does cost us a double connect, which is expensive.
2716:                // I am also not sure what cost it is to the server, which
2717:                // will reject the rsh because it is not on a priveleged
2718:                // port. We may eventually want a property to be able to
2719:                // turn this on and off.
2720:                //
2721:                // Thanks to Roger Vaughn <rvaughn@pobox.com> for solving
2722:                // this problem and providing this code!
2723:                //
2724:
2725:                try {
2726:                    Socket probe = new Socket(host, port);
2727:                    interfaceAddress = probe.getLocalAddress();
2728:                    probe.close();
2729:                } catch (IOException ex) {
2730:                    // Didn't work! Use the "default" instead.
2731:                    interfaceAddress = InetAddress.getLocalHost();
2732:                }
2733:
2734:                return interfaceAddress;
2735:            }
2736:
2737:            private Socket bindLocalSocket(CVSRequest request,
2738:                    InetAddress localhost, String host, int port)
2739:                    throws IOException {
2740:                Socket sock = null;
2741:                String errMessage = "could not bind socket between 1025-1152 locally";
2742:
2743:                for (int local = 1025; sock == null && local < 1152; ++local) {
2744:                    if (this .isCanceled())
2745:                        break;
2746:
2747:                    CVSTracer.traceIf(request.traceRequest,
2748:                            "bindLocalSocket() trying port " + local);
2749:
2750:                    try {
2751:                        sock = new Socket(host, port, localhost, local);
2752:                    } catch (IOException ex) {
2753:                        socket = null;
2754:                        CVSTracer.traceIf(request.traceRequest,
2755:                                "bindLocalSocket() exception message: "
2756:                                        + ex.getMessage());
2757:
2758:                        //
2759:                        // HACK
2760:                        // If we attempt to run through each of these sockets, while
2761:                        // we are going over the wire (we don't get "Address in use",
2762:                        // we get "Connection refused"), then we are going to spend
2763:                        // one hell of a time in this loop. The hack is that we depend
2764:                        // on the word "refused" to be in the correct error message. If
2765:                        // not, then we only revert back to the infinite wait while we
2766:                        // loop over all of these ports.
2767:                        //
2768:                        if (ex.getMessage().indexOf("refused") > -1
2769:                                || ex.getMessage().indexOf("timed out") > -1) {
2770:                            errMessage = ex.getMessage();
2771:                            break;
2772:                        }
2773:                    }
2774:                }
2775:
2776:                if (sock == null) {
2777:                    throw new IOException(errMessage);
2778:                }
2779:
2780:                return sock;
2781:            }
2782:
2783:            //
2784:            // UNDONE HIGH
2785:            // There *is* a .ssh_known_hosts file, especially w/ cygwin.
2786:            //
2787:            public boolean verifyHost(String host, SshPublicKey pk)
2788:                    throws TransportProtocolException {
2789:                CVSTracer.traceIf(false, "CVSClient.verifyHost: host '" + host
2790:                        + "', Pk '" + pk + "'");
2791:
2792:                return true;
2793:            }
2794:
2795:            private void establishSSHConnection(CVSRequest request)
2796:                    throws IOException {
2797:                SshConnectionProperties properties = new SshConnectionProperties();
2798:
2799:                CVSTracer
2800:                        .traceIf(request.traceRequest,
2801:                                "CVSClient.establishSSHConnection: creating connection...");
2802:
2803:                InetAddress localhost = this .getInterfaceAddress(request
2804:                        .getHostName(), request.getPort());
2805:
2806:                properties.setHost(request.getHostName());
2807:                properties.setPort(request.getPort());
2808:
2809:                CVSTracer.traceIf(request.traceRequest,
2810:                        "CVSClient.establishSSHConnection: localHost="
2811:                                + localhost);
2812:
2813:                this .sshClient = new SshClient();
2814:
2815:                CVSTracer.traceIf(request.traceRequest,
2816:                        "CVSClient.establishSSHConnection: sshClient="
2817:                                + this .sshClient);
2818:
2819:                this .sshClient.connect(properties, this );
2820:
2821:                CVSTracer.traceIf(request.traceRequest,
2822:                        "CVSClient.establishSSHConnection: connected");
2823:
2824:                PasswordAuthenticationClient pwdAuth = new PasswordAuthenticationClient();
2825:
2826:                pwdAuth.setUsername(request.getUserName());
2827:                pwdAuth.setPassword(request.getPassword());
2828:
2829:                int result = sshClient.authenticate(pwdAuth);
2830:
2831:                CVSTracer.traceIf(request.traceRequest,
2832:                        "CVSClient.authenticate: result=" + result);
2833:
2834:                if (result == AuthenticationProtocolState.FAILED) {
2835:                    CVSTracer.traceIf(request.traceRequest,
2836:                            "The authentication failed");
2837:                    throw new IOException("ssh authentication failure");
2838:                } else if (result == AuthenticationProtocolState.PARTIAL) {
2839:                    CVSTracer.traceIf(request.traceRequest,
2840:                            "The authentication succeeded but another"
2841:                                    + "authentication is required");
2842:                    throw new IOException("ssh authentication partial");
2843:                } else if (result == AuthenticationProtocolState.COMPLETE) {
2844:                    CVSTracer.traceIf(request.traceRequest,
2845:                            "The authentication is complete");
2846:                }
2847:
2848:                //	String srvVersionStr = this.sshTransport.getServerVersion();
2849:
2850:                //	CVSTracer.traceIf( request.traceRequest,
2851:                //		"CVSClient.establishSSHConnection: SVR VERSION '" + srvVersionStr + "'" );
2852:
2853:                this .sshSession = this .sshClient.openSessionChannel();
2854:
2855:                CVSTracer.traceIf(request.traceRequest,
2856:                        "CVSClient.establishSSHConnection: sshSession="
2857:                                + this .sshSession);
2858:
2859:                boolean ok = this .sshSession.executeCommand(request
2860:                        .getServerCommand());
2861:
2862:                CVSTracer.traceIf(request.traceRequest,
2863:                        "CVSClient.establishSSHConnection: command("
2864:                                + request.getServerCommand() + ") = " + ok);
2865:
2866:                if (ok) {
2867:                    CVSTracer
2868:                            .traceIf(request.traceRequest,
2869:                                    "CVSClient.establishSSHConnection: command session established");
2870:                } else {
2871:                    CVSTracer.traceIf(request.traceRequest,
2872:                            "CVSClient.establishSSHConnection: executeCommand( '"
2873:                                    + request.getServerCommand() + "' failed.");
2874:
2875:                    throw new IOException("failed to execute command '"
2876:                            + request.getServerCommand() + "'");
2877:                }
2878:            }
2879:
2880:            private Socket establishRSHSocket(CVSRequest request)
2881:                    throws IOException {
2882:                Socket sock = null;
2883:
2884:                InetAddress localhost = this .getInterfaceAddress(request
2885:                        .getHostName(), request.getPort());
2886:
2887:                for (int local = 512; sock == null && local < 1024; ++local) {
2888:                    try {
2889:                        sock = new Socket(request.getHostName(), request
2890:                                .getPort(), localhost, local);
2891:                    } catch (IOException ex) {
2892:                        socket = null;
2893:                    }
2894:                }
2895:
2896:                if (sock == null) {
2897:                    throw new IOException(
2898:                            "Could not bind rsh socket between 512-1023 locally.");
2899:                }
2900:
2901:                return sock;
2902:            }
2903:
2904:            private boolean openServer(CVSRequest request) {
2905:                boolean result;
2906:
2907:                this .socket = null;
2908:                this .process = null;
2909:                this .serverIsOpen = false;
2910:
2911:                // Create the socket used for the event server connection
2912:                try {
2913:                    CVSTracer.traceIf(request.traceRequest,
2914:                            "CVSClient.openServer: creating connection...");
2915:
2916:                    result = true;
2917:                    switch (request.getConnectionMethod()) {
2918:                    case CVSRequest.METHOD_INETD:
2919:                        this .socket = new Socket(request.getHostName(), request
2920:                                .getPort());
2921:                        break;
2922:
2923:                    case CVSRequest.METHOD_SSH:
2924:                        this .establishSSHConnection(request);
2925:                        break;
2926:
2927:                    case CVSRequest.METHOD_RSH:
2928:                        if (request.getRshProcess() != null) {
2929:                            int index = request.getServerCommand().indexOf(' ');
2930:
2931:                            String[] argv = new String[6];
2932:
2933:                            argv[0] = request.getRshProcess();
2934:                            argv[1] = request.getHostName();
2935:                            argv[2] = "-l";
2936:                            argv[3] = request.getUserName();
2937:                            if (index < 0) {
2938:                                argv[4] = request.getServerCommand();
2939:                                argv[5] = "server";
2940:                            } else {
2941:                                argv[4] = request.getServerCommand().substring(
2942:                                        0, index);
2943:                                argv[5] = request.getServerCommand().substring(
2944:                                        index + 1);
2945:                            }
2946:
2947:                            if (request.traceRequest) {
2948:                                for (int i = 0; i < argv.length; ++i)
2949:                                    CVSTracer.traceIf(true,
2950:                                            "CVSClient.openServer: RSH argv["
2951:                                                    + i + "] = '" + argv[i]
2952:                                                    + "'");
2953:                            }
2954:
2955:                            this .process = Runtime.getRuntime().exec(argv);
2956:                        } else {
2957:                            this .socket = this .establishRSHSocket(request);
2958:                        }
2959:                        break;
2960:                    }
2961:
2962:                    CVSTracer.traceIf(request.traceRequest,
2963:                            "CVSClient.openServer: creating i/o streams...");
2964:
2965:                    if (this .sshSession != null) {
2966:                        this .instream = new DataInputStream(this .sshSession
2967:                                .getInputStream());
2968:
2969:                        this .outstream = new DataOutputStream(this .sshSession
2970:                                .getOutputStream());
2971:                    } else if (this .process != null) {
2972:                        this .instream = new DataInputStream(this .process
2973:                                .getInputStream());
2974:
2975:                        this .outstream = new DataOutputStream(this .process
2976:                                .getOutputStream());
2977:                    } else if (this .socket != null) {
2978:                        this .instream = new DataInputStream(this .socket
2979:                                .getInputStream());
2980:
2981:                        this .outstream = new DataOutputStream(this .socket
2982:                                .getOutputStream());
2983:                    } else {
2984:                        CVSTracer
2985:                                .traceIf(request.traceRequest,
2986:                                        "CVSClient.openServer: failed to establish connection.");
2987:                        result = false;
2988:                    }
2989:
2990:                    if (result) {
2991:                        CVSTracer.traceIf(request.traceRequest,
2992:                                "CVSClient.openServer: server is open.");
2993:                        this .serverIsOpen = true;
2994:                    }
2995:                } catch (IOException ex) {
2996:                    this .serverIsOpen = false;
2997:                    int meth = request.getConnectionMethod();
2998:
2999:                    this .setReason("could not create "
3000:                            + (meth == CVSRequest.METHOD_INETD ? "INETD"
3001:                                    : (meth == CVSRequest.METHOD_RSH ? "RSH"
3002:                                            : "SSH")) + " connection for '"
3003:                            + port + "@" + request.getHostName() + "' --> "
3004:                            + ex.getMessage());
3005:
3006:                    CVSLog.logMsg(this .getReason());
3007:                }
3008:
3009:                if (this .serverIsOpen
3010:                        && this .socket != null
3011:                        && (request.getConnectionMethod() == CVSRequest.METHOD_RSH)) {
3012:                    CVSTracer
3013:                            .traceIf(request.traceRequest,
3014:                                    "CVSClient.openServer: performing rsh protocol initialization.");
3015:
3016:                    result = this .performRSHProtocol(request.getUserName(),
3017:                            request.getServerCommand());
3018:
3019:                    if (result == false) {
3020:                        this .closeServer();
3021:                    }
3022:                }
3023:
3024:                return this .serverIsOpen;
3025:            }
3026:
3027:            public boolean performRSHProtocol(String remoteUserName,
3028:                    String serverCommand) {
3029:                int status;
3030:
3031:                // ------------- STDERR PORT ---------------
3032:                try {
3033:                    this .outstream.write(48); // 48 = "0"
3034:                    this .outstream.write(0);
3035:                } catch (IOException ex) {
3036:                    CVSLog.logMsg("RSH: FAIL-ed writing stderr port");
3037:                    return false;
3038:                }
3039:
3040:                // ------------- LOCAL USER NAME ---------------
3041:                // Use the Java system property "user.name" for the local
3042:                // name, but default to remoteUserName is not set.
3043:                String localUserName = System.getProperty("user.name",
3044:                        remoteUserName);
3045:
3046:                try {
3047:                    this .outstream.write(localUserName.getBytes());
3048:                    this .outstream.write(0);
3049:                } catch (IOException ex) {
3050:                    CVSLog.logMsg("RSH: FAIL-ed writing local user");
3051:                    return false;
3052:                }
3053:
3054:                // ------------- REMOTE USER NAME ---------------
3055:                try {
3056:                    this .outstream.write(remoteUserName.getBytes());
3057:                    this .outstream.write(0);
3058:                } catch (IOException ex) {
3059:                    CVSLog.logMsg("RSH: FAIL-ed writing remote user");
3060:                    return false;
3061:                }
3062:
3063:                // ------------- COMMAND LINE ---------------
3064:                try {
3065:                    this .outstream.write(serverCommand.getBytes());
3066:                    this .outstream.write(0);
3067:                    this .outstream.flush();
3068:                } catch (IOException ex) {
3069:                    CVSLog.logMsg("RSH: FAIL-ed writing command");
3070:                    return false;
3071:                }
3072:
3073:                // ------------- READ STATUS BYTE ---------------
3074:                try {
3075:                    status = this .instream.read();
3076:                } catch (IOException ex) {
3077:                    CVSLog.logMsg("RSH: FAIL-ed reading status");
3078:                    return false;
3079:                }
3080:
3081:                if (status != 0)
3082:                    return false;
3083:
3084:                return true;
3085:            }
3086:
3087:            public boolean closeServer() {
3088:                boolean result = true;
3089:
3090:                if (this .serverIsOpen) {
3091:                    try {
3092:                        if (this .sshSession != null) {
3093:                            this .sshSession.close();
3094:                            this .sshClient.disconnect();
3095:                        } else {
3096:                            this .instream.close();
3097:                            this .outstream.close();
3098:                        }
3099:
3100:                        if (this .socket != null) {
3101:                            this .socket.close();
3102:                        } else if (this .process != null) {
3103:                            this .process.destroy();
3104:                        }
3105:                    } catch (IOException ex) {
3106:                        result = false;
3107:                        this .setReason("could not close socket - "
3108:                                + ex.getMessage());
3109:                        CVSLog.logMsg(this .getReason());
3110:                    }
3111:
3112:                    this .socket = null;
3113:                    this .sshClient = null;
3114:                    this .sshSession = null;
3115:                    this .instream = null;
3116:                    this .outstream = null;
3117:                    this .serverIsOpen = false;
3118:                }
3119:
3120:                return result;
3121:            }
3122:
3123:            // EH-null-ui  Etienne-Hugues Fortin <ehfortin@sympatico.ca>
3124:            private class NullCVSUI implements  CVSUserInterface {
3125:                public void uiDisplayProgressMsg(String message) {
3126:                }
3127:
3128:                public void uiDisplayProgramError(String error) {
3129:                }
3130:
3131:                public void uiDisplayResponse(CVSResponse response) {
3132:                }
3133:            }
3134:
3135:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.