I18n-commits
Threads by month
- ----- 2026 -----
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
April 2010
- 3 participants
- 32 discussions
r1733 - in trunk/maven-i18n-plugin/src: it/parsers/newProject it/parsers/withNewKeys main/java/org/nuiton/i18n/plugin main/java/org/nuiton/i18n/plugin/parser
by tchemit@users.nuiton.org 03 Apr '10
by tchemit@users.nuiton.org 03 Apr '10
03 Apr '10
Author: tchemit
Date: 2010-04-03 11:38:02 +0200 (Sat, 03 Apr 2010)
New Revision: 1733
Log:
finalize fix bug #438 + improve design and integration tests
Added:
trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/I18nParserConfiguration.java
Modified:
trunk/maven-i18n-plugin/src/it/parsers/newProject/invoker.properties
trunk/maven-i18n-plugin/src/it/parsers/newProject/pom.xml
trunk/maven-i18n-plugin/src/it/parsers/withNewKeys/invoker.properties
trunk/maven-i18n-plugin/src/it/parsers/withNewKeys/pom.xml
trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/AbstractI18nMojo.java
trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/GenerateMojo.java
trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/AbstractFileParser.java
trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/AbstractI18nParserMojo.java
trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/FileParser.java
trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/ParserThread.java
Modified: trunk/maven-i18n-plugin/src/it/parsers/newProject/invoker.properties
===================================================================
--- trunk/maven-i18n-plugin/src/it/parsers/newProject/invoker.properties 2010-04-02 20:02:13 UTC (rev 1732)
+++ trunk/maven-i18n-plugin/src/it/parsers/newProject/invoker.properties 2010-04-03 09:38:02 UTC (rev 1733)
@@ -1,6 +1,6 @@
# A comma or space separated list of goals/phases to execute, may
# specify an empty list to execute the default goal of the IT project
-invoker.goals=clean process-resources
+invoker.goals=clean compile
# Optionally, a list of goals to run during further invocations of Maven
#invoker.goals.2=${project.groupId}:${project.artifactId}:${project.version}:run
Modified: trunk/maven-i18n-plugin/src/it/parsers/newProject/pom.xml
===================================================================
--- trunk/maven-i18n-plugin/src/it/parsers/newProject/pom.xml 2010-04-02 20:02:13 UTC (rev 1732)
+++ trunk/maven-i18n-plugin/src/it/parsers/newProject/pom.xml 2010-04-03 09:38:02 UTC (rev 1733)
@@ -15,6 +15,7 @@
<version>@pom.version@</version>
</parent>
+ <groupId>org.nuiton.i18n</groupId>
<artifactId>parsers-newProject</artifactId>
<!-- ************************************************************* -->
@@ -29,15 +30,17 @@
<packaging>jar</packaging>
- <properties>
- <i18nVersion>@pom.version@</i18nVersion>
+ <dependencies>
- <!-- default encoding -->
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>nuiton-i18n</artifactId>
+ <version>${project.version}</version>
+ </dependency>
- </properties>
-
+ </dependencies>
+
<build>
<plugins>
@@ -45,27 +48,27 @@
<plugin>
<groupId>org.nuiton.i18n</groupId>
<artifactId>maven-i18n-plugin</artifactId>
- <version>${i18nVersion}</version>
-
- <!--configuration>
- <treateDefaultEntry>false</treateDefaultEntry>
- <entries>
- <entry>
- <specificGoal>parserValidation</specificGoal>
- <basedir>${maven.src.dir}/main/java/</basedir>
- <includes>
- <param>**/**-validation.xml</param>
- </includes>
- </entry>
- </entries>
- </configuration-->
+ <version>@pom.version@</version>
+ <configuration>
+ <verbose>true</verbose>
+ </configuration>
<executions>
<execution>
+ <id>first</id>
<goals>
<goal>parserJava</goal>
<goal>parserValidation</goal>
</goals>
</execution>
+ <execution>
+ <!-- this execution is to test thread with no files -->
+ <id>second</id>
+ <goals>
+ <goal>parserJava</goal>
+ <goal>parserValidation</goal>
+ </goals>
+ <phase>compile</phase>
+ </execution>
</executions>
</plugin>
</plugins>
Modified: trunk/maven-i18n-plugin/src/it/parsers/withNewKeys/invoker.properties
===================================================================
--- trunk/maven-i18n-plugin/src/it/parsers/withNewKeys/invoker.properties 2010-04-02 20:02:13 UTC (rev 1732)
+++ trunk/maven-i18n-plugin/src/it/parsers/withNewKeys/invoker.properties 2010-04-03 09:38:02 UTC (rev 1733)
@@ -1,6 +1,6 @@
# A comma or space separated list of goals/phases to execute, may
# specify an empty list to execute the default goal of the IT project
-invoker.goals=clean process-resources
+invoker.goals=clean compile
# Optionally, a list of goals to run during further invocations of Maven
#invoker.goals.2=${project.groupId}:${project.artifactId}:${project.version}:run
Modified: trunk/maven-i18n-plugin/src/it/parsers/withNewKeys/pom.xml
===================================================================
--- trunk/maven-i18n-plugin/src/it/parsers/withNewKeys/pom.xml 2010-04-02 20:02:13 UTC (rev 1732)
+++ trunk/maven-i18n-plugin/src/it/parsers/withNewKeys/pom.xml 2010-04-03 09:38:02 UTC (rev 1733)
@@ -15,6 +15,7 @@
<version>@pom.version@</version>
</parent>
+ <groupId>org.nuiton.i18n</groupId>
<artifactId>parsers-withNewKeys</artifactId>
<!-- ************************************************************* -->
@@ -29,15 +30,16 @@
<packaging>jar</packaging>
- <properties>
+ <dependencies>
- <i18nVersion>@pom.version@</i18nVersion>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>nuiton-i18n</artifactId>
+ <version>${project.version}</version>
+ </dependency>
- <!-- default encoding -->
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </dependencies>
- </properties>
-
<build>
<plugins>
@@ -45,30 +47,30 @@
<plugin>
<groupId>org.nuiton.i18n</groupId>
<artifactId>maven-i18n-plugin</artifactId>
- <version>${i18nVersion}</version>
+ <version>@pom.version@</version>
<configuration>
<keepGetters>true</keepGetters>
+ <verbose>true</verbose>
</configuration>
- <!--configuration>
- <treateDefaultEntry>false</treateDefaultEntry>
- <entries>
- <entry>
- <specificGoal>parserValidation</specificGoal>
- <basedir>${maven.src.dir}/main/java/</basedir>
- <includes>
- <param>**/**-validation.xml</param>
- </includes>
- </entry>
- </entries>
- </configuration-->
<executions>
<execution>
+ <id>first</id>
<goals>
<goal>parserJava</goal>
<goal>parserValidation</goal>
<goal>gen</goal>
</goals>
</execution>
+ <execution>
+ <!-- this execution is to test thread with no files -->
+ <id>second</id>
+ <goals>
+ <goal>parserJava</goal>
+ <goal>parserValidation</goal>
+ <goal>gen</goal>
+ </goals>
+ <phase>compile</phase>
+ </execution>
</executions>
</plugin>
</plugins>
Modified: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/AbstractI18nMojo.java
===================================================================
--- trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/AbstractI18nMojo.java 2010-04-02 20:02:13 UTC (rev 1732)
+++ trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/AbstractI18nMojo.java 2010-04-03 09:38:02 UTC (rev 1733)
@@ -139,6 +139,7 @@
return !acceptPackaging(Packaging.pom);
}
+ @Override
public void init() throws Exception {
if (verbose) {
@@ -251,10 +252,12 @@
}
+ @Override
public File getBackupFile(File file) {
return new File(file.getAbsolutePath() + "~");
}
+ @Override
protected void backupFile(File f) throws IOException {
File dst = getBackupFile(f);
copyFile(f, dst);
@@ -268,19 +271,31 @@
this.encoding = encoding;
}
+ @Override
public MavenProject getProject() {
return project;
}
+ @Override
public void setProject(MavenProject project) {
this.project = project;
}
+ @Override
public boolean isVerbose() {
return verbose;
}
+ @Override
public void setVerbose(boolean verbose) {
this.verbose = verbose;
}
+
+ public boolean isSilent() {
+ return silent;
+ }
+
+ public boolean isStrictMode() {
+ return strictMode;
+ }
}
Modified: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/GenerateMojo.java
===================================================================
--- trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/GenerateMojo.java 2010-04-02 20:02:13 UTC (rev 1732)
+++ trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/GenerateMojo.java 2010-04-03 09:38:02 UTC (rev 1733)
@@ -73,7 +73,6 @@
*/
protected boolean keepGetters;
-
@Override
protected boolean checkSkip() {
if (!needGeneration()) {
Modified: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/AbstractFileParser.java
===================================================================
--- trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/AbstractFileParser.java 2010-04-02 20:02:13 UTC (rev 1732)
+++ trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/AbstractFileParser.java 2010-04-03 09:38:02 UTC (rev 1733)
@@ -63,6 +63,11 @@
return log;
}
+ /**
+ * Method to invoke when a i18n key was detected .
+ *
+ * @param key the i18n key to register
+ */
protected void registerKey(String key) {
Object value = oldParser.get(key);
if (value == null) {
Modified: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/AbstractI18nParserMojo.java
===================================================================
--- trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/AbstractI18nParserMojo.java 2010-04-02 20:02:13 UTC (rev 1732)
+++ trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/AbstractI18nParserMojo.java 2010-04-03 09:38:02 UTC (rev 1733)
@@ -34,7 +34,7 @@
*
* @author tony
*/
-public abstract class AbstractI18nParserMojo extends AbstractI18nMojo {
+public abstract class AbstractI18nParserMojo extends AbstractI18nMojo implements I18nParserConfiguration {
/** @return the outGetter to use for the instance (java.getter,...) */
protected abstract String getOutGetter();
@@ -64,8 +64,16 @@
/** @return the default src directory to use in directory scanner */
protected abstract File getDefaultBasedir();
+ /**
+ * @return a new file parser to be used in the parser consumer thread
+ * @since 1.2
+ */
public abstract FileParser newFileParser();
+ /**
+ * @param entry the incoming source entry to attach to the file updater
+ * @return a new file updater to detects files to treate
+ */
public abstract FileUpdater newFileUpdater(SourceEntry entry);
/**
@@ -146,6 +154,7 @@
ParserThread thread;
+ @Override
public boolean isStrictMode() {
return strictMode;
}
@@ -187,7 +196,7 @@
}
}
- thread = new ParserThread(result);
+ thread = new ParserThread(this);
}
@Override
@@ -245,13 +254,15 @@
continue;
}
+ // launch parser for found files
+ String[] files = entry.getFiles();
+
if (!silent) {
getLog().info("start entry " + entry.toString());
- getLog().info("incoming file(s) : " + entry.getFoudFiles());
+ getLog().info(files.length + " file(s) to treate (amoung " +
+ entry.getFoudFiles() + " files)");
}
- // launch parser for found files
- String[] files = entry.getFiles();
for (int i = 0, max = files.length; i < max; i++) {
String file1 = files[i];
String fileName = entry.getBasedir().getAbsolutePath() +
@@ -301,6 +312,16 @@
thread.clear();
}
+ @Override
+ public boolean isShowTouchedFiles() {
+ return showTouchedFiles;
+ }
+
+ @Override
+ public SortedProperties getResult() {
+ return result;
+ }
+
/**
* Add the default entry to entries given in configuration.
* <p/>
Modified: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/FileParser.java
===================================================================
--- trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/FileParser.java 2010-04-02 20:02:13 UTC (rev 1732)
+++ trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/FileParser.java 2010-04-03 09:38:02 UTC (rev 1733)
@@ -1,6 +1,5 @@
package org.nuiton.i18n.plugin.parser;
-import org.apache.maven.plugin.logging.Log;
import org.nuiton.io.SortedProperties;
import java.io.File;
@@ -16,24 +15,15 @@
public interface FileParser {
/**
- * maven logger to use.
- *
- * @return the logger
- */
- Log getLog();
-
- /** @return {@code true} if should print on logger when file is touched */
- boolean isShowTouchedFiles();
-
- /**
* @return {@code true} if file was touched (says contains at least one i18n
* key)
*/
boolean isTouched();
/**
- * TODO As we do not used anylonger old language, we should directly TODO
- * use only a set of keys, no need to keep i18n value...
+ * TODO As we do not used anylonger old language, we should directly
+ * <p/>
+ * TODO use only a set of keys, no need to keep i18n value...
*
* @return the results of i18n keys found for the given file
*/
Added: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/I18nParserConfiguration.java
===================================================================
--- trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/I18nParserConfiguration.java (rev 0)
+++ trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/I18nParserConfiguration.java 2010-04-03 09:38:02 UTC (rev 1733)
@@ -0,0 +1,23 @@
+package org.nuiton.i18n.plugin.parser;
+
+import org.apache.maven.plugin.logging.Log;
+import org.nuiton.io.SortedProperties;
+
+/**
+ * Shared configuration for a parser mojo.
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 1.2
+ */
+public interface I18nParserConfiguration {
+
+ boolean isVerbose();
+
+ boolean isSilent();
+
+ boolean isShowTouchedFiles();
+
+ Log getLog();
+
+ SortedProperties getResult();
+}
Property changes on: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/I18nParserConfiguration.java
___________________________________________________________________
Added: svn:keywords
+ "Author Date Id Revision HeadURL
Modified: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/ParserThread.java
===================================================================
--- trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/ParserThread.java 2010-04-02 20:02:13 UTC (rev 1732)
+++ trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/ParserThread.java 2010-04-03 09:38:02 UTC (rev 1733)
@@ -1,7 +1,6 @@
package org.nuiton.i18n.plugin.parser;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.apache.maven.plugin.logging.Log;
import org.nuiton.io.SortedProperties;
import org.nuiton.plugin.PluginHelper;
@@ -17,135 +16,15 @@
* @author tchemit <chemit(a)codelutin.com>
* @since 1.2
*/
-public class ParserThread extends Thread {
+public class ParserThread extends Thread implements I18nParserConfiguration {
- /** Logger */
- private static final Log log = LogFactory.getLog(ParserThread.class);
-
/**
- * This is a task to parse a {@link #file}.
- * <p/>
- * The task will be executed in the executor service created in the thread.
+ * the incoming configuration (from mojo which contains shared result and
+ * logger)
*/
- class ParserTask implements Runnable {
+ protected final I18nParserConfiguration configuration;
- /** the file parser */
- protected final FileParser parser;
-
- /** the file to parse */
- protected final File file;
-
- /** starting time */
- protected long startingTime;
-
- /** ending time */
- protected long endingTime;
-
- ParserTask(FileParser parser, File file) {
- this.parser = parser;
- this.file = file;
- }
-
- @Override
- public void run() {
- startingTime = System.nanoTime();
- if (log.isDebugEnabled()) {
- log.debug("starting action for " + file);
- }
- try {
-
- parser.parseFile(file);
-
- } catch (IOException e) {
- if (log.isErrorEnabled()) {
- log.error("could not parse file " + file, e);
- }
- } finally {
-
- if (log.isDebugEnabled()) {
- log.debug("ending action for " + file);
- }
- endingTime = System.nanoTime();
- }
- }
-
- @Override
- public String toString() {
- return super.toString() + " - " + file;
- }
-
- protected File getFile() {
- return file;
- }
-
- protected long getDelay() {
- return endingTime - startingTime;
- }
-
- protected void destroy() {
- parser.destroy();
- }
-
- @Override
- protected void finalize() throws Throwable {
- super.finalize();
- destroy();
- }
-
- /**
- * Register the result of the parsing of the {@link #file} after {@link
- * #run()} method was invoked.
- * <p/>
- * This method should be invoked by the executor as an ending hook.
- *
- * @param treatedFiles list of files already treated
- * @param touchedFiles list of files already touched
- * @param result shared result.
- */
- protected synchronized void registerResult(List<File> treatedFiles,
- List<File> touchedFiles,
- SortedProperties result) {
-
- try {
- treatedFiles.add(file);
- if (log.isDebugEnabled()) {
- String delay = PluginHelper.convertTime(getDelay());
- log.debug("[" + treatedFiles.size() + "] " + file +
- " in " + delay);
- }
-
- if (parser.isTouched()) {
-
- // mark file as touched
- touchedFiles.add(file);
-
- if (parser.isShowTouchedFiles()) {
- parser.getLog().info("touch " + file);
- }
- if (log.isInfoEnabled()) {
- String delay = PluginHelper.convertTime(getDelay());
- log.info("[" + treatedFiles.size() + "] touchs " +
- file + " in " + delay);
- }
-
- // merge file result with
- // merge result
- result.putAll(parser.getResult());
- }
- } finally {
-
- // destroy runner
- destroy();
-
- // release lock2
-
- synchronized (lock2) {
- lock2.notifyAll();
- }
- }
- }
- }
-
+ /** queue of tasks to consume */
protected final BlockingQueue<ParserTask> tasks;
/** list of files consumed */
@@ -154,8 +33,8 @@
/** list of files touched (says having at least one i18n key) */
protected final List<File> touchedFiles;
- /** the shared result where to merge atomic results */
- protected final SortedProperties result;
+ /** number of files registred to consume */
+ protected int nbFiles;
/**
* object used to lock method {@link #terminatesAndWaits()} until the thread
@@ -169,17 +48,39 @@
*/
private final Object lock2 = new Object();
- /** number of files registred to consume */
- protected int nbFiles;
-
- public ParserThread(SortedProperties result) {
+ public ParserThread(I18nParserConfiguration configuration) {
super(ParserThread.class.getSimpleName());
- this.result = result;
+ this.configuration = configuration;
tasks = new LinkedBlockingQueue<ParserTask>();
touchedFiles = new ArrayList<File>();
treatedFiles = new ArrayList<File>();
}
+ @Override
+ public boolean isVerbose() {
+ return getConfiguration().isVerbose();
+ }
+
+ @Override
+ public boolean isSilent() {
+ return getConfiguration().isSilent();
+ }
+
+ @Override
+ public boolean isShowTouchedFiles() {
+ return getConfiguration().isShowTouchedFiles();
+ }
+
+ @Override
+ public Log getLog() {
+ return getConfiguration().getLog();
+ }
+
+ @Override
+ public SortedProperties getResult() {
+ return getConfiguration().getResult();
+ }
+
public List<File> getTreatedFiles() {
return treatedFiles;
}
@@ -199,8 +100,8 @@
for (File f : files) {
nbFiles++;
- if (log.isInfoEnabled()) {
- log.info("[" + nbFiles + "] " + f);
+ if (isVerbose()) {
+ getLog().info("[" + nbFiles + "] " + f);
}
tasks.offer(new ParserTask(parser, f));
}
@@ -215,49 +116,55 @@
* <b>Note:</b> The method does not return until all files are not
* consumed.
*/
- public void terminatesAndWaits() {
+ public synchronized void terminatesAndWaits() {
- if (log.isInfoEnabled()) {
- log.info("add terminate runner");
+ if (isVerbose()) {
+ getLog().info("add terminate runner");
}
tasks.offer(new ParserTask(null, null));
- // block until end of service
-
- if (log.isInfoEnabled()) {
- log.info("block until ends...");
+ // we waits a little time to make sure, the thread receive the
+ // sentinel, we can not use a lock here
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ if (getLog().isErrorEnabled()) {
+ getLog().error(e);
+ }
}
- //TODO-TC20100402 Should test (and use another internal state) to be
- //TODO-TC20100402 sure We have to perform a lock, sometimes it is not
- //TODO-TC20100402 necessary if thread is dead before coming at this point
+ if (getNbFilesToTreate() > 0) {
- synchronized (lock) {
- try {
- lock.wait();
- } catch (InterruptedException e) {
- if (log.isErrorEnabled()) {
- log.error(e);
+ // there is still something to treate,
+ // MUST block until the thread is fully terminated
+
+ if (isVerbose()) {
+ getLog().info("block until ends...");
+ }
+
+ synchronized (lock) {
+ try {
+ lock.wait();
+ } catch (InterruptedException e) {
+ if (getLog().isErrorEnabled()) {
+ getLog().error(e);
+ }
}
}
}
- if (nbFiles != treatedFiles.size()) {
+
+ if (getNbFilesToTreate() > 0) {
+ // this case should never happens : once we are here, all files
+ // MUST have been consumed
throw new IllegalStateException(
"should have " + nbFiles + " files treated, but found " +
treatedFiles.size());
}
- if (log.isDebugEnabled()) {
- log.debug("thread is terminated.");
+ if (getLog().isDebugEnabled()) {
+ getLog().debug("thread is terminated.");
}
}
- /** clean internal state after usage of the thread. */
- public void clear() {
- treatedFiles.clear();
- touchedFiles.clear();
- nbFiles = 0;
- }
-
@Override
public void run() {
@@ -273,8 +180,8 @@
try {
runner = tasks.take();
} catch (InterruptedException e) {
- if (log.isErrorEnabled()) {
- log.error(e);
+ if (getLog().isErrorEnabled()) {
+ getLog().error(e);
}
canQuit = true;
continue;
@@ -282,31 +189,21 @@
if (runner.getFile() == null) {
// ask to quit the tread
- if (log.isDebugEnabled()) {
- log.debug("no more files to treate, wait termination...");
+ if (getLog().isDebugEnabled()) {
+ getLog().debug("Termination is asked..., will terminate to " +
+ "resting consume files");
}
- //FIXME-TC20100402, sleep to make sure that the lock2 is always
- //FIXME-TC20100402 block before the thread is done.
- //FIXME-TC20100402 otherwise, it could ends in a dead-end...
- //TODO Should really use another lock or internal state before
- //TODO doing lock in method terminatesAndWaits
-
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- log.error(e);
- }
canQuit = true;
continue;
}
- if (log.isDebugEnabled()) {
- log.debug("consume " + runner);
+ if (getLog().isDebugEnabled()) {
+ getLog().debug("consume " + runner);
}
executor.execute(runner);
- if (log.isDebugEnabled()) {
- log.debug("after consume " + runner);
+ if (getLog().isDebugEnabled()) {
+ getLog().debug("after consume " + runner);
}
}
@@ -315,14 +212,14 @@
if (nbFiles == 0) {
// no file consumed
- if (log.isInfoEnabled()) {
- log.info("no file consumed.");
+ if (isVerbose()) {
+ getLog().info("No file consumed.");
}
} else {
- if (log.isInfoEnabled()) {
- log.info("will waits until all files (" + nbFiles +
- ") are consumed (still " + getFilesToTreate() +
- " file(s) to consume)");
+ if (isVerbose()) {
+ getLog().info("Will waits until all files (" + nbFiles +
+ ") are consumed (still " + getNbFilesToTreate() +
+ " file(s) to consume)");
}
}
@@ -332,20 +229,20 @@
while (!canQuit) {
- int treate = getFilesToTreate();
+ int nbFilesToTreate = getNbFilesToTreate();
// can quit if and only if executore is terminated are there is no
// more files to consume
- // Note : normally, the second is not necessary...
- canQuit = executor.isTerminated() || treate == 0;
+ // Note : normally, the second test is not necessary...
+ canQuit = executor.isTerminated() || nbFilesToTreate == 0;
if (canQuit) {
continue;
}
- if (log.isDebugEnabled()) {
- log.debug("waiting end... (still " + treate +
- " file(s) to consume)");
+ if (getLog().isDebugEnabled()) {
+ getLog().debug("Waiting end... (still " + nbFilesToTreate +
+ " file(s) to consume)");
}
// waits a task to be done
@@ -353,14 +250,19 @@
try {
lock2.wait();
} catch (InterruptedException e) {
- log.error(e);
+ getLog().error(e);
break;
}
}
+
+ if (getLog().isDebugEnabled()) {
+ getLog().debug("A task was consumed, still " + getNbFilesToTreate() +
+ " file(s) to treate.");
+ }
}
- if (log.isInfoEnabled()) {
- log.info("executor is terminated, will release thread lock.");
+ if (isVerbose()) {
+ getLog().info("Executor is terminated, will release thread lock.");
}
// service was shutdown and terminated, release thread main lock.
@@ -371,7 +273,20 @@
}
+ /** clean internal state after usage of the thread. */
+ public void clear() {
+ treatedFiles.clear();
+ touchedFiles.clear();
+ nbFiles = 0;
+ }
+
+ /**
+ * Creates the {@link ExecutorService} which will consumed i8n tasks.
+ *
+ * @return the instanciated executor
+ */
protected ExecutorService createExecutor() {
+
// creates thread factory
ThreadFactory factory =
new ThreadFactory() {
@@ -396,16 +311,146 @@
@Override
protected void afterExecute(Runnable r, Throwable t) {
- super.afterExecute(r, t);
- ParserTask i18n = (ParserTask) r;
- i18n.registerResult(treatedFiles, touchedFiles, result);
+ try {
+ super.afterExecute(r, t);
+ ParserTask i18n = (ParserTask) r;
+ i18n.registerResult(treatedFiles, touchedFiles, getResult());
+ } finally {
+
+ // task is done, notify thread
+
+ synchronized (lock2) {
+ lock2.notifyAll();
+ }
+ }
}
};
return executor;
}
- protected int getFilesToTreate() {
+ protected I18nParserConfiguration getConfiguration() {
+ return configuration;
+ }
+
+ protected int getNbFilesToTreate() {
return nbFiles - treatedFiles.size();
}
+ /**
+ * This is a task to parse a {@link #file}.
+ * <p/>
+ * The task will be executed in the executor service created in the thread.
+ */
+ class ParserTask implements Runnable {
+
+ /** the file parser */
+ protected final FileParser parser;
+
+ /** the file to parse */
+ protected final File file;
+
+ /** starting time */
+ protected long startingTime;
+
+ /** ending time */
+ protected long endingTime;
+
+ ParserTask(FileParser parser, File file) {
+ this.parser = parser;
+ this.file = file;
+ }
+
+ @Override
+ public void run() {
+ startingTime = System.nanoTime();
+ if (getLog().isDebugEnabled()) {
+ getLog().debug("starting action for " + file);
+ }
+ try {
+
+ parser.parseFile(file);
+
+ } catch (IOException e) {
+ if (getLog().isErrorEnabled()) {
+ getLog().error("could not parse file " + file, e);
+ }
+ } finally {
+
+ if (getLog().isDebugEnabled()) {
+ getLog().debug("ending action for " + file);
+ }
+ endingTime = System.nanoTime();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + " - " + file;
+ }
+
+ protected File getFile() {
+ return file;
+ }
+
+ protected long getDelay() {
+ return endingTime - startingTime;
+ }
+
+ protected void destroy() {
+ parser.destroy();
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ super.finalize();
+ destroy();
+ }
+
+ /**
+ * Register the result of the parsing of the {@link #file} after {@link
+ * #run()} method was invoked.
+ * <p/>
+ * This method should be invoked by the executor as an ending hook.
+ *
+ * @param treatedFiles list of files already treated
+ * @param touchedFiles list of files already touched
+ * @param result shared result.
+ */
+ protected synchronized void registerResult(List<File> treatedFiles,
+ List<File> touchedFiles,
+ SortedProperties result) {
+
+ try {
+ treatedFiles.add(file);
+ if (getLog().isDebugEnabled()) {
+ String delay = PluginHelper.convertTime(getDelay());
+ getLog().debug("[" + treatedFiles.size() + "] " + file +
+ " in " + delay);
+ }
+
+ if (parser.isTouched()) {
+
+ // mark file as touched
+ touchedFiles.add(file);
+
+ if (isShowTouchedFiles()) {
+ getLog().info("touch " + file);
+ }
+ if (isVerbose()) {
+ String delay = PluginHelper.convertTime(getDelay());
+ getLog().info("[" + treatedFiles.size() + "] touchs " +
+ file + " in " + delay);
+ }
+
+ // merge file result with
+ // merge result
+ result.putAll(parser.getResult());
+ }
+ } finally {
+
+ // destroy runner
+ destroy();
+ }
+ }
+ }
}
1
0
r1732 - trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser
by tchemit@users.nuiton.org 02 Apr '10
by tchemit@users.nuiton.org 02 Apr '10
02 Apr '10
Author: tchemit
Date: 2010-04-02 22:02:13 +0200 (Fri, 02 Apr 2010)
New Revision: 1732
Log:
Anomalie #438: Blocage sur le parserJava lorsqu'il n'y a aucun fichier ?\195?\160 parser
Modified:
trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/ParserThread.java
Modified: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/ParserThread.java
===================================================================
--- trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/ParserThread.java 2010-03-30 20:35:54 UTC (rev 1731)
+++ trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/ParserThread.java 2010-04-02 20:02:13 UTC (rev 1732)
@@ -22,14 +22,23 @@
/** Logger */
private static final Log log = LogFactory.getLog(ParserThread.class);
+ /**
+ * This is a task to parse a {@link #file}.
+ * <p/>
+ * The task will be executed in the executor service created in the thread.
+ */
class ParserTask implements Runnable {
+ /** the file parser */
protected final FileParser parser;
+ /** the file to parse */
protected final File file;
+ /** starting time */
protected long startingTime;
+ /** ending time */
protected long endingTime;
ParserTask(FileParser parser, File file) {
@@ -83,6 +92,16 @@
destroy();
}
+ /**
+ * Register the result of the parsing of the {@link #file} after {@link
+ * #run()} method was invoked.
+ * <p/>
+ * This method should be invoked by the executor as an ending hook.
+ *
+ * @param treatedFiles list of files already treated
+ * @param touchedFiles list of files already touched
+ * @param result shared result.
+ */
protected synchronized void registerResult(List<File> treatedFiles,
List<File> touchedFiles,
SortedProperties result) {
@@ -114,8 +133,15 @@
result.putAll(parser.getResult());
}
} finally {
+
// destroy runner
destroy();
+
+ // release lock2
+
+ synchronized (lock2) {
+ lock2.notifyAll();
+ }
}
}
}
@@ -132,11 +158,17 @@
protected final SortedProperties result;
/**
- * object used to lock method {@link #terminatesAndWaits()} until all tasks
- * are consumed.
+ * object used to lock method {@link #terminatesAndWaits()} until the thread
+ * is not fully terminated.
*/
private final Object lock = new Object();
+ /**
+ * object used to lock in {@link #run()} until all tasks are consumed after
+ * the shutdown of the executor
+ */
+ private final Object lock2 = new Object();
+
/** number of files registred to consume */
protected int nbFiles;
@@ -156,28 +188,39 @@
return touchedFiles;
}
+ /**
+ * Add a file to be consumed.
+ *
+ * @param parser the parser of the file
+ * @param files files to parse
+ */
public void addFile(FileParser parser, File... files) {
- synchronized (tasks) {
+ for (File f : files) {
- for (File f : files) {
-
- nbFiles++;
- if (log.isInfoEnabled()) {
- log.info("[" + nbFiles + "] " + f);
- }
- tasks.offer(new ParserTask(parser, f));
+ nbFiles++;
+ if (log.isInfoEnabled()) {
+ log.info("[" + nbFiles + "] " + f);
}
+ tasks.offer(new ParserTask(parser, f));
}
}
- public synchronized void terminatesAndWaits() {
- synchronized (tasks) {
- if (log.isDebugEnabled()) {
- log.debug("add terminate runner");
- }
- tasks.offer(new ParserTask(null, null));
+ /**
+ * Ask the thread to stop.
+ * <p/>
+ * It will finish all incoming files (but will not accept more files to
+ * parse)
+ * <p/>
+ * <b>Note:</b> The method does not return until all files are not
+ * consumed.
+ */
+ public void terminatesAndWaits() {
+
+ if (log.isInfoEnabled()) {
+ log.info("add terminate runner");
}
+ tasks.offer(new ParserTask(null, null));
// block until end of service
@@ -185,6 +228,10 @@
log.info("block until ends...");
}
+ //TODO-TC20100402 Should test (and use another internal state) to be
+ //TODO-TC20100402 sure We have to perform a lock, sometimes it is not
+ //TODO-TC20100402 necessary if thread is dead before coming at this point
+
synchronized (lock) {
try {
lock.wait();
@@ -204,6 +251,7 @@
}
}
+ /** clean internal state after usage of the thread. */
public void clear() {
treatedFiles.clear();
touchedFiles.clear();
@@ -213,36 +261,12 @@
@Override
public void run() {
- // creates thread factory
- ThreadFactory factory =
- new ThreadFactory() {
- final ThreadFactory defaultFactory =
- Executors.defaultThreadFactory();
-
- public Thread newThread(Runnable r) {
- Thread thread =
- defaultFactory.newThread(r);
- thread.setName(ParserThread.this + "-" + thread.getName());
- return thread;
- }
- };
-
// create pool executor
- ExecutorService service = new ThreadPoolExecutor(
- 8, 10,
- 1L, TimeUnit.SECONDS,
- new LinkedBlockingQueue<Runnable>(),
- factory) {
+ ExecutorService executor = createExecutor();
- @Override
- protected void afterExecute(Runnable r, Throwable t) {
- super.afterExecute(r, t);
- ParserTask i18n = (ParserTask) r;
- i18n.registerResult(treatedFiles, touchedFiles, result);
- }
- };
+ boolean canQuit = false;
- while (true) {
+ while (!canQuit) {
// waiting for a new file to treate
ParserTask runner;
@@ -252,60 +276,136 @@
if (log.isErrorEnabled()) {
log.error(e);
}
+ canQuit = true;
continue;
}
if (runner.getFile() == null) {
// ask to quit the tread
- if (log.isInfoEnabled()) {
- log.info("no more files to treate, wait termination...");
+ if (log.isDebugEnabled()) {
+ log.debug("no more files to treate, wait termination...");
}
- service.shutdown();
- break;
+ //FIXME-TC20100402, sleep to make sure that the lock2 is always
+ //FIXME-TC20100402 block before the thread is done.
+ //FIXME-TC20100402 otherwise, it could ends in a dead-end...
+ //TODO Should really use another lock or internal state before
+ //TODO doing lock in method terminatesAndWaits
+
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ log.error(e);
+ }
+ canQuit = true;
+ continue;
}
if (log.isDebugEnabled()) {
log.debug("consume " + runner);
}
- service.execute(runner);
+ executor.execute(runner);
if (log.isDebugEnabled()) {
log.debug("after consume " + runner);
}
}
- if (log.isInfoEnabled()) {
- log.info("will waits until ends of all " + nbFiles + " runner(s)!");
+ // ask executor to terminate
+ executor.shutdown();
+
+ if (nbFiles == 0) {
+ // no file consumed
+ if (log.isInfoEnabled()) {
+ log.info("no file consumed.");
+ }
+ } else {
+ if (log.isInfoEnabled()) {
+ log.info("will waits until all files (" + nbFiles +
+ ") are consumed (still " + getFilesToTreate() +
+ " file(s) to consume)");
+ }
}
- // waits end of service
+ // waits end of executor
- while (true) {
+ canQuit = false;
- if (service.isTerminated()) {
- if (log.isInfoEnabled()) {
- log.info("all runners are terminated. [" + treatedFiles.size() + "]");
- }
+ while (!canQuit) {
- // release lock
- synchronized (lock) {
- lock.notifyAll();
- }
- break;
+ int treate = getFilesToTreate();
+
+ // can quit if and only if executore is terminated are there is no
+ // more files to consume
+ // Note : normally, the second is not necessary...
+ canQuit = executor.isTerminated() || treate == 0;
+
+ if (canQuit) {
+ continue;
}
if (log.isDebugEnabled()) {
- log.debug("waiting end...");
+ log.debug("waiting end... (still " + treate +
+ " file(s) to consume)");
}
- try {
- sleep(200);
- } catch (InterruptedException e) {
- if (log.isErrorEnabled()) {
+ // waits a task to be done
+ synchronized (lock2) {
+ try {
+ lock2.wait();
+ } catch (InterruptedException e) {
log.error(e);
+ break;
}
}
}
+
+ if (log.isInfoEnabled()) {
+ log.info("executor is terminated, will release thread lock.");
+ }
+
+ // service was shutdown and terminated, release thread main lock.
+
+ synchronized (lock) {
+ lock.notifyAll();
+ }
+
}
+ protected ExecutorService createExecutor() {
+ // creates thread factory
+ ThreadFactory factory =
+ new ThreadFactory() {
+ final ThreadFactory defaultFactory =
+ Executors.defaultThreadFactory();
+
+ public Thread newThread(Runnable r) {
+ Thread thread =
+ defaultFactory.newThread(r);
+ thread.setName(ParserThread.this + "-" +
+ thread.getName());
+ return thread;
+ }
+ };
+
+ // create pool executor
+ ExecutorService executor = new ThreadPoolExecutor(
+ 8, 10,
+ 1L, TimeUnit.SECONDS,
+ new LinkedBlockingQueue<Runnable>(),
+ factory) {
+
+ @Override
+ protected void afterExecute(Runnable r, Throwable t) {
+ super.afterExecute(r, t);
+ ParserTask i18n = (ParserTask) r;
+ i18n.registerResult(treatedFiles, touchedFiles, result);
+ }
+ };
+ return executor;
+ }
+
+ protected int getFilesToTreate() {
+ return nbFiles - treatedFiles.size();
+ }
+
}
1
0