OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Rev 180 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 180 Rev 182
1
/*
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 * 
3
 * 
4
 * Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
4
 * Copyright 2011-2019 OpenConcerto, by ILM Informatique. All rights reserved.
5
 * 
5
 * 
6
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
6
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
7
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
7
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
8
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
8
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
9
 * language governing permissions and limitations under the License.
9
 * language governing permissions and limitations under the License.
10
 * 
10
 * 
11
 * When distributing the software, include this License Header Notice in each file.
11
 * When distributing the software, include this License Header Notice in each file.
12
 */
12
 */
13
 
13
 
14
 package org.openconcerto.utils;
14
 package org.openconcerto.utils;
15
 
15
 
16
import org.openconcerto.utils.OSFamily.Unix;
16
import org.openconcerto.utils.OSFamily.Unix;
17
 
17
 
18
import java.io.ByteArrayOutputStream;
18
import java.io.ByteArrayOutputStream;
19
import java.io.File;
19
import java.io.File;
20
import java.io.IOException;
20
import java.io.IOException;
21
import java.io.InputStream;
21
import java.io.InputStream;
22
import java.lang.reflect.Method;
22
import java.lang.reflect.Method;
23
import java.nio.charset.Charset;
23
import java.nio.charset.Charset;
24
import java.util.concurrent.FutureTask;
24
import java.util.concurrent.FutureTask;
25
import java.util.concurrent.RunnableFuture;
25
import java.util.concurrent.RunnableFuture;
26
import java.util.logging.Level;
26
import java.util.logging.Level;
27
import java.util.regex.Matcher;
27
import java.util.regex.Matcher;
28
import java.util.regex.Pattern;
28
import java.util.regex.Pattern;
29
 
29
 
30
import javax.swing.SwingUtilities;
30
import javax.swing.SwingUtilities;
31
import javax.swing.filechooser.FileSystemView;
31
import javax.swing.filechooser.FileSystemView;
32
import javax.xml.parsers.DocumentBuilder;
32
import javax.xml.parsers.DocumentBuilder;
33
import javax.xml.parsers.DocumentBuilderFactory;
33
import javax.xml.parsers.DocumentBuilderFactory;
34
 
34
 
35
import org.w3c.dom.Element;
35
import org.w3c.dom.Element;
36
import org.w3c.dom.NodeList;
36
import org.w3c.dom.NodeList;
37
 
37
 
38
import net.jcip.annotations.GuardedBy;
38
import net.jcip.annotations.GuardedBy;
39
import net.jcip.annotations.ThreadSafe;
39
import net.jcip.annotations.ThreadSafe;
40
 
40
 
41
/**
41
/**
42
 * A desktop environment like Gnome or MacOS.
42
 * A desktop environment like Gnome or MacOS.
43
 * 
43
 * 
44
 * @author Sylvain CUAZ
44
 * @author Sylvain CUAZ
45
 * @see #getDE()
45
 * @see #getDE()
46
 */
46
 */
47
@ThreadSafe
47
@ThreadSafe
48
public abstract class DesktopEnvironment {
48
public abstract class DesktopEnvironment {
49
 
49
 
50
    static public final class Gnome extends DesktopEnvironment {
50
    static public final class Gnome extends DesktopEnvironment {
51
 
51
 
52
        static private final String getTextContent(final Element parentElem, final String childName) {
52
        static private final String getTextContent(final Element parentElem, final String childName) {
53
            final NodeList children = parentElem.getElementsByTagName(childName);
53
            final NodeList children = parentElem.getElementsByTagName(childName);
54
            if (children.getLength() != 1)
54
            if (children.getLength() != 1)
55
                throw new IllegalStateException("Not one child " + childName + " in " + parentElem);
55
                throw new IllegalStateException("Not one child " + childName + " in " + parentElem);
56
            return children.item(0).getTextContent();
56
            return children.item(0).getTextContent();
57
        }
57
        }
58
 
58
 
59
        private final String name;
59
        private final String name;
60
 
60
 
61
        public Gnome(final String name) {
61
        public Gnome(final String name) {
62
            this.name = name;
62
            this.name = name;
63
        }
63
        }
64
 
64
 
65
        @Override
65
        @Override
66
        protected String findVersion() {
66
        protected String findVersion() {
67
            try {
67
            try {
68
                if (this.name.equals("gnome")) {
68
                if (this.name.equals("gnome")) {
69
                    // e.g. GNOME gnome-about 2.24.1
69
                    // e.g. GNOME gnome-about 2.24.1
70
                    final String line = cmdSubstitution(Runtime.getRuntime().exec(new String[] { "gnome-about", "--version" }));
70
                    final String line = cmdSubstitution(Runtime.getRuntime().exec(new String[] { "gnome-about", "--version" }));
71
                    final String[] words = line.split(" ");
71
                    final String[] words = line.split(" ");
72
                    return words[words.length - 1];
72
                    return words[words.length - 1];
73
                } else if (this.name.equals("gnome3")) {
73
                } else if (this.name.equals("gnome3")) {
74
                    final DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
74
                    final DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
75
                    // <gnome-version>
75
                    // <gnome-version>
76
                    // <platform>3</platform>
76
                    // <platform>3</platform>
77
                    // <minor>18</minor>
77
                    // <minor>18</minor>
78
                    // <micro>2</micro>
78
                    // <micro>2</micro>
79
                    // </gnome-version>
79
                    // </gnome-version>
80
                    final Element root = builder.parse(new File("/usr/share/gnome/gnome-version.xml")).getDocumentElement();
80
                    final Element root = builder.parse(new File("/usr/share/gnome/gnome-version.xml")).getDocumentElement();
81
                    return getTextContent(root, "platform") + '.' + getTextContent(root, "minor") + '.' + getTextContent(root, "micro");
81
                    return getTextContent(root, "platform") + '.' + getTextContent(root, "minor") + '.' + getTextContent(root, "micro");
82
                } else {
82
                } else {
83
                    throw new IllegalStateException("unknown name : " + this.name);
83
                    throw new IllegalStateException("unknown name : " + this.name);
84
                }
84
                }
85
            } catch (Exception e) {
85
            } catch (Exception e) {
86
                e.printStackTrace();
86
                e.printStackTrace();
87
                return null;
87
                return null;
88
            }
88
            }
89
        }
89
        }
90
    }
90
    }
91
 
91
 
92
    static public final class MATE extends DesktopEnvironment {
92
    static public final class MATE extends DesktopEnvironment {
93
 
93
 
94
        @Override
94
        @Override
95
        protected String findVersion() {
95
        protected String findVersion() {
96
            try {
96
            try {
97
                // e.g. GNOME gnome-about 2.24.1
97
                // e.g. GNOME gnome-about 2.24.1
98
                final String line = cmdSubstitution(Runtime.getRuntime().exec(new String[] { "mate-about", "--version" }));
98
                final String line = cmdSubstitution(Runtime.getRuntime().exec(new String[] { "mate-about", "--version" }));
99
                final String[] words = line.split(" ");
99
                final String[] words = line.split(" ");
100
                return words[words.length - 1];
100
                return words[words.length - 1];
101
            } catch (Exception e) {
101
            } catch (Exception e) {
102
                e.printStackTrace();
102
                e.printStackTrace();
103
                return null;
103
                return null;
104
            }
104
            }
105
        }
105
        }
106
    }
106
    }
107
 
107
 
108
    static public final class KDE extends DesktopEnvironment {
108
    static public final class KDE extends DesktopEnvironment {
109
 
109
 
110
        private static final Pattern versionPattern = Pattern.compile("^KDE: (.*)$", Pattern.MULTILINE);
110
        private static final Pattern versionPattern = Pattern.compile("^KDE: (.*)$", Pattern.MULTILINE);
111
 
111
 
112
        @Override
112
        @Override
113
        protected String findVersion() {
113
        protected String findVersion() {
114
            try {
114
            try {
115
                // Qt: 3.3.8b
115
                // Qt: 3.3.8b
116
                // KDE: 3.5.10
116
                // KDE: 3.5.10
117
                // kde-config: 1.0
117
                // kde-config: 1.0
118
                final String line = cmdSubstitution(Runtime.getRuntime().exec(new String[] { "kde-config", "--version" }));
118
                final String line = cmdSubstitution(Runtime.getRuntime().exec(new String[] { "kde-config", "--version" }));
119
                final Matcher matcher = versionPattern.matcher(line);
119
                final Matcher matcher = versionPattern.matcher(line);
120
                matcher.find();
120
                matcher.find();
121
                return matcher.group(1);
121
                return matcher.group(1);
122
            } catch (Exception e) {
122
            } catch (Exception e) {
123
                e.printStackTrace();
123
                e.printStackTrace();
124
                return null;
124
                return null;
125
            }
125
            }
126
        }
126
        }
127
    }
127
    }
128
 
128
 
129
    static public final class XFCE extends DesktopEnvironment {
129
    static public final class XFCE extends DesktopEnvironment {
130
        // xfce4-about 4.11.1 (Xfce 4.10)
130
        // xfce4-about 4.11.1 (Xfce 4.10)
131
        // Copyright (c) 2008-2011
131
        // Copyright (c) 2008-2011
132
        private static final Pattern versionPattern = Pattern.compile("^xfce4-about.+\\(\\p{Alnum}+\\p{Blank}+(.+)\\)$", Pattern.MULTILINE);
132
        private static final Pattern versionPattern = Pattern.compile("^xfce4-about.+\\(\\p{Alnum}+\\p{Blank}+(.+)\\)$", Pattern.MULTILINE);
133
 
133
 
134
        @Override
134
        @Override
135
        protected String findVersion() {
135
        protected String findVersion() {
136
            try {
136
            try {
137
                final String line = cmdSubstitution(Runtime.getRuntime().exec(new String[] { "xfce4-about", "--version" }));
137
                final String line = cmdSubstitution(Runtime.getRuntime().exec(new String[] { "xfce4-about", "--version" }));
138
                final Matcher matcher = versionPattern.matcher(line);
138
                final Matcher matcher = versionPattern.matcher(line);
139
                matcher.find();
139
                matcher.find();
140
                return matcher.group(1);
140
                return matcher.group(1);
141
            } catch (Exception e) {
141
            } catch (Exception e) {
142
                e.printStackTrace();
142
                e.printStackTrace();
143
                return null;
143
                return null;
144
            }
144
            }
145
        }
145
        }
146
    }
146
    }
147
 
147
 
148
    static public final class Unknown extends DesktopEnvironment {
148
    static public final class Unknown extends DesktopEnvironment {
149
        @Override
149
        @Override
150
        protected String findVersion() {
150
        protected String findVersion() {
151
            return "";
151
            return "";
152
        }
152
        }
153
    }
153
    }
154
 
154
 
155
    static private class DEisOS extends DesktopEnvironment {
155
    static private class DEisOS extends DesktopEnvironment {
156
        @Override
156
        @Override
157
        protected String findVersion() {
157
        protected String findVersion() {
158
            return System.getProperty("os.version");
158
            return System.getProperty("os.version");
159
        }
159
        }
160
    }
160
    }
161
 
161
 
162
    static public final class Windows extends DEisOS {
162
    static public final class Windows extends DEisOS {
163
        static private boolean needsQuoting(String s) {
-
 
164
            final int len = s.length();
-
 
165
            if (len == 0) // empty string have to be quoted
-
 
166
                return true;
-
 
167
            for (int i = 0; i < len; i++) {
-
 
168
                switch (s.charAt(i)) {
-
 
169
                case ' ':
-
 
170
                case '\t':
-
 
171
                case '\\':
-
 
172
                case '"':
-
 
173
                    return true;
-
 
174
                }
-
 
175
            }
-
 
176
            return false;
-
 
177
        }
-
 
178
 
-
 
179
        // on Windows program themselves are required to parse the command line, thus a lot of them
-
 
180
        // do it differently, see http://www.autohotkey.net/~deleyd/parameters/parameters.htm
-
 
181
 
-
 
182
        static private final Pattern quotePatrn = Pattern.compile("([\\\\]*)\"");
-
 
183
        static private final Pattern endSlashPatrn = Pattern.compile("([\\\\]*)\\z");
-
 
184
 
-
 
185
        // see http://bugs.sun.com/view_bug.do?bug_id=6468220
-
 
186
        // e.g. find.exe, choice.exe
-
 
187
        public String quoteParamForMsftC(String s) {
-
 
188
            if (!needsQuoting(s))
-
 
189
                return s;
-
 
190
            if (s.length() > 0) {
-
 
191
                // replace '(\*)"' by '$1$1\"', e.g. '\quote " \"' by '\quote \" \\\"'
-
 
192
                // $1 needed so that the backslash we add isn't escaped itself by a preceding
-
 
193
                // backslash
-
 
194
                s = quotePatrn.matcher(s).replaceAll("$1$1\\\\\"");
-
 
195
                // replace '(\*)\z' by '$1$1', e.g. 'foo\' by 'foo\\'
-
 
196
                // needed to not escape closing quote
-
 
197
                s = endSlashPatrn.matcher(s).replaceAll("$1$1");
-
 
198
            }
-
 
199
            return '"' + s + '"';
-
 
200
        }
-
 
201
 
-
 
202
        // e.g. bash.exe
163
        // e.g. bash.exe
203
        public String quoteParamForGCC(String s) {
164
        public String quoteParamForGCC(String s) {
204
            return StringUtils.doubleQuote(s);
165
            return StringUtils.doubleQuote(s);
205
        }
166
        }
206
 
-
 
207
        public String quoteParamForScript(final String s) {
-
 
208
            if (s.indexOf('"') >= 0)
-
 
209
                throw new IllegalArgumentException("Can not pass a double quote as part of a parameter");
-
 
210
            return '"' + s + '"';
-
 
211
        }
-
 
212
 
-
 
213
        @Override
-
 
214
        public String quoteParamForExec(final String s) {
-
 
215
            return quoteParamForMsftC(s);
-
 
216
        }
-
 
217
    }
167
    }
218
 
168
 
219
    static public final class Mac extends DEisOS {
169
    static public final class Mac extends DEisOS {
220
 
170
 
221
        // From CarbonCore/Folders.h
171
        // From CarbonCore/Folders.h
222
        public static final String kDocumentsDirectory = "docs";
172
        public static final String kDocumentsDirectory = "docs";
223
        public static final String kPreferencesDirectory = "pref";
173
        public static final String kPreferencesDirectory = "pref";
224
        private static Class<?> FileManagerClass;
174
        private static Class<?> FileManagerClass;
225
        private static Short kUserDomain;
175
        private static Short kUserDomain;
226
        private static Method OSTypeToInt;
176
        private static Method OSTypeToInt;
227
 
177
 
228
        private static Class<?> getFileManagerClass() {
178
        private static Class<?> getFileManagerClass() {
229
            if (FileManagerClass == null) {
179
            if (FileManagerClass == null) {
230
                try {
180
                try {
231
                    FileManagerClass = Class.forName("com.apple.eio.FileManager");
181
                    FileManagerClass = Class.forName("com.apple.eio.FileManager");
232
                    OSTypeToInt = FileManagerClass.getMethod("OSTypeToInt", String.class);
182
                    OSTypeToInt = FileManagerClass.getMethod("OSTypeToInt", String.class);
233
                    kUserDomain = (Short) FileManagerClass.getField("kUserDomain").get(null);
183
                    kUserDomain = (Short) FileManagerClass.getField("kUserDomain").get(null);
234
                } catch (RuntimeException e) {
184
                } catch (RuntimeException e) {
235
                    throw e;
185
                    throw e;
236
                } catch (Exception e) {
186
                } catch (Exception e) {
237
                    throw new IllegalStateException(e);
187
                    throw new IllegalStateException(e);
238
                }
188
                }
239
            }
189
            }
240
            return FileManagerClass;
190
            return FileManagerClass;
241
        }
191
        }
242
 
192
 
243
        @Override
193
        @Override
244
        public File getDocumentsFolder() {
194
        public File getDocumentsFolder() {
245
            return new File(System.getProperty("user.home"), "Documents/");
195
            return new File(System.getProperty("user.home"), "Documents/");
246
        }
196
        }
247
 
197
 
248
        // There was a warning until JRE v16, now "--add-exports
198
        // There was a warning until JRE v16, now "--add-exports
249
        // java.desktop/com.apple.eio=ALL-UNNAMED" is needed. Further this needs the EDT which is
199
        // java.desktop/com.apple.eio=ALL-UNNAMED" is needed. Further this needs the EDT which is
250
        // undesirable just to get some paths.
200
        // undesirable just to get some paths.
251
        // https://bugs.openjdk.java.net/browse/JDK-8187981
201
        // https://bugs.openjdk.java.net/browse/JDK-8187981
252
        @Deprecated
202
        @Deprecated
253
        public File getFolder(String type) {
203
        public File getFolder(String type) {
254
            try {
204
            try {
255
                final Method findFolder = getFileManagerClass().getMethod("findFolder", Short.TYPE, Integer.TYPE);
205
                final Method findFolder = getFileManagerClass().getMethod("findFolder", Short.TYPE, Integer.TYPE);
256
                final RunnableFuture<String> f = new FutureTask<>(() -> (String) findFolder.invoke(null, kUserDomain, OSTypeToInt.invoke(null, type)));
206
                final RunnableFuture<String> f = new FutureTask<>(() -> (String) findFolder.invoke(null, kUserDomain, OSTypeToInt.invoke(null, type)));
257
                // EDT needed at least for JRE v14-16 on macOS 10.15, otherwise the VM crashes :
207
                // EDT needed at least for JRE v14-16 on macOS 10.15, otherwise the VM crashes :
258
                // Problematic frame: __NSAssertMainEventQueueIsCurrentEventQueue_block_invoke or
208
                // Problematic frame: __NSAssertMainEventQueueIsCurrentEventQueue_block_invoke or
259
                // "The current event queue and the main event queue are not the same. This is
209
                // "The current event queue and the main event queue are not the same. This is
260
                // probably because _TSGetMainThread was called for the first time off the main
210
                // probably because _TSGetMainThread was called for the first time off the main
261
                // thread."
211
                // thread."
262
                if (SwingUtilities.isEventDispatchThread())
212
                if (SwingUtilities.isEventDispatchThread())
263
                    f.run();
213
                    f.run();
264
                else
214
                else
265
                    SwingUtilities.invokeLater(f);
215
                    SwingUtilities.invokeLater(f);
266
                final String path = f.get();
216
                final String path = f.get();
267
                return new File(path);
217
                return new File(path);
268
            } catch (RuntimeException e) {
218
            } catch (RuntimeException e) {
269
                throw e;
219
                throw e;
270
            } catch (Exception e) {
220
            } catch (Exception e) {
271
                throw new IllegalStateException(e);
221
                throw new IllegalStateException(e);
272
            }
222
            }
273
        }
223
        }
274
 
224
 
275
        public File getAppDir(final String bundleID) throws IOException {
225
        public File getAppDir(final String bundleID) throws IOException {
276
            // we used to ask for the URL of the application file but since 10.7 it returns a
226
            // we used to ask for the URL of the application file but since 10.7 it returns a
277
            // file reference URL like "file:///.file/id=6723689.35865"
227
            // file reference URL like "file:///.file/id=6723689.35865"
278
            final ProcessBuilder processBuilder = new ProcessBuilder("osascript", "-e",
228
            final ProcessBuilder processBuilder = new ProcessBuilder("osascript", "-e",
279
                    "tell application id \"com.apple.Finder\" to POSIX path of (application file id \"" + bundleID + "\" as string)");
229
                    "tell application id \"com.apple.Finder\" to POSIX path of (application file id \"" + bundleID + "\" as string)");
280
            // if not found prints nothing to out and a cryptic error to the standard error stream
230
            // if not found prints nothing to out and a cryptic error to the standard error stream
281
            final String dir = cmdSubstitution(processBuilder.start()).trim();
231
            final String dir = cmdSubstitution(processBuilder.start()).trim();
282
            return dir.length() == 0 ? null : new File(dir);
232
            return dir.length() == 0 ? null : new File(dir);
283
        }
233
        }
284
    }
234
    }
285
 
235
 
286
    /**
236
    /**
287
     * Execute the passed command and test its return code.
237
     * Execute the passed command and test its return code.
288
     * 
238
     * 
289
     * @param command the command to {@link Runtime#exec(String[]) execute}.
239
     * @param command the command to {@link Runtime#exec(String[]) execute}.
290
     * @return <code>false</code> if the {@link Process#waitFor() return code} is not 0 or an
240
     * @return <code>false</code> if the {@link Process#waitFor() return code} is not 0 or an
291
     *         exception is thrown.
241
     *         exception is thrown.
292
     * @throws RTInterruptedException if this is interrupted while waiting.
242
     * @throws RTInterruptedException if this is interrupted while waiting.
293
     */
243
     */
294
    public static final boolean test(final String... command) throws RTInterruptedException {
244
    public static final boolean test(final String... command) throws RTInterruptedException {
295
        try {
245
        try {
296
            return Runtime.getRuntime().exec(command).waitFor() == 0;
246
            return Runtime.getRuntime().exec(command).waitFor() == 0;
297
        } catch (InterruptedException e) {
247
        } catch (InterruptedException e) {
298
            throw new RTInterruptedException(e);
248
            throw new RTInterruptedException(e);
299
        } catch (IOException e) {
249
        } catch (IOException e) {
300
            Log.get().finer(e.getLocalizedMessage());
250
            Log.get().finer(e.getLocalizedMessage());
301
            return false;
251
            return false;
302
        }
252
        }
303
    }
253
    }
304
 
254
 
305
    public final static String cmdSubstitution(Process p) throws IOException {
255
    public final static String cmdSubstitution(Process p) throws IOException {
306
        return cmdSubstitution(p, null);
256
        return cmdSubstitution(p, null);
307
    }
257
    }
308
 
258
 
309
    public final static String cmdSubstitution(final Process p, final Charset encoding) throws IOException {
259
    public final static String cmdSubstitution(final Process p, final Charset encoding) throws IOException {
310
        final ByteArrayOutputStream out = new ByteArrayOutputStream(100 * 1024);
260
        final ByteArrayOutputStream out = new ByteArrayOutputStream(100 * 1024);
311
        // some programs won't write anything until they read everything (e.g. powershell.exe)
261
        // some programs won't write anything until they read everything (e.g. powershell.exe)
312
        p.getOutputStream().close();
262
        p.getOutputStream().close();
313
        p.getErrorStream().close();
263
        p.getErrorStream().close();
314
        StreamUtils.copy(p.getInputStream(), out);
264
        StreamUtils.copy(p.getInputStream(), out);
315
        p.getInputStream().close();
265
        p.getInputStream().close();
316
        return encoding == null ? out.toString() : out.toString(encoding.name());
266
        return encoding == null ? out.toString() : out.toString(encoding.name());
317
    }
267
    }
318
 
268
 
319
    private static final String detectXDG() {
269
    private static final String detectXDG() {
320
        String res = null;
270
        String res = null;
321
        InputStream scriptIns = null;
271
        InputStream scriptIns = null;
322
        try {
272
        try {
323
            scriptIns = DesktopEnvironment.class.getResourceAsStream("DesktopEnvironmentXDG.sh");
273
            scriptIns = DesktopEnvironment.class.getResourceAsStream("DesktopEnvironmentXDG.sh");
324
            final Process ps = new ProcessBuilder("sh").start();
274
            final Process ps = new ProcessBuilder("sh").start();
325
            ps.getErrorStream().close();
275
            ps.getErrorStream().close();
326
            StreamUtils.copy(scriptIns, ps.getOutputStream());
276
            StreamUtils.copy(scriptIns, ps.getOutputStream());
327
            ps.getOutputStream().close();
277
            ps.getOutputStream().close();
328
            res = FileUtils.readUTF8(ps.getInputStream()).trim();
278
            res = FileUtils.readUTF8(ps.getInputStream()).trim();
329
            ps.getInputStream().close();
279
            ps.getInputStream().close();
330
            if (ps.waitFor() != 0)
280
            if (ps.waitFor() != 0)
331
                throw new IllegalStateException("Not OK : " + ps.exitValue());
281
                throw new IllegalStateException("Not OK : " + ps.exitValue());
332
        } catch (Exception e) {
282
        } catch (Exception e) {
333
            Log.get().fine(e.getLocalizedMessage());
283
            Log.get().fine(e.getLocalizedMessage());
334
        } finally {
284
        } finally {
335
            if (scriptIns != null) {
285
            if (scriptIns != null) {
336
                try {
286
                try {
337
                    scriptIns.close();
287
                    scriptIns.close();
338
                } catch (IOException e) {
288
                } catch (IOException e) {
339
                    e.printStackTrace();
289
                    e.printStackTrace();
340
                }
290
                }
341
            }
291
            }
342
        }
292
        }
343
        return res;
293
        return res;
344
    }
294
    }
345
 
295
 
346
    private static final DesktopEnvironment detectDE() {
296
    private static final DesktopEnvironment detectDE() {
347
        final OSFamily os = OSFamily.getInstance();
297
        final OSFamily os = OSFamily.getInstance();
348
        if (os == OSFamily.Windows) {
298
        if (os == OSFamily.Windows) {
349
            return new Windows();
299
            return new Windows();
350
        } else if (os == OSFamily.Mac) {
300
        } else if (os == OSFamily.Mac) {
351
            return new Mac();
301
            return new Mac();
352
        } else if (os instanceof Unix) {
302
        } else if (os instanceof Unix) {
353
            final String de = detectXDG();
303
            final String de = detectXDG();
354
            if (de.equals("xfce"))
304
            if (de.equals("xfce"))
355
                return new XFCE();
305
                return new XFCE();
356
            else if (de.equals("mate"))
306
            else if (de.equals("mate"))
357
                return new MATE();
307
                return new MATE();
358
            else if (de.equals("kde"))
308
            else if (de.equals("kde"))
359
                return new KDE();
309
                return new KDE();
360
            else if (de.startsWith("gnome"))
310
            else if (de.startsWith("gnome"))
361
                return new Gnome(de);
311
                return new Gnome(de);
362
        }
312
        }
363
        return new Unknown();
313
        return new Unknown();
364
    }
314
    }
365
 
315
 
366
    @GuardedBy("DesktopEnvironment.class")
316
    @GuardedBy("DesktopEnvironment.class")
367
    private static DesktopEnvironment DE = null;
317
    private static DesktopEnvironment DE = null;
368
 
318
 
369
    public synchronized static final DesktopEnvironment getDE() {
319
    public synchronized static final DesktopEnvironment getDE() {
370
        if (DE == null) {
320
        if (DE == null) {
371
            DE = detectDE();
321
            DE = detectDE();
372
        }
322
        }
373
        return DE;
323
        return DE;
374
    }
324
    }
375
 
325
 
376
    public synchronized static final void resetDE() {
326
    public synchronized static final void resetDE() {
377
        DE = null;
327
        DE = null;
378
    }
328
    }
379
 
329
 
380
    @GuardedBy("this")
330
    @GuardedBy("this")
381
    private String version;
331
    private String version;
382
 
332
 
383
    private DesktopEnvironment() {
333
    private DesktopEnvironment() {
384
        this.version = null;
334
        this.version = null;
385
    }
335
    }
386
 
336
 
387
    protected abstract String findVersion();
337
    protected abstract String findVersion();
388
 
338
 
389
    public synchronized final String getVersion() {
339
    public synchronized final String getVersion() {
390
        if (this.version == null)
340
        if (this.version == null)
391
            this.version = this.findVersion();
341
            this.version = this.findVersion();
392
        return this.version;
342
        return this.version;
393
    }
343
    }
394
 
344
 
395
    // where to write user-visible files (e.g. spreadsheets, exports)
345
    // where to write user-visible files (e.g. spreadsheets, exports)
396
    public File getDocumentsFolder() {
346
    public File getDocumentsFolder() {
397
        return FileSystemView.getFileSystemView().getDefaultDirectory();
347
        return FileSystemView.getFileSystemView().getDefaultDirectory();
398
    }
348
    }
399
 
349
 
400
    // on some systems arguments are not passed correctly by ProcessBuilder
350
    // on some systems arguments are not passed correctly by ProcessBuilder
401
    public String quoteParamForExec(String s) {
351
    public final String quoteParamForExec(String s) {
402
        return s;
352
        return Platform.getInstance().getProcessArg(s);
403
    }
353
    }
404
 
354
 
405
    @Override
355
    @Override
406
    public String toString() {
356
    public String toString() {
407
        return "DesktopEnvironment " + this.getClass().getSimpleName();
357
        return "DesktopEnvironment " + this.getClass().getSimpleName();
408
    }
358
    }
409
 
359
 
410
    public static void main(String[] args) {
360
    public static void main(String[] args) {
411
        // removes default
361
        // removes default
412
        LogUtils.rmRootHandlers();
362
        LogUtils.rmRootHandlers();
413
        // add console handler
363
        // add console handler
414
        LogUtils.setUpConsoleHandler();
364
        LogUtils.setUpConsoleHandler();
415
        Log.get().setLevel(Level.FINE);
365
        Log.get().setLevel(Level.FINE);
416
        final DesktopEnvironment de = getDE();
366
        final DesktopEnvironment de = getDE();
417
        System.out.println(de + " version " + de.getVersion());
367
        System.out.println(de + " version " + de.getVersion());
418
    }
368
    }
419
}
369
}