--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<fileset-config file-format-version="1.2.0" simple-config="true">\r
+ <local-check-config name="Uguu Checks" location="G:\work\work-eclipse\deployer\uguu.checkstyle.xml" type="external" description="">\r
+ <additional-data name="protect-config-file" value="false"/>\r
+ </local-check-config>\r
+ <fileset name="all" enabled="true" check-config-name="Uguu Checks" local="true">\r
+ <file-match-pattern match-pattern="." include-pattern="true"/>\r
+ </fileset>\r
+</fileset-config>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+ <classpathentry kind="src" path="src/main/java"/>\r
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>\r
+ <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+ <name>deployer</name>\r
+ <comment></comment>\r
+ <projects>\r
+ </projects>\r
+ <buildSpec>\r
+ <buildCommand>\r
+ <name>org.eclipse.jdt.core.javabuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>com.atlassw.tools.eclipse.checkstyle.CheckstyleBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ </buildSpec>\r
+ <natures>\r
+ <nature>org.eclipse.jdt.core.javanature</nature>\r
+ <nature>com.atlassw.tools.eclipse.checkstyle.CheckstyleNature</nature>\r
+ </natures>\r
+</projectDescription>\r
--- /dev/null
+/*
+ * Copyright (C) 2007 uguu at users.sourceforge.jp, All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of Clarkware Consulting, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact clarkware@clarkware.com.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * CLARKWARE CONSULTING OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="Shift_JIS"?>\r
+<project>\r
+ <modelVersion>4.0.0</modelVersion>\r
+ <groupId>jp.sourceforge.deployer</groupId>\r
+ <artifactId>deployer</artifactId>\r
+ <name>\83f\83v\83\8d\83C\83\84\81[</name>\r
+ <version>1.0.0</version>\r
+ <description>\83z\83b\83g \83f\83v\83\8d\83C\8b@\94\\82ð\8e\9d\82Â\83R\83\93\83|\81[\83l\83\93\83g\82ð\92ñ\8b\9f\82µ\82Ü\82·\81B\83f\83v\83\8d\83C\83\84\81[\82Í\81A\93Á\92è\83f\83B\83\8c\83N\83g\83\8a\82É\83t\83@\83C\83\8b\82ª\94z\92u\82³\82ê\82½\82Æ\82«\81A\82»\82ê\82ð\8dì\8bÆ\83f\83B\83\8c\83N\83g\83\8a\82É\93W\8aJ\82µ\81A\93Æ\8e©\83N\83\89\83X\83\8d\81[\83_\81[\82ð\8d\\92z\82µ\81A\83A\83v\83\8a\83P\81[\83V\83\87\83\93\82É\83C\83x\83\93\83g\82ð\92Ê\92m\82µ\82Ü\82·\81B</description>\r
+ <url>http://deployer.sourceforge.jp/</url>\r
+ <inceptionYear>2007</inceptionYear>\r
+ <developers>\r
+ <developer>\r
+ <id>uguu</id>\r
+ <name>uguu</name>\r
+ <email>uguu@users.sourceforge.jp</email>\r
+ <organization />\r
+ <roles>\r
+ <role>Developer</role>\r
+ </roles>\r
+ </developer>\r
+ </developers>\r
+ <licenses>\r
+ <license>\r
+ <name>BSD License</name>\r
+ <url>LICENSE.txt</url>\r
+ </license>\r
+ </licenses>\r
+ <scm>\r
+ <connection>scm:svn:http://svn.sourceforge.jp/svnroot/deployer/</connection>\r
+ <url>http://svn.sourceforge.jp/svnroot/deployer/</url>\r
+ </scm>\r
+ <organization>\r
+ <name>uguu</name>\r
+ </organization>\r
+ <build>\r
+ <plugins>\r
+ <plugin>\r
+ <groupId>org.apache.maven.plugins</groupId>\r
+ <artifactId>maven-compiler-plugin</artifactId>\r
+ <configuration>\r
+ <source>1.5</source>\r
+ <target>1.5</target>\r
+ </configuration>\r
+ </plugin>\r
+ <plugin>\r
+ <groupId>org.apache.maven.plugins</groupId>\r
+ <artifactId>maven-site-plugin</artifactId>\r
+ <configuration>\r
+ <locales>ja</locales>\r
+ <inputEncoding>Shift_JIS</inputEncoding>\r
+ <outputEncoding>Shift_JIS</outputEncoding>\r
+ </configuration>\r
+ </plugin>\r
+ <plugin>\r
+ <groupId>org.apache.maven.plugins</groupId>\r
+ <artifactId>maven-assembly-plugin</artifactId>\r
+ <configuration>\r
+ <descriptors>\r
+ <descriptor>src/main/assembly/dist.xml</descriptor>\r
+ </descriptors>\r
+ </configuration>\r
+ </plugin>\r
+ </plugins>\r
+ </build>\r
+ <reporting>\r
+ <plugins>\r
+ <plugin>\r
+ <groupId>org.apache.maven.plugins</groupId>\r
+ <artifactId>maven-surefire-report-plugin</artifactId>\r
+ </plugin>\r
+ <plugin>\r
+ <groupId>org.apache.maven.plugins</groupId>\r
+ <artifactId>maven-javadoc-plugin</artifactId>\r
+ <configuration>\r
+ <source>1.5</source>\r
+ <encoding>UTF-8</encoding>\r
+ <charset>Shift_JIS</charset>\r
+ <docencoding>Shift_JIS</docencoding>\r
+ <links>\r
+ <link>http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/</link>\r
+ </links>\r
+ </configuration>\r
+ </plugin>\r
+ <plugin>\r
+ <groupId>org.apache.maven.plugins</groupId>\r
+ <artifactId>maven-changelog-plugin</artifactId>\r
+ </plugin>\r
+ <plugin>\r
+ <groupId>org.apache.maven.plugins</groupId>\r
+ <artifactId>maven-changes-plugin</artifactId>\r
+ <configuration>\r
+ <xmlPath>${basedir}/src/site/changes.xml</xmlPath>\r
+ </configuration>\r
+ <reportSets>\r
+ <reportSet>\r
+ <reports>\r
+ <report>changes-report</report>\r
+ </reports>\r
+ </reportSet>\r
+ </reportSets>\r
+ </plugin>\r
+ <plugin>\r
+ <groupId>org.apache.maven.plugins</groupId>\r
+ <artifactId>maven-checkstyle-plugin</artifactId>\r
+ <configuration>\r
+ <configLocation>uguu.checkstyle.xml</configLocation>\r
+ <propertyExpansion>basedir=./</propertyExpansion>\r
+ </configuration>\r
+ </plugin>\r
+ </plugins>\r
+ </reporting>\r
+</project>\r
--- /dev/null
+<?xml version="1.0" encoding="Shift_JIS"?>\r
+<assembly>\r
+ <formats>\r
+ <format>zip</format>\r
+ <format>tar.gz</format>\r
+ </formats>\r
+ <fileSets>\r
+ <fileSet>\r
+ <directory>src</directory>\r
+ <outputDirectory>src</outputDirectory>\r
+ </fileSet>\r
+ <fileSet>\r
+ <directory>target/site</directory>\r
+ <outputDirectory>docs</outputDirectory>\r
+ </fileSet>\r
+ <fileSet>\r
+ <directory>target</directory>\r
+ <outputDirectory>bin</outputDirectory>\r
+ <includes>\r
+ <include>*.jar</include>\r
+ </includes>\r
+ </fileSet>\r
+ <fileSet>\r
+ <includes>\r
+ <include>LICENSE.txt</include>\r
+ <include>pom.xml</include>\r
+ <include>uguu.checkstyle.xml</include>\r
+ </includes>\r
+ </fileSet>\r
+ </fileSets>\r
+ <dependencySets>\r
+ <dependencySet>\r
+ <unpack>false</unpack>\r
+ <outputDirectory>lib</outputDirectory>\r
+ </dependencySet>\r
+ </dependencySets>\r
+</assembly>\r
--- /dev/null
+/*\r
+ * Copyright (C) 2007 uguu at users.sourceforge.jp, All Rights Reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright\r
+ * notice, this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ * notice, this list of conditions and the following disclaimer in the\r
+ * documentation and/or other materials provided with the distribution.\r
+ *\r
+ * 3. Neither the name of Clarkware Consulting, Inc. nor the names of its\r
+ * contributors may be used to endorse or promote products derived\r
+ * from this software without prior written permission. For written\r
+ * permission, please contact clarkware@clarkware.com.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\r
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL\r
+ * CLARKWARE CONSULTING OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+\r
+package jp.sourceforge.deployer;\r
+\r
+/**\r
+ * <p>\r
+ * クラスローダーを破棄しようとしましたが、タイムアウト時間内に破棄できず失敗したことを表す例外です。クラスローダーからロードされたクラス、クラスのインスタンスなどが解放されていない可能性が高いです。クラスローダーの破棄は、このクラスローダーに属する全てのクラス、インスタンスを破棄してから行ってください。\r
+ * </p>\r
+ * \r
+ * @author $Author$\r
+ * @version $Rev$\r
+ */\r
+public class ClassLoaderUnloadFailException extends RuntimeException {\r
+\r
+ /**\r
+ * <p>\r
+ * インスタンスを初期化します。\r
+ * </p>\r
+ */\r
+ public ClassLoaderUnloadFailException() {\r
+ super("クラスローダーの破棄に失敗しました。");\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2007 uguu at users.sourceforge.jp, All Rights Reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright\r
+ * notice, this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ * notice, this list of conditions and the following disclaimer in the\r
+ * documentation and/or other materials provided with the distribution.\r
+ *\r
+ * 3. Neither the name of Clarkware Consulting, Inc. nor the names of its\r
+ * contributors may be used to endorse or promote products derived\r
+ * from this software without prior written permission. For written\r
+ * permission, please contact clarkware@clarkware.com.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\r
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL\r
+ * CLARKWARE CONSULTING OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+\r
+package jp.sourceforge.deployer;\r
+\r
+/**\r
+ * <p>\r
+ * クラスローダーが既に破棄されていることを表す例外です。クラスローダーが破棄されているにもかかわらず、何らかの操作を行おうとしたときにスローされます。\r
+ * </p>\r
+ * \r
+ * @author $Author$\r
+ * @version $Rev$\r
+ */\r
+public class ClassLoaderUnloadedException extends RuntimeException {\r
+\r
+ /**\r
+ * <p>\r
+ * インスタンスを初期化します。\r
+ * </p>\r
+ */\r
+ public ClassLoaderUnloadedException() {\r
+ super("クラスローダーは既に破棄されています。");\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2007 uguu at users.sourceforge.jp, All Rights Reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright\r
+ * notice, this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ * notice, this list of conditions and the following disclaimer in the\r
+ * documentation and/or other materials provided with the distribution.\r
+ *\r
+ * 3. Neither the name of Clarkware Consulting, Inc. nor the names of its\r
+ * contributors may be used to endorse or promote products derived\r
+ * from this software without prior written permission. For written\r
+ * permission, please contact clarkware@clarkware.com.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\r
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL\r
+ * CLARKWARE CONSULTING OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+\r
+package jp.sourceforge.deployer;\r
+\r
+/**\r
+ * <p>\r
+ * 定数を定義します。\r
+ * </p>\r
+ * \r
+ * @author $Author$\r
+ * @version $Rev$\r
+ */\r
+public final class Consts {\r
+\r
+ /**\r
+ * <p>\r
+ * {@link Thread#sleep(long)}メソッドに指定する単位時間です。\r
+ * </p>\r
+ */\r
+ public static final int SLEEP_UNIT_TIME = 1000;\r
+\r
+ /**\r
+ * <p>\r
+ * 入出力処理で使用するバッファの長さです。\r
+ * </p>\r
+ */\r
+ public static final int BUFFER_LENGTH = 1024;\r
+\r
+ /**\r
+ * <p>\r
+ * インスタンス化を禁止します。\r
+ * </p>\r
+ */\r
+ private Consts() {\r
+ throw new UnsupportedOperationException();\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2007 uguu at users.sourceforge.jp, All Rights Reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright\r
+ * notice, this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ * notice, this list of conditions and the following disclaimer in the\r
+ * documentation and/or other materials provided with the distribution.\r
+ *\r
+ * 3. Neither the name of Clarkware Consulting, Inc. nor the names of its\r
+ * contributors may be used to endorse or promote products derived\r
+ * from this software without prior written permission. For written\r
+ * permission, please contact clarkware@clarkware.com.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\r
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL\r
+ * CLARKWARE CONSULTING OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+\r
+package jp.sourceforge.deployer;\r
+\r
+import java.io.File;\r
+import java.io.FileInputStream;\r
+import java.io.FileNotFoundException;\r
+import java.io.FileOutputStream;\r
+import java.io.IOException;\r
+import java.nio.channels.FileLock;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+import java.util.regex.Pattern;\r
+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 $Author$\r
+ * @version $Rev$\r
+ */\r
+public final class Deployer {\r
+\r
+ /**\r
+ * <p>\r
+ * リスナーのリスト。\r
+ * </p>\r
+ */\r
+ private List<DeployerListener> _listenerList = new ArrayList<DeployerListener>();\r
+\r
+ /**\r
+ * <p>\r
+ * 配置ディレクトリ。\r
+ * </p>\r
+ */\r
+ private File _deployDirectory;\r
+\r
+ /**\r
+ * <p>\r
+ * アーカイブ・ファイルであると認識するファイルのパターン。\r
+ * </p>\r
+ */\r
+ private Pattern _filePattern;\r
+\r
+ /**\r
+ * <p>\r
+ * 作業ディレクトリ。\r
+ * </p>\r
+ */\r
+ private File _workDirectory;\r
+\r
+ /**\r
+ * <p>\r
+ * ファイル監視。\r
+ * </p>\r
+ */\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
+ }\r
+ if (!deployDirectory.isDirectory()) {\r
+ throw new IllegalArgumentException("deployDirectory is not directory.");\r
+ }\r
+ if (filePattern == null) {\r
+ throw new IllegalArgumentException("filePattern is null.");\r
+ }\r
+ if (workDirectory == null) {\r
+ throw new IllegalArgumentException("workDirectory is null.");\r
+ }\r
+ if (!workDirectory.isDirectory()) {\r
+ throw new IllegalArgumentException("workDirectory is not directory.");\r
+ }\r
+\r
+ this._deployDirectory = deployDirectory;\r
+ this._filePattern = filePattern;\r
+ this._workDirectory = workDirectory;\r
+\r
+ // ディレクトリの監視を開始する。\r
+ this._fileMonitor = new FileMonitor(this._deployDirectory, this._filePattern);\r
+ 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
+ }\r
+ synchronized (this._listenerList) {\r
+ this._listenerList.add(listener);\r
+ }\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 FileMonitorFailException\r
+ * ファイルの監視に失敗した場合。\r
+ */\r
+ public void monitor() throws FileMonitorFailException {\r
+ this._fileMonitor.monitor();\r
+ }\r
+\r
+ /**\r
+ * <p>\r
+ * デプロイします。\r
+ * </p>\r
+ * \r
+ * @param file\r
+ * アーカイブ・ファイル。\r
+ * @throws IOException\r
+ * 入出力に失敗した場合。\r
+ */\r
+ private void deploy(File file) throws IOException {\r
+ // イベントを通知する。\r
+ synchronized (this._listenerList) {\r
+ for (DeployerListener l : this._listenerList) {\r
+ l.deployStart(this, file);\r
+ }\r
+ }\r
+ // デプロイ先のディレクトリを削除する。\r
+ File destDir = this.getDestDirectory(file, this._deployDirectory, this._workDirectory);\r
+ if (destDir.exists()) {\r
+ this.delete(destDir);\r
+ this.deleteWithParent(destDir.getParentFile());\r
+ }\r
+ // デプロイ先のディレクトリを作成する。\r
+ if (!destDir.mkdirs()) {\r
+ throw new DirectoryCreateFailException(destDir);\r
+ }\r
+ // デプロイ先に展開する。\r
+ this.decompress(file, destDir);\r
+ // イベントを通知する。\r
+ synchronized (this._listenerList) {\r
+ for (DeployerListener l : this._listenerList) {\r
+ l.deployEnd(this, file, destDir);\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * <p>\r
+ * アンデプロイします。\r
+ * </p>\r
+ * \r
+ * @param file\r
+ * アーカイブ・ファイル。\r
+ * @throws IOException\r
+ * 入出力に失敗した場合。\r
+ */\r
+ private void undeploy(File file) throws IOException {\r
+ File destDir = this.getDestDirectory(file, this._deployDirectory, this._workDirectory);\r
+ // イベントを通知する。\r
+ synchronized (this._listenerList) {\r
+ for (DeployerListener l : this._listenerList) {\r
+ l.undeployStart(this, file, destDir);\r
+ }\r
+ }\r
+ // デプロイ先のディレクトリを削除する。\r
+ this.delete(destDir);\r
+ this.deleteWithParent(destDir.getParentFile());\r
+ // イベントを通知する。\r
+ synchronized (this._listenerList) {\r
+ for (DeployerListener l : this._listenerList) {\r
+ l.undeployEnd(this, file);\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * <p>\r
+ * アーカイブ・ファイルを展開します。\r
+ * </p>\r
+ * \r
+ * @param file\r
+ * 展開するアーカイブ・ファイル。\r
+ * @param destDir\r
+ * 展開先ディレクトリ。\r
+ * @throws IOException\r
+ * 入出力に失敗した場合。\r
+ */\r
+ private void decompress(File file, File destDir) throws IOException {\r
+ FileInputStream fileIn = null;\r
+ while (fileIn == null) {\r
+ try {\r
+ fileIn = new FileInputStream(file);\r
+ } catch (FileNotFoundException e) {\r
+ fileIn = null;\r
+ try {\r
+ Thread.sleep(Consts.SLEEP_UNIT_TIME);\r
+ } catch (InterruptedException e1) {\r
+ e1.printStackTrace();\r
+ }\r
+ }\r
+ }\r
+ try {\r
+ ZipInputStream zipIn = new ZipInputStream(fileIn);\r
+ try {\r
+ FileLock lock = fileIn.getChannel().lock(0, Long.MAX_VALUE, true);\r
+ try {\r
+ ZipEntry zipEntry;\r
+ 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 FileCreateFailException(f);\r
+ }\r
+ // ファイルを展開します。\r
+ FileOutputStream fileOut = new FileOutputStream(f);\r
+ try {\r
+ byte[] buf = new byte[Consts.BUFFER_LENGTH];\r
+ int len;\r
+ while ((len = zipIn.read(buf)) != -1) {\r
+ fileOut.write(buf, 0, len);\r
+ }\r
+ } finally {\r
+ fileOut.close();\r
+ }\r
+ } else {\r
+ File dir = new File(destDir, zipEntry.getName().replace('/', File.separatorChar));\r
+ if (!dir.mkdirs()) {\r
+ throw new DirectoryCreateFailException(dir);\r
+ }\r
+ }\r
+ }\r
+ } finally {\r
+ lock.release();\r
+ }\r
+ } finally {\r
+ zipIn.close();\r
+ }\r
+ } finally {\r
+ fileIn.close();\r
+ }\r
+ }\r
+\r
+ /**\r
+ * <p>\r
+ * ディレクトリを完全に削除します。\r
+ * </p>\r
+ * \r
+ * @param dir\r
+ * 削除するディレクトリ。\r
+ * @throws IOException\r
+ * 削除に失敗した場合。\r
+ */\r
+ private void delete(File dir) throws IOException {\r
+ for (File f : dir.listFiles()) {\r
+ if (!f.isDirectory()) {\r
+ if (!f.delete()) {\r
+ throw new FileDeleteFailException(f);\r
+ }\r
+ } else {\r
+ this.delete(f);\r
+ }\r
+ }\r
+ if (!dir.delete()) {\r
+ throw new DirectoryDeleteFailException(dir);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * <p>\r
+ * 親ディレクトリが空であるならば、作業ディレクトリまで遡って削除します。\r
+ * </p>\r
+ * \r
+ * @param dir\r
+ * 削除するディレクトリ。\r
+ * @throws IOException\r
+ * 削除に失敗した場合。\r
+ */\r
+ private void deleteWithParent(File dir) throws IOException {\r
+ if (this._workDirectory.getAbsolutePath().equals(dir.getAbsolutePath())) {\r
+ return;\r
+ }\r
+ if (dir.listFiles().length > 0) {\r
+ return;\r
+ }\r
+ File parentDir = dir.getParentFile();\r
+ if (!dir.delete()) {\r
+ throw new IOException("ディレクトリ\"" + dir.getAbsolutePath() + "\"の削除に失敗しました。");\r
+ }\r
+ this.deleteWithParent(parentDir);\r
+ }\r
+\r
+ /**\r
+ * <p>\r
+ * アーカイブ・ファイルの展開先ディレクトリを算出します。アーカイブ・ファイルの展開先は配置ディレクトリからの相対パスであるため、少し操作が必要になります。\r
+ * </p>\r
+ * \r
+ * @param archiveFile\r
+ * 展開するアーカイブ・ファイル。\r
+ * @param deployDirectory\r
+ * 配置ディレクトリ。\r
+ * @param workDirectory\r
+ * 作業ディレクトリ。\r
+ * @return アーカイブ・ファイルの展開先ディレクトリ。\r
+ */\r
+ private File getDestDirectory(File archiveFile, File deployDirectory, File workDirectory) {\r
+ String name = archiveFile.getAbsolutePath().substring(deployDirectory.getAbsolutePath().length());\r
+ File dir = new File(workDirectory, name);\r
+ return dir;\r
+ }\r
+\r
+ /**\r
+ * <p>\r
+ * 配置ディレクトリを監視します。\r
+ * </p>\r
+ */\r
+ private class FileMonitorListenerImpl implements FileMonitorListener {\r
+\r
+ /**\r
+ * <p>\r
+ * インスタンスを初期化します。\r
+ * </p>\r
+ */\r
+ public FileMonitorListenerImpl() {\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ public void create(FileMonitor monitor, File file) {\r
+ try {\r
+ Deployer.this.deploy(file);\r
+ } catch (IOException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ public void delete(FileMonitor monitor, File file) {\r
+ try {\r
+ Deployer.this.undeploy(file);\r
+ } catch (IOException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ public void update(FileMonitor monitor, File file) {\r
+ try {\r
+ Deployer.this.undeploy(file);\r
+ Deployer.this.deploy(file);\r
+ } catch (IOException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2007 uguu at users.sourceforge.jp, All Rights Reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright\r
+ * notice, this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ * notice, this list of conditions and the following disclaimer in the\r
+ * documentation and/or other materials provided with the distribution.\r
+ *\r
+ * 3. Neither the name of Clarkware Consulting, Inc. nor the names of its\r
+ * contributors may be used to endorse or promote products derived\r
+ * from this software without prior written permission. For written\r
+ * permission, please contact clarkware@clarkware.com.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\r
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL\r
+ * CLARKWARE CONSULTING OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+\r
+package jp.sourceforge.deployer;\r
+\r
+import java.io.File;\r
+import java.io.IOException;\r
+import java.lang.ref.WeakReference;\r
+import java.net.MalformedURLException;\r
+import java.net.URL;\r
+import java.net.URLClassLoader;\r
+import java.util.ArrayList;\r
+import java.util.Enumeration;\r
+import java.util.List;\r
+\r
+/**\r
+ * <p>\r
+ * アーカイブ・ファイル配置後のクラスやリソースを読み込むクラスローダーです。\r
+ * </p>\r
+ * <p>\r
+ * アーカイブ・ファイルにはクラス・ファイル、リソース、jarファイルを含めることが出来、コンストラクタでディレクトリを指定することでクラスローダーの管理下に置くことができます。例えば、classes/からクラス・ファイル、lib/からjarファイルを検索するように初期化することが出来ます。ディレクトリは複数指定することが出来ます。\r
+ * </p>\r
+ * <p>\r
+ * 内部的には{@link URLClassLoader}クラスを使用しています。コンストラクタで指定された検索対象ディレクトリ、及びjarディレクトリに含まれるjarファイルは、{@link URLClassLoader}クラスにURLで渡されます。{@link #dispose()}メソッドが呼び出されると、{@link URLClassLoader}インスタンスは破棄され、強制的にガベージコレクタを動かすことで完全に破棄します(破棄しようとします。クラスローダーが読み込んだクラス内でリソースリークが発生している場合、破棄は失敗し、ブロックしてしまいます)。\r
+ * </p>\r
+ * <p>\r
+ * ホット・デプロイを前提としているので、クラスローダーが読み込んだリソースなどを破棄する{@link #dispose()}メソッドが用意されています。例えば{@link Deployer}クラスと連携する場合、{@link DeployerListener#undeployEnd(Deployer, File)}メソッドの呼び出しでこのクラスローダーを破棄することが出来ます。\r
+ * </p>\r
+ * \r
+ * @author $Author$\r
+ * @version $Rev$\r
+ */\r
+public final class DeployerClassLoader extends ClassLoader {\r
+\r
+ /**\r
+ * 内部クラスローダの弱参照。参照の有効性を調べることで、クラスローダの破棄が成功したかどうかを判定するために使用しています。\r
+ */\r
+ private WeakReference<InternalURLClassLoader> wrCL;\r
+\r
+ /**\r
+ * 内部クラスローダ。クラスローダの実際の処理は、この内部クラスローダが行っています。\r
+ */\r
+ private InternalURLClassLoader cl;\r
+\r
+ /**\r
+ * <p>\r
+ * {@link DeployerClassLoader}インスタンスを初期化します。\r
+ * </p>\r
+ * \r
+ * @param fileDirectories\r
+ * クラス・ファイル、リソースなどを検索するディレクトリ。複数指定することが出来ます(例えば、classes/、conf/のように)。<br>\r
+ * nullの場合は無視します。配列中のnullも無視します。\r
+ * @param jarDirectories\r
+ * jarファイルを検索するディレクトリ。このディレクトリ以下に存在するjarファイルを読み込みます。<br>\r
+ * nullの場合は無視します。配列中のnullも無視します。\r
+ * @param parent\r
+ * 親クラスローダー。\r
+ * @throws MalformedURLException\r
+ * 指定されたディレクトリの形式が不正である場合。\r
+ */\r
+ public DeployerClassLoader(File[] fileDirectories, File[] jarDirectories, ClassLoader parent) throws MalformedURLException {\r
+ super();\r
+\r
+ /*\r
+ * クラスローダの検索パスとして追加するURLを収集します。\r
+ */\r
+ List<URL> urlList = new ArrayList<URL>();\r
+\r
+ // クラス・ファイル、リソースなどを検索するディレクトリのパスを追加します。\r
+ if (fileDirectories != null) {\r
+ for (File f : fileDirectories) {\r
+ if (f != null) {\r
+ urlList.add(f.toURL());\r
+ }\r
+ }\r
+ }\r
+\r
+ // jarファイルのパスを追加します。\r
+ if (jarDirectories != null) {\r
+ for (File f : jarDirectories) {\r
+ if (f != null) {\r
+ urlList.addAll(this.getJarFileList(f));\r
+ }\r
+ }\r
+ }\r
+\r
+ /*\r
+ * 内部クラスローダを初期化します。\r
+ */\r
+ if (parent == null) {\r
+ this.cl = new InternalURLClassLoader(urlList.toArray(new URL[0]));\r
+ } else {\r
+ this.cl = new InternalURLClassLoader(urlList.toArray(new URL[0]), parent);\r
+ }\r
+ // 内部クラスローダの破棄を確認するため、弱参照を保持します。\r
+ this.wrCL = new WeakReference<InternalURLClassLoader>(this.cl);\r
+ }\r
+\r
+ /**\r
+ * <p>\r
+ * {@link DeployerClassLoader}インスタンスを初期化します。\r
+ * </p>\r
+ * \r
+ * @param fileDirectories\r
+ * クラス・ファイル、リソースなどを検索するディレクトリ。複数指定することが出来ます(例えば、classes/、conf/のように)。<br>\r
+ * nullの場合は無視します。配列中のnullも無視します。\r
+ * @param jarDirectories\r
+ * jarファイルを検索するディレクトリ。このディレクトリ以下に存在するjarファイルを読み込みます。<br>\r
+ * nullの場合は無視します。配列中のnullも無視します。\r
+ * @throws MalformedURLException\r
+ * 指定されたディレクトリの形式が不正である場合。\r
+ */\r
+ public DeployerClassLoader(File[] fileDirectories, File[] jarDirectories) throws MalformedURLException {\r
+ this(fileDirectories, jarDirectories, null);\r
+ }\r
+\r
+ /**\r
+ * <p>\r
+ * 指定されたディレクトリ以下のjarファイルを検索し、そのURLをリストとして返します。\r
+ * </p>\r
+ * \r
+ * @param dir\r
+ * 検索するディレクトリ。<br>\r
+ * nullの場合は空のリストを返します。\r
+ * @return 検索結果のURLのリスト。\r
+ * @throws MalformedURLException\r
+ * URLの形式が不正である場合。\r
+ */\r
+ private List<URL> getJarFileList(File dir) throws MalformedURLException {\r
+ List<URL> urlList = new ArrayList<URL>();\r
+\r
+ if (dir == null) {\r
+ return urlList;\r
+ }\r
+\r
+ File[] files = dir.listFiles();\r
+ if (files == null) {\r
+ return urlList;\r
+ }\r
+\r
+ for (File f : files) {\r
+ if (f.isFile() && f.getName().toLowerCase().endsWith(".jar")) {\r
+ urlList.add(f.toURL());\r
+ } else if (f.isDirectory()) {\r
+ urlList.addAll(this.getJarFileList(f));\r
+ }\r
+ }\r
+\r
+ return urlList;\r
+ }\r
+\r
+ /**\r
+ * <p>\r
+ * クラスローダーを破棄します。これにより、クラスローダーは使用不可状態になり、クラスローダーに属していたクラスは解放されます。\r
+ * </p>\r
+ * <p>\r
+ * このメソッド呼び出しはタイムアウトしません。すなわち、以下のコードと等価です。\r
+ * </p>\r
+ * \r
+ * <pre>\r
+ * cl.dispose(0);\r
+ * </pre>\r
+ */\r
+ public void dispose() {\r
+ this.dispose(0);\r
+ }\r
+\r
+ /**\r
+ * <p>\r
+ * クラスローダーを破棄します。これにより、クラスローダーは使用不可状態になり、クラスローダーに属していたクラスは解放されます。\r
+ * </p>\r
+ * <p>\r
+ * メソッド呼び出しの結果、クラスローダーはすぐに使用不可状態になりますが、属しているクラスの解放はすぐには行われない可能性があります。これは、クラスローダーのリソースの解放を強制ガベージコレクタに頼っているためです。このため、タイムアウト時間を指定することが出来ます。タイムアウト時間は破棄を試みますが、それでも破棄出来ない場合は{@link ClassLoaderUnloadFailException}例外をスローします。この場合、クラスローダーは使用不可状態になっていますが、クラスは破棄されていません。完全に破棄するために、このメソッド呼び出しを何度も試みることが出来ます。\r
+ * </p>\r
+ * \r
+ * @param timeout\r
+ * 破棄を試みるタイムアウト時間。0以下の場合、タイムアウトしない。\r
+ */\r
+ public void dispose(int timeout) {\r
+ this.cl = null;\r
+\r
+ // タイムアウト時間が経過するまで、破棄を試みます。\r
+ long t = System.currentTimeMillis();\r
+ while (((System.currentTimeMillis() - t) < timeout) || timeout <= 0) {\r
+ // 内部クラスローダを破棄するため、強制的にガベージコレクションを試みます。\r
+ System.gc();\r
+\r
+ // 内部クラスローダへの弱参照がnullになっている場合、破棄されたことを表します。\r
+ // 従って、処理を抜けます。\r
+ if (this.wrCL.get() == null) {\r
+ break;\r
+ }\r
+\r
+ // 処理の間隔をあけるため、単位時間の間、処理を中断します。\r
+ try {\r
+ Thread.sleep(Consts.SLEEP_UNIT_TIME);\r
+ } catch (InterruptedException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+\r
+ // 弱参照がnullではない場合、タイムアウトしたことを表します。\r
+ // 従って、例外をスローします。\r
+ if (this.wrCL.get() != null) {\r
+ throw new ClassLoaderUnloadFailException();\r
+ }\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ protected Package definePackage(String name, String specTitle, String specVersion, String specVendor, String implTitle, String implVersion, String implVendor, URL sealBase) {\r
+ if (this.cl == null) {\r
+ throw new ClassLoaderUnloadedException();\r
+ }\r
+ return this.cl.definePackage(name, specTitle, specVersion, specVendor, implTitle, implVersion, implVendor, sealBase);\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ protected Class<?> findClass(String name) throws ClassNotFoundException {\r
+ if (this.cl == null) {\r
+ throw new ClassLoaderUnloadedException();\r
+ }\r
+ return this.cl.findClass(name);\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ protected String findLibrary(String libname) {\r
+ if (this.cl == null) {\r
+ throw new ClassLoaderUnloadedException();\r
+ }\r
+ return this.cl.findLibrary(libname);\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ protected URL findResource(String name) {\r
+ if (this.cl == null) {\r
+ throw new ClassLoaderUnloadedException();\r
+ }\r
+ return this.cl.findResource(name);\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ protected Enumeration<URL> findResources(String name) throws IOException {\r
+ if (this.cl == null) {\r
+ throw new ClassLoaderUnloadedException();\r
+ }\r
+ return this.cl.findResources(name);\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ protected Package getPackage(String name) {\r
+ if (this.cl == null) {\r
+ throw new ClassLoaderUnloadedException();\r
+ }\r
+ return this.cl.getPackage(name);\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ protected Package[] getPackages() {\r
+ if (this.cl == null) {\r
+ throw new ClassLoaderUnloadedException();\r
+ }\r
+ return this.cl.getPackages();\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {\r
+ if (this.cl == null) {\r
+ throw new ClassLoaderUnloadedException();\r
+ }\r
+ return this.cl.loadClass(name, resolve);\r
+ }\r
+\r
+ /**\r
+ * <p>\r
+ * 内部クラスローダ。必要なメソッドのアクセス修飾子をpublicに変更するために定義します。\r
+ * </p>\r
+ * \r
+ * @author uguu\r
+ */\r
+ private class InternalURLClassLoader extends URLClassLoader {\r
+\r
+ /**\r
+ * <p>\r
+ * インスタンスを初期化します。\r
+ * </p>\r
+ * \r
+ * @param urls\r
+ * 検索パスに含めるURLの配列。\r
+ */\r
+ public InternalURLClassLoader(URL[] urls) {\r
+ super(urls);\r
+ }\r
+\r
+ /**\r
+ * <p>\r
+ * インスタンスを初期化します。\r
+ * </p>\r
+ * \r
+ * @param urls\r
+ * 検索パスに含めるURLの配列。\r
+ * @param parent\r
+ * 親クラスローダー。\r
+ */\r
+ public InternalURLClassLoader(URL[] urls, ClassLoader parent) {\r
+ super(urls, parent);\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ public Package definePackage(String name, String specTitle, String specVersion, String specVendor, String implTitle, String implVersion, String implVendor, URL sealBase) {\r
+ return super.definePackage(name, specTitle, specVersion, specVendor, implTitle, implVersion, implVendor, sealBase);\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ public Class<?> findClass(String name) throws ClassNotFoundException {\r
+ return super.findClass(name);\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ public String findLibrary(String libname) {\r
+ return super.findLibrary(libname);\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ public Package getPackage(String name) {\r
+ return super.getPackage(name);\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ public Package[] getPackages() {\r
+ return super.getPackages();\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ public synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {\r
+ return super.loadClass(name, resolve);\r
+ }\r
+\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2007 uguu at users.sourceforge.jp, All Rights Reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright\r
+ * notice, this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ * notice, this list of conditions and the following disclaimer in the\r
+ * documentation and/or other materials provided with the distribution.\r
+ *\r
+ * 3. Neither the name of Clarkware Consulting, Inc. nor the names of its\r
+ * contributors may be used to endorse or promote products derived\r
+ * from this software without prior written permission. For written\r
+ * permission, please contact clarkware@clarkware.com.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\r
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL\r
+ * CLARKWARE CONSULTING OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+\r
+package jp.sourceforge.deployer;\r
+\r
+import java.io.File;\r
+\r
+/**\r
+ * <p>\r
+ * {@link Deployer}クラスによるファイル配置のイベントを受け取るリスナーです。\r
+ * </p>\r
+ * \r
+ * @author $Author$\r
+ * @version $Rev$\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
--- /dev/null
+/*\r
+ * Copyright (C) 2007 uguu at users.sourceforge.jp, All Rights Reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright\r
+ * notice, this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ * notice, this list of conditions and the following disclaimer in the\r
+ * documentation and/or other materials provided with the distribution.\r
+ *\r
+ * 3. Neither the name of Clarkware Consulting, Inc. nor the names of its\r
+ * contributors may be used to endorse or promote products derived\r
+ * from this software without prior written permission. For written\r
+ * permission, please contact clarkware@clarkware.com.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\r
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL\r
+ * CLARKWARE CONSULTING OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+\r
+package jp.sourceforge.deployer;\r
+\r
+import java.io.File;\r
+import java.io.IOException;\r
+\r
+/**\r
+ * <p>\r
+ * ディレクトリの作成に失敗したことを表す例外です。\r
+ * </p>\r
+ * \r
+ * @author $Author$\r
+ * @version $Rev$\r
+ */\r
+public class DirectoryCreateFailException extends IOException {\r
+\r
+ /**\r
+ * <p>\r
+ * インスタンスを初期化します。\r
+ * </p>\r
+ * \r
+ * @param dir\r
+ * 作成に失敗したディレクトリ。\r
+ */\r
+ public DirectoryCreateFailException(File dir) {\r
+ super("ディレクトリ\"" + dir.getAbsolutePath() + "\"の作成に失敗しました。");\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2007 uguu at users.sourceforge.jp, All Rights Reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright\r
+ * notice, this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ * notice, this list of conditions and the following disclaimer in the\r
+ * documentation and/or other materials provided with the distribution.\r
+ *\r
+ * 3. Neither the name of Clarkware Consulting, Inc. nor the names of its\r
+ * contributors may be used to endorse or promote products derived\r
+ * from this software without prior written permission. For written\r
+ * permission, please contact clarkware@clarkware.com.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\r
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL\r
+ * CLARKWARE CONSULTING OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+\r
+package jp.sourceforge.deployer;\r
+\r
+import java.io.File;\r
+import java.io.IOException;\r
+\r
+/**\r
+ * <p>\r
+ * ディレクトリの削除に失敗したことを表す例外です。\r
+ * </p>\r
+ * \r
+ * @author $Author$\r
+ * @version $Rev$\r
+ */\r
+public class DirectoryDeleteFailException extends IOException {\r
+\r
+ /**\r
+ * <p>\r
+ * インスタンスを初期化します。\r
+ * </p>\r
+ * \r
+ * @param dir\r
+ * 削除に失敗したディレクトリ。\r
+ */\r
+ public DirectoryDeleteFailException(File dir) {\r
+ super("ディレクトリ\"" + dir.getAbsolutePath() + "\"の削除に失敗しました。");\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2007 uguu at users.sourceforge.jp, All Rights Reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright\r
+ * notice, this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ * notice, this list of conditions and the following disclaimer in the\r
+ * documentation and/or other materials provided with the distribution.\r
+ *\r
+ * 3. Neither the name of Clarkware Consulting, Inc. nor the names of its\r
+ * contributors may be used to endorse or promote products derived\r
+ * from this software without prior written permission. For written\r
+ * permission, please contact clarkware@clarkware.com.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\r
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL\r
+ * CLARKWARE CONSULTING OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+\r
+package jp.sourceforge.deployer;\r
+\r
+import java.io.File;\r
+import java.io.IOException;\r
+\r
+/**\r
+ * <p>\r
+ * ファイルの作成に失敗したことを表す例外です。\r
+ * </p>\r
+ * \r
+ * @author $Author$\r
+ * @version $Rev$\r
+ */\r
+public class FileCreateFailException extends IOException {\r
+\r
+ /**\r
+ * <p>\r
+ * インスタンスを初期化します。\r
+ * </p>\r
+ * \r
+ * @param file\r
+ * 作成に失敗したファイル。\r
+ */\r
+ public FileCreateFailException(File file) {\r
+ super("ファイル\"" + file.getAbsolutePath() + "\"の作成に失敗しました。");\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2007 uguu at users.sourceforge.jp, All Rights Reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright\r
+ * notice, this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ * notice, this list of conditions and the following disclaimer in the\r
+ * documentation and/or other materials provided with the distribution.\r
+ *\r
+ * 3. Neither the name of Clarkware Consulting, Inc. nor the names of its\r
+ * contributors may be used to endorse or promote products derived\r
+ * from this software without prior written permission. For written\r
+ * permission, please contact clarkware@clarkware.com.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\r
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL\r
+ * CLARKWARE CONSULTING OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+\r
+package jp.sourceforge.deployer;\r
+\r
+import java.io.File;\r
+import java.io.IOException;\r
+\r
+/**\r
+ * <p>\r
+ * ファイルの削除に失敗したことを表す例外です。\r
+ * </p>\r
+ * \r
+ * @author $Author$\r
+ * @version $Rev$\r
+ */\r
+public class FileDeleteFailException extends IOException {\r
+\r
+ /**\r
+ * <p>\r
+ * インスタンスを初期化します。\r
+ * </p>\r
+ * \r
+ * @param file\r
+ * 削除に失敗したファイル。\r
+ */\r
+ public FileDeleteFailException(File file) {\r
+ super("ファイル\"" + file.getAbsolutePath() + "\"の削除に失敗しました。");\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2007 uguu at users.sourceforge.jp, All Rights Reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright\r
+ * notice, this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ * notice, this list of conditions and the following disclaimer in the\r
+ * documentation and/or other materials provided with the distribution.\r
+ *\r
+ * 3. Neither the name of Clarkware Consulting, Inc. nor the names of its\r
+ * contributors may be used to endorse or promote products derived\r
+ * from this software without prior written permission. For written\r
+ * permission, please contact clarkware@clarkware.com.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\r
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL\r
+ * CLARKWARE CONSULTING OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+\r
+package jp.sourceforge.deployer;\r
+\r
+import java.io.File;\r
+import java.io.FileInputStream;\r
+import java.io.IOException;\r
+import java.security.MessageDigest;\r
+import java.security.NoSuchAlgorithmException;\r
+import java.util.ArrayList;\r
+import java.util.Arrays;\r
+import java.util.HashMap;\r
+import java.util.List;\r
+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 $Author$\r
+ * @version $Rev$\r
+ */\r
+public final class FileMonitor {\r
+\r
+ /**\r
+ * <p>\r
+ * リスナーのリスト。\r
+ * </p>\r
+ */\r
+ private List<FileMonitorListener> _listenerList = new ArrayList<FileMonitorListener>();\r
+\r
+ /**\r
+ * <p>\r
+ * 監視する基底ディレクトリ。\r
+ * </p>\r
+ */\r
+ private File _baseDirectory;\r
+\r
+ /**\r
+ * <p>\r
+ * 監視するファイルの正規表現パターン。\r
+ * </p>\r
+ */\r
+ private Pattern _filePattern;\r
+\r
+ /**\r
+ * <p>\r
+ * 監視中ファイルの情報。\r
+ * </p>\r
+ */\r
+ private Map<String, MonitoringFileInfo> _monitoringFileMap = new HashMap<String, MonitoringFileInfo>();\r
+\r
+ /**\r
+ * <p>\r
+ * ファイルの長さを比較するか。\r
+ * </p>\r
+ */\r
+ private boolean _checkLength = true;\r
+\r
+ /**\r
+ * <p>\r
+ * ファイルの最終更新日時を比較するか。\r
+ * </p>\r
+ */\r
+ private boolean _checkLastModified = true;\r
+\r
+ /**\r
+ * <p>\r
+ * ファイルの内容を確認するか。\r
+ * </p>\r
+ */\r
+ private boolean _checkContent;\r
+\r
+ /**\r
+ * <p>\r
+ * ハッシュ・アルゴリズム。\r
+ * </p>\r
+ */\r
+ private String _hashAlgorithm = "MD5";\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
+ }\r
+ if (!baseDirectory.isDirectory()) {\r
+ throw new IllegalArgumentException("baseDirectory is not directory.");\r
+ }\r
+ if (filePattern == null) {\r
+ throw new IllegalArgumentException("filePattern is null.");\r
+ }\r
+ this._baseDirectory = baseDirectory;\r
+ this._filePattern = filePattern;\r
+ }\r
+\r
+ /**\r
+ * <p>\r
+ * 指定したディレクトリの全てのファイルを監視する{@link FileMonitor}インスタンスを初期化します。\r
+ * </p>\r
+ * <p>\r
+ * このコンストラクタ呼び出しは、以下のコードと等価です。\r
+ * </p>\r
+ * \r
+ * <pre>\r
+ * new FileMonitor(baseDirectory, Pattern.compile(".*"))\r
+ * </pre>\r
+ * \r
+ * @param baseDirectory\r
+ * 監視するディレクトリ。<br>\r
+ * nullの場合、{@link IllegalArgumentException}例外をスローします。<br>\r
+ * ディレクトリを表していない場合、{@link IllegalArgumentException}例外をスローします。\r
+ */\r
+ public FileMonitor(File baseDirectory) {\r
+ this(baseDirectory, Pattern.compile(".*"));\r
+ }\r
+\r
+ /**\r
+ * <p>\r
+ * ファイル・サイズを監視するかどうかを取得します。初期値はtrueです。\r
+ * </p>\r
+ * \r
+ * @return ファイル・サイズを監視する場合はtrue、監視しない場合はfalse。\r
+ */\r
+ public boolean isCheckLength() {\r
+ return this._checkLength;\r
+ }\r
+\r
+ /**\r
+ * <p>\r
+ * ファイル・サイズを監視するかどうかを設定します。\r
+ * </p>\r
+ * \r
+ * @param checkLength\r
+ * ファイル・サイズを監視する場合はtrue、監視しない場合はfalse。\r
+ */\r
+ public void setCheckLength(boolean checkLength) {\r
+ this._checkLength = checkLength;\r
+ }\r
+\r
+ /**\r
+ * <p>\r
+ * 最終更新日時を監視するかどうかを取得します。初期値はtrueです。\r
+ * </p>\r
+ * \r
+ * @return 最終更新日時を監視する場合はtrue、監視しない場合はfalse。\r
+ */\r
+ public boolean isCheckLastModified() {\r
+ return this._checkLastModified;\r
+ }\r
+\r
+ /**\r
+ * <p>\r
+ * 最終更新日時を監視するかどうかを設定します。\r
+ * </p>\r
+ * \r
+ * @param checkLastModified\r
+ * 最終更新日時を監視する場合はtrue、監視しない場合はfalse。\r
+ */\r
+ public void setCheckLastModified(boolean checkLastModified) {\r
+ this._checkLastModified = checkLastModified;\r
+ }\r
+\r
+ /**\r
+ * <p>\r
+ * ファイルの内容(ハッシュ値)を監視するかどうかを取得します。初期値はfalseです。\r
+ * </p>\r
+ * \r
+ * @return ファイルの内容を監視する場合はtrue、監視しない場合はfalse。\r
+ */\r
+ public boolean isCheckContent() {\r
+ return this._checkContent;\r
+ }\r
+\r
+ /**\r
+ * <p>\r
+ * ファイルの内容(ハッシュ値)を監視するかどうかを設定します。\r
+ * </p>\r
+ * <p>\r
+ * ファイルの内容を監視すると、監視のパフォーマンスが低下する場合があります。\r
+ * </p>\r
+ * \r
+ * @param checkContent\r
+ * ファイルの内容を監視する場合はtrue、監視しない場合はfalse。\r
+ */\r
+ public void setCheckContent(boolean checkContent) {\r
+ this._checkContent = checkContent;\r
+ }\r
+\r
+ /**\r
+ * <p>\r
+ * ファイルの内容を比較するときに使用するハッシュ・アルゴリズムを取得します。初期値は"MD5"です。\r
+ * </p>\r
+ * \r
+ * @return ハッシュ・アルゴリズム。\r
+ */\r
+ public String getHashAlgorithm() {\r
+ return this._hashAlgorithm;\r
+ }\r
+\r
+ /**\r
+ * <p>\r
+ * ファイルの内容を比較するときに使用するハッシュ・アルゴリズムを設定します。\r
+ * </p>\r
+ * <p>\r
+ * ハッシュ値の計算は{@link MessageDigest}クラスを使用します。従って、このメソッドで指定するハッシュ・アルゴリズムは{@link MessageDigest}クラスがサポートするアルゴリズムである必要があります。{@link MessageDigest}クラスがサポートしないハッシュ・アルゴリズムを設定した場合、{@link #monitor()}メソッドの呼び出しで{@link FileMonitorFailException}例外がスローされる可能性があります。\r
+ * </p>\r
+ * \r
+ * @param hashAlgorithm\r
+ * ハッシュ・アルゴリズム。\r
+ */\r
+ public void setHashAlgorithm(String hashAlgorithm) {\r
+ this._hashAlgorithm = hashAlgorithm;\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
+ }\r
+ synchronized (this._listenerList) {\r
+ this._listenerList.add(listener);\r
+ }\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
+ }\r
+ }\r
+\r
+ /**\r
+ * <p>\r
+ * リスナーの配列を返します。\r
+ * </p>\r
+ * <p>\r
+ * このメソッドはスレッドセーフです。\r
+ * </p>\r
+ * \r
+ * @return リスナーの配列。\r
+ */\r
+ private FileMonitorListener[] getListeners() {\r
+ synchronized (this._listenerList) {\r
+ return this._listenerList.toArray(new FileMonitorListener[0]);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * <p>\r
+ * ファイルの作成、更新、削除を監視し、リスナーにイベントを通知します。\r
+ * </p>\r
+ * \r
+ * @throws FileMonitorFailException\r
+ * ファイルの監視に失敗した場合。\r
+ */\r
+ public void monitor() throws FileMonitorFailException {\r
+ try {\r
+ this.checkCreateOrUpdate(this._baseDirectory);\r
+ } catch (NoSuchAlgorithmException e) {\r
+ throw new FileMonitorFailException(e);\r
+ } catch (IOException e) {\r
+ throw new FileMonitorFailException(e);\r
+ }\r
+ this.checkDelete();\r
+ this.checkClear();\r
+ }\r
+\r
+ /**\r
+ * <p>\r
+ * ディレクトリ内のファイルの作成、更新を確認します。\r
+ * </p>\r
+ * \r
+ * @param dir\r
+ * 確認するディレクトリ。\r
+ * @throws IOException\r
+ * 入出力に失敗した場合。\r
+ * @throws NoSuchAlgorithmException\r
+ * ハッシュ・アルゴリズムが見つからなかった場合。\r
+ */\r
+ private void checkCreateOrUpdate(File dir) throws IOException, NoSuchAlgorithmException {\r
+ if (dir == null) {\r
+ return;\r
+ }\r
+\r
+ File[] files = dir.listFiles();\r
+ if (files == null) {\r
+ return;\r
+ }\r
+\r
+ for (File f : files) {\r
+ if (f.isFile()) {\r
+ this.checkFileCreateOrUpdate(f);\r
+ } else {\r
+ this.checkCreateOrUpdate(f);\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * <p>\r
+ * ファイルの作成、更新を確認します。\r
+ * </p>\r
+ * \r
+ * @param file\r
+ * 確認するファイル。\r
+ * @throws IOException\r
+ * 入出力に失敗した場合。\r
+ * @throws NoSuchAlgorithmException\r
+ * ハッシュ・アルゴリズムが見つからなかった場合。\r
+ */\r
+ private void checkFileCreateOrUpdate(File file) throws NoSuchAlgorithmException, IOException {\r
+ if (this._filePattern.matcher(file.getAbsolutePath()).matches()) {\r
+ synchronized (this._monitoringFileMap) {\r
+ if (!this._monitoringFileMap.containsKey(file.getAbsolutePath())) {\r
+ // ファイルがマップに存在しない場合、新規のモニター対象。\r
+ MonitoringFileInfo info = new MonitoringFileInfo();\r
+ info.path = file.getAbsolutePath();\r
+ this.setMonitoringFileInfo(file, info);\r
+ info.checked = true;\r
+ this._monitoringFileMap.put(file.getAbsolutePath(), info);\r
+ // イベントを通知する。\r
+ FileMonitorListener[] listeners = this.getListeners();\r
+ for (FileMonitorListener l : listeners) {\r
+ l.create(this, file);\r
+ }\r
+ } else {\r
+ // ファイルがマップに存在する場合、変更のモニター対象。\r
+ MonitoringFileInfo info = this._monitoringFileMap.get(file.getAbsolutePath());\r
+ if (this.isModified(file, info)) {\r
+ this.setMonitoringFileInfo(file, info);\r
+ // イベントを通知する。\r
+ FileMonitorListener[] listeners = this.getListeners();\r
+ for (FileMonitorListener l : listeners) {\r
+ l.update(this, file);\r
+ }\r
+ }\r
+ info.checked = true;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * <p>\r
+ * 更新されているかどうかを調べます。\r
+ * </p>\r
+ * \r
+ * @param file\r
+ * 元のファイル。\r
+ * @param info\r
+ * 監視中ファイルの情報。\r
+ * @return 更新されている場合はtrue、更新されていない場合はfalse。\r
+ * @throws IOException\r
+ * 入出力に失敗した場合。\r
+ * @throws NoSuchAlgorithmException\r
+ * ハッシュ・アルゴリズムが見つからなかった場合。\r
+ */\r
+ private boolean isModified(File file, MonitoringFileInfo info) throws NoSuchAlgorithmException, IOException {\r
+ if (this._checkLength) {\r
+ if (file.length() != info.length) {\r
+ return true;\r
+ }\r
+ }\r
+ if (this._checkLastModified) {\r
+ if (file.lastModified() != info.lastModified) {\r
+ return true;\r
+ }\r
+ }\r
+ if (this._checkContent) {\r
+ if (!Arrays.equals(this.getHashData(file), info.hashData)) {\r
+ return true;\r
+ }\r
+ }\r
+ return false;\r
+ }\r
+\r
+ /**\r
+ * <p>\r
+ * 監視中ファイル情報に新しい情報を設定します。\r
+ * </p>\r
+ * \r
+ * @param file\r
+ * 元のファイル。\r
+ * @param info\r
+ * 監視中ファイルの情報。\r
+ * @throws IOException\r
+ * 入出力に失敗した場合。\r
+ * @throws NoSuchAlgorithmException\r
+ * ハッシュ・アルゴリズムが見つからなかった場合。\r
+ */\r
+ private void setMonitoringFileInfo(File file, MonitoringFileInfo info) throws NoSuchAlgorithmException, IOException {\r
+ if (this._checkLength) {\r
+ info.length = file.length();\r
+ }\r
+ if (this._checkLastModified) {\r
+ info.lastModified = file.lastModified();\r
+ }\r
+ if (this._checkContent) {\r
+ info.hashData = this.getHashData(file);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * <p>\r
+ * ハッシュ値を算出します。\r
+ * </p>\r
+ * \r
+ * @param file\r
+ * 算出元のファイル。\r
+ * @return ハッシュ値。\r
+ * @throws IOException\r
+ * 入出力に失敗した場合。\r
+ * @throws NoSuchAlgorithmException\r
+ * ハッシュ・アルゴリズムが見つからなかった場合。\r
+ */\r
+ private byte[] getHashData(File file) throws IOException, NoSuchAlgorithmException {\r
+ MessageDigest md = MessageDigest.getInstance(this._hashAlgorithm);\r
+\r
+ FileInputStream fileIn = new FileInputStream(file);\r
+ try {\r
+ byte[] buf = new byte[Consts.BUFFER_LENGTH];\r
+ int len;\r
+ while ((len = fileIn.read(buf)) != -1) {\r
+ md.update(buf, 0, len);\r
+ }\r
+ } finally {\r
+ fileIn.close();\r
+ }\r
+\r
+ return md.digest();\r
+ }\r
+\r
+ /**\r
+ * <p>\r
+ * 削除されているかどうかを調べます。\r
+ * </p>\r
+ */\r
+ private void checkDelete() {\r
+ synchronized (this._monitoringFileMap) {\r
+ List<String> removeFileList = new ArrayList<String>();\r
+ for (MonitoringFileInfo info : this._monitoringFileMap.values()) {\r
+ if (!info.checked) {\r
+ File f = new File(info.path);\r
+ if (!f.exists()) {\r
+ removeFileList.add(info.path);\r
+ // イベントを通知する。\r
+ FileMonitorListener[] listeners = this.getListeners();\r
+ for (FileMonitorListener l : listeners) {\r
+ l.delete(this, f);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ for (String path : removeFileList) {\r
+ this._monitoringFileMap.remove(path);\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * <p>\r
+ * 監視中ファイルの情報のチェック済みマークをクリアします。\r
+ * </p>\r
+ */\r
+ private void checkClear() {\r
+ synchronized (this._monitoringFileMap) {\r
+ for (MonitoringFileInfo info : this._monitoringFileMap.values()) {\r
+ info.checked = false;\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * <p>\r
+ * 監視中ファイルの情報です。\r
+ * </p>\r
+ */\r
+ private class MonitoringFileInfo {\r
+\r
+ /**\r
+ * <p>\r
+ * パス。\r
+ * </p>\r
+ */\r
+ private String path;\r
+\r
+ /**\r
+ * <p>\r
+ * ファイルの長さ。\r
+ * </p>\r
+ */\r
+ private long length;\r
+\r
+ /**\r
+ * <p>\r
+ * 最終更新日時。\r
+ * </p>\r
+ */\r
+ private long lastModified;\r
+\r
+ /**\r
+ * <p>\r
+ * ハッシュ値。\r
+ * </p>\r
+ */\r
+ private byte[] hashData;\r
+\r
+ /**\r
+ * <p>\r
+ * チェック済みマーク。\r
+ * </p>\r
+ */\r
+ private boolean checked;\r
+\r
+ /**\r
+ * <p>\r
+ * インスタンスを初期化します。\r
+ * </p>\r
+ */\r
+ MonitoringFileInfo() {\r
+ }\r
+\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2007 uguu at users.sourceforge.jp, All Rights Reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright\r
+ * notice, this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ * notice, this list of conditions and the following disclaimer in the\r
+ * documentation and/or other materials provided with the distribution.\r
+ *\r
+ * 3. Neither the name of Clarkware Consulting, Inc. nor the names of its\r
+ * contributors may be used to endorse or promote products derived\r
+ * from this software without prior written permission. For written\r
+ * permission, please contact clarkware@clarkware.com.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\r
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL\r
+ * CLARKWARE CONSULTING OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+\r
+package jp.sourceforge.deployer;\r
+\r
+/**\r
+ * <p>\r
+ * ファイルの監視に失敗したことを表す例外です。\r
+ * </p>\r
+ * \r
+ * @author $Author$\r
+ * @version $Rev$\r
+ */\r
+public class FileMonitorFailException extends Exception {\r
+\r
+ /**\r
+ * <p>\r
+ * インスタンスを初期化します。\r
+ * </p>\r
+ * \r
+ * @param e\r
+ * 例外の原因。\r
+ */\r
+ public FileMonitorFailException(Exception e) {\r
+ super("ファイルの監視に失敗しました。", e);\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2007 uguu at users.sourceforge.jp, All Rights Reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright\r
+ * notice, this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ * notice, this list of conditions and the following disclaimer in the\r
+ * documentation and/or other materials provided with the distribution.\r
+ *\r
+ * 3. Neither the name of Clarkware Consulting, Inc. nor the names of its\r
+ * contributors may be used to endorse or promote products derived\r
+ * from this software without prior written permission. For written\r
+ * permission, please contact clarkware@clarkware.com.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\r
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL\r
+ * CLARKWARE CONSULTING OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+\r
+package jp.sourceforge.deployer;\r
+\r
+import java.io.File;\r
+\r
+/**\r
+ * <p>\r
+ * {@link FileMonitor}クラスによるファイル監視のイベントを受け取るリスナーです。\r
+ * </p>\r
+ * \r
+ * @author $Author$\r
+ * @version $Rev$\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
--- /dev/null
+<body>\r
+ <p>ホット デプロイ機能を持つコンポーネントを提供します。デプロイヤーは、特定ディレクトリにファイルが配置されたとき、それを作業ディレクトリに展開し、独自クラスローダーを構築し、アプリケーションにイベントを通知します。</p>\r
+</body>\r
--- /dev/null
+<?xml version="1.0" encoding="Shift_JIS"?>\r
+<document>\r
+ <properties>\r
+ <title>\83f\83v\83\8d\83C\83\84\81[ - \95Ï\8dX\97\9a\97ð</title>\r
+ <author email="uguu@users.sourceforge.jp">uguu</author>\r
+ </properties>\r
+ <body>\r
+ <release version="1.0" date="2007-05-29" description="\8dÅ\8f\89\82Ì\83\8a\83\8a\81[\83X">\r
+ <action dev="uguu" type="update">\r
+ \8dÅ\8f\89\82Ì\83\8a\83\8a\81[\83X\82Å\82·\81B\r
+ </action>\r
+ </release>\r
+ </body>\r
+</document>\r
--- /dev/null
+<?xml version="1.0" encoding="Shift_JIS"?>\r
+<project name="deployer">\r
+ <bannerLeft>\r
+ <name>\83f\83v\83\8d\83C\83\84\81[</name>\r
+ <href>http://deployer.sourceforge.jp/</href>\r
+ </bannerLeft>\r
+ <bannerRight>\r
+ <name>SourceForge.jp Project Info</name>\r
+ <src>http://sourceforge.jp/sflogo.php?group_id=2875</src>\r
+ <href>https://sourceforge.jp/projects/deployer/</href>\r
+ </bannerRight>\r
+ <body>\r
+ <links>\r
+ <item name="SourceForge.jp" href="http://sourceforge.jp/" />\r
+ </links>\r
+ <menu name="\83f\83v\83\8d\83C\83\84\81[">\r
+ <item name="\8aT\97v" href="index.html" />\r
+ <item name="\83z\83b\83g\83f\83v\83\8d\83C" href="hotdeploy.html" />\r
+ <item name="\83A\81[\83J\83C\83u\82Ì\8d\\91¢" href="archive.html" />\r
+ <item name="\83R\81[\83f\83B\83\93\83O\97á" href="coding.html" />\r
+ <item name="\83_\83E\83\93\83\8d\81[\83h" href="https://sourceforge.jp/projects/deployer/files/" />\r
+ <item name="\8dX\90V\97\9a\97ð" href="changes-report.html" />\r
+ </menu>\r
+ ${reports}\r
+ </body>\r
+</project>\r
--- /dev/null
+<?xml version="1.0" encoding="Shift_JIS"?>\r
+<document>\r
+ <properties>\r
+ <author email="uguu at users.sourceforge.jp">uguu</author>\r
+ <title>\83f\83v\83\8d\83C\83\84\81[ - \83A\81[\83J\83C\83u\82Ì\8d\\91¢</title>\r
+ </properties>\r
+ <body>\r
+ <section name="\83A\81[\83J\83C\83u\82Ì\8d\\91¢">\r
+ <p>\83A\81[\83J\83C\83u\82Í\88È\89º\82Ì\97v\91f\82Å\8d\\90¬\82³\82ê\82Ü\82·\81B</p>\r
+ <ul>\r
+ <li>\83N\83\89\83X \83t\83@\83C\83\8b\81B</li>\r
+ <li>jar\83t\83@\83C\83\8b\81B</li>\r
+ <li>\82»\82Ì\91¼\82Ì\83t\83@\83C\83\8b(\83\8a\83\\81[\83X)\81B</li>\r
+ </ul>\r
+ <p>\82±\82Ì\8d\\90¬\82Í\8e©\97R\82É\92è\8b`\82·\82é\82±\82Æ\82ª\8fo\97\88\82Ü\82·\81B\97á\82¦\82Î\81A</p>\r
+ <source>/\r
++---WEB-INF/\r
+ +---classes/\r
+ | +---\83N\83\89\83X\81E\83t\83@\83C\83\8b\81A\83\8a\83\\81[\83X\81B\r
+ +---lib/\r
+ +---jar\83t\83@\83C\83\8b\81B</source>\r
+ <p>\82Æ\82¢\82¤\8d\\90¬\82Å\82 \82Á\82½\82è\81A</p>\r
+ <source>/\r
++---bin/\r
+| +---jar\83t\83@\83C\83\8b\81B\r
++---conf/\r
+ +---\83\8a\83\\81[\83X\81E\83t\83@\83C\83\8b(\95K\91R\93I\82É\83N\83\89\83X\81E\83t\83@\83C\83\8b\82à)\81B</source>\r
+ <p>\82Æ\82¢\82¤\8d\\90¬\82ð\92è\8b`\82·\82é\82±\82Æ\82ª\8fo\97\88\82Ü\82·\81B\82±\82ê\82Í\81ADeployerClassLoader\83N\83\89\83X\82Ì\83R\83\93\83X\83g\83\89\83N\83^\82É\8ew\92è\82·\82é\88ø\90\94\82Å\92è\8b`\82µ\82Ü\82·\81B</p>\r
+ </section>\r
+ </body>\r
+</document>\r
--- /dev/null
+<?xml version="1.0" encoding="Shift_JIS"?>\r
+<document>\r
+ <properties>\r
+ <author email="uguu at users.sourceforge.jp">uguu</author>\r
+ <title>\83f\83v\83\8d\83C\83\84\81[ - \83R\81[\83f\83B\83\93\83O\97á</title>\r
+ </properties>\r
+ <body>\r
+ <section name="\83R\81[\83f\83B\83\93\83O\97á">\r
+ <p>\88È\89º\82Ì\82æ\82¤\82È\8d\\91¢\82Ì\83A\81[\83J\83C\83u\81E\83t\83@\83C\83\8b\82ð\8dl\82¦\82Ü\82·\81B</p>\r
+ <source>/\r
++---classes/\r
+| +---\83N\83\89\83X\81E\83t\83@\83C\83\8b\r
++---lib/\r
+ +---jar\83t\83@\83C\83\8b</source>\r
+ <p>\88È\89º\82Ì\97v\8c\8f\82Ì\83T\81[\83o\81E\83N\83\89\83X\82ð\8f\91\82\82±\82Æ\82ð\8dl\82¦\82Ü\82·\81B</p>\r
+ <ul>\r
+ <li>\83T\81[\83o\81E\83N\83\89\83X\82ÌFQN\82Í"example.ExampleServer"\82Æ\82µ\82Ü\82·\81B</li>\r
+ <li>\82±\82Ì\83A\81[\83J\83C\83u\81E\83t\83@\83C\83\8b\82ðdeploy\83f\83B\83\8c\83N\83g\83\8a\82É\94z\92u\82·\82é\82Æ\81Awork\83f\83B\83\8c\83N\83g\83\8a\82É\93W\8aJ\82µ\81A\83N\83\89\83X\83\8d\81[\83_\82ð\8d\\92z\82µ\81A\95Ê\83X\83\8c\83b\83h\82ÅMain\83N\83\89\83X\82Ìexecute()\83\81\83\\83b\83h\82ð\8cÄ\82Ñ\8fo\82µ\82Ü\82·\81B</li>\r
+ <li>deploy\83f\83B\83\8c\83N\83g\83\8a\82É\94z\92u\82³\82ê\82½\83A\81[\83J\83C\83u\81E\83t\83@\83C\83\8b\82ð\8dí\8f\9c\82·\82é\82Æ\81Awork\83f\83B\83\8c\83N\83g\83\8a\82É\93W\8aJ\82³\82ê\82½\83t\83@\83C\83\8b\82ª\8dí\8f\9c\82³\82ê\81A\83N\83\89\83X\83\8d\81[\83_\82ª\94j\8aü\82³\82ê\82Ü\82·\81B</li>\r
+ </ul>\r
+ <p>\82±\82Ì\82æ\82¤\82È\83T\81[\83o\82Í\81A\88È\89º\82Ì\82æ\82¤\82È\83R\81[\83h\82Å\8eÀ\8c»\82Å\82«\82Ü\82·\81B</p>\r
+ <source><![CDATA[package example;\r
+\r
+import java.io.File;\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+import java.util.regex.Pattern;\r
+\r
+import jp.sourceforge.deployer.Deployer;\r
+import jp.sourceforge.deployer.DeployerClassLoader;\r
+import jp.sourceforge.deployer.DeployerListener;\r
+\r
+public class ExampleServer implements DeployerListener {\r
+\r
+ private static Deployer deployer;\r
+\r
+ private Map<String, DeployerClassLoader> appMap = new HashMap<String, DeployerClassLoader>();\r
+\r
+ public static void main(String[] args) throws Exception {\r
+ File deployDir = new File("./deploy");\r
+ Pattern filePattern = Pattern.compile(".*\\.jar");\r
+ File workDir = new File("./work");\r
+\r
+ deployer = new Deployer(deployDir, filePattern, workDir);\r
+ deployer.addListener(new ExampleServer());\r
+\r
+ while (true) {\r
+ deployer.monitor();\r
+ Thread.sleep(1000);\r
+ }\r
+ }\r
+\r
+ public void deployEnd(Deployer deployer, File file, File destDirectory) {\r
+ try {\r
+ System.out.println("deployEnd: " + file.getAbsolutePath());\r
+\r
+ File[] fileDirectories = new File[] { new File(destDirectory, "classes") };\r
+ File[] jarDirectories = new File[] { new File(destDirectory, "lib") };\r
+\r
+ final DeployerClassLoader cl = new DeployerClassLoader(fileDirectories, jarDirectories);\r
+\r
+ this.appMap.put(file.getAbsolutePath(), cl);\r
+\r
+ Runnable r = new Runnable() {\r
+\r
+ public void run() {\r
+ try {\r
+ Class clazz = cl.loadClass("Main");\r
+ Object obj = clazz.newInstance();\r
+ clazz.getMethod("execute").invoke(obj);\r
+ } catch (Exception e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+\r
+ };\r
+ Thread t = new Thread(r);\r
+ t.start();\r
+ } catch (Throwable t) {\r
+ t.printStackTrace();\r
+ }\r
+ }\r
+\r
+ public void deployFile(Deployer deployer, File file, File destDirectory, File deployFile) {\r
+ System.out.println("deployFile: " + deployFile.getAbsolutePath());\r
+ }\r
+\r
+ public void deployStart(Deployer deployer, File file) {\r
+ System.out.println("deployStart: " + file.getAbsolutePath());\r
+ }\r
+\r
+ public void undeployEnd(Deployer deployer, File file) {\r
+ System.out.println("undeployEnd: " + file.getAbsolutePath());\r
+\r
+ DeployerClassLoader cl = this.appMap.get(file.getAbsolutePath());\r
+ cl.dispose();\r
+ }\r
+\r
+ public void undeployStart(Deployer deployer, File file, File destDirectory) {\r
+ System.out.println("undeployStart: " + file.getAbsolutePath());\r
+ }\r
+\r
+}]]></source>\r
+ </section>\r
+ </body>\r
+</document>\r
--- /dev/null
+<?xml version="1.0" encoding="Shift_JIS"?>\r
+<document>\r
+ <properties>\r
+ <author email="uguu at users.sourceforge.jp">uguu</author>\r
+ <title>\83f\83v\83\8d\83C\83\84\81[ - \83z\83b\83g\83f\83v\83\8d\83C</title>\r
+ </properties>\r
+ <body>\r
+ <section name="\83z\83b\83g\83f\83v\83\8d\83C">\r
+ <p>\83A\83v\83\8a\83P\81[\83V\83\87\83\93\81E\83T\81[\83o\82É\82¨\82¢\82Ä\81A\83A\83v\83\8a\83P\81[\83V\83\87\83\93\82Ì\83t\83@\83C\83\8b\82ª\94z\92u\82³\82ê\82é\82Æ\8e©\93®\93I\82É\83T\81[\83o\82É\83f\83v\83\8d\83C\82³\82ê\81A\83t\83@\83C\83\8b\82ª\8dí\8f\9c\82³\82ê\82é\82Æ\8e©\93®\93I\82É\83T\81[\83o\82©\82ç\83A\83\93\83f\83v\83\8d\83C\82³\82ê\82é\8b@\94\\82ð\95\\82µ\82Ü\82·\81Bjava\82Ì\8fê\8d\87\81A\88ê\94Ê\93I\82É\82Í\83t\83@\83C\83\8b\82Íjar\88³\8fk\8c`\8e®(\8ag\92£\8eq\82Í\97l\81X\82È\82Å\82·\82ª)\82Å\81A\82 \82é\83f\83B\83\8c\83N\83g\83\8a\82É\94z\92u\82³\82ê\82é\82Æ\81A\83T\81[\83o\82ª\8e©\93®\93I\82É\8dì\8bÆ\83f\83B\83\8c\83N\83g\83\8a\82Æ\8cÄ\82Î\82ê\82é\8fê\8f\8a\82É\83t\83@\83C\83\8b\82ð\93W\8aJ\82µ\82Ü\82·\81B</p>\r
+ <p>\83f\83v\83\8d\83C\83\84\81[\82Í\82±\82Ì\8b@\94\\82ð\92ñ\8b\9f\82µ\82Ü\82·\81B\94z\92u\83f\83B\83\8c\83N\83g\83\8a\82ð\92è\8aú\93I\82É\8aÄ\8e\8b\82µ\81A\83t\83@\83C\83\8b\82ª\94z\92u\82³\82ê\82é\82Æ\8e©\93®\93I\82É\8dì\8bÆ\83f\83B\83\8c\83N\83g\83\8a\82É\93W\8aJ\82µ\81A\83T\81[\83o\82É\83C\83x\83\93\83g\82ð\92Ê\92m\82µ\82Ü\82·\81B</p>\r
+ <p>\94z\92u\83f\83B\83\8c\83N\83g\83\8a\81A\8dì\8bÆ\83f\83B\83\8c\83N\83g\83\8a\82Í\8e©\97R\82É\92è\8b`\82·\82é\82±\82Æ\82ª\8fo\97\88\82Ü\82·\81B\97á\82¦\82Î\81A</p>\r
+ <source>/\r
++---bin/\r
+| +---deployer.jar\82È\82Ç\83T\81[\83o\96{\91Ì\81B\r
++---deploy/\r
+| +---\94z\92u\83f\83B\83\8c\83N\83g\83\8a\81B\r
++---work/\r
+ +---\8dì\8bÆ\83f\83B\83\8c\83N\83g\83\8a\81B</source>\r
+ <p>\82Æ\82¢\82¤\8d\\90¬\82Å\82 \82Á\82½\82è\81A</p>\r
+ <source>/\r
++---bin/\r
+| +---deployer.jar\82È\82Ç\82Ì\83T\81[\83o\96{\91Ì\81B\r
++---profiles/\r
+ +---user1\r
+ | +---deploy/\r
+ | | +---\94z\92u\83f\83B\83\8c\83N\83g\83\8a\81B\r
+ | +---work/\r
+ | +---\8dì\8bÆ\83f\83B\83\8c\83N\83g\83\8a\81B\r
+ +---user2\r
+ | +---deploy/\r
+ | | +---\94z\92u\83f\83B\83\8c\83N\83g\83\8a\81B\r
+ | +---work/\r
+ | +---\8dì\8bÆ\83f\83B\83\8c\83N\83g\83\8a\81B\r
+ +---user3\r
+ +---deploy/\r
+ | +---\94z\92u\83f\83B\83\8c\83N\83g\83\8a\81B\r
+ +---work/\r
+ +---\8dì\8bÆ\83f\83B\83\8c\83N\83g\83\8a\81B</source>\r
+ <p>\82Æ\82¢\82¤\8d\\90¬\82ð\92è\8b`\82·\82é\82±\82Æ\82ª\8fo\97\88\82Ü\82·\81B\82±\82ê\82Í\81ADeployer\83N\83\89\83X\82Ì\83R\83\93\83X\83g\83\89\83N\83^\82É\8ew\92è\82·\82é\88ø\90\94\82Å\92è\8b`\82µ\82Ü\82·\81B</p>\r
+ </section>\r
+ </body>\r
+</document>\r
--- /dev/null
+<?xml version="1.0" encoding="Shift_JIS"?>\r
+<document>\r
+ <properties>\r
+ <author email="uguu at users.sourceforge.jp">uguu</author>\r
+ <title>\83f\83v\83\8d\83C\83\84\81[ - \8aT\97v</title>\r
+ </properties>\r
+ <body>\r
+ <section name="\8aT\97v">\r
+ <p>war\83t\83@\83C\83\8b\82Ì\82æ\82¤\82É\81A\83N\83\89\83X \83t\83@\83C\83\8b\81Ajar\83t\83@\83C\83\8b\81A\83\8a\83\\81[\83X\82ð\8ai\94[\82µ\82½\83A\81[\83J\83C\83u\82Ì\83z\83b\83g\83f\83v\83\8d\83C\82ð\8ds\82¢\81A\83N\83\89\83X\83\8d\81[\83_\81[\82ð\8d\\92z\82·\82é\8b@\94\\82ð\8e\9d\82¿\82Ü\82·\81B</p>\r
+ </section>\r
+ </body>\r
+</document>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--
+ This configuration file was written by the eclipse-cs plugin configuration editor
+-->\r
+<!--
+Checkstyle-Configuration: Uguu Checks
+Description:
+
+-->\r
+<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.2//EN" "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">\r
+<module name="Checker">\r
+ <property name="severity" value="warning"/>\r
+ <module name="TreeWalker">\r
+ <property name="tabWidth" value="4"/>\r
+ <module name="ModifierOrder"/>\r
+ <module name="RedundantModifier"/>\r
+ <module name="AvoidNestedBlocks"/>\r
+ <module name="EmptyBlock"/>\r
+ <module name="LeftCurly"/>\r
+ <module name="NeedBraces"/>\r
+ <module name="RightCurly"/>\r
+ <module name="AvoidInlineConditionals"/>\r
+ <module name="DoubleCheckedLocking"/>\r
+ <module name="EmptyStatement"/>\r
+ <module name="EqualsHashCode"/>\r
+ <module name="IllegalInstantiation"/>\r
+ <module name="InnerAssignment"/>\r
+ <module name="MissingSwitchDefault"/>\r
+ <module name="RedundantThrows"/>\r
+ <module name="SimplifyBooleanExpression"/>\r
+ <module name="SimplifyBooleanReturn"/>\r
+ <module name="DesignForExtension"/>\r
+ <module name="HideUtilityClassConstructor"/>\r
+ <module name="InterfaceIsType"/>\r
+ <module name="VisibilityModifier"/>\r
+ <module name="ArrayTypeStyle"/>\r
+ <module name="GenericIllegalRegexp">\r
+ <property name="format" value="\s+$"/>\r
+ <property name="ignoreComments" value="true"/>\r
+ <property name="message" value="Line has trailing spaces."/>\r
+ </module>\r
+ <module name="TodoComment"/>\r
+ <module name="UpperEll"/>\r
+ <module name="DefaultComesLast"/>\r
+ <module name="FallThrough"/>\r
+ <module name="IllegalCatch"/>\r
+ <module name="IllegalThrows"/>\r
+ <module name="ModifiedControlVariable"/>\r
+ <module name="RequireThis"/>\r
+ <module name="StringLiteralEquality"/>\r
+ <module name="FinalClass"/>\r
+ <module name="Indentation"/>\r
+ <module name="TrailingComment"/>\r
+ <module name="JavadocStyle">\r
+ <property name="checkFirstSentence" value="false"/>\r
+ </module>\r
+ <module name="JavadocType">\r
+ <property name="authorFormat" value="^\$Author.*\$$"/>\r
+ <property name="versionFormat" value="^\$Rev.*\$$"/>\r
+ </module>\r
+ <module name="JavadocVariable"/>\r
+ <module name="AbstractClassName"/>\r
+ <module name="ConstantName"/>\r
+ <module name="LocalFinalVariableName"/>\r
+ <module name="LocalVariableName"/>\r
+ <module name="MemberName">\r
+ <property name="format" value="^[a-z_][a-zA-Z0-9]*$"/>\r
+ </module>\r
+ <module name="MethodName"/>\r
+ <module name="PackageName"/>\r
+ <module name="ParameterName"/>\r
+ <module name="StaticVariableName"/>\r
+ <module name="TypeName"/>\r
+ <module name="Header">\r
+ <property name="headerFile" value="${basedir}/LICENSE.txt"/>\r
+ </module>\r
+ <module name="AvoidStarImport"/>\r
+ <module name="IllegalImport"/>\r
+ <module name="ImportOrder"/>\r
+ <module name="RedundantImport"/>\r
+ <module name="UnusedImports"/>\r
+ <module name="EmptyForInitializerPad"/>\r
+ <module name="EmptyForIteratorPad"/>\r
+ <module name="NoWhitespaceAfter"/>\r
+ <module name="NoWhitespaceBefore"/>\r
+ <module name="OperatorWrap"/>\r
+ <module name="MethodParamPad"/>\r
+ <module name="ParenPad"/>\r
+ <module name="TabCharacter"/>\r
+ <module name="TypecastParenPad">\r
+ <property name="tokens" value="RPAREN,TYPECAST"/>\r
+ </module>\r
+ <module name="WhitespaceAfter"/>\r
+ <module name="WhitespaceAround">\r
+ <property name="tokens" value="ASSIGN,BAND,BAND_ASSIGN,BOR,BOR_ASSIGN,BSR,BSR_ASSIGN,BXOR,BXOR_ASSIGN,COLON,DIV,DIV_ASSIGN,EQUAL,GE,GT,LAND,LCURLY,LE,LITERAL_ASSERT,LITERAL_CATCH,LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_FOR,LITERAL_IF,LITERAL_RETURN,LITERAL_SYNCHRONIZED,LITERAL_TRY,LITERAL_WHILE,LOR,LT,MINUS,MINUS_ASSIGN,MOD,MOD_ASSIGN,NOT_EQUAL,PLUS,PLUS_ASSIGN,QUESTION,RCURLY,SL,SLIST,SL_ASSIGN,SR,SR_ASSIGN,STAR,STAR_ASSIGN,LITERAL_ASSERT,TYPE_EXTENSION_AND"/>\r
+ </module>\r
+ <module name="CovariantEquals"/>\r
+ <module name="DeclarationOrder"/>\r
+ <module name="ExplicitInitialization"/>\r
+ <module name="HiddenField"/>\r
+ <module name="IllegalType">\r
+ <property name="tokens" value="METHOD_DEF,PARAMETER_DEF,VARIABLE_DEF"/>\r
+ </module>\r
+ <module name="JUnitTestCase"/>\r
+ <module name="MagicNumber"/>\r
+ <module name="MissingCtor"/>\r
+ <module name="MultipleStringLiterals"/>\r
+ <module name="MultipleVariableDeclarations"/>\r
+ <module name="PackageDeclaration"/>\r
+ <module name="MutableException"/>\r
+ </module>\r
+ <module name="NewlineAtEndOfFile">\r
+ <property name="lineSeparator" value="lf"/>\r
+ </module>\r
+ <module name="Translation"/>\r
+ <module name="PackageHtml"/>\r
+</module>\r