1 17 18 19 20 package org.apache.lenya.cms.rc; 21 22 import java.io.File ; 23 import java.io.IOException ; 24 import java.util.ArrayList ; 25 import java.util.HashMap ; 26 import java.util.Map ; 27 import java.util.Vector ; 28 29 import javax.xml.parsers.ParserConfigurationException ; 30 31 import org.apache.lenya.xml.DocumentHelper; 32 import org.apache.lenya.xml.NamespaceHelper; 33 import org.apache.lenya.xml.XPointerFactory; 34 import org.apache.log4j.Category; 35 import org.w3c.dom.Document ; 36 import org.w3c.dom.Element ; 37 import org.w3c.dom.Node ; 38 import org.w3c.dom.NodeList ; 39 40 43 public class RCML { 44 private static Category log = Category.getInstance(RCML.class); 45 46 public static final short co = 0; 47 public static final short ci = 1; 48 49 private File rcmlFile; 50 private Document document = null; 51 private boolean dirty = false; 52 private int maximalNumberOfEntries = 5; 53 54 private static Map ELEMENTS = new HashMap (); 55 protected static final String ELEMENT_CHECKIN = "CheckIn"; 56 protected static final String ELEMENT_CHECKOUT = "CheckOut"; 57 protected static final String ELEMENT_BACKUP = "Backup"; 58 59 { 60 ELEMENTS.put(new Short (ci), ELEMENT_CHECKIN); 61 ELEMENTS.put(new Short (co), ELEMENT_CHECKOUT); 62 } 63 64 67 public RCML() { 68 71 maximalNumberOfEntries = 10; 72 maximalNumberOfEntries = (2 * maximalNumberOfEntries) + 1; 73 } 74 75 86 public RCML(String rcmlDirectory, String filename, String rootDirectory) throws Exception { 87 this(); 88 rcmlFile = new File (rcmlDirectory, filename + ".rcml"); 89 90 if (!rcmlFile.isFile()) { 91 File dataFile = new File (rootDirectory, filename); 94 long lastModified = 0; 95 96 if (dataFile.isFile()) { 97 lastModified = dataFile.lastModified(); 98 } 99 100 initDocument(); 101 102 checkOutIn(RCML.ci, RevisionController.systemUsername, lastModified, false); 107 108 File parent = new File (rcmlFile.getParent()); 109 parent.mkdirs(); 110 111 write(); 112 } else { 113 document = DocumentHelper.readDocument(rcmlFile); 114 } 115 } 116 117 120 public void initDocument() throws ParserConfigurationException { 121 document = DocumentHelper.createDocument(null, "XPSRevisionControl", null); 122 } 123 124 130 protected void finalize() throws IOException , Exception { 131 if (this.isDirty()) { 132 log.debug("RCML.finalize(): calling write()"); 133 write(); 134 } 135 } 136 142 public void write() throws IOException , Exception { 143 DocumentHelper.writeDocument(document, rcmlFile); 144 clearDirty(); 145 } 146 147 158 public void checkOutIn(short type, String identity, long time, boolean backup) 159 throws IOException , Exception { 160 161 if (type != co && type != ci) { 162 throw new IllegalArgumentException ( 163 "ERROR: " + this.getClass().getName() + ".checkOutIn(): No such type"); 164 } 165 166 NamespaceHelper helper = new NamespaceHelper(null, "", document); 167 168 Element identityElement = helper.createElement("Identity", identity); 169 Element timeElement = helper.createElement("Time", "" + time); 170 171 String elementName = (String ) ELEMENTS.get(new Short (type)); 172 Element checkOutElement = helper.createElement(elementName); 173 174 checkOutElement.appendChild(identityElement); 175 checkOutElement.appendChild(timeElement); 176 177 if (backup) { 178 Element backupElement = helper.createElement(ELEMENT_BACKUP); 179 checkOutElement.appendChild(backupElement); 180 } 181 182 Element root = document.getDocumentElement(); 183 root.insertBefore(checkOutElement, root.getFirstChild()); 184 185 setDirty(); 186 187 if (type == co) { 203 write(); 204 } 205 } 206 207 214 public CheckOutEntry getLatestCheckOutEntry() throws Exception { 215 XPointerFactory xpf = new XPointerFactory(); 216 217 Vector firstCheckOut = 218 xpf.select( 219 document.getDocumentElement(), 220 "xpointer(/XPSRevisionControl/CheckOut[1]/Identity)xpointer(/XPSRevisionControl/CheckOut[1]/Time)"); 221 222 if (firstCheckOut.size() == 0) { 223 return null; 226 } 227 228 String [] fcoValues = xpf.getNodeValues(firstCheckOut); 229 long fcoTime = new Long (fcoValues[1]).longValue(); 230 231 return new CheckOutEntry(fcoValues[0], fcoTime); 232 } 233 234 241 public CheckInEntry getLatestCheckInEntry() throws Exception { 242 XPointerFactory xpf = new XPointerFactory(); 243 244 Vector firstCheckIn = 245 xpf.select( 246 document.getDocumentElement(), 247 "xpointer(/XPSRevisionControl/CheckIn[1]/Identity)xpointer(/XPSRevisionControl/CheckIn[1]/Time)"); 248 249 if (firstCheckIn.size() == 0) { 250 return null; 253 } 254 255 String [] fciValues = xpf.getNodeValues(firstCheckIn); 256 long fciTime = new Long (fciValues[1]).longValue(); 257 258 return new CheckInEntry(fciValues[0], fciTime); 259 } 260 261 268 public RCMLEntry getLatestEntry() throws Exception { 269 CheckInEntry cie = getLatestCheckInEntry(); 270 CheckOutEntry coe = getLatestCheckOutEntry(); 271 272 if ((cie != null) && (coe != null)) { 273 if (cie.getTime() > coe.getTime()) { 274 return cie; 275 } else { 276 return coe; 277 } 278 } 279 280 if (cie != null) { 281 return cie; 282 } else { 283 return coe; 284 } 285 } 286 287 294 public Vector getEntries() throws Exception { 295 XPointerFactory xpf = new XPointerFactory(); 296 297 Vector entries = 298 xpf.select( 299 document.getDocumentElement(), 300 "xpointer(/XPSRevisionControl/CheckOut|/XPSRevisionControl/CheckIn)"); 301 Vector RCMLEntries = new Vector (); 302 303 for (int i = 0; i < entries.size(); i++) { 304 Element elem = (Element ) entries.get(i); 305 String time = elem.getElementsByTagName("Time").item(0).getFirstChild().getNodeValue(); 306 String identity = 307 elem.getElementsByTagName("Identity").item(0).getFirstChild().getNodeValue(); 308 309 if (elem.getTagName().equals("CheckOut")) { 310 RCMLEntries.add(new CheckOutEntry(identity, new Long (time).longValue())); 311 } else { 312 RCMLEntries.add(new CheckInEntry(identity, new Long (time).longValue())); 313 } 314 } 315 316 return RCMLEntries; 317 } 318 319 327 public void pruneEntries(String backupDir) throws Exception { 328 XPointerFactory xpf = new XPointerFactory(); 329 330 Vector entries = 331 xpf.select( 332 document.getDocumentElement(), 333 "xpointer(/XPSRevisionControl/CheckOut|/XPSRevisionControl/CheckIn)"); 334 335 for (int i = maximalNumberOfEntries; i < entries.size(); i++) { 336 Element current = (Element ) entries.get(i); 337 338 String time = 340 current.getElementsByTagName("Time").item(0).getFirstChild().getNodeValue(); 341 File backupFile = new File (backupDir + "/" + time + ".bak"); 342 backupFile.delete(); 343 current.getParentNode().removeChild(current); 345 } 346 } 347 348 355 public org.w3c.dom.Document getDOMDocumentClone() throws Exception { 356 Document documentClone = DocumentHelper.createDocument(null, "dummy", null); 357 documentClone.removeChild(documentClone.getDocumentElement()); 358 documentClone.appendChild(documentClone.importNode(document.getDocumentElement(), true)); 359 360 return documentClone; 361 } 362 363 368 public boolean isDirty() { 369 return dirty; 370 } 371 372 375 protected void setDirty() { 376 dirty = true; 377 } 378 379 382 protected void clearDirty() { 383 dirty = false; 384 } 385 386 391 public void deleteFirstCheckIn() throws Exception { 392 XPointerFactory xpf = new XPointerFactory(); 393 Node root = document.getDocumentElement(); 394 Vector firstCheckIn = xpf.select(root, "xpointer(/XPSRevisionControl/CheckIn[1])"); 395 root.removeChild((Node ) firstCheckIn.elementAt(0)); 396 root.removeChild(root.getFirstChild()); setDirty(); 398 } 399 400 407 public String [] getBackupsTime() throws Exception { 408 XPointerFactory xpf = new XPointerFactory(); 409 410 Vector entries = 411 xpf.select( 412 document.getDocumentElement(), 413 "xpointer(/XPSRevisionControl/CheckIn)"); 414 ArrayList times = new ArrayList (); 415 416 for (int i = 0; i < entries.size(); i++) { 417 Element elem = (Element ) entries.get(i); 418 String time = elem.getElementsByTagName("Time").item(0).getFirstChild().getNodeValue(); 419 NodeList backupNodes = elem.getElementsByTagName(ELEMENT_BACKUP); 420 if (backupNodes != null && backupNodes.getLength()>0) { 421 times.add(time); 422 } 423 } 424 return (String []) times.toArray(new String [times.size()]); 425 426 } 427 428 433 public boolean delete() { 434 File rcmlFile = this.rcmlFile; 435 File directory = rcmlFile.getParentFile(); 436 boolean deleted = rcmlFile.delete(); 437 if (directory.exists() 438 && directory.isDirectory() 439 && directory.listFiles().length == 0) { 440 directory.delete(); 441 } 442 return deleted; 443 } 444 } 445 | Popular Tags |