diff --git a/rse/plugins/org.eclipse.rse.subsystems.files.core/src/org/eclipse/rse/subsystems/files/core/servicesubsystem/FileServiceSubSystem.java b/rse/plugins/org.eclipse.rse.subsystems.files.core/src/org/eclipse/rse/subsystems/files/core/servicesubsystem/FileServiceSubSystem.java index b4491e6f5b1..3068a3700c8 100644 --- a/rse/plugins/org.eclipse.rse.subsystems.files.core/src/org/eclipse/rse/subsystems/files/core/servicesubsystem/FileServiceSubSystem.java +++ b/rse/plugins/org.eclipse.rse.subsystems.files.core/src/org/eclipse/rse/subsystems/files/core/servicesubsystem/FileServiceSubSystem.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2010 IBM Corporation and others. + * Copyright (c) 2006, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -46,6 +46,7 @@ * David McKnight (IBM) - [272882] [api] Handle exceptions in IService.initService() * David McKnight (IBM) - [244041] [files] Renaming a file looses Encoding property * David McKnight (IBM) - [320713] [dstore] xml file transfer error on zOS + * David McKnight (IBM) - [368454] provide thread safety for cachedRemoteFiles hashmap *******************************************************************************/ package org.eclipse.rse.subsystems.files.core.servicesubsystem; @@ -1154,7 +1155,9 @@ public class FileServiceSubSystem extends RemoteFileSubSystem implements IFileSe IHost host = getHost(); IFileServiceSubSystemConfiguration config = (IFileServiceSubSystemConfiguration) newConfig; // file subsystem specific bits - _cachedRemoteFiles.clear(); + synchronized (_cachedRemoteFiles){ + _cachedRemoteFiles.clear(); + } _languageUtilityFactory = null; setFileService(config.getFileService(host)); setHostFileToRemoteFileAdapter(config.getHostFileAdapter()); diff --git a/rse/plugins/org.eclipse.rse.subsystems.files.core/src/org/eclipse/rse/subsystems/files/core/subsystems/RemoteFileSubSystem.java b/rse/plugins/org.eclipse.rse.subsystems.files.core/src/org/eclipse/rse/subsystems/files/core/subsystems/RemoteFileSubSystem.java index c8d253897d3..c1c6f566b7b 100644 --- a/rse/plugins/org.eclipse.rse.subsystems.files.core/src/org/eclipse/rse/subsystems/files/core/subsystems/RemoteFileSubSystem.java +++ b/rse/plugins/org.eclipse.rse.subsystems.files.core/src/org/eclipse/rse/subsystems/files/core/subsystems/RemoteFileSubSystem.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2002, 2009 IBM Corporation and others. + * Copyright (c) 2002, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -29,6 +29,7 @@ * Martin Oberhuber (Wind River) - [226574][api] Add ISubSystemConfiguration#supportsEncoding() * David McKnight (IBM) - [225747] [dstore] Trying to connect to an "Offline" system throws an NPE * David McKnight (IBM) - [272882] [api] Handle exceptions in IService.initService() + * David McKnight (IBM) - [368454] provide thread safety for cachedRemoteFiles hashmap *******************************************************************************/ package org.eclipse.rse.subsystems.files.core.subsystems; @@ -1271,35 +1272,43 @@ public abstract class RemoteFileSubSystem extends SubSystem implements IRemoteFi */ public void cacheRemoteFile(IRemoteFile file, String path) { - - if (_cachedRemoteFiles.containsKey(path)) - { - IRemoteFile oldFile = (IRemoteFile)_cachedRemoteFiles.remove(path); - if (oldFile == file) - { + boolean containsKey = false; + synchronized (_cachedRemoteFiles){ + containsKey = _cachedRemoteFiles.containsKey(path); + } + if (containsKey){ + IRemoteFile oldFile = null; + synchronized (_cachedRemoteFiles){ + oldFile = (IRemoteFile)_cachedRemoteFiles.remove(path); + } + if (oldFile == file){ // already cached - recache - _cachedRemoteFiles.put(path, file); + synchronized (_cachedRemoteFiles){ + _cachedRemoteFiles.put(path, file); + } return; } - + // replace file under parent if (oldFile instanceof RemoteFile) { RemoteFile roldFile = (RemoteFile)oldFile; - if (roldFile._parentFile != null) // prevent parent query from bug #196664 - { + if (roldFile._parentFile != null){ // prevent parent query from bug #196664 roldFile._parentFile.replaceContent(oldFile, file); } } else if (oldFile != null && oldFile.getParentRemoteFile() != null) { oldFile.getParentRemoteFile().replaceContent(oldFile, file); } - + // preserve persistent information from old file to new - if (oldFile != null) + if (oldFile != null){ oldFile.copyContentsTo(file); - + } + } + + synchronized (_cachedRemoteFiles){ + _cachedRemoteFiles.put(path, file); } - _cachedRemoteFiles.put(path, file); } /** @@ -1321,18 +1330,19 @@ public abstract class RemoteFileSubSystem extends SubSystem implements IRemoteFi */ public IRemoteFile getCachedRemoteFile(String path) { - if (_cachedRemoteFiles.size() > 0) - { - path = path.replaceAll("//", "/"); //$NON-NLS-1$ //$NON-NLS-2$ - if (path.endsWith("\\") || (path.endsWith("/") && path.length() > 1)) //$NON-NLS-1$ //$NON-NLS-2$ - { - path = path.substring(0, path.length() - 1); - } - if (_cachedRemoteFiles.containsKey(path)) - { - {return (IRemoteFile)_cachedRemoteFiles.get(path);} - } - + synchronized (_cachedRemoteFiles){ + if (_cachedRemoteFiles.size() > 0) + { + path = path.replaceAll("//", "/"); //$NON-NLS-1$ //$NON-NLS-2$ + if (path.endsWith("\\") || (path.endsWith("/") && path.length() > 1)) //$NON-NLS-1$ //$NON-NLS-2$ + { + path = path.substring(0, path.length() - 1); + } + if (_cachedRemoteFiles.containsKey(path)) + { + {return (IRemoteFile)_cachedRemoteFiles.get(path);} + } + } } return null; } @@ -1356,7 +1366,10 @@ public abstract class RemoteFileSubSystem extends SubSystem implements IRemoteFi //If getContents() is implemented correctly, no matches should be removed String prefix = file.getAbsolutePath() + file.getSeparator(); //Clone the hashMap in order to avoid ConcurrentModificationException in the iterator - HashMap tmpMap = (HashMap)_cachedRemoteFiles.clone(); + HashMap tmpMap = null; + synchronized (_cachedRemoteFiles){ + tmpMap = (HashMap)_cachedRemoteFiles.clone(); + } Iterator it = tmpMap.keySet().iterator(); while (it.hasNext()) { String remotePath = (String)it.next(); @@ -1367,13 +1380,15 @@ public abstract class RemoteFileSubSystem extends SubSystem implements IRemoteFi } } - _cachedRemoteFiles.remove(file.getAbsolutePath()); + removeCachedRemoteFile(file.getAbsolutePath()); } } protected void removeCachedRemoteFile(String path) { - _cachedRemoteFiles.remove(path); + synchronized (_cachedRemoteFiles){ + _cachedRemoteFiles.remove(path); + } } @@ -1382,7 +1397,9 @@ public abstract class RemoteFileSubSystem extends SubSystem implements IRemoteFi switch (e.getState()) { case CommunicationsEvent.AFTER_DISCONNECT : - _cachedRemoteFiles.clear(); + synchronized (_cachedRemoteFiles){ + _cachedRemoteFiles.clear(); + } // DKM - taking this out because it causes an exception when the event occurs in Modal Context //ISystemRegistry sr = RSECorePlugin.getTheSystemRegistry(); //sr.connectedStatusChange(this, false, true, true);