// 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.qvcslib; import java.util.Collections; import java.util.Iterator; import java.util.Map; import java.util.TreeMap; import java.util.logging.Level; import java.util.logging.Logger; /** * Archive Directory Manager Factory. * * @author Jim Voris */ public final class ArchiveDirManagerFactory { // This is a singleton. private static final ArchiveDirManagerFactory ARCHIVE_DIR_MANAGER_FACTORY = new ArchiveDirManagerFactory(); // Create our logger object private static final Logger LOGGER = Logger.getLogger("com.qumasoft.qvcslib"); private final Map<String, ArchiveDirManagerInterface> directoryManagerMap; private final Map<String, AbstractProjectProperties> projectPropertiesMap; private final Map<String, String> serverPasswordsMap; private final Map<String, String> serverUsersMap; /** * Creates a new instance of ArchiveDirManagerFactory. */ private ArchiveDirManagerFactory() { directoryManagerMap = Collections.synchronizedMap(new TreeMap<String, ArchiveDirManagerInterface>()); projectPropertiesMap = Collections.synchronizedMap(new TreeMap<String, AbstractProjectProperties>()); serverPasswordsMap = Collections.synchronizedMap(new TreeMap<String, String>()); serverUsersMap = Collections.synchronizedMap(new TreeMap<String, String>()); } /** * Get the factory singleton. * @return the factory singleton. */ public static ArchiveDirManagerFactory getInstance() { return ARCHIVE_DIR_MANAGER_FACTORY; } /** * Create the archive directory manager for the given parameters. * @param serverName the server name. * @param directoryCoordinate the directory coordinate. * @param projectType the project type. * @param projectProperties the project properties. * @param userName the user name. * @param discardObsoleteFilesFlag true if we should discard obsolete files (this is only used when first porting C++ flavor archives to QVCS-Enterprise use). * @return the archive dir manager interface for the given parameters. * @throws QVCSException if we have problems. */ public synchronized ArchiveDirManagerInterface getDirectoryManager(String serverName, DirectoryCoordinate directoryCoordinate, String projectType, AbstractProjectProperties projectProperties, String userName, boolean discardObsoleteFilesFlag) throws QVCSException { projectPropertiesMap.put(getPropertiesViewKey(serverName, directoryCoordinate.getProjectName(), directoryCoordinate.getViewName(), projectType), projectProperties); return getArchiveDirectoryManager(serverName, directoryCoordinate.getProjectName(), projectProperties, directoryCoordinate.getViewName(), directoryCoordinate.getAppendedPath()); } /** * Discard any directory manager references associated with the given parameters. * @param serverName the server name. * @param projectName the project name. * @param viewName the view name. */ public synchronized void discardViewDirectoryManagers(String serverName, String projectName, String viewName) { String keyPrefix; if (serverName.length() > 0) { keyPrefix = serverName + ":" + projectName + ":" + viewName + "//"; } else { keyPrefix = projectName + ":" + viewName + "//"; } Iterator<String> it = directoryManagerMap.keySet().iterator(); while (it.hasNext()) { String key = it.next(); if (key.startsWith(keyPrefix)) { it.remove(); } } } /** * Reset the directory map. Basically discard any references that we're holding of archive directory managers. */ public void resetDirectoryMap() { directoryManagerMap.clear(); } private ArchiveDirManagerInterface getArchiveDirectoryManager(String serverName, String projectName, AbstractProjectProperties projectProperties, String viewName, String appendedPath) throws QVCSException { String keyValue = getProjectViewKey(serverName, projectName, viewName, projectProperties, appendedPath); LOGGER.log(Level.FINE, "ArchiveDirManagerFactory.getDirectoryManager: Getting directory manager for: " + keyValue); ArchiveDirManagerInterface directoryManager = directoryManagerMap.get(keyValue); if (directoryManager == null) { // There is no directoryManager for this archive directory yet. // We'll need to make one. Figure out which kind we need -- // a proxy or a local directory manager. if (projectProperties.isRemoteProject()) { // We're running on the client... LOGGER.log(Level.FINE, "ArchiveDirManagerFactory.getDirectoryManager: creating ArchiveDirManagerProxy for directory " + appendedPath); // Get the password for this project. The GUI should have set this via a call to setProjectPassword // before calling the factory to build the ArchiveDirManager. String serverPassword = serverPasswordsMap.get(serverName); String userName = serverUsersMap.get(serverName); directoryManager = new ArchiveDirManagerProxy(serverName, projectProperties, projectName, viewName, userName, serverPassword, appendedPath); } if (directoryManager != null) { directoryManagerMap.put(keyValue, directoryManager); } } else { LOGGER.log(Level.FINE, "Re-using existing directory manager for " + keyValue); } return directoryManager; } /** * Get the project properties. * @param serverName the server name. * @param projectName the project name. * @param viewName the view name. * @param projectType the project type. * @return the project's project properties. * @throws QVCSException if we cannot find or manufacture the project properties using the given parameters. */ public synchronized AbstractProjectProperties getProjectProperties(String serverName, String projectName, String viewName, String projectType) throws QVCSException { String propertiesKey = getPropertiesViewKey(serverName, projectName, viewName, projectType); AbstractProjectProperties projectProperties = projectPropertiesMap.get(propertiesKey); if (projectProperties == null) { // There is no project properties for this project yet. // We'll need to make one. projectProperties = ProjectPropertiesFactory.getProjectPropertiesFactory().buildProjectProperties(projectName, projectType); if (projectProperties == null) { throw new QVCSException("Failed to build " + projectType + " project properties for project: " + projectName); } projectPropertiesMap.put(propertiesKey, projectProperties); } return projectProperties; } /** * Remove a directory manager. Removes the directory manager associated with the given parameters from the cache that the factory maintains. * @param serverName the server name. * @param projectName the project name. * @param viewName the view name. * @param projectType the type of project. * @param appendedPath the appended path. */ public synchronized void removeDirectoryManager(String serverName, String projectName, String viewName, String projectType, String appendedPath) { String propertiesKey = getPropertiesViewKey(serverName, projectName, viewName, projectType); AbstractProjectProperties projectProperties = projectPropertiesMap.get(propertiesKey); if (projectProperties != null) { String keyValue = getProjectViewKey(serverName, projectName, viewName, projectProperties, appendedPath); LOGGER.log(Level.FINE, "ArchiveDirManagerFactory.removeDirectoryManager: removing directory manager for: " + keyValue); directoryManagerMap.remove(keyValue); if (appendedPath.length() == 0) { serverPasswordsMap.remove(serverName); serverUsersMap.remove(serverName); } } } /** * Set the password to use for the given server. * @param serverName the server name. * @param password the password. */ public void setServerPassword(String serverName, String password) { serverPasswordsMap.put(serverName, password); } /** * Set the user name associated with the given server name. * @param serverName the server name. * @param username the user name to associate with that server. */ public void setServerUsername(String serverName, String username) { serverUsersMap.put(serverName, username); } private String getPropertiesViewKey(String serverName, String projectName, String viewName, String projectType) { String keyValue = serverName + "." + projectType + "." + projectName + "." + viewName; if (0 == projectType.compareTo((QVCSConstants.QVCS_SERVED_PROJECT_TYPE))) { keyValue = projectType + "." + projectName + "." + viewName; } return keyValue; } private String getProjectViewKey(String serverName, String projectName, String viewName, AbstractProjectProperties projectProperties, String appendedPath) { // Make this a standard appended path... String standardAppendedPath = Utility.convertToStandardPath(appendedPath); if (projectProperties.getIgnoreCaseFlag()) { standardAppendedPath = standardAppendedPath.toLowerCase(); } String keyValue = serverName + ":" + projectName + ":" + viewName + "//" + projectProperties.getProjectType() + ":" + standardAppendedPath; if (0 == projectProperties.getProjectType().compareTo(QVCSConstants.QVCS_SERVED_PROJECT_TYPE)) { // If we're running on the server, the key value must not include the server name, since it may vary. // NOTE: IF THIS CHANGES, YOU HAVE TO CHANGE CODE IN ViewManager.removeView() SINCE THAT // CODE ASSUMES THAT A BLANK SERVERNAME WILL WORK WHEN RUNNING ON THE SERVER. keyValue = projectName + ":" + viewName + "//" + projectProperties.getProjectType() + ":" + standardAppendedPath; } return keyValue; } }