> Author: bentmann
> Date: Tue Jun 30 22:36:30 2009
> New Revision: 789993
>
> URL:
http://svn.apache.org/viewvc?rev=789993&view=rev> Log:
> [MNG-4224] maven lifecycle participant
> Submitted by: Igor Fedorenko
>
> Added:
> maven/components/trunk/maven-core/src/main/java/org/apache/maven/AbstractMavenLifecycleParticipant.java (with props)
> maven/components/trunk/maven-core/src/test/java/org/apache/maven/MavenLifecycleParticipantTest.java (with props)
> maven/components/trunk/maven-core/src/test/projects/lifecycle-listener/ (with props)
> maven/components/trunk/maven-core/src/test/projects/lifecycle-listener/lifecycle-listener-dependency-injection/ (with props)
> maven/components/trunk/maven-core/src/test/projects/lifecycle-listener/lifecycle-listener-dependency-injection/pom.xml (with props)
> Modified:
> maven/components/trunk/maven-core/src/main/java/org/apache/maven/DefaultMaven.java
> maven/components/trunk/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java
> maven/components/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycleExecutor.java
> maven/components/trunk/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginManager.java
> maven/components/trunk/maven-core/src/main/java/org/apache/maven/project/MavenProject.java
> maven/components/trunk/maven-core/src/test/java/org/apache/maven/MavenTest.java
>
> Added: maven/components/trunk/maven-core/src/main/java/org/apache/maven/AbstractMavenLifecycleParticipant.java
> URL:
http://svn.apache.org/viewvc/maven/components/trunk/maven-core/src/main/java/org/apache/maven/AbstractMavenLifecycleParticipant.java?rev=789993&view=auto> ==============================================================================
> --- maven/components/trunk/maven-core/src/main/java/org/apache/maven/AbstractMavenLifecycleParticipant.java (added)
> +++ maven/components/trunk/maven-core/src/main/java/org/apache/maven/AbstractMavenLifecycleParticipant.java Tue Jun 30 22:36:30 2009
> @@ -0,0 +1,54 @@
> +package org.apache.maven;
> +
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
> + * agreements. See the NOTICE file distributed with this work for additional information regarding
> + * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
> + * "License"); you may not use this file except in compliance with the License. You may obtain a
> + * copy of the License at
> + *
> + *
http://www.apache.org/licenses/LICENSE-2.0> + *
> + * Unless required by applicable law or agreed to in writing, software distributed under the License
> + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
> + * or implied. See the License for the specific language governing permissions and limitations under
> + * the License.
> + */
> +
> +
> +import org.apache.maven.execution.MavenSession;
> +
> +/**
> + * Allows core extensions to participate in build lifecycle.
> + *
> + * All callback methods (will) follow beforeXXX/afterXXX naming pattern to
> + * indicate at what lifecycle point it is being called.
> + *
> + */
> +public abstract class AbstractMavenLifecycleParticipant
> +{
> +
> + /**
> + * Invoked after all MavenProject instances have been created.
> + *
> + * This callback is intended to allow extensions to manipulate MavenProjects
> + * before they are sorted and actual build execution starts.
> + */
> + public void afterProjectsRead( MavenSession session ) throws MavenExecutionException
> + {
> + // do nothing
> + }
> +
> + /**
> + * Invoked after MavenSession instance has been created.
> + *
> + * This callback is intended to allow extensions to inject execution properties,
> + * activate profiles and perform similar tasks that affect MavenProject
> + * instance construction.
> + */
> + public void afterSessionStart( MavenSession session ) throws MavenExecutionException
> + {
> + // do nothing
> + }
> +
> +}
>
> Propchange: maven/components/trunk/maven-core/src/main/java/org/apache/maven/AbstractMavenLifecycleParticipant.java
> ------------------------------------------------------------------------------
> svn:eol-style = native
>
> Propchange: maven/components/trunk/maven-core/src/main/java/org/apache/maven/AbstractMavenLifecycleParticipant.java
> ------------------------------------------------------------------------------
> svn:keywords = Author Date Id Revision
>
> Modified: maven/components/trunk/maven-core/src/main/java/org/apache/maven/DefaultMaven.java
> URL:
http://svn.apache.org/viewvc/maven/components/trunk/maven-core/src/main/java/org/apache/maven/DefaultMaven.java?rev=789993&r1=789992&r2=789993&view=diff> ==============================================================================
> --- maven/components/trunk/maven-core/src/main/java/org/apache/maven/DefaultMaven.java (original)
> +++ maven/components/trunk/maven-core/src/main/java/org/apache/maven/DefaultMaven.java Tue Jun 30 22:36:30 2009
> @@ -22,7 +22,6 @@
> import java.util.Arrays;
> import java.util.Collection;
> import java.util.Date;
> -import java.util.HashMap;
> import java.util.LinkedHashMap;
> import java.util.LinkedHashSet;
> import java.util.List;
> @@ -46,6 +45,7 @@
> import org.codehaus.plexus.PlexusContainer;
> import org.codehaus.plexus.component.annotations.Component;
> import org.codehaus.plexus.component.annotations.Requirement;
> +import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
> import org.codehaus.plexus.logging.Logger;
> import org.codehaus.plexus.util.Os;
> import org.codehaus.plexus.util.StringUtils;
> @@ -86,13 +86,24 @@
> DelegatingLocalArtifactRepository delegatingLocalArtifactRepository = new DelegatingLocalArtifactRepository( request.getLocalRepository() );
>
> request.setLocalRepository( delegatingLocalArtifactRepository );
> -
> - MavenSession session;
> +
> + MavenSession session = new MavenSession( container, request, result);
>
> - Map<String,MavenProject> projects;
> + try
> + {
> + for ( AbstractMavenLifecycleParticipant listener : getLifecycleParticipants() )
> + {
> + listener.afterSessionStart( session );
> + }
> + }
> + catch ( MavenExecutionException e )
> + {
> + return processResult( result, e );
> + }
>
> //TODO: optimize for the single project or no project
>
> + List<MavenProject> projects;
> try
> {
> projects = getProjectsForMavenReactor( request );
> @@ -101,7 +112,7 @@
> if ( projects.isEmpty() )
> {
> MavenProject project = projectBuilder.buildStandaloneSuperProject( request.getProjectBuildingRequest() );
> - projects.put( ArtifactUtils.key( project.getGroupId(), project.getArtifactId(), project.getVersion() ), project );
> + projects.add( project );
> request.setProjectPresent( false );
> }
> }
> @@ -113,12 +124,28 @@
> {
> return processResult( result, e );
> }
> -
> +
> + session.setProjects( projects );
> +
> + try
> + {
> + for ( AbstractMavenLifecycleParticipant listener : getLifecycleParticipants() )
> + {
> + listener.afterProjectsRead( session );
> + }
> + }
> + catch ( MavenExecutionException e )
> + {
> + return processResult( result, e );
> + }
> +
> try
> {
> - ProjectSorter projectSorter = new ProjectSorter( projects.values() );
> -
> - session = new MavenSession( container, request, result, projectSorter.getSortedProjects() );
> + ProjectSorter projectSorter = new ProjectSorter( session.getProjects() );
> +
> + projects = projectSorter.getSortedProjects();
> +
> + session.setProjects( projects );
> }
> catch ( CycleDetectedException e )
> {
> @@ -132,14 +159,20 @@
> {
> return processResult( result, e );
> }
> -
> +
> // Desired order of precedence for local artifact repositories
> //
> // Reactor
> // Workspace
> // User Local Repository
> -
> - delegatingLocalArtifactRepository.setBuildReactor( new ReactorArtifactRepository( projects ) );
> + try
> + {
> + delegatingLocalArtifactRepository.setBuildReactor( new ReactorArtifactRepository( getProjectMap( session.getProjects() ) ) );
> + }
> + catch ( MavenExecutionException e )
> + {
> + return processResult( result, e );
> + }
>
> if ( result.hasExceptions() )
> {
> @@ -162,6 +195,22 @@
> return result;
> }
>
> + private List<AbstractMavenLifecycleParticipant> getLifecycleParticipants()
> + {
> + // TODO injection of component lists does not work
> + List<AbstractMavenLifecycleParticipant> lifecycleListeners;
> + try
> + {
> + lifecycleListeners = container.lookupList( AbstractMavenLifecycleParticipant.class );
> + }
> + catch ( ComponentLookupException e1 )
> + {
> + // this is just silly, lookupList should return an empty list!
> + lifecycleListeners = new ArrayList<AbstractMavenLifecycleParticipant>();
> + }
> + return lifecycleListeners;
> + }
> +
> private MavenExecutionResult processResult( MavenExecutionResult result, Exception e )
> {
> ExceptionHandler handler = new DefaultExceptionHandler();
> @@ -175,14 +224,14 @@
> return result;
> }
>
> - protected Map<String,MavenProject> getProjectsForMavenReactor( MavenExecutionRequest request )
> + private List<MavenProject> getProjectsForMavenReactor( MavenExecutionRequest request )
> throws MavenExecutionException, ProjectBuildingException
> {
> // We have no POM file.
> //
> if ( request.getPom() == null || !request.getPom().exists() )
> {
> - return new HashMap<String,MavenProject>();
> + return new ArrayList<MavenProject>();
> }
>
> List<File> files = Arrays.asList( request.getPom().getAbsoluteFile() );
> @@ -191,6 +240,12 @@
>
> collectProjects( projects, files, request );
>
> + return projects;
> + }
> +
> + private Map<String, MavenProject> getProjectMap( List<MavenProject> projects )
> + throws org.apache.maven.DuplicateProjectException
> + {
> Map<String, MavenProject> index = new LinkedHashMap<String, MavenProject>();
> Map<String, List<File>> collisions = new LinkedHashMap<String, List<File>>();
>
>
> Modified: maven/components/trunk/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java
> URL:
http://svn.apache.org/viewvc/maven/components/trunk/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java?rev=789993&r1=789992&r2=789993&view=diff> ==============================================================================
> --- maven/components/trunk/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java (original)
> +++ maven/components/trunk/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java Tue Jun 30 22:36:30 2009
> @@ -31,7 +31,6 @@
> import org.apache.maven.project.ProjectBuildingRequest;
> import org.apache.maven.settings.Settings;
> import org.codehaus.plexus.PlexusContainer;
> -import org.codehaus.plexus.util.dag.CycleDetectedException;
>
> /**
> * @author Jason van Zyl
> @@ -55,25 +54,37 @@
>
> private MavenProject topLevelProject;
>
> + @Deprecated
> public MavenSession( PlexusContainer container, MavenExecutionRequest request, MavenExecutionResult result, MavenProject project )
> - throws CycleDetectedException, DuplicateProjectException
> {
> this( container, request, result, Arrays.asList( new MavenProject[]{ project } ) );
> }
>
> + @Deprecated
> public MavenSession( PlexusContainer container, MavenExecutionRequest request, MavenExecutionResult result, List<MavenProject> projects )
> - throws CycleDetectedException, DuplicateProjectException
> {
> this.container = container;
> this.request = request;
> this.result = result;
> + setProjects( projects );
> + }
> +
> + public MavenSession( PlexusContainer container, MavenExecutionRequest request, MavenExecutionResult result )
> + {
> + this.container = container;
> + this.request = request;
> + this.result = result;
> + }
> +
> + public void setProjects( List<MavenProject> projects )
> + {
> //TODO: Current for testing classes creating the session
> if ( projects.size() > 0 )
> {
> this.currentProject = projects.get( 0 );
> this.topLevelProject = projects.get( 0 );
> }
> - this.projects = projects;
> + this.projects = projects;
> }
>
> @Deprecated
>
> Modified: maven/components/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycleExecutor.java
> URL:
http://svn.apache.org/viewvc/maven/components/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycleExecutor.java?rev=789993&r1=789992&r2=789993&view=diff> ==============================================================================
> --- maven/components/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycleExecutor.java (original)
> +++ maven/components/trunk/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycleExecutor.java Tue Jun 30 22:36:30 2009
> @@ -806,7 +806,10 @@
> {
> String phase = goalsForLifecyclePhase.getKey();
> String goals = goalsForLifecyclePhase.getValue();
> - parseLifecyclePhaseDefinitions( plugins, phase, goals );
> + if ( goals != null )
> + {
> + parseLifecyclePhaseDefinitions( plugins, phase, goals );
> + }
> }
> }
> else if ( lifecycle.getDefaultPhases() != null )
>
> Modified: maven/components/trunk/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginManager.java
> URL:
http://svn.apache.org/viewvc/maven/components/trunk/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginManager.java?rev=789993&r1=789992&r2=789993&view=diff> ==============================================================================
> --- maven/components/trunk/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginManager.java (original)
> +++ maven/components/trunk/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginManager.java Tue Jun 30 22:36:30 2009
> @@ -222,7 +222,7 @@
> }
> }
>
> - private PluginDescriptor parsebuildPluginDescriptor( InputStream is )
> + public PluginDescriptor parsebuildPluginDescriptor( InputStream is )
> throws IOException, PlexusConfigurationException
> {
> PluginDescriptor pluginDescriptor;
>
> Modified: maven/components/trunk/maven-core/src/main/java/org/apache/maven/project/MavenProject.java
> URL:
http://svn.apache.org/viewvc/maven/components/trunk/maven-core/src/main/java/org/apache/maven/project/MavenProject.java?rev=789993&r1=789992&r2=789993&view=diff> ==============================================================================
> --- maven/components/trunk/maven-core/src/main/java/org/apache/maven/project/MavenProject.java (original)
> +++ maven/components/trunk/maven-core/src/main/java/org/apache/maven/project/MavenProject.java Tue Jun 30 22:36:30 2009
> @@ -164,7 +164,9 @@
> private RepositorySystem repositorySystem;
>
> private File parentFile;
> -
> +
> + private Map<String, Object> context;
> +
> //
>
> public MavenProject()
> @@ -1966,4 +1968,41 @@
> {
> return groupId + ":" + artifactId + ":" + version;
> }
> +
> + /**
> + * Sets the value of the context value of this project identified
> + * by the given key. If the supplied value is <code>null</code>,
> + * the context value is removed from this project.
> + *
> + * Context values are intended to allow core extensions to associate
> + * derived state with project instances.
> + */
> + public void setContextValue( String key, Object value )
> + {
> + if ( context == null )
> + {
> + context = new HashMap<String, Object>();
> + }
> + if ( value != null )
> + {
> + context.put( key, value );
> + }
> + else
> + {
> + context.remove( key );
> + }
> + }
> +
> + /**
> + * Returns context value of this project associated with the given key
> + * or null if this project has no such value.
> + */
> + public Object getContextValue( String key )
> + {
> + if ( context == null )
> + {
> + return null;
> + }
> + return context.get( key );
> + }
> }
>
> Added: maven/components/trunk/maven-core/src/test/java/org/apache/maven/MavenLifecycleParticipantTest.java
> URL:
http://svn.apache.org/viewvc/maven/components/trunk/maven-core/src/test/java/org/apache/maven/MavenLifecycleParticipantTest.java?rev=789993&view=auto> ==============================================================================
> --- maven/components/trunk/maven-core/src/test/java/org/apache/maven/MavenLifecycleParticipantTest.java (added)
> +++ maven/components/trunk/maven-core/src/test/java/org/apache/maven/MavenLifecycleParticipantTest.java Tue Jun 30 22:36:30 2009
> @@ -0,0 +1,111 @@
> +package org.apache.maven;
> +
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
> + * agreements. See the NOTICE file distributed with this work for additional information regarding
> + * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
> + * "License"); you may not use this file except in compliance with the License. You may obtain a
> + * copy of the License at
> + *
> + *
http://www.apache.org/licenses/LICENSE-2.0> + *
> + * Unless required by applicable law or agreed to in writing, software distributed under the License
> + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
> + * or implied. See the License for the specific language governing permissions and limitations under
> + * the License.
> + */
> +
> +
> +import java.io.File;
> +import java.io.IOException;
> +import java.util.ArrayList;
> +
> +import org.apache.maven.artifact.Artifact;
> +import org.apache.maven.execution.MavenExecutionRequest;
> +import org.apache.maven.execution.MavenExecutionResult;
> +import org.apache.maven.execution.MavenSession;
> +import org.apache.maven.model.Dependency;
> +import org.apache.maven.project.MavenProject;
> +import org.codehaus.plexus.PlexusContainer;
> +import org.codehaus.plexus.component.repository.ComponentDescriptor;
> +
> +public class MavenLifecycleParticipantTest
> + extends AbstractCoreMavenComponentTestCase
> +{
> +
> + private static final String INJECTED_ARTIFACT_ID = "injected";
> +
> + public static class InjectDependencyLifecycleListener
> + extends AbstractMavenLifecycleParticipant
> + {
> +
> + @Override
> + public void afterProjectsRead( MavenSession session )
> + {
> + MavenProject project = session.getProjects().get( 0 );
> +
> + Dependency dependency = new Dependency();
> + dependency.setArtifactId( INJECTED_ARTIFACT_ID );
> + dependency.setGroupId( "foo" );
> + dependency.setVersion( "1.2.3" );
> + dependency.setScope( "system" );
> + try
> + {
> + dependency.setSystemPath( new File(
> + "src/test/projects/lifecycle-executor/project-with-additional-lifecycle-elements/pom.xml" ).getCanonicalPath() );
> + }
> + catch ( IOException e )
> + {
> + throw new RuntimeException( e );
> + }
> +
> + project.getModel().addDependency( dependency );
> + }
> +
> + @Override
> + public void afterSessionStart( MavenSession session )
> + {
> + session.getExecutionProperties().setProperty( "injected", "bar" );
> + }
> +
> + }
> +
> + @Override
> + protected void setupContainer()
> + {
> + super.setupContainer();
> + }
> +
> + @Override
> + protected String getProjectsDirectory()
> + {
> + return "src/test/projects/lifecycle-listener";
> + }
> +
> + public void testDependencyInjection()
> + throws Exception
> + {
> + PlexusContainer container = getContainer();
> +
> + ComponentDescriptor cd =
> + new ComponentDescriptor( InjectDependencyLifecycleListener.class, container.getContainerRealm() );
> + cd.setRoleClass( AbstractMavenLifecycleParticipant.class );
> + container.addComponentDescriptor( cd );
> +
> + Maven maven = container.lookup( Maven.class );
> + File pom = getProject( "lifecycle-listener-dependency-injection" );
> + MavenExecutionRequest request = createMavenExecutionRequest( pom );
> + MavenExecutionResult result = maven.execute( request );
> +
> + assertFalse( result.hasExceptions() );
> +
> + MavenProject project = result.getProject();
> +
> + assertEquals( "bar", project.getProperties().getProperty( "foo" ) );
> +
> + ArrayList<Artifact> artifacts = new ArrayList<Artifact>( project.getArtifacts() );
> +
> + assertEquals( 1, artifacts.size() );
> + assertEquals( INJECTED_ARTIFACT_ID, artifacts.get( 0 ).getArtifactId() );
> + }
> +}
>
> Propchange: maven/components/trunk/maven-core/src/test/java/org/apache/maven/MavenLifecycleParticipantTest.java
> ------------------------------------------------------------------------------
> svn:eol-style = native
>
> Propchange: maven/components/trunk/maven-core/src/test/java/org/apache/maven/MavenLifecycleParticipantTest.java
> ------------------------------------------------------------------------------
> svn:keywords = Author Date Id Revision
>
> Modified: maven/components/trunk/maven-core/src/test/java/org/apache/maven/MavenTest.java
> URL:
http://svn.apache.org/viewvc/maven/components/trunk/maven-core/src/test/java/org/apache/maven/MavenTest.java?rev=789993&r1=789992&r2=789993&view=diff> ==============================================================================
> --- maven/components/trunk/maven-core/src/test/java/org/apache/maven/MavenTest.java (original)
> +++ maven/components/trunk/maven-core/src/test/java/org/apache/maven/MavenTest.java Tue Jun 30 22:36:30 2009
> @@ -6,7 +6,6 @@
> import org.apache.maven.exception.ExceptionSummary;
> import org.apache.maven.execution.MavenExecutionRequest;
> import org.apache.maven.execution.MavenExecutionResult;
> -import org.apache.maven.execution.MavenSession;
> import org.codehaus.plexus.component.annotations.Requirement;
>
> public class MavenTest
>
> Propchange: maven/components/trunk/maven-core/src/test/projects/lifecycle-listener/
> ------------------------------------------------------------------------------
> bugtraq:label = Enter issue ID:
>
> Propchange: maven/components/trunk/maven-core/src/test/projects/lifecycle-listener/
> ------------------------------------------------------------------------------
> bugtraq:message = Issue id: %BUGID%
>
> Propchange: maven/components/trunk/maven-core/src/test/projects/lifecycle-listener/
> ------------------------------------------------------------------------------
> bugtraq:number = false
>
> Propchange: maven/components/trunk/maven-core/src/test/projects/lifecycle-listener/
> ------------------------------------------------------------------------------
> bugtraq:url =
http://jira.codehaus.org/browse/%BUGID%>
> Propchange: maven/components/trunk/maven-core/src/test/projects/lifecycle-listener/lifecycle-listener-dependency-injection/
> ------------------------------------------------------------------------------
> bugtraq:label = Enter issue ID:
>
> Propchange: maven/components/trunk/maven-core/src/test/projects/lifecycle-listener/lifecycle-listener-dependency-injection/
> ------------------------------------------------------------------------------
> bugtraq:message = Issue id: %BUGID%
>
> Propchange: maven/components/trunk/maven-core/src/test/projects/lifecycle-listener/lifecycle-listener-dependency-injection/
> ------------------------------------------------------------------------------
> bugtraq:number = false
>
> Propchange: maven/components/trunk/maven-core/src/test/projects/lifecycle-listener/lifecycle-listener-dependency-injection/
> ------------------------------------------------------------------------------
> bugtraq:url =
http://jira.codehaus.org/browse/%BUGID%>
> Added: maven/components/trunk/maven-core/src/test/projects/lifecycle-listener/lifecycle-listener-dependency-injection/pom.xml
> URL:
http://svn.apache.org/viewvc/maven/components/trunk/maven-core/src/test/projects/lifecycle-listener/lifecycle-listener-dependency-injection/pom.xml?rev=789993&view=auto> ==============================================================================
> --- maven/components/trunk/maven-core/src/test/projects/lifecycle-listener/lifecycle-listener-dependency-injection/pom.xml (added)
> +++ maven/components/trunk/maven-core/src/test/projects/lifecycle-listener/lifecycle-listener-dependency-injection/pom.xml Tue Jun 30 22:36:30 2009
> @@ -0,0 +1,12 @@
> +<project>
> + <modelVersion>4.0.0</modelVersion>
> +
> + <groupId>org.apache.maven.lifecycle-listener.test</groupId>
> + <artifactId>simple</artifactId>
> + <version>1.0</version>
> +
> + <properties>
> + <foo>${injected}</foo>
> + </properties>
> +
> +</project>
>
> Propchange: maven/components/trunk/maven-core/src/test/projects/lifecycle-listener/lifecycle-listener-dependency-injection/pom.xml
> ------------------------------------------------------------------------------
> svn:eol-style = native
>
> Propchange: maven/components/trunk/maven-core/src/test/projects/lifecycle-listener/lifecycle-listener-dependency-injection/pom.xml
> ------------------------------------------------------------------------------
> svn:keywords = Author Date Id Revision
>
>
>