/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package jp.or.med.orca.monsiaj; import java.io.*; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLClassLoader; import java.util.Properties; import java.util.jar.JarFile; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; /** * * @author mihara */ public class Loader { private static Logger log = LogManager.getLogger(Loader.class); private final String VERSION_URL = "http://ftp.orca.med.or.jp/pub/java-client/version.txt"; private final String DOWNLOAD_URL = "http://ftp.orca.med.or.jp/pub/java-client/"; private final String[] CACHE_DIR_PATH_ELEM = {System.getProperty("user.home"), ".monsiaj", "cache"}; private final String CACHE_DIR = createFilePath(CACHE_DIR_PATH_ELEM).getAbsolutePath(); private static final String[] PROP_PATH_ELEM = {System.getProperty("user.home"), ".monsiaj", "loader.properties"}; private static final String PROP_PATH = createFilePath(PROP_PATH_ELEM).getAbsolutePath(); private Properties prop; private static File createFilePath(String[] elements) { String path = ""; for (String elem : elements) { if (path.isEmpty()) { path = elem; } else { path = path + File.separator + elem; } } return new File(path); } private String loadCacheVersion() { prop = new Properties(); try { prop.load(new FileInputStream(PROP_PATH)); } catch (IOException ex) { // initial } if (prop.containsKey("cacheVersion")) { return prop.getProperty("cacheVersion"); } else { return null; } } private void saveCacheVersion(String v) { prop.setProperty("cacheVersion", v); try { prop.store(new FileOutputStream(Loader.PROP_PATH), PROP_PATH); } catch (IOException ex) { log.error(ex.getMessage(), ex); } } private void removeCacheVersion() { prop.clear(); try { prop.store(new FileOutputStream(Loader.PROP_PATH), PROP_PATH); } catch (IOException ex) { log.catching(Level.ERROR, ex); } } private void updateCache(String version) throws IOException { log.debug("-- updateCache"); /* * キャッシュディレクトリの削除と作成 */ File cacheDir = new File(CACHE_DIR); FileUtils.deleteDirectory(cacheDir); if (!cacheDir.mkdirs()) { throw new IOException("cant make cachedir"); } /* * zipファイルのダウンロード */ String strURL = DOWNLOAD_URL + "monsiaj-bin-" + version + ".zip"; log.info("download " + strURL); HttpURLConnection con = httpGet(strURL); URL url = new URL(strURL); File tmp = File.createTempFile("monsiaj-bin-" + version + "-", ".zip"); tmp.deleteOnExit(); BufferedInputStream in = new BufferedInputStream(con.getInputStream()); int length; try (BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(tmp))) { while ((length = in.read()) != -1) { out.write(length); } } con.disconnect(); ZipUtils.unzip(tmp, cacheDir); tmp.delete(); log.debug("-- updateCache end"); } private static HttpURLConnection httpGet(String strURL) throws IOException { URL url = new URL(strURL); HttpURLConnection con = (HttpURLConnection) url.openConnection(); con.setInstanceFollowRedirects(false); con.setRequestMethod("GET"); con.connect(); if (con.getResponseCode() != HttpURLConnection.HTTP_OK) { con.disconnect(); throw new IOException("" + con.getResponseCode()); } return con; } private String getVersion() throws IOException { HttpURLConnection con = httpGet(VERSION_URL); BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream())); String version = reader.readLine(); con.disconnect(); return version; } private void checkCache() { try { log.debug("-- checkCache start"); String cacheVersion = loadCacheVersion(); String serverVersion = getVersion(); log.info("cacheVersion : " + cacheVersion); log.info("serverVersion: " + serverVersion); if (cacheVersion == null || !cacheVersion.equals(serverVersion)) { updateCache(serverVersion); saveCacheVersion(serverVersion); } else { log.info("use cache"); } log.debug("-- checkCache end"); } catch (Exception ex) { log.error("checkCache failure"); log.error(ex.getMessage(), ex); } } private void loadCache(File file) throws Exception { URLClassLoader loader = (URLClassLoader) ClassLoader.getSystemClassLoader(); if (file.isDirectory()) { for (File f : file.listFiles()) { loadCache(f); } } else { if (file.getName().endsWith(".jar")) { if (JarVerifier.verify(new JarFile(file))) { URL u = file.toURI().toURL(); Method m = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{URL.class}); m.setAccessible(true); m.invoke(loader, new Object[]{u}); } else { throw new Exception("invalid jar(code sign verification error) : " + file.getName()); } } } } private void invokeLauncher(String[] args) throws Exception { String cacheVersion = loadCacheVersion(); File file = new File(CACHE_DIR + "monsiaj-bin-" + cacheVersion + "/jmareceipt.jar"); URLClassLoader loader = new URLClassLoader(new URL[]{new URL(file.getAbsolutePath())}); Class<?> cobj = loader.loadClass("jp.or.med.orca.jmareceipt.JMAReceiptLauncher"); Method m = cobj.getMethod("main", new Class[]{args.getClass()}); m.setAccessible(true); int mods = m.getModifiers(); if (m.getReturnType() != void.class || !Modifier.isStatic(mods) || !Modifier.isPublic(mods)) { throw new NoSuchMethodException("main"); } m.invoke(null, new Object[]{args}); } private void launch(String[] args) throws Exception { try { log.debug("-- launch start"); loadCache(new File(CACHE_DIR)); invokeLauncher(args); } catch (Exception ex) { removeCacheVersion(); log.error(ex.getMessage(), ex); log.info("remove cacheVersion"); } } public static void main(String[] args) throws Exception { log.info("---- Loader start"); Loader loader = new Loader(); loader.checkCache(); /* * 起動時以降はproxyを解除、クライアント印刷などのHTTPアクセスをproxy経由にしないため */ System.clearProperty("proxyHost"); System.clearProperty("proxyPort"); loader.launch(args); log.info("---- Loader end"); } }