1 17 18 19 20 package org.apache.lenya.cms.rc; 21 22 import java.io.File ; 23 import java.io.FileInputStream ; 24 import java.io.FileNotFoundException ; 25 import java.io.IOException ; 26 import java.io.InputStream ; 27 import java.io.OutputStream ; 28 import java.util.Date ; 29 30 import org.apache.lenya.util.XPSFileOutputStream; 31 import org.apache.log4j.Category; 32 33 36 public class RevisionController { 37 private static Category log = Category.getInstance(RevisionController.class); 38 39 public static final String systemUsername = "System"; 47 48 private String rcmlDir = null; 49 private String rootDir = null; 50 private String backupDir = null; 51 52 56 public RevisionController() { 57 Configuration conf = new Configuration(); 58 rcmlDir = conf.getRcmlDirectory(); 59 if (!new File (rcmlDir).exists()) 60 log.error("No such directory: " + rcmlDir); 61 backupDir = conf.getBackupDirectory(); 62 if (!new File (backupDir).exists()) 63 log.error("No such directory: " + backupDir); 64 rootDir = "conf.rootDirectory"; 65 } 66 67 74 public RevisionController(String rcmlDirectory, String backupDirectory, String rootDirectory) { 75 this.rcmlDir = rcmlDirectory; 76 this.backupDir = backupDirectory; 77 this.rootDir = rootDirectory; 78 } 79 80 85 public RevisionController(String rootDir) { 86 this(); 87 this.rootDir = rootDir; 88 } 89 90 95 public String toString() { 96 return "rcmlDir=" + rcmlDir + " , rcbakDir=" + backupDir + " , rootDir=" + rootDir; 97 } 98 99 110 public RCML getRCML(String source) throws FileNotFoundException , IOException , Exception { 111 return new RCML(rcmlDir, source, rootDir); 112 } 113 114 122 public File reservedCheckOut(String source, String identity) throws Exception { 123 124 File file = new File (rootDir + source); 125 130 131 RCML rcml = new RCML(rcmlDir, source, rootDir); 132 133 RCMLEntry entry = rcml.getLatestEntry(); 134 135 if (entry != null) { 139 log.debug("entry: " + entry); 140 log.debug("entry.type:" + entry.getType()); 141 log.debug("entry.identity" + entry.getIdentity()); 142 } 143 144 if ((entry != null) 145 && (entry.getType() != RCML.ci) 146 && !entry.getIdentity().equals(identity)) { 147 throw new FileReservedCheckOutException(rootDir + source, rcml); 148 } 149 150 rcml.checkOutIn(RCML.co, identity, new Date ().getTime(), false); 151 152 return file; 153 } 154 155 162 public boolean canCheckOut(String source, String identity) throws Exception { 163 RCML rcml = new RCML(rcmlDir, source, rootDir); 164 165 RCMLEntry entry = rcml.getLatestEntry(); 166 167 if (entry != null) { 171 log.debug("entry: " + entry); 172 log.debug("entry.type:" + entry.getType()); 173 log.debug("entry.identity" + entry.getIdentity()); 174 } 175 176 boolean checkedOutByOther = 177 entry != null && entry.getType() != RCML.ci && !entry.getIdentity().equals(identity); 178 179 return !checkedOutByOther; 180 } 181 182 196 public long reservedCheckIn(String destination, String identity, boolean backup) 197 throws FileReservedCheckInException, Exception { 198 RCML rcml = new RCML(rcmlDir, destination, rootDir); 199 200 CheckOutEntry coe = rcml.getLatestCheckOutEntry(); 201 CheckInEntry cie = rcml.getLatestCheckInEntry(); 202 203 if (!((coe == null) || identity.equals(RevisionController.systemUsername))) { 211 231 if ((cie != null) && (cie.getTime() > coe.getTime())) { 232 if (!cie.getIdentity().equals(identity)) { 234 throw new FileReservedCheckInException(rootDir + destination, rcml); 237 } 238 } else { 239 if (!coe.getIdentity().equals(identity)) { 241 throw new FileReservedCheckInException(rootDir + destination, rcml); 244 } 245 } 246 } 247 248 File originalFile = new File (rootDir, destination); 249 long time = new Date ().getTime(); 250 251 if (backup && originalFile.isFile()) { 252 File backupFile = new File (backupDir, destination + ".bak." + time); 253 File parent = new File (backupFile.getParent()); 254 255 if (!parent.isDirectory()) { 256 parent.mkdirs(); 257 } 258 259 log.info( 260 "Backup: copy " 261 + originalFile.getAbsolutePath() 262 + " to " 263 + backupFile.getAbsolutePath()); 264 265 InputStream in = new FileInputStream (originalFile.getAbsolutePath()); 266 267 OutputStream out = new XPSFileOutputStream(backupFile.getAbsolutePath()); 268 byte[] buffer = new byte[512]; 269 int length; 270 271 while ((length = in.read(buffer)) != -1) { 272 out.write(buffer, 0, length); 273 } 274 275 out.close(); 276 } 277 278 rcml.checkOutIn(RCML.ci, identity, time, backup); 279 rcml.pruneEntries(backupDir); 280 rcml.write(); 281 282 return time; 288 } 289 290 298 public String getBackupFilename(long time, String filename) { 299 File backup = new File (backupDir, filename + ".bak." + time); 300 301 return backup.getAbsolutePath(); 302 } 303 304 312 public File getBackupFile(long time, String filename) { 313 File backup = new File (backupDir, filename + ".bak." + time); 314 315 return backup; 316 } 317 318 333 public long rollback(String destination, String identity, boolean backupFlag, long time) 334 throws 335 FileReservedCheckInException, 336 FileReservedCheckOutException, 337 FileNotFoundException , 338 Exception { 339 File backup = new File (backupDir, destination + ".bak." + time); 342 File current = new File (rootDir, destination); 343 344 if (!backup.isFile()) { 345 throw new FileNotFoundException (backup.getAbsolutePath()); 346 } 347 348 if (!current.isFile()) { 349 throw new FileNotFoundException (current.getAbsolutePath()); 350 } 351 352 reservedCheckOut(destination, identity); 355 356 FileInputStream in = new FileInputStream (backup.getAbsolutePath()); 359 360 XPSFileOutputStream out = new XPSFileOutputStream(current.getAbsolutePath()); 361 byte[] buffer = new byte[512]; 362 int length; 363 364 while ((length = in.read(buffer)) != -1) { 365 out.write(buffer, 0, length); 366 } 367 368 out.close(); 369 370 long newtime = reservedCheckIn(destination, identity, backupFlag); 375 376 return newtime; 377 } 378 379 388 public void undoCheckIn(long time, String destination) throws Exception { 389 File backup = new File (backupDir + "/" + destination + ".bak." + time); 390 File current = new File (rootDir + destination); 391 392 RCML rcml = new RCML(rcmlDir, destination, rootDir); 393 394 if (!backup.isFile()) { 395 throw new FileNotFoundException (backup.getAbsolutePath()); 396 } 397 398 if (!current.isFile()) { 399 throw new FileNotFoundException (current.getAbsolutePath()); 400 } 401 402 FileInputStream in = new FileInputStream (backup.getAbsolutePath()); 403 404 XPSFileOutputStream out = new XPSFileOutputStream(current.getAbsolutePath()); 405 byte[] buffer = new byte[512]; 406 int length; 407 408 while ((length = in.read(buffer)) != -1) { 409 out.write(buffer, 0, length); 410 } 411 412 log.info("Undo: copy " + backup.getAbsolutePath() + " " + current.getAbsolutePath()); 413 414 rcml.deleteFirstCheckIn(); 415 out.close(); 416 } 417 418 423 public void deleteRevisions(String filename) throws RevisionControlException{ 424 try { 425 RCML rcml = this.getRCML(filename); 426 String [] times = rcml.getBackupsTime(); 427 for (int i=0; i < times.length; i++) { 428 long time = new Long (times[i]).longValue(); 429 File backup = this.getBackupFile(time, filename); 430 File parentDirectory = null; 431 parentDirectory = backup.getParentFile(); 432 boolean deleted = backup.delete(); 433 if (!deleted) { 434 throw new RevisionControlException("The backup file, "+backup.getCanonicalPath()+" could not be deleted!"); 435 } 436 if (parentDirectory != null 437 && parentDirectory.exists() 438 && parentDirectory.isDirectory() 439 && parentDirectory.listFiles().length == 0) { 440 parentDirectory.delete(); 441 } 442 } 443 } catch (Exception e) { 444 throw new RevisionControlException(e); 445 } 446 } 447 448 453 public void deleteRCML(String filename) throws RevisionControlException{ 454 try { 455 RCML rcml = this.getRCML(filename); 456 boolean deleted = rcml.delete(); 457 if (!deleted) { 458 throw new RevisionControlException("The rcml file could not be deleted!"); 459 } 460 } catch (Exception e) { 461 throw new RevisionControlException(e); 462 } 463 } 464 465 } 466 | Popular Tags |