1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-04 23:55:26 +02:00

[392012] [dstore] make server safer for delete operations

This commit is contained in:
David McKnight 2012-10-16 20:11:56 +00:00
parent 1062b05a6a
commit 4b0b3fbd1b
3 changed files with 139 additions and 93 deletions

View file

@ -45,6 +45,7 @@
* David McKnight (IBM) - [371401] [dstore][multithread] avoid use of static variables - causes memory leak after disconnect
* Noriaki Takatsu (IBM) - [380562] [multithread][dstore] File Search is not canceled by the client UI on disconnect
* David McKnight (IBM) - [390037] [dstore] Duplicated items in the System view
* David McKnight (IBM) - [392012] [dstore] make server safer for delete operations
*******************************************************************************/
package org.eclipse.rse.dstore.universal.miners;
@ -53,6 +54,7 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@ -462,6 +464,7 @@ public class UniversalFileSystemMiner extends Miner {
public void updateCancellableThreads(DataElement command, ICancellableHandler thread)
{
//First Check to make sure that there are no "zombie" threads
List threadsToRemove = new ArrayList();
Iterator iter = _cancellableThreads.keySet().iterator();
try
{
@ -472,7 +475,12 @@ public class UniversalFileSystemMiner extends Miner {
if ((theThread == null) ||
theThread.isDone() || theThread.isCancelled())
{
_cancellableThreads.remove(threadElement);
threadsToRemove.add(threadElement);
}
}
if (!threadsToRemove.isEmpty()){
for (int i = 0; i < threadsToRemove.size(); i++){
_cancellableThreads.remove(threadsToRemove.get(i));
}
}
}
@ -485,7 +493,7 @@ public class UniversalFileSystemMiner extends Miner {
_cancellableThreads.put(command, thread);
}
}
/**
* Method to list the files for a given filter.
@ -645,10 +653,24 @@ public class UniversalFileSystemMiner extends Miner {
* Method to Delete a file or folder.
*/
public DataElement handleDelete(DataElement subject, DataElement status, boolean refreshDataStore) {
DeleteThread deleteThread = new DeleteThread(subject, this, _dataStore, false, status);
deleteThread.start();
// first make sure this is a valid object to delete
String type = subject.getType();
if (IUniversalDataStoreConstants.UNIVERSAL_FOLDER_DESCRIPTOR.equals(type) ||
IUniversalDataStoreConstants.UNIVERSAL_FILE_DESCRIPTOR.equals(type) ||
IUniversalDataStoreConstants.UNIVERSAL_ARCHIVE_FILE_DESCRIPTOR.equals(type) ||
IUniversalDataStoreConstants.UNIVERSAL_VIRTUAL_FILE_DESCRIPTOR.equals(type) ||
IUniversalDataStoreConstants.UNIVERSAL_VIRTUAL_FOLDER_DESCRIPTOR.equals(type) ||
IUniversalDataStoreConstants.UNIVERSAL_FILTER_DESCRIPTOR.equals(type)){
DeleteThread deleteThread = new DeleteThread(subject, this, _dataStore, false, status);
deleteThread.start();
updateCancellableThreads(status.getParent(), deleteThread);
updateCancellableThreads(status.getParent(), deleteThread);
}
else {
UniversalServerUtilities.logWarning(getName(), "illegal deletion type: " + type, _dataStore); //$NON-NLS-1$
statusCancelled(status);
}
return status;
}
@ -659,9 +681,9 @@ public class UniversalFileSystemMiner extends Miner {
deleteThread.start();
updateCancellableThreads(status.getParent(), deleteThread);
return status;
}
/**
* Method to Rename a file or folder.

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2007, 2011 IBM Corporation and others.
* Copyright (c) 2007, 2012 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
@ -16,6 +16,7 @@
* David McKnight (IBM) - [264607] Unable to delete a broken symlink
* David McKnight (IBM) - [321026][dstore] Broken symbolic link can't be removed
* David McKnight (IBM) - [342450][dstore] Real files should not be deleted when deleting a symbolic link
* David McKnight (IBM) - [392012] [dstore] make server safer for delete operations
*******************************************************************************/
package org.eclipse.rse.internal.dstore.universal.miners.filesystem;
@ -119,97 +120,107 @@ public class DeleteThread extends SecuredThread implements ICancellableHandler {
}
private DataElement handleDelete(DataElement subject, DataElement thisStatus) throws SystemMessageException
{
String type = subject.getType();
if (type.equals(IUniversalDataStoreConstants.UNIVERSAL_VIRTUAL_FILE_DESCRIPTOR)
|| type.equals(IUniversalDataStoreConstants.UNIVERSAL_VIRTUAL_FOLDER_DESCRIPTOR)) {
return handleDeleteFromArchive(subject, thisStatus);
}
File deleteObj = new File(subject.getAttribute(DE.A_VALUE)
+ File.separatorChar + subject.getName());
DataElement deObj = null;
String attributes = subject.getSource();
String classification = "file"; //$NON-NLS-1$
String[] str = attributes.split("\\"+IServiceConstants.TOKEN_SEPARATOR); //$NON-NLS-1$
if (str.length > 11){ // 11 is classification index
classification = str[11];
}
boolean exists = deleteObj.exists();
if (!exists){
// special case for broken symbolic link
if (classification.startsWith("broken symbolic link")){ //$NON-NLS-1$
exists = true;
else if (IUniversalDataStoreConstants.UNIVERSAL_FOLDER_DESCRIPTOR.equals(type) ||
IUniversalDataStoreConstants.UNIVERSAL_FILE_DESCRIPTOR.equals(type) ||
IUniversalDataStoreConstants.UNIVERSAL_ARCHIVE_FILE_DESCRIPTOR.equals(type) ||
IUniversalDataStoreConstants.UNIVERSAL_FILTER_DESCRIPTOR.equals(type)){
String path = subject.getAttribute(DE.A_VALUE)+ File.separatorChar + subject.getName();
if (path.equals(""+File.separatorChar)){ // no path provided //$NON-NLS-1$
return _miner.statusCancelled(_status);
}
}
if (!exists) {
thisStatus.setAttribute(DE.A_SOURCE, IServiceConstants.FAILED_WITH_DOES_NOT_EXIST + "|" + deleteObj.getAbsolutePath()); //$NON-NLS-1$
UniversalServerUtilities.logError(CLASSNAME,
"The object to delete does not exist", null, _dataStore); //$NON-NLS-1$
} else {
try {
if (classification != null && classification.startsWith("symbolic link")){ //$NON-NLS-1$
// only delete the link - no the actual file or folder contents
deleteObj.delete();
File deleteObj = new File(path);
DataElement deObj = null;
String attributes = subject.getSource();
String classification = "file"; //$NON-NLS-1$
String[] str = attributes.split("\\"+IServiceConstants.TOKEN_SEPARATOR); //$NON-NLS-1$
if (str.length > 11){ // 11 is classification index
classification = str[11];
}
boolean exists = deleteObj.exists();
if (!exists){
// special case for broken symbolic link
if (classification.startsWith("broken symbolic link")){ //$NON-NLS-1$
exists = true;
}
else if (deleteObj.isFile()) {
if (deleteObj.delete() == false) {
thisStatus.setAttribute(DE.A_SOURCE, IServiceConstants.FAILED + "|" + deleteObj.getAbsolutePath()); //$NON-NLS-1$
} else {
// delete was successful and delete the object from the
// datastore
deObj = _dataStore.find(subject, DE.A_NAME, subject
.getName(), 1);
_dataStore.deleteObject(subject, deObj);
thisStatus.setAttribute(DE.A_SOURCE, IServiceConstants.SUCCESS + "|" + deleteObj.getAbsolutePath()); //$NON-NLS-1$
}
_dataStore.refresh(subject);
} else if (deleteObj.isDirectory()) { // it is directory and
// need to delete the
// entire directory +
// children
deleteDir(deleteObj, thisStatus);
if (deleteObj.delete() == false) {
thisStatus.setAttribute(DE.A_SOURCE, IServiceConstants.FAILED + "|" + deleteObj.getAbsolutePath()); //$NON-NLS-1$
UniversalServerUtilities.logError(CLASSNAME,
"Deletion of dir fialed", null, _dataStore); //$NON-NLS-1$
} else {
_dataStore.deleteObjects(subject);
DataElement parent = subject.getParent();
_dataStore.deleteObject(parent, subject);
_dataStore.refresh(parent);
thisStatus.setAttribute(DE.A_SOURCE, IServiceConstants.SUCCESS + "|" + deleteObj.getAbsolutePath()); //$NON-NLS-1$
}
} else {
// try to treat this as a file
if (deleteObj.delete() == false) {
thisStatus.setAttribute(DE.A_SOURCE, IServiceConstants.FAILED + "|" + deleteObj.getAbsolutePath()); //$NON-NLS-1$
UniversalServerUtilities
.logError(
CLASSNAME,
"The object to delete is neither a File or Folder! in handleDelete", //$NON-NLS-1$
null, _dataStore);
} else {
// delete was successful and delete the object from the
// datastore
deObj = _dataStore.find(subject, DE.A_NAME, subject
.getName(), 1);
_dataStore.deleteObject(subject, deObj);
thisStatus.setAttribute(DE.A_SOURCE, IServiceConstants.SUCCESS + "|" + deleteObj.getAbsolutePath()); //$NON-NLS-1$
}
_dataStore.refresh(subject);
}
} catch (Exception e) {
thisStatus.setAttribute(DE.A_SOURCE, IServiceConstants.FAILED_WITH_EXCEPTION + "|" + deleteObj.getAbsolutePath()); //$NON-NLS-1$
thisStatus.setAttribute(DE.A_VALUE, e.getLocalizedMessage());
}
if (!exists) {
thisStatus.setAttribute(DE.A_SOURCE, IServiceConstants.FAILED_WITH_DOES_NOT_EXIST + "|" + deleteObj.getAbsolutePath()); //$NON-NLS-1$
UniversalServerUtilities.logError(CLASSNAME,
"Delete of the object failed", e, _dataStore); //$NON-NLS-1$
"The object to delete does not exist", null, _dataStore); //$NON-NLS-1$
} else {
try {
if (classification != null && classification.startsWith("symbolic link")){ //$NON-NLS-1$
// only delete the link - no the actual file or folder contents
deleteObj.delete();
}
else if (deleteObj.isFile()) {
if (deleteObj.delete() == false) {
thisStatus.setAttribute(DE.A_SOURCE, IServiceConstants.FAILED + "|" + deleteObj.getAbsolutePath()); //$NON-NLS-1$
} else {
// delete was successful and delete the object from the
// datastore
deObj = _dataStore.find(subject, DE.A_NAME, subject
.getName(), 1);
_dataStore.deleteObject(subject, deObj);
thisStatus.setAttribute(DE.A_SOURCE, IServiceConstants.SUCCESS + "|" + deleteObj.getAbsolutePath()); //$NON-NLS-1$
}
_dataStore.refresh(subject);
} else if (deleteObj.isDirectory()) { // it is directory and
// need to delete the
// entire directory +
// children
deleteDir(deleteObj, thisStatus);
if (deleteObj.delete() == false) {
thisStatus.setAttribute(DE.A_SOURCE, IServiceConstants.FAILED + "|" + deleteObj.getAbsolutePath()); //$NON-NLS-1$
UniversalServerUtilities.logError(CLASSNAME,
"Deletion of dir fialed", null, _dataStore); //$NON-NLS-1$
} else {
_dataStore.deleteObjects(subject);
DataElement parent = subject.getParent();
_dataStore.deleteObject(parent, subject);
_dataStore.refresh(parent);
thisStatus.setAttribute(DE.A_SOURCE, IServiceConstants.SUCCESS + "|" + deleteObj.getAbsolutePath()); //$NON-NLS-1$
}
} else {
// try to treat this as a file
if (deleteObj.delete() == false) {
thisStatus.setAttribute(DE.A_SOURCE, IServiceConstants.FAILED + "|" + deleteObj.getAbsolutePath()); //$NON-NLS-1$
UniversalServerUtilities
.logError(
CLASSNAME,
"The object to delete is neither a File or Folder! in handleDelete", //$NON-NLS-1$
null, _dataStore);
} else {
// delete was successful and delete the object from the
// datastore
deObj = _dataStore.find(subject, DE.A_NAME, subject
.getName(), 1);
_dataStore.deleteObject(subject, deObj);
thisStatus.setAttribute(DE.A_SOURCE, IServiceConstants.SUCCESS + "|" + deleteObj.getAbsolutePath()); //$NON-NLS-1$
}
_dataStore.refresh(subject);
}
} catch (Exception e) {
thisStatus.setAttribute(DE.A_SOURCE, IServiceConstants.FAILED_WITH_EXCEPTION + "|" + deleteObj.getAbsolutePath()); //$NON-NLS-1$
thisStatus.setAttribute(DE.A_VALUE, e.getLocalizedMessage());
UniversalServerUtilities.logError(CLASSNAME,
"Delete of the object failed", e, _dataStore); //$NON-NLS-1$
}
}
_dataStore.refresh(subject);
}
else {
_dataStore.trace("attempt to delete "+subject + " prevented"); //$NON-NLS-1$//$NON-NLS-2$
}
_dataStore.refresh(subject);
return _miner.statusDone(_status);
}
@ -254,7 +265,7 @@ public class DeleteThread extends SecuredThread implements ICancellableHandler {
public void deleteDir(File fileObj, DataElement status) {
try {
File list[] = fileObj.listFiles();
for (int i = 0; i < list.length; ++i) {
for (int i = 0; i < list.length && !_isCancelled; ++i) {
if (list[i].isFile()) {
if (!(list[i].delete())) {
status.setAttribute(DE.A_SOURCE, IServiceConstants.FAILED);

View file

@ -1524,7 +1524,12 @@ public class DStoreFileService extends AbstractDStoreService implements IFileSer
public void delete(String remoteParent, String fileName, IProgressMonitor monitor) throws SystemMessageException
{
String remotePath = remoteParent + getSeparator(remoteParent) + fileName;
DataElement de = getElementFor(remotePath);
// always get a fresh element for deletions (spiriting could cause issues on server-side)
DataElement universaltemp = getMinerElement();
String normalizedPath = PathUtility.normalizeUnknown(remotePath);
DataElement de = universaltemp.getDataStore().createObject(universaltemp, IUniversalDataStoreConstants.UNIVERSAL_FILTER_DESCRIPTOR, normalizedPath, normalizedPath, "", false); //$NON-NLS-1$
// if we don't have a proper element, we won't have a command descriptor
if (de.getType().equals(IUniversalDataStoreConstants.UNIVERSAL_FILTER_DESCRIPTOR)){
// need to fetch
@ -1568,12 +1573,16 @@ public class DStoreFileService extends AbstractDStoreService implements IFileSer
delete(remoteParents[0], fileNames[0], monitor);
return;
}
DataElement universaltemp = getMinerElement();
ArrayList dataElements = new ArrayList(remoteParents.length);
for (int i = 0; i < remoteParents.length; i++)
{
String remotePath = remoteParents[i] + getSeparator(remoteParents[i]) + fileNames[i];
DataElement de = getElementFor(remotePath);
// always get a fresh element for deletions (spiriting could cause issues on server-side)
String normalizedPath = PathUtility.normalizeUnknown(remotePath);
DataElement de = universaltemp.getDataStore().createObject(universaltemp, IUniversalDataStoreConstants.UNIVERSAL_FILTER_DESCRIPTOR, normalizedPath, normalizedPath, "", false); //$NON-NLS-1$
// if we don't have a proper element, we won't have a command descriptor
if (de.getType().equals(IUniversalDataStoreConstants.UNIVERSAL_FILTER_DESCRIPTOR)){
// need to fetch
@ -1633,7 +1642,11 @@ public class DStoreFileService extends AbstractDStoreService implements IFileSer
newPath = remoteParent + getSeparator(remoteParent) + newName;
}
DataElement de = getElementFor(oldPath);
// always get a fresh element for renames (spiriting could cause issues on server-side)
DataElement universaltemp = getMinerElement();
String normalizedPath = PathUtility.normalizeUnknown(oldPath);
DataElement de = universaltemp.getDataStore().createObject(universaltemp, IUniversalDataStoreConstants.UNIVERSAL_FILTER_DESCRIPTOR, normalizedPath, normalizedPath, "", false); //$NON-NLS-1$
// if we don't have a proper element, we won't have a command descriptor
if (de.getType().equals(IUniversalDataStoreConstants.UNIVERSAL_FILTER_DESCRIPTOR)){
// need to fetch