1 package charactermanaj.util;
4 import java.io.FileOutputStream;
5 import java.io.IOException;
6 import java.io.InputStream;
7 import java.io.OutputStream;
8 import java.net.JarURLConnection;
9 import java.net.URISyntaxException;
11 import java.net.URLConnection;
12 import java.util.ArrayList;
13 import java.util.Collection;
14 import java.util.EnumSet;
15 import java.util.Enumeration;
16 import java.util.jar.JarEntry;
17 import java.util.jar.JarFile;
18 import java.util.logging.Level;
19 import java.util.logging.Logger;
26 public class SetupLocalization extends ResourceLoader {
28 private final Logger logger = Logger.getLogger(getClass().getName());
30 public static final String DIRNAME_RESOURCES = "resources";
33 * リソースフォルダ下のサブディレクトリ一覧.<br>
35 public enum Resources {
36 Languages("languages"), Menu("menu"), Template("template");
38 private final String dirName;
40 private Resources(String dirName) {
41 this.dirName = dirName;
44 public String getDirName() {
49 public String toString() {
57 * アプリケーションデータ用ディレクトリを指定して構築する.
62 public SetupLocalization(File baseDir) {
63 if (baseDir == null || !baseDir.isDirectory()) {
64 throw new IllegalArgumentException();
66 this.baseDir = baseDir;
70 * コピー対象とするリソース一覧を取得する.<br>
73 * リソースディレクトリのサブディレクトリ名のリスト
74 * @return リソース一覧(言語関連リソース、テンプレートなど)
78 protected Collection<String> getResourceList(EnumSet<Resources> resourceSet)
80 if (resourceSet == null) {
81 resourceSet = EnumSet.noneOf(Resources.class);
83 ArrayList<String> resources = new ArrayList<String>();
85 ClassLoader cl = getClass().getClassLoader();
87 for (Resources resourceKey : resourceSet) {
88 String name = resourceKey.getDirName();
89 URL loc = cl.getResource(name);
93 String protocol = loc.getProtocol();
94 if ("file".equals(protocol)) {
95 // ファイル上にクラスやリソースがある場合
97 File dir = new File(loc.toURI());
98 File[] files = dir.listFiles();
100 for (File file : files) {
101 if (file.isDirectory()) {
104 resources.add(name + "/" + file.getName());
107 } catch (URISyntaxException e) {
108 throw new RuntimeException(e);
111 } else if ("jar".equals(protocol)) {
113 JarURLConnection conn = (JarURLConnection) loc.openConnection();
114 JarEntry dirEntry = conn.getJarEntry();
115 assert dirEntry != null; // "jar:file:xxxx.jar!yyyy" のyyyyの部分
116 String prefix = dirEntry.getName() + "/";
117 JarFile jarFile = conn.getJarFile();
119 Enumeration<JarEntry> enm = jarFile.entries();
120 while (enm.hasMoreElements()) {
121 JarEntry entry = enm.nextElement();
122 if (entry.isDirectory()) {
125 String entryName = entry.getName();
126 if (entryName.startsWith(prefix)) {
127 resources.add(entryName);
131 if (!conn.getUseCaches()) {
132 // キャッシュしてある場合は明示的にクローズしない.
133 // (そもそもクローズする必要はないかも)
134 // (たぶん、システムなどがインスタンスを再利用していると思われるため)
135 // (jdk5でクローズすると例外が発生する。jdk7のリビジョンによっても発生するようだ)
136 // http://bugs.sun.com/view_bug.do?bug_id=7050028
143 logger.log(Level.FINE, "resource list: " +resources);
148 * リソースをファイルにコピーする.<br>
152 * @throws IOException
154 protected void copyResource(URL fromURL, File toFile) throws IOException {
155 logger.log(Level.INFO, "copy resource '" + fromURL + "' to '" + toFile + "'");
156 File dir = toFile.getParentFile();
157 if ( !dir.exists()) {
158 if ( !dir.mkdirs()) {
159 throw new IOException("can't create directory. " + dir);
163 URLConnection conn = fromURL.openConnection();
164 conn.setDoInput(true);
165 InputStream is = conn.getInputStream();
167 long lastModified = conn.getLastModified();
168 OutputStream os = new FileOutputStream(toFile);
170 byte[] buf = new byte[4096];
172 int rd = is.read(buf);
176 os.write(buf, 0, rd);
181 boolean result = toFile.setLastModified(lastModified);
182 logger.log(Level.FINE, "setLastModified(" + toFile+ ") succeeded=" + result);
193 public File getResourceDir() {
195 return new File(baseDir, DIRNAME_RESOURCES).getCanonicalFile();
196 } catch (Exception ex) {
197 throw new RuntimeException(ex);
202 * ローカルシステム上のアプリケーションデータディレクトリに言語リソースをコピーする.
207 * 上書きを許可する場合はtrue、スキップする場合はfalse
208 * @throws IOException
211 public void setupToLocal(EnumSet<Resources> resourceSet, boolean overwrite)
213 File toDir = getResourceDir();
214 ClassLoader cl = getDefaultClassLoader();
215 for (String resourceName : getResourceList(resourceSet)) {
216 URL url = cl.getResource(resourceName);
218 File toFile = new File(toDir, resourceName).getCanonicalFile();
219 if (overwrite || !toFile.exists()) {
220 // 上書き許可か、まだファイルが存在しなければコピーする.
221 copyResource(url, toFile);
225 logger.log(Level.WARNING, "missing resource: " + resourceName);