Dear developers, After some months of reporting issues for Maven, I have noticed common bugs in various plugins. For me it seems that many developers are either completely unaware of the problems (i.e. do not handle them at all) or are misunderstanding them (i.e. handle them insufficiently). Therefore, I would like to illustrate the source of those problems in more detail such that developers can start to prevent bugs right from the beginning rather than fixing them afterwards.
1) Relative Paths It is common practice for users of Maven to specify relative paths in the POM, not to mention that the Super POM does so, too. The intention is almost always to resolve such relative paths against the base directory of the current project. In other words, the paths target/classes and ${basedir}/target/classes should resolve to the same directory for a given POM. Unfortunately, the class java.io.File does not resolve relative paths against the project's base directory. As mentioned in its class javadoc [0], it resolves relative paths against the current working directory. In plain English: Unless a Maven component has complete control over the current working directory, any usage of java.io.File in combination with a relative path is a bug. At first glance, one might be tempted to argue that the project base directory is equal to the current working directory. However, this assumption is generally not true. Consider the following scenarios: a) Reactor Builds When a child module is build during a reactor build, the current working is usually the base directory of the parent project, not the base directory of the current module. That is the most common scenario where users are faced with the bug. b) Embedded Maven Invocations Other tools, most prominently IDEs, that run Maven under the hood may have set the current working directory to their installation folder or whatever they like. c) Maven Invocations using the -f switch While it is surely an uncommon use-case, the user is free to invoke Maven from an arbitrary working directory by specifying an absolute path like mvn -f /home/me/projects/demo/pom.xml In order to guarantee reliable builds, Maven and its plugins must manually resolve relative paths against the project's base directory. A simple idiom like the following should do just fine: File file = new File( path ); if ( !file.isAbsolute() ) { file = new File( project.getBasedir(), file ); } Many Maven plugins can get this resolution automatically if they declare their affected mojo parameters of type java.io.File instead of java.lang.String. This subtle difference in parameter types will trigger a feature that seems to be known as "path translation", i.e. Maven itself will properly resolve relative paths when it pumps the XML configuration into a mojo. While it will not cure this problem completely, I suggest to review the MavenProject API such that it ensures the following invariant: All paths reported by means of a getter-like method are absolute. This basically requires to resolve all relative paths that are pushed in by a setter-like method. MavenProject.addCompileSourceRoot() is just one example for a public API method that currently blindly accepts a relative path, giving rise to later failures because a misbehaving component resolves this path not properly. 2) Resource Bundle Families Especially reporting plugins employ resource bundles to support internationalization. One language (usually English) is provided as the fallback/default language in the base resource bundle. Due to the lookup strategy performed by ResourceBundle.getBundle() [1], one must always provide a dedicated resource bundle for this default language, too. This bundle can be empty because it inherits the strings via the parent chain from the base bundle, but it must exist. Take the following example. A report mojo uses a resource bundle family with the base name "mymojo-report" and erroneously provides only the following bundles: - mymojo-report.properties (base bundle for English) - mymojo-report_de.properties (specific bundle for German) Further assume that the default locale of the current JVM is "de". Now, when ResourceBundle.getBundle() is called to retrieve the bundle for locale "en", it will try the following candidate bundles and use the first one found: - mymojo-report_en.properties (candidate for requested locale) - mymojo-report_de.properties (candidate for default locale) - mymojo-report.properties (base bundle, always last) Because "mymojo-report_en.properties" does not exist, the bundle "mymojo-report_de.properties" will be chosen instead of the base bundle which would have provided the requested English translation. Plugin developers can easily expose this bug when calling mvn site -Dlocales=xy,en where "xy" denotes some other language supported by the plugin. Specifying "xy" as the first locale will have the Maven Site Plugin change the JVM's default locale to "xy" which in turn causes the lookup for "en" to fail as outlined above. Thanks for your attention, Benjamin Bentmann [0] http://java.sun.com/javase/6/docs/api/java/io/File.html [1] http://java.sun.com/javase/6/docs/api/java/util/ResourceBundle.html#getBundle(java.lang.String,%20java.util.Locale,%20java.lang.ClassLoader) [2] http://jira.codehaus.org/browse/MNG-3273 --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]