001: /* ====================================================================
002: * The JRefactory License, Version 1.0
003: *
004: * Copyright (c) 2001 JRefactory. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * 3. The end-user documentation included with the redistribution,
019: * if any, must include the following acknowledgment:
020: * "This product includes software developed by the
021: * JRefactory (http://www.sourceforge.org/projects/jrefactory)."
022: * Alternately, this acknowledgment may appear in the software itself,
023: * if and wherever such third-party acknowledgments normally appear.
024: *
025: * 4. The names "JRefactory" must not be used to endorse or promote
026: * products derived from this software without prior written
027: * permission. For written permission, please contact seguin@acm.org.
028: *
029: * 5. Products derived from this software may not be called "JRefactory",
030: * nor may "JRefactory" appear in their name, without prior written
031: * permission of Chris Seguin.
032: *
033: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
034: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
035: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
036: * DISCLAIMED. IN NO EVENT SHALL THE CHRIS SEGUIN OR
037: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
038: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
039: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
040: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
041: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
042: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
043: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
044: * SUCH DAMAGE.
045: * ====================================================================
046: *
047: * This software consists of voluntary contributions made by many
048: * individuals on behalf of JRefactory. For more information on
049: * JRefactory, please see
050: * <http://www.sourceforge.org/projects/jrefactory>.
051: */
052: package org.acm.seguin.version;
053:
054: import java.io.BufferedReader;
055: import java.io.File;
056: import java.io.IOException;
057: import java.io.InputStream;
058: import java.io.InputStreamReader;
059: import org.acm.seguin.util.FileSettings;
060: import org.acm.seguin.util.MissingSettingsException;
061: import org.acm.seguin.awt.ExceptionPrinter;
062:
063: /**
064: * Creates a process that checks out a file from source safe
065: *
066: *@author Chris Seguin
067: *@created June 11, 1999
068: */
069: public class SourceSafe implements VersionControl {
070: // Instance Variables
071: private String exeFile;
072: private String user;
073:
074: /**
075: * Constructor for the source safe object
076: */
077: public SourceSafe() {
078: try {
079: FileSettings bundle = FileSettings
080: .getRefactorySettings("vss");
081: exeFile = bundle.getString("vss");
082: } catch (MissingSettingsException mre) {
083: System.out.println("Unable to initialize source safe");
084: ExceptionPrinter.print(mre, false);
085: } catch (NumberFormatException nfe) {
086: System.out
087: .println("Unable to interpret the count property as an integer");
088: }
089: }
090:
091: /**
092: * Determines if a file is under version control
093: *
094: *@param fullFilename The full path of the file
095: *@return Returns true if the files is under version control
096: */
097: public synchronized boolean contains(String fullFilename) {
098: try {
099: System.out.println("\tChecking for " + fullFilename);
100: String project = getProject(Runtime.getRuntime(),
101: fullFilename);
102: boolean result = ((project != null) && (project.length() > 0));
103: System.out.println("\t" + fullFilename + " is "
104: + (result ? "" : "not ") + "in Source Safe");
105: return result;
106: } catch (IOException ioe) {
107: ExceptionPrinter.print(ioe, false);
108: return false;
109: }
110: }
111:
112: /**
113: * Adds a file to version control
114: *
115: *@param fullFilename the file to add
116: */
117: public synchronized void add(String fullFilename) {
118: }
119:
120: /**
121: * Check out the file from source safe
122: *
123: *@param file the name of the file
124: */
125: public synchronized void checkOut(String file) {
126: try {
127: // Get the runtime program
128: Runtime processFactory = Runtime.getRuntime();
129:
130: System.out.println("\tFinding the project");
131: String project = getProject(processFactory, file);
132: if (project == null) {
133: System.out.println("\tNot in any project");
134: return;
135: }
136: System.out.println("\tChanging to project: " + project);
137: changeProject(processFactory, project);
138: System.out.println("\tChecking out the file: " + file);
139: checkout(processFactory, file);
140: System.out.println("\tDone: " + file);
141: } catch (IOException ioe) {
142: ExceptionPrinter.print(ioe, false);
143: }
144: }
145:
146: /**
147: * Check out the file from source safe
148: *
149: *@param file the name of the file
150: */
151: public synchronized void checkIn(String file) {
152: try {
153: // Get the runtime program
154: Runtime processFactory = Runtime.getRuntime();
155:
156: System.out.println("\tFinding the project");
157: String project = getProject(processFactory, file);
158: if (project == null) {
159: System.out.println("\tNot in any project");
160: return;
161: }
162: System.out.println("\tChecking in the file to " + project);
163: changeProject(processFactory, project);
164: System.out.println("\tChanged to the project");
165: checkin(processFactory, file);
166: System.out.println("\tDone: " + file);
167: } catch (IOException ioe) {
168: ExceptionPrinter.print(ioe, false);
169: }
170: }
171:
172: /**
173: * Find the project
174: *
175: *@param factory the run time factory
176: *@param file the name of the file to find
177: *@return the name of the project or null if in no project
178: *@exception IOException is thrown if the command cannot be executed
179: */
180: protected String getProject(Runtime factory, String file)
181: throws IOException {
182: System.out.println("DEBUG[SourceSafe.getProject] #1");
183: BufferedReader input = executeLocate(factory, file);
184:
185: // Skip the first line
186: System.out.println("DEBUG[SourceSafe.getProject] #2");
187: String firstLine = input.readLine();
188: System.out.println("DEBUG[SourceSafe.getProject] #3 - "
189: + firstLine);
190:
191: // Get the path
192: String path = getPath(file);
193: System.out
194: .println("DEBUG[SourceSafe.getProject] #4 - " + path);
195:
196: String found = input.readLine();
197: if (isNotInSourceSafe(found)) {
198: return null;
199: }
200: System.out.println("DEBUG[SourceSafe.getProject] #5 - "
201: + found);
202:
203: // Find the project
204: int matchCode = -1;
205: do {
206: System.out.println("DEBUG[SourceSafe.getProject] #6");
207: if (found.indexOf("(Deleted)") == -1) {
208: System.out.println("DEBUG[SourceSafe.getProject] #7");
209: String project = extractProjectName(found);
210: System.out
211: .println("DEBUG[SourceSafe.getProject] #8 - "
212: + project);
213: if (match(path, project) != -1) {
214: System.out
215: .println("DEBUG[SourceSafe.getProject] #9");
216: return project;
217: }
218: }
219:
220: // Read the next line
221: System.out.println("DEBUG[SourceSafe.getProject] #10");
222: found = input.readLine();
223: System.out.println("DEBUG[SourceSafe.getProject] #11 - "
224: + found);
225: if ((found.length() == 0) || (found.charAt(0) != '$')) {
226: return null;
227: }
228: System.out.println("DEBUG[SourceSafe.getProject] #12");
229: } while (matchCode == -1);
230:
231: // Not found
232: System.out.println("DEBUG[SourceSafe.getProject] #13");
233: return null;
234: }
235:
236: /**
237: * Get the filename
238: *
239: *@param fullFilename the fully qualified path
240: *@return the filename
241: */
242: protected String getFilename(String fullFilename) {
243: File temp = new File(fullFilename);
244: return temp.getName();
245: }
246:
247: /**
248: * Get the path
249: *
250: *@param fullFilename the fully qualified path
251: *@return the path
252: */
253: protected String getPath(String fullFilename) {
254: File temp = new File(fullFilename);
255: return temp.getParentFile().getPath();
256: }
257:
258: /**
259: * Change to the project directory
260: *
261: *@param factory the run time factory
262: *@param project the name of the project to change to
263: *@exception IOException is thrown if the command cannot be executed
264: */
265: protected void changeProject(Runtime factory, String project)
266: throws IOException {
267: // Create the executable
268: String[] args = new String[3];
269: args[0] = exeFile;
270: args[1] = "CP";
271: args[2] = project;
272:
273: Process proc = factory.exec(args);
274:
275: try {
276: proc.waitFor();
277: } catch (InterruptedException ie) {
278: }
279: }
280:
281: /**
282: * Check out the file
283: *
284: *@param factory the run time factory
285: *@param file the file that we are checking out
286: *@exception IOException is thrown if the command cannot be executed
287: */
288: protected void checkout(Runtime factory, String file)
289: throws IOException {
290: // Create the executable
291: String[] args = new String[3];
292: args[0] = exeFile;
293: args[1] = "CHECKOUT";
294: args[2] = getFilename(file);
295:
296: Process proc = factory.exec(args);
297:
298: try {
299: proc.waitFor();
300: } catch (InterruptedException ie) {
301: }
302: }
303:
304: /**
305: * Check in the file
306: *
307: *@param factory the run time factory
308: *@param file the file that we are checking out
309: *@exception IOException is thrown if the command cannot be executed
310: */
311: protected void checkin(Runtime factory, String file)
312: throws IOException {
313: // Create the executable
314: String[] args = new String[3];
315: args[0] = exeFile;
316: args[1] = "CHECKIN";
317: args[2] = getFilename(file);
318:
319: Process proc = factory.exec(args);
320:
321: try {
322: proc.waitFor();
323: } catch (InterruptedException ie) {
324: }
325: }
326:
327: /**
328: * Matches the path to the projects
329: *
330: *@param path the path
331: *@param project the project
332: *@return the index of the item in the roots, or -1 if not there
333: */
334: protected int match(String path, String project) {
335: try {
336: FileSettings bundle = FileSettings
337: .getRefactorySettings("vss");
338: int index = 1;
339: while (true) {
340: String sourceStart = bundle
341: .getString("source." + index);
342: String projectStart = bundle.getString("project."
343: + index);
344:
345: if (startSame(path, sourceStart)
346: && startSame(project, projectStart)) {
347: // Check the rest
348: String restPath = path.substring(sourceStart
349: .length());
350: String restProject = project.substring(projectStart
351: .length());
352: System.out.println(" Rest [" + restPath + "] ["
353: + restProject + "]");
354:
355: if (compare(restPath, restProject)) {
356: System.out.println("\t\tFound!");
357: return index;
358: }
359: }
360:
361: System.out.println("Not this pair... " + index);
362: index++;
363: }
364: } catch (MissingSettingsException mre) {
365: }
366:
367: // Not found
368: return -1;
369: }
370:
371: /**
372: * Compares two files
373: *
374: *@param one the first name
375: *@param two the second name
376: *@return Description of the Returned Value
377: */
378: protected boolean compare(String one, String two) {
379: if (one.length() != two.length()) {
380: return false;
381: }
382:
383: int last = one.length();
384: for (int ndx = 0; ndx < last; ndx++) {
385: char ch1 = one.charAt(ndx);
386: char ch2 = two.charAt(ndx);
387:
388: if (ch1 == '/') {
389: if (!((ch2 == '/') || (ch2 == '\\'))) {
390: return false;
391: }
392: } else if (ch1 == '\\') {
393: if (!((ch2 == '/') || (ch2 == '\\'))) {
394: return false;
395: }
396: } else {
397: if (ch1 != ch2) {
398: return false;
399: }
400: }
401: }
402:
403: return true;
404: }
405:
406: /**
407: * Description of the Method
408: *
409: *@param found Description of Parameter
410: *@return Description of the Returned Value
411: */
412: private boolean isNotInSourceSafe(String found) {
413: if (found == null) {
414: return true;
415: }
416:
417: String trimmed = found.trim();
418: if (trimmed == null) {
419: return true;
420: }
421:
422: return trimmed.equals("No matches found.");
423: }
424:
425: /**
426: * Description of the Method
427: *
428: *@param file Description of Parameter
429: *@param factory Description of Parameter
430: *@return Description of the Returned Value
431: *@exception IOException Description of Exception
432: */
433: private BufferedReader executeLocate(Runtime factory, String file)
434: throws IOException {
435: // Create the executable
436: String[] args = new String[3];
437: args[0] = exeFile;
438: args[1] = "LOCATE";
439: args[2] = getFilename(file);
440:
441: Process proc = factory.exec(args);
442: InputStream in = proc.getInputStream();
443:
444: // Read lines
445: return new BufferedReader(new InputStreamReader(in));
446: }
447:
448: /**
449: * Description of the Method
450: *
451: *@param found Description of Parameter
452: *@return Description of the Returned Value
453: */
454: private String extractProjectName(String found) {
455: int last = found.lastIndexOf("/");
456: if (last < 1) {
457: return found;
458: }
459:
460: return found.substring(0, last);
461: }
462:
463: /**
464: * Description of the Method
465: *
466: *@param fullName Description of Parameter
467: *@param prefix Description of Parameter
468: *@return Description of the Returned Value
469: */
470: private boolean startSame(String fullName, String prefix) {
471: System.out.println(" Comparing prefix:[" + prefix
472: + "] full:[" + fullName + "]");
473: return fullName.startsWith(prefix);
474: }
475:
476: /**
477: * Main program
478: *
479: *@param args the command line arguments
480: */
481: public static void main(String[] args) {
482: if (args.length != 1) {
483: System.out
484: .println("Syntax: java org.acm.seguin.version.SourceSafe filename");
485: return;
486: }
487:
488: (new SourceSafe()).checkIn(args[0]);
489: }
490: }
|