ProcessBuilder

 ProcessBuilderクラスを使って、Javaプログラム起動用の簡単なランチャーを書いてみる。

ソースコード

import java.awt.Color;
import java.awt.Font;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JWindow;
import javax.swing.SwingUtilities;

public class Launcher {
	private Properties properties;
	
	public Launcher(Properties p){
		properties=p;
	}
	
	private JWindow createSplashScreen(String path) {
		ImageIcon img=null;
		try{
			if(path!=null){
				BufferedImage im=ImageIO.read(new File(path));
				img=new ImageIcon(im);
			}
		}catch(IOException ie){
		}catch(NullPointerException ie){}
		JLabel splashLabel;
		if(img!=null){
			splashLabel=new JLabel(img);
		}else{
			splashLabel=new JLabel(properties.getProperty("name"));
			splashLabel.setFont(new Font(Font.DIALOG,Font.BOLD,36));
		}
		splashLabel.setOpaque(true);
		splashLabel.setBackground(new Color(255,255,255,0));
		JWindow splash=new JWindow(new JFrame());
		splash.getContentPane().add(splashLabel);
		splash.setBackground(new Color(255,255,255,0));
		splash.setAlwaysOnTop(true);
		splash.pack();
		splash.setLocationRelativeTo(null);
		return splash;
	}
	
	private void start(){
		long delay=Long.parseLong(properties.getProperty("delay"));
		final JWindow splash=createSplashScreen(
				properties.getProperty("image"));
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				splash.setVisible(true);
			}
		});
		try {
			init();
			Thread.sleep(delay);
			System.exit(0);
		} catch(InterruptedException ex) {}
	}
	
	private List<File> addJarList(List<File> list,String obj){
		if(obj==null)return list;
		File f=new File(obj);
		if(f.exists()&&f.isDirectory()){
			File[] ff=f.listFiles();
			for(int i=0;i<ff.length;i++){
				if(ff[i].getName().toLowerCase().endsWith("jar")){
					list.add(ff[i]);
				}
			}
		}
		return list;
	}
	
	private void init(){
		List<File> list=new ArrayList<File>();
		String line=properties.getProperty("path");
		String[] obj=line.split(",");
		for(int i=0;i<obj.length;i++){
			list=addJarList(list,obj[i]);
		}
		String path=".";
		for(int i=0;i<list.size();i++){
			File fx=list.get(i);
			path=path+";\""+fx.getAbsolutePath()+"\"";
		}
		try{
			List<String> args=new ArrayList<String>();
			args.add("java");
			args.add("-cp");
			args.add(path);
			args.add("-Xmx"+properties.getProperty("memory")+"m");
			String op=properties.getProperty("option");
			if(op!=null&&op.isEmpty()){
				args.add(op);
			}
			args.add(properties.getProperty("exec"));
			ProcessBuilder pb=new ProcessBuilder(args);
			pb.redirectErrorStream(true);
			pb.start();
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args){
		Properties prop = new Properties();
		try{
			prop.loadFromXML(new FileInputStream("properties.xml"));
			Launcher app=new Launcher(prop);
			app.start();
		}catch(FileNotFoundException fe){
			fe.printStackTrace();
		}catch(IOException ie){
			ie.printStackTrace();
		}
	}
}

■プロパティファイル(properties.xml)
 以下のようなプロパティファイルを作成する。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>TmFlow2D ver.0.1</comment>
<entry key="name">TmFlow2D</entry>
<entry key="image">./splash.png</entry>
<entry key="delay">3000</entry>
<entry key="path">lib,bin</entry>
<entry key="memory">256</entry>
<entry key="option">-Dawt.useSystemAAFontSettings=on</entry>
<entry key="exec">jp.t.matsuoka.tmflow2d.gui.TmFlow2dApp</entry>
</properties>

 なお、

  • name=プログラム名
  • image=スプラッシュ画像の相対パス
  • delay=スプラッシュ画像の表示時間
  • path=クラスパスを通すJarファイルがあるフォルダの相対パス(カンマで複数指定)
  • memory=JVMの最大メモリ
  • option=その他のJVMオプション
  • exec=起動するクラス

■結果
 executable-jarにしたLauncherクラスを起動すると、properties.xmlを読み込み、スプラッシュウィンドウを表示する。その後、pathに設定したフォルダ内のJarファイルにクラスパスを通し、別プロセスで目的のクラスを起動する。
 クラスパスとかの設定が不要なので、以外に便利だったりする。

 Jarファイル(ソースコード込み)はここに置いておく。