/* * Created on Aug 6, 2004 */ package org.openedit.repository.filesystem; import java.io.File; import java.io.FilenameFilter; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.openedit.repository.ContentItem; import org.openedit.repository.RepositoryException; import com.openedit.util.PathUtilities; /** * @author Matthew Avery, mavery@einnovation.com */ public abstract class VersionedRepository extends FileRepository { static final String VERSIONS = ".versions"; static final String META_DATA = ".metadata.xml"; private static final Log log = LogFactory.getLog(VersionedRepository.class); public VersionedRepository() { //We always need a default constructor } public ContentItem get( String inPath ) throws RepositoryException { File file = getFile( inPath); FileItem contentItem = new FileItem(); // if ( inPath.endsWith(".html") && !file.exists() ) // { // String xmlPath = PathUtilities.extractPagePath( inPath )+ ".xml"; // File xfile = getFile(xmlPath); // if( xfile.exists()) // { // file = xfile; // contentItem.setActualPath(xmlPath); // } // } // checkVersion(file, inPath); contentItem.setPath( inPath ); contentItem.setFile( file); return contentItem; } public ContentItem getStub( String inPath ) throws RepositoryException { return createContentItem(inPath); } /** * Be careful with this method since it can slow the system down * @param inPath */ protected void checkVersion(File file, String inPath) throws RepositoryException { if (file.isDirectory()) { return; } //if there is no versions directory yet then we return File versionsDirectory = getVersionsDirectory( file ); if( !versionsDirectory.exists() ) { return; } int m = maxVersionNumber(file); if ( m == 0) { createInitialContentItem( inPath ); } else { String max = String.valueOf( m ); File lastVersion = getVersionFile( file, max ); if( file.lastModified() > lastVersion.lastModified() ) { ContentItem newItem = createContentItem(inPath); newItem.setAuthor( "admin" ); newItem.setMessage("edited version from disk"); saveVersion( newItem ); } } } public void put( ContentItem inContentItem ) throws RepositoryException { String path = inContentItem.getPath(); File file = getFile( path ); if (file.isDirectory()) { if( !inContentItem.isFolder() ) { throw new RepositoryException( "Error attempting to write content to a " + "folder instead of a file for path " + path ); } else { return; //folder already exists } } checkReservedPaths( path ); if (file.exists()) { if (inContentItem.getMessage() == null) { inContentItem.setMessage( inContentItem.getPath() + " modified" ); } inContentItem.setType( ContentItem.TYPE_EDITED ); } else { if (inContentItem.getMessage() == null) { inContentItem.setMessage( inContentItem.getPath() + " added" ); } inContentItem.setType( ContentItem.TYPE_ADDED ); } if (path.endsWith("/") && !file.exists()) { file.mkdirs(); } else { writeContent( inContentItem ); } if ( inContentItem.isMakeVersion() ) { saveVersion( inContentItem ); } } protected String[] listFiles( final String inFileName, File versionsDirectory ) { FilenameFilter filenameFilter = new FilenameFilter() { public boolean accept( File dir, String name ) { return name.endsWith( inFileName ) && !name.endsWith( META_DATA ); } }; String[] filesInDirectory = versionsDirectory.list( filenameFilter ); return filesInDirectory; } protected void checkReservedPaths( String inPath ) throws RepositoryException { if (inPath.indexOf( VERSIONS ) > -1) { throw new RepositoryException( "The path \"" + inPath + "\" is a reserved path. " + "Choose a different path or use a different repository." ); } } protected int maxVersionNumber( File inFile ) { File versionsDirectory = getVersionsDirectory( inFile ); String[] oldVersionPaths = listFiles( inFile.getName(), versionsDirectory ); int maxVersionNum = 0; if ( oldVersionPaths != null) { for ( int n = 0; n < oldVersionPaths.length; n++ ) { int versionNum = extractVersionNumberFromFilename( oldVersionPaths[n] ); maxVersionNum = Math.max( maxVersionNum, versionNum ); } } return maxVersionNum; } protected int extractVersionNumberFromFilename( String inVersionPath ) { int separator = inVersionPath.indexOf( '~' ); if (separator >= 0 ) { try { //.versions/test.jpg~99 //~._~monday //1~~monday //1~._~monday String name = PathUtilities.extractFileName(inVersionPath); separator = inVersionPath.indexOf( '~' ); if( separator == -1) { return 0; } return Integer.parseInt( name.substring( 0, separator ) ); } catch( NumberFormatException e ) { log.error("Should not get errors " + e); } return 0; } else { return 0; } } public void move( ContentItem inSource, ContentItem inDestination ) throws RepositoryException { File sourceFile = getFile( inSource.getPath() ); File destination = getFile( inDestination.getPath() ); if ( inDestination.getMessage() == null) { inDestination.setMessage( inSource.getPath() + " moved to " + inDestination.getPath() ); } if ( inDestination.getType() == null) { inDestination.setType( ContentItem.TYPE_MOVED); } if( inDestination.getPath().endsWith("/")) { destination.mkdirs(); } moveFiles( sourceFile, destination ); if ( inDestination.isMakeVersion() ) { saveVersion( inDestination ); } } public void copy( ContentItem inSource, ContentItem inDestination ) throws RepositoryException { File sourceFile = getFile( inSource ); File destination = getFile( inDestination.getPath() ); if ( inDestination.getMessage() == null) { inDestination.setMessage( inSource.getPath() + " copied to " + inDestination.getPath() ); } if ( inDestination.getType() == null) { inDestination.setType( ContentItem.TYPE_COPIED); } copyFiles(sourceFile, destination); if ( inDestination.isMakeVersion() ) { saveVersion( inDestination ); } } public void remove( ContentItem inContentItem ) throws RepositoryException { File todelete = getFile( inContentItem.getPath() ); if ( inContentItem.getMessage() == null) { inContentItem.setMessage( inContentItem.getPath() + " removed"); } inContentItem.setType( ContentItem.TYPE_REMOVED ); /* if ( inContentItem.exists() ) { File metadata = getMetaDataFile(todelete); if ( metadata.exists() ) { incrementVersion( inContentItem ); saveVersion( inContentItem ); } } */ if( inContentItem.isMakeVersion() ) { saveVersion(inContentItem); } deleteAll(todelete); } public abstract List getVersions( String inPath ) throws RepositoryException; // protected ContentItem getContentItem( String inPath, ContentItem inContentItem ) // { // FileItem contentItem = new FileItem(); // contentItem.setPath( inPath ); // contentItem.setFile( getVersionFile( getFile( inPath ), inContentItem.getVersion() ) ); // return contentItem; // } protected ContentItem createInitialContentItem( String inPath ) throws RepositoryException { ContentItem contentItem = createContentItem(inPath); contentItem.setPath(inPath); contentItem.setAuthor( "admin" ); contentItem.setMessage( "automatic version" ); contentItem.setVersion( "1" ); contentItem.setType( ContentItem.TYPE_ADDED ); if ( contentItem.exists() ) { saveVersion( contentItem ); } return contentItem; } protected File getVersionsDirectory( String inPath ) { return getVersionsDirectory( new File( getExternalPath(), inPath ) ); } protected File getVersionsDirectory( File inSourceFile ) { File reservedDirectory = new File( inSourceFile.getParentFile(), VERSIONS ); return reservedDirectory; } protected File getMetaDataFile( File file ) { File metadata = new File( getVersionsDirectory( file ), file.getName() + META_DATA ); return metadata; } protected abstract void saveVersion( ContentItem inContentItem ) throws RepositoryException; /** * @param inFile * @param inNumber * @return */ protected File getVersionFile( File inSourceFile, String inVersionNumber ) { File versionFile = new File( getVersionsDirectory( inSourceFile ), inVersionNumber + '~' + inSourceFile.getName() ); return versionFile; } }