001: /*
002: ** Java cvs client library package.
003: ** Copyright (c) 1997-2002 by Timothy Gerard Endres
004: **
005: ** This program is free software.
006: **
007: ** You may redistribute it and/or modify it under the terms of the GNU
008: ** Library General Public License (LGPL) as published by the Free Software
009: ** Foundation.
010: **
011: ** Version 2 of the license should be included with this distribution in
012: ** the file LICENSE.txt, as well as License.html. If the license is not
013: ** included with this distribution, you may find a copy at the FSF web
014: ** site at 'www.gnu.org' or 'www.fsf.org', or you may write to the Free
015: ** Software Foundation at 59 Temple Place - Suite 330, Boston, MA 02111 USA.
016: **
017: ** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND,
018: ** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR
019: ** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY
020: ** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR
021: ** REDISTRIBUTION OF THIS SOFTWARE.
022: **
023: */
024:
025: package com.ice.cvsc;
026:
027: import java.awt.*;
028: import java.io.*;
029: import java.util.*;
030:
031: /**
032: * Implements several general utility methods used by the cvs
033: * client package.
034: *
035: * @version $Revision: 2.11 $
036: * @author Timothy Gerard Endres, <a href="mailto:time@ice.com">time@ice.com</a>.
037: */
038:
039: public class CVSCUtilities extends Object {
040: static public final String RCS_ID = "$Id: CVSCUtilities.java,v 2.11 2003/07/27 01:08:32 time Exp $";
041: static public final String RCS_REV = "$Revision: 2.11 $";
042:
043: static private boolean redirectOutErr;
044: static private PrintStream out;
045: static private PrintStream err;
046:
047: static {
048: CVSCUtilities.redirectOutErr = false;
049: CVSCUtilities.out = null;
050: CVSCUtilities.err = null;
051: }
052:
053: static public boolean caseSensitivePathNames() {
054: boolean result = true;
055:
056: String osname = System.getProperty("os.name");
057:
058: if (osname != null) {
059: if (osname.startsWith("macos"))
060: result = false;
061: else if (osname.startsWith("Windows"))
062: result = false;
063: }
064:
065: return result;
066: }
067:
068: /**
069: * This class method determines if a path exists 'within'
070: * another path. In the cvsc package, we are constantly
071: * checking to be sure that a directory is contained within
072: * a given tree, or that a file is in the correct path.
073: * The difficulty is that each platform has different
074: * path separators and 'case' requirements. Worse, on
075: * systems like Windoze, the user can type lower case,
076: * while the FileDialog returns what may be upper case
077: * on the file system. This method is an attempt to
078: * normalize all of this.
079: *
080: * @param path The shorter or <em>parent</em> path.
081: * @param path The longer or <em>child</em> path.
082: * @return True if subPath is a subdirectory of path.
083: */
084:
085: static public boolean isSubpathInPath(String rootPath,
086: String subPath) {
087: boolean result = false;
088:
089: if (rootPath.length() > subPath.length()) {
090: result = false;
091: } else {
092: subPath = CVSCUtilities.importPath(subPath);
093: rootPath = CVSCUtilities.importPath(rootPath);
094:
095: if (!CVSCUtilities.caseSensitivePathNames()) {
096: subPath = subPath.toLowerCase();
097: rootPath = rootPath.toLowerCase();
098: }
099:
100: result = subPath.startsWith(rootPath);
101: }
102:
103: if (!result) {
104: CVSTracer.traceIf(true,
105: "CVSCUtilities.isSubpathInPath: FALSE result\n"
106: + " adjusted rootPath '" + rootPath
107: + "'\n" + " adjusted subPath '" + subPath
108: + "'");
109: }
110:
111: return result;
112: }
113:
114: static public int computeTranslation(CVSEntry entry) {
115: String options = entry.getOptions();
116:
117: int trans = CVSClient.TRANSLATE_ASCII;
118:
119: if (options != null && options.length() > 0) {
120: // REVIEW
121: // UNDONE You know this needs more sophisitication...
122: if (options.startsWith("-kb")) {
123: trans = CVSClient.TRANSLATE_NONE;
124: }
125: }
126:
127: return trans;
128: }
129:
130: // NOTE
131: // These are not really done. For instance, the Macintosh
132: // file system treats "::" as if it were "/../" under UNIX,
133: // and DOS has drive letters with colons, and so on...
134: // However, for our simply purposes, these translations
135: // appear to be adequate.
136: //
137: static public String exportPath(String path) {
138: return path.replace('/', File.separatorChar);
139: }
140:
141: static public String importPath(String path) {
142: return path.replace(File.separatorChar, '/');
143: }
144:
145: static public String ensureFinalSlash(String path) {
146: return (path.endsWith("/") ? path : path + "/");
147: }
148:
149: static public String stripFinalSlash(String path) {
150: return (path.endsWith("/") ? path.substring(0,
151: (path.length() - 1)) : path);
152: }
153:
154: static public String stripFinalSeparator(String path) {
155: for (;;) {
156: if (path.endsWith("/"))
157: path = path.substring(0, (path.length() - 1));
158: else if (path.endsWith(File.separator))
159: path = path.substring(0, (path.length() - 1));
160: else
161: break;
162: }
163:
164: return path;
165: }
166:
167: /**
168: * Given a localDirectory from a CVSEntry, get the
169: * parent directory of the localDirectory.
170: */
171: static public String getLocalParent(String localDir) {
172: localDir = CVSCUtilities.stripFinalSlash(localDir);
173: int index = localDir.lastIndexOf('/');
174: if (index > 0) {
175: localDir = localDir.substring(0, index);
176: }
177: return localDir;
178: }
179:
180: static public int slashCount(String s) {
181: int result = 0;
182: for (int cIdx = 0; cIdx < s.length(); ++cIdx) {
183: if (s.charAt(cIdx) == '/')
184: result++;
185: }
186: return result;
187: }
188:
189: static public boolean createEmptyFile(File f) {
190: boolean result = true;
191:
192: try {
193: FileWriter writer = new FileWriter(f);
194: writer.close();
195: } catch (IOException ex) {
196: result = false;
197: CVSTracer.traceWithStack("ERROR creating empty file '"
198: + f.getPath() + "' - " + ex.getMessage());
199: }
200:
201: return result;
202: }
203:
204: static public void writeStringFile(File f, String str)
205: throws IOException {
206: FileWriter writer = null;
207:
208: try {
209: writer = new FileWriter(f);
210:
211: if (str != null) {
212: writer.write(str);
213: }
214: } finally {
215: if (writer != null)
216: writer.close();
217: }
218: }
219:
220: static public String readStringFile(File f) throws IOException {
221: BufferedReader in = null;
222: String result = "";
223:
224: try {
225: in = new BufferedReader(new FileReader(f));
226: result = in.readLine();
227: if (result == null)
228: result = "";
229: } finally {
230: if (in != null)
231: try {
232: in.close();
233: } catch (IOException ex) {
234: }
235: }
236:
237: return result;
238: }
239:
240: static public void endRedirectOutput() {
241: if (CVSCUtilities.redirectOutErr) {
242: CVSCUtilities.redirectOutErr = false;
243: System.out.flush();
244: System.out.close();
245: System.setOut(CVSCUtilities.out);
246: System.setErr(CVSCUtilities.err);
247: CVSCUtilities.out = null;
248: CVSCUtilities.err = null;
249: }
250: }
251:
252: public static void integrateEntriesLog(File adminDir)
253: throws IOException {
254: PrintWriter outBak = null;
255: BufferedReader logIn = null;
256: BufferedReader entIn = null;
257:
258: // System.err.println( "INTEGRATE LOGFILE: " + adminDir.getPath() );
259:
260: File logF = new File(adminDir, "Entries.Log");
261:
262: if (!logF.exists())
263: return;
264:
265: // System.err.println
266: // ( "Integrating '" + logF.getPath() + "' into 'Entries'" );
267:
268: Vector nameV = new Vector();
269: Vector lineV = new Vector();
270:
271: File entF = new File(adminDir, "Entries");
272: File bakF = new File(adminDir, "Entries.Backup");
273:
274: try {
275: entIn = new BufferedReader(new FileReader(entF));
276:
277: for (;;) {
278: String inLine = entIn.readLine();
279: if (inLine == null)
280: break;
281:
282: char ch = inLine.charAt(0);
283: if (ch != '/' && ch != 'D')
284: continue;
285:
286: int begIdx = (ch == 'D' ? 2 : 1);
287: int idx = inLine.indexOf("/", begIdx);
288: if (idx == -1)
289: continue;
290:
291: lineV.addElement(inLine);
292: nameV.addElement(inLine.substring(begIdx, idx));
293: }
294:
295: entIn.close();
296: entIn = null;
297:
298: // System.err.println( "WE'VE READ " + lineV.size() + " entries" );
299:
300: logIn = new BufferedReader(new FileReader(logF));
301:
302: for (;;) {
303: String inLine = logIn.readLine();
304: if (inLine == null)
305: break;
306:
307: if (inLine.length() < 5)
308: break;
309:
310: // System.err.println( "Processing LOG LINE: " + inLine );
311:
312: char selCh = inLine.charAt(0);
313: char sepCh = inLine.charAt(1);
314: if ((selCh != 'A' && selCh != 'R') || sepCh != ' ') {
315: // System.err.println( "IGNORE bad selector: " + inLine );
316: continue;
317: }
318:
319: char ch = inLine.charAt(2);
320:
321: int begIdx = (ch == 'D' ? 4 : 3);
322: int idx = inLine.indexOf("/", begIdx);
323: if (idx == -1)
324: continue;
325:
326: String name = inLine.substring(begIdx, idx);
327: // System.err.println( "Processing LOG NAME: " + name );
328:
329: if (selCh == 'A') {
330: if (nameV.contains(name)) {
331: // System.err.println( "OVERWRITING: " + name );
332: idx = nameV.indexOf(name);
333: lineV.setElementAt(inLine.substring(2), idx);
334: } else {
335: // System.err.println( "APPENDING: " + name );
336: nameV.addElement(name);
337: lineV.addElement(inLine.substring(2));
338: }
339: } else if (selCh == 'R') {
340: if (nameV.contains(name)) {
341: // System.err.println( "REMOVING: " + name );
342: idx = nameV.indexOf(name);
343: nameV.removeElementAt(idx);
344: lineV.removeElementAt(idx);
345: } else {
346: // System.err.println( "IGNORING: " + name );
347: }
348: }
349: }
350:
351: logIn.close();
352: logIn = null;
353:
354: // System.err.println( "WRITING BACKUP: " + bakF.getPath() );
355: // System.err.println( " nameV.size=" + nameV.size()
356: // + ", lineV.size=" + lineV.size() );
357:
358: outBak = new PrintWriter(new FileWriter(bakF));
359:
360: for (int i = 0, sz = nameV.size(); i < sz; ++i) {
361: outBak.println(lineV.elementAt(i));
362: }
363:
364: outBak.close();
365: outBak = null;
366:
367: // System.err.println( "RENAMING BACKUP: to " + entF.getPath() );
368:
369: entF.delete();
370: if (bakF.renameTo(entF)) {
371: // System.err.println( "DELETING LOGFILE: " + logF.getPath() );
372: logF.delete();
373: } else {
374: throw new IOException("RENAME FAILED from '"
375: + bakF.getPath() + "' to '" + entF.getPath()
376: + "'");
377: }
378:
379: // System.err.println( "DONE" );
380: } finally {
381: try {
382: if (entIn != null)
383: entIn.close();
384: if (logIn != null)
385: logIn.close();
386: if (outBak != null)
387: outBak.close();
388: } catch (IOException ex) {
389: }
390: }
391: }
392:
393: }
|