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 206475
Collapse All | Expand All

(-)a/db/nbproject/project.xml (-1 / +1 lines)
Lines 90-96 Link Here
90
                    <build-prerequisite/>
90
                    <build-prerequisite/>
91
                    <compile-dependency/>
91
                    <compile-dependency/>
92
                    <run-dependency>
92
                    <run-dependency>
93
                        <specification-version>1.1</specification-version>
93
                        <specification-version>1.10</specification-version>
94
                    </run-dependency>
94
                    </run-dependency>
95
                </dependency>
95
                </dependency>
96
                <dependency>
96
                <dependency>
(-)a/db/src/org/netbeans/modules/db/explorer/DatabaseConnection.java (-118 / +19 lines)
Lines 609-743 Link Here
609
            return ;
609
            return ;
610
        }
610
        }
611
        final String key = this.connectionFileName;
611
        final String key = this.connectionFileName;
612
        waitForReading(new Runnable() {
612
        // If the password was saved, then it means the user checked
613
            @Override
613
        // the box to say the password should be remembered.
614
            public void run() {
614
        char[] chars = Keyring.read(key);
615
                // If the password was saved, then it means the user checked
615
        if (chars != null) {
616
                // the box to say the password should be remembered.
616
            LOGGER.log(Level.FINE, "A password read for " + key);
617
                char[] chars = Keyring.read(key);
617
            pwd = String.valueOf(chars);
618
                if (chars != null) {
618
            rpwd = true;
619
                    LOGGER.log(Level.FINE, "A password read for " + key);
619
        } else {
620
                    pwd = String.valueOf(chars);
620
            LOGGER.log(Level.FINE, "No password read for " + key);
621
                    rpwd = true;
621
            pwd = "";
622
                } else {
622
            rpwd = false;
623
                    LOGGER.log(Level.FINE, "No password read for " + key);
623
        }
624
                    pwd = "";
625
                    rpwd = false;
626
                }
627
            }
628
            
629
        });
630
    }
624
    }
631
625
632
    public static void storePassword(final String key, final char[] pwd) {
626
    public static void storePassword(final String key, final char[] pwd) {
633
        Parameters.notNull("key", key);
627
        Parameters.notNull("key", key);
634
        Parameters.notNull("pwd", pwd);
628
        Parameters.notNull("pwd", pwd);
635
        RP.post(new Runnable() {
636
629
637
            @Override
630
        LOGGER.log(Level.FINE, "Storing password for " + key);
638
            public void run() {
631
        Keyring.save(key,
639
                LOGGER.log(Level.FINE, "Storing password for " + key);
632
                pwd,
640
                Keyring.save(key,
633
                NbBundle.getMessage(DatabaseConnectionConvertor.class,
641
                        pwd,
634
                    "DatabaseConnectionConvertor.password_description", key)); //NOI18N
642
                        NbBundle.getMessage(DatabaseConnectionConvertor.class,
643
                            "DatabaseConnectionConvertor.password_description", key)); //NOI18N
644
            }
645
        });
646
    }
647
    
648
    private void waitForReading(final Runnable toRun) {
649
        if (SwingUtilities.isEventDispatchThread()) {
650
            LOGGER.finest("Showing a wait dialog...");
651
            showWaitingDialog(toRun);
652
            LOGGER.finest("Showing a wait dialog - done.");
653
        } else {
654
            if (keyringTask != null && ! keyringTask.isFinished()) {
655
                LOGGER.finest("Wait for finished keyringTask");
656
                keyringTask.waitFinished();
657
                LOGGER.finest("keyringTask done.");
658
                toRun.run();
659
                return ;
660
            }            
661
            final Object lock = new Object();
662
            SwingUtilities.invokeLater(new Runnable() {
663
664
                @Override
665
                public void run() {
666
                    LOGGER.finest("Showing a wait dialog...");
667
                    showWaitingDialog(toRun);
668
                    synchronized (lock) {
669
                        lock.notifyAll();
670
                    }
671
                    LOGGER.finest("Showing a wait dialog - done.");
672
                }
673
            });
674
            try {
675
                synchronized (lock) {
676
                    lock.wait();
677
                }
678
            } catch (InterruptedException ex) {
679
                LOGGER.log(Level.INFO, ex.getMessage(), ex);
680
            }
681
        }
682
    }
683
    
684
    private RequestProcessor.Task keyringTask = null;
685
    
686
    private void showWaitingDialog(final Runnable toRun) {
687
        assert SwingUtilities.isEventDispatchThread();
688
689
        ProgressHandle progress = ProgressHandleFactory.createHandle("keyring");
690
        JComponent progressComponent = ProgressHandleFactory.createProgressComponent(progress);
691
        progress.start();
692
        ConnectProgressDialog panel = new ConnectProgressDialog(progressComponent,
693
                NbBundle.getMessage(DatabaseConnection.class, "DatabaseConnection_PleaseWaitMessage")); // NOI18N);
694
        panel.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage (ConnectAction.class, "ACS_ConnectingDialogTextA11yDesc")); // NOI18N
695
        final Dialog d = new JDialog(WindowManager.getDefault().getMainWindow(),
696
                                NbBundle.getMessage(DatabaseConnection.class, "DatabaseConnection_PleaseWaitTitle"), // NOI18N
697
                                true);
698
        d.add(panel);
699
        d.setSize(new Dimension(500, 100));
700
        d.setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
701
        keyringTask = RP.post(new Runnable() {
702
703
            @Override
704
            public void run() {
705
                try {
706
                    toRun.run();
707
                } finally {
708
                    SwingUtilities.invokeLater(new Runnable() {
709
710
                        @Override
711
                        public void run() {
712
                            if (d != null) {
713
                                LOGGER.finest("Hide Waiting For Access to Keyring dialog.");
714
                                d.setVisible(false);
715
                                d.dispose();
716
                            }
717
                        }
718
                    });
719
                }
720
            }
721
        });
722
        LOGGER.finest("Show Waiting For Access to Keyring dialog.");
723
        try {
724
            Thread.sleep(100);
725
        } catch (InterruptedException ex) {
726
            LOGGER.log(Level.INFO, ex.getMessage(), ex);
727
        }
728
        d.setVisible(! keyringTask.isFinished());
729
    }
635
    }
730
    
636
    
731
    public static void deletePassword(final String key) {
637
    public static void deletePassword(final String key) {
732
        Parameters.notNull("key", key);
638
        Parameters.notNull("key", key);
733
        RP.post(new Runnable() {
734
639
735
            @Override
640
        LOGGER.log(Level.FINE, "Deleting password for " + key);
736
            public void run() {
641
        Keyring.delete(key);
737
                LOGGER.log(Level.FINE, "Deleting password for " + key);
738
                Keyring.delete(key);
739
            }
740
        });
741
    }
642
    }
742
    
643
    
743
    /** Returns if password should be remembered */
644
    /** Returns if password should be remembered */
(-)a/j2eeserver/nbproject/project.xml (-1 / +1 lines)
Lines 173-179 Link Here
173
                    <build-prerequisite/>
173
                    <build-prerequisite/>
174
                    <compile-dependency/>
174
                    <compile-dependency/>
175
                    <run-dependency>
175
                    <run-dependency>
176
                        <specification-version>1.5</specification-version>
176
                        <specification-version>1.10</specification-version>
177
                    </run-dependency>
177
                    </run-dependency>
178
                </dependency>
178
                </dependency>
179
                <dependency>
179
                <dependency>
(-)a/j2eeserver/src/org/netbeans/modules/j2ee/deployment/impl/ServerRegistry.java (-94 / +27 lines)
Lines 46-53 Link Here
46
46
47
import java.io.File;
47
import java.io.File;
48
import java.io.IOException;
48
import java.io.IOException;
49
import java.util.concurrent.ExecutionException;
50
import java.util.concurrent.TimeoutException;
51
import java.util.logging.Logger;
49
import java.util.logging.Logger;
52
import org.netbeans.modules.j2ee.deployment.devmodules.api.J2eeModule;
50
import org.netbeans.modules.j2ee.deployment.devmodules.api.J2eeModule;
53
import org.netbeans.modules.j2ee.deployment.plugins.api.InstanceProperties;
51
import org.netbeans.modules.j2ee.deployment.plugins.api.InstanceProperties;
Lines 67-83 Link Here
67
import java.util.List;
65
import java.util.List;
68
import java.util.Map;
66
import java.util.Map;
69
import java.util.Set;
67
import java.util.Set;
70
import java.util.concurrent.Callable;
71
import java.util.concurrent.CopyOnWriteArrayList;
68
import java.util.concurrent.CopyOnWriteArrayList;
72
import java.util.concurrent.Future;
73
import java.util.concurrent.TimeUnit;
74
import java.util.logging.Level;
69
import java.util.logging.Level;
75
import javax.swing.SwingUtilities;
76
import org.netbeans.api.annotations.common.CheckForNull;
70
import org.netbeans.api.annotations.common.CheckForNull;
77
import org.netbeans.api.annotations.common.NonNull;
71
import org.netbeans.api.annotations.common.NonNull;
78
import org.netbeans.api.annotations.common.NullAllowed;
72
import org.netbeans.api.annotations.common.NullAllowed;
79
import org.netbeans.api.keyring.Keyring;
73
import org.netbeans.api.keyring.Keyring;
80
import org.netbeans.api.progress.ProgressUtils;
81
import org.netbeans.modules.j2ee.deployment.devmodules.spi.InstanceListener;
74
import org.netbeans.modules.j2ee.deployment.devmodules.spi.InstanceListener;
82
import org.netbeans.modules.j2ee.deployment.plugins.api.AlreadyRegisteredException;
75
import org.netbeans.modules.j2ee.deployment.plugins.api.AlreadyRegisteredException;
83
import org.netbeans.modules.j2ee.deployment.plugins.spi.OptionalDeploymentManagerFactory;
76
import org.netbeans.modules.j2ee.deployment.plugins.spi.OptionalDeploymentManagerFactory;
Lines 87-93 Link Here
87
import org.openide.filesystems.FileEvent;
80
import org.openide.filesystems.FileEvent;
88
import org.openide.filesystems.FileObject;
81
import org.openide.filesystems.FileObject;
89
import org.openide.filesystems.FileUtil;
82
import org.openide.filesystems.FileUtil;
90
import org.openide.util.RequestProcessor;
91
83
92
public final class ServerRegistry implements java.io.Serializable {
84
public final class ServerRegistry implements java.io.Serializable {
93
85
Lines 99-106 Link Here
99
    public static final String TARGETNAME_ATTR = "targetName"; //NOI18N
91
    public static final String TARGETNAME_ATTR = "targetName"; //NOI18N
100
    public static final String SERVER_NAME = "serverName"; //NOI18N
92
    public static final String SERVER_NAME = "serverName"; //NOI18N
101
    
93
    
102
    private static final RequestProcessor KEYRING_ACCESS = new RequestProcessor();
103
    
104
    private static ServerRegistry instance = null;
94
    private static ServerRegistry instance = null;
105
    public synchronized static ServerRegistry getInstance() {
95
    public synchronized static ServerRegistry getInstance() {
106
        if(instance == null) instance = new ServerRegistry();
96
        if(instance == null) instance = new ServerRegistry();
Lines 424-435 Link Here
424
                LOGGER.log(Level.INFO, null, ioe);
414
                LOGGER.log(Level.INFO, null, ioe);
425
            }
415
            }
426
        }
416
        }
427
            KEYRING_ACCESS.post(new Runnable() {
417
428
                @Override
418
        Keyring.delete(getPasswordKey(url));
429
                public void run() {
430
                    Keyring.delete(getPasswordKey(url));
431
                }
432
            });
433
    }
419
    }
434
420
435
    /**
421
    /**
Lines 651-747 Link Here
651
    public static Profiler getProfiler() {
637
    public static Profiler getProfiler() {
652
        return (Profiler)Lookup.getDefault().lookup(Profiler.class);
638
        return (Profiler)Lookup.getDefault().lookup(Profiler.class);
653
    }
639
    }
654
    
640
655
    @CheckForNull
641
    @CheckForNull
656
    static String readPassword(@NonNull final String url) {
642
    static String readPassword(@NonNull final String url) {
657
        Callable<String> call = new Callable<String>() {
643
        char[] passwordChars = Keyring.read(getPasswordKey(url));
658
            @Override
644
        if (passwordChars != null) {
659
            public String call() throws Exception {
645
            String password = String.valueOf(passwordChars);
660
                char[] passwordChars = Keyring.read(getPasswordKey(url));
646
            Arrays.fill(passwordChars, ' ');
661
                if (passwordChars != null) {
647
            return password;
662
                    String password = String.valueOf(passwordChars);
648
        }
663
                    Arrays.fill(passwordChars, ' ');
649
        return null;
664
                    return password;
665
                }
666
                return null;
667
            }
668
        };
669
        return readPassword(call);
670
    }
650
    }
671
    
651
672
    static void savePassword(@NonNull final String url, @NullAllowed final String password,
652
    static void savePassword(@NonNull final String url, @NullAllowed final String password,
673
            @NullAllowed final String displayName) {
653
            @NullAllowed final String displayName) {
674
        
654
675
        Runnable run = new Runnable() {
655
        if (password == null) {
676
            @Override
656
            return;
677
            public void run() {
657
        }
678
                if (password == null) {
658
        Keyring.save(getPasswordKey(url), password.toCharArray(), displayName);
679
                    return;
680
                }
681
                Keyring.save(getPasswordKey(url), password.toCharArray(), displayName);
682
            }
683
        };
684
        KEYRING_ACCESS.post(run);
685
    }
659
    }
686
    
660
    
687
    static void savePassword(@NonNull final FileObject fo, @NullAllowed final String password,
661
    static void savePassword(@NonNull final FileObject fo, @NullAllowed final String password,
688
            @NullAllowed final String displayName) {
662
            @NullAllowed final String displayName) {
689
        
663
        
690
        Runnable run = new Runnable() {
664
        if (password == null) {
691
665
            return;
692
            @Override
666
        }
693
            public void run() {
667
        String url = (String) fo.getAttribute(InstanceProperties.URL_ATTR);
694
                if (password == null) {
668
        if (url == null) {
695
                    return;
669
            return;
696
                }
670
        }
697
                String url = (String) fo.getAttribute(InstanceProperties.URL_ATTR);
671
        Keyring.save(getPasswordKey(url), password.toCharArray(), displayName);
698
                if (url == null) {
699
                    return;
700
                }
701
                Keyring.save(getPasswordKey(url), password.toCharArray(), displayName);
702
                try {
703
                    fo.setAttribute(InstanceProperties.PASSWORD_ATTR, null);
704
                } catch (IOException ex) {
705
                    LOGGER.log(Level.INFO, null, ex);
706
                }
707
            }
708
        };
709
        KEYRING_ACCESS.post(run);
710
    }    
711
    
712
    private static String readPassword(Callable<String> readTask) {
713
        try {
672
        try {
714
            final Future<String> result = KEYRING_ACCESS.submit(readTask);
673
            fo.setAttribute(InstanceProperties.PASSWORD_ATTR, null);
715
            if (SwingUtilities.isEventDispatchThread()) {
674
        } catch (IOException ex) {
716
                if (!result.isDone()) {
717
                    try {
718
                        // lets wait in awt to avoid flashing dialogs
719
                        result.get(50, TimeUnit.MILLISECONDS);
720
                    } catch (TimeoutException ex) {
721
                        ProgressUtils.showProgressDialogAndRun(new Runnable() {
722
723
                            @Override
724
                            public void run() {
725
                                try {
726
                                    result.get();
727
                                } catch (InterruptedException ex) {
728
                                    Thread.currentThread().interrupt();
729
                                } catch (ExecutionException ex) {
730
                                    LOGGER.log(Level.INFO, null, ex);
731
                                }
732
                            }
733
                        }, NbBundle.getMessage(ServerRegistry.class, "MSG_KeyringAccess"));
734
                    }
735
                }
736
            }
737
            return result.get();
738
        } catch (InterruptedException ex) {
739
            Thread.currentThread().interrupt();
740
        } catch (ExecutionException ex) {
741
            LOGGER.log(Level.INFO, null, ex);
675
            LOGGER.log(Level.INFO, null, ex);
742
        }
676
        }
743
        return null;         
677
    }    
744
    }
745
678
746
    private static String getPasswordKey(String url) {
679
    private static String getPasswordKey(String url) {
747
        StringBuilder builder = new StringBuilder("j2eeserver:");
680
        StringBuilder builder = new StringBuilder("j2eeserver:");
(-)a/j2eeserver/test/unit/src/org/netbeans/modules/j2ee/deployment/plugins/api/InstancePropertiesTest.java (-25 / +4 lines)
Lines 200-212 Link Here
200
200
201
    public void testPasswordInKeyring() throws Exception {
201
    public void testPasswordInKeyring() throws Exception {
202
        // the instance from test layer
202
        // the instance from test layer
203
        assertEquals("Adminpasswd", getPasswordFromKeyring("j2eeserver:fooservice"));
203
        assertEquals("Adminpasswd", new String(Keyring.read("j2eeserver:fooservice")));
204
204
205
        // new instance
205
        // new instance
206
        String url = TEST_URL_PREFIX + "passwordInKeyring";
206
        String url = TEST_URL_PREFIX + "passwordInKeyring";
207
        InstanceProperties.createInstanceProperties(
207
        InstanceProperties.createInstanceProperties(
208
                url, TEST_USERNAME, TEST_PASSWORD, TEST_DISPLAY_NAME);
208
                url, TEST_USERNAME, TEST_PASSWORD, TEST_DISPLAY_NAME);
209
        assertEquals(TEST_PASSWORD, getPasswordFromKeyring("j2eeserver:" + url));
209
        assertEquals(TEST_PASSWORD, new String(Keyring.read("j2eeserver:" + url)));
210
210
211
        // all password attributes are converted to keyring
211
        // all password attributes are converted to keyring
212
        FileObject fo = FileUtil.getConfigFile("J2EE/InstalledServers");
212
        FileObject fo = FileUtil.getConfigFile("J2EE/InstalledServers");
Lines 219-249 Link Here
219
        String url = TEST_URL_PREFIX + "keyringCleanup";
219
        String url = TEST_URL_PREFIX + "keyringCleanup";
220
        InstanceProperties.createInstanceProperties(
220
        InstanceProperties.createInstanceProperties(
221
                url, TEST_USERNAME, TEST_PASSWORD, TEST_DISPLAY_NAME);
221
                url, TEST_USERNAME, TEST_PASSWORD, TEST_DISPLAY_NAME);
222
        assertEquals(TEST_PASSWORD, getPasswordFromKeyring("j2eeserver:" + url));
222
        assertEquals(TEST_PASSWORD, new String(Keyring.read("j2eeserver:" + url)));
223
223
224
        ServerRegistry.getInstance().removeServerInstance(url);
224
        ServerRegistry.getInstance().removeServerInstance(url);
225
        assertNull(getPasswordFromKeyring("j2eeserver:" + url));
225
        assertNull(Keyring.read("j2eeserver:" + url));
226
    }
227
228
    private static String getPasswordFromKeyring(final String key) throws Exception {
229
        Future<String> ret = getKeyringAccess().submit(new Callable<String>() {
230
231
            @Override
232
            public String call() throws Exception {
233
                char[] passwd = Keyring.read(key);
234
                if (passwd != null) {
235
                    return String.valueOf(passwd);
236
                }
237
                return null;
238
            }
239
        });
240
        return ret.get(5, TimeUnit.SECONDS);
241
    }
242
243
    private static RequestProcessor getKeyringAccess() throws Exception {
244
        Field field = ServerRegistry.class.getDeclaredField("KEYRING_ACCESS");
245
        field.setAccessible(true);
246
        return (RequestProcessor) field.get(null);
247
    }
226
    }
248
227
249
    private static void assertPropertiesEquals(Map<String, String> expected, InstanceProperties props) {
228
    private static void assertPropertiesEquals(Map<String, String> expected, InstanceProperties props) {
(-)a/keyring/manifest.mf (-1 / +1 lines)
Lines 1-6 Link Here
1
Manifest-Version: 1.0
1
Manifest-Version: 1.0
2
OpenIDE-Module: org.netbeans.modules.keyring
2
OpenIDE-Module: org.netbeans.modules.keyring
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/keyring/Bundle.properties
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/keyring/Bundle.properties
4
OpenIDE-Module-Specification-Version: 1.9
4
OpenIDE-Module-Specification-Version: 1.10
5
OpenIDE-Module-Recommends: org.netbeans.modules.keyring.impl
5
OpenIDE-Module-Recommends: org.netbeans.modules.keyring.impl
6
6
(-)a/keyring/nbproject/project.xml (+18 lines)
Lines 6-11 Link Here
6
            <code-name-base>org.netbeans.modules.keyring</code-name-base>
6
            <code-name-base>org.netbeans.modules.keyring</code-name-base>
7
            <module-dependencies>
7
            <module-dependencies>
8
                <dependency>
8
                <dependency>
9
                    <code-name-base>org.netbeans.api.annotations.common</code-name-base>
10
                    <build-prerequisite/>
11
                    <compile-dependency/>
12
                    <run-dependency>
13
                        <release-version>1</release-version>
14
                        <specification-version>1.13</specification-version>
15
                    </run-dependency>
16
                </dependency>
17
                <dependency>
18
                    <code-name-base>org.netbeans.api.progress</code-name-base>
19
                    <build-prerequisite/>
20
                    <compile-dependency/>
21
                    <run-dependency>
22
                        <release-version>1</release-version>
23
                        <specification-version>1.27</specification-version>
24
                    </run-dependency>
25
                </dependency>
26
                <dependency>
9
                    <code-name-base>org.openide.util</code-name-base>
27
                    <code-name-base>org.openide.util</code-name-base>
10
                    <build-prerequisite/>
28
                    <build-prerequisite/>
11
                    <compile-dependency/>
29
                    <compile-dependency/>
(-)a/keyring/src/org/netbeans/api/keyring/Keyring.java (-13 / +92 lines)
Lines 45-66 Link Here
45
import java.util.Arrays;
45
import java.util.Arrays;
46
import java.util.HashMap;
46
import java.util.HashMap;
47
import java.util.Map;
47
import java.util.Map;
48
import java.util.concurrent.Callable;
49
import java.util.concurrent.ExecutionException;
50
import java.util.concurrent.Future;
51
import java.util.concurrent.TimeUnit;
52
import java.util.concurrent.TimeoutException;
48
import java.util.logging.Level;
53
import java.util.logging.Level;
49
import java.util.logging.Logger;
54
import java.util.logging.Logger;
55
import javax.swing.SwingUtilities;
56
import org.netbeans.api.annotations.common.CheckForNull;
57
import org.netbeans.api.annotations.common.NonNull;
58
import org.netbeans.api.annotations.common.NullAllowed;
59
import org.netbeans.api.progress.ProgressUtils;
50
import org.netbeans.spi.keyring.KeyringProvider;
60
import org.netbeans.spi.keyring.KeyringProvider;
51
import org.openide.util.Lookup;
61
import org.openide.util.Lookup;
62
import org.openide.util.NbBundle;
52
import org.openide.util.Parameters;
63
import org.openide.util.Parameters;
64
import org.openide.util.RequestProcessor;
53
65
54
/**
66
/**
55
 * Client class for working with stored keys (such as passwords).
67
 * Client class for working with stored keys (such as passwords).
56
 * <p>The key identifier should be unique for the whole application,
68
 * <p>The key identifier should be unique for the whole application,
57
 * so qualify it with any prefixes as needed.
69
 * so qualify it with any prefixes as needed.
58
 * <p>Avoid calling methods on this class from the event dispatch thread,
59
 * as some provider implementations may need to block while displaying a dialog
60
 * (e.g. prompting for a master password to access the keyring).
61
 */
70
 */
71
@NbBundle.Messages("MSG_KeyringAccess=Requesting keyring access")
62
public class Keyring {
72
public class Keyring {
63
73
74
    private static final RequestProcessor KEYRING_ACCESS = new RequestProcessor();
75
64
    private Keyring() {}
76
    private Keyring() {}
65
77
66
    private static final Logger LOG = Logger.getLogger("org.netbeans.modules.keyring");
78
    private static final Logger LOG = Logger.getLogger("org.netbeans.modules.keyring");
Lines 82-96 Link Here
82
        return PROVIDER;
94
        return PROVIDER;
83
    }
95
    }
84
96
97
    private static synchronized char[] readImpl(String key) {
98
        LOG.log(Level.FINEST, "reading: {0}", key);
99
        return provider().read(key);
100
    }
101
85
    /**
102
    /**
86
     * Reads a key from the ring.
103
     * Reads a key from the ring.
87
     * @param key the identifier of the key
104
     * @param key the identifier of the key
88
     * @return its value if found (you may null out its elements), else null if not present
105
     * @return its value if found (you may null out its elements), else null if not present
89
     */
106
     */
90
    public static synchronized char[] read(String key) {
107
    @CheckForNull
108
    public static char[] read(@NonNull final String key) {
91
        Parameters.notNull("key", key);
109
        Parameters.notNull("key", key);
92
        LOG.log(Level.FINEST, "reading: {0}", key);
110
93
        return provider().read(key);
111
        try {
112
            final Future<char[]> result = KEYRING_ACCESS.submit(new Callable<char[]>() {
113
                @Override
114
                public char[] call() throws Exception {
115
                    return Keyring.readImpl(key);
116
                }
117
            });
118
119
            if (SwingUtilities.isEventDispatchThread()) {
120
                if (!result.isDone()) {
121
                    try {
122
                        // lets wait in awt to avoid flashing dialogs
123
                        result.get(70, TimeUnit.MILLISECONDS);
124
                    } catch (TimeoutException ex) {
125
                        ProgressUtils.showProgressDialogAndRun(new Runnable() {
126
127
                            @Override
128
                            public void run() {
129
                                try {
130
                                    result.get();
131
                                } catch (InterruptedException ex) {
132
                                    Thread.currentThread().interrupt();
133
                                } catch (ExecutionException ex) {
134
                                    LOG.log(Level.INFO, null, ex);
135
                                }
136
                            }
137
                        }, Bundle.MSG_KeyringAccess());
138
                    }
139
                }
140
            }
141
            return result.get();
142
        } catch (InterruptedException ex) {
143
            Thread.currentThread().interrupt();
144
        } catch (ExecutionException ex) {
145
            LOG.log(Level.INFO, null, ex);
146
        }
147
        return null;
148
    }
149
150
    private static synchronized void saveImpl(String key, char[] password, String description) {
151
        LOG.log(Level.FINEST, "saving: {0}", key);
152
        provider().save(key, password, description);
153
        Arrays.fill(password, (char) 0);
94
    }
154
    }
95
155
96
    /**
156
    /**
Lines 102-113 Link Here
102
     *                 (its contents will be nulled out by end of call)
162
     *                 (its contents will be nulled out by end of call)
103
     * @param description a user-visible description of the key (may be null)
163
     * @param description a user-visible description of the key (may be null)
104
     */
164
     */
105
    public static synchronized void save(String key, char[] password, String description) {
165
    public static void save(@NonNull final String key, @NonNull final char[] password,
166
            @NullAllowed final String description) {
167
106
        Parameters.notNull("key", key);
168
        Parameters.notNull("key", key);
107
        Parameters.notNull("password", password);
169
        Parameters.notNull("password", password);
108
        LOG.log(Level.FINEST, "saving: {0}", key);
170
109
        provider().save(key, password, description);
171
        Runnable run = new Runnable() {
110
        Arrays.fill(password, (char) 0);
172
173
            @Override
174
            public void run() {
175
                Keyring.saveImpl(key, password, description);
176
            }
177
        };
178
        KEYRING_ACCESS.post(run);
179
    }
180
181
    private static synchronized void deleteImpl(String key) {
182
        LOG.log(Level.FINEST, "deleting: {0}", key);
183
        provider().delete(key);
111
    }
184
    }
112
185
113
    /**
186
    /**
Lines 115-124 Link Here
115
     * If the key was not in the ring to begin with, does nothing.
188
     * If the key was not in the ring to begin with, does nothing.
116
     * @param key a key identifier
189
     * @param key a key identifier
117
     */
190
     */
118
    public static synchronized void delete(String key) {
191
    public static void delete(@NonNull final String key) {
119
        Parameters.notNull("key", key);
192
        Parameters.notNull("key", key);
120
        LOG.log(Level.FINEST, "deleting: {0}", key);
193
121
        provider().delete(key);
194
        KEYRING_ACCESS.post(new Runnable() {
195
196
            @Override
197
            public void run() {
198
                Keyring.deleteImpl(key);
199
            }
200
        });
122
    }
201
    }
123
202
124
    private static class DummyKeyringProvider implements KeyringProvider {
203
    private static class DummyKeyringProvider implements KeyringProvider {
(-)a/php.project/nbproject/project.xml (-1 / +1 lines)
Lines 177-183 Link Here
177
                    <build-prerequisite/>
177
                    <build-prerequisite/>
178
                    <compile-dependency/>
178
                    <compile-dependency/>
179
                    <run-dependency>
179
                    <run-dependency>
180
                        <specification-version>1.0</specification-version>
180
                        <specification-version>1.10</specification-version>
181
                    </run-dependency>
181
                    </run-dependency>
182
                </dependency>
182
                </dependency>
183
                <dependency>
183
                <dependency>
(-)a/php.project/src/org/netbeans/modules/php/project/connections/spi/RemoteConfiguration.java (-69 / +16 lines)
Lines 42-62 Link Here
42
42
43
package org.netbeans.modules.php.project.connections.spi;
43
package org.netbeans.modules.php.project.connections.spi;
44
44
45
import java.util.concurrent.Callable;
46
import java.util.concurrent.ExecutionException;
47
import java.util.concurrent.Future;
48
import java.util.concurrent.TimeUnit;
49
import java.util.concurrent.TimeoutException;
50
import java.util.logging.Level;
45
import java.util.logging.Level;
51
import java.util.logging.Logger;
46
import java.util.logging.Logger;
52
import javax.swing.SwingUtilities;
53
import org.netbeans.api.keyring.Keyring;
47
import org.netbeans.api.keyring.Keyring;
54
import org.netbeans.api.progress.ProgressUtils;
55
import org.netbeans.modules.php.api.util.StringUtils;
48
import org.netbeans.modules.php.api.util.StringUtils;
56
import org.netbeans.modules.php.project.connections.ConfigManager;
49
import org.netbeans.modules.php.project.connections.ConfigManager;
57
import org.netbeans.modules.php.project.util.PhpProjectUtils;
50
import org.netbeans.modules.php.project.util.PhpProjectUtils;
58
import org.openide.util.NbBundle;
51
import org.openide.util.NbBundle;
59
import org.openide.util.RequestProcessor;
60
52
61
/**
53
/**
62
 * Class representing a remote configuration (e.g. FTP, SFTP).
54
 * Class representing a remote configuration (e.g. FTP, SFTP).
Lines 69-75 Link Here
69
public abstract class RemoteConfiguration {
61
public abstract class RemoteConfiguration {
70
62
71
    protected static final Logger LOGGER = Logger.getLogger(RemoteConfiguration.class.getName());
63
    protected static final Logger LOGGER = Logger.getLogger(RemoteConfiguration.class.getName());
72
    static final RequestProcessor KEYRING_ACCESS = new RequestProcessor();
73
64
74
    protected final ConfigManager.Configuration cfg;
65
    protected final ConfigManager.Configuration cfg;
75
66
Lines 301-349 Link Here
301
    }
292
    }
302
293
303
    private String readPasswordFromKeyring() {
294
    private String readPasswordFromKeyring() {
304
        try {
295
        // new password key
305
            final Future<String> result = KEYRING_ACCESS.submit(new Callable<String>() {
296
        char[] newPassword = Keyring.read(passwordKey);
306
                @Override
297
        if (newPassword != null) {
307
                public String call() throws Exception {
298
            return new String(newPassword);
308
                    // new password key
299
        }
309
                    char[] newPassword = Keyring.read(passwordKey);
300
        // deprecated password key
310
                    if (newPassword != null) {
301
        newPassword = Keyring.read(deprecatedPasswordKey);
311
                        return new String(newPassword);
302
        if (newPassword != null) {
312
                    }
303
            return new String(newPassword);
313
                    // deprecated password key
314
                    newPassword = Keyring.read(deprecatedPasswordKey);
315
                    if (newPassword != null) {
316
                        return new String(newPassword);
317
                    }
318
                    return null;
319
                }
320
            });
321
            if (SwingUtilities.isEventDispatchThread()) {
322
                if (!result.isDone()) {
323
                    try {
324
                        // let's wait in awt to avoid flashing dialogs
325
                        result.get(99, TimeUnit.MILLISECONDS);
326
                    } catch (TimeoutException ex) {
327
                        ProgressUtils.showProgressDialogAndRun(new Runnable() {
328
                            @Override
329
                            public void run() {
330
                                try {
331
                                    result.get();
332
                                } catch (InterruptedException ex) {
333
                                    Thread.currentThread().interrupt();
334
                                } catch (ExecutionException ex) {
335
                                    LOGGER.log(Level.INFO, null, ex);
336
                                }
337
                            }
338
                        }, NbBundle.getMessage(RemoteConfiguration.class, "MSG_KeyringAccess"));
339
                    }
340
                }
341
            }
342
            return result.get();
343
        } catch (InterruptedException ex) {
344
            Thread.currentThread().interrupt();
345
        } catch (ExecutionException ex) {
346
            LOGGER.log(Level.INFO, null, ex);
347
        }
304
        }
348
        return null;
305
        return null;
349
    }
306
    }
Lines 355-383 Link Here
355
            return;
312
            return;
356
        }
313
        }
357
        if (StringUtils.hasText(password)) {
314
        if (StringUtils.hasText(password)) {
358
            KEYRING_ACCESS.post(new Runnable() {
315
            Keyring.save(passwordKey, password.toCharArray(),
359
                @Override
316
                    NbBundle.getMessage(RemoteConfiguration.class, "MSG_PasswordFor", getDisplayName(), type));
360
                public void run() {
317
            // remove old password key
361
                    Keyring.save(passwordKey, password.toCharArray(),
318
            Keyring.delete(deprecatedPasswordKey);
362
                            NbBundle.getMessage(RemoteConfiguration.class, "MSG_PasswordFor", getDisplayName(), type));
363
                    // remove old password key
364
                    Keyring.delete(deprecatedPasswordKey);
365
                }
366
            });
367
        } else {
319
        } else {
368
            deletePassword();
320
            deletePassword();
369
        }
321
        }
370
    }
322
    }
371
323
372
    protected void deletePassword() {
324
    protected void deletePassword() {
373
        KEYRING_ACCESS.post(new Runnable() {
325
        Keyring.delete(passwordKey);
374
            @Override
326
        // remove old password key
375
            public void run() {
327
        Keyring.delete(deprecatedPasswordKey);
376
                Keyring.delete(passwordKey);
377
                // remove old password key
378
                Keyring.delete(deprecatedPasswordKey);
379
            }
380
        });
381
    }
328
    }
382
329
383
}
330
}

Return to bug 206475