OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

Rev 177 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 177 Rev 180
Line 13... Line 13...
13
 
13
 
14
 package org.openconcerto.utils.prog;
14
 package org.openconcerto.utils.prog;
15
 
15
 
16
import org.openconcerto.utils.FileUtils;
16
import org.openconcerto.utils.FileUtils;
17
import org.openconcerto.utils.OSFamily;
17
import org.openconcerto.utils.OSFamily;
-
 
18
import org.openconcerto.utils.OSFamily.Unix;
18
import org.openconcerto.utils.ProcessStreams;
19
import org.openconcerto.utils.ProcessStreams;
19
import org.openconcerto.utils.PropertiesUtils;
20
import org.openconcerto.utils.PropertiesUtils;
20
 
21
 
21
import java.io.File;
22
import java.io.File;
22
import java.io.IOException;
23
import java.io.IOException;
Line 38... Line 39...
38
 * @author Sylvain
39
 * @author Sylvain
39
 * @see #launch(String, List)
40
 * @see #launch(String, List)
40
 */
41
 */
41
public abstract class VMLauncher {
42
public abstract class VMLauncher {
42
 
43
 
-
 
44
    private static final String PROPERTIES_EXT = ".properties";
43
    /**
45
    /**
44
     * Boolean system property, if set to <code>true</code> then {@link #restart(Class, List)} will
46
     * Boolean system property, if set to <code>true</code> then {@link #restart(Class, List)} will
45
     * simply return <code>null</code>. Useful e.g. when using IDE launch configuration (to debug).
47
     * simply return <code>null</code>. Useful e.g. when using IDE launch configuration (to debug).
46
     */
48
     */
47
    static public final String NO_RESTART = "vm.noRestart";
49
    static public final String NO_RESTART = "vm.noRestart";
48
 
50
 
-
 
51
    // Explicitly passed to jpackage
-
 
52
    static public final String APPDIR_SYSPROP = "jpackage.app.dir";
-
 
53
 
-
 
54
    // Automatically set by the jpackage launcher (could be set explicitly using --java-options
-
 
55
    // '-Djpackage.app-path=$APPDIR/../../bin/launcher' if jpackage ever changes that)
-
 
56
    static public final String APP_EXE_SYSPROP = "jpackage.app-path";
-
 
57
 
-
 
58
    // The path to the app directory with the jar
-
 
59
    public static final File getJPackageAppDir() {
-
 
60
        final String appPath = System.getProperty(APPDIR_SYSPROP, "");
-
 
61
        return appPath.isEmpty() ? null : new File(appPath);
-
 
62
    }
-
 
63
 
-
 
64
    // The path to the executable
-
 
65
    private static final String getJPackageAppPath() {
-
 
66
        final String appPath = System.getProperty(APP_EXE_SYSPROP, "");
-
 
67
        return appPath.isEmpty() ? null : appPath;
-
 
68
    }
-
 
69
 
-
 
70
    private static final void addJPackageSystemPropertyArgument(final List<String> args, final String propName) {
-
 
71
        final String arg = getJPackageSystemPropertyArg(propName);
-
 
72
        if (arg != null)
-
 
73
            args.add(arg);
-
 
74
    }
-
 
75
 
-
 
76
    private static final String getJPackageSystemPropertyArg(final String propName) {
-
 
77
        final String val = System.getProperty(propName);
-
 
78
        if (val == null)
-
 
79
            return null;
-
 
80
        return "-D" + propName + "=" + val;
-
 
81
    }
-
 
82
 
49
    private static NativeLauncherFinder getNativeAppLauncher() {
83
    private static NativeLauncherFinder getNativeAppLauncher() {
50
        final OSFamily os = OSFamily.getInstance();
84
        final OSFamily os = OSFamily.getInstance();
51
        final NativeLauncherFinder l;
85
        final NativeLauncherFinder l;
52
        if (os.equals(OSFamily.Windows)) {
86
        if (os.equals(OSFamily.Windows)) {
53
            l = new WinLauncherFinder();
87
            l = new WinLauncherFinder();
54
        } else if (os.equals(OSFamily.Mac)) {
88
        } else if (os.equals(OSFamily.Mac)) {
55
            l = new MacLauncherFinder();
89
            l = new MacLauncherFinder();
-
 
90
        } else if (os instanceof Unix) {
-
 
91
            l = new UnixLauncherFinder();
56
        } else {
92
        } else {
57
            l = UnknownLauncherFinder;
93
            l = UnknownLauncherFinder;
58
        }
94
        }
59
        return l;
95
        return l;
60
    }
96
    }
Line 96... Line 132...
96
        /**
132
        /**
97
         * The command to launch this application with the passed arguments.
133
         * The command to launch this application with the passed arguments.
98
         * 
134
         * 
99
         * @param args the program arguments.
135
         * @param args the program arguments.
100
         * @return the command.
136
         * @return the command.
-
 
137
         * @throws UnsupportedOperationException if {@link #getAppPath()} returns <code>null</code>.
101
         */
138
         */
-
 
139
        public final List<String> getCommand(final List<String> args) throws UnsupportedOperationException {
-
 
140
            final String appPath = this.getAppPath();
-
 
141
            if (appPath == null)
-
 
142
                throw new UnsupportedOperationException();
-
 
143
 
-
 
144
            return getCommand(appPath, args);
-
 
145
        }
-
 
146
 
102
        public abstract List<String> getCommand(final List<String> args);
147
        protected List<String> getCommand(final String appPath, final List<String> args) {
-
 
148
            final List<String> command = new ArrayList<String>(4 + args.size());
-
 
149
            command.add(appPath);
-
 
150
            command.addAll(args);
-
 
151
            return command;
-
 
152
        }
103
    }
153
    }
104
 
154
 
105
    private static class MacLauncherFinder extends NativeLauncherFinder {
155
    private static class MacLauncherFinder extends NativeLauncherFinder {
106
        private static final String APP_EXT = ".app";
156
        private static final String APP_EXT = ".app";
-
 
157
        // jpackage uses "Contents/app"
107
        private static final Pattern MAC_PATTERN = Pattern.compile(Pattern.quote(APP_EXT) + "/Contents/Resources(/Java)?/[^/]+\\.jar$");
158
        private static final Pattern MAC_PATTERN = Pattern.compile(Pattern.quote(APP_EXT) + "/Contents/(Resources(/Java)?|app)/[^/]+\\.jar$");
108
 
159
 
109
        @Override
160
        @Override
110
        public String getAppPath() {
161
        public String getAppPath() {
111
            final Matcher matcher = MAC_PATTERN.matcher(this.getFirstItem());
162
            final Matcher matcher = MAC_PATTERN.matcher(this.getFirstItem());
112
            if (matcher.matches()) {
163
            if (matcher.matches()) {
113
                final String appPath = getFirstItem().substring(0, matcher.start() + APP_EXT.length());
164
                final String appPath = getFirstItem().substring(0, matcher.start() + APP_EXT.length());
114
                final File contentsDir = new File(appPath, "Contents");
165
                final File contentsDir = new File(appPath, "Contents");
115
                final List<String> bundleContent = Arrays.asList(contentsDir.list());
-
 
116
                if (bundleContent.contains("Info.plist") && bundleContent.contains("PkgInfo") && new File(contentsDir, "MacOS").isDirectory())
166
                if (new File(contentsDir, "Info.plist").isFile() && new File(contentsDir, "MacOS").isDirectory())
117
                    return appPath;
167
                    return appPath;
118
            }
168
            }
119
            return null;
169
            return null;
120
        }
170
        }
121
 
171
 
122
        @Override
172
        @Override
123
        public List<String> getCommand(List<String> args) {
173
        protected List<String> getCommand(String appPath, List<String> args) {
124
            final List<String> command = new ArrayList<String>(4 + args.size());
174
            final List<String> command = new ArrayList<String>(4 + args.size());
125
            command.add("open");
175
            command.add("open");
126
            // since we restarting we need to launch a new instance of us
176
            // since we restarting we need to launch a new instance of us
127
            command.add("-n");
177
            command.add("-n");
128
            command.add(getAppPath());
178
            command.add(appPath);
129
            command.add("--args");
179
            command.add("--args");
130
            command.addAll(args);
180
            command.addAll(args);
131
            return command;
181
            return command;
132
        }
182
        }
133
    }
183
    }
Line 139... Line 189...
139
            if (this.getFirstItem().endsWith(".exe"))
189
            if (this.getFirstItem().endsWith(".exe"))
140
                return getFirstItem();
190
                return getFirstItem();
141
            else
191
            else
142
                return null;
192
                return null;
143
        }
193
        }
-
 
194
    }
-
 
195
 
-
 
196
    private static class UnixLauncherFinder extends NativeLauncherFinder {
-
 
197
 
-
 
198
        private final String jpackageApp;
-
 
199
 
-
 
200
        public UnixLauncherFinder() {
-
 
201
            this.jpackageApp = getJPackageAppPath();
-
 
202
        }
144
 
203
 
145
        @Override
204
        @Override
146
        public List<String> getCommand(List<String> args) {
-
 
147
            final List<String> command = new ArrayList<String>(4 + args.size());
-
 
148
            command.add(getAppPath());
205
        public String getAppPath() {
149
            command.addAll(args);
-
 
150
            return command;
206
            return this.jpackageApp;
151
        }
207
        }
152
    }
208
    }
153
 
209
 
154
    private static final NativeLauncherFinder UnknownLauncherFinder = new NativeLauncherFinder() {
210
    private static final NativeLauncherFinder UnknownLauncherFinder = new NativeLauncherFinder() {
155
        @Override
211
        @Override
156
        public String getAppPath() {
212
        public String getAppPath() {
157
            return null;
213
            return null;
158
        }
214
        }
159
 
-
 
160
        @Override
-
 
161
        public List<String> getCommand(List<String> args) {
-
 
162
            throw new UnsupportedOperationException();
-
 
163
        }
-
 
164
    };
215
    };
165
 
216
 
166
    public static final Process restart(final Class<?> mainClass, final String... args) throws IOException {
217
    public static final Process restart(final Class<?> mainClass, final String... args) throws IOException {
167
        return restart(mainClass, Arrays.asList(args));
218
        return restart(mainClass, Arrays.asList(args));
168
    }
219
    }
Line 219... Line 270...
219
 
270
 
220
    public static final String ENV_VMARGS = "JAVA_VMARGS";
271
    public static final String ENV_VMARGS = "JAVA_VMARGS";
221
    public static final String PROPS_VMARGS = "VMARGS";
272
    public static final String PROPS_VMARGS = "VMARGS";
222
    public static final String ENV_PROGARGS = "JAVA_PROGARGS";
273
    public static final String ENV_PROGARGS = "JAVA_PROGARGS";
223
 
274
 
-
 
275
    // Don't split on spaces to avoid dealing with quotes or escapes : vmArgs=-Dfoo bar\t-DotherProp
224
    // handle DOS, Mac and Unix newlines
276
    // Handle DOS, Mac and Unix newlines (and tabs).
225
    private static final Pattern NL = Pattern.compile("\\p{Cntrl}+");
277
    private static final Pattern NL = Pattern.compile("\\p{Cntrl}+");
226
 
278
 
227
    private File wd;
279
    private File wd;
228
 
280
 
229
    public VMLauncher() {
281
    public VMLauncher() {
230
        this.wd = null;
282
        this.wd = null;
231
    }
283
    }
232
 
284
 
233
    public final File getLauncherWD() {
285
    public final File getLauncherWD() {
234
        if (this.wd == null) {
286
        if (this.wd == null) {
-
 
287
            final File appDir = getJPackageAppDir();
-
 
288
            if (appDir == null) {
235
            final NativeLauncherFinder nativeAppLauncher = getNativeAppLauncher();
289
                final NativeLauncherFinder nativeAppLauncher = getNativeAppLauncher();
236
            final String appPath = nativeAppLauncher.getAppPath();
290
                final String appPath = nativeAppLauncher.getAppPath();
237
            if (appPath != null)
291
                if (appPath != null)
238
                this.wd = new File(appPath).getAbsoluteFile().getParentFile();
292
                    this.wd = new File(appPath).getAbsoluteFile().getParentFile();
239
            // when launched with -jar there's only one item
293
                // when launched with -jar there's only one item
240
            else if (nativeAppLauncher.getFirstItem().equals(nativeAppLauncher.getClassPath()) && new File(nativeAppLauncher.getFirstItem()).isFile())
294
                else if (nativeAppLauncher.getFirstItem().equals(nativeAppLauncher.getClassPath()) && new File(nativeAppLauncher.getFirstItem()).isFile())
241
                this.wd = new File(nativeAppLauncher.getFirstItem()).getParentFile();
295
                    this.wd = new File(nativeAppLauncher.getFirstItem()).getParentFile();
242
            // support launch in an IDE
296
                // support launch in an IDE
243
            else
297
                else
244
                this.wd = FileUtils.getWD();
298
                    this.wd = FileUtils.getWD();
-
 
299
            } else {
-
 
300
                this.wd = appDir;
-
 
301
            }
245
        }
302
        }
246
        return this.wd;
303
        return this.wd;
247
    }
304
    }
248
 
305
 
249
    private final List<String> split(String res) {
306
    private final List<String> split(String res) {
Line 304... Line 361...
304
     */
361
     */
305
    public final Process launch(final String mainClass, final List<String> progParams) throws IOException {
362
    public final Process launch(final String mainClass, final List<String> progParams) throws IOException {
306
        final boolean debug = Boolean.getBoolean("launcher.debug");
363
        final boolean debug = Boolean.getBoolean("launcher.debug");
307
        final String javaBinary = getJavaBinary();
364
        final String javaBinary = getJavaBinary();
308
        final File sameJava = new File(System.getProperty("java.home"), "bin/" + javaBinary);
365
        final File sameJava = new File(System.getProperty("java.home"), "bin/" + javaBinary);
-
 
366
        // allow to know what binary (and thus java.home) was tested
-
 
367
        if (debug)
-
 
368
            System.err.println("sameJava : " + sameJava);
309
        final String java = sameJava.canExecute() ? sameJava.getAbsolutePath() : javaBinary;
369
        final String java = sameJava.canExecute() ? sameJava.getAbsolutePath() : javaBinary;
310
        final File propFile = this.getPropFile(mainClass);
370
        final File propFile = this.getPropFile(mainClass);
311
        final Properties props = this.getProps(propFile);
371
        final Properties props = this.getProps(propFile);
312
        if (debug)
372
        if (debug)
313
            System.err.println("propFile : " + propFile);
373
            System.err.println("propFile : " + propFile);
Line 318... Line 378...
318
        if (this.enableRemoteDebug(props)) {
378
        if (this.enableRemoteDebug(props)) {
319
            command.add(RemoteDebugArgs.getArgs(props.getProperty("remoteDebugAddr")));
379
            command.add(RemoteDebugArgs.getArgs(props.getProperty("remoteDebugAddr")));
320
        }
380
        }
321
        command.addAll(this.getVMArguments());
381
        command.addAll(this.getVMArguments());
322
 
382
 
323
        // for java the last specified property wins
383
        // For java the last specified property wins. MAYBE concat properties whose names start with
-
 
384
        // PROPS_VMARGS, that way we could override just one of many e.g. VMARGS.garbageCollector.
324
        if (propFile != null) {
385
        if (propFile != null) {
325
            final List<String> appProps = this.getProp(props, PROPS_VMARGS);
386
            final List<String> appProps = this.getProp(props, PROPS_VMARGS);
326
            command.addAll(appProps);
387
            command.addAll(appProps);
327
            final File userFile = new File(System.getProperty("user.home"), ".java/ilm/" + propFile.getName());
-
 
328
            final List<String> userProps = this.getProp(userFile, PROPS_VMARGS);
-
 
329
            command.addAll(userProps);
-
 
330
            if (debug) {
388
            if (debug) {
331
                System.err.println("appProps : " + appProps);
389
                System.err.println("VM arguments from " + propFile + " : " + appProps);
-
 
390
            }
-
 
391
            // Don't use Properties(defaults) constructor since we want to combine values.
-
 
392
            final File localFile = FileUtils.prependSuffix(propFile, "-local", PROPERTIES_EXT);
-
 
393
            final File userFile = new File(System.getProperty("user.home"), ".java/ilm/" + propFile.getName());
-
 
394
            for (final File f : Arrays.asList(localFile, userFile)) {
-
 
395
                final List<String> moreProps = this.getProp(f, PROPS_VMARGS);
-
 
396
                command.addAll(moreProps);
-
 
397
                if (debug) {
332
                System.err.println("userProps ( from " + userFile + ") : " + userProps);
398
                    System.err.println("VM arguments from " + f + " : " + moreProps);
-
 
399
                }
333
            }
400
            }
334
        }
401
        }
335
        final String envVMArgs = System.getenv(ENV_VMARGS);
402
        final String envVMArgs = System.getenv(ENV_VMARGS);
336
        if (envVMArgs != null)
403
        if (envVMArgs != null)
337
            command.addAll(split(envVMArgs));
404
            command.addAll(split(envVMArgs));
-
 
405
        // launched app may also need this context
-
 
406
        addJPackageSystemPropertyArgument(command, APPDIR_SYSPROP);
-
 
407
        addJPackageSystemPropertyArgument(command, APP_EXE_SYSPROP);
338
 
408
 
339
        command.add("-cp");
409
        command.add("-cp");
340
        command.add(getClassPath());
410
        command.add(getClassPath());
341
        command.add(mainClass);
411
        command.add(mainClass);
342
        final String envProgArgs = System.getenv(ENV_PROGARGS);
412
        final String envProgArgs = System.getenv(ENV_PROGARGS);
Line 397... Line 467...
397
        return this.getLauncherWD();
467
        return this.getLauncherWD();
398
    }
468
    }
399
 
469
 
400
    protected File getPropFile(final String mainClass) {
470
    protected File getPropFile(final String mainClass) {
401
        final String className = mainClass.substring(mainClass.lastIndexOf('.') + 1);
471
        final String className = mainClass.substring(mainClass.lastIndexOf('.') + 1);
402
        return new File(getWD(), className + ".properties");
472
        return new File(getWD(), className + PROPERTIES_EXT);
403
    }
473
    }
404
}
474
}