View Javadoc

1   package org.apache.maven.plugin.resources.remote;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.maven.ProjectDependenciesResolver;
23  import org.apache.maven.artifact.Artifact;
24  import org.apache.maven.artifact.factory.ArtifactFactory;
25  import org.apache.maven.artifact.repository.ArtifactRepository;
26  import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
27  import org.apache.maven.artifact.resolver.ArtifactResolutionException;
28  import org.apache.maven.artifact.resolver.ArtifactResolver;
29  import org.apache.maven.artifact.versioning.VersionRange;
30  import org.apache.maven.execution.MavenSession;
31  import org.apache.maven.model.Model;
32  import org.apache.maven.model.Organization;
33  import org.apache.maven.model.Resource;
34  import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
35  import org.apache.maven.plugin.AbstractMojo;
36  import org.apache.maven.plugin.MojoExecutionException;
37  import org.apache.maven.plugin.logging.Log;
38  import org.apache.maven.plugin.resources.remote.io.xpp3.RemoteResourcesBundleXpp3Reader;
39  import org.apache.maven.plugin.resources.remote.io.xpp3.SupplementalDataModelXpp3Reader;
40  import org.apache.maven.plugins.annotations.Component;
41  import org.apache.maven.plugins.annotations.LifecyclePhase;
42  import org.apache.maven.plugins.annotations.Mojo;
43  import org.apache.maven.plugins.annotations.Parameter;
44  import org.apache.maven.project.InvalidProjectModelException;
45  import org.apache.maven.project.MavenProject;
46  import org.apache.maven.project.MavenProjectBuilder;
47  import org.apache.maven.project.ProjectBuildingException;
48  import org.apache.maven.project.artifact.InvalidDependencyVersionException;
49  import org.apache.maven.project.inheritance.ModelInheritanceAssembler;
50  import org.apache.maven.shared.artifact.filter.collection.ArtifactFilterException;
51  import org.apache.maven.shared.artifact.filter.collection.ArtifactIdFilter;
52  import org.apache.maven.shared.artifact.filter.collection.FilterArtifacts;
53  import org.apache.maven.shared.artifact.filter.collection.GroupIdFilter;
54  import org.apache.maven.shared.artifact.filter.collection.ProjectTransitivityFilter;
55  import org.apache.maven.shared.artifact.filter.collection.ScopeFilter;
56  import org.apache.maven.shared.filtering.MavenFileFilter;
57  import org.apache.maven.shared.filtering.MavenFileFilterRequest;
58  import org.apache.maven.shared.filtering.MavenFilteringException;
59  import org.apache.velocity.VelocityContext;
60  import org.apache.velocity.app.Velocity;
61  import org.apache.velocity.app.VelocityEngine;
62  import org.apache.velocity.exception.MethodInvocationException;
63  import org.apache.velocity.exception.ParseErrorException;
64  import org.apache.velocity.exception.ResourceNotFoundException;
65  import org.apache.velocity.runtime.RuntimeServices;
66  import org.apache.velocity.runtime.log.LogChute;
67  import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
68  import org.codehaus.plexus.resource.ResourceManager;
69  import org.codehaus.plexus.resource.loader.FileResourceLoader;
70  import org.codehaus.plexus.util.FileUtils;
71  import org.codehaus.plexus.util.IOUtil;
72  import org.codehaus.plexus.util.ReaderFactory;
73  import org.codehaus.plexus.util.StringUtils;
74  import org.codehaus.plexus.util.WriterFactory;
75  import org.codehaus.plexus.util.xml.Xpp3Dom;
76  import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
77  
78  import java.io.File;
79  import java.io.FileInputStream;
80  import java.io.FileOutputStream;
81  import java.io.FileReader;
82  import java.io.FileWriter;
83  import java.io.IOException;
84  import java.io.InputStream;
85  import java.io.InputStreamReader;
86  import java.io.OutputStream;
87  import java.io.OutputStreamWriter;
88  import java.io.PrintWriter;
89  import java.io.Reader;
90  import java.io.StringReader;
91  import java.io.Writer;
92  import java.net.MalformedURLException;
93  import java.net.URL;
94  import java.text.SimpleDateFormat;
95  import java.util.ArrayList;
96  import java.util.Arrays;
97  import java.util.Collections;
98  import java.util.Comparator;
99  import java.util.Date;
100 import java.util.Enumeration;
101 import java.util.HashMap;
102 import java.util.LinkedHashSet;
103 import java.util.List;
104 import java.util.Map;
105 import java.util.Properties;
106 import java.util.Set;
107 import java.util.TreeMap;
108 
109 /**
110  * <p>
111  * Pull down resourceBundles containing remote resources and process the
112  * resources contained inside. When that is done the resources are injected
113  * into the current (in-memory) Maven project, making them available to the
114  * process-resources phase.
115  * </p>
116  * <p>
117  * Resources that end in ".vm" are treated as velocity templates.  For those, the ".vm" is
118  * stripped off for the final artifact name and it's  fed through velocity to have properties
119  * expanded, conditions processed, etc...
120  * </p>
121  * <p/>
122  * Resources that don't end in ".vm" are copied "as is".
123  */
124 // NOTE: Removed the following in favor of maven-artifact-resolver library, for MRRESOURCES-41
125 // If I leave this intact, interdependent projects within the reactor that haven't been built
126 // (remember, this runs in the generate-resources phase) will cause the build to fail.
127 //
128 // @requiresDependencyResolution test
129 @Mojo( name = "process", defaultPhase = LifecyclePhase.GENERATE_RESOURCES, threadSafe = true )
130 public class ProcessRemoteResourcesMojo
131     extends AbstractMojo implements LogChute
132 {
133 
134     private static final String TEMPLATE_SUFFIX = ".vm";
135 
136     /**
137      * <p>
138      * In cases where a local resource overrides one from a remote resource bundle, that resource
139      * should be filtered if the resource set specifies it. In those cases, this parameter defines
140      * the list of delimiters for filterable expressions. These delimiters are specified in the
141      * form 'beginToken*endToken'. If no '*' is given, the delimiter is assumed to be the same for start and end.
142      * </p>
143      * <p>
144      * So, the default filtering delimiters might be specified as:
145      * </p>
146      * <pre>
147      * &lt;delimiters&gt;
148      *   &lt;delimiter&gt;${*}&lt/delimiter&gt;
149      *   &lt;delimiter&gt;@&lt/delimiter&gt;
150      * &lt;/delimiters&gt;
151      * </pre>
152      * <p/>
153      * Since the '@' delimiter is the same on both ends, we don't need to specify '@*@' (though we can).
154      *
155      * @since 1.1
156      */
157     @Parameter
158     protected List<String> filterDelimiters;
159 
160     /**
161      * @since 1.1
162      */
163     @Parameter( defaultValue = "true" )
164     protected boolean useDefaultFilterDelimiters;
165 
166     /**
167      * If true, only generate resources in the directory of the root project in a multimodule build.
168      * Dependencies from all modules will be aggregated before resource-generation takes place.
169      *
170      * @since 1.1
171      */
172     @Parameter( defaultValue = "false" )
173     protected boolean runOnlyAtExecutionRoot;
174 
175     /**
176      * Used for calculation of execution-root for {@link ProcessRemoteResourcesMojo#runOnlyAtExecutionRoot}.
177      */
178     @Parameter( defaultValue = "${basedir}", readonly = true, required = true )
179     protected File basedir;
180 
181     /**
182      * The character encoding scheme to be applied when filtering resources.
183      */
184     @Parameter( property = "encoding", defaultValue = "${project.build.sourceEncoding}" )
185     protected String encoding;
186 
187     /**
188      * The local repository taken from Maven's runtime. Typically $HOME/.m2/repository.
189      */
190     @Parameter( defaultValue = "${localRepository}", readonly = true, required = true )
191     private ArtifactRepository localRepository;
192 
193     /**
194      * List of Remote Repositories used by the resolver.
195      */
196     @Parameter( defaultValue = "${project.remoteArtifactRepositories}", readonly = true, required = true )
197     private List<ArtifactRepository> remoteArtifactRepositories;
198 
199     /**
200      * The current Maven project.
201      */
202     @Component
203     private MavenProject project;
204 
205     /**
206      * The directory where processed resources will be placed for packaging.
207      */
208     @Parameter( defaultValue = "${project.build.directory}/maven-shared-archive-resources" )
209     private File outputDirectory;
210 
211     /**
212      * The directory containing extra information appended to the generated resources.
213      */
214     @Parameter( defaultValue = "${basedir}/src/main/appended-resources" )
215     private File appendedResourcesDirectory;
216 
217     /**
218      * Supplemental model data.  Useful when processing
219      * artifacts with incomplete POM metadata.
220      * <p/>
221      * By default, this Mojo looks for supplemental model
222      * data in the file "${appendedResourcesDirectory}/supplemental-models.xml".
223      *
224      * @since 1.0-alpha-5
225      */
226     @Parameter
227     private String[] supplementalModels;
228 
229     /**
230      * List of artifacts that are added to the search path when looking
231      * for supplementalModels, expressed with
232      * <code>groupId:artifactId:version[:type[:classifier]]</code> format.
233      *
234      * @since 1.1
235      */
236     @Parameter
237     private List<String> supplementalModelArtifacts;
238 
239     /**
240      * Map of artifacts to supplemental project object models.
241      */
242     private Map<String, Model> supplementModels;
243 
244     /**
245      * Merges supplemental data model with artifact
246      * metadata.  Useful when processing artifacts with
247      * incomplete POM metadata.
248      */
249     @Component
250     private ModelInheritanceAssembler inheritanceAssembler;
251 
252     /**
253      * The resource bundles that will be retrieved and processed,
254      * expressed with <code>groupId:artifactId:version[:type[:classifier]]</code> format.
255      */
256     @Parameter( required = true )
257     private List<String> resourceBundles;
258 
259     /**
260      * Skip remote-resource processing
261      *
262      * @since 1.0-alpha-5
263      */
264     @Parameter( property = "remoteresources.skip", defaultValue = "false" )
265     private boolean skip;
266 
267     /**
268      * Attaches the resources to the project as a resource directory.
269      *
270      * @since 1.0-beta-1
271      * @deprecated Please use {@link #attachToMain} and {@link #attachToTest} instead.
272      */
273     @Deprecated
274     @Parameter( defaultValue = "true" )
275     private boolean attached = true;
276 
277     /**
278      * Attaches the resources to the main build of the project as a resource
279      * directory.
280      *
281      * @since 1.5
282      */
283     @Parameter( defaultValue = "true", property = "attachToMain" )
284     private boolean attachToMain;
285 
286     /**
287      * Attaches the resources to the test build of the project as a resource
288      * directory.
289      *
290      * @since 1.5
291      */
292     @Parameter( defaultValue = "true", property = "attachToTest" )
293     private boolean attachToTest;
294 
295     /**
296      * Additional properties to be passed to velocity.
297      * <p/>
298      * Several properties are automatically added:<br/>
299      * project - the current MavenProject <br/>
300      * projects - the list of dependency projects<br/>
301      * projectTimespan - the timespan of the current project (requires inceptionYear in pom)<br/>
302      * locator - the ResourceManager that can be used to retrieve additional resources<br/>
303      * <p/>
304      * See <a href="http://maven.apache.org/ref/current/maven-project/apidocs/org/apache/maven/project/MavenProject.html">
305      * the javadoc for MavenProject</a> for information about the properties on the MavenProject.
306      */
307     @Parameter
308     private Map<String, Object> properties = new HashMap<String, Object>();
309     
310     /**
311      * Whether to include properties defined in the project when filtering resources.
312      *
313      * @since 1.2
314      */
315     @Parameter( defaultValue = "false" )
316     protected boolean includeProjectProperties = false;
317 
318     /**
319      * The list of resources defined for the project.
320      */
321     @Parameter( defaultValue = "${project.resources}", readonly = true, required = true )
322     private List<Resource> resources;
323 
324     /**
325      * Artifact Resolver, needed to resolve and download the {@code resourceBundles}.
326      */
327     @Component
328     private ArtifactResolver artifactResolver;
329 
330     /**
331      * Filtering support, for local resources that override those in the remote bundle.
332      */
333     @Component
334     private MavenFileFilter fileFilter;
335 
336     /**
337      * Artifact factory, needed to create artifacts.
338      */
339     @Component
340     private ArtifactFactory artifactFactory;
341 
342     /**
343      * The Maven session.
344      */
345     @Component
346     private MavenSession mavenSession;
347 
348     /**
349      * ProjectBuilder, needed to create projects from the artifacts.
350      */
351     @Component( role = MavenProjectBuilder.class )
352     private MavenProjectBuilder mavenProjectBuilder;
353 
354     /**
355      */
356     @Component
357     private ResourceManager locator;
358 
359 
360     /**
361      * Scope to include. An Empty string indicates all scopes (default is "runtime").
362      *
363      * @since 1.0
364      */
365     @Parameter( property = "includeScope", defaultValue = "runtime" )
366     protected String includeScope;
367 
368     /**
369      * Scope to exclude. An Empty string indicates no scopes (default).
370      *
371      * @since 1.0
372      */
373     @Parameter( property = "excludeScope", defaultValue = "" )
374     protected String excludeScope;
375     
376     
377     /**
378      * When resolving project dependencies, specify the scopes to include.
379      * The default is the same as "includeScope" if there are no exclude scopes set.
380      * Otherwise, it defaults to "test" to grab all the dependencies so the
381      * exclude filters can filter out what is not needed.
382      * @since 1.5 
383      */
384     @Parameter
385     private String[] resolveScopes;
386     
387 
388     /**
389      * Comma separated list of Artifact names too exclude.
390      *
391      * @since 1.0
392      */
393     @Parameter( property = "excludeArtifactIds", defaultValue = "" )
394     protected String excludeArtifactIds;
395 
396     /**
397      * Comma separated list of Artifact names to include.
398      *
399      * @since 1.0
400      */
401     @Parameter( property = "includeArtifactIds", defaultValue = "" )
402     protected String includeArtifactIds;
403 
404     /**
405      * Comma separated list of GroupId Names to exclude.
406      *
407      * @since 1.0
408      */
409     @Parameter( property = "excludeGroupIds", defaultValue = "" )
410     protected String excludeGroupIds;
411 
412     /**
413      * Comma separated list of GroupIds to include.
414      *
415      * @since 1.0
416      */
417     @Parameter( property = "includeGroupIds", defaultValue = "" )
418     protected String includeGroupIds;
419 
420     /**
421      * If we should exclude transitive dependencies
422      *
423      * @since 1.0
424      */
425     @Parameter( property = "excludeTransitive", defaultValue = "false" )
426     protected boolean excludeTransitive;
427 
428     /**
429      */
430     @Component( hint = "default" )
431     protected ProjectDependenciesResolver dependencyResolver;
432 
433     
434     private VelocityEngine velocity;
435     
436     @SuppressWarnings( "unchecked" )
437     public void execute()
438         throws MojoExecutionException
439     {
440         if ( skip )
441         {
442             return;
443         }
444 
445         if ( runOnlyAtExecutionRoot && !isExecutionRoot() )
446         {
447             getLog().info( "Skipping remote-resource generation in this project because it's not the Execution Root" );
448             return;
449         }
450         if ( resolveScopes == null )
451         {
452             if ( excludeScope == null || "".equals( excludeScope ) )
453             {
454                 resolveScopes = new String[] { this.includeScope };
455             }
456             else
457             {
458                 resolveScopes = new String[] { Artifact.SCOPE_TEST };
459             }
460         }
461         velocity = new VelocityEngine();
462         velocity.setProperty( VelocityEngine.RUNTIME_LOG_LOGSYSTEM, this );
463         velocity.setProperty( "resource.loader", "classpath" );
464         velocity.setProperty( "classpath.resource.loader.class", ClasspathResourceLoader.class.getName() );
465         velocity.init();
466 
467         if ( supplementalModels == null )
468         {
469             File sups = new File( appendedResourcesDirectory, "supplemental-models.xml" );
470             if ( sups.exists() )
471             {
472                 try
473                 {
474                     supplementalModels = new String[]{ sups.toURI().toURL().toString() };
475                 }
476                 catch ( MalformedURLException e )
477                 {
478                     //ignore
479                     getLog().debug( "URL issue with supplemental-models.xml: " + e.toString() );
480                 }
481             }
482         }
483 
484         addSupplementalModelArtifacts();
485         locator.addSearchPath( FileResourceLoader.ID, project.getFile().getParentFile().getAbsolutePath() );
486         if ( appendedResourcesDirectory != null )
487         {
488             locator.addSearchPath( FileResourceLoader.ID, appendedResourcesDirectory.getAbsolutePath() );
489         }
490         locator.addSearchPath( "url", "" );
491         locator.setOutputDirectory( new File( project.getBuild().getDirectory() ) );
492 
493         if ( includeProjectProperties )
494         {
495             final Properties projectProperties = project.getProperties();
496             for ( Object key : projectProperties.keySet() )
497             {
498                 properties.put( key.toString(), projectProperties.get( key ).toString() );
499             }
500         }
501 
502         ClassLoader origLoader = Thread.currentThread().getContextClassLoader();
503         try
504         {
505             Thread.currentThread().setContextClassLoader( this.getClass().getClassLoader() );
506 
507             validate();
508 
509             List<File> resourceBundleArtifacts = downloadBundles( resourceBundles );
510             supplementModels = loadSupplements( supplementalModels );
511 
512             VelocityContext context = new VelocityContext( properties );
513             configureVelocityContext( context );
514 
515             RemoteResourcesClassLoader classLoader = new RemoteResourcesClassLoader( null );
516 
517             initalizeClassloader( classLoader, resourceBundleArtifacts );
518             Thread.currentThread().setContextClassLoader( classLoader );
519 
520             processResourceBundles( classLoader, context );
521 
522             try
523             {
524                 if ( outputDirectory.exists() )
525                 {
526                     // ----------------------------------------------------------------------------
527                     // Push our newly generated resources directory into the MavenProject so that
528                     // these resources can be picked up by the process-resources phase.
529                     // ----------------------------------------------------------------------------
530                     Resource resource = new Resource();
531                     resource.setDirectory( outputDirectory.getAbsolutePath() );
532                     // MRRESOURCES-61 handle main and test resources separately
533                     if ( attached && attachToMain )
534                     {
535                         project.getResources().add( resource );
536                     }
537                     if ( attached && attachToTest )
538                     {
539                         project.getTestResources().add( resource );
540                     }
541 
542                     // ----------------------------------------------------------------------------
543                     // Write out archiver dot file
544                     // ----------------------------------------------------------------------------
545                     File dotFile = new File( project.getBuild().getDirectory(), ".plxarc" );
546                     FileUtils.mkdir( dotFile.getParentFile().getAbsolutePath() );
547                     FileUtils.fileWrite( dotFile.getAbsolutePath(), outputDirectory.getName() );
548                 }
549             }
550             catch ( IOException e )
551             {
552                 throw new MojoExecutionException( "Error creating dot file for archiving instructions.", e );
553             }
554         }
555         finally
556         {
557             Thread.currentThread().setContextClassLoader( origLoader );
558         }
559     }
560 
561     private boolean isExecutionRoot()
562     {
563         Log log = this.getLog();
564 
565         boolean result = mavenSession.getExecutionRootDirectory().equalsIgnoreCase( basedir.toString() );
566 
567         if ( log.isDebugEnabled() )
568         {
569             log.debug( "Root Folder:" + mavenSession.getExecutionRootDirectory() );
570             log.debug( "Current Folder:" + basedir );
571 
572             if ( result )
573             {
574                 log.debug( "This is the execution root." );
575             }
576             else
577             {
578                 log.debug( "This is NOT the execution root." );
579             }
580         }
581 
582         return result;
583     }
584 
585     private void addSupplementalModelArtifacts()
586         throws MojoExecutionException
587     {
588         if ( supplementalModelArtifacts != null && !supplementalModelArtifacts.isEmpty() )
589         {
590             List<File> artifacts = downloadBundles( supplementalModelArtifacts );
591 
592             for ( File artifact : artifacts )
593             {
594                 if ( artifact.isDirectory() )
595                 {
596                     locator.addSearchPath( FileResourceLoader.ID, artifact.getAbsolutePath() );
597                 }
598                 else
599                 {
600                     try
601                     {
602                         locator.addSearchPath( "jar", "jar:" + artifact.toURI().toURL().toExternalForm() );
603                     }
604                     catch ( MalformedURLException e )
605                     {
606                         throw new MojoExecutionException( "Could not use jar " + artifact.getAbsolutePath(), e );
607                     }
608                 }
609             }
610 
611 
612         }
613     }
614 
615     @SuppressWarnings( "unchecked" )
616     protected List<MavenProject> getProjects()
617         throws MojoExecutionException
618     {
619         List<MavenProject> projects = new ArrayList<MavenProject>();
620 
621         // add filters in well known order, least specific to most specific
622         FilterArtifacts filter = new FilterArtifacts();
623 
624         Set<Artifact> artifacts = resolveProjectArtifacts();
625         if ( this.excludeTransitive )
626         {
627             Set<Artifact> depArtifacts;
628             if ( runOnlyAtExecutionRoot )
629             {
630                 depArtifacts = aggregateProjectDependencyArtifacts();
631             }
632             else
633             {
634                 depArtifacts = project.getDependencyArtifacts();
635             }
636             filter.addFilter( new ProjectTransitivityFilter( depArtifacts, true ) );
637         }
638 
639         filter.addFilter( new ScopeFilter( this.includeScope, this.excludeScope ) );
640         filter.addFilter( new GroupIdFilter( this.includeGroupIds, this.excludeGroupIds ) );
641         filter.addFilter( new ArtifactIdFilter( this.includeArtifactIds, this.excludeArtifactIds ) );
642 
643         // perform filtering
644         try
645         {
646             artifacts = filter.filter( artifacts );
647         }
648         catch ( ArtifactFilterException e )
649         {
650             throw new MojoExecutionException( e.getMessage(), e );
651         }
652 
653         for ( Artifact artifact : artifacts )
654         {
655             try
656             {
657                 List<ArtifactRepository> remoteRepo = remoteArtifactRepositories;
658                 if ( artifact.isSnapshot() )
659                 {
660                     VersionRange rng = VersionRange.createFromVersion( artifact.getBaseVersion() );
661                     artifact =
662                         artifactFactory.createDependencyArtifact( artifact.getGroupId(), artifact.getArtifactId(), rng,
663                                                                   artifact.getType(), artifact.getClassifier(),
664                                                                   artifact.getScope(), null, artifact.isOptional() );
665                 }
666 
667                 getLog().debug( "Building project for " + artifact );
668                 MavenProject p = null;
669                 try
670                 {
671                     p = mavenProjectBuilder.buildFromRepository( artifact, remoteRepo, localRepository );
672                 }
673                 catch ( InvalidProjectModelException e )
674                 {
675                     getLog().warn( "Invalid project model for artifact [" + artifact.getArtifactId() + ":" +
676                                        artifact.getGroupId() + ":" + artifact.getVersion() + "]. " +
677                                        "It will be ignored by the remote resources Mojo." );
678                     continue;
679                 }
680 
681                 String supplementKey =
682                     generateSupplementMapKey( p.getModel().getGroupId(), p.getModel().getArtifactId() );
683 
684                 if ( supplementModels.containsKey( supplementKey ) )
685                 {
686                     Model mergedModel = mergeModels( p.getModel(), supplementModels.get( supplementKey ) );
687                     MavenProject mergedProject = new MavenProject( mergedModel );
688                     projects.add( mergedProject );
689                     mergedProject.setArtifact( artifact );
690                     mergedProject.setVersion( artifact.getVersion() );
691                     getLog().debug( "Adding project with groupId [" + mergedProject.getGroupId() + "] (supplemented)" );
692                 }
693                 else
694                 {
695                     projects.add( p );
696                     getLog().debug( "Adding project with groupId [" + p.getGroupId() + "]" );
697                 }
698             }
699             catch ( ProjectBuildingException e )
700             {
701                 throw new MojoExecutionException( e.getMessage(), e );
702             }
703         }
704         Collections.sort( projects, new ProjectComparator() );
705         return projects;
706     }
707 
708     private Set<Artifact> resolveProjectArtifacts()
709         throws MojoExecutionException
710     {
711         try
712         {
713             if ( runOnlyAtExecutionRoot )
714             {
715                 List<MavenProject> projects = mavenSession.getSortedProjects();
716                 return dependencyResolver.resolve( projects, Arrays.asList( resolveScopes ),
717                                                    mavenSession );
718             }
719             else
720             {
721                 return dependencyResolver.resolve( project, Arrays.asList( resolveScopes ),
722                                                    mavenSession );
723             }
724         }
725         catch ( ArtifactResolutionException e )
726         {
727             throw new MojoExecutionException(
728                 "Failed to resolve dependencies for one or more projects in the reactor. Reason: " + e.getMessage(),
729                 e );
730         }
731         catch ( ArtifactNotFoundException e )
732         {
733             throw new MojoExecutionException(
734                 "Failed to resolve dependencies for one or more projects in the reactor. Reason: " + e.getMessage(),
735                 e );
736         }
737     }
738 
739     @SuppressWarnings( "unchecked" )
740     private Set<Artifact> aggregateProjectDependencyArtifacts()
741         throws MojoExecutionException
742     {
743         Set<Artifact> artifacts = new LinkedHashSet<Artifact>();
744 
745         List<MavenProject> projects = mavenSession.getSortedProjects();
746         for ( MavenProject p : projects )
747         {
748             if ( p.getDependencyArtifacts() == null )
749             {
750                 try
751                 {
752                     Set<Artifact> depArtifacts = p.createArtifacts( artifactFactory, null, null );
753 
754                     if ( depArtifacts != null && !depArtifacts.isEmpty() )
755                     {
756                         for ( Artifact artifact : depArtifacts )
757                         {
758                             if ( artifact.getVersion() == null && artifact.getVersionRange() != null )
759                             {
760                                 // Version is required for equality comparison between artifacts,
761                                 // but it is not needed for our purposes of filtering out
762                                 // transitive dependencies (which requires only groupId/artifactId).
763                                 // Therefore set an arbitrary version if missing.
764                                 artifact.setResolvedVersion( Artifact.LATEST_VERSION );
765                             }
766                             artifacts.add( artifact );
767                         }  
768                     }
769                 }
770                 catch ( InvalidDependencyVersionException e )
771                 {
772                     throw new MojoExecutionException(
773                         "Failed to create dependency artifacts for: " + p.getId() + ". Reason: " + e.getMessage(), e );
774                 }
775             }
776         }
777 
778         return artifacts;
779     }
780 
781     protected Map<Organization, List<MavenProject>> getProjectsSortedByOrganization( List<MavenProject> projects )
782         throws MojoExecutionException
783     {
784         Map<Organization, List<MavenProject>> organizations =
785             new TreeMap<Organization, List<MavenProject>>( new OrganizationComparator() );
786         List<MavenProject> unknownOrganization = new ArrayList<MavenProject>();
787 
788         for ( MavenProject p : projects )
789         {
790             if ( p.getOrganization() != null && StringUtils.isNotEmpty( p.getOrganization().getName() ) )
791             {
792                 List<MavenProject> sortedProjects = (List<MavenProject>) organizations.get( p.getOrganization() );
793                 if ( sortedProjects == null )
794                 {
795                     sortedProjects = new ArrayList<MavenProject>();
796                 }
797                 sortedProjects.add( p );
798 
799                 organizations.put( p.getOrganization(), sortedProjects );
800             }
801             else
802             {
803                 unknownOrganization.add( p );
804             }
805         }
806         if ( !unknownOrganization.isEmpty() )
807         {
808             Organization unknownOrg = new Organization();
809             unknownOrg.setName( "an unknown organization" );
810             organizations.put( unknownOrg, unknownOrganization );
811         }
812 
813         return organizations;
814     }
815 
816     protected boolean copyResourceIfExists( File file, String relFileName, VelocityContext context )
817         throws IOException, MojoExecutionException
818     {
819         for ( Resource resource : resources )
820         {
821             File resourceDirectory = new File( resource.getDirectory() );
822 
823             if ( !resourceDirectory.exists() )
824             {
825                 continue;
826             }
827 
828             //TODO - really should use the resource includes/excludes and name mapping
829             File source = new File( resourceDirectory, relFileName );
830             File templateSource = new File( resourceDirectory, relFileName + TEMPLATE_SUFFIX );
831 
832             if ( !source.exists() && templateSource.exists() )
833             {
834                 source = templateSource;
835             }
836 
837             if ( source.exists() && !source.equals( file ) )
838             {
839                 if ( source == templateSource )
840                 {
841                     Reader reader = null;
842                     Writer writer = null;
843                     try
844                     {
845                         if ( encoding != null )
846                         {
847                             reader = new InputStreamReader( new FileInputStream( source ), encoding );
848                             writer = new OutputStreamWriter( new FileOutputStream( file ), encoding );
849                         }
850                         else
851                         {
852                             reader = ReaderFactory.newPlatformReader( source );
853                             writer = WriterFactory.newPlatformWriter( file );
854                         }
855 
856                         velocity.evaluate( context, writer, "", reader );
857                         velocity.evaluate( context, writer, "", reader );
858                     }
859                     catch ( ParseErrorException e )
860                     {
861                         throw new MojoExecutionException( "Error rendering velocity resource.", e );
862                     }
863                     catch ( MethodInvocationException e )
864                     {
865                         throw new MojoExecutionException( "Error rendering velocity resource.", e );
866                     }
867                     catch ( ResourceNotFoundException e )
868                     {
869                         throw new MojoExecutionException( "Error rendering velocity resource.", e );
870                     }
871                     finally
872                     {
873                         IOUtil.close( writer );
874                         IOUtil.close( reader );
875                     }
876                 }
877                 else if ( resource.isFiltering() )
878                 {
879 
880                     MavenFileFilterRequest req = setupRequest( resource, source, file );
881 
882                     try
883                     {
884                         fileFilter.copyFile( req );
885                     }
886                     catch ( MavenFilteringException e )
887                     {
888                         throw new MojoExecutionException( "Error filtering resource: " + source, e );
889                     }
890                 }
891                 else
892                 {
893                     FileUtils.copyFile( source, file );
894                 }
895 
896                 //exclude the original (so eclipse doesn't complain about duplicate resources)
897                 resource.addExclude( relFileName );
898 
899                 return true;
900             }
901 
902         }
903         return false;
904     }
905 
906     private MavenFileFilterRequest setupRequest( Resource resource, File source, File file )
907     {
908         MavenFileFilterRequest req = new MavenFileFilterRequest();
909         req.setFrom( source );
910         req.setTo( file );
911         req.setFiltering( resource.isFiltering() );
912 
913         req.setMavenProject( project );
914         req.setMavenSession( mavenSession );
915         req.setInjectProjectBuildFilters( true );
916 
917         if ( encoding != null )
918         {
919             req.setEncoding( encoding );
920         }
921 
922         if ( filterDelimiters != null && !filterDelimiters.isEmpty() )
923         {
924             LinkedHashSet<String> delims = new LinkedHashSet<String>();
925             if ( useDefaultFilterDelimiters )
926             {
927                 delims.addAll( req.getDelimiters() );
928             }
929 
930             for ( String delim : filterDelimiters )
931             {
932                 if ( delim == null )
933                 {
934                     delims.add( "${*}" );
935                 }
936                 else
937                 {
938                     delims.add( delim );
939                 }
940             }
941 
942             req.setDelimiters( delims );
943         }
944 
945         return req;
946     }
947 
948     protected void validate()
949         throws MojoExecutionException
950     {
951         int bundleCount = 1;
952 
953         for ( String artifactDescriptor : resourceBundles )
954         {
955             // groupId:artifactId:version, groupId:artifactId:version:type
956             // or groupId:artifactId:version:type:classifier
957             String[] s = StringUtils.split( artifactDescriptor, ":" );
958 
959             if ( s.length < 3 || s.length > 5 )
960             {
961                 String position;
962 
963                 if ( bundleCount == 1 )
964                 {
965                     position = "1st";
966                 }
967                 else if ( bundleCount == 2 )
968                 {
969                     position = "2nd";
970                 }
971                 else if ( bundleCount == 3 )
972                 {
973                     position = "3rd";
974                 }
975                 else
976                 {
977                     position = bundleCount + "th";
978                 }
979 
980                 throw new MojoExecutionException( "The " + position +
981                                                       " resource bundle configured must specify a groupId, artifactId, " +
982                                                       " version and, optionally, type and classifier for a remote resource bundle. " +
983                                                       "Must be of the form <resourceBundle>groupId:artifactId:version</resourceBundle>, " +
984                                                       "<resourceBundle>groupId:artifactId:version:type</resourceBundle> or " +
985                                                       "<resourceBundle>groupId:artifactId:version:type:classifier</resourceBundle>" );
986             }
987 
988             bundleCount++;
989         }
990 
991     }
992 
993     protected void configureVelocityContext( VelocityContext context )
994         throws MojoExecutionException
995     {
996         String inceptionYear = project.getInceptionYear();
997         String year = new SimpleDateFormat( "yyyy" ).format( new Date() );
998 
999         if ( StringUtils.isEmpty( inceptionYear ) )
1000         {
1001             if ( getLog().isDebugEnabled() )
1002             {
1003                 getLog().debug( "inceptionYear not specified, defaulting to " + year );
1004             }
1005 
1006             inceptionYear = year;
1007         }
1008         context.put( "project", project );
1009         List<MavenProject> projects = getProjects();
1010         context.put( "projects", projects );
1011         context.put( "projectsSortedByOrganization", getProjectsSortedByOrganization( projects ) );
1012         context.put( "presentYear", year );
1013         context.put( "locator", locator);
1014 
1015         if ( inceptionYear.equals( year ) )
1016         {
1017             context.put( "projectTimespan", year );
1018         }
1019         else
1020         {
1021             context.put( "projectTimespan", inceptionYear + "-" + year );
1022         }
1023     }
1024 
1025     private List<File> downloadBundles( List<String> bundles )
1026         throws MojoExecutionException
1027     {
1028         List<File> bundleArtifacts = new ArrayList<File>();
1029 
1030         try
1031         {
1032             for ( String artifactDescriptor : bundles )
1033             {
1034                 // groupId:artifactId:version[:type[:classifier]]
1035                 String[] s = artifactDescriptor.split( ":" );
1036 
1037                 File artifactFile = null;
1038                 //check if the artifact is part of the reactor
1039                 if ( mavenSession != null )
1040                 {
1041                     List<MavenProject> list = mavenSession.getSortedProjects();
1042                     for ( MavenProject p : list )
1043                     {
1044                         if ( s[0].equals( p.getGroupId() ) && s[1].equals( p.getArtifactId() ) &&
1045                             s[2].equals( p.getVersion() ) )
1046                         {
1047                             if ( s.length >= 4 && "test-jar".equals( s[3] ) ) 
1048                             {
1049                                 artifactFile = new File( p.getBuild().getTestOutputDirectory() );
1050                             } 
1051                             else 
1052                             {
1053                                 artifactFile = new File( p.getBuild().getOutputDirectory() );
1054                             }
1055                         }
1056                     }
1057                 }
1058                 if ( artifactFile == null || !artifactFile.exists() )
1059                 {
1060                     String type = ( s.length >= 4 ? s[3] : "jar" );
1061                     String classifier = ( s.length == 5 ? s[4] : null );
1062                     Artifact artifact =
1063                         artifactFactory.createDependencyArtifact( s[0], s[1], VersionRange.createFromVersion( s[2] ),
1064                                                                   type, classifier, Artifact.SCOPE_RUNTIME );
1065 
1066                     artifactResolver.resolve( artifact, remoteArtifactRepositories, localRepository );
1067 
1068                     artifactFile = artifact.getFile();
1069                 }
1070                 bundleArtifacts.add( artifactFile );
1071             }
1072         }
1073         catch ( ArtifactResolutionException e )
1074         {
1075             throw new MojoExecutionException( "Error downloading resources archive.", e );
1076         }
1077         catch ( ArtifactNotFoundException e )
1078         {
1079             throw new MojoExecutionException( "Resources archive cannot be found.", e );
1080         }
1081 
1082         return bundleArtifacts;
1083     }
1084 
1085     private void initalizeClassloader( RemoteResourcesClassLoader cl, List<File> artifacts )
1086         throws MojoExecutionException
1087     {
1088         try
1089         {
1090             for ( File artifact : artifacts )
1091             {
1092                 cl.addURL( artifact.toURI().toURL() );
1093             }
1094         }
1095         catch ( MalformedURLException e )
1096         {
1097             throw new MojoExecutionException( "Unable to configure resources classloader: " + e.getMessage(), e );
1098         }
1099     }
1100 
1101     protected void processResourceBundles( RemoteResourcesClassLoader classLoader, VelocityContext context )
1102         throws MojoExecutionException
1103     {
1104         InputStreamReader reader = null;
1105 
1106         try
1107         {
1108 
1109             for ( Enumeration<URL> e = classLoader.getResources( BundleRemoteResourcesMojo.RESOURCES_MANIFEST );
1110                   e.hasMoreElements(); )
1111             {
1112                 URL url = e.nextElement();
1113 
1114                 try
1115                 {
1116                     reader = new InputStreamReader( url.openStream() );
1117 
1118                     RemoteResourcesBundleXpp3Reader bundleReader = new RemoteResourcesBundleXpp3Reader();
1119 
1120                     RemoteResourcesBundle bundle = bundleReader.read( reader );
1121 
1122                     for ( String bundleResource : bundle.getRemoteResources() )
1123                     {
1124                         String projectResource = bundleResource;
1125 
1126                         boolean doVelocity = false;
1127                         if ( projectResource.endsWith( TEMPLATE_SUFFIX ) )
1128                         {
1129                             projectResource = projectResource.substring( 0, projectResource.length() - 3 );
1130                             doVelocity = true;
1131                         }
1132 
1133                         // Don't overwrite resource that are already being provided.
1134 
1135                         File f = new File( outputDirectory, projectResource );
1136 
1137                         FileUtils.mkdir( f.getParentFile().getAbsolutePath() );
1138 
1139                         if ( !copyResourceIfExists( f, projectResource, context ) )
1140                         {
1141                             if ( doVelocity )
1142                             {
1143                                 PrintWriter writer;
1144                                 if ( bundle.getSourceEncoding() == null )
1145                                 {
1146                                     writer = new PrintWriter( new FileWriter( f ) );
1147                                 }
1148                                 else
1149                                 {
1150                                     writer = new PrintWriter( new OutputStreamWriter( new FileOutputStream( f ),
1151                                                                                       bundle.getSourceEncoding() ) );
1152 
1153                                 }
1154 
1155                                 try
1156                                 {
1157                                     if ( bundle.getSourceEncoding() == null )
1158                                     {
1159                                         velocity.mergeTemplate( bundleResource, "ISO-8859-1",
1160                                                                             context, writer );
1161                                     }
1162                                     else
1163                                     {
1164                                         velocity.mergeTemplate( bundleResource, bundle.getSourceEncoding(),
1165                                                                             context, writer );
1166 
1167                                     }
1168                                 }
1169                                 finally
1170                                 {
1171                                     IOUtil.close( writer );
1172                                 }
1173                             }
1174                             else
1175                             {
1176                                 URL resUrl = classLoader.getResource( bundleResource );
1177                                 if ( resUrl != null )
1178                                 {
1179                                     FileUtils.copyURLToFile( resUrl, f );
1180                                 }
1181                             }
1182                             File appendedResourceFile = new File( appendedResourcesDirectory, projectResource );
1183                             File appendedVmResourceFile =
1184                                 new File( appendedResourcesDirectory, projectResource + ".vm" );
1185                             if ( appendedResourceFile.exists() )
1186                             {
1187                                 final InputStream in = new FileInputStream( appendedResourceFile );
1188                                 final OutputStream append = new FileOutputStream( f, true );
1189 
1190                                 try
1191                                 {
1192                                     IOUtil.copy( in, append );
1193                                 }
1194                                 finally
1195                                 {
1196                                     IOUtil.close( in );
1197                                     IOUtil.close( append );
1198                                 }
1199                             }
1200                             else if ( appendedVmResourceFile.exists() )
1201                             {
1202                                 PrintWriter writer;
1203                                 FileReader freader = new FileReader( appendedVmResourceFile );
1204 
1205                                 if ( bundle.getSourceEncoding() == null )
1206                                 {
1207                                     writer = new PrintWriter( new FileWriter( f, true ) );
1208                                 }
1209                                 else
1210                                 {
1211                                     writer = new PrintWriter( new OutputStreamWriter( new FileOutputStream( f, true ),
1212                                                                                       bundle.getSourceEncoding() ) );
1213                                 }
1214 
1215                                 try
1216                                 {
1217                                     Velocity.init();
1218                                     Velocity.evaluate( context, writer, "remote-resources", freader );
1219                                 }
1220                                 finally
1221                                 {
1222                                     IOUtil.close( writer );
1223                                     IOUtil.close( freader );
1224                                 }
1225                             }
1226 
1227                         }
1228                     }
1229                 }
1230                 finally
1231                 {
1232                     reader.close();
1233                 }
1234             }
1235         }
1236         catch ( IOException e )
1237         {
1238             throw new MojoExecutionException( "Error finding remote resources manifests", e );
1239         }
1240         catch ( XmlPullParserException e )
1241         {
1242             throw new MojoExecutionException( "Error parsing remote resource bundle descriptor.", e );
1243         }
1244         catch ( Exception e )
1245         {
1246             throw new MojoExecutionException( "Error rendering velocity resource.", e );
1247         }
1248     }
1249 
1250     protected Model getSupplement( Xpp3Dom supplementModelXml )
1251         throws MojoExecutionException
1252     {
1253         MavenXpp3Reader modelReader = new MavenXpp3Reader();
1254         Model model = null;
1255 
1256         try
1257         {
1258             model = modelReader.read( new StringReader( supplementModelXml.toString() ) );
1259             String groupId = model.getGroupId();
1260             String artifactId = model.getArtifactId();
1261 
1262             if ( groupId == null || groupId.trim().equals( "" ) )
1263             {
1264                 throw new MojoExecutionException(
1265                     "Supplemental project XML " + "requires that a <groupId> element be present." );
1266             }
1267 
1268             if ( artifactId == null || artifactId.trim().equals( "" ) )
1269             {
1270                 throw new MojoExecutionException(
1271                     "Supplemental project XML " + "requires that a <artifactId> element be present." );
1272             }
1273         }
1274         catch ( IOException e )
1275         {
1276             getLog().warn( "Unable to read supplemental XML: " + e.getMessage(), e );
1277         }
1278         catch ( XmlPullParserException e )
1279         {
1280             getLog().warn( "Unable to parse supplemental XML: " + e.getMessage(), e );
1281         }
1282 
1283         return model;
1284     }
1285 
1286     protected Model mergeModels( Model parent, Model child )
1287     {
1288         inheritanceAssembler.assembleModelInheritance( child, parent );
1289         return child;
1290     }
1291 
1292     private static String generateSupplementMapKey( String groupId, String artifactId )
1293     {
1294         return groupId.trim() + ":" + artifactId.trim();
1295     }
1296 
1297     private Map<String, Model> loadSupplements( String models[] )
1298         throws MojoExecutionException
1299     {
1300         if ( models == null )
1301         {
1302             getLog().debug( "Supplemental data models won't be loaded.  " + "No models specified." );
1303             return Collections.emptyMap();
1304         }
1305 
1306         List<Supplement> supplements = new ArrayList<Supplement>();
1307         for ( int idx = 0; idx < models.length; idx++ )
1308         {
1309             String set = models[idx];
1310             getLog().debug( "Preparing ruleset: " + set );
1311             try
1312             {
1313                 File f = locator.getResourceAsFile( set, getLocationTemp( set ) );
1314 
1315                 if ( null == f || !f.exists() )
1316                 {
1317                     throw new MojoExecutionException( "Cold not resolve " + set );
1318                 }
1319                 if ( !f.canRead() )
1320                 {
1321                     throw new MojoExecutionException( "Supplemental data models won't be loaded. " + "File " +
1322                                                           f.getAbsolutePath() +
1323                                                           " cannot be read, check permissions on the file." );
1324                 }
1325 
1326                 getLog().debug( "Loading supplemental models from " + f.getAbsolutePath() );
1327 
1328                 SupplementalDataModelXpp3Reader reader = new SupplementalDataModelXpp3Reader();
1329                 SupplementalDataModel supplementalModel = reader.read( new FileReader( f ) );
1330                 supplements.addAll( supplementalModel.getSupplement() );
1331             }
1332             catch ( Exception e )
1333             {
1334                 String msg = "Error loading supplemental data models: " + e.getMessage();
1335                 getLog().error( msg, e );
1336                 throw new MojoExecutionException( msg, e );
1337             }
1338         }
1339 
1340         getLog().debug( "Loading supplements complete." );
1341 
1342         Map<String, Model> supplementMap = new HashMap<String, Model>();
1343         for ( Supplement sd : supplements )
1344         {
1345             Xpp3Dom dom = (Xpp3Dom) sd.getProject();
1346 
1347             Model m = getSupplement( dom );
1348             supplementMap.put( generateSupplementMapKey( m.getGroupId(), m.getArtifactId() ), m );
1349         }
1350 
1351         return supplementMap;
1352     }
1353 
1354     /**
1355      * Convenience method to get the location of the specified file name.
1356      *
1357      * @param name the name of the file whose location is to be resolved
1358      * @return a String that contains the absolute file name of the file
1359      */
1360     private String getLocationTemp( String name )
1361     {
1362         String loc = name;
1363         if ( loc.indexOf( '/' ) != -1 )
1364         {
1365             loc = loc.substring( loc.lastIndexOf( '/' ) + 1 );
1366         }
1367         if ( loc.indexOf( '\\' ) != -1 )
1368         {
1369             loc = loc.substring( loc.lastIndexOf( '\\' ) + 1 );
1370         }
1371         getLog().debug( "Before: " + name + " After: " + loc );
1372         return loc;
1373     }
1374 
1375     class OrganizationComparator
1376         implements Comparator<Organization>
1377     {
1378         public int compare( Organization org1, Organization org2 )
1379         {
1380             int i = compareStrings( org1.getName(), org2.getName() );
1381             if ( i == 0 )
1382             {
1383                 i = compareStrings( org1.getUrl(), org2.getUrl() );
1384             }
1385             return i;
1386         }
1387 
1388         public boolean equals( Organization o1, Organization o2 )
1389         {
1390             return compare( o1, o2 ) == 0;
1391         }
1392 
1393         private int compareStrings( String s1, String s2 )
1394         {
1395             if ( s1 == null && s2 == null )
1396             {
1397                 return 0;
1398             }
1399             else if ( s1 == null && s2 != null )
1400             {
1401                 return 1;
1402             }
1403             else if ( s1 != null && s2 == null )
1404             {
1405                 return -1;
1406             }
1407 
1408             return s1.compareToIgnoreCase( s2 );
1409         }
1410     }
1411 
1412     class ProjectComparator
1413         implements Comparator<MavenProject>
1414     {
1415         public int compare( MavenProject p1, MavenProject p2 )
1416         {
1417             return p1.getArtifact().compareTo( p2.getArtifact() );
1418         }
1419 
1420         public boolean equals( MavenProject p1, MavenProject p2 )
1421         {
1422             return p1.getArtifact().equals( p2.getArtifact() );
1423         }
1424     }
1425 
1426     /* LogChute methods */
1427     public void init( RuntimeServices rs )
1428         throws Exception
1429     {
1430     }
1431 
1432     public void log( int level, String message )
1433     {
1434         switch ( level )
1435         {
1436             case LogChute.WARN_ID:
1437                 getLog().warn( message );
1438                 break;
1439             case LogChute.INFO_ID:
1440                 // velocity info messages are too verbose, just consider them as debug messages...
1441                 getLog().debug( message );
1442                 break;
1443             case LogChute.DEBUG_ID:
1444                 getLog().debug( message );
1445                 break;
1446             case LogChute.ERROR_ID:
1447                 getLog().error( message );
1448                 break;
1449             default:
1450                 getLog().debug( message );
1451                 break;
1452         }       
1453     }
1454 
1455     public void log( int level, String message, Throwable t )
1456     {
1457         switch ( level )
1458         {
1459             case LogChute.WARN_ID:
1460                 getLog().warn( message, t );
1461                 break;
1462             case LogChute.INFO_ID:
1463                 // velocity info messages are too verbose, just consider them as debug messages...
1464                 getLog().debug( message, t );
1465                 break;
1466             case LogChute.DEBUG_ID:
1467                 getLog().debug( message, t );
1468                 break;
1469             case LogChute.ERROR_ID:
1470                 getLog().error( message, t );
1471                 break;
1472             default:
1473                 getLog().debug( message, t );
1474                 break;
1475         }        
1476     }
1477 
1478     public boolean isLevelEnabled( int level )
1479     {
1480         return false;
1481     }
1482 
1483 }