package org.exist.collections.triggers; import java.io.IOException; import java.net.URISyntaxException; import java.util.Date; import java.util.Map; import org.exist.collections.Collection; import org.exist.collections.CollectionConfigurationException; import org.exist.dom.DocumentImpl; import org.exist.security.PermissionDeniedException; import org.exist.storage.DBBroker; import org.exist.storage.txn.Txn; import org.exist.util.LockException; import org.exist.xmldb.XmldbURI; import org.exist.xquery.XPathException; import org.exist.xquery.value.DateTimeValue; /** * This collection trigger will save all old versions of documents before * they are overwritten or removed. The old versions are kept in the * 'history root' which is by default '<code>/db/history</code>', but can be * changed with the parameter '<code>root</code>'. * You need to configure this trigger for every collection whose history you * want to preserve, by modifying '<code>collection.xconf</code>' such that it * resembles this: * * <pre> * <?xml version='1.0'?> * <collection xmlns='http://exist-db.org/collection-config/1.0'> * <triggers> * <trigger * event='update' * class='org.exist.collections.triggers.HistoryTrigger' * /> * <trigger * event='remove' * class='org.exist.collections.triggers.HistoryTrigger' * /> * </triggers> * </collection> * </pre> * * @author Mark Spanbroek * @see org.exist.collections.triggers.Trigger */ public class HistoryTrigger extends FilteringTrigger implements DocumentTrigger { protected XmldbURI rootPath = XmldbURI.ROOT_COLLECTION_URI.append("history"); public void configure(DBBroker broker, Collection parent, Map parameters) throws CollectionConfigurationException { super.configure(broker, parent, parameters); if(parameters.containsKey("root")) { try { rootPath = XmldbURI.xmldbUriFor(parameters.get("root").toString()); } catch(URISyntaxException e) { throw new CollectionConfigurationException(e); } } } public void prepare(int event, DBBroker broker, Txn transaction, XmldbURI documentName, DocumentImpl doc) throws TriggerException { if(doc == null) return; // construct the destination path XmldbURI path = rootPath.append(doc.getURI()); try { //construct the destination document name String dtValue = new DateTimeValue(new Date(doc.getMetadata().getLastModified())).getStringValue(); dtValue = dtValue.replaceAll(":", "-"); // multiple ':' are not allowed in URI so use '-' dtValue = dtValue.replaceAll("\\.", "-"); // as we are using '-' instead of ':' do the same for '.' XmldbURI name = XmldbURI.create(dtValue); // create the destination document //TODO : how is the transaction handled ? It holds the locks ! Collection destination = broker.getOrCreateCollection(transaction, path); broker.saveCollection(transaction, destination); broker.copyResource(transaction, doc, destination, name); } catch(XPathException xpe) { throw new TriggerException(xpe); } catch(IOException exception) { throw new TriggerException(exception); } catch(PermissionDeniedException exception) { throw new TriggerException(exception); } catch(LockException exception) { throw new TriggerException(exception); } } public void finish(int event, DBBroker broker, Txn transaction, XmldbURI documentPath, DocumentImpl document) { } }