Я работаю над клиент-серверным Java-приложением, которое предназначено для работы в Mac OS X, а также в Windows и Linux. Приложение имеет несколько различных клиентских модулей, которые должны выполняться из приложения запуска.
Я посмотрел на класс ProcessBuilder, но мне кажется, что он мне не подходит. Я нашел поток здесь att stackoverflow, где был предложен пример использования Ant ( здесь ).
Я реализовал метод, который выполняет клиентские модули:
public void launchAnt(ApplicationData applicationData) {
Project project = new Project();
project.setBaseDir(new File(System.getProperty("user.dir")));
project.init();
DefaultLogger logger = new DefaultLogger();
project.addBuildListener(logger);
logger.setOutputPrintStream(System.out);
logger.setErrorPrintStream(System.err);
logger.setMessageOutputLevel(Project.MSG_INFO);
System.setOut(new PrintStream(new DemuxOutputStream(project, false)));
System.setErr(new PrintStream(new DemuxOutputStream(project, true)));
project.fireBuildStarted();
System.out.println("ApplicationLauncher.launch(): Running");
Throwable caught = null;
try {
/**
* Create Java task
*/
Java javaTask = new Java();
javaTask.setTaskName("Run " + applicationData.getApplication().name());
javaTask.setProject(project);
javaTask.setFork(false);
javaTask.setFailonerror(true);
javaTask.setClassname(applicationData.getClassName());
/**
* Working directory
*/
File workdir = new File(System.getProperty("user.dir"));
if(workdir.exists()) {
javaTask.setDir(workdir);
} else {
System.out.println("ApplicationLauncher.launch(): ERROR: Unable to set workdir, " + workdir.getAbsolutePath() + " does note exist.");
}
/**
* Classpath
*/
Path path = new Path(project);
Collection<String> classpaths = getClasspath();
for (String classpath : classpaths) {
Path currPath = new Path(project, new File(classpath).getAbsolutePath());
path.add(currPath);
}
System.out.println("ApplicationLauncher.launch(): Classpath: " + path.toString());
javaTask.setClasspath(path);
/**
* Arguments
*/
Argument arg = javaTask.createArg();
arg.setValue(applicationData.getArguments());
/**
* Initiate and execute
*/
javaTask.init();
int ret = javaTask.executeJava();
System.out.println("ApplicationLauncher.launch(): Java task return code: " + ret);
} catch (BuildException e) {
caught = e;
}
project.log("ApplicationLauncher.launch(): Finished");
project.fireBuildFinished(caught);
}
ApplicationData - это объект, который содержит некоторую информацию о приложении, которое будет запущено. Этот код работает хорошо, и приложение запускается. Проблема возникает в приложении, которое запускается, где эта строка вызывает ClassNotFoundException:
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
Это трассировка стека:
java.lang.ClassNotFoundException: apple.laf.AquaLookAndFeel
at org.apache.tools.ant.AntClassLoader.findClassInComponents(AntClassLoader.java:1361)
at org.apache.tools.ant.AntClassLoader.findClass(AntClassLoader.java:1311)
at org.apache.tools.ant.AntClassLoader.loadClass(AntClassLoader.java:1070)
at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:374)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:242)
at javax.swing.SwingUtilities.loadSystemClass(SwingUtilities.java:1788)
at javax.swing.UIManager.setLookAndFeel(UIManager.java:484)
Если я пытаюсь запустить приложение в автономном режиме, оно работает нормально. Приложение запуска содержит точно такую же строку, в которой происходит сбой, и она прекрасно работает в модуле запуска. Кажется, что есть что-то, что не так с этим способом запуска приложения.
Я сравнил System.properties и classpath при выполнении приложения из модуля запуска и автономно (который работает), и нет никакой разницы.
Я просто не понимаю, почему этот класс не может быть найден.
Кто-нибудь еще видел эту проблему? Любое предложение приветствуется!
Thanx!