OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

Rev 28 | Rev 80 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
17 ilm 1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
5
 *
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
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.
10
 *
11
 * When distributing the software, include this License Header Notice in each file.
12
 */
13
 
14
 package org.openconcerto.utils;
15
 
16
import java.io.ByteArrayOutputStream;
17
import java.io.File;
18
import java.io.IOException;
19
import java.lang.reflect.Method;
20
import java.util.regex.Matcher;
21
import java.util.regex.Pattern;
22
 
23
import javax.swing.filechooser.FileSystemView;
24
 
25
/**
26
 * A desktop environment like Gnome or MacOS.
27
 *
28
 * @author Sylvain CUAZ
29
 * @see #getDE()
30
 */
31
public abstract class DesktopEnvironment {
32
 
33
    static public final class Gnome extends DesktopEnvironment {
34
 
35
        @Override
36
        protected String findVersion() {
37
            try {
38
                // e.g. GNOME gnome-about 2.24.1
39
                final String line = cmdSubstitution(Runtime.getRuntime().exec(new String[] { "gnome-about", "--version" }));
40
                final String[] words = line.split(" ");
41
                return words[words.length - 1];
42
            } catch (Exception e) {
43
                e.printStackTrace();
44
                return null;
45
            }
46
        }
47
    }
48
 
49
    static public final class KDE extends DesktopEnvironment {
50
 
51
        private static final Pattern versionPattern = Pattern.compile("^KDE: (.*)$", Pattern.MULTILINE);
52
 
53
        @Override
54
        protected String findVersion() {
55
            try {
56
                // Qt: 3.3.8b
57
                // KDE: 3.5.10
58
                // kde-config: 1.0
59
                final String line = cmdSubstitution(Runtime.getRuntime().exec(new String[] { "kde-config", "--version" }));
60
                final Matcher matcher = versionPattern.matcher(line);
61
                matcher.find();
62
                return matcher.group(1);
63
            } catch (Exception e) {
64
                e.printStackTrace();
65
                return null;
66
            }
67
        }
68
    }
69
 
70
    static public final class XFCE extends DesktopEnvironment {
71
 
72
        @Override
73
        protected String findVersion() {
74
            // TODO
75
            return "";
76
        }
77
    }
78
 
79
    static public final class Unknown extends DesktopEnvironment {
80
        @Override
81
        protected String findVersion() {
82
            return "";
83
        }
84
    }
85
 
86
    static private class DEisOS extends DesktopEnvironment {
87
        @Override
88
        protected String findVersion() {
89
            return System.getProperty("os.version");
90
        }
91
    }
92
 
93
    static public final class Windows extends DEisOS {
28 ilm 94
        static private boolean needsQuoting(String s) {
95
            final int len = s.length();
96
            if (len == 0) // empty string have to be quoted
97
                return true;
98
            for (int i = 0; i < len; i++) {
99
                switch (s.charAt(i)) {
100
                case ' ':
101
                case '\t':
102
                case '\\':
103
                case '"':
104
                    return true;
105
                }
106
            }
107
            return false;
108
        }
109
 
61 ilm 110
        // on Windows program themselves are required to parse the command line, thus a lot of them
111
        // do it differently, see http://www.autohotkey.net/~deleyd/parameters/parameters.htm
112
 
113
        static private final Pattern quotePatrn = Pattern.compile("([\\\\]*)\"");
114
        static private final Pattern endSlashPatrn = Pattern.compile("([\\\\]*)\\z");
115
 
28 ilm 116
        // see http://bugs.sun.com/view_bug.do?bug_id=6468220
61 ilm 117
        // e.g. find.exe, choice.exe
118
        public String quoteParamForMsftC(String s) {
28 ilm 119
            if (!needsQuoting(s))
120
                return s;
61 ilm 121
            if (s.length() > 0) {
122
                // replace '(\*)"' by '$1$1\"', e.g. '\quote " \"' by '\quote \" \\\"'
123
                // $1 needed so that the backslash we add isn't escaped itself by a preceding
124
                // backslash
125
                s = quotePatrn.matcher(s).replaceAll("$1$1\\\\\"");
126
                // replace '(\*)\z' by '$1$1', e.g. 'foo\' by 'foo\\'
127
                // needed to not escape closing quote
128
                s = endSlashPatrn.matcher(s).replaceAll("$1$1");
129
            }
130
            return '"' + s + '"';
131
        }
132
 
133
        // e.g. bash.exe
134
        public String quoteParamForGCC(String s) {
28 ilm 135
            return StringUtils.doubleQuote(s);
136
        }
61 ilm 137
 
138
        public String quoteParamForScript(final String s) {
139
            if (s.indexOf('"') >= 0)
140
                throw new IllegalArgumentException("Can not pass a double quote as part of a parameter");
141
            return '"' + s + '"';
142
        }
143
 
144
        @Override
145
        public String quoteParamForExec(final String s) {
146
            return quoteParamForMsftC(s);
147
        }
17 ilm 148
    }
149
 
150
    static public final class Mac extends DEisOS {
151
 
152
        // From CarbonCore/Folders.h
153
        private static final String kDocumentsDirectory = "docs";
154
        private static final String kPreferencesDirectory = "pref";
155
        private static Class<?> FileManagerClass;
156
        private static Short kUserDomain;
157
        private static Method OSTypeToInt;
158
 
159
        private static Class<?> getFileManagerClass() {
160
            if (FileManagerClass == null) {
161
                try {
162
                    FileManagerClass = Class.forName("com.apple.eio.FileManager");
163
                    OSTypeToInt = FileManagerClass.getMethod("OSTypeToInt", String.class);
164
                    kUserDomain = (Short) FileManagerClass.getField("kUserDomain").get(null);
165
                } catch (RuntimeException e) {
166
                    throw e;
167
                } catch (Exception e) {
168
                    throw new IllegalStateException(e);
169
                }
170
            }
171
            return FileManagerClass;
172
        }
173
 
174
        @Override
175
        public File getDocumentsFolder() {
176
            return getFolder(kDocumentsDirectory);
177
        }
178
 
179
        @Override
180
        public File getPreferencesFolder(String appName) {
181
            return new File(getFolder(kPreferencesDirectory), appName);
182
        }
183
 
184
        public File getFolder(String type) {
185
            try {
186
                final Method findFolder = getFileManagerClass().getMethod("findFolder", Short.TYPE, Integer.TYPE);
187
                final String path = (String) findFolder.invoke(null, kUserDomain, OSTypeToInt.invoke(null, type));
188
                return new File(path);
189
            } catch (RuntimeException e) {
190
                throw e;
191
            } catch (Exception e) {
192
                throw new IllegalStateException(e);
193
            }
194
        }
195
 
61 ilm 196
        public File getAppDir(final String bundleID) throws IOException {
197
            // we used to ask for the URL of the application file but since 10.7 it returns a
198
            // file reference URL like "file:///.file/id=6723689.35865"
199
            final ProcessBuilder processBuilder = new ProcessBuilder("osascript", "-e", "tell application id \"com.apple.Finder\" to POSIX path of (application file id \"" + bundleID
200
                    + "\" as string)");
201
            // if not found prints nothing to out and a cryptic error to the standard error stream
202
            final String dir = cmdSubstitution(processBuilder.start()).trim();
203
            return dir.length() == 0 ? null : new File(dir);
204
        }
17 ilm 205
    }
206
 
207
    /**
208
     * Execute the passed command and test its return code.
209
     *
210
     * @param command the command to {@link Runtime#exec(String[]) execute}.
211
     * @return <code>false</code> if the {@link Process#waitFor() return code} is not 0 or an
212
     *         exception is thrown.
213
     * @throws RTInterruptedException if this is interrupted while waiting.
214
     */
215
    public static final boolean test(final String... command) throws RTInterruptedException {
216
        try {
217
            return Runtime.getRuntime().exec(command).waitFor() == 0;
218
        } catch (InterruptedException e) {
219
            throw new RTInterruptedException(e);
220
        } catch (IOException e) {
221
            Log.get().finer(e.getLocalizedMessage());
222
            return false;
223
        }
224
    }
225
 
226
    public final static String cmdSubstitution(Process p) throws IOException {
227
        final ByteArrayOutputStream out = new ByteArrayOutputStream(100 * 1024);
228
        StreamUtils.copy(p.getInputStream(), out);
229
        return out.toString();
230
    }
231
 
232
    private static final DesktopEnvironment detectDE() {
233
        final String os = System.getProperty("os.name");
234
        if (os.startsWith("Windows")) {
235
            return new Windows();
236
        } else if (os.startsWith("Mac OS")) {
237
            return new Mac();
238
        } else if (os.startsWith("Linux")) {
239
            // from redhat xdg-utils 1.0.2-14.20091016cvs
240
            if ("true".equalsIgnoreCase(System.getenv("KDE_FULL_SESSION")))
241
                return new KDE();
242
            else if (System.getenv("GNOME_DESKTOP_SESSION_ID") != null)
243
                return new Gnome();
244
            // the above variable is deprecated, the line below only works for newer gnome
245
            else if (test("dbus-send", "--print-reply", "--dest=org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus.GetNameOwner", "string:org.gnome.SessionManager"))
246
                return new Gnome();
247
            else {
248
                try {
249
                    final String saveMode = cmdSubstitution(Runtime.getRuntime().exec(new String[] { "xprop", "-root", "_DT_SAVE_MODE" }));
250
                    if (saveMode.endsWith(" = \"xfce4\""))
251
                        return new XFCE();
252
                } catch (IOException e) {
253
                    Log.get().fine(e.getLocalizedMessage());
254
                }
255
            }
256
        }
257
        return new Unknown();
258
    }
259
 
260
    private static DesktopEnvironment DE = null;
261
 
262
    public static final DesktopEnvironment getDE() {
263
        if (DE == null) {
264
            DE = detectDE();
265
        }
266
        return DE;
267
    }
268
 
269
    public static final void resetDE() {
270
        DE = null;
271
    }
272
 
273
    private String version;
274
 
275
    private DesktopEnvironment() {
276
        this.version = null;
277
    }
278
 
279
    protected abstract String findVersion();
280
 
281
    public final String getVersion() {
282
        if (this.version == null)
283
            this.version = this.findVersion();
284
        return this.version;
285
    }
286
 
287
    public File getDocumentsFolder() {
288
        return FileSystemView.getFileSystemView().getDefaultDirectory();
289
    }
290
 
291
    public File getPreferencesFolder(final String appName) {
292
        return new File(System.getProperty("user.home"), "." + appName);
293
    }
294
 
28 ilm 295
    // on some systems arguments are not passed correctly by ProcessBuilder
296
    public String quoteParamForExec(String s) {
297
        return s;
298
    }
299
 
17 ilm 300
    @Override
301
    public String toString() {
302
        return "DesktopEnvironment " + this.getClass().getSimpleName();
303
    }
304
 
305
    public static void main(String[] args) {
306
        System.out.println(getDE() + " version " + getDE().getVersion());
307
    }
308
}