OSDN Git Service

コメントを記入しました。
authoruguu <uguu@bdfc86a3-8c30-0410-b963-dc9a622ac1c7>
Sat, 19 May 2007 20:33:57 +0000 (20:33 +0000)
committeruguu <uguu@bdfc86a3-8c30-0410-b963-dc9a622ac1c7>
Sat, 19 May 2007 20:33:57 +0000 (20:33 +0000)
git-svn-id: svn+ssh://svn.sourceforge.jp/svnroot/deployer@3 bdfc86a3-8c30-0410-b963-dc9a622ac1c7

deployer/trunk/src/main/java/jp/gr/java_conf/uguu/deployer/Deployer.java
deployer/trunk/src/main/java/jp/gr/java_conf/uguu/deployer/DeployerClassLoader.java
deployer/trunk/src/main/java/jp/gr/java_conf/uguu/deployer/DeployerClassLoaderListener.java
deployer/trunk/src/main/java/jp/gr/java_conf/uguu/deployer/DeployerListener.java
deployer/trunk/src/main/java/jp/gr/java_conf/uguu/deployer/FileMonitor.java
deployer/trunk/src/main/java/jp/gr/java_conf/uguu/deployer/FileMonitorListener.java

index 6b9e679..542ffe4 100644 (file)
@@ -13,6 +13,16 @@ import java.util.regex.Pattern;
 import java.util.zip.ZipEntry;\r
 import java.util.zip.ZipInputStream;\r
 \r
+/**\r
+ * <p>\r
+ * ファイルを監視し、アーカイブ・ファイルが配置されたときに作業ディレクトリに展開し、イベントを通知します。\r
+ * </p>\r
+ * <p>\r
+ * {@link #monitor()}メソッドの呼び出しでファイルを一回監視することが出来ます。ファイルを定期的に監視する場合、定期的に{@link #monitor()}メソッドを呼び出してください。\r
+ * </p>\r
+ * \r
+ * @author uguu\r
+ */\r
 public class Deployer {\r
 \r
     private List<DeployerListener> listenerList = new ArrayList<DeployerListener>();\r
@@ -25,6 +35,23 @@ public class Deployer {
 \r
     private FileMonitor            fileMonitor;\r
 \r
+    /**\r
+     * <p>\r
+     * インスタンスを初期化します。\r
+     * </p>\r
+     * \r
+     * @param deployDirectory\r
+     *            アーカイブ・ファイルの格納ディレクトリ。ここにアーカイブ・ファイルを配置すると、{@link Deployer}クラスが認識し、作業ディレクトリに展開します。<br>\r
+     *            nullの場合、{@link IllegalArgumentException}例外をスローします。<br>\r
+     *            ディレクトリではない場合、{@link IllegalArgumentException}例外をスローします。\r
+     * @param filePattern\r
+     *            アーカイブ・ファイルであると認識するファイルのパターン。絶対パスと比較されます。<br>\r
+     *            nullの場合、{@link IllegalArgumentException}例外をスローします。\r
+     * @param workDirectory\r
+     *            作業ディレクトリ。アーカイブ・ファイルはここに展開されます。<br>\r
+     *            nullの場合、{@link IllegalArgumentException}例外をスローします。<br>\r
+     *            ディレクトリではない場合、{@link IllegalArgumentException}例外をスローします。\r
+     */\r
     public Deployer(File deployDirectory, Pattern filePattern, File workDirectory) {\r
         if (deployDirectory == null) {\r
             throw new IllegalArgumentException("deployDirectory is null.");\r
@@ -51,6 +78,18 @@ public class Deployer {
         this.fileMonitor.addListener(new FileMonitorListenerImpl());\r
     }\r
 \r
+    /**\r
+     * <p>\r
+     * アーカイブ・ファイルの配置、配置解除のイベントが通知されるリスナーを追加します。\r
+     * </p>\r
+     * <p>\r
+     * このメソッドはスレッドセーフです。\r
+     * </p>\r
+     * \r
+     * @param listener\r
+     *            イベントが通知されるリスナー。<br>\r
+     *            nullの場合、{@link IllegalArgumentException}例外をスローします。\r
+     */\r
     public void addListener(DeployerListener listener) {\r
         if (listener == null) {\r
             throw new IllegalArgumentException("listener is null.");\r
@@ -60,12 +99,31 @@ public class Deployer {
         }\r
     }\r
 \r
+    /**\r
+     * <p>\r
+     * 登録されているリスナーを削除します。\r
+     * </p>\r
+     * <p>\r
+     * このメソッドはスレッドセーフです。\r
+     * </p>\r
+     * \r
+     * @param listener\r
+     *            削除するリスナー。\r
+     */\r
     public void removeListener(DeployerListener listener) {\r
         synchronized (this.listenerList) {\r
             this.listenerList.remove(listener);\r
         }\r
     }\r
 \r
+    /**\r
+     * <p>\r
+     * アーカイブ・ファイルを監視し、配置、配置解除を行い、リスナーにイベントを通知します。\r
+     * </p>\r
+     * \r
+     * @throws IOException\r
+     *             入出力エラーが発生した場合。\r
+     */\r
     public void monitor() throws IOException {\r
         this.fileMonitor.monitor();\r
     }\r
@@ -139,6 +197,12 @@ public class Deployer {
                     while ((zipEntry = zipIn.getNextEntry()) != null) {\r
                         if (!zipEntry.isDirectory()) {\r
                             File f = new File(destDir, zipEntry.getName().replace('/', File.separatorChar));\r
+                            // イベントを通知します。\r
+                            synchronized (this.listenerList) {\r
+                                for (DeployerListener l : this.listenerList) {\r
+                                    l.deployFile(this, file, destDir, f);\r
+                                }\r
+                            }\r
                             if (!f.createNewFile()) {\r
                                 throw new IOException("ファイル\"" + f.getAbsolutePath() + "\"の作成に失敗しました。");\r
                             }\r
@@ -153,12 +217,6 @@ public class Deployer {
                             } finally {\r
                                 fileOut.close();\r
                             }\r
-                            // イベントを通知します。\r
-                            synchronized (this.listenerList) {\r
-                                for (DeployerListener l : this.listenerList) {\r
-                                    l.deployFile(this, file, destDir, f);\r
-                                }\r
-                            }\r
                         } else {\r
                             File dir = new File(destDir, zipEntry.getName().replace('/', File.separatorChar));\r
                             if (!dir.mkdirs()) {\r
index 2028915..839549b 100644 (file)
@@ -10,10 +10,24 @@ import java.net.URL;
 import java.util.ArrayList;\r
 import java.util.Enumeration;\r
 import java.util.List;\r
-import java.util.Vector;\r
+import java.util.NoSuchElementException;\r
 import java.util.jar.JarEntry;\r
 import java.util.jar.JarFile;\r
 \r
+/**\r
+ * <p>\r
+ * アーカイブ・ファイル配置後のクラスやリソースを利用するクラスローダーです。\r
+ * </p>\r
+ * <p>\r
+ * アーカイブ・ファイルにはクラス・ファイル、リソース、jarファイルを含めることが出来、コンストラクタでディレクトリを指定することでクラスローダーの管理下に置くことができます。例えば、classes/からクラス・ファイル、lib/からjarファイルを検索するように初期化することが出来ます。\r
+ * </p>\r
+ * <p>\r
+ * ホット・デプロイを前提としているので、クラスローダーが読み込んだリソースなどを破棄する{@link #dispose()}メソッドが用意されています。例えば{@link Deployer}クラスと連携する場合、{@link DeployerListener#undeployEnd(Deployer, File)}メソッドの呼び出しでこのクラスローダーを破棄することが出来ます。\r
+ * TODO: dispose()メソッドは実装されていません。一度管理下に置いたリソースを破棄する方法が分からないためです。\r
+ * </p>\r
+ * \r
+ * @author uguu\r
+ */\r
 public class DeployerClassLoader extends ClassLoader {\r
 \r
     private List<DeployerClassLoaderListener> listenerList = new ArrayList<DeployerClassLoaderListener>();\r
@@ -24,17 +38,67 @@ public class DeployerClassLoader extends ClassLoader {
 \r
     private String                            jarDirectory;\r
 \r
-    public DeployerClassLoader(File deployDirectory, String classDirectory, String jarDirectory, ClassLoader parent) throws IOException {\r
+    /**\r
+     * <p>\r
+     * {@link DeployerClassLoader}インスタンスを初期化します。\r
+     * </p>\r
+     * \r
+     * @param deployDirectory\r
+     *            アーカイブ・ファイルを配置したディレクトリ。このディレクトリ以下からクラス・ファイル、リソース、jarファイルなどを検索します。<br>\r
+     *            nullの場合、{@link IllegalArgumentException}例外をスローします。<br>\r
+     *            ディレクトリではない場合、{@link IllegalArgumentException}例外をスローします。\r
+     * @param classDirectory\r
+     *            クラス・ファイルを検索するディレクトリの名前。<br>\r
+     *            nullの場合、{@link IllegalArgumentException}例外をスローします。\r
+     * @param jarDirectory\r
+     *            jarファイルを検索するディレクトリの名前。<br>\r
+     *            nullの場合、{@link IllegalArgumentException}例外をスローします。\r
+     * @param parent\r
+     *            親クラスローダー。\r
+     */\r
+    public DeployerClassLoader(File deployDirectory, String classDirectory, String jarDirectory, ClassLoader parent) {\r
         super(parent);\r
         this.initialize(deployDirectory, classDirectory, jarDirectory);\r
     }\r
 \r
-    public DeployerClassLoader(File deployDirectory, String classDirectory, String jarDirectory) throws IOException {\r
+    /**\r
+     * <p>\r
+     * {@link DeployerClassLoader}インスタンスを初期化します。\r
+     * </p>\r
+     * \r
+     * @param deployDirectory\r
+     *            アーカイブ・ファイルを配置したディレクトリ。このディレクトリ以下からクラス・ファイル、リソース、jarファイルなどを検索します。<br>\r
+     *            nullの場合、{@link IllegalArgumentException}例外をスローします。<br>\r
+     *            ディレクトリではない場合、{@link IllegalArgumentException}例外をスローします。\r
+     * @param classDirectory\r
+     *            クラス・ファイルを検索するディレクトリの名前。<br>\r
+     *            nullの場合、{@link IllegalArgumentException}例外をスローします。\r
+     * @param jarDirectory\r
+     *            jarファイルを検索するディレクトリの名前。<br>\r
+     *            nullの場合、{@link IllegalArgumentException}例外をスローします。\r
+     */\r
+    public DeployerClassLoader(File deployDirectory, String classDirectory, String jarDirectory) {\r
         super();\r
         this.initialize(deployDirectory, classDirectory, jarDirectory);\r
     }\r
 \r
-    private void initialize(File deployDirectory, String classDirectory, String jarDirectory) throws IOException {\r
+    /**\r
+     * <p>\r
+     * クラスローダーを初期化します。\r
+     * </p>\r
+     * \r
+     * @param deployDirectory\r
+     *            アーカイブ・ファイルを配置したディレクトリ。このディレクトリ以下からクラス・ファイル、リソース、jarファイルなどを検索します。<br>\r
+     *            nullの場合、{@link IllegalArgumentException}例外をスローします。<br>\r
+     *            ディレクトリではない場合、{@link IllegalArgumentException}例外をスローします。\r
+     * @param classDirectory\r
+     *            クラス・ファイルを検索するディレクトリの名前。<br>\r
+     *            nullの場合、{@link IllegalArgumentException}例外をスローします。\r
+     * @param jarDirectory\r
+     *            jarファイルを検索するディレクトリの名前。<br>\r
+     *            nullの場合、{@link IllegalArgumentException}例外をスローします。\r
+     */\r
+    private void initialize(File deployDirectory, String classDirectory, String jarDirectory) {\r
         if (deployDirectory == null) {\r
             throw new IllegalArgumentException("deployDirectory is null.");\r
         }\r
@@ -53,6 +117,18 @@ public class DeployerClassLoader extends ClassLoader {
         this.jarDirectory = jarDirectory;\r
     }\r
 \r
+    /**\r
+     * <p>\r
+     * クラスローダーがクラスを操作したときのイベントを受け取るリスナーを追加します。\r
+     * </p>\r
+     * <p>\r
+     * このメソッドはスレッドセーフです。\r
+     * </p>\r
+     * \r
+     * @param listener\r
+     *            イベントが通知されるリスナー。<br>\r
+     *            nullの場合、{@link IllegalArgumentException}例外をスローします。\r
+     */\r
     public void addListener(DeployerClassLoaderListener listener) {\r
         if (listener == null) {\r
             throw new IllegalArgumentException("listener is null.");\r
@@ -62,19 +138,49 @@ public class DeployerClassLoader extends ClassLoader {
         }\r
     }\r
 \r
+    /**\r
+     * <p>\r
+     * 既に登録されているリスナーを削除します。\r
+     * </p>\r
+     * <p>\r
+     * このメソッドはスレッドセーフです。\r
+     * </p>\r
+     * \r
+     * @param listener\r
+     *            削除するリスナー。\r
+     */\r
     public void removeListener(DeployerClassLoaderListener listener) {\r
         synchronized (this.listenerList) {\r
             this.listenerList.remove(listener);\r
         }\r
     }\r
 \r
+    /**\r
+     * <p>\r
+     * クラスローダーが保持している全てのリソースを破棄します。\r
+     * </p>\r
+     * TODO: メソッドは機能しません。\r
+     */\r
     public void dispose() {\r
         // TODO 定義済みクラスをうまく解放する方法を考える。\r
     }\r
 \r
+    /**\r
+     * <p>\r
+     * クラスを検索します。\r
+     * </p>\r
+     * <p>\r
+     * このメソッドは、クラスがまだ読み込まれていないときに呼び出されます。呼び出されると、クラス・ディレクトリやjarファイルからクラスを検索し、見つかった場合、クラスとして定義します({@link #defineClass(String, byte[], int, int)}メソッドを呼び出します)。クラスが見つからなかった場合、{@link ClassNotFoundException}例外をスローします。\r
+     * </p>\r
+     * \r
+     * @param name\r
+     *            検索するクラスのFQN。\r
+     * @return 見つかったクラス。\r
+     * @throws ClassNotFoundException\r
+     *             クラスが見つからなかった場合。\r
+     */\r
     @Override\r
     protected Class<?> findClass(String name) throws ClassNotFoundException {\r
-//        String resName = "/" + name.replace('.', '/') + ".class";\r
         String resName = name.replace('.', '/') + ".class";\r
         URL url = this.findResource(resName);\r
         if (url == null) {\r
@@ -113,105 +219,229 @@ public class DeployerClassLoader extends ClassLoader {
         }\r
     }\r
 \r
+    /**\r
+     * <p>\r
+     * リソースを検索します。\r
+     * </p>\r
+     * <p>\r
+     * まずクラス・ディレクトリから、次にjarディレクトリからファイルを検索します。そして、最初に見つかったファイルのURLを返します。\r
+     * </p>\r
+     * <p>\r
+     * このメソッドは{@link #findResources(String)}メソッドを呼び出し、その最初のURLを返します。このとき、{@link #findResources(String)}メソッドが{@link IOException}例外をスローする可能性があります。{@link IOException}例外がスローされた場合、nullを返します。\r
+     * </p>\r
+     * \r
+     * @param name\r
+     *            リソース名。\r
+     * @return リソースのURL。\r
+     */\r
     @Override\r
     protected URL findResource(String name) {\r
-        URL url;\r
-        // クラス ディレクトリから探す。\r
+        Enumeration<URL> resources;\r
         try {\r
-            url = this.findResourceForClassDirectory(new File(this.deployDirectory, this.classDirectory), name);\r
-        } catch (MalformedURLException e) {\r
-            throw new RuntimeException(e);\r
-        }\r
-        if (url != null) {\r
-            return url;\r
+            resources = this.findResources(name);\r
+        } catch (IOException e) {\r
+            return null;\r
         }\r
-        // jarディレクトリから探す。\r
-        List<File> jarFileList = this.getJarFileList(new File(this.deployDirectory, this.jarDirectory));\r
-        for (File jarFile : jarFileList) {\r
-            try {\r
-                url = this.findResourceForJarFile(jarFile, name);\r
-            } catch (IOException e) {\r
-                throw new RuntimeException(e);\r
-            }\r
-            if (url != null) {\r
-                return url;\r
-            }\r
+        if (resources.hasMoreElements()) {\r
+            return resources.nextElement();\r
+        } else {\r
+            return null;\r
         }\r
-        return null;\r
     }\r
 \r
+    /**\r
+     * <p>\r
+     * リソースを検索します。\r
+     * </p>\r
+     * <p>\r
+     * まずクラス・ディレクトリから、次にjarディレクトリからファイルを検索します。そして、見つかった全てのファイルのURLを列挙します。例えば、"foo/bar/boo.txt"がfoo.jarとbar.jarから見つかった場合、これらのURLが列挙されます。\r
+     * </p>\r
+     * \r
+     * @param name\r
+     *            リソース名。\r
+     * @return リソースのURLの列挙。\r
+     * @throws IOException\r
+     *             入出力エラーが発生した場合。\r
+     */\r
     @Override\r
     protected Enumeration<URL> findResources(String name) throws IOException {\r
-        Vector<URL> urlVector = new Vector<URL>();\r
-        URL url;\r
-        // クラス ディレクトリから探す。\r
-        try {\r
-            url = this.findResourceForClassDirectory(new File(this.deployDirectory, this.classDirectory), name);\r
-        } catch (MalformedURLException e) {\r
-            throw new RuntimeException(e);\r
+        File classDir = new File(this.deployDirectory, this.classDirectory);\r
+        if (!classDir.exists()) {\r
+            classDir = null;\r
         }\r
-        if (url != null) {\r
-            urlVector.add(url);\r
+        File jarDir = new File(this.deployDirectory, this.jarDirectory);\r
+        if (!jarDir.exists()) {\r
+            jarDir = null;\r
+        }\r
+        return new ResourceEnumeration(classDir, jarDir, name);\r
+    }\r
+\r
+    /**\r
+     * <p>\r
+     * リソースを列挙します。\r
+     * </p>\r
+     * \r
+     * @author uguu\r
+     */\r
+    private class ResourceEnumeration implements Enumeration<URL> {\r
+\r
+        private String     resourceName;\r
+\r
+        private File       classDir;\r
+\r
+        private List<File> jarFileList;\r
+\r
+        private int        currentIndex = -1;\r
+\r
+        /**\r
+         * <p>\r
+         * インスタンスを初期化します。\r
+         * </p>\r
+         * \r
+         * @param classDirectory\r
+         *            クラス・ファイルを検索するディレクトリ。<br>\r
+         *            このパスが存在し、かつディレクトリではない場合、{@link IllegalArgumentException}例外をスローします。\r
+         * @param jarDirectory\r
+         *            jarファイルを検索するディレクトリ。<br>\r
+         *            このパスが存在し、かつディレクトリではない場合、{@link IllegalArgumentException}例外をスローします。\r
+         * @param resourceName\r
+         *            列挙するリソースの名前。<br>\r
+         *            nullの場合、{@link IllegalArgumentException}例外をスローします。\r
+         */\r
+        public ResourceEnumeration(File classDirectory, File jarDirectory, String resourceName) {\r
+            if (classDirectory != null && !classDirectory.isDirectory()) {\r
+                throw new IllegalArgumentException("classDirectory is not directory.");\r
+            }\r
+            if (jarDirectory != null && !jarDirectory.isDirectory()) {\r
+                throw new IllegalArgumentException("jarDirectory is not directory.");\r
+            }\r
+            if (resourceName == null) {\r
+                throw new IllegalArgumentException("resourceName is null.");\r
+            }\r
+\r
+            this.classDir = classDirectory;\r
+            this.resourceName = resourceName;\r
+\r
+            this.jarFileList = this.getJarFileList(jarDirectory);\r
         }\r
-        // jarディレクトリから探す。\r
-        List<File> jarFileList = this.getJarFileList(new File(this.deployDirectory, this.jarDirectory));\r
-        for (File jarFile : jarFileList) {\r
+\r
+        /**\r
+         * <p>\r
+         * 列挙中に次の要素が存在するかどうかを返します。\r
+         * </p>\r
+         * \r
+         * @return 次の要素が存在する場合はtrue、存在しない場合はfalse。\r
+         */\r
+        public boolean hasMoreElements() {\r
             try {\r
-                url = this.findResourceForJarFile(jarFile, name);\r
+                URL url = this.nextElement(false);\r
+                return (url != null);\r
             } catch (IOException e) {\r
                 throw new RuntimeException(e);\r
             }\r
-            if (url != null) {\r
-                urlVector.add(url);\r
-            }\r
         }\r
-        return urlVector.elements();\r
-    }\r
 \r
-    private URL findResourceForClassDirectory(File classDir, String resourceName) throws MalformedURLException {\r
-        String resName = resourceName.replace('/', File.separatorChar);\r
-        File resFile = new File(classDir, resName);\r
-        if (resFile.exists()) {\r
-            URL url = new URL("file:/" + resFile.getAbsolutePath().replace(File.separatorChar, '/'));\r
-            return url;\r
-        } else {\r
-            return null;\r
+        /**\r
+         * <p>\r
+         * 列挙中の次の要素を返します。\r
+         * </p>\r
+         * \r
+         * @return 列挙中の次の要素。<br>\r
+         *         次の要素が存在しない場合は{@link NoSuchElementException}例外をスローします。\r
+         */\r
+        public URL nextElement() {\r
+            try {\r
+                URL url = this.nextElement(true);\r
+                if (url != null) {\r
+                    return url;\r
+                } else {\r
+                    throw new NoSuchElementException();\r
+                }\r
+            } catch (IOException e) {\r
+                throw new RuntimeException(e);\r
+            }\r
         }\r
-    }\r
 \r
-    private List<File> getJarFileList(File jarDir) {\r
-        List<File> jarFileList = new ArrayList<File>();\r
+        private URL nextElement(boolean updateIndex) throws IOException {\r
+            int curIdx = this.currentIndex;\r
 \r
-        File[] files = jarDir.listFiles();\r
-        if (files == null) {\r
-            return new ArrayList<File>();\r
-        }\r
-        for (File file : files) {\r
-            if (file.isFile()) {\r
-                if (file.getName().endsWith(".jar")) {\r
-                    jarFileList.add(file);\r
+            while (true) {\r
+                if (curIdx == this.jarFileList.size()) {\r
+                    return null;\r
                 }\r
-            } else {\r
-                jarFileList.addAll(this.getJarFileList(file));\r
+                if (curIdx == -1) {\r
+                    URL url = this.findResourceForClassDirectory(this.classDir, this.resourceName);\r
+                    if (url != null) {\r
+                        if (updateIndex) {\r
+                            this.currentIndex = curIdx;\r
+                        }\r
+                        return url;\r
+                    }\r
+                } else {\r
+                    File jarFile = this.jarFileList.get(curIdx);\r
+                    URL url = this.findResourceForJarFile(jarFile, this.resourceName);\r
+                    if (url != null) {\r
+                        if (updateIndex) {\r
+                            this.currentIndex = curIdx;\r
+                        }\r
+                        return url;\r
+                    }\r
+                }\r
+                curIdx++;\r
             }\r
         }\r
 \r
-        return jarFileList;\r
-    }\r
+        private List<File> getJarFileList(File dir) {\r
+            List<File> jarFileList = new ArrayList<File>();\r
 \r
-    private URL findResourceForJarFile(File jarFile, String resourceName) throws IOException {\r
-        JarFile jar = new JarFile(jarFile);\r
-        try {\r
-            JarEntry entry = jar.getJarEntry(resourceName);\r
-            if (entry != null) {\r
-                URL url = new URL("jar:file:/" + jarFile.getAbsolutePath().replace(File.separatorChar, '/') + "!/" + entry.getName());\r
+            if (dir != null) {\r
+                File[] files = dir.listFiles();\r
+                if (files == null) {\r
+                    return new ArrayList<File>();\r
+                }\r
+                for (File file : files) {\r
+                    if (file.isFile()) {\r
+                        if (file.getName().endsWith(".jar")) {\r
+                            jarFileList.add(file);\r
+                        }\r
+                    } else {\r
+                        jarFileList.addAll(this.getJarFileList(file));\r
+                    }\r
+                }\r
+            }\r
+\r
+            return jarFileList;\r
+        }\r
+\r
+        private URL findResourceForClassDirectory(File classDir, String resourceName) throws MalformedURLException {\r
+            if (classDir != null) {\r
+                return null;\r
+            }\r
+            String resName = resourceName.replace('/', File.separatorChar);\r
+            File resFile = new File(classDir, resName);\r
+            if (resFile.exists()) {\r
+                URL url = new URL("file:/" + resFile.getAbsolutePath().replace(File.separatorChar, '/'));\r
                 return url;\r
             } else {\r
                 return null;\r
             }\r
-        } finally {\r
-            jar.close();\r
         }\r
+\r
+        private URL findResourceForJarFile(File jarFile, String resourceName) throws IOException {\r
+            JarFile jar = new JarFile(jarFile);\r
+            try {\r
+                JarEntry entry = jar.getJarEntry(resourceName);\r
+                if (entry != null) {\r
+                    URL url = new URL("jar:file:/" + jarFile.getAbsolutePath().replace(File.separatorChar, '/') + "!/" + entry.getName());\r
+                    return url;\r
+                } else {\r
+                    return null;\r
+                }\r
+            } finally {\r
+                jar.close();\r
+            }\r
+        }\r
+\r
     }\r
 \r
 }\r
index 61468ed..db3e811 100644 (file)
@@ -3,8 +3,25 @@ package jp.gr.java_conf.uguu.deployer;
 \r
 import java.net.URL;\r
 \r
+/**\r
+ * <p>\r
+ * {@link DeployerClassLoader}クラスによるクラス操作のイベントを受け取るリスナーです。\r
+ * </p>\r
+ * \r
+ * @author uguu\r
+ */\r
 public interface DeployerClassLoaderListener {\r
 \r
+    /**\r
+     * <p>\r
+     * クラスが検索されたときに呼び出されます。\r
+     * </p>\r
+     * \r
+     * @param clazz\r
+     *            検索したクラス。\r
+     * @param url\r
+     *            クラスの実態が存在するURL。\r
+     */\r
     void findClass(Class clazz, URL url);\r
 \r
 }\r
index 8e4d207..cfbf3a1 100644 (file)
@@ -3,16 +3,79 @@ package jp.gr.java_conf.uguu.deployer;
 \r
 import java.io.File;\r
 \r
+/**\r
+ * <p>\r
+ * {@link Deployer}クラスによるファイル配置のイベントを受け取るリスナーです。\r
+ * </p>\r
+ * \r
+ * @author uguu\r
+ */\r
 public interface DeployerListener {\r
 \r
+    /**\r
+     * <p>\r
+     * アーカイブ・ファイルの配置を開始するときに呼び出されます。\r
+     * </p>\r
+     * \r
+     * @param deployer\r
+     *            イベントの通知元の{@link Deployer}インスタンス。\r
+     * @param file\r
+     *            配置するアーカイブ・ファイル。\r
+     */\r
     void deployStart(Deployer deployer, File file);\r
 \r
+    /**\r
+     * <p>\r
+     * アーカイブ・ファイルから抽出したファイルを配置するときに呼び出されます。\r
+     * </p>\r
+     * \r
+     * @param deployer\r
+     *            イベントの通知元の{@link Deployer}インスタンス。\r
+     * @param file\r
+     *            配置するアーカイブ・ファイル。\r
+     * @param destDirectory\r
+     *            配置先のルート・ディレクトリ。\r
+     * @param deployFile\r
+     *            配置するファイル。\r
+     */\r
     void deployFile(Deployer deployer, File file, File destDirectory, File deployFile);\r
 \r
+    /**\r
+     * <p>\r
+     * アーカイブ・ファイルの配置が終了したときに呼び出されます。\r
+     * </p>\r
+     * \r
+     * @param deployer\r
+     *            イベントの通知元の{@link Deployer}インスタンス。\r
+     * @param file\r
+     *            配置したアーカイブ・ファイル。\r
+     * @param destDirectory\r
+     *            配置先のルート・ディレクトリ。\r
+     */\r
     void deployEnd(Deployer deployer, File file, File destDirectory);\r
 \r
+    /**\r
+     * <p>\r
+     * アーカイブ・ファイルの配置の解除を開始するときに呼び出されます。\r
+     * </p>\r
+     * \r
+     * @param deployer\r
+     *            イベントの通知元の{@link Deployer}インスタンス。\r
+     * @param file\r
+     *            配置解除するアーカイブ・ファイル。\r
+     * @param destDirectory\r
+     *            配置先のルート・ディレクトリ。\r
+     */\r
     void undeployStart(Deployer deployer, File file, File destDirectory);\r
 \r
+    /**\r
+     * アーカイブ・ファイルの配置の解除が終了したときに呼び出されます。\r
+     * \r
+     * @param deployer\r
+     *            イベントの通知元の{@link Deployer}インスタンス。\r
+     * @param file\r
+     *            配置解除したアーカイブ・ファイル。\r
+     */\r
     void undeployEnd(Deployer deployer, File file);\r
 \r
 }\r
index b260704..94dcf62 100644 (file)
@@ -9,6 +9,16 @@ import java.util.List;
 import java.util.Map;\r
 import java.util.regex.Pattern;\r
 \r
+/**\r
+ * <p>\r
+ * ファイルの作成、更新、削除を監視し、イベントを通知します。\r
+ * </p>\r
+ * <p>\r
+ * {@link #monitor()}メソッドの呼び出しでファイルを一回監視することが出来ます。ファイルを定期的に監視する場合、定期的に{@link #monitor()}メソッドを呼び出してください。\r
+ * </p>\r
+ * \r
+ * @author uguu\r
+ */\r
 public class FileMonitor {\r
 \r
     private List<FileMonitorListener>       listenerList      = new ArrayList<FileMonitorListener>();\r
@@ -19,6 +29,19 @@ public class FileMonitor {
 \r
     private Map<String, MonitoringFileInfo> monitoringFileMap = new HashMap<String, MonitoringFileInfo>();\r
 \r
+    /**\r
+     * <p>\r
+     * 指定したディレクトリの指定したパターンに合致するファイルを監視する{@link FileMonitor}インスタンスを初期化します。\r
+     * </p>\r
+     * \r
+     * @param baseDirectory\r
+     *            監視するディレクトリ。<br>\r
+     *            nullの場合、{@link IllegalArgumentException}例外をスローします。<br>\r
+     *            ディレクトリを表していない場合、{@link IllegalArgumentException}例外をスローします。\r
+     * @param filePattern\r
+     *            監視するファイルのパターンを表す正規表現。絶対パスと比較されます。<br>\r
+     *            nullの場合、{@link IllegalArgumentException}例外をスローします。\r
+     */\r
     public FileMonitor(File baseDirectory, Pattern filePattern) {\r
         if (baseDirectory == null) {\r
             throw new IllegalArgumentException("baseDirectory is null.");\r
@@ -33,10 +56,34 @@ public class FileMonitor {
         this.filePattern = filePattern;\r
     }\r
 \r
+    /**\r
+     * <p>\r
+     * 指定したディレクトリの全てのファイルを監視する{@link FileMonitor}インスタンスを初期化します。\r
+     * </p>\r
+     * <p>\r
+     * このコンストラクタ呼び出しは、以下のコードと等価です。\r
+     * </p>\r
+     * <blockquote> new FileMonitor(baseDirectory, Pattern.compile(".*"))\r
+     * </blockquote>\r
+     * \r
+     * @param baseDirectory\r
+     */\r
     public FileMonitor(File baseDirectory) {\r
         this(baseDirectory, Pattern.compile(".*"));\r
     }\r
 \r
+    /**\r
+     * <p>\r
+     * ファイルの作成、更新、削除を認識したときにイベントが通知されるリスナーを追加します。\r
+     * </p>\r
+     * <p>\r
+     * このメソッドはスレッドセーフです。\r
+     * </p>\r
+     * \r
+     * @param listener\r
+     *            イベントが通知されるリスナー。<br>\r
+     *            nullの場合、{@link IllegalArgumentException}例外をスローします。\r
+     */\r
     public void addListener(FileMonitorListener listener) {\r
         if (listener == null) {\r
             throw new IllegalArgumentException("listener is null.");\r
@@ -46,6 +93,17 @@ public class FileMonitor {
         }\r
     }\r
 \r
+    /**\r
+     * <p>\r
+     * 登録されているリスナーを削除します。\r
+     * </p>\r
+     * <p>\r
+     * このメソッドはスレッドセーフです。\r
+     * </p>\r
+     * \r
+     * @param listener\r
+     *            削除するリスナー。\r
+     */\r
     public void removeListener(FileMonitorListener listener) {\r
         synchronized (this.listenerList) {\r
             this.listenerList.remove(listener);\r
@@ -58,6 +116,14 @@ public class FileMonitor {
         }\r
     }\r
 \r
+    /**\r
+     * <p>\r
+     * ファイルの作成、更新、削除を監視し、リスナーにイベントを通知します。\r
+     * </p>\r
+     * \r
+     * @throws IOException\r
+     *             入出力エラーが発生した場合。\r
+     */\r
     public void monitor() throws IOException {\r
         this.checkCreateOrUpdate(this.baseDirectory);\r
         this.checkDelete();\r
index ca6028d..6e58cff 100644 (file)
@@ -3,12 +3,49 @@ package jp.gr.java_conf.uguu.deployer;
 \r
 import java.io.File;\r
 \r
+/**\r
+ * <p>\r
+ * {@link FileMonitor}クラスによるファイル監視のイベントを受け取るリスナーです。\r
+ * </p>\r
+ * \r
+ * @author uguu\r
+ */\r
 public interface FileMonitorListener {\r
 \r
+    /**\r
+     * <p>\r
+     * ファイルが作成されたときに呼び出されます。\r
+     * </p>\r
+     * \r
+     * @param monitor\r
+     *            イベントの通知元の{@link FileMonitor}インスタンス。\r
+     * @param file\r
+     *            作成されたファイル。\r
+     */\r
     void create(FileMonitor monitor, File file);\r
 \r
+    /**\r
+     * <p>\r
+     * ファイルが更新されたときに呼び出されます。\r
+     * </p>\r
+     * \r
+     * @param monitor\r
+     *            イベントの通知元の{@link FileMonitor}インスタンス。\r
+     * @param file\r
+     *            更新されたファイル。\r
+     */\r
     void update(FileMonitor monitor, File file);\r
 \r
+    /**\r
+     * <p>\r
+     * ファイルが削除されたときに呼び出されます。\r
+     * </p>\r
+     * \r
+     * @param monitor\r
+     *            イベントの通知元の{@link FileMonitor}インスタンス。\r
+     * @param file\r
+     *            削除されたファイル。\r
+     */\r
     void delete(FileMonitor monitor, File file);\r
 \r
 }\r