KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > lib > cvsclient > command > commit > CommitCommand


1 /*****************************************************************************
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is the CVS Client Library.
16  * The Initial Developer of the Original Software is Robert Greig.
17  * Portions created by Robert Greig are Copyright (C) 2000.
18  * All Rights Reserved.
19  *
20  * Contributor(s): Robert Greig.
21  *****************************************************************************/

22 package org.netbeans.lib.cvsclient.command.commit;
23
24 import java.io.*;
25 import java.util.*;
26
27 import org.netbeans.lib.cvsclient.*;
28 import org.netbeans.lib.cvsclient.admin.*;
29 import org.netbeans.lib.cvsclient.command.*;
30 import org.netbeans.lib.cvsclient.connection.*;
31 import org.netbeans.lib.cvsclient.event.*;
32 import org.netbeans.lib.cvsclient.request.*;
33
34 /**
35  * The command to commit any changes that have been made.
36  * @author Robert Greig
37  */

38 public class CommitCommand extends BasicCommand {
39     /**
40      * The argument requests that must be added at the end.
41      * These argument requests indicate the files to be committed
42      */

43     private final List argumentRequests = new LinkedList();
44
45     /**
46      * The log message used for the commit.
47      */

48     private String JavaDoc message;
49
50     /**
51      * Forces the commit of the file(s) even if no changes were done.
52      * the standard behaviour is NOT-TO-BE recursive in this case.
53      */

54     private boolean forceCommit;
55
56     /**
57      * The filename for the file that defines the message.
58      */

59     private String JavaDoc logMessageFromFile;
60
61     /**
62      * Determines that no module program should run on the server.
63      */

64     private boolean noModuleProgram;
65
66     /** Holds value of property toRevisionOrBranch. */
67     private String JavaDoc toRevisionOrBranch;
68
69     /**
70      * Construct a CommitCommand.
71      */

72     public CommitCommand() {
73         resetCVSCommand();
74     }
75
76     /**
77      * Returns the commit message.
78      */

79     public String JavaDoc getMessage() {
80         return message;
81     }
82
83     /**
84      * Sets the commit message.
85      */

86     public void setMessage(String JavaDoc message) {
87         this.message = message;
88     }
89
90     /**
91      * Indicates whether the commit should be forced even if there are no
92      * changes.
93      */

94     public boolean isForceCommit() {
95         return forceCommit;
96     }
97
98     /**
99      * Sets whether the commit should be forced even if there are no changes.
100      */

101     public void setForceCommit(boolean forceCommit) {
102         this.forceCommit = forceCommit;
103     }
104
105     /**
106      * Adds the appropriate requests for a given directory.
107      * Sends a directory request followed by as many Entry and Modified requests
108      * as required.
109      * @param directory the directory to send requests for
110      * @throws IOException if an error occurs constructing the requests
111      */

112     protected void addRequestsForDirectory(File directory)
113             throws IOException {
114         if (!directory.exists()) {
115             return;
116         }
117         // remove localPath prefix from directory. If left with
118
// nothing, use dot (".") in the directory request. Also remove the
119
// trailing slash
120
String JavaDoc dir = getRelativeToLocalPathInUnixStyle(directory);
121
122         try {
123             String JavaDoc repository = clientServices.getRepositoryForDirectory(
124                     directory.getAbsolutePath());
125             requests.add(new DirectoryRequest(dir, repository));
126             String JavaDoc tag = clientServices.getStickyTagForDirectory(directory);
127             if (tag != null) {
128                 requests.add(new StickyRequest(tag));
129             }
130         }
131         catch (IOException ex) {
132             System.err.println("An error occurred reading the respository " +
133                                "for the directory " + dir + ": " + ex);
134             ex.printStackTrace();
135         }
136
137         // Obtain a set of all files known to CVS. We union
138
// this set with the set of files in the actual filesystem directory
139
// to obtain a set of files to commit (or at least attempt to commit).
140
Set set = clientServices.getAllFiles(directory);
141
142         // We must add the local files (and directories) because the above
143
// command does *not* return cvs controlled directories
144
final File[] files = directory.listFiles();
145
146         // get the union of the files in the directory and the files retrieved
147
// from the Entries file.
148
set.addAll(Arrays.asList(files));
149
150         List subdirectories = null;
151         if (isRecursive()) {
152             subdirectories = new LinkedList();
153         }
154
155         for (Iterator it = set.iterator(); it.hasNext();) {
156             File file = (File)it.next();
157             if (file.getName().equals("CVS")) { //NOI18N
158
continue;
159             }
160
161             try {
162                 final Entry entry = clientServices.getEntry(file);
163                 // a non-null entry means the file does exist in the
164
// Entries file for this directory
165
if (entry == null) {
166                     continue;
167                 }
168
169                 // here file.isFile() is *not* used, because not existing
170
// files (removed ones) should also be sent
171
if (file.isFile()) {
172                     sendEntryAndModifiedRequests(entry, file);
173                 }
174                 else if (isRecursive() && file.isDirectory()) {
175                     File cvsSubDir = new File(file, "CVS"); //NOI18N
176
if (cvsSubDir.exists()) {
177                         subdirectories.add(file);
178                     }
179                 }
180             }
181             catch (IOException ex) {
182                 System.err.println("An error occurred getting the " +
183                                    "Entry for file " + file + ": " + ex);
184                 ex.printStackTrace();
185             }
186         }
187
188         if (isRecursive()) {
189             for (Iterator it = subdirectories.iterator(); it.hasNext();) {
190                 File subdirectory = (File)it.next();
191                 addRequestsForDirectory(subdirectory);
192             }
193         }
194     }
195
196     /**
197      * Add the appropriate requests for a single file.
198      * A directory request is sent, followed by an Entry and Modified request.
199      * @param file the file to send requests for
200      * @throws IOException if an error occurs constructing the requests
201      */

202     protected void addRequestsForFile(File file)
203             throws IOException {
204         final File parentDirectory = file.getParentFile();
205         // remove localPath prefix from directory. If left with
206
// nothing, use dot (".") in the directory request
207
String JavaDoc dir = getRelativeToLocalPathInUnixStyle(parentDirectory);
208
209         try {
210             // send a argument request indicating the file to update
211
requests.add(new DirectoryRequest(dir, clientServices.
212                                                    getRepositoryForDirectory(parentDirectory.
213                                                                              getAbsolutePath())));
214             String JavaDoc tag = clientServices.getStickyTagForDirectory(parentDirectory);
215             if (tag != null) {
216                 requests.add(new StickyRequest(tag));
217             }
218         }
219         catch (IOException ex) {
220             System.err.println("An error occurred reading the respository " +
221                                "for the directory " + dir + ": " + ex);
222             ex.printStackTrace();
223         }
224
225         try {
226             final Entry entry = clientServices.getEntry(file);
227             // a non-null entry means the file does exist in the
228
// Entries file for this directory
229
if (entry != null) {
230                 sendEntryAndModifiedRequests(entry, file);
231             }
232         }
233         catch (IOException ex) {
234             System.err.println("An error occurred getting the Entry " +
235                                "for file " + file + ": " + ex);
236             ex.printStackTrace();
237         }
238     }
239
240     /**
241      * Should return true if unchanged files should not be sent to server.
242      * If false is returned, all files will be sent to server
243      * This method is used by <code>sendEntryAndModifiedRequests</code>.
244      */

245     protected boolean doesCheckFileTime() {
246         return !isForceCommit();
247     }
248
249     /**
250      * Execute the command.
251      * @param client the client services object that provides any necessary
252      * services to this command, including the ability to actually
253      * process all the requests
254      */

255     public void execute(ClientServices client, EventManager em)
256             throws CommandException, AuthenticationException {
257         client.ensureConnection();
258
259         super.execute(client, em);
260
261         try {
262             // add arguments.
263
if (isForceCommit()) {
264                 requests.add(1, new ArgumentRequest("-f")); //NOI18N
265
if (isRecursive()) {
266                     requests.add(1, new ArgumentRequest("-R")); //NOI18N
267
}
268             }
269             if (isNoModuleProgram()) {
270                 requests.add(1, new ArgumentRequest("-n")); //NOI18N
271
}
272             if (getToRevisionOrBranch() != null) {
273                 requests.add(1, new ArgumentRequest("-r")); //NOI18N
274
requests.add(2, new ArgumentRequest(getToRevisionOrBranch()));
275             }
276
277             // build the message to send
278
String JavaDoc message = getMessage();
279             if (getLogMessageFromFile() != null) {
280                 message = loadLogFile(getLogMessageFromFile());
281             }
282             if (message != null) {
283                 message = message.trim();
284             }
285             if (message == null
286                     || message.length() == 0) {
287                 message = "no message"; //NOI18N
288
}
289             addMessageRequest(message);
290
291             addRequestForWorkingDirectory(client);
292             requests.addAll(argumentRequests);
293             argumentRequests.clear(); // MK sanity check.
294
addArgumentRequests();
295             requests.add(CommandRequest.COMMIT);
296
297             client.processRequests(requests);
298         }
299         catch (CommandException ex) {
300             throw ex;
301         }
302         catch (Exception JavaDoc ex) {
303             throw new CommandException(ex, ex.getLocalizedMessage());
304         }
305         finally {
306             requests.clear();
307         }
308     }
309
310     protected void addArgumentRequests() {
311         if (isForceCommit()) {
312             Iterator it = requests.iterator();
313             String JavaDoc directory = "";
314             List args = new LinkedList();
315             while (it.hasNext()) {
316                 Object JavaDoc req = it.next();
317                 if (req instanceof org.netbeans.lib.cvsclient.request.DirectoryRequest) {
318                     org.netbeans.lib.cvsclient.request.DirectoryRequest dirReq = (org.netbeans.lib.cvsclient.request.DirectoryRequest)req;
319                     // haven't checked but I'm almost sure that within the Argument request always the local directory is used.
320
directory = dirReq.getLocalDirectory();
321                 }
322                 else if (req instanceof org.netbeans.lib.cvsclient.request.EntryRequest) {
323                     org.netbeans.lib.cvsclient.request.EntryRequest entReq = (org.netbeans.lib.cvsclient.request.EntryRequest)req;
324                     String JavaDoc argument = null;
325                     if (directory.length() == 0) {
326                         argument = entReq.getEntry().getName();
327                     }
328                     else {
329                         argument = directory + '/' + entReq.getEntry().getName();
330                     }
331                     args.add(new ArgumentRequest(argument));
332                 }
333             }
334             it = args.iterator();
335             while (it.hasNext()) {
336                 requests.add(it.next());
337             }
338         }
339         else {
340             super.addArgumentRequests();
341         }
342     }
343
344     /**
345      * This method returns how the command would looklike when typed on the command line.
346      * Example: checkout -p CvsCommand.java
347      * @returns <command's name> [<parameters>] files/dirs
348      */

349     public String JavaDoc getCVSCommand() {
350         StringBuffer JavaDoc toReturn = new StringBuffer JavaDoc("commit "); //NOI18N
351
toReturn.append(getCVSArguments());
352         File[] files = getFiles();
353         if (files != null) {
354             for (int index = 0; index < files.length; index++) {
355                 toReturn.append(files[index].getName() + " "); //NOI18N
356
}
357         }
358         return toReturn.toString();
359     }
360
361     /**
362      * Takes the arguments and sets the command.
363      * To be mainly used for automatic settings (like parsing the .cvsrc file).
364      * @return true if the option (switch) was recognized and set
365      */

366     public boolean setCVSCommand(char opt, String JavaDoc optArg) {
367         if (opt == 'm') {
368             setMessage(optArg);
369         }
370         else if (opt == 'l') {
371             setRecursive(false);
372         }
373         else if (opt == 'R') {
374             setRecursive(true);
375         }
376         else if (opt == 'f') {
377             setForceCommit(true);
378         }
379         else if (opt == 'F') {
380             setLogMessageFromFile(optArg);
381         }
382         else if (opt == 'r') {
383             setToRevisionOrBranch(optArg);
384         }
385         else if (opt == 'n') {
386             setNoModuleProgram(true);
387         }
388         else {
389             return false;
390         }
391         return true;
392     }
393
394     /**
395      * Returns a String defining which options are available for this command.
396      */

397     public String JavaDoc getOptString() {
398         return "m:flRnF:r:"; //NOI18N
399
}
400
401     /**
402      * Method that is called while the command is being executed.
403      * Descendants can override this method to return a Builder instance
404      * that will parse the server's output and create data structures.
405      */

406     public Builder createBuilder(EventManager eventMan) {
407         return new CommitBuilder(eventMan, getLocalDirectory(), clientServices.getRepository());
408     }
409
410     /**
411      * Generates the Argument/Argumentx series of requests depending
412      * on the number of lines in the message request.
413      */

414     private void addMessageRequest(String JavaDoc message) {
415         requests.add(new ArgumentRequest("-m")); //NOI18N
416
StringTokenizer token = new StringTokenizer(message, "\n", false); //NOI18N
417
boolean first = true;
418         while (token.hasMoreTokens()) {
419             if (first) {
420                 requests.add(new ArgumentRequest(token.nextToken()));
421                 first = false;
422             }
423             else {
424                 requests.add(new ArgumentxRequest(token.nextToken()));
425             }
426         }
427     }
428
429     /**
430      * Returns the filename for the file that defines the message.
431      */

432     public String JavaDoc getLogMessageFromFile() {
433         return logMessageFromFile;
434     }
435
436     /**
437      * Sets the filename for the file that defines the message.
438      */

439     public void setLogMessageFromFile(String JavaDoc logMessageFromFile) {
440         this.logMessageFromFile = logMessageFromFile;
441     }
442
443     /**
444      * Returns whether no module program should be executed on the server.
445      */

446     public boolean isNoModuleProgram() {
447         return noModuleProgram;
448     }
449
450     /**
451      * Sets whether no module program should run on the server
452      */

453     public void setNoModuleProgram(boolean noModuleProgram) {
454         this.noModuleProgram = noModuleProgram;
455     }
456
457     /** Getter for property toRevisionOrBranch.
458      * @return Value of property toRevisionOrBranch.
459      */

460     public String JavaDoc getToRevisionOrBranch() {
461         return toRevisionOrBranch;
462     }
463
464     /** Setter for property toRevisionOrBranch.
465      * @param toRevisionOrBranch New value of property toRevisionOrBranch.
466      */

467     public void setToRevisionOrBranch(String JavaDoc toRevBranch) {
468         this.toRevisionOrBranch = toRevBranch;
469     }
470
471     private String JavaDoc loadLogFile(String JavaDoc fileName)
472             throws CommandException {
473         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
474         BufferedReader reader = null;
475         try {
476             reader = new BufferedReader(new FileReader(fileName));
477             String JavaDoc line;
478             while ((line = reader.readLine()) != null) {
479                 buffer.append(line + "\n"); //NOI18N
480
}
481         }
482         catch (FileNotFoundException ex) {
483             throw new CommandException(ex,
484                                        CommandException.getLocalMessage("CommitCommand.logInfoFileNotExists", new Object JavaDoc[]{fileName})); //NOI18N
485
}
486         catch (IOException ex) {
487             throw new CommandException(ex,
488                                        CommandException.getLocalMessage("CommitCommand.errorReadingLogFile", new Object JavaDoc[]{fileName})); //NOI18N
489
}
490         finally {
491             if (reader != null) {
492                 try {
493                     reader.close();
494                 }
495                 catch (IOException exc) {
496                 }
497             }
498         }
499         return buffer.toString();
500     }
501
502     /**
503      * Resets all switches in the command.
504      * After calling this method, the command should have no switches defined
505      * and should behave defaultly.
506      */

507     public void resetCVSCommand() {
508         setMessage(null);
509         setRecursive(true);
510         setForceCommit(false);
511         setLogMessageFromFile(null);
512         setNoModuleProgram(false);
513         setToRevisionOrBranch(null);
514     }
515
516     /**
517      * Returns the arguments of the command in the command-line style.
518      * Similar to getCVSCommand() however without the files and command's name.
519      */

520     public String JavaDoc getCVSArguments() {
521         StringBuffer JavaDoc toReturn = new StringBuffer JavaDoc();
522         if (!isRecursive()) {
523             toReturn.append("-l "); //NOI18N
524
}
525         if (isForceCommit()) {
526             toReturn.append("-f "); //NOI18N
527
if (isRecursive()) {
528                 toReturn.append("-R ");
529             }
530         }
531         if (isNoModuleProgram()) {
532             toReturn.append("-n "); //NOI18N
533
}
534         if (getToRevisionOrBranch() != null) {
535             toReturn.append("-r "); //NOI18N
536
toReturn.append(getToRevisionOrBranch() + " "); //NOI18N
537
}
538         if (getLogMessageFromFile() != null) {
539             toReturn.append("-F "); //NOI18N
540
toReturn.append(getLogMessageFromFile());
541             toReturn.append(" "); //NOI18N
542
}
543         if (getMessage() != null) {
544             toReturn.append("-m \""); //NOI18N
545
toReturn.append(getMessage());
546             toReturn.append("\" "); //NOI18N
547
}
548         return toReturn.toString();
549     }
550 }
551
Popular Tags