001: /*
002: * Copyright (C) 2001, 2002 Robert MacGrogan
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2.1 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: *
018: *
019: * $Archive: SourceJammer$
020: * $FileName: SourceVersionChecker.java$
021: * $FileID: 3964$
022: *
023: * Last change:
024: * $AuthorName: Rob MacGrogan$
025: * $Date: 4/23/03 5:05 PM$
026: * $Comment: Replaced GPL header with LGPL header.$
027: */
028:
029: package org.sourcejammer.client.filesys;
030:
031: import java.util.Hashtable;
032: import java.io.IOException;
033: import org.sourcejammer.util.ConfigurationException;
034: import org.sourcejammer.util.FileUtil;
035: import org.sourcejammer.util.RepeatingResponse;
036: import org.sourcejammer.util.TempDirectoryManager;
037: import sun.awt.RepaintArea;
038:
039: /**
040: * Title: $FileName: SourceVersionChecker.java$
041: * @author $AuthorName: Rob MacGrogan$
042: * @version $VerNum: 2$<br><br>
043: *
044: * $Description: $
045: * $KeyWordsOff: $<br><br>
046: *
047: * The function of this class is to act as the go-between for retreiving source
048: * files from the server and saving them to the local file system and also for
049: * retreiving files from the local filesystem and sending them to the server.<br /><br />
050: *
051: * This class uses the file source.jam to track what has been stored in the
052: * directory it is responsible for. The source.jam file contains information about
053: * the version number and archive that each relavent file originates from. If
054: * the version number and archive match and the file, the file does not need
055: * to be retrieved again from the server.
056: */
057: public class SourceVersionChecker {
058:
059: public static final String OLD_FILE_INFO_FILE_NAME = "source.jam";
060: public static final String LOCAL_FILE_INFO_FILE_NAME = ".source.jam";
061: private java.io.File mflTargetDirectory = null;
062: private Hashtable mhshSourceInfo = null;
063: private String msServerURL = null;
064: private String msArchiveName = null;
065:
066: /**
067: * @param flTargetDirectory -- the directory that this SourceVersionChecker
068: * is responsible for.
069: * @param serverURL -- URL for the SJ server that the client is connected to.
070: * @param archiveName -- name of the SJ archive the client is connected to.
071: */
072: public SourceVersionChecker(java.io.File flTargetDirectory,
073: String serverURL, String archiveName) throws IOException {
074: mflTargetDirectory = flTargetDirectory;
075: msServerURL = serverURL;
076: msArchiveName = archiveName;
077: reloadSourceJamHashtable();
078: }
079:
080: /**
081: * Save the file (byte array) to the target directory for this
082: * SourceVersionChecker, using the name specified.
083: *
084: * @param sName -- name to use in saving the file.
085: * @param lSourceVersionUniqueID -- unique ID of the VERSION of the file
086: * being saved.
087: * @param byFile -- the file as a byte array.
088: * @param setToReadOnly -- if true, the file will be set to read-only after
089: * it is saved.
090: * @param promptIfWritable -- prompts the user if a file named sName already
091: * exists in this directory and that file is NOT read-only. This
092: * property only works when called from Swing. Always set to false
093: * if calling from command line.
094: *
095: * @return true if the file was saved successfully. False otherwise.
096: */
097: public boolean saveFile(String sName, long lSourceVersionUniqueID,
098: byte[] byFile, boolean setToReadOnly,
099: RepeatingResponse repeating) throws IOException {
100:
101: int iNumBytes = byFile.length;
102: boolean bFileWritten = false;
103: if (repeating != null) {
104: bFileWritten = FileSysUtil.writeLocalFile(
105: mflTargetDirectory, sName, byFile, setToReadOnly,
106: repeating);
107: } else {
108: bFileWritten = FileSysUtil.writeLocalFile(
109: mflTargetDirectory, sName, byFile, setToReadOnly);
110: }
111: if (bFileWritten) {
112: java.io.File flFile = new java.io.File(mflTargetDirectory,
113: sName);
114:
115: long lDate = flFile.lastModified();
116: StoredFileInfoBean bnInfo = getStoredFileInfo(sName);
117: bnInfo.setSourceVersionUniqueID(lSourceVersionUniqueID);
118: bnInfo.setDate(flFile.lastModified());
119: bnInfo.setNumBytes(flFile.length());
120: bnInfo.setArchiveName(msArchiveName);
121: bnInfo.setServerURL(msServerURL);
122: saveSourceJamFile();
123: }
124: return bFileWritten;
125: }
126:
127: /**
128: * Save the file (byte array) to the target directory for this
129: * SourceVersionChecker, using the name specified.
130: *
131: * @param sName -- name to use in saving the file.
132: * @param lSourceVersionUniqueID -- unique ID of the VERSION of the file
133: * being saved.
134: * @param lTempFileId -- id of temp file to be saved to parent directory.
135: * @param setToReadOnly -- if true, the file will be set to read-only after
136: * it is saved.
137: *
138: * @return true if the file was saved successfully. False otherwise.
139: */
140: public boolean saveFile(String sName, long lSourceVersionUniqueID,
141: long lTempFileId, boolean setToReadOnly,
142: RepeatingResponse repeating) throws IOException {
143:
144: java.io.File flTemp = TempDirectoryManager
145: .getTempFileById(lTempFileId);
146: java.io.File flFile = new java.io.File(mflTargetDirectory,
147: sName);
148: boolean bFileWritten = false;
149: if (repeating != null) {
150: bFileWritten = FileSysUtil.streamFileToFile(flTemp, flFile,
151: setToReadOnly, repeating);
152: } else {
153: bFileWritten = FileSysUtil.streamFileToFile(flTemp, flFile,
154: setToReadOnly);
155: }
156: //Remove temp file whether written or not so we don't have to deal with it
157: //later.
158: TempDirectoryManager.deleteTempFile(lTempFileId);
159: if (bFileWritten) {
160: long lDate = flFile.lastModified();
161: StoredFileInfoBean bnInfo = getStoredFileInfo(sName);
162: bnInfo.setSourceVersionUniqueID(lSourceVersionUniqueID);
163: bnInfo.setDate(flFile.lastModified());
164: bnInfo.setNumBytes(flFile.length());
165: bnInfo.setArchiveName(msArchiveName);
166: bnInfo.setServerURL(msServerURL);
167: saveSourceJamFile();
168: }
169: return bFileWritten;
170: }
171:
172: /**
173: * Returns the StoredFileInfoBean for the specified file in the
174: * directory served by this SourceVersionChecker. The StoredFileInfoBean
175: * will contain identifying information about version of this file
176: * that is stored in this directory. This information may or may not be
177: * current. Call isStoredFileInfoAccurate() to check.
178: */
179: public StoredFileInfoBean getStoredFileInfo(String sFileName)
180: throws IOException {
181: StoredFileInfoBean oReturn = null;
182: oReturn = (StoredFileInfoBean) mhshSourceInfo.get(sFileName);
183: if (oReturn == null) {
184: oReturn = buildStoredInfoBeanForCurrentFile(sFileName);
185: mhshSourceInfo.put(sFileName, oReturn);
186: }
187: return oReturn;
188: }
189:
190: /**
191: * Updates the source.jam file for the target directory for this
192: * SourceVersionChecker. Sets the version ID of the specified file.
193: *
194: * @param sFileName -- name of the file whose version id is to be updated.
195: * @param lSourceVersionID -- version id of the specified file.
196: */
197: public void updateLocalInfo(String sFileName, long lSourceVersionID)
198: throws IOException {
199: StoredFileInfoBean oNewInfo = buildStoredInfoBeanForCurrentFile(sFileName);
200: oNewInfo.setSourceVersionUniqueID(lSourceVersionID);
201: mhshSourceInfo.put(sFileName, oNewInfo);
202: saveSourceJamFile();
203: }
204:
205: /**
206: * Returns true if the file info in the source.jam file matches the actual
207: * file in the directory.
208: */
209: public boolean isStoredFileInfoAccurate(String sFileName)
210: throws IOException {
211: boolean bReturn = false;
212: if (mhshSourceInfo != null) {
213: StoredFileInfoBean bn = (StoredFileInfoBean) mhshSourceInfo
214: .get(sFileName);
215: StoredFileInfoBean bnCheck = buildStoredInfoBeanForCurrentFile(sFileName);
216: if (bn != null && bn.equalsIgnoreVersion(bnCheck)) {
217: bReturn = true;
218: }
219: }
220: return bReturn;
221: }
222:
223: /**
224: * Returns true if the specified version of the specified file is the
225: * version of that file currently stored in the directory for this
226: * SourceVersionChecker.
227: */
228: public boolean isFileCurrent(String sFileName,
229: long lSourceVersionUniqueID) throws IOException {
230: boolean bReturn = false;
231: StoredFileInfoBean bn = (StoredFileInfoBean) mhshSourceInfo
232: .get(sFileName);
233: if (bn != null) {
234: if (isStoredFileInfoAccurate(sFileName)
235: && lSourceVersionUniqueID == bn
236: .getSourceVersionUniqueID()) {
237: bReturn = true;
238: }
239: }
240: return bReturn;
241: }
242:
243: /**
244: * Builds a new StoredFileInfoBean (except for the Version #) from the
245: * current file in the directory.
246: */
247: private StoredFileInfoBean buildStoredInfoBeanForCurrentFile(
248: String sFileName) throws IOException {
249:
250: StoredFileInfoBean bnReturn = null;
251: java.io.File fl = new java.io.File(mflTargetDirectory,
252: sFileName);
253: bnReturn = new StoredFileInfoBean();
254: bnReturn.setDate(fl.lastModified());
255: bnReturn.setName(sFileName);
256: bnReturn.setNumBytes(fl.length());
257: bnReturn.setArchiveName(msArchiveName);
258: bnReturn.setServerURL(msServerURL);
259: return bnReturn;
260: }
261:
262: /**
263: * Save the info about the particular file to the source.jam file.
264: */
265: private void updateFileInfo(StoredFileInfoBean bn)
266: throws IOException {
267: Hashtable hsh = getSourceJamHasttable();
268: hsh.put(bn.getName(), bn);
269: saveSourceJamFile();
270: }
271:
272: private void saveSourceJamFile() throws IOException {
273: Hashtable hsh = getSourceJamHasttable();
274: java.io.File flSourceJam = new java.io.File(mflTargetDirectory,
275: LOCAL_FILE_INFO_FILE_NAME);
276: if (flSourceJam.isHidden()) {
277: FileSysUtil.makeFileVisible(flSourceJam);
278: }
279: FileSysUtil.writeObjectToFileSys(hsh, flSourceJam);
280: if (!flSourceJam.isHidden()) {
281: FileSysUtil.makeFileHidden(flSourceJam);
282: }
283: }
284:
285: private Hashtable getSourceJamHasttable() {
286: if (mhshSourceInfo == null) {
287: makeNewSourceJamIfNull();
288: }
289: return mhshSourceInfo;
290: }
291:
292: private synchronized void makeNewSourceJamIfNull() {
293: if (mhshSourceInfo == null) {
294: mhshSourceInfo = new Hashtable();
295: }
296: }
297:
298: private synchronized void reloadSourceJamHashtable()
299: throws IOException {
300: if (mflTargetDirectory.isDirectory()
301: && mflTargetDirectory.exists()) {
302: java.io.File flSourceInfo = getSourceFile();
303: if (flSourceInfo.exists()) {
304: Object o = FileSysUtil
305: .readObjectFromFileSys(flSourceInfo);
306: try {
307: mhshSourceInfo = (Hashtable) o;
308: } catch (Throwable ex) {
309: //source.jam file is corrupted. Remove it.
310: flSourceInfo.delete();
311: mhshSourceInfo = new Hashtable();
312: }
313: }//end if source.jam exists
314: else {
315: mhshSourceInfo = new Hashtable();
316: }
317: }//end if target directory exists
318: }
319:
320: private java.io.File getSourceFile() {
321: java.io.File fl = new java.io.File(mflTargetDirectory,
322: LOCAL_FILE_INFO_FILE_NAME);
323: if (!fl.exists()) {
324: //In case they've got a .source.jam file with the old name.
325: java.io.File flOld = new java.io.File(mflTargetDirectory,
326: OLD_FILE_INFO_FILE_NAME);
327: if (flOld.exists()) {
328: flOld.renameTo(fl);
329: }
330: }
331: return fl;
332: }
333: }
|