This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository observe. See https://gitlab.nuiton.org/codelutin/observe.git commit 4ca7029ccaf2a58e56d2713223b64401f6221995 Author: Tony CHEMIT <chemit@codelutin.com> Date: Wed Aug 31 13:29:44 2016 +0200 Rename maven plugin + add two new mojo to generate validators stuffs. --- .../LICENSE.txt | 0 {check-api-maven-plugin => maven-plugin}/README.md | 0 {check-api-maven-plugin => maven-plugin}/pom.xml | 19 +- .../src/license/THIRD-PARTY.properties | 0 .../maven/plugins/checkapi/CheckApiMojo.java | 0 .../checkapi/GenerateI18nValidatorFieldsMojo.java | 223 +++++++++++++++++++++ .../checkapi/GenerateValidatorsDescriptorMojo.java | 183 +++++++++++++++++ .../MismatchMethodParameterNameException.java | 0 .../plugins/checkapi/MissingClassException.java | 0 .../plugins/checkapi/MissingMethodException.java | 0 .../plugins/checkapi/ValidatorCacheRequest.java | 25 +++ .../maven/plugins/checkapi/ValidatorsCache.java | 184 +++++++++++++++++ maven-plugin/src/main/resources/log4j.properties | 33 +++ 13 files changed, 662 insertions(+), 5 deletions(-) diff --git a/check-api-maven-plugin/LICENSE.txt b/maven-plugin/LICENSE.txt similarity index 100% rename from check-api-maven-plugin/LICENSE.txt rename to maven-plugin/LICENSE.txt diff --git a/check-api-maven-plugin/README.md b/maven-plugin/README.md similarity index 100% rename from check-api-maven-plugin/README.md rename to maven-plugin/README.md diff --git a/check-api-maven-plugin/pom.xml b/maven-plugin/pom.xml similarity index 88% rename from check-api-maven-plugin/pom.xml rename to maven-plugin/pom.xml index a67a4da..92f3248 100644 --- a/check-api-maven-plugin/pom.xml +++ b/maven-plugin/pom.xml @@ -31,10 +31,10 @@ <version>5.0-SNAPSHOT</version> </parent> - <artifactId>check-api-maven-plugin</artifactId> + <artifactId>maven-plugin</artifactId> - <name>ObServe :: Check API maven plugin</name> - <description>ObServe Check API maven plugin module</description> + <name>ObServe :: Maven plugin</name> + <description>ObServe Maven plugin module</description> <packaging>maven-plugin</packaging> <dependencies> @@ -43,6 +43,15 @@ <artifactId>helper-maven-plugin-api</artifactId> </dependency> + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-validator</artifactId> + </dependency> + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + </dependency> + <!-- provided dependencies --> <dependency> @@ -94,12 +103,12 @@ <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-jcl</artifactId> - <scope>test</scope> + <scope>runtime</scope> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> - <scope>test</scope> + <scope>runtime</scope> </dependency> </dependencies> diff --git a/check-api-maven-plugin/src/license/THIRD-PARTY.properties b/maven-plugin/src/license/THIRD-PARTY.properties similarity index 100% rename from check-api-maven-plugin/src/license/THIRD-PARTY.properties rename to maven-plugin/src/license/THIRD-PARTY.properties diff --git a/check-api-maven-plugin/src/main/java/fr/ird/observe/maven/plugins/checkapi/CheckApiMojo.java b/maven-plugin/src/main/java/fr/ird/observe/maven/plugins/checkapi/CheckApiMojo.java similarity index 100% rename from check-api-maven-plugin/src/main/java/fr/ird/observe/maven/plugins/checkapi/CheckApiMojo.java rename to maven-plugin/src/main/java/fr/ird/observe/maven/plugins/checkapi/CheckApiMojo.java diff --git a/maven-plugin/src/main/java/fr/ird/observe/maven/plugins/checkapi/GenerateI18nValidatorFieldsMojo.java b/maven-plugin/src/main/java/fr/ird/observe/maven/plugins/checkapi/GenerateI18nValidatorFieldsMojo.java new file mode 100644 index 0000000..a06aea4 --- /dev/null +++ b/maven-plugin/src/main/java/fr/ird/observe/maven/plugins/checkapi/GenerateI18nValidatorFieldsMojo.java @@ -0,0 +1,223 @@ +package fr.ird.observe.maven.plugins.checkapi; + +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.apache.maven.project.MavenProject; +import org.nuiton.plugin.AbstractPlugin; +import org.nuiton.plugin.PluginHelper; + +import java.io.BufferedWriter; +import java.io.File; +import java.net.MalformedURLException; +import java.net.URLClassLoader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +/** + * Pour générer les clefs i18n des champs utilisés dans les validateurs. + * + * Created on 31/08/16. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 5.0 + */ +@Mojo(name = "generate-i18n-validator-fields", defaultPhase = LifecyclePhase.GENERATE_RESOURCES, requiresDependencyResolution = ResolutionScope.COMPILE) +class GenerateI18nValidatorFieldsMojo extends AbstractPlugin implements ValidatorCacheRequest { + + @Parameter(defaultValue = "${project}", required = true, readonly = true) + private MavenProject project; + + @Parameter(defaultValue = "${project.basedir}/src/main/resources", required = true) + private File sourceRoot; + + @Parameter(defaultValue = "${project.basedir}/src/main/validators/validators.xml", required = true) + private File validatorsFile; + + /** + * Un flag pour activer le mode verbeux. + * + * @since 1.0.0 + */ + @Parameter(property = "generateI18nValidatorFields.verbose", defaultValue = "${maven.verbose}") + private boolean verbose; + + /** + * A flag to skip the goal. + * + * @since 1.0.0 + */ + @Parameter(property = "generateI18nValidatorFields.skip", defaultValue = "false") + private boolean skip; + + /** + * Encoding a utiliser pour lire et ecrire les fichiers. + * + * @since 1.0.0 + */ + @Parameter(property = "i18n.encoding", defaultValue = "${project.build.sourceEncoding}", required = true) + protected String encoding; + + /** + * To set the package fully qualified name of the generated class. + * + * By default, will use groupId.artifactId (with {@code -} replaced by {@code .}). + */ + @Parameter(property = "i18n.packageName") + private String packageName; + + /** + * Name of the generated class. + */ + @Parameter(property = "i18n.className", defaultValue = "I18nValidatorHelper", required = true) + private String className; + + /** + * Prefix to add to generated i18n keys. + */ + @Parameter(property = "i18n.prefix") + private String prefix; + /** + * The root directory where to generated. + */ + @Parameter(property = "i18n.outputDirectory", defaultValue = "${basedir}/target/generated-sources/java", required = true) + private File outputDirectory; + + @Parameter(property = "generateI18nValidatorFields.contexts", required = true) + private String[] contexts; + + private Path outputFile; + + private Collection<ValidatorsCache.ValidatorInfo> validators; + + @Override + protected void init() throws Exception { + + if (skip) { + return; + } + if (getLog().isDebugEnabled()) { + setVerbose(true); + } + + if (packageName == null) { + + packageName = getProject().getGroupId() + "." + getProject().getArtifactId().replaceAll("-", "."); + + } + Path directory = PluginHelper.getFile(outputDirectory, packageName.trim().split("\\.")).toPath(); + + Files.createDirectories(directory); + + outputFile = directory.resolve(className + ".java"); + + validators = ValidatorsCache.get().getValidators(this); + } + + @Override + protected boolean checkSkip() { + if (skip) { + getLog().info("Skipping goal (skip flag is on)."); + return false; + } + if (validators.isEmpty()) { + getLog().info("Skipping goal (no validator detected)."); + return false; + } + + return super.checkSkip(); + } + + @Override + public void doAction() throws Exception { + + if (isVerbose()) { + getLog().info("project = " + project); + } + + getLog().info("Generate to " + outputFile); + + List<String> compileSourceRoots = getProject().getCompileSourceRoots(); + + if (!compileSourceRoots.contains(outputDirectory.getAbsolutePath())) { + + getLog().info("Add to compile source root: " + outputDirectory); + + getProject().addCompileSourceRoot(outputDirectory.getAbsolutePath()); + } + + Set<String> fields = new TreeSet<>(); + for (ValidatorsCache.ValidatorInfo validator : validators) { + fields.addAll(validator.getFields()); + } + + getLog().info(fields.size() + " field(s) detected."); + + try (BufferedWriter writer = Files.newBufferedWriter(outputFile, StandardCharsets.UTF_8)) { + + writer.write("// Generated by " + getClass().getName() + " at " + new Date() + "\n"); + writer.write("package " + packageName + ";\n"); + writer.write("\n"); + writer.write("\n"); + writer.write("import static org.nuiton.i18n.I18n.n;\n"); + writer.write("\n"); + writer.write("\n"); + writer.write("public class " + className + " {\n"); + writer.write("\n static {"); + writer.write("\n"); + + for (String field : fields) { + writer.write(" n(\"" + prefix + field + "\");\n"); + } + + writer.write("\n"); + writer.write(" }\n"); + writer.write("\n"); + writer.write("}\n"); + + } + } + + + @Override + public MavenProject getProject() { + return project; + } + + @Override + public boolean isVerbose() { + return verbose; + } + + @Override + public String[] getContexts() { + return contexts; + } + + @Override + public URLClassLoader getUrlClassLoader() throws MalformedURLException { + return initClassLoader(project, validatorsFile.getParentFile(), true, false, true, true, false); + } + + @Override + public void setProject(MavenProject project) { + this.project = project; + } + + @Override + public void setVerbose(boolean verbose) { + this.verbose = verbose; + } + + @Override + public Path getSourceRootPath() { + return sourceRoot.toPath(); + } +} diff --git a/maven-plugin/src/main/java/fr/ird/observe/maven/plugins/checkapi/GenerateValidatorsDescriptorMojo.java b/maven-plugin/src/main/java/fr/ird/observe/maven/plugins/checkapi/GenerateValidatorsDescriptorMojo.java new file mode 100644 index 0000000..0d7015a --- /dev/null +++ b/maven-plugin/src/main/java/fr/ird/observe/maven/plugins/checkapi/GenerateValidatorsDescriptorMojo.java @@ -0,0 +1,183 @@ +package fr.ird.observe.maven.plugins.checkapi; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonObject; +import com.google.gson.JsonSerializer; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.apache.maven.project.MavenProject; +import org.nuiton.plugin.AbstractPlugin; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URLClassLoader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Set; +import java.util.TreeSet; + +/** + * Pour générer les clefs i18n des champs utilisés dans les validateurs. + * + * Created on 31/08/16. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 5.0 + */ +@Mojo(name = "generate-validators-descriptor", defaultPhase = LifecyclePhase.GENERATE_RESOURCES, requiresDependencyResolution = ResolutionScope.COMPILE) +class GenerateValidatorsDescriptorMojo extends AbstractPlugin implements ValidatorCacheRequest { + + @Parameter(defaultValue = "${project}", required = true, readonly = true) + private MavenProject project; + + @Parameter(defaultValue = "${project.basedir}/src/main/resources", required = true) + private File sourceRoot; + + @Parameter(defaultValue = "${project.basedir}/src/main/resources/validators.xml", required = true) + private File validatorsFile; + + /** + * The root directory where to generated. + */ + @Parameter(property = "generateValidatorsDescriptor.outputFile", defaultValue = "${project.build.outputDirectory}/META-INF/validators/${project.artifactId}.json", required = true) + private File outputFile; + + /** + * Un flag pour activer le mode verbeux. + * + * @since 1.0.0 + */ + @Parameter(property = "generateValidatorsDescriptor.verbose", defaultValue = "${maven.verbose}") + private boolean verbose; + + /** + * A flag to skip the goal. + * + * @since 1.0.0 + */ + @Parameter(property = "generateValidatorsDescriptor.skip", defaultValue = "false") + private boolean skip; + + /** + * Encoding a utiliser pour lire et ecrire les fichiers. + * + * @since 1.0.0 + */ + @Parameter(property = "generateValidatorsDescriptor.encoding", defaultValue = "${project.build.sourceEncoding}", required = true) + protected String encoding; + + @Parameter(property = "generateValidatorsDescriptor.contexts", required = true) + private String[] contexts; + + private Collection<ValidatorsCache.ValidatorInfo> validators; + + @Override + protected void init() throws Exception { + + if (skip) { + return; + } + if (getLog().isDebugEnabled()) { + setVerbose(true); + } + + Files.createDirectories(outputFile.getParentFile().toPath()); + + validators = ValidatorsCache.get().getValidators(this); + } + + @Override + protected boolean checkSkip() { + if (skip) { + getLog().info("Skipping goal (skip flag is on)."); + return false; + } + if (validators.isEmpty()) { + getLog().info("Skipping goal (no validator detected)."); + return false; + } + + return super.checkSkip(); + } + + @Override + public void doAction() throws Exception { + + if (isVerbose()) { + getLog().info("project = " + project); + } + + getLog().info("Generate to " + outputFile); + + Set<String> fields = new TreeSet<>(); + for (ValidatorsCache.ValidatorInfo validator : validators) { + fields.addAll(validator.getFields()); + } + + getLog().info(fields.size() + " field(s) detected."); + + ArrayList<ValidatorsCache.ValidatorInfo> validatorList = new ArrayList<>(validators); + + Collections.sort(validatorList, (o1, o2) -> o1.getType().getName().compareToIgnoreCase(o2.getType().getName())); + + Gson gson = new GsonBuilder() + .setPrettyPrinting() + .registerTypeAdapter(ValidatorsCache.ValidatorInfo.class, (JsonSerializer<ValidatorsCache.ValidatorInfo>) (src, typeOfSrc, context) -> { + + JsonObject element2 = new JsonObject(); + element2.add("type", context.serialize(src.getType().getName())); + element2.add("context", context.serialize(src.getContext())); + element2.add("scope", context.serialize(src.getScope())); + element2.add("fields", context.serialize(src.getFields())); + + return element2; + }) + .create(); + String validatorsJson = gson.toJson(validatorList); + Files.write(outputFile.toPath(), validatorsJson.getBytes(StandardCharsets.UTF_8)); + + } + + + @Override + public MavenProject getProject() { + return project; + } + + @Override + public boolean isVerbose() { + return verbose; + } + + @Override + public String[] getContexts() { + return contexts; + } + + @Override + public URLClassLoader getUrlClassLoader() throws MalformedURLException { + return initClassLoader(project, validatorsFile.getParentFile(), true, false, true, true, false); + } + + @Override + public void setProject(MavenProject project) { + this.project = project; + } + + @Override + public void setVerbose(boolean verbose) { + this.verbose = verbose; + } + + @Override + public Path getSourceRootPath() { + return sourceRoot.toPath(); + } +} diff --git a/check-api-maven-plugin/src/main/java/fr/ird/observe/maven/plugins/checkapi/MismatchMethodParameterNameException.java b/maven-plugin/src/main/java/fr/ird/observe/maven/plugins/checkapi/MismatchMethodParameterNameException.java similarity index 100% rename from check-api-maven-plugin/src/main/java/fr/ird/observe/maven/plugins/checkapi/MismatchMethodParameterNameException.java rename to maven-plugin/src/main/java/fr/ird/observe/maven/plugins/checkapi/MismatchMethodParameterNameException.java diff --git a/check-api-maven-plugin/src/main/java/fr/ird/observe/maven/plugins/checkapi/MissingClassException.java b/maven-plugin/src/main/java/fr/ird/observe/maven/plugins/checkapi/MissingClassException.java similarity index 100% rename from check-api-maven-plugin/src/main/java/fr/ird/observe/maven/plugins/checkapi/MissingClassException.java rename to maven-plugin/src/main/java/fr/ird/observe/maven/plugins/checkapi/MissingClassException.java diff --git a/check-api-maven-plugin/src/main/java/fr/ird/observe/maven/plugins/checkapi/MissingMethodException.java b/maven-plugin/src/main/java/fr/ird/observe/maven/plugins/checkapi/MissingMethodException.java similarity index 100% rename from check-api-maven-plugin/src/main/java/fr/ird/observe/maven/plugins/checkapi/MissingMethodException.java rename to maven-plugin/src/main/java/fr/ird/observe/maven/plugins/checkapi/MissingMethodException.java diff --git a/maven-plugin/src/main/java/fr/ird/observe/maven/plugins/checkapi/ValidatorCacheRequest.java b/maven-plugin/src/main/java/fr/ird/observe/maven/plugins/checkapi/ValidatorCacheRequest.java new file mode 100644 index 0000000..8ca27f7 --- /dev/null +++ b/maven-plugin/src/main/java/fr/ird/observe/maven/plugins/checkapi/ValidatorCacheRequest.java @@ -0,0 +1,25 @@ +package fr.ird.observe.maven.plugins.checkapi; + +import org.apache.maven.plugin.logging.Log; + +import java.net.MalformedURLException; +import java.net.URLClassLoader; +import java.nio.file.Path; + +/** + * Created on 31/08/16. + * + * @author Tony Chemit - chemit@codelutin.com + */ +public interface ValidatorCacheRequest { + + Log getLog(); + + Path getSourceRootPath(); + + boolean isVerbose(); + + String[] getContexts(); + + URLClassLoader getUrlClassLoader() throws MalformedURLException; +} diff --git a/maven-plugin/src/main/java/fr/ird/observe/maven/plugins/checkapi/ValidatorsCache.java b/maven-plugin/src/main/java/fr/ird/observe/maven/plugins/checkapi/ValidatorsCache.java new file mode 100644 index 0000000..f505deb --- /dev/null +++ b/maven-plugin/src/main/java/fr/ird/observe/maven/plugins/checkapi/ValidatorsCache.java @@ -0,0 +1,184 @@ +package fr.ird.observe.maven.plugins.checkapi; + +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Multimap; +import org.apache.maven.plugin.logging.Log; +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.simple.SimpleBeanValidator; + +import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.Arrays; +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.Set; + +/** + * Created on 31/08/16. + * + * @author Tony Chemit - chemit@codelutin.com + */ +public class ValidatorsCache { + + public static class ValidatorInfo { + + private final Class<?> type; + private final String context; + private final NuitonValidatorScope scope; + private final Set<String> fields; + + ValidatorInfo(Class<?> type, String context, NuitonValidatorScope scope, Set<String> fields) { + this.type = type; + this.context = context; + this.scope = scope; + this.fields = fields; + } + + public Class<?> getType() { + return type; + } + + public String getContext() { + return context; + } + + public NuitonValidatorScope getScope() { + return scope; + } + + public Set<String> getFields() { + return fields; + } + } + + private final static ValidatorsCache instance = new ValidatorsCache(); + + public static ValidatorsCache get() { + return instance; + } + + private final Multimap<String, ValidatorInfo> validators = ArrayListMultimap.create(); + + public Collection<ValidatorInfo> getValidators(ValidatorCacheRequest request) throws IOException { + + Log log = request.getLog(); + boolean verbose = request.isVerbose(); + Path sourceRootPath = request.getSourceRootPath(); + String[] contexts = request.getContexts(); + + String key = sourceRootPath.toFile().getAbsolutePath() + "#" + String.join("-", (CharSequence[]) contexts); + if (!validators.containsKey(key)) { + + log.info("Loading validators " + Arrays.toString(contexts) + " from " + sourceRootPath); + + ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); + try { + + + Thread.currentThread().setContextClassLoader(request.getUrlClassLoader()); + + Set<Class<?>> types = new PathSimpleFileVisitor(log, sourceRootPath, verbose).walk(); + + NuitonValidatorScope[] scopes = NuitonValidatorScope.values(); + + for (String context : contexts) { + + for (Class<?> type : types) { + + SimpleBeanValidator<?> validator = SimpleBeanValidator.newValidator(type, context, scopes); + + for (NuitonValidatorScope scope : validator.getEffectiveScopes()) { + + Set<String> effectiveFields = validator.getEffectiveFields(scope); + ValidatorInfo validatorInfo = new ValidatorInfo(type, context, scope, effectiveFields); + validators.put(key, validatorInfo); + } + + } + + } + + } finally { + + Thread.currentThread().setContextClassLoader(contextClassLoader); + + } + + } + return validators.get(key); + } + + private static class PathSimpleFileVisitor extends SimpleFileVisitor<Path> { + + private final Set<Class<?>> types = new LinkedHashSet<>(); + private final Log log; + private final Path sourceRootPath; + private final boolean verbose; + + private String packageName = ""; + + PathSimpleFileVisitor(Log log, Path sourceRootPath, boolean verbose) { + + this.log = log; + this.sourceRootPath = sourceRootPath; + this.verbose = verbose; + } + + public Set<Class<?>> walk() throws IOException { + + Files.walkFileTree(sourceRootPath, this); + + log.info(types.size() + " type(s) detected."); + return types; + } + + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { + if (!dir.equals(sourceRootPath)) { + if (!packageName.isEmpty()) { + packageName += "."; + } + packageName += dir.toFile().getName(); + } + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { + if (!dir.equals(sourceRootPath)) { + String name = dir.toFile().getName(); + packageName = packageName.substring(0, packageName.length() - name.length()); + if (packageName.endsWith(".")) { + packageName = packageName.substring(0, packageName.length() - 1); + } + } + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + String name = file.toFile().getName(); + if (name.endsWith("-validation.xml")) { + int i = name.indexOf('-'); + String typeName = packageName + "." + name.substring(0, i); + try { + Class<?> type = Class.forName(typeName); + + boolean add = types.add(type); + if (add) { + if (verbose) { + log.info("Register " + typeName); + } + } + } catch (ClassNotFoundException e) { + throw new IllegalStateException("Can't find class: " + typeName); + } + } + return FileVisitResult.CONTINUE; + } + } +} diff --git a/maven-plugin/src/main/resources/log4j.properties b/maven-plugin/src/main/resources/log4j.properties new file mode 100644 index 0000000..0c0d367 --- /dev/null +++ b/maven-plugin/src/main/resources/log4j.properties @@ -0,0 +1,33 @@ +### +# #%L +# I18n :: Maven Plugin +# +# $Id$ +# $HeadURL$ +# %% +# Copyright (C) 2007 - 2010 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>. +# #L% +### +# Global logging configuration +log4j.rootLogger=ERROR, stdout +# Console output... +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) %M - %m%n + +# package level +log4j.logger.fr.ird=INFO -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.