// Copyright 2004-2014 Jim Voris // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package com.qumasoft.server; import com.qumasoft.qvcslib.ArchiveInfoInterface; import com.qumasoft.qvcslib.DirectoryCoordinate; import com.qumasoft.qvcslib.QVCSConstants; import com.qumasoft.qvcslib.QVCSException; import com.qumasoft.qvcslib.ServedProjectProperties; import com.qumasoft.qvcslib.ServerResponseFactoryInterface; import com.qumasoft.qvcslib.Utility; import com.qumasoft.server.dataaccess.FileDAO; import com.qumasoft.server.dataaccess.impl.FileDAOImpl; import java.io.File; import java.sql.SQLException; import java.util.Collection; import java.util.logging.Level; import java.util.logging.Logger; /** * TODO -- this is not finished, or useful at all at the moment. * The class holds the code we use to verify that the trunk archives match the database. (Recall that trunk archives are the only * archive files there are). * * <p>For projects, the verification is absolutely strict: if the project exists in the served projects list, then it must exist on * disk, and it must exist in the database.</p> * * <p>For directories, the verification is fairly strict: the given directory id must match what we find in the archive directory. * If the directory has moved (i.e. it has a different appended path), then we'll update the database to capture the new appended * path. We do not allow additions of directories, or deletions of directories: If any are found, we'll throw a QVCSException.</p> * * <p>For files within a given directory, we allow renames, moves, additions, and deletions of files.</p> * * @author Jim Voris */ public final class DatabaseVerificationManager { // Create our logger object private static final Logger LOGGER = Logger.getLogger("com.qumasoft.server"); private static final DatabaseVerificationManager DATABASE_VERIFICATION_MANAGER = new DatabaseVerificationManager(); /** * Creates a new instance of DatabaseVerificationManager. */ private DatabaseVerificationManager() { } /** * Get the singleton instance of the Database verification manager. * * @return the singleton instance of the Database verification manager. */ public static DatabaseVerificationManager getInstance() { return DATABASE_VERIFICATION_MANAGER; } /** * Iterate over the Trunk to verify that it matches what's in the database. If there are differences, the file systems wins, and * we update the database to match the file system. */ void verifyTrunkToDatabase(ServedProjectProperties[] projectPropertiesList) throws QVCSException { LOGGER.log(Level.INFO, "QVCSEnterpriseServer: Verifying directory structure against database..."); // try // { // // Verify that the projects exist in the database. // verifyProjectsExistInDatabase(projectPropertiesList); // // // Iterate over the list of projects... // for (int i = 0; i < projectPropertiesList.length; i++) // { // // Wrap this work in a server transaction so the DirectoryContents // // stuff will behave in a useful way... // ServerResponseFactoryInterface bogusResponseObject = new BogusResponseObject(); // // // Keep track that we're in a transaction. // ServerTransactionManager.getInstance().clientBeginTransaction(bogusResponseObject); // // String archiveLocation = projectPropertiesList[i].getArchiveLocation(); // File projectBaseDirectory = new File(archiveLocation); // // // Verify the directory structure against the database. // verifyDirectoryStructureToDatabase(projectBaseDirectory, projectPropertiesList[i], bogusResponseObject); // // // And verify the directory contents objects for this project tree. // verifyFilesToDatabase(projectBaseDirectory, projectPropertiesList[i], bogusResponseObject); // // // Keep track that we ended this transaction. // ServerTransactionManager.getInstance().clientEndTransaction(bogusResponseObject); // } // } // catch (QVCSException e) // { // m_logger.log(Level.WARNING, Utility.expandStackTraceToString(e)); // throw e; // } } /** * Verify the directory structure for given project. * * @param directory the root directory of the project. * @param servedProjectProperties the project properties. * @param bogusResponseObject a bogus response object. * @throws QVCSException if something goes wrong. */ private void verifyDirectoryStructureToDatabase(File directory, ServedProjectProperties servedProjectProperties, ServerResponseFactoryInterface bogusResponseObject) throws QVCSException { // TODO } /** * Verify a given directory against the database. */ private void verifyFilesToDatabase(File directory, ServedProjectProperties servedProjectProperties, ServerResponseFactoryInterface bogusResponseObject) throws QVCSException { LOGGER.log(Level.INFO, "Verifying database for directory: [" + directory.getAbsolutePath() + "]"); String projectName = servedProjectProperties.getProjectName(); String viewName = QVCSConstants.QVCS_TRUNK_VIEW; String appendedPath = ServerUtility.deduceAppendedPath(directory, servedProjectProperties); File[] fileList = directory.listFiles(); if (fileList != null) { try { // Create the archiveDirManager for this directory... DirectoryCoordinate directoryCoordinate = new DirectoryCoordinate(projectName, viewName, appendedPath); ArchiveDirManager archiveDirManager = (ArchiveDirManager) ArchiveDirManagerFactoryForServer.getInstance() .getDirectoryManager(QVCSConstants.QVCS_SERVER_SERVER_NAME, directoryCoordinate, QVCSConstants.QVCS_SERVED_PROJECT_TYPE, QVCSConstants.QVCS_SERVER_USER, bogusResponseObject, false); verifyDatabaseFilesForArchiveDirManager(archiveDirManager); } catch (QVCSException e) { LOGGER.log(Level.WARNING, Utility.expandStackTraceToString(e)); } catch (SQLException e) { LOGGER.log(Level.WARNING, Utility.expandStackTraceToString(e)); throw new QVCSException("Could not verify database against archive directory tree."); } for (File fileList1 : fileList) { if (fileList1.isDirectory()) { // Recurse through the directory tree... verifyFilesToDatabase(fileList1, servedProjectProperties, bogusResponseObject); } } } } /** * Verify that the records in the database match what's on disk for a given archive directory. This method will update the * database as needed so that it matches what's on disk. * * @param archiveDirManager the directory manager for the directory that we're verifying. * @throws SQLException if there is a SQL problem. */ private void verifyDatabaseFilesForArchiveDirManager(ArchiveDirManager archiveDirManager) throws SQLException { // Wrap this in a transaction. DatabaseManager.getInstance().getConnection().setAutoCommit(false); FileDAO fileDAO = new FileDAOImpl(); try { // TODO. // Verify all the files in this directory. Collection<ArchiveInfoInterface> archiveInfoCollection = archiveDirManager.getArchiveInfoCollection().values(); // for (ArchiveInfoInterface archiveInfo : archiveInfoCollection) // { // com.qumasoft.server.datamodel.File file = new com.qumasoft.server.datamodel.File(); // file.setFileId(archiveInfo.getFileID()); // file.setBranchId(1); // We're guaranteed to be on the trunk here. // file.setDeletedFlag(false); // file.setDirectoryId(archiveDirManager.getDirectoryID()); // file.setFileName(archiveInfo.getShortWorkfileName()); // fileDAO.insert(file); // } DatabaseManager.getInstance().getConnection().commit(); } finally { DatabaseManager.getInstance().getConnection().setAutoCommit(true); } } /** * Verify that any project listed in the project properties list exists in the database. * * @param projectPropertiesList the list of served projects. * @throws QVCSException if we find a project that doesn't exist in the database. */ private void verifyProjectsExistInDatabase(ServedProjectProperties[] projectPropertiesList) throws QVCSException { throw new UnsupportedOperationException("Not yet implemented"); } }