Author: tchemit Date: 2010-03-08 19:35:57 +0100 (Mon, 08 Mar 2010) New Revision: 1708 Log: introduce bundle package to put all the bundle-mojo + move all specific to parser stuff to parser package Added: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/bundle/ trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/bundle/AbstractI18nBundleMojo.java trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/bundle/BundleMojo.java trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/bundle/CollectI18nArtifactsMojo.java trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/bundle/I18nArtifact.java trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/I18nLogger.java trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/SourceEntry.java Removed: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/AbstractI18nBundleMojo.java trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/BundleMojo.java trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/CollectI18nArtifactsMojo.java trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/I18nArtifact.java trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/I18nLogger.java trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/SourceEntry.java 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/GenerateMojo.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/I18nSourceEntry.java trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/KeysModifier.java trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/impl/ParserJavaMojo.java trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/impl/ParserValidationMojo.java trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/impl/ParserXmlMojo.java Deleted: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/AbstractI18nBundleMojo.java =================================================================== --- trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/AbstractI18nBundleMojo.java 2010-03-08 11:04:08 UTC (rev 1707) +++ trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/AbstractI18nBundleMojo.java 2010-03-08 18:35:57 UTC (rev 1708) @@ -1,88 +0,0 @@ -/* - * *##% - * I18n :: Maven Plugin - * Copyright (C) 2007 - 2009 CodeLutin - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * ##%* - */ -package org.nuiton.i18n.plugin; - -import java.io.File; -import java.io.IOException; -import java.net.URL; -import java.util.Locale; - -/** - * Created: 26 déc. 2009 - * - * @author tchemit <chemit@codelutin.com> - * @version $Revision$ - * <p/> - * Mise a jour: $Date$ par : - * $Author: tchemit $ - */ -public abstract class AbstractI18nBundleMojo extends AbstractI18nMojo { - - /** - * Repertoire ou generer les bundles. - * - * @parameter expression="${i18n.collectOutputDir}" default-value="${basedir}/target/i18n" - * @required - * @since 1.0.2 - */ - protected File collectOutputDir; - - /** - * Nom de base des fichiers qui contient les localisations des bundles. - * - * @parameter expression="${i18n.collectOutputName}" default-value="collect-${project.artifactId}-i18n" - * @required - * @since 1.0.2 - */ - protected String collectOutputName; - - /** - * Pour obtenir les urls des fichiers i18n d'un projet (avec recherche - * dans ses dépendances). - * <p/> - * <b>Note:</b> L'ordre des urls reflète l'ordre des dépendances. - * - * @param locale la locale a traiter - * @return les urls des bundles i18n detectees pour le projet. - * @throws Exception pour tout problème - */ - protected abstract URL[] getCollectI18nResources(Locale locale) - throws Exception; - - /** - * Pour obtenir le fichier contenant les localisation des bundles i18n du - * projet pour une {@code locale} donnée. - * - * @param locale la locale - * @param create un drapeau pour forcer la création du fichier - * s'il n'existe pas - * @return le fichier qui contient les urls des bundles i18n pour la - * locale donnée. - * @throws IOException pour tout pb - */ - protected File getCollectOutputFile(Locale locale, boolean create) - throws IOException { - File bundleOut = getI18nFile(collectOutputDir, collectOutputName, - locale, create); - return bundleOut; - } - -} 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-03-08 11:04:08 UTC (rev 1707) +++ trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/AbstractI18nMojo.java 2010-03-08 18:35:57 UTC (rev 1708) @@ -32,16 +32,14 @@ import java.util.SortedSet; /** - * Classe permettant d'obenir les parametres pendant les différentes phases - * du plugin. + * Classe permettant d'obenir les parametres pendant les différentes phases du + * plugin. * * @author julien */ public abstract class AbstractI18nMojo extends AbstractPlugin { - /** - * Le nombre de getters détectés pendant le cycle de vie du build. - */ + /** Le nombre de getters détectés pendant le cycle de vie du build. */ private static int NB_GETTER_FILES; /** @@ -97,7 +95,8 @@ /** * Met les fichiers generes dans le repertoire des sources i18n. * <p/> - * Note: Par défaut active, pour pouvoir paquager avec les bundles mis a jour. + * Note: Par défaut active, pour pouvoir paquager avec les bundles mis a + * jour. * * @parameter expression="${i18n.genSrc}" default-value="true" */ @@ -124,22 +123,15 @@ * ne conserve que les clef scannees (et donc traite tous les fichiers) * <p/> * <p/> - * Note : par default, on ne l'active car rescanne tous les fichiers. - * s + * Note : par default, on ne l'active car rescanne tous les fichiers. s * * @parameter expression="${i18n.strictMode}" default-value="false" */ protected boolean strictMode; - /** - * les locales a traiter - */ + /** les locales a traiter */ protected Locale[] locales; - /** - * logger verbeux - */ - protected I18nLogger verboseLog; @Override protected boolean checkPackaging() { @@ -149,8 +141,6 @@ public void init() throws Exception { - verboseLog = new I18nLogger(this); - if (verbose) { getLog().info("config - verbose mode is on"); } @@ -167,8 +157,8 @@ } /** - * @return <code>true</code> si des getters ont etes enregistres pendant - * le cycle de vie, <code>false</code> sinon. + * @return <code>true</code> si des getters ont etes enregistres pendant le + * cycle de vie, <code>false</code> sinon. */ protected boolean needGeneration() { boolean needGeneration = NB_GETTER_FILES > 0; @@ -178,17 +168,13 @@ /** * Prend en compte qu'un getter a été détecté. * <p/> - * Cela veut dire qu'un goal de parser a détecté des clefs. Il - * faudra donc activer les goal get et gen. + * Cela veut dire qu'un goal de parser a détecté des clefs. Il faudra donc + * activer les goal get et gen. */ protected void addGetter() { NB_GETTER_FILES++; } - protected I18nLogger getVerboseLog() { - return verboseLog; - } - /** * @param root le repertoire ou sont stockes les fichiers i18n * @param artifactId le nom de l'artifact Deleted: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/BundleMojo.java =================================================================== --- trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/BundleMojo.java 2010-03-08 11:04:08 UTC (rev 1707) +++ trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/BundleMojo.java 2010-03-08 18:35:57 UTC (rev 1708) @@ -1,246 +0,0 @@ -/* - * *##% - * I18n :: Maven Plugin - * Copyright (C) 2007 - 2009 CodeLutin - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * ##%* - */ -package org.nuiton.i18n.plugin; - -import org.nuiton.i18n.bundle.I18nBundleEntry; -import org.nuiton.i18n.bundle.I18nBundleUtil; -import org.nuiton.i18n.init.DefaultI18nInitializer; -import org.nuiton.io.SortedProperties; -import org.nuiton.plugin.PluginHelper; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.net.URL; -import java.util.*; -import java.util.Map.Entry; - -/** - * Créer un bundle pour une application finale. - * <p/> - * Cela génère un merge de tous les fichiers i18n utilisés en un seul. - * <p/> - * On utilise la dépendance sur les artifacts pour connaitre l'ordre le - * chargement des bundles. - * <p/> - * Si dans un bundle childs, la valeur de la clef est vide, on conserve alors - * celui du parent, - * <p/> - * Ainsi on obtient un bundle dont toutes les clefs sont traduites. - * <p/> - * Le but aussi d'utiliser un unique bundle est de gagner du temps au runtime - * car la recherche des bundles devient trop couteuse en temps lorsque l'on a de - * nombreuses dépendances (au dessus de 100 deps cela peut prendre plusieurs - * secondes, ce qui 'est pas acceptable). - * <p/> - * On a ajoute un second mode d'initialisation dans la clesse I18n pour - * n'utiliser qu'un seul bundle et courcircuiter le chargement couteux... - * - * @author tchemit <chemit@codelutin.com> - * @goal bundle - * @phase generate-resources - * @execute goal=collect-i18n-artifacts - * @requiresProject true - * @requiresDependencyResolution runtime - * @since 0.12 - */ -public class BundleMojo extends AbstractI18nBundleMojo { - - /** - * Repertoire ou generer les bundles. - * - * @parameter expression="${i18n.bundleOutputDir}" default-value="${basedir}/target/generated-sources/resources/META-INF" - * @required - * @since 1.0.0 - */ - protected File bundleOutputDir; - - /** - * Nom du bundle a generer. - * - * @parameter expression="${i18n.bundleOutputName}" default-value="${project.artifactId}-i18n" - * @required - * @since 1.0.2 - */ - protected String bundleOutputName; - - /** - * Un drapeau pour vérifier que les bundles ne contiennent pas d'entrées - * vides. - * - * @parameter expression="${i18n.checkBundle}" default-value="true" - * @required - * @since 1.0.0 - */ - protected boolean checkBundle; - - /** - * Un drapeau pour afficher les entrées vides. (nécessite {@link - * #checkBundle} activé). - * - * @parameter expression="${i18n.showEmpty}" default-value="false" - * @required - * @since 1.0.0 - */ - protected boolean showEmpty; - - @Override - public void init() throws Exception { - super.init(); - - createDirectoryIfNecessary(bundleOutputDir); - - // ajout de repertoire de generation (le parent en fait) - // dans les resources du projet - - addResourceDir(bundleOutputDir.getParentFile(), "**/*.properties"); - } - - @Override - protected void doAction() throws Exception { - long t00 = System.nanoTime(); - - String version = getProject().getVersion(); - version = PluginHelper.removeSnapshotSuffix(version); - - if (!silent) { - getLog().info("config - bundle name : " + bundleOutputName); - getLog().info("config - basedir : " + bundleOutputDir); - getLog().info("config - locales : " + Arrays.toString(locales)); - getLog().info("config - version : " + version); - } - - Map<Locale, String> bundleDico = - new LinkedHashMap<Locale, String>(locales.length); - - for (Locale locale : locales) { - - long t0 = System.nanoTime(); - - File bundleOut = getI18nFile(bundleOutputDir, bundleOutputName, - locale, false); - - if (!silent) { - getLog().info("generate bundle for locale " + locale); - } - - SortedProperties propertiesOut = - new SortedProperties(encoding, false); - StringBuilder buffer = new StringBuilder(); - - URL[] urls = getCollectI18nResources(locale); - if (urls.length == 0) { - getLog().warn("no bundle for locale " + locale); - continue; - } - - for (URL url : urls) { - long t000 = System.nanoTime(); - I18nBundleEntry bundleEntry = - new I18nBundleEntry(url, locale, null); - bundleEntry.load(propertiesOut); - String strPath = bundleEntry.getPath().toString(); - int index = strPath.indexOf("i18n/"); - - buffer.append(',').append(strPath.substring(index)); - if (verbose) { - getLog().info( - "loaded " + bundleEntry.getPath() + " in " + - PluginHelper.convertTime(t000, System.nanoTime())); - } - } - - if (buffer.length() > 0) { - bundleDico.put(locale, buffer.substring(1)); - if (!silent) { - getLog().info( - "bundles for locale : " + bundleDico.get(locale)); - } - } - propertiesOut.store(bundleOut); - if (!silent && verbose) { - getLog().info( - "bundle created in " + - PluginHelper.convertTime(t0, System.nanoTime()) + - " (detected sentences : " + propertiesOut.size() + ")"); - } - if (checkBundle) { - checkBundle(locale, propertiesOut, showEmpty); - } - } - - // ecriture du ficher des definitions i18n (permet de faire une - // recherche extact sur un fichier puis d'en deduire les bundles a - // charger - String f = String.format(DefaultI18nInitializer.UNIQUE_BUNDLE_DEF, - bundleOutputName); - File defOut = new File(bundleOutputDir, f); - if (!silent) { - getLog().info("prepare i18n definition " + - defOut.getAbsolutePath()); - } - SortedProperties p = new SortedProperties(encoding, false); - p.setProperty(DefaultI18nInitializer.BUNDLE_DEF_LOCALES, bundles); - p.setProperty(DefaultI18nInitializer.BUNDLE_DEF_VERSION, version); - for (Entry<Locale, String> e : bundleDico.entrySet()) { - p.setProperty(DefaultI18nInitializer.BUNDLES_FOR_LOCALE + - e.getKey().toString(), e.getValue()); - } - FileOutputStream out = new FileOutputStream(defOut); - try { - p.store(out, null); - } finally { - out.close(); - } - - if (!silent && verbose) { - getLog().info("done in " + - PluginHelper.convertTime(t00, System.nanoTime())); - } - } - - @Override - protected URL[] getCollectI18nResources(Locale locale) throws IOException { - File file = getCollectOutputFile(locale, false); - if (!file.exists()) { - return I18nBundleUtil.EMPTY_URL_ARRAY; - } - URL[] urls = getLinesAsURL(file); - return urls; - } - - /** - * TODO Move this in PluginHelper. - * - * @param src the source file to read - * @return the url instanciated from lines of the source file. - * @throws IOException if any pb while reading file - */ - public static URL[] getLinesAsURL(File src) throws IOException { - List<URL> result = new ArrayList<URL>(); - for (String line : PluginHelper.getLines(src)) { - if (!line.isEmpty()) { - result.add(new URL(line)); - } - } - return result.toArray(new URL[result.size()]); - } -} Deleted: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/CollectI18nArtifactsMojo.java =================================================================== --- trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/CollectI18nArtifactsMojo.java 2010-03-08 11:04:08 UTC (rev 1707) +++ trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/CollectI18nArtifactsMojo.java 2010-03-08 18:35:57 UTC (rev 1708) @@ -1,256 +0,0 @@ -/* - * *##% - * I18n :: Maven Plugin - * Copyright (C) 2007 - 2009 CodeLutin - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * ##%* - */ -package org.nuiton.i18n.plugin; - -import org.apache.maven.artifact.Artifact; -import org.apache.maven.artifact.factory.ArtifactFactory; -import org.apache.maven.artifact.metadata.ArtifactMetadataSource; -import org.apache.maven.artifact.repository.ArtifactRepository; -import org.apache.maven.artifact.resolver.ArtifactCollector; -import org.apache.maven.artifact.resolver.filter.ArtifactFilter; -import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter; -import org.apache.maven.shared.dependency.tree.DependencyNode; -import org.apache.maven.shared.dependency.tree.DependencyTreeBuilder; -import org.apache.maven.shared.dependency.tree.DependencyTreeBuilderException; -import org.nuiton.i18n.bundle.I18nBundleEntry; -import org.nuiton.plugin.DependencyUtil; -import org.nuiton.plugin.PluginHelper; - -import java.io.File; -import java.io.IOException; -import java.net.URL; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -/** - * Detects any i18n artifacts and store the result as a file. - * <p/> - * Created: 24 déc. 2009 - * - * @author tchemit <chemit@codelutin.com> - * @version $Revision$ - * <p/> - * Mise a jour: $Date$ par : - * $Author: tchemit $ - * @goal collect-i18n-artifacts - * @phase generate-resources - * @requiresProject true - * @requiresDependencyResolution runtime - * @since 1.0.2 - */ -public class CollectI18nArtifactsMojo extends AbstractI18nBundleMojo { - - /** - * Local Repository. - * - * @parameter expression="${localRepository}" - * @required - * @readonly - * @since 1.0.2 - */ - protected ArtifactRepository localRepository; - - /** - * Dependency tree builder component. - * - * @component - * @since 1.0.2 - */ - protected DependencyTreeBuilder dependencyTreeBuilder; - - /** - * Artifact Factory component. - * - * @component - * @since 1.0.2 - */ - protected ArtifactFactory factory; - - /** - * Artifact metadata source component. - * - * @component - * @since 1.0.2 - */ - protected ArtifactMetadataSource artifactMetadataSource; - - /** - * Artifact collector component. - * - * @component - * @since 1.0.2 - */ - protected ArtifactCollector collector; - - I18nArtifact[] i18nArtifacts; - - @Override - public void init() throws Exception { - super.init(); - - PluginHelper.createDirectoryIfNecessary(collectOutputDir); - } - - @Override - protected void doAction() throws Exception { - - // detects the i18n artifacts (only once since it cost some times)... - i18nArtifacts = detectI18nArtifacts(); - - if (i18nArtifacts.length == 0) { - getLog().warn("no i18n artifact detected."); - return; - } - - for (Locale locale : locales) { - - if (!silent) { - getLog().info("generate collected i18n artifacts for locale " + - locale); - } - URL[] urls = getCollectI18nResources(locale); - - if (urls.length == 0) { - getLog().warn("no i18n bundles for locale " + locale); - return; - } - - File bundleOut = getCollectOutputFile(locale, true); - - storeCollectI18nResources(bundleOut, urls); - - getLog().info("collected " + urls.length + - " i18n artifacts for locale " + locale + - " stored in " + bundleOut); - } - } - - @Override - protected URL[] getCollectI18nResources(Locale locale) - throws IOException, DependencyTreeBuilderException { - - // la locale par defaut est la première - Locale defaultLocale = locales[0]; - - List<URL> urls = new ArrayList<URL>(); - for (I18nArtifact artifact : i18nArtifacts) { - I18nBundleEntry[] bundleEntries = - artifact.getBundleEntries(locale, defaultLocale); - for (I18nBundleEntry bundleEntry : bundleEntries) { - - URL path = bundleEntry.getPath(); - urls.add(path); - if (verbose) { - getLog().info("add " + path); - } - } - } - return urls.toArray(new URL[urls.size()]); - } - - protected void storeCollectI18nResources(File bundleOut, URL[] urls) - throws IOException { - StringBuilder buffer = new StringBuilder(); - - for (URL path : urls) { - - buffer.append(path).append("\n"); - - if (verbose) { - getLog().info("add " + path); - } - } - writeFile(bundleOut, buffer.toString(), encoding); - } - - /** - * Detecte les {@link I18nArtifact} et les retourne dans l'ordre de - * chargement dans le système i18n, i.e l'ordre des dependances entre - * artifacts. - * - * @return les artifacts i18nables triés par leur ordre de chargement dans - * le système i18n. - * @throws IOException while detecting bundles from artifacts - * @throws DependencyTreeBuilderException if any error while building the - * depencendy tree - */ - protected I18nArtifact[] detectI18nArtifacts() - throws IOException, DependencyTreeBuilderException { - - Map<Artifact, I18nArtifact> dico = - new HashMap<Artifact, I18nArtifact>(); - - I18nArtifact i18nArtifact; - for (Object o : project.getArtifacts()) { - i18nArtifact = new I18nArtifact((Artifact) o); - if (i18nArtifact.detectBundles()) { - if (!silent) { - getLog().info("detected i18n artifact " + i18nArtifact); - } - dico.put(i18nArtifact.getArtifact(), i18nArtifact); - } else { - if (getLog().isDebugEnabled()) { - getLog().debug("reject artifact " + i18nArtifact); - } - } - } - - ArtifactFilter artifactFilter - = new ScopeArtifactFilter(Artifact.SCOPE_RUNTIME); - - DependencyNode rootNode = dependencyTreeBuilder.buildDependencyTree( - project, localRepository, factory, - artifactMetadataSource, artifactFilter, collector); - - List<Artifact> artifacts = new ArrayList<Artifact>(dico.keySet()); - - DependencyUtil.sortArtifacts(rootNode, artifacts, - getLog().isDebugEnabled()); - - // l'artifact du projet est traite en dernier car s'il possède des - // bundles alors ils doivent etre charge en dernier - - Artifact projectArtifact = project.getArtifact(); - i18nArtifact = new I18nArtifact(projectArtifact, src.getParentFile()); - - if (i18nArtifact.detectBundles()) { - if (!silent) { - getLog().info("detected i18n artifact " + i18nArtifact); - } - artifacts.add(i18nArtifact.getArtifact()); - dico.put(i18nArtifact.getArtifact(), i18nArtifact); - } else { - if (getLog().isDebugEnabled()) { - getLog().debug("reject artifact " + i18nArtifact); - } - } - - I18nArtifact[] result = new I18nArtifact[artifacts.size()]; - int i = 0; - for (Artifact artifact : artifacts) { - result[i++] = dico.get(artifact); - } - return result; - } -} 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-03-08 11:04:08 UTC (rev 1707) +++ trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/GenerateMojo.java 2010-03-08 18:35:57 UTC (rev 1708) @@ -48,8 +48,8 @@ protected boolean checkBundle; /** - * Un drapeau pour afficher les entrées vides. (nécessite - * {@link #checkBundle} activé). + * Un drapeau pour afficher les entrées vides. (nécessite {@link + * #checkBundle} activé). * * @parameter expression="${i18n.showEmpty}" default-value="false" * @required Deleted: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/I18nArtifact.java =================================================================== --- trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/I18nArtifact.java 2010-03-08 11:04:08 UTC (rev 1707) +++ trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/I18nArtifact.java 2010-03-08 18:35:57 UTC (rev 1708) @@ -1,109 +0,0 @@ -/* - * *##% - * I18n :: Maven Plugin - * Copyright (C) 2007 - 2009 CodeLutin - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * ##%* - */ -package org.nuiton.i18n.plugin; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.maven.artifact.Artifact; -import org.nuiton.i18n.bundle.I18nBundle; -import org.nuiton.i18n.bundle.I18nBundleEntry; -import org.nuiton.i18n.bundle.I18nBundleUtil; - -import java.io.File; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.List; -import java.util.Locale; - -/** - * @author tchemit <chemit@codelutin.com> - * @since 0.12 - */ -public class I18nArtifact { - - static final Log log = LogFactory.getLog(I18nArtifact.class); - - protected final Artifact artifact; - - protected final URL url; - - protected I18nBundle[] bundles; - - public I18nArtifact(Artifact artifact) throws MalformedURLException { - this.artifact = artifact; - url = artifact.getFile().toURI().toURL(); - } - - public I18nArtifact(Artifact artifact, - File file) throws MalformedURLException { - this.artifact = artifact; - url = file.toURI().toURL(); - } - - public Artifact getArtifact() { - return artifact; - } - - public URL getUrl() { - return url; - } - - public I18nBundleEntry[] getBundleEntries(Locale l, Locale defaultLocale) { - if (bundles == null) { - throw new NullPointerException( - "le bundleManager n'a pas ete initialise!"); - } - return I18nBundleUtil.getBundleEntries(l, defaultLocale, bundles); - } - - public boolean detectBundles() throws IOException { - - URL[] i18nUrls = I18nBundleUtil.getURLs(url); - - if (i18nUrls == null || i18nUrls.length == 0) { - // aucune url sur un fichier de traduction trouve - // l'artifact n'est pas i18n. - if (log.isDebugEnabled()) { - log.debug("no i18n url for artifact " + artifact); - } - return false; - } - - List<I18nBundle> listBundles = - I18nBundleUtil.detectBundles(i18nUrls); - - if (listBundles.isEmpty()) { - // pas de bundle instancie (cela ne devrait jamais arrive...) - return false; - } - - bundles = listBundles.toArray(new I18nBundle[listBundles.size()]); - - return true; - } - - @Override - public String toString() { - return artifact.getGroupId() + ":" + artifact.getArtifactId() + ":" + - artifact.getVersion(); - } -} Deleted: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/I18nLogger.java =================================================================== --- trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/I18nLogger.java 2010-03-08 11:04:08 UTC (rev 1707) +++ trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/I18nLogger.java 2010-03-08 18:35:57 UTC (rev 1708) @@ -1,132 +0,0 @@ -/** - * *##% - * I18n :: Maven Plugin - * Copyright (C) 2007 - 2009 CodeLutin - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * ##%* - */ -package org.nuiton.i18n.plugin; - -import org.apache.maven.plugin.logging.SystemStreamLog; -import org.nuiton.plugin.PluginHelper; - -import java.beans.Introspector; -import java.io.File; - -/** - * Le logger utilisé par les mojo. - * - * @author tchemit <chemit@codelutin.com> - * @since 0.9 - */ -public class I18nLogger extends SystemStreamLog { - - /** - * l'entrée en cours de traitement (pour les parseurs) - */ - private SourceEntry entry; - - /** - * le fichier en cours de traitement (pour les parseurs) - */ - protected File file; - - /** - * le prefix du mojo courant a ajouter dans les logs. - */ - protected String parser; - - public I18nLogger(AbstractI18nMojo parser) { - this.parser = "i18n:" + Introspector.decapitalize( - parser.getClass().getSimpleName()) + " on " + - parser.getArtifactId(); - } - - @Override - public void info(CharSequence content) { - print(0, "INFO", null, content.toString()); - } - - @Override - public void debug(CharSequence content) { - print(0, "DEBUG", null, content.toString()); - } - - public void infoEntry(String action, CharSequence content) { - print(0, "INFO", action, - entry.toString() + - (content == null ? "" : " - " + content.toString())); - } - - public void infoFile(String action, String content) { - print(2, "INFO", action, file.toString() + - (content == null ? "" : " - " + content)); - } - - public void infoAction(String action, String content) { - print(2, "INFO", action, content == null ? "" : " - " + content); - } - - private void print(int start, String prefix, String context, - String content) { - StringBuilder sb = new StringBuilder(); - sb.append("[").append(prefix).append("] [").append(parser).append("] "); - - for (int i = 0; i < start; i++) { - sb.append(' '); - } - if (context != null) { - sb.append("<").append(context).append("> "); - } - sb.append(content); - System.out.println(sb.toString()); - } - - public void setEntry(SourceEntry entry) { - this.entry = entry; - } - - /** - * Construit une chaine de log formatée. - * - * @param msg le prefix du message - * @param nbFiles le nombre de fichiers actuellement traités - * @param time le time de traitement de ce fichier - * @param all le temps de traitement de tous les fichiers - * @return la chaine de log formatée - */ - public String getLogEntry(String msg, int nbFiles, long time, long all) { - long now = System.nanoTime(); - long delta = now - time; - String s = msg; - if (time > 0) { - s += " (" + PluginHelper.convertTime(delta) + ")"; - } - if (all > 0) { - s += "(total time:" + PluginHelper.convertTime(now - all) + ")"; - } - if (nbFiles > 0) { - s += " ( ~ " + - PluginHelper.convertTime((now - all) / nbFiles) + " / file)"; - } - return s; - } - - public void setFile(File file) { - this.file = file; - } - -} Deleted: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/SourceEntry.java =================================================================== --- trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/SourceEntry.java 2010-03-08 11:04:08 UTC (rev 1707) +++ trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/SourceEntry.java 2010-03-08 18:35:57 UTC (rev 1708) @@ -1,292 +0,0 @@ -/* - * *##% - * I18n :: Maven Plugin - * Copyright (C) 2007 - 2009 CodeLutin - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * ##%* - */ -package org.nuiton.i18n.plugin; - -import org.apache.maven.plugin.logging.Log; -import org.codehaus.plexus.util.DirectoryScanner; -import org.nuiton.io.FileUpdater; - -import java.io.File; -import java.lang.annotation.Annotation; -import java.net.URLClassLoader; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * A simple model for a sourceEntry represents by a basedir and includes - * and/or exlucdes pattern. - * <p/> - * The class offers the usefull method : - * {@link #getIncludedFiles(File, String[], String[])} - * <p/> - * to obtain the list of files from - * the {@link #basedir} directory which respects the {@link #includes} and/or - * {@link #excludes} patterns using an internal {@link DirectoryScanner} - * object. - * <p/> - * Note : <b>The class does not extends <code>DirectoryScanner</code> since - * we DO not want to expose his methods.</b> - * - * @author tchemit <chemit@codelutin.com> - */ -public class SourceEntry { - - /** - * If you want to restrict use of the entry, set the class name goal to - * this property via {@link #setSpecificGoal(String)}. - * <p/> - * If let to <code>null</code>, all goals can use this entry. - */ - protected String specificGoal; - - protected File basedir; - - protected String[] includes; - - protected String[] excludes; - - /** - * Files to be find - */ - protected String[] files; - - protected String[] skipFiles; - - protected String skipMessage; - - protected FileUpdater updater; - - public String[] getExcludes() { - return excludes; - } - - public void setExcludes(String[] excludes) { - this.excludes = excludes; - } - - public String[] getIncludes() { - return includes; - } - - public void setIncludes(String[] includes) { - this.includes = includes; - } - - public File getBasedir() { - return basedir; - } - - public void setBasedir(File basedir) { - this.basedir = basedir; - } - - public String getSpecificGoal() { - return specificGoal; - } - - public void setSpecificGoal(String specificGoal) { - this.specificGoal = specificGoal; - } - - public boolean useForGoal(String goal) { - return specificGoal == null || specificGoal.equalsIgnoreCase(goal); - } - - public boolean hasSrc() { - return basedir != null; - } - - public boolean hasIncludes() { - return includes != null && includes.length > 0; - } - - public boolean hasExcludes() { - return excludes != null && excludes.length > 0; - } - - /** - * Test if a file is up to date and not to be treated. - * <p/> - * - * @param file the file path to test - * @return {@code true} if file is up to date and do not need to be parsed - * @see FileUpdater - */ - public final boolean isFileUptodate(File file) { - return updater != null && updater.isFileUpToDate(file); - } - - public String[] getIncludedFiles(File defaultBasedir, - String[] defaultIncludes, - String[] defaultExcludes) { - // normalized entry - if (!hasSrc()) { - setBasedir(defaultBasedir); - } - if (!hasIncludes()) { - setIncludes(defaultIncludes); - } - if (!hasExcludes()) { - setExcludes(defaultExcludes); - } - // init directory scanner - DirectoryScanner ds = new DirectoryScanner(); - ds.setBasedir(getBasedir()); - ds.setIncludes(getIncludes()); - if (hasExcludes()) { - ds.setExcludes(getExcludes()); - } - // scan - ds.scan(); - // get found files - String[] foundFiles; - foundFiles = ds.getIncludedFiles(); - return foundFiles; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder("basedir:").append(basedir); - if (includes != null) { - sb.append(", includes:").append(Arrays.toString(includes)); - } - if (excludes != null) { - sb.append(", excludes:").append(Arrays.toString(excludes)); - } - return sb.toString(); - } - - public String[] getIncludedFiles(File basedir, - String[] defaultIncludes, - String[] defaultExcludes, - URLClassLoader loader, - List<String> annotationClass, - Log log) { - List<String> result = new ArrayList<String>(); - - for (String s : - getIncludedFiles(basedir, defaultIncludes, defaultExcludes)) { - if (filterByAnnotation(s, loader, annotationClass, log)) { - result.add(s); - } - } - return result.toArray(new String[result.size()]); - } - - protected boolean filterByAnnotation(String file, - URLClassLoader loader, - List<String> annotationClass, - Log log) { - - - Annotation annotation = getAnnotation(file, loader, annotationClass, - log); - - boolean result = annotation != null; - - if (result && log.isDebugEnabled()) { - log.debug("find i18n annotated file : " + file); - } - return result; - } - - protected String getFQN(String file) { - String filePath = file; - filePath = filePath.substring(0, filePath.length() - ".java".length()); - String replaceEx = File.separator.equals("\\") ? "\\\\" : File.separator; - return filePath.replaceAll(replaceEx, "."); - } - - public Class<?> getClass(String file, URLClassLoader loader, Log log) { - String fqn = getFQN(file); - try { - return loader.loadClass(fqn); - - } catch (Throwable e) { - log.warn("could not find class " + fqn + " " + e); - return null; - } - } - - public Annotation getAnnotation(String file, - URLClassLoader loader, - List<String> annotationClass, - Log log) { - - Class<?> currentClass = getClass(file, loader, log); - - try { - Annotation[] annos = currentClass.getAnnotations(); - if (annos != null && annos.length > 0) { - for (Annotation anno : annos) { - if (annotationClass.contains( - anno.annotationType().getName())) { - return anno; - } - } - } - } catch (Throwable e) { - log.warn("could not find annotation for " + file + " " + e); - } - return null; - - } - - public Class<?> getClass(File file, URLClassLoader loader, Log log) { - String f = file.getAbsolutePath().substring( - basedir.getAbsolutePath().length() + 1); - return getClass(f, loader, log); - } - - public Annotation getAnnotation(File file, - URLClassLoader loader, - List<String> annotationClass, - Log log) { - String f = file.getAbsolutePath().substring( - basedir.getAbsolutePath().length() + 1); - return getAnnotation(f, loader, annotationClass, log); - } - - public String getSkipMessage() { - return skipMessage; - } - - public String[] getFiles() { - return files; - } - - public String[] getSkipFiles() { - return skipFiles; - } - - public int getFoudFiles() { - return skipFiles.length + files.length; - } - - public FileUpdater getUpdater() { - return updater; - } - - public void setUpdater(FileUpdater updater) { - this.updater = updater; - } -} Copied: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/bundle/AbstractI18nBundleMojo.java (from rev 1707, trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/AbstractI18nBundleMojo.java) =================================================================== --- trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/bundle/AbstractI18nBundleMojo.java (rev 0) +++ trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/bundle/AbstractI18nBundleMojo.java 2010-03-08 18:35:57 UTC (rev 1708) @@ -0,0 +1,91 @@ +/* + * *##% + * I18n :: Maven Plugin + * Copyright (C) 2007 - 2009 CodeLutin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * ##%* + */ +package org.nuiton.i18n.plugin.bundle; + +import org.nuiton.i18n.plugin.AbstractI18nMojo; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.Locale; + +/** + * Created: 26 déc. 2009 + * + * @author tchemit <chemit@codelutin.com> + * @version $Revision$ + * <p/> + * Mise a jour: $Date$ + * par : $Author: tchemit $ + */ +public abstract class AbstractI18nBundleMojo extends AbstractI18nMojo { + + /** + * Repertoire ou generer les bundles. + * + * @parameter expression="${i18n.collectOutputDir}" default-value="${basedir}/target/i18n" + * @required + * @since 1.0.2 + */ + protected File collectOutputDir; + + /** + * Nom de base des fichiers qui contient les localisations des bundles. + * + * @parameter expression="${i18n.collectOutputName}" + * default-value="collect-${project.artifactId}-i18n" + * @required + * @since 1.0.2 + */ + protected String collectOutputName; + + /** + * Pour obtenir les urls des fichiers i18n d'un projet (avec recherche dans + * ses dépendances). + * <p/> + * <b>Note:</b> L'ordre des urls reflète l'ordre des dépendances. + * + * @param locale la locale a traiter + * @return les urls des bundles i18n detectees pour le projet. + * @throws Exception pour tout problème + */ + protected abstract URL[] getCollectI18nResources(Locale locale) + throws Exception; + + /** + * Pour obtenir le fichier contenant les localisation des bundles i18n du + * projet pour une {@code locale} donnée. + * + * @param locale la locale + * @param create un drapeau pour forcer la création du fichier s'il n'existe + * pas + * @return le fichier qui contient les urls des bundles i18n pour la locale + * donnée. + * @throws IOException pour tout pb + */ + protected File getCollectOutputFile(Locale locale, boolean create) + throws IOException { + File bundleOut = getI18nFile(collectOutputDir, collectOutputName, + locale, create); + return bundleOut; + } + +} Property changes on: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/bundle/AbstractI18nBundleMojo.java ___________________________________________________________________ Added: svn:keywords + "Author Date Id Revision HeadURL Copied: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/bundle/BundleMojo.java (from rev 1707, trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/BundleMojo.java) =================================================================== --- trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/bundle/BundleMojo.java (rev 0) +++ trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/bundle/BundleMojo.java 2010-03-08 18:35:57 UTC (rev 1708) @@ -0,0 +1,246 @@ +/* + * *##% + * I18n :: Maven Plugin + * Copyright (C) 2007 - 2009 CodeLutin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * ##%* + */ +package org.nuiton.i18n.plugin.bundle; + +import org.nuiton.i18n.bundle.I18nBundleEntry; +import org.nuiton.i18n.bundle.I18nBundleUtil; +import org.nuiton.i18n.init.DefaultI18nInitializer; +import org.nuiton.io.SortedProperties; +import org.nuiton.plugin.PluginHelper; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URL; +import java.util.*; +import java.util.Map.Entry; + +/** + * Créer un bundle pour une application finale. + * <p/> + * Cela génère un merge de tous les fichiers i18n utilisés en un seul. + * <p/> + * On utilise la dépendance sur les artifacts pour connaitre l'ordre le + * chargement des bundles. + * <p/> + * Si dans un bundle childs, la valeur de la clef est vide, on conserve alors + * celui du parent, + * <p/> + * Ainsi on obtient un bundle dont toutes les clefs sont traduites. + * <p/> + * Le but aussi d'utiliser un unique bundle est de gagner du temps au runtime + * car la recherche des bundles devient trop couteuse en temps lorsque l'on a de + * nombreuses dépendances (au dessus de 100 deps cela peut prendre plusieurs + * secondes, ce qui 'est pas acceptable). + * <p/> + * On a ajoute un second mode d'initialisation dans la clesse I18n pour + * n'utiliser qu'un seul bundle et courcircuiter le chargement couteux... + * + * @author tchemit <chemit@codelutin.com> + * @goal bundle + * @phase generate-resources + * @execute goal=collect-i18n-artifacts + * @requiresProject true + * @requiresDependencyResolution runtime + * @since 0.12 + */ +public class BundleMojo extends AbstractI18nBundleMojo { + + /** + * Repertoire ou generer les bundles. + * + * @parameter expression="${i18n.bundleOutputDir}" default-value="${basedir}/target/generated-sources/resources/META-INF" + * @required + * @since 1.0.0 + */ + protected File bundleOutputDir; + + /** + * Nom du bundle a generer. + * + * @parameter expression="${i18n.bundleOutputName}" default-value="${project.artifactId}-i18n" + * @required + * @since 1.0.2 + */ + protected String bundleOutputName; + + /** + * Un drapeau pour vérifier que les bundles ne contiennent pas d'entrées + * vides. + * + * @parameter expression="${i18n.checkBundle}" default-value="true" + * @required + * @since 1.0.0 + */ + protected boolean checkBundle; + + /** + * Un drapeau pour afficher les entrées vides. (nécessite {@link + * #checkBundle} activé). + * + * @parameter expression="${i18n.showEmpty}" default-value="false" + * @required + * @since 1.0.0 + */ + protected boolean showEmpty; + + @Override + public void init() throws Exception { + super.init(); + + createDirectoryIfNecessary(bundleOutputDir); + + // ajout de repertoire de generation (le parent en fait) + // dans les resources du projet + + addResourceDir(bundleOutputDir.getParentFile(), "**/*.properties"); + } + + @Override + protected void doAction() throws Exception { + long t00 = System.nanoTime(); + + String version = getProject().getVersion(); + version = PluginHelper.removeSnapshotSuffix(version); + + if (!silent) { + getLog().info("config - bundle name : " + bundleOutputName); + getLog().info("config - basedir : " + bundleOutputDir); + getLog().info("config - locales : " + Arrays.toString(locales)); + getLog().info("config - version : " + version); + } + + Map<Locale, String> bundleDico = + new LinkedHashMap<Locale, String>(locales.length); + + for (Locale locale : locales) { + + long t0 = System.nanoTime(); + + File bundleOut = getI18nFile(bundleOutputDir, bundleOutputName, + locale, false); + + if (!silent) { + getLog().info("generate bundle for locale " + locale); + } + + SortedProperties propertiesOut = + new SortedProperties(encoding, false); + StringBuilder buffer = new StringBuilder(); + + URL[] urls = getCollectI18nResources(locale); + if (urls.length == 0) { + getLog().warn("no bundle for locale " + locale); + continue; + } + + for (URL url : urls) { + long t000 = System.nanoTime(); + I18nBundleEntry bundleEntry = + new I18nBundleEntry(url, locale, null); + bundleEntry.load(propertiesOut); + String strPath = bundleEntry.getPath().toString(); + int index = strPath.indexOf("i18n/"); + + buffer.append(',').append(strPath.substring(index)); + if (verbose) { + getLog().info( + "loaded " + bundleEntry.getPath() + " in " + + PluginHelper.convertTime(t000, System.nanoTime())); + } + } + + if (buffer.length() > 0) { + bundleDico.put(locale, buffer.substring(1)); + if (!silent) { + getLog().info( + "bundles for locale : " + bundleDico.get(locale)); + } + } + propertiesOut.store(bundleOut); + if (!silent && verbose) { + getLog().info( + "bundle created in " + + PluginHelper.convertTime(t0, System.nanoTime()) + + " (detected sentences : " + propertiesOut.size() + ")"); + } + if (checkBundle) { + checkBundle(locale, propertiesOut, showEmpty); + } + } + + // ecriture du ficher des definitions i18n (permet de faire une + // recherche extact sur un fichier puis d'en deduire les bundles a + // charger + String f = String.format(DefaultI18nInitializer.UNIQUE_BUNDLE_DEF, + bundleOutputName); + File defOut = new File(bundleOutputDir, f); + if (!silent) { + getLog().info("prepare i18n definition " + + defOut.getAbsolutePath()); + } + SortedProperties p = new SortedProperties(encoding, false); + p.setProperty(DefaultI18nInitializer.BUNDLE_DEF_LOCALES, bundles); + p.setProperty(DefaultI18nInitializer.BUNDLE_DEF_VERSION, version); + for (Entry<Locale, String> e : bundleDico.entrySet()) { + p.setProperty(DefaultI18nInitializer.BUNDLES_FOR_LOCALE + + e.getKey().toString(), e.getValue()); + } + FileOutputStream out = new FileOutputStream(defOut); + try { + p.store(out, null); + } finally { + out.close(); + } + + if (!silent && verbose) { + getLog().info("done in " + + PluginHelper.convertTime(t00, System.nanoTime())); + } + } + + @Override + protected URL[] getCollectI18nResources(Locale locale) throws IOException { + File file = getCollectOutputFile(locale, false); + if (!file.exists()) { + return I18nBundleUtil.EMPTY_URL_ARRAY; + } + URL[] urls = getLinesAsURL(file); + return urls; + } + + /** + * TODO Move this in PluginHelper. + * + * @param src the source file to read + * @return the url instanciated from lines of the source file. + * @throws IOException if any pb while reading file + */ + public static URL[] getLinesAsURL(File src) throws IOException { + List<URL> result = new ArrayList<URL>(); + for (String line : PluginHelper.getLines(src)) { + if (!line.isEmpty()) { + result.add(new URL(line)); + } + } + return result.toArray(new URL[result.size()]); + } +} Property changes on: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/bundle/BundleMojo.java ___________________________________________________________________ Added: svn:mergeinfo + Copied: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/bundle/CollectI18nArtifactsMojo.java (from rev 1707, trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/CollectI18nArtifactsMojo.java) =================================================================== --- trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/bundle/CollectI18nArtifactsMojo.java (rev 0) +++ trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/bundle/CollectI18nArtifactsMojo.java 2010-03-08 18:35:57 UTC (rev 1708) @@ -0,0 +1,253 @@ +/* + * *##% + * I18n :: Maven Plugin + * Copyright (C) 2007 - 2009 CodeLutin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * ##%* + */ +package org.nuiton.i18n.plugin.bundle; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.factory.ArtifactFactory; +import org.apache.maven.artifact.metadata.ArtifactMetadataSource; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.artifact.resolver.ArtifactCollector; +import org.apache.maven.artifact.resolver.filter.ArtifactFilter; +import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter; +import org.apache.maven.shared.dependency.tree.DependencyNode; +import org.apache.maven.shared.dependency.tree.DependencyTreeBuilder; +import org.apache.maven.shared.dependency.tree.DependencyTreeBuilderException; +import org.nuiton.i18n.bundle.I18nBundleEntry; +import org.nuiton.plugin.DependencyUtil; +import org.nuiton.plugin.PluginHelper; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.*; + +/** + * Detects any i18n artifacts and store the result as a file. + * <p/> + * Created: 24 déc. 2009 + * + * @author tchemit <chemit@codelutin.com> + * @version $Revision$ + * <p/> + * Mise a jour: $Date$ + * par : $Author: tchemit $ + * @goal collect-i18n-artifacts + * @phase generate-resources + * @requiresProject true + * @requiresDependencyResolution runtime + * @since 1.0.2 + */ +public class CollectI18nArtifactsMojo extends AbstractI18nBundleMojo { + + /** + * Local Repository. + * + * @parameter expression="${localRepository}" + * @required + * @readonly + * @since 1.0.2 + */ + protected ArtifactRepository localRepository; + + /** + * Dependency tree builder component. + * + * @component + * @since 1.0.2 + */ + protected DependencyTreeBuilder dependencyTreeBuilder; + + /** + * Artifact Factory component. + * + * @component + * @since 1.0.2 + */ + protected ArtifactFactory factory; + + /** + * Artifact metadata source component. + * + * @component + * @since 1.0.2 + */ + protected ArtifactMetadataSource artifactMetadataSource; + + /** + * Artifact collector component. + * + * @component + * @since 1.0.2 + */ + protected ArtifactCollector collector; + + I18nArtifact[] i18nArtifacts; + + @Override + public void init() throws Exception { + super.init(); + + PluginHelper.createDirectoryIfNecessary(collectOutputDir); + } + + @Override + protected void doAction() throws Exception { + + // detects the i18n artifacts (only once since it cost some times)... + i18nArtifacts = detectI18nArtifacts(); + + if (i18nArtifacts.length == 0) { + getLog().warn("no i18n artifact detected."); + return; + } + + for (Locale locale : locales) { + + if (!silent) { + getLog().info("generate collected i18n artifacts for locale " + + locale); + } + URL[] urls = getCollectI18nResources(locale); + + if (urls.length == 0) { + getLog().warn("no i18n bundles for locale " + locale); + return; + } + + File bundleOut = getCollectOutputFile(locale, true); + + storeCollectI18nResources(bundleOut, urls); + + getLog().info("collected " + urls.length + + " i18n artifacts for locale " + locale + + " stored in " + bundleOut); + } + } + + @Override + protected URL[] getCollectI18nResources(Locale locale) + throws IOException, DependencyTreeBuilderException { + + // la locale par defaut est la première + Locale defaultLocale = locales[0]; + + List<URL> urls = new ArrayList<URL>(); + for (I18nArtifact artifact : i18nArtifacts) { + I18nBundleEntry[] bundleEntries = + artifact.getBundleEntries(locale, defaultLocale); + for (I18nBundleEntry bundleEntry : bundleEntries) { + + URL path = bundleEntry.getPath(); + urls.add(path); + if (verbose) { + getLog().info("add " + path); + } + } + } + return urls.toArray(new URL[urls.size()]); + } + + protected void storeCollectI18nResources(File bundleOut, URL[] urls) + throws IOException { + StringBuilder buffer = new StringBuilder(); + + for (URL path : urls) { + + buffer.append(path).append("\n"); + + if (verbose) { + getLog().info("add " + path); + } + } + writeFile(bundleOut, buffer.toString(), encoding); + } + + /** + * Detecte les {@link I18nArtifact} et les retourne dans l'ordre de + * chargement dans le système i18n, i.e l'ordre des dependances entre + * artifacts. + * + * @return les artifacts i18nables triés par leur ordre de chargement dans + * le système i18n. + * @throws IOException while detecting bundles from + * artifacts + * @throws DependencyTreeBuilderException if any error while building the + * depencendy tree + */ + protected I18nArtifact[] detectI18nArtifacts() + throws IOException, DependencyTreeBuilderException { + + Map<Artifact, I18nArtifact> dico = + new HashMap<Artifact, I18nArtifact>(); + + I18nArtifact i18nArtifact; + for (Object o : project.getArtifacts()) { + i18nArtifact = new I18nArtifact((Artifact) o); + if (i18nArtifact.detectBundles()) { + if (!silent) { + getLog().info("detected i18n artifact " + i18nArtifact); + } + dico.put(i18nArtifact.getArtifact(), i18nArtifact); + } else { + if (getLog().isDebugEnabled()) { + getLog().debug("reject artifact " + i18nArtifact); + } + } + } + + ArtifactFilter artifactFilter + = new ScopeArtifactFilter(Artifact.SCOPE_RUNTIME); + + DependencyNode rootNode = dependencyTreeBuilder.buildDependencyTree( + project, localRepository, factory, + artifactMetadataSource, artifactFilter, collector); + + List<Artifact> artifacts = new ArrayList<Artifact>(dico.keySet()); + + DependencyUtil.sortArtifacts(rootNode, artifacts, + getLog().isDebugEnabled()); + + // l'artifact du projet est traite en dernier car s'il possède des + // bundles alors ils doivent etre charge en dernier + + Artifact projectArtifact = project.getArtifact(); + i18nArtifact = new I18nArtifact(projectArtifact, src.getParentFile()); + + if (i18nArtifact.detectBundles()) { + if (!silent) { + getLog().info("detected i18n artifact " + i18nArtifact); + } + artifacts.add(i18nArtifact.getArtifact()); + dico.put(i18nArtifact.getArtifact(), i18nArtifact); + } else { + if (getLog().isDebugEnabled()) { + getLog().debug("reject artifact " + i18nArtifact); + } + } + + I18nArtifact[] result = new I18nArtifact[artifacts.size()]; + int i = 0; + for (Artifact artifact : artifacts) { + result[i++] = dico.get(artifact); + } + return result; + } +} Property changes on: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/bundle/CollectI18nArtifactsMojo.java ___________________________________________________________________ Added: svn:keywords + "Author Date Id Revision HeadURL Copied: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/bundle/I18nArtifact.java (from rev 1707, trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/I18nArtifact.java) =================================================================== --- trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/bundle/I18nArtifact.java (rev 0) +++ trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/bundle/I18nArtifact.java 2010-03-08 18:35:57 UTC (rev 1708) @@ -0,0 +1,109 @@ +/* + * *##% + * I18n :: Maven Plugin + * Copyright (C) 2007 - 2009 CodeLutin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * ##%* + */ +package org.nuiton.i18n.plugin.bundle; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.maven.artifact.Artifact; +import org.nuiton.i18n.bundle.I18nBundle; +import org.nuiton.i18n.bundle.I18nBundleEntry; +import org.nuiton.i18n.bundle.I18nBundleUtil; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.List; +import java.util.Locale; + +/** + * @author tchemit <chemit@codelutin.com> + * @since 0.12 + */ +public class I18nArtifact { + + static final Log log = LogFactory.getLog(I18nArtifact.class); + + protected final Artifact artifact; + + protected final URL url; + + protected I18nBundle[] bundles; + + public I18nArtifact(Artifact artifact) throws MalformedURLException { + this.artifact = artifact; + url = artifact.getFile().toURI().toURL(); + } + + public I18nArtifact(Artifact artifact, + File file) throws MalformedURLException { + this.artifact = artifact; + url = file.toURI().toURL(); + } + + public Artifact getArtifact() { + return artifact; + } + + public URL getUrl() { + return url; + } + + public I18nBundleEntry[] getBundleEntries(Locale l, Locale defaultLocale) { + if (bundles == null) { + throw new NullPointerException( + "le bundleManager n'a pas ete initialise!"); + } + return I18nBundleUtil.getBundleEntries(l, defaultLocale, bundles); + } + + public boolean detectBundles() throws IOException { + + URL[] i18nUrls = I18nBundleUtil.getURLs(url); + + if (i18nUrls == null || i18nUrls.length == 0) { + // aucune url sur un fichier de traduction trouve + // l'artifact n'est pas i18n. + if (log.isDebugEnabled()) { + log.debug("no i18n url for artifact " + artifact); + } + return false; + } + + List<I18nBundle> listBundles = + I18nBundleUtil.detectBundles(i18nUrls); + + if (listBundles.isEmpty()) { + // pas de bundle instancie (cela ne devrait jamais arrive...) + return false; + } + + bundles = listBundles.toArray(new I18nBundle[listBundles.size()]); + + return true; + } + + @Override + public String toString() { + return artifact.getGroupId() + ":" + artifact.getArtifactId() + ":" + + artifact.getVersion(); + } +} Property changes on: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/bundle/I18nArtifact.java ___________________________________________________________________ Added: svn:mergeinfo + 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-03-08 11:04:08 UTC (rev 1707) +++ trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/AbstractI18nParserMojo.java 2010-03-08 18:35:57 UTC (rev 1708) @@ -21,8 +21,6 @@ package org.nuiton.i18n.plugin.parser; import org.nuiton.i18n.plugin.AbstractI18nMojo; -import org.nuiton.i18n.plugin.I18nLogger; -import org.nuiton.i18n.plugin.SourceEntry; import org.nuiton.io.FileUpdater; import org.nuiton.io.SortedProperties; @@ -103,16 +101,15 @@ /** * flag to save previous getter in a backup before doing parsing. * <p/> - * Note: by default, do not perform backup (but it was here originaly so let it possible...) + * Note: by default, do not perform backup (but it was here originaly so let + * it possible...) * * @parameter expression="${i18n.backupGetter}" default-value="false" * @since 1.0.2 */ protected boolean backupGetter; - /** - * Liste des évènements - */ + /** Liste des évènements */ protected List<ParserEvent> events = new ArrayList<ParserEvent>(); protected SortedProperties result; @@ -129,10 +126,17 @@ protected List<File> treadedFiles; + /** logger verbeux */ + protected I18nLogger verboseLog = new I18nLogger(this); + public boolean isStrictMode() { return strictMode; } + protected I18nLogger getVerboseLog() { + return verboseLog; + } + @Override public void init() throws Exception { super.init(); @@ -141,7 +145,6 @@ oldParser = new SortedProperties(encoding); oldLanguage = new SortedProperties(encoding); createDirectoryIfNecessary(out); -// out.mkdirs(); // evenements if (keysModifier) { addParserEvent(KeysModifier.getInstance( @@ -161,7 +164,7 @@ getLog().info("detected entries : " + entries.length); for (SourceEntry e : entries) { - getLog().info(e.toString()+", specific goal ? " + + getLog().info(e.toString() + ", specific goal ? " + e.getSpecificGoal()); } } @@ -186,12 +189,10 @@ // Reprise sur un ancien parsing File oldParserFile = getGetterFile(out, getOutGetter(), true); File saveFile = getBackupFile(oldParserFile); -// File saveFile = getGetterFileBackup(out, getOutGetter()); oldParser.load(oldParserFile); if (backupGetter) { backupFile(oldParserFile); -// copyFile(oldParserFile, saveFile); } // Anciennes cles disponnibles Copied: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/I18nLogger.java (from rev 1707, trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/I18nLogger.java) =================================================================== --- trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/I18nLogger.java (rev 0) +++ trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/I18nLogger.java 2010-03-08 18:35:57 UTC (rev 1708) @@ -0,0 +1,127 @@ +/** + * *##% + * I18n :: Maven Plugin + * Copyright (C) 2007 - 2009 CodeLutin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * ##%* + */ +package org.nuiton.i18n.plugin.parser; + +import org.apache.maven.plugin.logging.SystemStreamLog; +import org.nuiton.i18n.plugin.AbstractI18nMojo; +import org.nuiton.plugin.PluginHelper; + +import java.beans.Introspector; +import java.io.File; + +/** + * Le logger utilisé par les mojo de parsing. + * + * @author tchemit <chemit@codelutin.com> + * @since 0.9 + */ +public class I18nLogger extends SystemStreamLog { + + /** l'entrée en cours de traitement (pour les parseurs) */ + private SourceEntry entry; + + /** le fichier en cours de traitement (pour les parseurs) */ + protected File file; + + /** le prefix du mojo courant a ajouter dans les logs. */ + protected String parser; + + public I18nLogger(AbstractI18nMojo parser) { + this.parser = "i18n:" + Introspector.decapitalize( + parser.getClass().getSimpleName()) + " on " + + parser.getArtifactId(); + } + + @Override + public void info(CharSequence content) { + print(0, "INFO", null, content.toString()); + } + + @Override + public void debug(CharSequence content) { + print(0, "DEBUG", null, content.toString()); + } + + public void infoEntry(String action, CharSequence content) { + print(0, "INFO", action, + entry.toString() + + (content == null ? "" : " - " + content.toString())); + } + + public void infoFile(String action, String content) { + print(2, "INFO", action, file.toString() + + (content == null ? "" : " - " + content)); + } + + public void infoAction(String action, String content) { + print(2, "INFO", action, content == null ? "" : " - " + content); + } + + private void print(int start, String prefix, String context, + String content) { + StringBuilder sb = new StringBuilder(); + sb.append("[").append(prefix).append("] [").append(parser).append("] "); + + for (int i = 0; i < start; i++) { + sb.append(' '); + } + if (context != null) { + sb.append("<").append(context).append("> "); + } + sb.append(content); + System.out.println(sb.toString()); + } + + public void setEntry(SourceEntry entry) { + this.entry = entry; + } + + /** + * Construit une chaine de log formatée. + * + * @param msg le prefix du message + * @param nbFiles le nombre de fichiers actuellement traités + * @param time le time de traitement de ce fichier + * @param all le temps de traitement de tous les fichiers + * @return la chaine de log formatée + */ + public String getLogEntry(String msg, int nbFiles, long time, long all) { + long now = System.nanoTime(); + long delta = now - time; + String s = msg; + if (time > 0) { + s += " (" + PluginHelper.convertTime(delta) + ")"; + } + if (all > 0) { + s += "(total time:" + PluginHelper.convertTime(now - all) + ")"; + } + if (nbFiles > 0) { + s += " ( ~ " + + PluginHelper.convertTime((now - all) / nbFiles) + " / file)"; + } + return s; + } + + public void setFile(File file) { + this.file = file; + } + +} Property changes on: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/I18nLogger.java ___________________________________________________________________ Added: svn:mergeinfo + Modified: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/I18nSourceEntry.java =================================================================== --- trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/I18nSourceEntry.java 2010-03-08 11:04:08 UTC (rev 1707) +++ trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/I18nSourceEntry.java 2010-03-08 18:35:57 UTC (rev 1708) @@ -20,8 +20,6 @@ */ package org.nuiton.i18n.plugin.parser; -import org.nuiton.i18n.plugin.SourceEntry; - import java.io.File; import java.util.ArrayList; import java.util.List; Modified: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/KeysModifier.java =================================================================== --- trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/KeysModifier.java 2010-03-08 11:04:08 UTC (rev 1707) +++ trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/KeysModifier.java 2010-03-08 18:35:57 UTC (rev 1708) @@ -47,6 +47,7 @@ private static final long serialVersionUID = 1L; // Modification des clés dans le fichier + protected List<String> newKeys; protected boolean needModifiedFile; @@ -58,6 +59,7 @@ protected String encoding; // Interface + protected JLabel name = new JLabel(); protected JLabel path = new JLabel(); @@ -205,7 +207,7 @@ return key.getText(); } - /** Action sur le boutton pour passer � la cl� suivante */ + /** Action sur le boutton pour passer a la cle suivante */ class EventNextKey implements ActionListener { @Override public void actionPerformed(ActionEvent e) { Copied: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/SourceEntry.java (from rev 1707, trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/SourceEntry.java) =================================================================== --- trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/SourceEntry.java (rev 0) +++ trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/SourceEntry.java 2010-03-08 18:35:57 UTC (rev 1708) @@ -0,0 +1,289 @@ +/* + * *##% + * I18n :: Maven Plugin + * Copyright (C) 2007 - 2009 CodeLutin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * ##%* + */ +package org.nuiton.i18n.plugin.parser; + +import org.apache.maven.plugin.logging.Log; +import org.codehaus.plexus.util.DirectoryScanner; +import org.nuiton.io.FileUpdater; + +import java.io.File; +import java.lang.annotation.Annotation; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * A simple model for a sourceEntry represents by a basedir and includes and/or + * exlucdes pattern. + * <p/> + * The class offers the usefull method : {@link #getIncludedFiles(File, + * String[], String[])} + * <p/> + * to obtain the list of files from the {@link #basedir} directory which + * respects the {@link #includes} and/or {@link #excludes} patterns using an + * internal {@link DirectoryScanner} object. + * <p/> + * Note : <b>The class does not extends <code>DirectoryScanner</code> since we + * DO not want to expose his methods.</b> + * + * @author tchemit <chemit@codelutin.com> + */ +public class SourceEntry { + + /** + * If you want to restrict use of the entry, set the class name goal to this + * property via {@link #setSpecificGoal(String)}. + * <p/> + * If let to <code>null</code>, all goals can use this entry. + */ + protected String specificGoal; + + protected File basedir; + + protected String[] includes; + + protected String[] excludes; + + /** Files to be find */ + protected String[] files; + + protected String[] skipFiles; + + protected String skipMessage; + + protected FileUpdater updater; + + public String[] getExcludes() { + return excludes; + } + + public void setExcludes(String[] excludes) { + this.excludes = excludes; + } + + public String[] getIncludes() { + return includes; + } + + public void setIncludes(String[] includes) { + this.includes = includes; + } + + public File getBasedir() { + return basedir; + } + + public void setBasedir(File basedir) { + this.basedir = basedir; + } + + public String getSpecificGoal() { + return specificGoal; + } + + public void setSpecificGoal(String specificGoal) { + this.specificGoal = specificGoal; + } + + public boolean useForGoal(String goal) { + return specificGoal == null || specificGoal.equalsIgnoreCase(goal); + } + + public boolean hasSrc() { + return basedir != null; + } + + public boolean hasIncludes() { + return includes != null && includes.length > 0; + } + + public boolean hasExcludes() { + return excludes != null && excludes.length > 0; + } + + /** + * Test if a file is up to date and not to be treated. + * <p/> + * + * @param file the file path to test + * @return {@code true} if file is up to date and do not need to be parsed + * @see FileUpdater + */ + public final boolean isFileUptodate(File file) { + return updater != null && updater.isFileUpToDate(file); + } + + public String[] getIncludedFiles(File defaultBasedir, + String[] defaultIncludes, + String[] defaultExcludes) { + // normalized entry + if (!hasSrc()) { + setBasedir(defaultBasedir); + } + if (!hasIncludes()) { + setIncludes(defaultIncludes); + } + if (!hasExcludes()) { + setExcludes(defaultExcludes); + } + // init directory scanner + DirectoryScanner ds = new DirectoryScanner(); + ds.setBasedir(getBasedir()); + ds.setIncludes(getIncludes()); + if (hasExcludes()) { + ds.setExcludes(getExcludes()); + } + // scan + ds.scan(); + // get found files + String[] foundFiles; + foundFiles = ds.getIncludedFiles(); + return foundFiles; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("basedir:").append(basedir); + if (includes != null) { + sb.append(", includes:").append(Arrays.toString(includes)); + } + if (excludes != null) { + sb.append(", excludes:").append(Arrays.toString(excludes)); + } + return sb.toString(); + } + + public String[] getIncludedFiles(File basedir, + String[] defaultIncludes, + String[] defaultExcludes, + URLClassLoader loader, + List<String> annotationClass, + Log log) { + List<String> result = new ArrayList<String>(); + + for (String s : + getIncludedFiles(basedir, defaultIncludes, defaultExcludes)) { + if (filterByAnnotation(s, loader, annotationClass, log)) { + result.add(s); + } + } + return result.toArray(new String[result.size()]); + } + + protected boolean filterByAnnotation(String file, + URLClassLoader loader, + List<String> annotationClass, + Log log) { + + + Annotation annotation = getAnnotation(file, loader, annotationClass, + log); + + boolean result = annotation != null; + + if (result && log.isDebugEnabled()) { + log.debug("find i18n annotated file : " + file); + } + return result; + } + + protected String getFQN(String file) { + String filePath = file; + filePath = filePath.substring(0, filePath.length() - ".java".length()); + String replaceEx = File.separator.equals("\\") ? "\\\\" : File.separator; + return filePath.replaceAll(replaceEx, "."); + } + + public Class<?> getClass(String file, URLClassLoader loader, Log log) { + String fqn = getFQN(file); + try { + return loader.loadClass(fqn); + + } catch (Throwable e) { + log.warn("could not find class " + fqn + " " + e); + return null; + } + } + + public Annotation getAnnotation(String file, + URLClassLoader loader, + List<String> annotationClass, + Log log) { + + Class<?> currentClass = getClass(file, loader, log); + + try { + Annotation[] annos = currentClass.getAnnotations(); + if (annos != null && annos.length > 0) { + for (Annotation anno : annos) { + if (annotationClass.contains( + anno.annotationType().getName())) { + return anno; + } + } + } + } catch (Throwable e) { + log.warn("could not find annotation for " + file + " " + e); + } + return null; + + } + + public Class<?> getClass(File file, URLClassLoader loader, Log log) { + String f = file.getAbsolutePath().substring( + basedir.getAbsolutePath().length() + 1); + return getClass(f, loader, log); + } + + public Annotation getAnnotation(File file, + URLClassLoader loader, + List<String> annotationClass, + Log log) { + String f = file.getAbsolutePath().substring( + basedir.getAbsolutePath().length() + 1); + return getAnnotation(f, loader, annotationClass, log); + } + + public String getSkipMessage() { + return skipMessage; + } + + public String[] getFiles() { + return files; + } + + public String[] getSkipFiles() { + return skipFiles; + } + + public int getFoudFiles() { + return skipFiles.length + files.length; + } + + public FileUpdater getUpdater() { + return updater; + } + + public void setUpdater(FileUpdater updater) { + this.updater = updater; + } +} Property changes on: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/SourceEntry.java ___________________________________________________________________ Added: svn:keywords + "Author Date Id Revision HeadURL Modified: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/impl/ParserJavaMojo.java =================================================================== --- trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/impl/ParserJavaMojo.java 2010-03-08 11:04:08 UTC (rev 1707) +++ trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/impl/ParserJavaMojo.java 2010-03-08 18:35:57 UTC (rev 1708) @@ -20,11 +20,7 @@ package org.nuiton.i18n.plugin.parser.impl; -import org.nuiton.i18n.plugin.SourceEntry; -import org.nuiton.i18n.plugin.parser.AbstractI18nParserMojo; -import org.nuiton.i18n.plugin.parser.I18nSourceEntry; -import org.nuiton.i18n.plugin.parser.ParserEvent; -import org.nuiton.i18n.plugin.parser.ParserException; +import org.nuiton.i18n.plugin.parser.*; import org.nuiton.io.FileUpdater; import org.nuiton.io.FileUpdaterHelper; import org.nuiton.processor.filters.I18nFilter; Modified: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/impl/ParserValidationMojo.java =================================================================== --- trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/impl/ParserValidationMojo.java 2010-03-08 11:04:08 UTC (rev 1707) +++ trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/impl/ParserValidationMojo.java 2010-03-08 18:35:57 UTC (rev 1708) @@ -19,8 +19,8 @@ * ##%* */ package org.nuiton.i18n.plugin.parser.impl; -import org.nuiton.i18n.plugin.SourceEntry; import org.nuiton.i18n.plugin.parser.I18nSourceEntry; +import org.nuiton.i18n.plugin.parser.SourceEntry; import org.nuiton.io.FileUpdater; import org.nuiton.io.MirroredFileUpdater; import org.xml.sax.EntityResolver; @@ -36,8 +36,9 @@ /** * Récupération des chaine à traduire depuis les fichiers xml de validation. * <p/> - * Le goal doit etre execute avant que les resources soient copiees dans target/classes - * pour rendre operatne le file updater (sinon lesfichiers sont toujours a jour...) + * Le goal doit etre execute avant que les resources soient copiees dans + * target/classes pour rendre operatne le file updater (sinon lesfichiers sont + * toujours a jour...) * * @author chemit * @goal parserValidation @@ -161,6 +162,7 @@ public static final String XWORK_PUBLIC_ID = "-//OpenSymphony Group//XWork Validator 1.0.2//EN"; + boolean useLocal = useLocalResolver; @Override Modified: trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/impl/ParserXmlMojo.java =================================================================== --- trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/impl/ParserXmlMojo.java 2010-03-08 11:04:08 UTC (rev 1707) +++ trunk/maven-i18n-plugin/src/main/java/org/nuiton/i18n/plugin/parser/impl/ParserXmlMojo.java 2010-03-08 18:35:57 UTC (rev 1708) @@ -44,10 +44,9 @@ */ public abstract class ParserXmlMojo extends AbstractI18nParserMojo { - /** - * Taille du buffer pour les lectures/écritures - */ + /** Taille du buffer pour les lectures/écritures */ protected static final int BUFFER_SIZE = 8 * 1024; + /** * default src for an entry. * @@ -72,14 +71,10 @@ */ public abstract String extract(String i18nString); - /** - * @return le fichier des rules - */ + /** @return le fichier des rules */ protected abstract String getFileRules(); - /** - * @return le fichier des rules de base à toujours charger - */ + /** @return le fichier des rules de base à toujours charger */ protected abstract String getCoreFileRules(); @Override