Java tutorial
/* * Copyright (c) 2009-2010 The Regents of the University of California. * All rights reserved. * * '$Author: crawl $' * '$Date: 2014-02-11 09:32:24 -0800 (Tue, 11 Feb 2014) $' * '$Revision: 32584 $' * * Permission is hereby granted, without written agreement and without * license or royalty fees, to use, copy, modify, and distribute this * software and its documentation for any purpose, provided that the above * copyright notice and the following two paragraphs appear in all copies * of this software. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, * ENHANCEMENTS, OR MODIFICATIONS. * */ package org.kepler.objectmanager.cache; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInput; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Arrays; import java.util.Enumeration; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.StringTokenizer; import java.util.Vector; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreeModel; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.kepler.build.modules.Module; import org.kepler.build.modules.ModuleTree; import org.kepler.configuration.ConfigurationManager; import org.kepler.configuration.ConfigurationProperty; import org.kepler.sms.NamedOntModel; import org.kepler.sms.OntologyCatalog; import org.kepler.util.DotKeplerManager; import org.kepler.util.FileUtil; import org.kepler.util.sql.DatabaseFactory; import ptolemy.util.MessageHandler; public class LocalRepositoryManager { private static final Log log = LogFactory.getLog(LocalRepositoryManager.class.getName()); private static final boolean isDebugging = log.isDebugEnabled(); public static final String KAR_LOCAL_REPOS_TABLE_NAME = "KAR_LOCAL_REPOS"; /** The name in the configuration file containing the display name * for modules. */ private static final String MODULE_DISPLAY_NAME = "moduleDisplayName"; /** * The list of KAR files that make up the library. */ private Vector<File> _karFiles; /** List of MoML files that make up the library. */ private Vector<File> _xmlFiles; private Connection _conn; private Statement _stmt; private PreparedStatement _insertPrepStmt; private PreparedStatement _deletePrepStmt; private PreparedStatement _updateNamePrepStmt; private PreparedStatement _updatePathPrepStmt; private LinkedHashMap<String, TreeModel> _folderModel; public TreeModel getFolderModel(String name) { return _folderModel.get(name); } public void setFolderModel(LinkedHashMap<String, TreeModel> folderModel) { _folderModel = folderModel; } /** * The local repositories that the cache is built from. Keys are the * repository names, values are the directory files. */ private LinkedHashMap<LocalRepository, String> _localRepositories; /** * This is the folder that we save KARs to by default. */ private LocalRepository _localSaveRepo; /** * The file in the module readwrite area where we'll save the name of the * user selected local repository to save KAR files in by default. */ private String _localSaveRepoFileName; /** * We keep a copy of the initial local repositories so we can see if they * have changed. */ private LinkedHashMap<LocalRepository, String> _checkpointRepos; private File _defaultUserWorkflowDirectory; /** * Empty Constructor. */ public LocalRepositoryManager() { DotKeplerManager dkm = DotKeplerManager.getInstance(); // Set up file name for storing default local save directory File modDir = dkm.getTransientModuleDirectory("core"); if (modDir != null) { _localSaveRepoFileName = modDir.toString(); } else { _localSaveRepoFileName = System.getProperty("KEPLER"); } if (!_localSaveRepoFileName.endsWith(File.separator)) { _localSaveRepoFileName += File.separator; } _localSaveRepoFileName += "LocalSaveRepository"; // Set up the location of the default workflows directory _defaultUserWorkflowDirectory = dkm.getPersistentUserWorkflowsDir();//new File(persistentDir, "workflows"); if (!_defaultUserWorkflowDirectory.exists()) { _defaultUserWorkflowDirectory.mkdirs(); } // Set up prepared statements for select,insert,update,delete // local repository information try { _conn = DatabaseFactory.getDBConnection(); } catch (Exception e) { MessageHandler.error("Error opening cache database.", e); return; } try { _stmt = _conn.createStatement(); _insertPrepStmt = _conn.prepareStatement( "insert into " + KAR_LOCAL_REPOS_TABLE_NAME + " (name,path) values ( ?, ? ) "); _deletePrepStmt = _conn .prepareStatement("DELETE FROM " + KAR_LOCAL_REPOS_TABLE_NAME + " WHERE PATH = ? "); _updateNamePrepStmt = _conn .prepareStatement("UPDATE " + KAR_LOCAL_REPOS_TABLE_NAME + " SET NAME = ? WHERE PATH = ? "); _updatePathPrepStmt = _conn .prepareStatement("UPDATE " + KAR_LOCAL_REPOS_TABLE_NAME + " SET PATH = ? WHERE NAME = ? "); } catch (SQLException e) { e.printStackTrace(); } initLocalRepos(); initLocalSaveRepo(); } /** * Initialize local repositories that contain KAR files. */ private void initLocalRepos() { // Check to see if there are any local repositories try { String query = "SELECT count(*) FROM " + KAR_LOCAL_REPOS_TABLE_NAME; if (isDebugging) log.debug(query); ResultSet rs = null; try { rs = _stmt.executeQuery(query); if (rs != null && rs.next()) { int cnt = rs.getInt(1); if (cnt <= 0) { // Set the defaults if there are no local repositories in // the database this.setDefaultLocalRepos(); } } } finally { if (rs != null) { rs.close(); } } } catch (SQLException sqle) { log.error(sqle.getMessage()); } refreshReposFromDB(); } public LinkedHashMap<LocalRepository, String> selectReposFromDB() { LinkedHashMap<LocalRepository, String> localRepos = new LinkedHashMap<LocalRepository, String>(); try { String query = "SELECT name,path FROM " + KAR_LOCAL_REPOS_TABLE_NAME + " order by name"; if (isDebugging) log.debug(query); ResultSet rs = null; try { rs = _stmt.executeQuery(query); if (rs != null) { while (rs.next()) { String theName = rs.getString(1); String paths = rs.getString(2); LocalRepository repo = new LocalRepository(paths); localRepos.put(repo, theName); } } } finally { if (rs != null) { rs.close(); } } } catch (SQLException sqle) { log.error(sqle.getMessage()); sqle.printStackTrace(); } return localRepos; } /** * Repopulate our local hashtable from the database. */ private void refreshReposFromDB() { _localRepositories = selectReposFromDB(); } /** * Return a list of all the KAR files that were found after calling * scanReposForKarFiles() * * @return Vector of File objects pointing to KAR files */ public Vector<File> getKarFiles() { return _karFiles; } /** Return a list of all the XML files that were found after calling * scanReposForXMLFiles() */ public Vector<File> getXMLFiles() { //return new Vector<File>(); return _xmlFiles; } /** * Search for Kar files in local Kar Repositories and build a list of all * the KAR files that are found. This list can be retrieved using * getKarFiles() */ public void scanReposForKarFiles() { log.info("Scanning Local Repositories for KAR files..."); _karFiles = new Vector<File>(); _xmlFiles = new Vector<File>(); LinkedHashMap<String, TreeModel> folderModel = new LinkedHashMap<String, TreeModel>(); setFolderModel(folderModel); for (LocalRepository repoRoot : getLocalRepositories().keySet()) { if (isDebugging) { log.debug("Recursing for Kar files in local repository: " + repoRoot.toString()); } refreshFolderModelForRepo(repoRoot); } } /** * Refresh the folder model for the specified local repository. * * @param repo */ public void refreshFolderModelForRepo(LocalRepository repo) { if (isDebugging) log.debug("refreshFolderModelForRepo(" + repo.toString() + ")"); String repoName = getLocalRepositories().get(repo); if (repoName == null) { log.warn("Error: not a local repository: " + repo); return; } TreeModel tm = getFolderModel(repoName); if (tm == null) { tm = new DefaultTreeModel(new DefaultMutableTreeNode(repo)); _folderModel.put(repoName, tm); } DefaultMutableTreeNode root = (DefaultMutableTreeNode) tm.getRoot(); root.removeAllChildren(); for (File dir : repo.getDirectories()) { findKarsRecursive(dir, 20, root); } } /** * Given the File object for a folder in a local repository, return the * corresponding DefaultMutableTreeNode object from the Folder model. * * @param folder * @return */ public DefaultMutableTreeNode getFolderModelNode(File folder) { String folderStr = folder.toString(); for (LocalRepository repo : getLocalRepositories().keySet()) { for (File repoRootDir : repo.getDirectories()) { if (folderStr.equals(repoRootDir.toString())) { return (DefaultMutableTreeNode) getFolderModel(getLocalRepositories().get(repo)).getRoot(); } else if (folderStr.startsWith(repoRootDir.toString())) { String remainder = folderStr.substring(repoRootDir.toString().length()); if (remainder.startsWith(File.separator)) { remainder = remainder.substring(1); } StringTokenizer st = new StringTokenizer(remainder, File.separator); TreeModel tm = getFolderModel(getLocalRepositories().get(repo)); DefaultMutableTreeNode root = (DefaultMutableTreeNode) tm.getRoot(); String dir = null; File current = repoRootDir; int count = st.countTokens(); while (st.hasMoreTokens()) { dir = st.nextToken(); current = new File(current.toString(), dir); DefaultMutableTreeNode dmtn = checkChildren(root, current); if (dmtn == null) { return null; } if (count == 1) { return dmtn; } else { root = dmtn; } count--; } } } } return null; } /** * * @param dmtn * @param dir * @return the TreeNode that corresponds to the given directory name */ private DefaultMutableTreeNode checkChildren(DefaultMutableTreeNode dmtn, File folder) { Enumeration<?> children = dmtn.children(); while (children.hasMoreElements()) { DefaultMutableTreeNode child = (DefaultMutableTreeNode) children.nextElement(); if (child.getUserObject().equals(folder)) { return child; } } return null; } public void refreshFolderModelForFolder(File folder) { // find the corresponding TreeNode DefaultMutableTreeNode dmtn = getFolderModelNode(folder); if (dmtn == null) { return; } // remove the children of that TreeNode dmtn.removeAllChildren(); // rebuild the children of the TreeNode findKarsRecursive(folder, 20, dmtn); } /** * Recursive function for finding files that end in ".kar" (case * insensitive). * * @param dir * The root of the local repository that contains KAR files * @param depth * The maximum recursion depth */ private void findKarsRecursive(File dir, int depth, DefaultMutableTreeNode tn) { if (isDebugging) log.debug(depth + ": " + dir.toString()); if (!dir.exists()) { log.warn(dir.toString() + " does not exist"); return; } if (!dir.isDirectory()) { log.warn(dir.toString() + " is not a directory"); return; } if (depth < 0) { log.warn(dir.toString() + " is too deep"); return; } File[] listing = dir.listFiles(); for (int i = 0; i < listing.length; i++) { File currentListing = listing[i]; if (currentListing.isDirectory()) { if (currentListing.getName().equals(".svn")) { // skip .svn folders } else if (currentListing.getName().contains(".")) { // skip any folders that contain periods // ptolemy cannot handle periods in NamedObj Names. System.out.println("WARNING: skipping due to periods: " + currentListing); } else { DefaultMutableTreeNode dmtn = new DefaultMutableTreeNode(currentListing); tn.add(dmtn); findKarsRecursive(currentListing, (depth - 1), dmtn); } } else { if (currentListing.getName().toLowerCase().endsWith(".kar")) { _karFiles.addElement(currentListing); } else if (currentListing.getName().toLowerCase().endsWith(".xml")) { _xmlFiles.addElement(currentListing); } } } } /** * */ private void initLocalSaveRepo() { File localSaveRepoFile = new File(_localSaveRepoFileName); if (localSaveRepoFile.exists()) { if (isDebugging) { log.debug("localSaveRepo exists: " + localSaveRepoFile.toString()); } try { InputStream is = null; ObjectInput oi = null; try { is = new FileInputStream(localSaveRepoFile); oi = new ObjectInputStream(is); Object newObj = oi.readObject(); setLocalSaveRepo((File) newObj); return; } finally { if (oi != null) { oi.close(); } if (is != null) { is.close(); } } } catch (Exception e1) { // problem reading file, try to delete it log.warn("Exception while reading localSaveRepoFile: " + e1.getMessage()); try { localSaveRepoFile.delete(); } catch (Exception e2) { log.warn("Unable to delete localSaveRepoFile: " + e2.getMessage()); } } } try { setDefaultSaveRepo(); } catch (Exception e) { e.printStackTrace(); } } /** * @param directory */ public void setLocalSaveRepo(File dir) { if (isDebugging) log.debug("setLocalSaveRepo(" + dir + ")"); if (getRepositoryForFile(dir) != null) { _localSaveRepo = new LocalRepository(dir); serializeLocalSaveRepo(); } } /** * Set the default Save repository. * * @throws Exception */ public void setDefaultSaveRepo() { if (isDebugging) log.debug("setDefaultSaveRepo()"); // Use the default workflows directory // see if it's the root of a local repository LocalRepository repo = getRepositoryForFile(_defaultUserWorkflowDirectory); if (repo == null) { // see if it's a subdirectory in a local repository repo = getContainingLocalRepository(_defaultUserWorkflowDirectory); } if (repo != null) { setLocalSaveRepo(repo.getDefaultDirectory()); return; } // If there is no default workflows directory // Set the save repo to the first local repo in the list for (LocalRepository localRepo : _localRepositories.keySet()) { setLocalSaveRepo(localRepo.getDefaultDirectory()); break; } } /** * Set the default local repositories to be the kar directories for each of * the modules in the system along with a default workflows directory. */ public void setDefaultLocalRepos() { if (isDebugging) log.debug("setDefaultLocalRepos()"); // Set up a default list of local repository directories _localRepositories = new LinkedHashMap<LocalRepository, String>(); try { String deleteAll = "delete from " + KAR_LOCAL_REPOS_TABLE_NAME; if (isDebugging) log.debug(deleteAll); _stmt.executeUpdate(deleteAll); } catch (SQLException sqle) { log.error(sqle.getMessage()); sqle.printStackTrace(); } final DotKeplerManager dkm = DotKeplerManager.getInstance(); for (Module module : ModuleTree.instance()) { if (isDebugging) log.debug("Checking for kar directory in " + module.getStemName()); //String modName = m.getName(); String modName = module.getStemName(); File modDir = dkm.getPersistentModuleDirectory(modName); File karDir = new File(modDir, "kar"); if (karDir.isDirectory() && karDir.exists()) { if (isDebugging) log.debug(karDir + " " + modName); try { String repoName = getLocalRepositoryName(modName); addLocalRepoRootDir(karDir, repoName); } catch (Exception e) { MessageHandler.error("Error adding local repository " + karDir, e); } } // NOTE: use the fully versioned name of the module instead of // the name without a version since the demo workflows can // change between versions of the same module. // File workflowDir = dkm.getPersistentModuleWorkflowsDir(module.getName()); // only add the demos to the library. // <module>/workflows/data may contain XML files that generate // errors when parsed. // see http://bugzilla.ecoinformatics.org/show_bug.cgi?id=5643 File demoDir = new File(workflowDir, "demos"); if (demoDir.isDirectory() && demoDir.exists()) { if (isDebugging) log.debug(demoDir + " " + modName); try { String repoName = getLocalRepositoryName(modName); addLocalRepoRootDir(demoDir, repoName); } catch (Exception e) { MessageHandler.error("Error adding local repository " + karDir, e); } } /* else if (modName.equals(Module.PTOLEMY) || modName.matches(Module.PTOLEMY+"-\\d+\\.\\d+") || modName.matches(Module.PTOLEMY_KEPLER+"-\\d+\\.\\d+")) { Project project = ProjectLocator.getAntProject(); // NOTE: getAntProject() may return null; in this case // create a new one. if (project == null) { project = new Project(); } final FileSet fileSet = new FileSet(); fileSet.setProject(project); fileSet.setDir(module.getSrc()); XXX space added to prevent closing comment fileSet.setIncludes("** /demo"); fileSet.setExcludesfile(new File(project.getBaseDir(), "build-area/settings/ptolemy-excludes")); final String[] files = fileSet.getDirectoryScanner() .getIncludedDirectories(); for (String name : files) { String repoName = modName; repoName = repoName.substring(0, 1).toUpperCase() + repoName.substring(1); try { System.out.println(name); addLocalRepoRootDir(new File(module.getSrc(), name), repoName); } catch (Exception e) { MessageHandler.error("Error adding local repository " + karDir, e); } } } */ } // Include a default workflows directory try { addLocalRepoRootDir(_defaultUserWorkflowDirectory, dkm.getPersistentUserWorkflowsDirName()); } catch (Exception e) { e.printStackTrace(); } if (getLocalRepositories().size() <= 0) { log.error("No local repositories specified."); } } /** * Serialize the local save repository to a file on disk so it can be loaded * the next time Kepler starts. */ private void serializeLocalSaveRepo() { if (isDebugging) log.debug("serializeLocalSaveRepo()"); File localSaveRepoFile = new File(_localSaveRepoFileName); if (localSaveRepoFile.exists()) { if (isDebugging) log.debug("delete " + localSaveRepoFile); localSaveRepoFile.delete(); } try { OutputStream os = new FileOutputStream(localSaveRepoFile); ObjectOutputStream oos = new ObjectOutputStream(os); oos.writeObject(_localSaveRepo.getDefaultDirectory()); oos.flush(); oos.close(); if (isDebugging) { log.debug("wrote " + localSaveRepoFile); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * Save the local repo dirs to a private variable so we can determine when * they have changed between build points. */ public void setCheckpoint() { _checkpointRepos = (LinkedHashMap<LocalRepository, String>) getLocalRepositories().clone(); } /** * Reset the list of local repositories to be what it was the last time the * setCheckpoint() method was called. */ public void restoreCheckpoint() { _localRepositories = (LinkedHashMap<LocalRepository, String>) _checkpointRepos.clone(); } /** * Check to see if the LocalRepositories have changed since the last time * setCheckpoint() was called. * * @return true if the local repositories have changed */ public boolean changedSinceCheckpoint() { if (!_checkpointRepos.equals(getLocalRepositories())) { return true; } return false; } public boolean isLocalRepositoryName(String name) { for (String l : getLocalRepositories().values()) { if (l.equals(name)) { return true; } } return false; } /** * This method only removes the given directory from the in-memory repository * list. To update the database you must call the synchronizeDB() method. * * @param directory * @throws Exception * if the directory could not be removed */ public void removeLocalRepoRootDir(File directory) throws Exception { if (isDebugging) log.debug("removeLocalRepoRootDir(" + directory + ")"); // do not remove anything if there is only one local repo left if (_localRepositories.size() == 1) { throw new Exception("There must always be at least one local repository directory"); } LocalRepository repo = getRepositoryForFile(directory); if (repo != null) { boolean isSaveDir = false; if (getSaveRepository().equals(directory)) { isSaveDir = true; } int numLeft = repo.removeDir(directory); if (numLeft == 0) { _localRepositories.remove(repo); } if (isSaveDir) { setDefaultSaveRepo(); } } else { throw new Exception("Unable to remove directory " + directory + "\n No Local Repository directory matching that name was found."); } } /** * Synchronize the KAR_LOCAL_REPOS table with the _localRepositories private variable list. * This method only removes rows from the table that are not in the list. * It does not add rows to the table for extra entries that are in the list. */ public void synchronizeDB() { LinkedHashMap<LocalRepository, String> localRepos = selectReposFromDB(); for (LocalRepository repo : localRepos.keySet()) { if (!_localRepositories.containsKey(repo)) { try { // this will cascade deletion of KARs and KAR contents // from the tables _deletePrepStmt.setString(1, repo.toString()); _deletePrepStmt.executeUpdate(); _conn.commit(); } catch (SQLException sqle) { sqle.printStackTrace(); } } } } /** * Change the name of a local repository. * * @param directory the default root directory of the repository * @param name * @throws Exception */ public void setLocalRepoName(File directory, String name) throws Exception { if (_localRepositories.containsValue(name)) { throw new Exception("This name is already assigned to a local repository directory."); } Iterator<NamedOntModel> models = OntologyCatalog.instance().getNamedOntModels(); while (models.hasNext()) { if (models.next().getName().equals(name)) { throw new Exception("This name is already being used for an ontology."); } } LocalRepository repo = getRepositoryForFile(directory); if (repo == null) { throw new Exception("No repository found with directory " + directory); } try { _updateNamePrepStmt.setString(1, name); _updateNamePrepStmt.setString(2, repo.getDirectoriesAsString()); _updateNamePrepStmt.executeUpdate(); _conn.commit(); String oldName = _localRepositories.put(repo, name); if (isDebugging) log.debug(oldName + " was changed to " + name); } catch (SQLException sqle) { log.warn(sqle.getMessage()); } } /** * Given a file, return true if it is in a local repository, false if it is * not. * * @param aFile * @return */ public boolean isInLocalRepository(File aFile) { LocalRepository containingRepo = getContainingLocalRepository(aFile); if (containingRepo != null) { return true; } return false; } /** * Given a file, return the local repository that it is in or null if it is * not in a local repository. This also returns null if the file passed in * is a local repository. * * @param aFile * @return */ public LocalRepository getContainingLocalRepository(File aFile) { for (LocalRepository repo : getLocalRepositories().keySet()) { for (File repoRootDir : repo.getDirectories()) { try { if (FileUtil.isSubdirectory(repoRootDir, aFile)) { return repo; } } catch (Exception e) { e.printStackTrace(); } } } return null; } /** * Convenience method for addLocalRepoRootDir(File, String) * * @param directory * @throws Exception */ public void addLocalRepoRootDir(File directory) throws Exception { addLocalRepoRootDir(directory, directory.getName()); } /** Add a local repository for a given root directory and name. If * a repository with that name already exists, the directory is added * to the list of root directories for that repository. * @param directory * @throws Exception */ public void addLocalRepoRootDir(File directory, String name) throws Exception { if (isDebugging) log.debug("addLocalRepoRootDir(" + directory + ", " + name + ")"); if (!directory.isDirectory()) { throw new Exception("The specified local repository root must be a directory"); } String selFileName = FileUtil.clean(directory); LocalRepository existingRepo = null; // check to make sure this directory is not a sub directory // of any existing local repositories for (Map.Entry<LocalRepository, String> entry : getLocalRepositories().entrySet()) { final LocalRepository repo = entry.getKey(); for (File localDir : repo.getDirectories()) { // make sure this selection doesn't match an existing local repository exactly if (FileUtil.clean(localDir).equals(selFileName)) { throw new Exception("Local repository root directory was not added because \n" + directory + "\n is already listed as a local repository root directory."); } // make sure this selection is not a subdirecctory of an existing local repository boolean selectionIsSub = FileUtil.isSubdirectory(localDir, directory); if (selectionIsSub) { throw new Exception("Local repository was not added because \n" + directory + "\n is a subdirectory of \n" + localDir); } // make sure this selection does not contain an existing local repository as a subdirectory boolean repoIsSub = FileUtil.isSubdirectory(directory, localDir); if (repoIsSub) { throw new Exception("Local repository was not added because \n" + localDir + "\n is a subdirectory of \n" + directory); } } final String repoName = entry.getValue(); if (repoName.equals(name)) { existingRepo = repo; } } try { // see if a repository with that name already exists if (existingRepo == null) { _insertPrepStmt.setString(1, name); _insertPrepStmt.setString(2, directory.toString()); _insertPrepStmt.executeUpdate(); _localRepositories.put(new LocalRepository(directory), name); } else { String paths = existingRepo.addDirectory(directory); _updatePathPrepStmt.setString(1, paths); _updatePathPrepStmt.setString(2, name); _updatePathPrepStmt.executeUpdate(); } _conn.commit(); } catch (SQLException sqle) { sqle.printStackTrace(); } } public LinkedHashMap<LocalRepository, String> getLocalRepositories() { return _localRepositories; } public File getSaveRepository() { if (_localSaveRepo != null) { List<File> dirs = _localSaveRepo.getDirectories(); if (!dirs.isEmpty()) { return dirs.get(0); } } return null; } /** Get the repository for a file. Returns null if no repository * has a root directory matching this path. */ public LocalRepository getRepositoryForFile(File file) { for (LocalRepository repo : getLocalRepositories().keySet()) { if (repo.isFileRepoDirectory(file)) { return repo; } } return null; } /** * Method for getting an instance of this singleton class. */ public static LocalRepositoryManager getInstance() { return LocalRepositoryManagerHolder.INSTANCE; } private static class LocalRepositoryManagerHolder { private static final LocalRepositoryManager INSTANCE = new LocalRepositoryManager(); } /** Get the display name of a local repository for a module. */ public static String getLocalRepositoryName(String moduleName) throws Exception { String name = null; // see if the module name is customized Module module = ModuleTree.instance().getModuleByStemName(moduleName); if (module != null) { ConfigurationProperty property = ConfigurationManager.getInstance().getProperty(module); if (property != null) { ConfigurationProperty nameProperty = property.getProperty(MODULE_DISPLAY_NAME); if (nameProperty != null) { name = nameProperty.getValue(); } } } // the module name was not customized, so return a name the same as the // module name with the first letter upper-case. if (name == null) { name = moduleName; name = name.substring(0, 1).toUpperCase() + name.substring(1); } return name; } /** A repository on the local disk. The repository may have more than one * root directory. */ public static class LocalRepository { /** Get the default directory. */ public File getDefaultDirectory() { return _directories.get(0); } /** Returns true if the given file is one of the directories of this repository. */ public boolean isFileRepoDirectory(File file) { for (File dir : _directories) { if (dir.equals(file)) { return true; } } return false; } /** Get the absolute path of the default root directory. */ @Override public String toString() { //System.out.println("in toString from: " + new Exception().getStackTrace()[1]); return getDefaultDirectory().toString(); } /** Returns true iff the given object is a LocalRepository containing * the same directories this LocalRepository. */ @Override public boolean equals(Object object) { if (object == null || !(object instanceof LocalRepository)) { return false; } else { // see if the directories are the same return _directoriesString.equals(((LocalRepository) object)._directoriesString); } } /** Get the directories in separated by File.pathSeparator character. */ private String getDirectoriesAsString() { return _directoriesString; } /** Get the hash code of this LocalRepository. */ @Override public int hashCode() { // use the hash code of the directories in this repository return _directoriesString.hashCode(); } /** Remove a root directory. * @return the number of remaining root directories. */ public int removeDir(File directory) { _directories.remove(directory); _updateDirectoriesString(); return _directories.size(); } /** Create a new Repository with a root directory. */ private LocalRepository(File dir) { addDirectory(dir); } /** Create a new Repository with a set of root directories. * @param paths A string of paths separated by File.pathSeparator. */ private LocalRepository(String paths) { String[] parts = paths.split(File.pathSeparator); for (String part : parts) { addDirectory(new File(part)); } } /** Add a root directory. * @return A string of paths separated by File.pathSeparator. */ private String addDirectory(File directory) { _directories.add(directory); _updateDirectoriesString(); return _directoriesString; } /** Get the root directories. */ private List<File> getDirectories() { return new LinkedList<File>(_directories); } /** Update _directoriesString to be the sorted list of directories * in _directories separated by File.pathSeparator. */ private void _updateDirectoriesString() { // get the directories as an array and sort lexicographically final File[] array = _directories.toArray(new File[_directories.size()]); Arrays.sort(array); StringBuilder buf = new StringBuilder(); for (int i = 0; i < array.length - 1; i++) { buf.append(array[i].getAbsolutePath()); buf.append(File.pathSeparatorChar); } buf.append(array[array.length - 1]); _directoriesString = buf.toString(); } /** The root directories. */ private List<File> _directories = new LinkedList<File>(); /** The root directories separated by File.pathSeparator character. */ private String _directoriesString = ""; } }