/* 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 com.qumasoft.qvcslib.notifications.ServerNotificationCheckIn; import com.qumasoft.qvcslib.notifications.ServerNotificationCheckOut; import com.qumasoft.qvcslib.notifications.ServerNotificationCreateArchive; import com.qumasoft.qvcslib.notifications.ServerNotificationHeaderChange; import com.qumasoft.qvcslib.notifications.ServerNotificationInterface; import com.qumasoft.qvcslib.notifications.ServerNotificationLock; import com.qumasoft.qvcslib.notifications.ServerNotificationMoveArchive; import com.qumasoft.qvcslib.notifications.ServerNotificationRemoveArchive; import com.qumasoft.qvcslib.notifications.ServerNotificationRenameArchive; import com.qumasoft.qvcslib.notifications.ServerNotificationSetRevisionDescription; import com.qumasoft.qvcslib.notifications.ServerNotificationUnlock; import com.qumasoft.qvcslib.requestdata.ClientRequestListClientProjectsData; import com.qumasoft.qvcslib.requestdata.ClientRequestListClientViewsData; import com.qumasoft.qvcslib.requestdata.ClientRequestLoginData; import com.qumasoft.qvcslib.response.ServerManagementInterface; import com.qumasoft.qvcslib.response.ServerResponseChangePassword; import com.qumasoft.qvcslib.response.ServerResponseCheckIn; import com.qumasoft.qvcslib.response.ServerResponseCheckOut; import com.qumasoft.qvcslib.response.ServerResponseCreateArchive; import com.qumasoft.qvcslib.response.ServerResponseError; import com.qumasoft.qvcslib.response.ServerResponseGetForVisualCompare; import com.qumasoft.qvcslib.response.ServerResponseGetInfoForMerge; import com.qumasoft.qvcslib.response.ServerResponseGetLogfileInfo; import com.qumasoft.qvcslib.response.ServerResponseGetMostRecentActivity; import com.qumasoft.qvcslib.response.ServerResponseGetRevision; import com.qumasoft.qvcslib.response.ServerResponseGetRevisionForCompare; import com.qumasoft.qvcslib.response.ServerResponseHeartBeat; import com.qumasoft.qvcslib.response.ServerResponseInterface; import com.qumasoft.qvcslib.response.ServerResponseLabel; import com.qumasoft.qvcslib.response.ServerResponseListFilesToPromote; import com.qumasoft.qvcslib.response.ServerResponseLock; import com.qumasoft.qvcslib.response.ServerResponseLogin; import com.qumasoft.qvcslib.response.ServerResponseMessage; import com.qumasoft.qvcslib.response.ServerResponseMoveFile; import com.qumasoft.qvcslib.response.ServerResponseProjectControl; import com.qumasoft.qvcslib.response.ServerResponsePromoteFile; import com.qumasoft.qvcslib.response.ServerResponseRegisterClientListener; import com.qumasoft.qvcslib.response.ServerResponseRenameArchive; import com.qumasoft.qvcslib.response.ServerResponseResolveConflictFromParentBranch; import com.qumasoft.qvcslib.response.ServerResponseSuccess; import com.qumasoft.qvcslib.response.ServerResponseTransactionBegin; import com.qumasoft.qvcslib.response.ServerResponseTransactionEnd; import com.qumasoft.qvcslib.response.ServerResponseUnLabel; import com.qumasoft.qvcslib.response.ServerResponseUnlock; import com.qumasoft.qvcslib.response.ServerResponseUpdateClient; import java.awt.Frame; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.EventListenerList; /** * Singleton transport proxy factory. Use this factory class to get instances of a transport proxy implementation for communication with server. * @author Jim Voris */ public final class TransportProxyFactory { private static int heartbeatThreadCounter = 0; // These are the kinds of proxies that we support. /** A raw socket proxy type. */ public static final TransportProxyType RAW_SOCKET_PROXY = new TransportProxyType("RawSocketProxy"); private static final TransportProxyFactory TRANSPORT_PROXY_FACTORY = new TransportProxyFactory(); private Map<String, TransportProxyInterface> transportProxyMap = null; private List<PasswordChangeListenerInterface> changedPasswordListenersList = null; private EventListenerList changeListenerArray = null; // Create our logger object private static final Logger LOGGER = Logger.getLogger("com.qumasoft.qvcslib"); private TransportProxyFactory() { transportProxyMap = Collections.synchronizedMap(new TreeMap<String, TransportProxyInterface>()); changedPasswordListenersList = Collections.synchronizedList(new ArrayList<PasswordChangeListenerInterface>()); changeListenerArray = new EventListenerList(); } /** * Get the factory singleton. * @return the factory singleton. */ public static TransportProxyFactory getInstance() { return TRANSPORT_PROXY_FACTORY; } /** * Add a change listener. * @param l the change listener. */ public synchronized void addChangeListener(ChangeListener l) { changeListenerArray.add(ChangeListener.class, l); } /** * Add a changed password listener. * @param listener the changed password listener. */ public void addChangedPasswordListener(PasswordChangeListenerInterface listener) { changedPasswordListenersList.add(listener); } /** * Remove a changed password listener. * @param listener the changed password listener to remove. */ public void removeChangedPasswordListener(PasswordChangeListenerInterface listener) { changedPasswordListenersList.remove(listener); } /** * Remove a change listener. * @param l the change listener to remove. */ public synchronized void removeChangeListener(ChangeListener l) { changeListenerArray.remove(ChangeListener.class, l); } /** * Lookup the transport proxy for this server. Return null if it does not exist * * @param serverProperties the server properties * @return the transport proxy to communicate with this server. */ public synchronized TransportProxyInterface getTransportProxy(ServerProperties serverProperties) { int port = serverProperties.getClientPort(); TransportProxyType transportType = serverProperties.getClientTransport(); String keyValue = makeKey(transportType, serverProperties, port); TransportProxyInterface transportProxy = transportProxyMap.get(keyValue); return transportProxy; } /** * Lookup the admin transport proxy for this server. Return null if it does not exist * * @param serverProperties the server properties * @return the transport proxy to communicate with this server. */ public synchronized TransportProxyInterface getAdminTransportProxy(ServerProperties serverProperties) { int port = serverProperties.getServerAdminPort(); TransportProxyType transportType = serverProperties.getServerAdminTransport(); String keyValue = makeKey(transportType, serverProperties, port); TransportProxyInterface transportProxy = transportProxyMap.get(keyValue); return transportProxy; } /** * Lookup or create a transport proxy for the given parameters. This method will send the login message to the server, but it does not wait for the login response. * @param transportType the type of transport. * @param serverProperties the server properties. * @param port the port number of the server. * @param userName the user name. * @param hashedPassword the hashed password. * @param listener the proxy listener. * @param visualCompareInterface the visual compare interface. * @return a transport proxy for the given parameters. */ public synchronized TransportProxyInterface getTransportProxy(TransportProxyType transportType, ServerProperties serverProperties, int port, String userName, byte[] hashedPassword, TransportProxyListenerInterface listener, VisualCompareInterface visualCompareInterface) { String keyValue = makeKey(transportType, serverProperties, port); TransportProxyInterface transportProxy = transportProxyMap.get(keyValue); if (transportProxy == null) { // There is no transportProxy for this server yet. // We'll need to make one. if (transportType == RAW_SOCKET_PROXY) { transportProxy = new RawSocketTransportProxy(serverProperties, listener, visualCompareInterface); if (transportProxy.open(port)) { transportProxyMap.put(keyValue, transportProxy); ReceiveThread receiveThread = new ReceiveThread(transportProxy, keyValue); receiveThread.setName("Receive thread " + keyValue); receiveThread.start(); login(userName, hashedPassword, transportProxy, serverProperties); } else { transportProxy = null; } } } else { LOGGER.log(Level.INFO, "Re-using transport proxy for server: [" + keyValue + "] transport type: [" + transportProxy.getTransportName() + "]"); } return transportProxy; } private String makeKey(TransportProxyType transportProxyType, ServerProperties serverProperties, int port) { String keyValue = transportProxyType.toString() + ":" + serverProperties.getServerName() + ":" + serverProperties.getServerIPAddress() + ":" + Integer.toString(port); return keyValue; } /** * Send a login request to the server. * @param userName the user name. * @param hashedPassword the hashed password. * @param transportProxy the transport proxy. * @param serverProperties the server properties. */ private static void login(String userName, byte[] hashedPassword, TransportProxyInterface transportProxy, ServerProperties serverProperties) { ClientRequestLoginData loginRequest = new ClientRequestLoginData(); loginRequest.setUserName(userName); loginRequest.setPassword(hashedPassword); loginRequest.setServerName(serverProperties.getServerName()); loginRequest.setVersion("3.0.9"); synchronized (transportProxy) { transportProxy.write(loginRequest); } } /** * Close all transports. */ public void closeAllTransports() { Set<String> transportKeys = transportProxyMap.keySet(); for (String key : transportKeys) { TransportProxyInterface transportProxy = transportProxyMap.get(key); transportProxy.removeAllListeners(); transportProxy.close(); } transportProxyMap.clear(); } /** * Notify listeners for a project control response. * @param response a project control response. */ public void notifyListeners(ServerResponseProjectControl response) { ChangeEvent event = new ChangeEvent(response); Object[] listeners = changeListenerArray.getListenerList(); for (int i = listeners.length - 2; i >= 0; i -= 2) { ((ChangeListener) listeners[i + 1]).stateChanged(event); } } /** * Notify listeners for a list files to promote response. * @param response a list files to promote response. */ public void notifyListeners(ServerResponseListFilesToPromote response) { ChangeEvent event = new ChangeEvent(response); Object[] listeners = changeListenerArray.getListenerList(); for (int i = listeners.length - 2; i >= 0; i -= 2) { ((ChangeListener) listeners[i + 1]).stateChanged(event); } } /** * Notify listeners for file promotion response. * @param response a file promotion response. */ public void notifyListeners(ServerResponsePromoteFile response) { ChangeEvent event = new ChangeEvent(response); Object[] listeners = changeListenerArray.getListenerList(); for (int i = listeners.length - 2; i >= 0; i -= 2) { ((ChangeListener) listeners[i + 1]).stateChanged(event); } } void notifyPasswordChangeListeners(ServerResponseChangePassword response) { for (PasswordChangeListenerInterface listener : changedPasswordListenersList) { listener.notifyPasswordChange(response); } } void notifyPasswordChangeListeners(ServerResponseLogin response) { for (PasswordChangeListenerInterface listener : changedPasswordListenersList) { listener.notifyLoginResult(response); } } void notifyPasswordChangeListeners(ServerResponseUpdateClient response) { for (PasswordChangeListenerInterface listener : changedPasswordListenersList) { listener.notifyUpdateComplete(); } } void notifyRecentActivityListeners(ServerResponseGetMostRecentActivity response) { ChangeEvent event = new ChangeEvent(response); Object[] listeners = changeListenerArray.getListenerList(); for (int i = listeners.length - 2; i >= 0; i -= 2) { ((ChangeListener) listeners[i + 1]).stateChanged(event); } } /** * Get the list of projects. * @param serverProperties the server properties. */ public void requestProjectList(ServerProperties serverProperties) { ClientRequestListClientProjectsData clientRequestListClientProjectsData = new ClientRequestListClientProjectsData(); clientRequestListClientProjectsData.setServerName(serverProperties.getServerName()); TransportProxyInterface transportProxy = getTransportProxy(serverProperties); if (transportProxy != null) { synchronized (transportProxy) { transportProxy.write(clientRequestListClientProjectsData); } } } /** * Request the list of views for the given project. * @param serverProperties the server properties. * @param projectName the project name. */ public void requestViewList(ServerProperties serverProperties, String projectName) { ClientRequestListClientViewsData clientRequestListClientViewsData = new ClientRequestListClientViewsData(); clientRequestListClientViewsData.setServerName(serverProperties.getServerName()); clientRequestListClientViewsData.setProjectName(projectName); TransportProxyInterface transportProxy = getTransportProxy(serverProperties); if (transportProxy != null) { synchronized (transportProxy) { transportProxy.write(clientRequestListClientViewsData); } } } class ReceiveThread extends java.lang.Thread { private final TransportProxyInterface localProxy; private final String keyValue; ReceiveThread(TransportProxyInterface transportProxy, String key) { localProxy = transportProxy; this.keyValue = key; setDaemon(true); } @Override public synchronized void run() { while (true) { if (localProxy == null) { /* * nothing to do */ try { wait(); } catch (InterruptedException e) { /* * should not happen */ continue; } } handleServerMessages(); // Something's happened to shut down our connection. if (localProxy != null) { transportProxyMap.remove(this.keyValue); localProxy.removeAllListeners(); ClientTransactionManager.getInstance().discardServerTransactions(localProxy); break; } } LOGGER.log(Level.FINE, "Receive thread exiting for [" + this.keyValue + "]"); } void handleServerMessages() { String connectedTo; connectedTo = "[" + localProxy.getServerProperties().getServerName() + "] at IP address [" + localProxy.getServerProperties().getServerIPAddress() + "] using [" + localProxy.getTransportName() + "]"; LOGGER.log(Level.FINE, "Waiting for messages from: [" + connectedTo + "]"); ResponseHandler responseHandler = new ResponseHandler(localProxy); try { synchronized (localProxy.getReadLock()) { while (true) { try { responseHandler.handleResponse(); } catch (QVCSRuntimeException e) { LOGGER.log(Level.FINE, "Breaking connection to: [" + connectedTo + "]"); break; } catch (RuntimeException e) { LOGGER.log(Level.INFO, "Breaking connection to: [" + connectedTo + "]"); LOGGER.log(Level.FINE, Utility.expandStackTraceToString(e)); break; } catch (Exception e) { LOGGER.log(Level.INFO, "Breaking connection to: [" + connectedTo + "]"); LOGGER.log(Level.FINE, Utility.expandStackTraceToString(e)); break; } catch (java.lang.OutOfMemoryError e) { LOGGER.log(Level.SEVERE, "Out of memory."); LOGGER.log(Level.WARNING, "Out of memory; breaking connection to: [", connectedTo + "]"); LOGGER.log(Level.WARNING, Utility.expandStackTraceToString(e)); break; } } } } catch (Exception e) { LOGGER.log(Level.INFO, "Breaking connection to: [" + connectedTo + "]"); LOGGER.log(Level.INFO, Utility.expandStackTraceToString(e)); } finally { try { localProxy.close(); } catch (Exception e) { LOGGER.log(Level.FINE, "Breaking connection to: [" + connectedTo + "]"); } } } } class ResponseHandler { private TransportProxyInterface responseProxy = null; // There needs to be a separate keyword manager for each separate // receive thread. private KeywordManagerInterface keywordManager = null; ResponseHandler(TransportProxyInterface transportProxy) { responseProxy = transportProxy; try { keywordManager = KeywordManagerFactory.getInstance().getKeywordManager(); } catch (Exception e) { LOGGER.log(Level.WARNING, Utility.expandStackTraceToString(e)); keywordManager = null; } } private boolean createWorkfileDirectory(File workfileFile) { boolean retVal = false; File parentFile = workfileFile.getParentFile(); if (parentFile != null) { if (!parentFile.exists()) { if (parentFile.mkdirs()) { retVal = true; } } else { retVal = true; } } return retVal; } private boolean canOverwriteWorkfile(ServerResponseGetRevision response, WorkFile workfileFile) { boolean retVal = false; if (workfileFile.exists()) { // Check to see if we should overwrite the file... if (workfileFile.canWrite()) { // The file is writable. See if we should overwrite it. if (response.getOverwriteBehavior() == Utility.OverwriteBehavior.REPLACE_WRITABLE_FILE) { retVal = workfileFile.delete(); } else if (response.getOverwriteBehavior() == Utility.OverwriteBehavior.ASK_BEFORE_OVERWRITE_OF_WRITABLE_FILE) { // We need to ask the user if we can overwrite the writable // workfile. if (response.getDirectoryLevelOperationFlag()) { retVal = false; LOGGER.log(Level.INFO, "Skipping get for [" + response.getClientWorkfileName() + "] because file is read/write."); } else { LOGGER.log(Level.WARNING, "Skipping get for [" + response.getClientWorkfileName() + "] because file is read/write."); retVal = false; } } else { assert (response.getOverwriteBehavior() == Utility.OverwriteBehavior.DO_NOT_REPLACE_WRITABLE_FILE); LOGGER.log(Level.INFO, "Skipping get for [" + response.getClientWorkfileName() + "] because file is read/write."); retVal = false; } } else { // The file is marked read-only... // Remove the existing workfile. if (workfileFile.setReadWrite()) { retVal = workfileFile.delete(); } } } else { // If the file doesn't exist, then we should be able to // write to the directory to create the file. retVal = true; } return retVal; } private boolean canOverwriteWorkfile(WorkFile workfileFile) { boolean retVal = false; if (workfileFile.exists()) { // Remove the existing workfile. if (workfileFile.setReadWrite()) { retVal = workfileFile.delete(); } } else { // If the file doesn't exist, then we should be able to // write to the directory to create the file. retVal = true; } return retVal; } /** * Dispatch response messages */ void handleResponse() { Object object = responseProxy.read(); if (object instanceof ServerNotificationInterface) { handleServerNotifications(object); } else if (object instanceof ServerManagementInterface) { ServerManager.getServerManager().handleServerManagement(object); } else if (object instanceof ServerResponseInterface) { ServerResponseInterface serverResponse = (ServerResponseInterface) object; ServerResponseInterface.ResponseOperationType responseType = serverResponse.getOperationType(); switch (responseType) { case SR_LOGIN: handleLoginResponse(object); break; case SR_REGISTER_CLIENT_LISTENER: handleRegisterClientListenerResponse(object); break; case SR_GET_REVISION: handleGetRevisionResponse(object); break; case SR_GET_REVISION_FOR_COMPARE: handleGetRevisionForCompareResponse(object); break; case SR_CHECK_OUT: handleCheckOutResponse(object); break; case SR_LOCK: handleLockResponse(object); break; case SR_UNLOCK: handleUnlockResponse(object); break; case SR_CHECK_IN: handleCheckInResponse(object); break; case SR_GET_FOR_VISUAL_COMPARE: handleGetForVisualCompareResponse(object); break; case SR_PROJECT_CONTROL: handleProjectControlResponse(object); break; case SR_LABEL: handleLabelResponse(object); break; case SR_REMOVE_LABEL: handleUnLabelResponse(object); break; case SR_GET_LOGFILE_INFO: handleGetLogfileInfoResponse(object); break; case SR_CHANGE_USER_PASSWORD: handleChangePasswordResponse(object); break; case SR_RESPONSE_SUCCESS: handleSuccessResponse(object); break; case SR_RESPONSE_ERROR: handleErrorResponse(object); break; case SR_CREATE_ARCHIVE: handleCreateArchiveResponse(object); break; case SR_MOVE_FILE: handleMoveFileResponse(object); break; case SR_RENAME_FILE: handleRenameArchiveResponse(object); break; case SR_BEGIN_TRANSACTION: handleTransactionBeginResponse(object); break; case SR_END_TRANSACTION: handleTransactionEndResponse(object); break; case SR_RESPONSE_MESSAGE: handleResponseMessage(object); break; case SR_HEARTBEAT: handleHeartBeatResponseMessage(object); break; case SR_UPDATE_CLIENT_JAR: handleUpdateClientResponseMessage(object); break; case SR_GET_INFO_FOR_MERGE: handleGetInfoForMerge(object); break; case SR_RESOLVE_CONFLICT_FROM_PARENT_BRANCH: handleResolveConflictFromParentBranch(object); break; case SR_LIST_FILES_TO_PROMOTE: handleListFilesToPromoteResponse(object); break; case SR_PROMOTE_FILE: handlePromoteFileResponse(object); break; case SR_GET_MOST_RECENT_ACTIVITY: handleGetMostRecentActivity(object); break; default: LOGGER.log(Level.WARNING, "read unknown or unexpected response object: " + object.getClass().toString()); break; } } else { if (object != null) { LOGGER.log(Level.WARNING, "read unknown or unexpected response object: " + object.getClass().toString()); } else { LOGGER.log(Level.FINE, "failed to read object from server.... server is probably shutting down."); throw new QVCSRuntimeException("Server is shutting down. Breaking connection"); } } } /** * Dispatch notification messages. */ void handleServerNotifications(Object object) { ServerNotificationInterface serverNotification = (ServerNotificationInterface) object; ServerNotificationInterface.NotificationType notificationType = serverNotification.getNotificationType(); switch (notificationType) { case SR_NOTIFY_CHECKIN: handleCheckInNotification(object); break; case SR_NOTIFY_CHECKOUT: handleCheckOutNotification(object); break; case SR_NOTIFY_CREATE: handleCreateArchiveNotification(object); break; case SR_NOTIFY_HEADER_CHANGE: handleHeaderChangeNotification(object); break; case SR_NOTIFY_LOCK: handleLockNotification(object); break; case SR_NOTIFY_SET_REV_DESCRIPTION: handleSetRevisionDescriptionNotification(object); break; case SR_NOTIFY_UNLOCK: handleUnlockNotification(object); break; case SR_NOTIFY_REMOVE: handleRemoveArchiveNotification(object); break; case SR_NOTIFY_RENAME: handleRenameArchiveNotification(object); break; case SR_NOTIFY_MOVEFILE: handleMoveArchiveNotification(object); break; default: LOGGER.log(Level.WARNING, "read unknown or unexpected notification object: " + object.getClass().toString()); break; } } void handleLoginResponse(Object object) { ServerResponseLogin response = (ServerResponseLogin) object; LOGGER.log(Level.FINE, "ServerResponseLogin for user [" + response.getUserName() + "]"); responseProxy.setIsLoggedInToServer(response.getLoginResult()); if (responseProxy.getIsLoggedInToServer()) { // Start the heartbeat thread. HeartbeatThread heartbeatThread = new HeartbeatThread(responseProxy); heartbeatThread.setName("Heart beat thread " + heartbeatThreadCounter++); responseProxy.setHeartBeatThread(heartbeatThread); heartbeatThread.start(); responseProxy.setUsername(response.getUserName()); notifyPasswordChangeListeners(response); LOGGER.log(Level.INFO, "User [" + response.getUserName() + "] is logged in to server: [" + response.getServerName() + "]"); } else { notifyPasswordChangeListeners(response); LOGGER.log(Level.INFO, "User [" + response.getUserName() + "] failed to log in to server: [" + response.getServerName() + "]"); responseProxy.close(); } } void handleHeartBeatResponseMessage(Object object) { ServerResponseHeartBeat response = (ServerResponseHeartBeat) object; LOGGER.log(Level.FINEST, "ServerResponseHeartBeat for server: " + response.getServerName()); } void handleRegisterClientListenerResponse(Object object) { ServerResponseRegisterClientListener response = (ServerResponseRegisterClientListener) object; LOGGER.log(Level.FINE, "read ServerResponseRegisterClientListener for directory [" + response.getAppendedPath() + "]"); ArchiveDirManagerProxy dirManagerProxy = (ArchiveDirManagerProxy) responseProxy.getDirectoryManager(response.getProjectName(), response.getViewName(), response.getAppendedPath()); response.updateDirManagerProxy(dirManagerProxy); } void handleGetRevisionResponse(Object object) { ServerResponseGetRevision response = (ServerResponseGetRevision) object; java.io.FileOutputStream outputStream = null; ArchiveDirManagerProxy dirManagerProxy = null; try { WorkFile workfile = new WorkFile(response.getClientWorkfileName()); // Figure out our directory manager. dirManagerProxy = (ArchiveDirManagerProxy) responseProxy.getDirectoryManager(response.getProjectName(), response.getViewName(), response.getAppendedPath()); if ((dirManagerProxy != null) && createWorkfileDirectory(workfile) && canOverwriteWorkfile(response, workfile)) { // Save this workfile in the keyword contracted cache. KeywordContractedWorkfileCache.getInstance().addContractedBuffer(response.getProjectName(), response.getAppendedPath(), response.getShortWorkfileName(), response.getRevisionString(), response.getBuffer()); // See if we have to worry about keyword expansion... if ((keywordManager != null) && response.getSkinnyLogfileInfo().getAttributes().getIsExpandKeywords()) { try { outputStream = new java.io.FileOutputStream(workfile); KeywordExpansionContext keywordExpansionContext = new KeywordExpansionContext(outputStream, workfile, response.getLogfileInfo(), response.getLogfileInfo().getRevisionInformation().getRevisionIndex(response.getRevisionString()), response.getLabelString(), dirManagerProxy.getAppendedPath(), dirManagerProxy.getProjectProperties()); keywordManager.expandKeywords(response.getBuffer(), keywordExpansionContext); } catch (QVCSException e) { LOGGER.log(Level.WARNING, Utility.expandStackTraceToString(e)); } finally { if (outputStream != null) { outputStream.close(); } } } else { try { outputStream = new java.io.FileOutputStream(workfile); Utility.writeDataToStream(response.getBuffer(), outputStream); } finally { if (outputStream != null) { outputStream.close(); } } } // Set the timestamp on the workfile. if (response.getTimestampBehavior() != Utility.TimestampBehavior.SET_TIMESTAMP_TO_NOW) { workfile.setLastModified(response.getTimestamp()); } // Mark the workfile read-only if we are supposed to if (response.getSkinnyLogfileInfo().getAttributes().getIsProtectWorkfile()) { workfile.setReadOnly(); } response.updateDirManagerProxy(dirManagerProxy); } else { // We need to put this outside of the preceding conditional so that we'll send a notifyAll // to the associated proxy object, even if we didn't do anything, since that thread is blocked // waiting for the notify. if (dirManagerProxy != null) { dirManagerProxy.notifyListeners(); } } } catch (java.io.IOException e) { LOGGER.log(Level.WARNING, Utility.expandStackTraceToString(e)); if (dirManagerProxy != null) { dirManagerProxy.notifyListeners(); } } } void handleCreateArchiveResponse(Object object) { ServerResponseCreateArchive response = (ServerResponseCreateArchive) object; LOGGER.log(Level.FINE, "read ServerResponseCreateArchive for directory " + response.getAppendedPath()); ArchiveDirManagerProxy dirManagerProxy = (ArchiveDirManagerProxy) responseProxy.getDirectoryManager(response.getProjectName(), response.getViewName(), response.getAppendedPath()); response.updateDirManagerProxy(dirManagerProxy); } void handleCheckOutResponse(Object object) { ServerResponseCheckOut response = (ServerResponseCheckOut) object; java.io.FileOutputStream outputStream = null; ArchiveDirManagerProxy dirManagerProxy = null; try { WorkFile workfile = new WorkFile(response.getClientWorkfileName()); // Figure out our proxy directory manager. dirManagerProxy = (ArchiveDirManagerProxy) responseProxy.getDirectoryManager(response.getProjectName(), response.getViewName(), response.getAppendedPath()); if ((dirManagerProxy != null) && createWorkfileDirectory(workfile) && canOverwriteWorkfile(workfile)) { // Save this workfile in the keyword contracted cache. KeywordContractedWorkfileCache.getInstance().addContractedBuffer(response.getProjectName(), response.getAppendedPath(), response.getShortWorkfileName(), response.getRevisionString(), response.getBuffer()); // See if we have to worry about keyword expansion... if ((keywordManager != null) && response.getSkinnyLogfileInfo().getAttributes().getIsExpandKeywords()) { try { outputStream = new java.io.FileOutputStream(workfile); KeywordExpansionContext keywordExpansionContext = new KeywordExpansionContext(outputStream, workfile, response.getLogfileInfo(), response.getLogfileInfo().getRevisionInformation().getRevisionIndex(response.getRevisionString()), response.getLabelString(), dirManagerProxy.getAppendedPath(), dirManagerProxy.getProjectProperties()); keywordManager.expandKeywords(response.getBuffer(), keywordExpansionContext); } catch (QVCSException e) { LOGGER.log(Level.WARNING, Utility.expandStackTraceToString(e)); } finally { if (outputStream != null) { outputStream.close(); } } } else { try { outputStream = new java.io.FileOutputStream(workfile); Utility.writeDataToStream(response.getBuffer(), outputStream); } finally { if (outputStream != null) { outputStream.close(); } } } response.updateDirManagerProxy(dirManagerProxy); } else { // We need to put this outside of the preceding conditional so that we'll send a notifyAll // to the associated proxy object, even if we didn't do anything, since that thread is blocked // waiting for the notify. if (dirManagerProxy != null) { dirManagerProxy.notifyListeners(); } } } catch (java.io.IOException e) { LOGGER.log(Level.WARNING, Utility.expandStackTraceToString(e)); if (dirManagerProxy != null) { dirManagerProxy.notifyListeners(); } } } void handleLabelResponse(Object object) { ServerResponseLabel response = (ServerResponseLabel) object; // Figure out our proxy directory manager. ArchiveDirManagerProxy dirManagerProxy = (ArchiveDirManagerProxy) responseProxy.getDirectoryManager(response.getProjectName(), response.getViewName(), response.getAppendedPath()); response.updateDirManagerProxy(dirManagerProxy); } void handleUnLabelResponse(Object object) { ServerResponseUnLabel response = (ServerResponseUnLabel) object; // Figure out our proxy directory manager. ArchiveDirManagerProxy dirManagerProxy = (ArchiveDirManagerProxy) responseProxy.getDirectoryManager(response.getProjectName(), response.getViewName(), response.getAppendedPath()); response.updateDirManagerProxy(dirManagerProxy); } void handleGetLogfileInfoResponse(Object object) { ServerResponseGetLogfileInfo response = (ServerResponseGetLogfileInfo) object; // Figure out our proxy directory manager. ArchiveDirManagerProxy dirManagerProxy = (ArchiveDirManagerProxy) responseProxy.getDirectoryManager(response.getProjectName(), response.getViewName(), response.getAppendedPath()); response.updateDirManagerProxy(dirManagerProxy); } void handleGetRevisionForCompareResponse(Object object) { ServerResponseGetRevisionForCompare response = (ServerResponseGetRevisionForCompare) object; // Figure out our proxy directory manager. ArchiveDirManagerProxy dirManagerProxy = (ArchiveDirManagerProxy) responseProxy.getDirectoryManager(response.getProjectName(), response.getViewName(), response.getAppendedPath()); response.updateDirManagerProxy(dirManagerProxy); } void handleLockResponse(Object object) { ServerResponseLock response = (ServerResponseLock) object; // Figure out our proxy directory manager. ArchiveDirManagerProxy dirManagerProxy = (ArchiveDirManagerProxy) responseProxy.getDirectoryManager(response.getProjectName(), response.getViewName(), response.getAppendedPath()); response.updateDirManagerProxy(dirManagerProxy); } void handleUnlockResponse(Object object) { ServerResponseUnlock response = (ServerResponseUnlock) object; try { WorkFile workfile = new WorkFile(response.getClientWorkfileName()); // Figure out our directory manager. ArchiveDirManagerProxy dirManagerProxy = (ArchiveDirManagerProxy) responseProxy.getDirectoryManager(response.getProjectName(), response.getViewName(), response.getAppendedPath()); if ((dirManagerProxy != null) && createWorkfileDirectory(workfile)) { if (response.getUndoCheckoutBehavior() == Utility.UndoCheckoutBehavior.DELETE_WORKFILE) { workfile.setReadWrite(); workfile.delete(); LOGGER.log(Level.INFO, "Undo checkout complete; deleted workfile: [" + workfile.getCanonicalPath() + "]"); } else { // Mark the workfile read-only if we are supposed to if (response.getSkinnyLogfileInfo().getAttributes().getIsProtectWorkfile()) { workfile.setReadOnly(); } } response.updateDirManagerProxy(dirManagerProxy); } else { // We need to put this outside of the preceding conditional so that we'll send a notifyAll // to the associated proxy object, even if we didn't do anything, since that thread is blocked // waiting for the notify. if (dirManagerProxy != null) { dirManagerProxy.notifyListeners(); } } } catch (IOException e) { LOGGER.log(Level.WARNING, Utility.expandStackTraceToString(e)); } } void handleCheckInResponse(Object object) { ServerResponseCheckIn response = (ServerResponseCheckIn) object; ArchiveDirManagerProxy directoryManagerProxy = (ArchiveDirManagerProxy) responseProxy.getDirectoryManager(response.getProjectName(), response.getViewName(), response.getAppendedPath()); // Update the LogfileInfo info for the ArchiveDirectoryManagerProxy directoryManagerProxy.updateArchiveInfo(response.getShortWorkfileName(), response.getSkinnyLogfileInfo()); LogFileProxy logFileProxy = (LogFileProxy) directoryManagerProxy.getArchiveInfo(response.getShortWorkfileName()); WorkFile workfile = new WorkFile(response.getClientWorkfileName()); byte[] buffer = KeywordContractedWorkfileCache.getInstance().getContractedBuffer(response.getIndex(), response.getNewRevisionString()); if ((buffer != null) && logFileProxy.getAttributes().getIsExpandKeywords() && (response.getAddedRevisionData() != null) && !response.getNoExpandKeywordsFlag()) { // See if we have to worry about keyword expansion... if (createWorkfileDirectory(workfile) && canOverwriteWorkfile(workfile)) { try (FileOutputStream outputStream = new FileOutputStream(workfile)) { KeywordExpansionContext keywordExpansionContext = new KeywordExpansionContext(outputStream, workfile, response.getLogfileInfo(), response.getAddedRevisionData().getNewRevisionIndex(), null, directoryManagerProxy.getAppendedPath(), directoryManagerProxy.getProjectProperties()); keywordManager.expandKeywords(buffer, keywordExpansionContext); } catch (QVCSException | IOException e) { LOGGER.log(Level.WARNING, Utility.expandStackTraceToString(e)); } } } if (logFileProxy.getAttributes().getIsDeleteWork()) { // The attributes say to delete the workfile.... do // that only if they are not keeping the file locked. if (!response.getKeepLockedFlag()) { workfile.delete(); } } else { // Make the workfile read-only if we are supposed to. if (!response.getKeepLockedFlag() && logFileProxy.getAttributes().getIsProtectWorkfile()) { workfile.setReadOnly(); } // Protect the workfile if the user asked us to. if (response.getProtectWorkfileFlag()) { workfile.setReadOnly(); } } response.updateDirManagerProxy(directoryManagerProxy); } void handleGetForVisualCompareResponse(Object object) { ServerResponseGetForVisualCompare response = (ServerResponseGetForVisualCompare) object; response.setVisualCompareInterface(responseProxy.getVisualCompareInterface()); java.io.FileOutputStream outputStream = null; ArchiveDirManagerProxy directoryManagerProxy = null; try { WorkFile workfile = new WorkFile(response.getClientOutputFileName()); java.io.File workFile = new java.io.File(response.getFullWorkfileName()); // Figure out our proxy directory manager. directoryManagerProxy = (ArchiveDirManagerProxy) responseProxy.getDirectoryManager(response.getProjectName(), response.getViewName(), response.getAppendedPath()); if ((directoryManagerProxy != null) && createWorkfileDirectory(workfile) && canOverwriteWorkfile(workfile)) { // Save this workfile in the keyword contracted cache. String shortWorkfileName = response.getFullWorkfileName().substring(1 + response.getFullWorkfileName().lastIndexOf(File.separatorChar)); KeywordContractedWorkfileCache.getInstance().addContractedBuffer(response.getProjectName(), response.getAppendedPath(), shortWorkfileName, response.getRevisionString(), response.getBuffer()); // See if we have to worry about keyword expansion... if ((keywordManager != null) && response.getLogfileInfo().getLogFileHeaderInfo().getLogFileHeader().attributes().getIsExpandKeywords()) { try { outputStream = new java.io.FileOutputStream(workfile); KeywordExpansionContext keywordExpansionContext = new KeywordExpansionContext(outputStream, workFile, response.getLogfileInfo(), response.getLogfileInfo().getRevisionInformation().getRevisionIndex(response.getRevisionString()), null, directoryManagerProxy.getAppendedPath(), directoryManagerProxy.getProjectProperties()); keywordManager.expandKeywords(response.getBuffer(), keywordExpansionContext); } catch (QVCSException e) { LOGGER.log(Level.WARNING, Utility.expandStackTraceToString(e)); } finally { if (outputStream != null) { outputStream.close(); } } } else { try { outputStream = new java.io.FileOutputStream(workfile); Utility.writeDataToStream(response.getBuffer(), outputStream); } finally { if (outputStream != null) { outputStream.close(); } } } response.updateDirManagerProxy(directoryManagerProxy); } else { // We need to put this outside of the preceding conditional so that we'll send a notifyAll // to the associated proxy object, even if we didn't do anything, since that thread is blocked // waiting for the notify. if (directoryManagerProxy != null) { directoryManagerProxy.notifyListeners(); } } } catch (java.io.IOException e) { LOGGER.log(Level.WARNING, Utility.expandStackTraceToString(e)); if (directoryManagerProxy != null) { directoryManagerProxy.notifyListeners(); } } } private void handleMoveFileResponse(Object object) { ServerResponseMoveFile response = (ServerResponseMoveFile) object; // With a move response, there is no guarantee that the required directory managers already exist... // So we have to make sure that they do so that we can move the workfile (at least). try { UserLocationProperties userLocationProperties = new UserLocationProperties(System.getProperty("user.dir"), responseProxy.getUsername()); String workfileBaseDirectory = userLocationProperties.getWorkfileLocation(responseProxy.getServerProperties().getServerName(), response.getProjectName(), response.getViewName()); String originWorkfileDirectory; String destinationWorkfileDirectory; if (response.getOriginAppendedPath().length() > 0) { originWorkfileDirectory = workfileBaseDirectory + File.separator + response.getOriginAppendedPath(); } else { originWorkfileDirectory = workfileBaseDirectory; } if (response.getDestinationAppendedPath().length() > 0) { destinationWorkfileDirectory = workfileBaseDirectory + File.separator + response.getDestinationAppendedPath(); } else { destinationWorkfileDirectory = workfileBaseDirectory; } RemoteProjectProperties remoteProjectProperties = new RemoteProjectProperties(response.getProjectName(), response.getProjectProperties()); DirectoryCoordinate originDirectoryCoordinate = new DirectoryCoordinate(response.getProjectName(), response.getViewName(), response.getOriginAppendedPath()); DirectoryManagerInterface originDirectoryManager = DirectoryManagerFactory.getInstance().getDirectoryManager(responseProxy.getServerProperties().getServerName(), originDirectoryCoordinate, QVCSConstants.QVCS_REMOTE_PROJECT_TYPE, remoteProjectProperties, originWorkfileDirectory, null, false); DirectoryCoordinate destinationDirectoryCoordinate = new DirectoryCoordinate(response.getProjectName(), response.getViewName(), response.getDestinationAppendedPath()); DirectoryManagerInterface destinationDirectoryManager = DirectoryManagerFactory.getInstance().getDirectoryManager(responseProxy.getServerProperties().getServerName(), destinationDirectoryCoordinate, QVCSConstants.QVCS_REMOTE_PROJECT_TYPE, remoteProjectProperties, destinationWorkfileDirectory, null, false); ArchiveDirManagerProxy originDirectoryManagerProxy = (ArchiveDirManagerProxy) originDirectoryManager.getArchiveDirManager(); ArchiveDirManagerProxy destinationDirectoryManagerProxy = (ArchiveDirManagerProxy) destinationDirectoryManager.getArchiveDirManager(); if ((originDirectoryManagerProxy != null) && (destinationDirectoryManagerProxy != null)) { // Remove the archive info from the origin directory... // (This should already have been done by the notify). originDirectoryManagerProxy.removeArchiveInfo(response.getShortWorkfileName()); // Add the archive info to the destination directory... // (This should already have been done by the notify). destinationDirectoryManagerProxy.updateArchiveInfo(response.getShortWorkfileName(), response.getSkinnyLogfileInfo()); // Move the workfile from the origin director to the destination directory. // (This was NOT done by the notify). WorkFile.moveFile(originWorkfileDirectory, destinationWorkfileDirectory, response.getShortWorkfileName()); LOGGER.log(Level.INFO, "Move file response received for: [" + response.getShortWorkfileName() + "]"); // So we have a fresh notion of the workfiles that we have... originDirectoryManagerProxy.getDirectoryManager().getWorkfileDirectoryManager().refresh(); destinationDirectoryManagerProxy.getDirectoryManager().getWorkfileDirectoryManager().refresh(); originDirectoryManagerProxy.notifyListeners(); destinationDirectoryManagerProxy.notifyListeners(); } } catch (QVCSException e) { LOGGER.log(Level.WARNING, Utility.expandStackTraceToString(e)); } } void handleRenameArchiveResponse(Object object) { ServerResponseRenameArchive response = (ServerResponseRenameArchive) object; ArchiveDirManagerProxy directoryManagerProxy = (ArchiveDirManagerProxy) responseProxy.getDirectoryManager(response.getProjectName(), response.getViewName(), response.getAppendedPath()); if (directoryManagerProxy != null) { directoryManagerProxy.removeArchiveInfo(response.getOldShortWorkfileName()); directoryManagerProxy.updateArchiveInfo(response.getNewShortWorkfileName(), response.getSkinnyLogfileInfo()); String workfileDirectory = directoryManagerProxy.getDirectoryManager().getWorkfileDirectoryManager().getWorkfileDirectory(); WorkFile.renameFile(workfileDirectory, response.getOldShortWorkfileName(), response.getNewShortWorkfileName()); LOGGER.log(Level.INFO, "Rename response received for: [" + response.getOldShortWorkfileName() + "]"); // So we have a fresh notion of the workfiles that we have... directoryManagerProxy.getDirectoryManager().getWorkfileDirectoryManager().refresh(); directoryManagerProxy.notifyListeners(); } } void handleGetInfoForMerge(Object object) { ServerResponseGetInfoForMerge response = (ServerResponseGetInfoForMerge) object; ArchiveDirManagerProxy directoryManagerProxy = (ArchiveDirManagerProxy) responseProxy.getDirectoryManager(response.getProjectName(), response.getViewName(), response.getAppendedPath()); if (directoryManagerProxy != null) { response.updateDirManagerProxy(directoryManagerProxy); } } void handleResolveConflictFromParentBranch(Object object) { ServerResponseResolveConflictFromParentBranch response = (ServerResponseResolveConflictFromParentBranch) object; ArchiveDirManagerProxy directoryManagerProxy = (ArchiveDirManagerProxy) responseProxy.getDirectoryManager(response.getProjectName(), response.getBranchName(), response.getAppendedPath()); if (directoryManagerProxy != null) { response.updateDirManagerProxy(directoryManagerProxy); } } void handlePromoteFileResponse(Object object) { ServerResponsePromoteFile response = (ServerResponsePromoteFile) object; ArchiveDirManagerProxy directoryManagerProxy = (ArchiveDirManagerProxy) responseProxy.getDirectoryManager(response.getProjectName(), response.getBranchName(), response.getAppendedPath()); if (directoryManagerProxy != null) { response.updateDirManagerProxy(directoryManagerProxy); } notifyListeners(response); } void handleListFilesToPromoteResponse(Object object) { ServerResponseListFilesToPromote response = (ServerResponseListFilesToPromote) object; notifyListeners(response); } void handleProjectControlResponse(Object object) { ServerResponseProjectControl response = (ServerResponseProjectControl) object; notifyListeners(response); } void handleChangePasswordResponse(Object object) { ServerResponseChangePassword response = (ServerResponseChangePassword) object; notifyPasswordChangeListeners(response); } private void handleGetMostRecentActivity(Object object) { ServerResponseGetMostRecentActivity response = (ServerResponseGetMostRecentActivity) object; notifyRecentActivityListeners(response); } void handleSuccessResponse(Object object) { ServerResponseSuccess response = (ServerResponseSuccess) object; responseProxy.getProxyListener().notifyTransportProxyListener(response); } void handleErrorResponse(Object object) { ServerResponseError response = (ServerResponseError) object; if (response.getProjectName() != null) { ArchiveDirManagerProxy directoryManagerProxy = (ArchiveDirManagerProxy) responseProxy.getDirectoryManager(response.getProjectName(), response.getViewName(), response.getAppendedPath()); response.updateDirManagerProxy(directoryManagerProxy); } LOGGER.log(Level.WARNING, "Error message from server [Project][View][AppendedPath]: [" + response.getProjectName() + "][" + response.getViewName() + "][" + response.getAppendedPath() + "]: " + response.getErrorMessage()); } void handleResponseMessage(Object object) { ServerResponseMessage response = (ServerResponseMessage) object; ArchiveDirManagerProxy directoryManagerProxy = null; if (response.getProjectName() != null) { directoryManagerProxy = (ArchiveDirManagerProxy) responseProxy.getDirectoryManager(response.getProjectName(), response.getViewName(), response.getAppendedPath()); } if (directoryManagerProxy != null) { // Wake up any waiting threads. LogFileProxy logFileProxy = (LogFileProxy) directoryManagerProxy.getArchiveInfo(response.getShortWorkfileName()); if (logFileProxy != null) { synchronized (logFileProxy) { logFileProxy.notifyAll(); } } // Wake up any other threads that may be synchronized on the directory (like the ANT tasks) response.updateDirManagerProxy(directoryManagerProxy); } responseProxy.getProxyListener().notifyTransportProxyListener(response); } private void handleUpdateClientResponseMessage(Object object) { ServerResponseUpdateClient response = (ServerResponseUpdateClient) object; java.io.FileOutputStream outputStream = null; try { try { String clientFileName = response.getRequestedFileName() + ".new"; String homeDirectory = System.getProperty("user.dir"); clientFileName = homeDirectory + File.separator + clientFileName; outputStream = new java.io.FileOutputStream(clientFileName); outputStream.write(response.getBuffer()); LOGGER.log(Level.INFO, "Update received for: " + response.getRequestedFileName()); } finally { if (outputStream != null) { outputStream.close(); } } if (response.getRestartFlag()) { // Show the message on the Swing thread. Runnable later = new Runnable() { @Override public void run() { // Time to exit the application. JOptionPane.showMessageDialog(null, "Updates received. Please restart the application.", "Updates Complete", JOptionPane.PLAIN_MESSAGE); Frame[] frames = Frame.getFrames(); for (Frame frame : frames) { if (frame instanceof ExitAppInterface) { ExitAppInterface exitApp = (ExitAppInterface) frame; exitApp.exitTheApp(); } } } }; SwingUtilities.invokeLater(later); } } catch (IOException e) { LOGGER.log(Level.WARNING, Utility.expandStackTraceToString(e)); } } void handleTransactionBeginResponse(Object object) { ServerResponseTransactionBegin response = (ServerResponseTransactionBegin) object; ClientTransactionManager.getInstance().beginTransaction(responseProxy.getServerProperties().getServerName(), response.getTransactionID()); } void handleTransactionEndResponse(Object object) { ServerResponseTransactionEnd response = (ServerResponseTransactionEnd) object; ClientTransactionManager.getInstance().endTransaction(responseProxy.getServerProperties().getServerName(), response.getTransactionID()); } //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// // Handle notification messages. //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// void handleCheckInNotification(Object object) { ServerNotificationCheckIn response = (ServerNotificationCheckIn) object; ArchiveDirManagerProxy directoryManagerProxy = (ArchiveDirManagerProxy) responseProxy.getDirectoryManager(response.getProjectName(), response.getViewName(), response.getAppendedPath()); if (directoryManagerProxy != null) { // Update the skinny logfileInfo info for the ArchiveDirectoryManagerProxy directoryManagerProxy.updateArchiveInfo(response.getShortWorkfileName(), response.getSkinnyLogfileInfo()); LOGGER.log(Level.INFO, "CheckIn notification received for: [" + response.getProjectName() + "::" + response.getViewName() + "::[" + response.getAppendedPath() + "/" + response.getShortWorkfileName() + "]"); directoryManagerProxy.notifyListeners(); } } void handleCheckOutNotification(Object object) { ServerNotificationCheckOut response = (ServerNotificationCheckOut) object; ArchiveDirManagerProxy directoryManagerProxy = (ArchiveDirManagerProxy) responseProxy.getDirectoryManager(response.getProjectName(), response.getViewName(), response.getAppendedPath()); if (directoryManagerProxy != null) { // Update the skinny logfileInfo info for the ArchiveDirectoryManagerProxy directoryManagerProxy.updateArchiveInfo(response.getShortWorkfileName(), response.getSkinnyLogfileInfo()); LOGGER.log(Level.INFO, "CheckOut notification received for: [" + response.getProjectName() + "::" + response.getViewName() + "::[" + response.getAppendedPath() + "/" + response.getShortWorkfileName() + "]"); directoryManagerProxy.notifyListeners(); } } void handleHeaderChangeNotification(Object object) { ServerNotificationHeaderChange response = (ServerNotificationHeaderChange) object; ArchiveDirManagerProxy directoryManagerProxy = (ArchiveDirManagerProxy) responseProxy.getDirectoryManager(response.getProjectName(), response.getViewName(), response.getAppendedPath()); if (directoryManagerProxy != null) { // Update the skinny logfileInfo info for the ArchiveDirectoryManagerProxy directoryManagerProxy.updateArchiveInfo(response.getShortWorkfileName(), response.getSkinnyLogfileInfo()); LOGGER.log(Level.INFO, "Header change notification received for: [" + response.getProjectName() + "::" + response.getViewName() + "::[" + response.getAppendedPath() + "/" + response.getShortWorkfileName() + "]"); directoryManagerProxy.notifyListeners(); } } void handleLockNotification(Object object) { ServerNotificationLock response = (ServerNotificationLock) object; ArchiveDirManagerProxy directoryManagerProxy = (ArchiveDirManagerProxy) responseProxy.getDirectoryManager(response.getProjectName(), response.getViewName(), response.getAppendedPath()); if (directoryManagerProxy != null) { // Update the skinny logfileInfo info for the ArchiveDirectoryManagerProxy directoryManagerProxy.updateArchiveInfo(response.getShortWorkfileName(), response.getSkinnyLogfileInfo()); LOGGER.log(Level.INFO, "Lock notification received for: [" + response.getProjectName() + "::" + response.getViewName() + "::[" + response.getAppendedPath() + "/" + response.getShortWorkfileName() + "]"); directoryManagerProxy.notifyListeners(); } } void handleUnlockNotification(Object object) { ServerNotificationUnlock response = (ServerNotificationUnlock) object; ArchiveDirManagerProxy directoryManagerProxy = (ArchiveDirManagerProxy) responseProxy.getDirectoryManager(response.getProjectName(), response.getViewName(), response.getAppendedPath()); if (directoryManagerProxy != null) { // Update the skinny logfileInfo info for the ArchiveDirectoryManagerProxy directoryManagerProxy.updateArchiveInfo(response.getShortWorkfileName(), response.getSkinnyLogfileInfo()); LOGGER.log(Level.INFO, "UnLock notification received for: [" + response.getProjectName() + "::" + response.getViewName() + "::[" + response.getAppendedPath() + "/" + response.getShortWorkfileName() + "]"); directoryManagerProxy.notifyListeners(); } } void handleCreateArchiveNotification(Object object) { ServerNotificationCreateArchive response = (ServerNotificationCreateArchive) object; ArchiveDirManagerProxy directoryManagerProxy = (ArchiveDirManagerProxy) responseProxy.getDirectoryManager(response.getProjectName(), response.getViewName(), response.getAppendedPath()); if (directoryManagerProxy == null) { try { DirectoryCoordinate directoryCoordinate = new DirectoryCoordinate(response.getProjectName(), response.getViewName(), response.getAppendedPath()); DirectoryManagerInterface directoryManager = DirectoryManagerFactory.getInstance().getDirectoryManager(response.getServerName(), directoryCoordinate, QVCSConstants.QVCS_REMOTE_PROJECT_TYPE, null, null, null, false); directoryManagerProxy = (ArchiveDirManagerProxy) directoryManager.getArchiveDirManager(); } catch (QVCSException e) { LOGGER.log(Level.WARNING, "Not able to create directory manager!!" + e.getLocalizedMessage()); directoryManagerProxy = null; } } if (directoryManagerProxy != null) { directoryManagerProxy.updateArchiveInfo(response.getShortWorkfileName(), response.getSkinnyLogfileInfo()); LOGGER.log(Level.INFO, "Creation notification received for: [" + response.getProjectName() + "::" + response.getViewName() + "::[" + response.getAppendedPath() + "/" + response.getShortWorkfileName() + "]"); directoryManagerProxy.notifyListeners(); } } void handleRemoveArchiveNotification(Object object) { ServerNotificationRemoveArchive response = (ServerNotificationRemoveArchive) object; ArchiveDirManagerProxy directoryManagerProxy = (ArchiveDirManagerProxy) responseProxy.getDirectoryManager(response.getProjectName(), response.getViewName(), response.getAppendedPath()); if (directoryManagerProxy != null) { directoryManagerProxy.removeArchiveInfo(response.getShortWorkfileName()); LOGGER.log(Level.INFO, "Remove notification received for: [" + response.getProjectName() + "::" + response.getViewName() + "::[" + response.getAppendedPath() + "/" + response.getShortWorkfileName() + "]"); directoryManagerProxy.notifyListeners(); } } void handleRenameArchiveNotification(Object object) { ServerNotificationRenameArchive response = (ServerNotificationRenameArchive) object; ArchiveDirManagerProxy directoryManagerProxy = (ArchiveDirManagerProxy) responseProxy.getDirectoryManager(response.getProjectName(), response.getViewName(), response.getAppendedPath()); if (directoryManagerProxy != null) { directoryManagerProxy.removeArchiveInfo(response.getOldShortWorkfileName()); directoryManagerProxy.updateArchiveInfo(response.getNewShortWorkfileName(), response.getSkinnyLogfileInfo()); LOGGER.log(Level.INFO, "Rename notification received for: [" + response.getProjectName() + "::" + response.getViewName() + "::[" + response.getAppendedPath() + "/" + response.getOldShortWorkfileName() + "]"); // So we have a fresh notion of the workfiles that we have... directoryManagerProxy.getDirectoryManager().getWorkfileDirectoryManager().refresh(); directoryManagerProxy.notifyListeners(); } } void handleMoveArchiveNotification(Object object) { ServerNotificationMoveArchive response = (ServerNotificationMoveArchive) object; // With a move notification, there is no guarantee that the required directory managers already exist... // So we have to make sure that they do so that we can move the workfile (at least). try { UserLocationProperties userLocationProperties = new UserLocationProperties(System.getProperty("user.dir"), responseProxy.getUsername()); String workfileBaseDirectory = userLocationProperties.getWorkfileLocation(responseProxy.getServerProperties().getServerName(), response.getProjectName(), response.getViewName()); String originWorkfileDirectory; String destinationWorkfileDirectory; if (response.getOriginAppendedPath().length() > 0) { originWorkfileDirectory = workfileBaseDirectory + File.separator + response.getOriginAppendedPath(); } else { originWorkfileDirectory = workfileBaseDirectory; } if (response.getDestinationAppendedPath().length() > 0) { destinationWorkfileDirectory = workfileBaseDirectory + File.separator + response.getDestinationAppendedPath(); } else { destinationWorkfileDirectory = workfileBaseDirectory; } RemoteProjectProperties remoteProjectProperties = new RemoteProjectProperties(response.getProjectName(), response.getProjectProperties()); DirectoryCoordinate originDirectoryCoordinate = new DirectoryCoordinate(response.getProjectName(), response.getViewName(), response.getOriginAppendedPath()); DirectoryManagerInterface originDirectoryManager = DirectoryManagerFactory.getInstance().getDirectoryManager(responseProxy.getServerProperties().getServerName(), originDirectoryCoordinate, QVCSConstants.QVCS_REMOTE_PROJECT_TYPE, remoteProjectProperties, originWorkfileDirectory, null, false); DirectoryCoordinate destinationDirectoryCoordinate = new DirectoryCoordinate(response.getProjectName(), response.getViewName(), response.getDestinationAppendedPath()); DirectoryManagerInterface destinationDirectoryManager = DirectoryManagerFactory.getInstance().getDirectoryManager(responseProxy.getServerProperties().getServerName(), destinationDirectoryCoordinate, QVCSConstants.QVCS_REMOTE_PROJECT_TYPE, remoteProjectProperties, destinationWorkfileDirectory, null, false); ArchiveDirManagerProxy originDirectoryManagerProxy = (ArchiveDirManagerProxy) originDirectoryManager.getArchiveDirManager(); ArchiveDirManagerProxy destinationDirectoryManagerProxy = (ArchiveDirManagerProxy) destinationDirectoryManager.getArchiveDirManager(); if ((originDirectoryManagerProxy != null) && (destinationDirectoryManagerProxy != null)) { // Remove the archive info from the origin directory... originDirectoryManagerProxy.removeArchiveInfo(response.getShortWorkfileName()); // Add the archive info to the destination directory... destinationDirectoryManagerProxy.updateArchiveInfo(response.getShortWorkfileName(), response.getSkinnyLogfileInfo()); LOGGER.log(Level.INFO, "Move notification received for: [" + response.getProjectName() + "::" + response.getViewName() + "::[" + response.getOriginAppendedPath() + "/" + response.getShortWorkfileName() + "]"); // So we have a fresh notion of the workfiles that we have... originDirectoryManagerProxy.getDirectoryManager().getWorkfileDirectoryManager().refresh(); destinationDirectoryManagerProxy.getDirectoryManager().getWorkfileDirectoryManager().refresh(); originDirectoryManagerProxy.notifyListeners(); destinationDirectoryManagerProxy.notifyListeners(); } } catch (QVCSException e) { LOGGER.log(Level.WARNING, Utility.expandStackTraceToString(e)); } } void handleSetRevisionDescriptionNotification(Object object) { ServerNotificationSetRevisionDescription response = (ServerNotificationSetRevisionDescription) object; ArchiveDirManagerProxy directoryManagerProxy = (ArchiveDirManagerProxy) responseProxy.getDirectoryManager(response.getProjectName(), response.getViewName(), response.getAppendedPath()); if (directoryManagerProxy != null) { // Update the skinny logfileInfo info for the ArchiveDirectoryManagerProxy directoryManagerProxy.updateArchiveInfo(response.getShortWorkfileName(), response.getSkinnyLogfileInfo()); LOGGER.log(Level.INFO, "SetRevisionDescription notification received for: [" + response.getProjectName() + "::" + response.getViewName() + "::[" + response.getAppendedPath() + "/" + response.getShortWorkfileName() + "]"); directoryManagerProxy.notifyListeners(); } } } }