This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 268926
Collapse All | Expand All

(-)a/dlight.remote.impl/src/org/netbeans/modules/remote/impl/fs/RemoteFileSystem.java (-18 / +100 lines)
Lines 45-60 Link Here
45
import java.awt.Image;
45
import java.awt.Image;
46
import java.awt.event.WindowEvent;
46
import java.awt.event.WindowEvent;
47
import java.awt.event.WindowFocusListener;
47
import java.awt.event.WindowFocusListener;
48
import java.io.BufferedReader;
48
import java.io.ByteArrayInputStream;
49
import java.io.ByteArrayInputStream;
49
import java.io.ByteArrayOutputStream;
50
import java.io.ByteArrayOutputStream;
50
import java.io.File;
51
import java.io.File;
51
import java.io.FileInputStream;
52
import java.io.FileInputStream;
52
import java.io.FileNotFoundException;
53
import java.io.FileNotFoundException;
53
import java.io.FileOutputStream;
54
import java.io.FileOutputStream;
55
import java.io.FileReader;
54
import java.io.IOException;
56
import java.io.IOException;
55
import java.io.InterruptedIOException;
57
import java.io.InterruptedIOException;
56
import java.io.ObjectInputStream;
58
import java.io.ObjectInputStream;
57
import java.io.ObjectOutputStream;
59
import java.io.ObjectOutputStream;
60
import java.io.OutputStream;
61
import java.io.OutputStreamWriter;
62
import java.io.PrintWriter;
63
import java.io.UnsupportedEncodingException;
58
import java.lang.ref.WeakReference;
64
import java.lang.ref.WeakReference;
59
import java.net.ConnectException;
65
import java.net.ConnectException;
60
import java.util.*;
66
import java.util.*;
Lines 70-81 Link Here
70
import org.netbeans.modules.dlight.libs.common.PathUtilities;
76
import org.netbeans.modules.dlight.libs.common.PathUtilities;
71
import org.netbeans.modules.nativeexecution.api.ExecutionEnvironment;
77
import org.netbeans.modules.nativeexecution.api.ExecutionEnvironment;
72
import org.netbeans.modules.nativeexecution.api.HostInfo;
78
import org.netbeans.modules.nativeexecution.api.HostInfo;
79
import org.netbeans.modules.nativeexecution.api.NativeProcessBuilder;
73
import org.netbeans.modules.nativeexecution.api.util.CommonTasksSupport;
80
import org.netbeans.modules.nativeexecution.api.util.CommonTasksSupport;
74
import org.netbeans.modules.nativeexecution.api.util.ConnectionListener;
81
import org.netbeans.modules.nativeexecution.api.util.ConnectionListener;
75
import org.netbeans.modules.nativeexecution.api.util.ConnectionManager;
82
import org.netbeans.modules.nativeexecution.api.util.ConnectionManager;
76
import org.netbeans.modules.nativeexecution.api.util.ConnectionManager.CancellationException;
83
import org.netbeans.modules.nativeexecution.api.util.ConnectionManager.CancellationException;
77
import org.netbeans.modules.nativeexecution.api.util.FileInfoProvider;
84
import org.netbeans.modules.nativeexecution.api.util.FileInfoProvider;
78
import org.netbeans.modules.nativeexecution.api.util.HostInfoUtils;
85
import org.netbeans.modules.nativeexecution.api.util.HostInfoUtils;
86
import org.netbeans.modules.nativeexecution.api.util.ProcessUtils;
79
import org.netbeans.modules.remote.actions.FastPasteAction;
87
import org.netbeans.modules.remote.actions.FastPasteAction;
80
import org.netbeans.modules.remote.api.ConnectionNotifier;
88
import org.netbeans.modules.remote.api.ConnectionNotifier;
81
import org.netbeans.modules.remote.impl.RemoteLogger;
89
import org.netbeans.modules.remote.impl.RemoteLogger;
Lines 140-146 Link Here
140
    private final List<FileSystemProblemListener> problemListeners =
148
    private final List<FileSystemProblemListener> problemListeners =
141
            new ArrayList<>(globalProblemListeners);
149
            new ArrayList<>(globalProblemListeners);
142
    transient private final StatusImpl status = new StatusImpl();
150
    transient private final StatusImpl status = new StatusImpl();
151
152
    /** If the ALLOW_ALTERNATIVE_DELETE_ON_EXIT is ON and transport does not support delete-on-exit, 
153
     *  then alternative delete-on-exit will work */
154
    public static final boolean ALLOW_ALTERNATIVE_DELETE_ON_EXIT = 
155
            RemoteFileSystemUtils.getBoolean("remote.alternative.delete.on.exit", true);
156
    public static final String DELETE_ON_EXIT_FILE_NAME = ".rfs_delete_on_exit"; // NOI18N
157
    /** guarded by self */
143
    private final LinkedHashSet<String> deleteOnExitFiles = new LinkedHashSet<>();
158
    private final LinkedHashSet<String> deleteOnExitFiles = new LinkedHashSet<>();
159
    /** 
160
     * guarded by deleteOnExitFiles 
161
     * The idea is to remove files only on 1-st connect; otherwise we'll get to complex sync */
162
    boolean deleteOnExitFlag;
163
144
    private final ThreadLocal<RemoteFileObjectBase> beingRemoved = new ThreadLocal<>();
164
    private final ThreadLocal<RemoteFileObjectBase> beingRemoved = new ThreadLocal<>();
145
    private final ThreadLocal<RemoteFileObjectBase> beingCreated = new ThreadLocal<>();
165
    private final ThreadLocal<RemoteFileObjectBase> beingCreated = new ThreadLocal<>();
146
    private final ThreadLocal<RemoteFileObjectBase> externallyRemoved = new ThreadLocal<>();
166
    private final ThreadLocal<RemoteFileObjectBase> externallyRemoved = new ThreadLocal<>();
Lines 186-191 Link Here
186
        if (!cache.exists() && !cache.mkdirs()) {
206
        if (!cache.exists() && !cache.mkdirs()) {
187
            throw new IOException(NbBundle.getMessage(getClass(), "ERR_CreateDir", cache.getAbsolutePath())); // new IOException sic! (ctor)
207
            throw new IOException(NbBundle.getMessage(getClass(), "ERR_CreateDir", cache.getAbsolutePath())); // new IOException sic! (ctor)
188
        }
208
        }
209
        if (ALLOW_ALTERNATIVE_DELETE_ON_EXIT) {
210
            loadDeleteOnExit();
211
            synchronized (deleteOnExitFiles) {
212
                deleteOnExitFlag = true;
213
            }
214
        }
189
        this.rootDelegate = new RootFileObject(this.root = new RemoteFileObject(this), this, execEnv, cache); // NOI18N
215
        this.rootDelegate = new RootFileObject(this.root = new RemoteFileObject(this), this, execEnv, cache); // NOI18N
190
        factory.register(rootDelegate);
216
        factory.register(rootDelegate);
191
217
Lines 347-352 Link Here
347
                    fo.connectionChanged();
373
                    fo.connectionChanged();
348
                }
374
                }
349
            }
375
            }
376
            if (ALLOW_ALTERNATIVE_DELETE_ON_EXIT) {
377
                if (ConnectionManager.getInstance().isConnectedTo(execEnv)) {
378
                    deleteOnExitImpl();
379
                }
380
            }
350
        }
381
        }
351
382
352
        private void maintainAutoMounts() {
383
        private void maintainAutoMounts() {
Lines 420-425 Link Here
420
        if (COLLECT_STATSISTICS) {
451
        if (COLLECT_STATSISTICS) {
421
            lockSupport.printStatistics(this);
452
            lockSupport.printStatistics(this);
422
        }
453
        }
454
        if (ALLOW_ALTERNATIVE_DELETE_ON_EXIT) {
455
            // right here: on IDE shutdown we otherwise won't be in time to store
456
            storeDeleteOnExit();
457
        }
423
    }
458
    }
424
    
459
    
425
    public ExecutionEnvironment getExecutionEnvironment() {
460
    public ExecutionEnvironment getExecutionEnvironment() {
Lines 949-984 Link Here
949
        return status;
984
        return status;
950
    }
985
    }
951
    
986
    
952
    public void deleteOnExit(String path) {
987
    public void deleteOnExit(String... paths) {
953
        synchronized(deleteOnExitFiles) {
988
        synchronized(deleteOnExitFiles) {
954
            if (deleteOnExitFiles.isEmpty()) {
989
            for (String p : paths) {
955
                Runtime.getRuntime().addShutdownHook(new Thread() {
990
                deleteOnExitFiles.add(p);                
956
957
                    @Override
958
                    public void run() {
959
                        releaseResources();
960
                    }
961
962
                });
963
            }
991
            }
964
            deleteOnExitFiles.add(path);
965
        }
992
        }
966
    }
993
    }
967
    
994
    
968
    private void releaseResources() {
995
    private void deleteOnExitImpl() {
969
    	ArrayList<String> toBeDeleted;
996
        assert ALLOW_ALTERNATIVE_DELETE_ON_EXIT;
997
        List<String> toBeDeleted = Collections.emptyList();
970
        synchronized(deleteOnExitFiles) {
998
        synchronized(deleteOnExitFiles) {
971
        	toBeDeleted = new ArrayList<>(deleteOnExitFiles);
999
            if (deleteOnExitFlag && !deleteOnExitFiles.isEmpty()) {
1000
                deleteOnExitFlag = false; // delete only on 1-st connect, otherwize we get sync issues
1001
                toBeDeleted = new ArrayList<>(deleteOnExitFiles);
1002
                deleteOnExitFiles.clear();
1003
            }
1004
        }
1005
        if (toBeDeleted.isEmpty()) {
1006
            return;
972
        }
1007
        }
973
    	Collections.reverse(toBeDeleted);
1008
    	Collections.reverse(toBeDeleted);
974
        for (String filename : toBeDeleted) {
1009
        StringBuilder sb = new StringBuilder();
975
            if (!ConnectionManager.getInstance().isConnectedTo(execEnv)) {
1010
        for (String p : toBeDeleted) {
976
                 return;
1011
            if (sb.length() > 0) {
1012
                sb.append(' ');
977
            }
1013
            }
978
            CommonTasksSupport.rmFile(execEnv, filename, null);
1014
            sb.append(p);
1015
        }
1016
        if (!ConnectionManager.getInstance().isConnectedTo(execEnv)) {
1017
             return;
1018
        }
1019
        ProcessUtils.execute(NativeProcessBuilder.newProcessBuilder(execEnv).setExecutable("xargs").setArguments("rm"), sb.toString().getBytes());
1020
1021
    }
1022
    
1023
    private void storeDeleteOnExit() {
1024
        assert ALLOW_ALTERNATIVE_DELETE_ON_EXIT;
1025
        ArrayList<String> toStore;
1026
        synchronized (deleteOnExitFiles) {
1027
            toStore = new ArrayList<>(deleteOnExitFiles);
1028
        }
1029
        File f = new File(getCache(), DELETE_ON_EXIT_FILE_NAME);
1030
        // the existence of cache root ensured in ctor
1031
        try (PrintWriter pw = new PrintWriter(f, "UTF8")) { // NOI18N
1032
            if (!toStore.isEmpty()) {
1033
                for (String path : toStore) {
1034
                    pw.append(path).append('\n');
1035
                }
1036
                pw.close();
1037
            }
1038
        } catch (FileNotFoundException | UnsupportedEncodingException ex) {
1039
            Exceptions.printStackTrace(ex); // should never occur
979
        }
1040
        }
980
    }
1041
    }
981
    
1042
    
1043
    private void loadDeleteOnExit() {
1044
        assert ALLOW_ALTERNATIVE_DELETE_ON_EXIT;
1045
        File f = new File(getCache(), DELETE_ON_EXIT_FILE_NAME);
1046
        // the existence of cache root ensured in ctor
1047
        synchronized (deleteOnExitFiles) {
1048
            // this is called from ctor only, so it's OK to do file ops in sync block
1049
            try (BufferedReader br = new BufferedReader(new FileReader(f))) {
1050
                for (String path; (path = br.readLine()) != null;) {
1051
                    if (!path.isEmpty()) {
1052
                        deleteOnExitFiles.add(path);
1053
                    }
1054
                }
1055
                // line is not visible here.
1056
            } catch (FileNotFoundException ex) {
1057
                // nothing to do: no file is quite normal
1058
            } catch (IOException ex) {
1059
                ex.printStackTrace(System.err);
1060
            }
1061
        }
1062
    }
1063
982
    /*package*/ void setBeingRemoved(RemoteFileObjectBase fo) {
1064
    /*package*/ void setBeingRemoved(RemoteFileObjectBase fo) {
983
        beingRemoved.set(fo);
1065
        beingRemoved.set(fo);
984
    }
1066
    }

Return to bug 268926