You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@continuum.apache.org by ev...@apache.org on 2008/07/08 07:17:36 UTC

svn commit: r674722 [1/2] - in /continuum/trunk: ./ continuum-base/continuum-scm/src/main/java/org/apache/continuum/scm/manager/spring/ continuum-core/ continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m1/ continuum-core/src/main/...

Author: evenisse
Date: Mon Jul  7 22:17:34 2008
New Revision: 674722

URL: http://svn.apache.org/viewvc?rev=674722&view=rev
Log:
Remove plexus-notification

Added:
    continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/
    continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/DefaultNotifierManager.java   (with props)
    continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/NotifierManager.java   (with props)
    continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/spring/
    continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/spring/NotifierFactoryBean.java   (with props)
    continuum/trunk/continuum-notifiers/continuum-notifier-api/src/main/java/org/apache/maven/continuum/notification/MessageContext.java   (with props)
    continuum/trunk/continuum-notifiers/continuum-notifier-api/src/main/java/org/apache/maven/continuum/notification/NotificationException.java   (with props)
    continuum/trunk/continuum-notifiers/continuum-notifier-api/src/main/java/org/apache/maven/continuum/notification/Notifier.java   (with props)
Removed:
    continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/ContinuumRecipientSource.java
Modified:
    continuum/trunk/continuum-base/continuum-scm/src/main/java/org/apache/continuum/scm/manager/spring/ScmProviderFactoryBean.java
    continuum/trunk/continuum-core/pom.xml
    continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m1/DefaultMavenOneMetadataHelper.java
    continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/DefaultContinuumNotificationDispatcher.java
    continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/console/ConsoleNotifier.java
    continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/mail/MailContinuumNotifier.java
    continuum/trunk/continuum-core/src/main/resources/META-INF/spring-context.xml
    continuum/trunk/continuum-core/src/test/java/org/apache/maven/continuum/notification/mail/MailContinuumNotifierTest.java
    continuum/trunk/continuum-core/src/test/resources/org/apache/maven/continuum/buildcontroller/DefaultBuildControllerTest.xml
    continuum/trunk/continuum-core/src/test/resources/org/apache/maven/continuum/notification/ContinuumNotificationDispatcherTest.xml
    continuum/trunk/continuum-core/src/test/resources/org/apache/maven/continuum/notification/mail/MailContinuumNotifierTest.xml
    continuum/trunk/continuum-notifiers/continuum-notifier-api/pom.xml
    continuum/trunk/continuum-notifiers/continuum-notifier-api/src/main/java/org/apache/maven/continuum/notification/AbstractContinuumNotifier.java
    continuum/trunk/continuum-notifiers/continuum-notifier-irc/src/main/java/org/apache/maven/continuum/notification/irc/IrcContinuumNotifier.java
    continuum/trunk/continuum-notifiers/continuum-notifier-jabber/src/main/java/org/apache/maven/continuum/notification/jabber/JabberContinuumNotifier.java
    continuum/trunk/continuum-notifiers/continuum-notifier-msn/src/main/java/org/apache/maven/continuum/notification/msn/MsnContinuumNotifier.java
    continuum/trunk/continuum-notifiers/continuum-notifier-wagon/pom.xml
    continuum/trunk/continuum-notifiers/continuum-notifier-wagon/src/main/java/org/apache/maven/continuum/notification/wagon/WagonContinuumNotifier.java
    continuum/trunk/continuum-notifiers/continuum-notifier-wagon/src/test/java/org/apache/maven/continuum/wagon/WagonContinuumNotifierTest.java
    continuum/trunk/continuum-notifiers/continuum-notifier-wagon/src/test/resources/org/apache/maven/continuum/wagon/WagonContinuumNotifierTest.xml
    continuum/trunk/continuum-notifiers/pom.xml
    continuum/trunk/continuum-test/src/main/java/org/apache/maven/continuum/AbstractContinuumTest.java
    continuum/trunk/continuum-test/src/main/java/org/apache/maven/continuum/jdo/MemoryJdoFactory.java
    continuum/trunk/continuum-test/src/main/resources/META-INF/spring-context.xml
    continuum/trunk/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/component/NotifierSummaryAction.java
    continuum/trunk/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/DeleteGroupNotifierAction.java
    continuum/trunk/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/DeleteProjectNotifierAction.java
    continuum/trunk/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/JabberGroupNotifierEditAction.java
    continuum/trunk/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/JabberProjectNotifierEditAction.java
    continuum/trunk/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/MailGroupNotifierEditAction.java
    continuum/trunk/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/MailProjectNotifierEditAction.java
    continuum/trunk/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/MsnGroupNotifierEditAction.java
    continuum/trunk/continuum-webapp/src/main/java/org/apache/maven/continuum/web/action/notifier/MsnProjectNotifierEditAction.java
    continuum/trunk/continuum-webapp/src/main/java/org/apache/maven/continuum/web/view/projectview/NotifierRecipientCell.java
    continuum/trunk/continuum-webapp/src/main/resources/META-INF/plexus/application.xml
    continuum/trunk/pom.xml

Modified: continuum/trunk/continuum-base/continuum-scm/src/main/java/org/apache/continuum/scm/manager/spring/ScmProviderFactoryBean.java
URL: http://svn.apache.org/viewvc/continuum/trunk/continuum-base/continuum-scm/src/main/java/org/apache/continuum/scm/manager/spring/ScmProviderFactoryBean.java?rev=674722&r1=674721&r2=674722&view=diff
==============================================================================
--- continuum/trunk/continuum-base/continuum-scm/src/main/java/org/apache/continuum/scm/manager/spring/ScmProviderFactoryBean.java (original)
+++ continuum/trunk/continuum-base/continuum-scm/src/main/java/org/apache/continuum/scm/manager/spring/ScmProviderFactoryBean.java Mon Jul  7 22:17:34 2008
@@ -1,5 +1,24 @@
 package org.apache.continuum.scm.manager.spring;
 
+/*
+ * 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.util.HashMap;
 import java.util.Map;
 

Modified: continuum/trunk/continuum-core/pom.xml
URL: http://svn.apache.org/viewvc/continuum/trunk/continuum-core/pom.xml?rev=674722&r1=674721&r2=674722&view=diff
==============================================================================
--- continuum/trunk/continuum-core/pom.xml (original)
+++ continuum/trunk/continuum-core/pom.xml Mon Jul  7 22:17:34 2008
@@ -37,10 +37,6 @@
     </dependency>
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
-      <artifactId>plexus-notification</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-utils</artifactId>
     </dependency>
     <dependency>

Modified: continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m1/DefaultMavenOneMetadataHelper.java
URL: http://svn.apache.org/viewvc/continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m1/DefaultMavenOneMetadataHelper.java?rev=674722&r1=674721&r2=674722&view=diff
==============================================================================
--- continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m1/DefaultMavenOneMetadataHelper.java (original)
+++ continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/execution/maven/m1/DefaultMavenOneMetadataHelper.java Mon Jul  7 22:17:34 2008
@@ -23,7 +23,7 @@
 import org.apache.maven.continuum.model.project.ProjectDependency;
 import org.apache.maven.continuum.model.project.ProjectDeveloper;
 import org.apache.maven.continuum.model.project.ProjectNotifier;
-import org.apache.maven.continuum.notification.ContinuumRecipientSource;
+import org.apache.maven.continuum.notification.AbstractContinuumNotifier;
 import org.apache.maven.continuum.project.builder.ContinuumProjectBuildingResult;
 import org.codehaus.plexus.logging.AbstractLogEnabled;
 import org.codehaus.plexus.util.StringUtils;
@@ -305,7 +305,7 @@
             {
                 Properties props = new Properties();
 
-                props.put( ContinuumRecipientSource.ADDRESS_FIELD, nagEmailAddress );
+                props.put( AbstractContinuumNotifier.ADDRESS_FIELD, nagEmailAddress );
 
                 ProjectNotifier notifier = new ProjectNotifier();
 

Modified: continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/DefaultContinuumNotificationDispatcher.java
URL: http://svn.apache.org/viewvc/continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/DefaultContinuumNotificationDispatcher.java?rev=674722&r1=674721&r2=674722&view=diff
==============================================================================
--- continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/DefaultContinuumNotificationDispatcher.java (original)
+++ continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/DefaultContinuumNotificationDispatcher.java Mon Jul  7 22:17:34 2008
@@ -19,25 +19,21 @@
  * under the License.
  */
 
-import org.apache.maven.continuum.configuration.ConfigurationException;
-import org.apache.maven.continuum.configuration.ConfigurationService;
 import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.BuildResult;
 import org.apache.maven.continuum.model.project.Project;
 import org.apache.maven.continuum.model.project.ProjectGroup;
 import org.apache.maven.continuum.model.project.ProjectNotifier;
+import org.apache.maven.continuum.notification.manager.NotifierManager;
 import org.apache.maven.continuum.store.ContinuumStore;
 import org.apache.maven.continuum.store.ContinuumStoreException;
-import org.codehaus.plexus.logging.AbstractLogEnabled;
-import org.codehaus.plexus.notification.NotificationException;
-import org.codehaus.plexus.notification.RecipientSource;
-import org.codehaus.plexus.notification.notifier.Notifier;
-import org.codehaus.plexus.notification.notifier.manager.NotifierManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
+import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 /**
  * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
@@ -46,13 +42,9 @@
  * role-hint="default"
  */
 public class DefaultContinuumNotificationDispatcher
-    extends AbstractLogEnabled
     implements ContinuumNotificationDispatcher
 {
-    /**
-     * @plexus.requirement
-     */
-    private ConfigurationService configurationService;
+    private Logger log = LoggerFactory.getLogger( getClass() );
 
     /**
      * @plexus.requirement
@@ -64,11 +56,6 @@
      */
     private ContinuumStore store;
 
-    /**
-     * @plexus.requirement
-     */
-    private RecipientSource recipientSource;
-
     // ----------------------------------------------------------------------
     // ContinuumNotificationDispatcher Implementation
     // ----------------------------------------------------------------------
@@ -110,7 +97,7 @@
     private void sendNotification( String messageId, Project project, BuildDefinition buildDefinition,
                                    BuildResult buildResult )
     {
-        Map context = new HashMap();
+        //Map context = new HashMap();
 
         // ----------------------------------------------------------------------
         // The objects are reread from the store to make sure they're getting the "final"
@@ -126,81 +113,90 @@
             //  - notifiers are used to send the notification
             project = store.getProjectWithAllDetails( project.getId() );
 
-            context.put( CONTEXT_PROJECT, project );
-            context.put( CONTEXT_BUILD_DEFINITION, buildDefinition );
+            ProjectGroup projectGroup =
+                store.getProjectGroupWithBuildDetailsByProjectGroupId( project.getProjectGroup().getId() );
 
-            if ( buildResult != null )
+            Map<String, List<ProjectNotifier>> notifiersMap = new HashMap<String, List<ProjectNotifier>>();
+            // perform the project level notifications
+            for ( ProjectNotifier notifier : (List<ProjectNotifier>) project.getNotifiers() )
             {
-                context.put( CONTEXT_BUILD, buildResult );
+                List<ProjectNotifier> notifiers = notifiersMap.get( notifier.getType() );
+                if ( notifiers == null )
+                {
+                    notifiers = new ArrayList<ProjectNotifier>();
+                }
 
-                if ( buildResult.getEndTime() != 0 )
+                if ( !notifier.isEnabled() )
                 {
-                    context.put( CONTEXT_BUILD_OUTPUT,
-                                 configurationService.getBuildOutput( buildResult.getId(), project.getId() ) );
+                    log.info( notifier.getType() + " notifier (id=" + notifier.getId() + ") is disabled." );
+
+                    continue;
                 }
 
-                context.put( CONTEXT_UPDATE_SCM_RESULT, buildResult.getScmResult() );
+                notifiers.add( notifier );
+                notifiersMap.put( notifier.getType(), notifiers );
             }
 
-            ProjectGroup projectGroup =
-                store.getProjectGroupWithBuildDetailsByProjectGroupId( project.getProjectGroup().getId() );
-
-            // perform the project lvl notifications
-            for ( Iterator i = project.getNotifiers().iterator(); i.hasNext(); )
+            // perform the project group level notifications
+            if ( projectGroup.getNotifiers() != null )
             {
-                sendNotification( messageId, (ProjectNotifier) i.next(), context );
+                for ( ProjectNotifier projectNotifier : (List<ProjectNotifier>) projectGroup.getNotifiers() )
+                {
+                    List<ProjectNotifier> projectNotifiers = notifiersMap.get( projectNotifier.getType() );
+                    if ( projectNotifiers == null )
+                    {
+                        projectNotifiers = new ArrayList<ProjectNotifier>();
+                    }
+
+                    if ( !projectNotifier.isEnabled() )
+                    {
+                        log.info( projectNotifier.getType() + " projectNotifier (id=" + projectNotifier.getId() +
+                            ") is disabled." );
+
+                        continue;
+                    }
+
+                    projectNotifiers.add( projectNotifier );
+                    notifiersMap.put( projectNotifier.getType(), projectNotifiers );
+                }
             }
 
-            // perform the project group lvl notifications
-            if ( projectGroup.getNotifiers() != null )
+            for ( String notifierType : notifiersMap.keySet() )
             {
-                for ( Iterator i = projectGroup.getNotifiers().iterator(); i.hasNext(); )
+                MessageContext context = new MessageContext();
+                context.setProject( project );
+                context.setBuildDefinition( buildDefinition );
+
+                if ( buildResult != null )
                 {
-                    sendNotification( messageId, (ProjectNotifier) i.next(), context );
+                    context.setBuildResult( buildResult );
                 }
+
+                List<ProjectNotifier> projectNotiiers = notifiersMap.get( notifierType );
+                context.setNotifier( projectNotiiers );
+
+                sendNotification( messageId, context );
             }
         }
         catch ( ContinuumStoreException e )
         {
-            getLogger().error( "Error while population the notification context.", e );
-
-            return;
-        }
-        catch ( ConfigurationException e )
-        {
-            getLogger().error( "Error while population the notification context.", e );
-
-            return;
+            log.error( "Error while population the notification context.", e );
         }
     }
 
-    private void sendNotification( String messageId, ProjectNotifier projectNotifier, Map context )
+    private void sendNotification( String messageId, MessageContext context )
     {
-        String notifierType = projectNotifier.getType();
-
-        if ( !projectNotifier.isEnabled() )
-        {
-            getLogger().info( notifierType + " notifier (id=" + projectNotifier.getId() + ") is disabled." );
-
-            return;
-        }
-
-        Map configuration = projectNotifier.getConfiguration();
+        String notifierType = context.getNotifiers().get( 0 ).getType();
 
         try
         {
-            context.put( CONTEXT_PROJECT_NOTIFIER, projectNotifier );
-
             Notifier notifier = notifierManager.getNotifier( notifierType );
 
-            Set recipients = recipientSource.getRecipients( String.valueOf( projectNotifier.getId() ), messageId,
-                                                            configuration, context );
-
-            notifier.sendNotification( messageId, recipients, configuration, context );
+            notifier.sendMessage( messageId, context );
         }
         catch ( NotificationException e )
         {
-            getLogger().error( "Error while trying to use the " + notifierType + " notifier.", e );
+            log.error( "Error while trying to use the " + notifierType + " notifier.", e );
         }
     }
 }

Modified: continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/console/ConsoleNotifier.java
URL: http://svn.apache.org/viewvc/continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/console/ConsoleNotifier.java?rev=674722&r1=674721&r2=674722&view=diff
==============================================================================
--- continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/console/ConsoleNotifier.java (original)
+++ continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/console/ConsoleNotifier.java Mon Jul  7 22:17:34 2008
@@ -21,62 +21,68 @@
 
 import org.apache.maven.continuum.model.project.BuildResult;
 import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.notification.AbstractContinuumNotifier;
 import org.apache.maven.continuum.notification.ContinuumNotificationDispatcher;
-import org.codehaus.plexus.notification.NotificationException;
-import org.codehaus.plexus.notification.notifier.AbstractNotifier;
+import org.apache.maven.continuum.notification.MessageContext;
+import org.apache.maven.continuum.notification.NotificationException;
 import org.codehaus.plexus.util.StringUtils;
-
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
  * @version $Id$
- * @plexus.component role="org.codehaus.plexus.notification.notifier.Notifier"
+ * @plexus.component role="org.apache.maven.continuum.notification.Notifier"
  * role-hint="console"
  */
 public class ConsoleNotifier
-    extends AbstractNotifier
+    extends AbstractContinuumNotifier
 {
+    private Logger log = LoggerFactory.getLogger( getClass() );
+
     // ----------------------------------------------------------------------
     // Notifier Implementation
     // ----------------------------------------------------------------------
 
-    public void sendNotification( String source, Set recipients, Map configuration, Map context )
+    public String getType()
+    {
+        return "console";
+    }
+
+    public void sendMessage( String messageId, MessageContext context )
         throws NotificationException
     {
-        Project project = (Project) context.get( ContinuumNotificationDispatcher.CONTEXT_PROJECT );
+        Project project = context.getProject();
 
-        BuildResult build = (BuildResult) context.get( ContinuumNotificationDispatcher.CONTEXT_BUILD );
+        BuildResult build = context.getBuildResult();
 
-        if ( source.equals( ContinuumNotificationDispatcher.MESSAGE_ID_BUILD_STARTED ) )
+        if ( messageId.equals( ContinuumNotificationDispatcher.MESSAGE_ID_BUILD_STARTED ) )
         {
             buildStarted( project );
         }
-        else if ( source.equals( ContinuumNotificationDispatcher.MESSAGE_ID_CHECKOUT_STARTED ) )
+        else if ( messageId.equals( ContinuumNotificationDispatcher.MESSAGE_ID_CHECKOUT_STARTED ) )
         {
             checkoutStarted( project );
         }
-        else if ( source.equals( ContinuumNotificationDispatcher.MESSAGE_ID_CHECKOUT_COMPLETE ) )
+        else if ( messageId.equals( ContinuumNotificationDispatcher.MESSAGE_ID_CHECKOUT_COMPLETE ) )
         {
             checkoutComplete( project );
         }
-        else if ( source.equals( ContinuumNotificationDispatcher.MESSAGE_ID_RUNNING_GOALS ) )
+        else if ( messageId.equals( ContinuumNotificationDispatcher.MESSAGE_ID_RUNNING_GOALS ) )
         {
             runningGoals( project, build );
         }
-        else if ( source.equals( ContinuumNotificationDispatcher.MESSAGE_ID_GOALS_COMPLETED ) )
+        else if ( messageId.equals( ContinuumNotificationDispatcher.MESSAGE_ID_GOALS_COMPLETED ) )
         {
             goalsCompleted( project, build );
         }
-        else if ( source.equals( ContinuumNotificationDispatcher.MESSAGE_ID_BUILD_COMPLETE ) )
+        else if ( messageId.equals( ContinuumNotificationDispatcher.MESSAGE_ID_BUILD_COMPLETE ) )
         {
             buildComplete( project, build );
         }
         else
         {
-            getLogger().warn( "Unknown source: '" + source + "'." );
+            log.warn( "Unknown messageId: '" + messageId + "'." );
         }
     }
 
@@ -137,13 +143,4 @@
             System.out.println( build.getError() );
         }
     }
-
-    /**
-     * @see org.codehaus.plexus.notification.notifier.Notifier#sendNotification(java.lang.String,java.util.Set,java.util.Properties)
-     */
-    public void sendNotification( String arg0, Set arg1, Properties arg2 )
-        throws NotificationException
-    {
-        throw new NotificationException( "Not implemented." );
-    }
 }

Modified: continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/mail/MailContinuumNotifier.java
URL: http://svn.apache.org/viewvc/continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/mail/MailContinuumNotifier.java?rev=674722&r1=674721&r2=674722&view=diff
==============================================================================
--- continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/mail/MailContinuumNotifier.java (original)
+++ continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/mail/MailContinuumNotifier.java Mon Jul  7 22:17:34 2008
@@ -19,16 +19,6 @@
  * under the License.
  */
 
-import java.io.StringWriter;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-
 import org.apache.maven.continuum.Continuum;
 import org.apache.maven.continuum.configuration.ConfigurationService;
 import org.apache.maven.continuum.execution.ExecutorConfigurator;
@@ -40,12 +30,16 @@
 import org.apache.maven.continuum.model.project.BuildDefinition;
 import org.apache.maven.continuum.model.project.BuildResult;
 import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.project.ProjectDeveloper;
 import org.apache.maven.continuum.model.project.ProjectNotifier;
+import org.apache.maven.continuum.model.scm.ChangeSet;
+import org.apache.maven.continuum.model.scm.ScmResult;
 import org.apache.maven.continuum.model.system.Installation;
 import org.apache.maven.continuum.model.system.Profile;
 import org.apache.maven.continuum.notification.AbstractContinuumNotifier;
 import org.apache.maven.continuum.notification.ContinuumNotificationDispatcher;
-import org.apache.maven.continuum.notification.ContinuumRecipientSource;
+import org.apache.maven.continuum.notification.MessageContext;
+import org.apache.maven.continuum.notification.NotificationException;
 import org.apache.maven.continuum.project.ContinuumProjectState;
 import org.apache.maven.continuum.reports.surefire.ReportTestResult;
 import org.apache.maven.continuum.reports.surefire.ReportTestSuiteGenerator;
@@ -54,10 +48,20 @@
 import org.codehaus.plexus.mailsender.MailMessage;
 import org.codehaus.plexus.mailsender.MailSender;
 import org.codehaus.plexus.mailsender.MailSenderException;
-import org.codehaus.plexus.notification.NotificationException;
 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
 import org.codehaus.plexus.util.StringUtils;
 import org.codehaus.plexus.velocity.VelocityComponent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.StringWriter;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 /**
  * @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
@@ -67,6 +71,8 @@
     extends AbstractContinuumNotifier
     implements Initializable
 {
+    private Logger log = LoggerFactory.getLogger( getClass() );
+
     // ----------------------------------------------------------------------
     // Requirements
     // ----------------------------------------------------------------------
@@ -90,16 +96,12 @@
      * @plexus.configuration
      */
     private MailSender mailSender;
-    
+
     /**
      * @plexus.requirement
-     */    
+     */
     private ReportTestSuiteGenerator reportTestSuiteGenerator;
 
-    /**
-     * @plexus.requirement role-hint="default"
-     */
-    //private ShellCommandHelper shellCommandHelper;
     // ----------------------------------------------------------------------
     // Configuration
     // ----------------------------------------------------------------------
@@ -116,6 +118,11 @@
     /**
      * @plexus.configuration
      */
+    private String toOverride;
+
+    /**
+     * @plexus.configuration
+     */
     private String timestampFormat;
 
     /**
@@ -127,16 +134,16 @@
      * @plexus.configuration
      */
     private boolean includeBuildSummary = true;
-    
+
     /**
      * @plexus.configuration
      */
     private boolean includeTestSummary = true;
-    
+
     /**
      * @plexus.configuration
      */
-    private boolean includeOutput = false;    
+    private boolean includeOutput = false;
 
     /**
      * Customizable mail subject.  Use any combination of literal text, project or build attributes.
@@ -192,13 +199,13 @@
 
         if ( StringUtils.isEmpty( fromMailbox ) )
         {
-            getLogger().info( "The from mailbox is not configured, will use the nag email address from the project." );
+            log.info( "The from mailbox is not configured, will use the nag email address from the project." );
 
             fromMailbox = null;
         }
         else
         {
-            getLogger().info( "Using '" + fromMailbox + "' as the from mailbox for all emails." );
+            log.info( "Using '" + fromMailbox + "' as the from mailbox for all emails." );
         }
 
         if ( StringUtils.isEmpty( fromName ) )
@@ -206,9 +213,9 @@
             fromName = "Continuum@" + buildHost;
         }
 
-        getLogger().info( "From name: " + fromName );
+        log.info( "From name: " + fromName );
 
-        getLogger().info( "Build host name: " + buildHost );
+        log.info( "Build host name: " + buildHost );
 
         // ----------------------------------------------------------------------
         //
@@ -221,20 +228,19 @@
     // Notifier Implementation
     // ----------------------------------------------------------------------
 
-    public void sendNotification( String source, Set recipients, Map configuration, Map context )
-        throws NotificationException
+    public String getType()
     {
-        Project project = (Project) context.get( ContinuumNotificationDispatcher.CONTEXT_PROJECT );
-
-        ProjectNotifier projectNotifier = (ProjectNotifier) context
-            .get( ContinuumNotificationDispatcher.CONTEXT_PROJECT_NOTIFIER );
-
-        BuildResult build = (BuildResult) context.get( ContinuumNotificationDispatcher.CONTEXT_BUILD );
-
-        String buildOutput = (String) context.get( ContinuumNotificationDispatcher.CONTEXT_BUILD_OUTPUT );
+        return "mail";
+    }
 
-        BuildDefinition buildDefinition = (BuildDefinition) context
-            .get( ContinuumNotificationDispatcher.CONTEXT_BUILD_DEFINITION );
+    public void sendMessage( String messageId, MessageContext context )
+        throws NotificationException
+    {
+        Project project = context.getProject();
+        List<ProjectNotifier> notifiers = context.getNotifiers();
+        BuildResult build = context.getBuildResult();
+        String buildOutput = getBuildOutput( project, build );
+        BuildDefinition buildDefinition = context.getBuildDefinition();
 
         // ----------------------------------------------------------------------
         // If there wasn't any building done, don't notify
@@ -249,36 +255,45 @@
         // Generate and send email
         // ----------------------------------------------------------------------
 
-        if ( source.equals( ContinuumNotificationDispatcher.MESSAGE_ID_BUILD_COMPLETE ) )
+        if ( messageId.equals( ContinuumNotificationDispatcher.MESSAGE_ID_BUILD_COMPLETE ) )
         {
-            buildComplete( project, projectNotifier, build, buildOutput, source, recipients, configuration,
-                           buildDefinition );
+            buildComplete( project, notifiers, build, buildOutput, messageId, context, buildDefinition );
         }
     }
 
-    private void buildComplete( Project project, ProjectNotifier projectNotifier, BuildResult build, String buildOutput,
-                                String source, Set recipients, Map configuration, BuildDefinition buildDefinition )
+    private void buildComplete( Project project, List<ProjectNotifier> notifiers, BuildResult build, String buildOutput,
+                                String messageId, MessageContext context, BuildDefinition buildDefinition )
         throws NotificationException
     {
-
-        // ----------------------------------------------------------------------
-        // Check if the mail should be sent at all
-        // ----------------------------------------------------------------------
-
         BuildResult previousBuild = getPreviousBuild( project, buildDefinition, build );
 
-        if ( !shouldNotify( build, previousBuild, projectNotifier ) )
+        List<ProjectNotifier> notifiersList = new ArrayList<ProjectNotifier>();
+        for ( ProjectNotifier notifier : notifiers )
         {
-            return;
+            // ----------------------------------------------------------------------
+            // Check if the mail should be sent at all
+            // ----------------------------------------------------------------------
+
+            if ( shouldNotify( build, previousBuild, notifier ) )
+            {
+                notifiersList.add( notifier );
+            }
         }
+        buildComplete( project, notifiersList, build, previousBuild, buildOutput, messageId, context, buildDefinition );
+    }
 
+    private void buildComplete( Project project, List<ProjectNotifier> notifiers, BuildResult build,
+                                BuildResult previousBuild, String buildOutput, String messageId,
+                                MessageContext messageContext, BuildDefinition buildDefinition )
+        throws NotificationException
+    {
         // ----------------------------------------------------------------------
         // Generate the mail contents
         // ----------------------------------------------------------------------
 
         String packageName = getClass().getPackage().getName().replace( '.', '/' );
 
-        String templateName = packageName + "/templates/" + project.getExecutorId() + "/" + source + ".vm";
+        String templateName = packageName + "/templates/" + project.getExecutorId() + "/" + messageId + ".vm";
 
         StringWriter writer = new StringWriter();
 
@@ -287,9 +302,9 @@
         try
         {
             VelocityContext context = new VelocityContext();
-            
+
             context.put( "includeTestSummary", includeTestSummary );
-            
+
             context.put( "includeOutput", includeOutput );
 
             if ( includeBuildResult )
@@ -301,11 +316,11 @@
             {
                 context.put( "build", build );
 
-                ReportTestResult reportTestResult = reportTestSuiteGenerator.generateReportTestResult( build.getId(),
-                                                                                                       project.getId() );
+                ReportTestResult reportTestResult =
+                    reportTestSuiteGenerator.generateReportTestResult( build.getId(), project.getId() );
 
                 context.put( "testResult", reportTestResult );
-                
+
                 context.put( "project", project );
 
                 context.put( "changesSinceLastSuccess", continuum.getChangesSinceLastSuccess( project.getId(), build
@@ -361,7 +376,7 @@
         }
         catch ( ResourceNotFoundException e )
         {
-            getLogger().info( "No such template: '" + templateName + "'." );
+            log.info( "No such template: '" + templateName + "'." );
 
             return;
         }
@@ -384,7 +399,7 @@
             throw new NotificationException( "Error while generating mail subject.", e );
         }
 
-        sendMessage( project, recipients, subject, content, configuration );
+        sendMessage( project, notifiers, subject, content, messageContext );
     }
 
     // ----------------------------------------------------------------------
@@ -409,8 +424,7 @@
     private List<String> getBuilderVersion( BuildDefinition buildDefinition, Project project )
         throws InstallationException
     {
-
-        ExecutorConfigurator executorConfigurator = null;
+        ExecutorConfigurator executorConfigurator;
         Installation builder = null;
         Profile profile = null;
         if ( buildDefinition != null )
@@ -445,7 +459,7 @@
             }
             else
             {
-                return Arrays.asList( new String[]{"No builder defined"} );
+                return Arrays.asList( "No builder defined" );
             }
         }
 
@@ -467,9 +481,7 @@
 
         boolean velocityResults = velocity.getEngine().evaluate( context, writer, "subjectPattern", subjectFormat );
 
-        String subject = writer.toString();
-
-        return subject;
+        return writer.toString();
     }
 
     private String getState( Project project, BuildResult build )
@@ -495,30 +507,31 @@
         }
         else
         {
-            getLogger().warn( "Unknown build state " + state + " for project " + project.getId() );
+            log.warn( "Unknown build state " + state + " for project " + project.getId() );
 
             return "ERROR: Unknown build state " + state;
         }
     }
 
-    private void sendMessage( Project project, Set recipients, String subject, String content, Map configuration )
+    private void sendMessage( Project project, List<ProjectNotifier> notifiers, String subject, String content,
+                              MessageContext context )
         throws NotificationException
     {
-        if ( recipients.size() == 0 )
+        if ( notifiers.size() == 0 )
         {
             // This is a useful message for the users when debugging why they don't
             // receive any mails
 
-            getLogger().info( "No mail recipients for '" + project.getName() + "'." );
+            log.info( "No mail notifier for '" + project.getName() + "'." );
 
             return;
         }
 
-        String fromMailbox = getFromMailbox( configuration );
+        String fromMailbox = getFromMailbox( notifiers );
 
         if ( fromMailbox == null )
         {
-            getLogger()
+            log
                 .warn( project.getName() +
                     ": Project is missing nag email and global from mailbox is missing, not sending mail." );
 
@@ -537,7 +550,7 @@
         {
             message.setSubject( subject );
 
-            getLogger().info( "Message Subject: '" + subject + "'." );
+            log.info( "Message Subject: '" + subject + "'." );
 
             message.setContent( content );
 
@@ -545,16 +558,89 @@
 
             message.setFrom( from );
 
-            getLogger().info( "Sending message: From '" + from + "'." );
+            log.info( "Sending message: From '" + from + "'." );
 
-            for ( Iterator it = recipients.iterator(); it.hasNext(); )
+            if ( StringUtils.isEmpty( toOverride ) )
             {
-                String mailbox = (String) it.next();
-
+                for ( ProjectNotifier notifier : notifiers )
+                {
+                    Map<String, String> conf = notifier.getConfiguration();
+                    if ( conf != null )
+                    {
+                        String addressField = conf.get( ADDRESS_FIELD );
+
+                        if ( StringUtils.isNotEmpty( addressField ) )
+                        {
+                            String[] addresses = StringUtils.split( addressField, "," );
+
+                            for ( String address : addresses )
+                            {
+                                // TODO: set a proper name
+                                MailMessage.Address to = new MailMessage.Address( address.trim() );
+
+                                log.info( "Recipient: To '" + to + "'." );
+
+                                message.addTo( to );
+                            }
+                        }
+
+                        String committerField = (String) notifier.getConfiguration().get( COMMITTER_FIELD );
+                        if ( StringUtils.isNotEmpty( committerField ) && context.getBuildResult() != null )
+                        {
+                            if ( Boolean.parseBoolean( committerField ) )
+                            {
+                                ScmResult scmResult = context.getBuildResult().getScmResult();
+                                if ( scmResult != null && scmResult.getChanges() != null &&
+                                    !scmResult.getChanges().isEmpty() )
+                                {
+                                    List<ProjectDeveloper> developers = project.getDevelopers();
+                                    if ( developers == null || developers.isEmpty() )
+                                    {
+                                        log.warn( "No developers have been configured...notifcation email " +
+                                            "will not be sent" );
+                                        return;
+                                    }
+
+                                    Map<String, String> developerToEmailMap = mapDevelopersToRecipients( developers );
+
+                                    List<ChangeSet> changes = scmResult.getChanges();
+
+                                    for ( ChangeSet changeSet : changes )
+                                    {
+                                        String scmId = changeSet.getAuthor();
+                                        if ( StringUtils.isNotEmpty( scmId ) )
+                                        {
+                                            String email = developerToEmailMap.get( scmId );
+                                            if ( StringUtils.isEmpty( email ) )
+                                            {
+                                                //TODO: Add a default domain so mail address won't be required
+                                                log.warn( "no email address is defined in developers list for '" +
+                                                    scmId + "' scm id." );
+                                            }
+                                            else
+                                            {
+                                                // TODO: set a proper name
+                                                MailMessage.Address to = new MailMessage.Address( email.trim() );
+
+                                                log.info( "Recipient: To '" + to + "'." );
+
+                                                message.addTo( to );
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            else
+            {
+                // TODO: use configuration file instead of to load it fron component configuration
                 // TODO: set a proper name
-                MailMessage.Address to = new MailMessage.Address( mailbox );
+                MailMessage.Address to = new MailMessage.Address( toOverride.trim() );
 
-                getLogger().info( "Recipient: To '" + to + "'." );
+                log.info( "Recipient: To '" + to + "'." );
 
                 message.addTo( to );
             }
@@ -567,7 +653,22 @@
         }
     }
 
-    private String getFromMailbox( Map configuration )
+    private Map<String, String> mapDevelopersToRecipients( List<ProjectDeveloper> developers )
+    {
+        Map<String, String> developersMap = new HashMap<String, String>();
+
+        for ( ProjectDeveloper developer : developers )
+        {
+            if ( StringUtils.isNotEmpty( developer.getScmId() ) && StringUtils.isNotEmpty( developer.getEmail() ) )
+            {
+                developersMap.put( developer.getScmId(), developer.getEmail() );
+            }
+        }
+
+        return developersMap;
+    }
+
+    private String getFromMailbox( List<ProjectNotifier> notifiers )
     {
         if ( fromMailbox != null )
         {
@@ -576,9 +677,14 @@
 
         String address = null;
 
-        if ( configuration != null )
+        for ( ProjectNotifier notifier : notifiers )
         {
-            address = (String) configuration.get( ContinuumRecipientSource.ADDRESS_FIELD );
+            Map<String, String> configuration = notifier.getConfiguration();
+            if ( configuration != null && StringUtils.isNotEmpty( configuration.get( ADDRESS_FIELD ) ) )
+            {
+                address = configuration.get( ADDRESS_FIELD );
+                break;
+            }
         }
 
         if ( StringUtils.isEmpty( address ) )
@@ -594,12 +700,23 @@
         return address;
     }
 
-    /**
-     * @see org.codehaus.plexus.notification.notifier.Notifier#sendNotification(java.lang.String,java.util.Set,java.util.Properties)
-     */
-    public void sendNotification( String arg0, Set arg1, Properties arg2 )
-        throws NotificationException
+    public String getBuildHost()
+    {
+        return buildHost;
+    }
+
+    public void setBuildHost( String buildHost )
+    {
+        this.buildHost = buildHost;
+    }
+
+    public String getToOverride()
+    {
+        return toOverride;
+    }
+
+    public void setToOverride( String toOverride )
     {
-        throw new NotificationException( "Not implemented." );
+        this.toOverride = toOverride;
     }
 }

Added: continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/DefaultNotifierManager.java
URL: http://svn.apache.org/viewvc/continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/DefaultNotifierManager.java?rev=674722&view=auto
==============================================================================
--- continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/DefaultNotifierManager.java (added)
+++ continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/DefaultNotifierManager.java Mon Jul  7 22:17:34 2008
@@ -0,0 +1,30 @@
+package org.apache.maven.continuum.notification.manager;
+
+import org.apache.maven.continuum.notification.Notifier;
+
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
+ * @version $Id$
+ */
+public class DefaultNotifierManager
+    implements NotifierManager
+{
+    private Map<String, Notifier> notifiers;
+
+    public Notifier getNotifier( String notifierId )
+    {
+        return notifiers.get( notifierId );
+    }
+
+    public Map getNotifiers()
+    {
+        return notifiers;
+    }
+
+    public void setNotifiers( Map notifiers )
+    {
+        this.notifiers = notifiers;
+    }
+}

Propchange: continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/DefaultNotifierManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/DefaultNotifierManager.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/NotifierManager.java
URL: http://svn.apache.org/viewvc/continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/NotifierManager.java?rev=674722&view=auto
==============================================================================
--- continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/NotifierManager.java (added)
+++ continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/NotifierManager.java Mon Jul  7 22:17:34 2008
@@ -0,0 +1,31 @@
+package org.apache.maven.continuum.notification.manager;
+
+/*
+ * 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.continuum.notification.Notifier;
+
+/**
+ * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
+ * @version $Id$
+ */
+public interface NotifierManager
+{
+    Notifier getNotifier(String notifierId);
+}

Propchange: continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/NotifierManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/NotifierManager.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/spring/NotifierFactoryBean.java
URL: http://svn.apache.org/viewvc/continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/spring/NotifierFactoryBean.java?rev=674722&view=auto
==============================================================================
--- continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/spring/NotifierFactoryBean.java (added)
+++ continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/spring/NotifierFactoryBean.java Mon Jul  7 22:17:34 2008
@@ -0,0 +1,89 @@
+package org.apache.maven.continuum.notification.manager.spring;
+
+/*
+ * 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.continuum.notification.Notifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.BeanFactoryUtils;
+import org.springframework.beans.factory.BeanInitializationException;
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
+ * @version $Id$
+ */
+public class NotifierFactoryBean
+    implements FactoryBean, ApplicationContextAware
+{
+    private Logger log = LoggerFactory.getLogger( getClass() );
+
+    private ApplicationContext applicationContext;
+
+    public Object getObject()
+        throws Exception
+    {
+        Map<String, Notifier> notifiers = new HashMap<String, Notifier>();
+
+        Map<String, Notifier> beans =
+            BeanFactoryUtils.beansOfTypeIncludingAncestors( applicationContext, Notifier.class );
+
+        for ( Notifier notifier : beans.values() )
+        {
+
+            if ( notifiers.containsKey( notifier.getType() ) )
+            {
+                throw new BeanInitializationException(
+                    "There are two Notifier beans in the appllication context for Notifier type " + notifier.getType() +
+                        ". Probably two conflicting scm implementations are present in the classpath." );
+            }
+
+            if ( log.isDebugEnabled() )
+            {
+                log.debug(
+                    "put provider with type " + notifier.getType() + " and class " + notifier.getClass().getName() );
+            }
+            notifiers.put( notifier.getType(), notifier );
+        }
+        return notifiers;
+    }
+
+    public Class getObjectType()
+    {
+        return Map.class;
+    }
+
+    public boolean isSingleton()
+    {
+        return true;
+    }
+
+    public void setApplicationContext( ApplicationContext applicationContext )
+        throws BeansException
+    {
+        this.applicationContext = applicationContext;
+    }
+}

Propchange: continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/spring/NotifierFactoryBean.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: continuum/trunk/continuum-core/src/main/java/org/apache/maven/continuum/notification/manager/spring/NotifierFactoryBean.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Modified: continuum/trunk/continuum-core/src/main/resources/META-INF/spring-context.xml
URL: http://svn.apache.org/viewvc/continuum/trunk/continuum-core/src/main/resources/META-INF/spring-context.xml?rev=674722&r1=674721&r2=674722&view=diff
==============================================================================
--- continuum/trunk/continuum-core/src/main/resources/META-INF/spring-context.xml (original)
+++ continuum/trunk/continuum-core/src/main/resources/META-INF/spring-context.xml Mon Jul  7 22:17:34 2008
@@ -28,4 +28,10 @@
 
   <bean id="workingDirectoryService" class="org.apache.maven.continuum.utils.DefaultWorkingDirectoryService" autowire="byName"/>
 
+  <bean id="notifierManager"
+    class="org.apache.maven.continuum.notification.manager.DefaultNotifierManager">
+    <property name="notifiers">
+      <bean class="org.apache.maven.continuum.notification.manager.spring.NotifierFactoryBean"/>
+    </property>
+  </bean>
 </beans>

Modified: continuum/trunk/continuum-core/src/test/java/org/apache/maven/continuum/notification/mail/MailContinuumNotifierTest.java
URL: http://svn.apache.org/viewvc/continuum/trunk/continuum-core/src/test/java/org/apache/maven/continuum/notification/mail/MailContinuumNotifierTest.java?rev=674722&r1=674721&r2=674722&view=diff
==============================================================================
--- continuum/trunk/continuum-core/src/test/java/org/apache/maven/continuum/notification/mail/MailContinuumNotifierTest.java (original)
+++ continuum/trunk/continuum-core/src/test/java/org/apache/maven/continuum/notification/mail/MailContinuumNotifierTest.java Mon Jul  7 22:17:34 2008
@@ -22,19 +22,20 @@
 import org.apache.maven.continuum.AbstractContinuumTest;
 import org.apache.maven.continuum.model.project.BuildResult;
 import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.project.ProjectNotifier;
 import org.apache.maven.continuum.notification.ContinuumNotificationDispatcher;
+import org.apache.maven.continuum.notification.MessageContext;
+import org.apache.maven.continuum.notification.Notifier;
 import org.apache.maven.continuum.project.ContinuumProjectState;
 import org.codehaus.plexus.mailsender.MailMessage;
 import org.codehaus.plexus.mailsender.MailSender;
 import org.codehaus.plexus.mailsender.test.MockMailSender;
-import org.codehaus.plexus.notification.notifier.Notifier;
 import org.codehaus.plexus.util.CollectionUtils;
 
+import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 /**
  * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
@@ -46,6 +47,9 @@
     public void testSuccessfulBuild()
         throws Exception
     {
+        MailContinuumNotifier notifier = (MailContinuumNotifier) lookup( Notifier.class.getName(), "mail" );
+        notifier.setToOverride( "recipient@host.com" );
+
         Project project = makeStubProject( "Test Project" );
         project.setGroupId( "foo.bar" );
 
@@ -54,8 +58,8 @@
         MailMessage mailMessage = sendNotificationAndGetMessage( project, build, "lots out build output" );
 
         assertEquals( "[continuum] BUILD SUCCESSFUL: foo.bar Test Project", mailMessage.getSubject() );
-        
-        dumpContent( mailMessage );
+
+        dumpContent( mailMessage, "recipient@host.com" );
     }
 
     public void testFailedBuild()
@@ -90,9 +94,23 @@
         dumpContent( mailMessage );
     }
 
-
     private void dumpContent( MailMessage mailMessage )
+        throws Exception
     {
+        dumpContent( mailMessage, null );
+    }
+
+    private void dumpContent( MailMessage mailMessage, String toOverride )
+        throws Exception
+    {
+        if ( toOverride != null )
+        {
+            assertEquals( toOverride, ( (MailMessage.Address) mailMessage.getToAddresses().get( 0 ) ).getMailbox() );
+        }
+        else
+        {
+            assertEquals( "foo@bar", ( (MailMessage.Address) mailMessage.getToAddresses().get( 0 ) ).getMailbox() );
+        }
         assertTrue( "The template isn't loaded correctly.",
                     mailMessage.getContent().indexOf( "#shellBuildResult()" ) < 0 );
         assertTrue( "The template isn't loaded correctly.",
@@ -111,27 +129,34 @@
     private MailMessage sendNotificationAndGetMessage( Project project, BuildResult build, String buildOutput )
         throws Exception
     {
-        Set recipients = new HashSet();
-
-        recipients.add( "foo@bar" );
+        MessageContext context = new MessageContext();
 
-        Map context = new HashMap();
+        context.setProject( project );
 
-        context.put( ContinuumNotificationDispatcher.CONTEXT_PROJECT, project );
+        context.setBuildResult( build );
 
-        context.put( ContinuumNotificationDispatcher.CONTEXT_BUILD, build );
+        ProjectNotifier projectNotifier = new ProjectNotifier();
+        projectNotifier.setType( "mail" );
+        Map<String, String> config = new HashMap<String, String>();
+        config.put( MailContinuumNotifier.ADDRESS_FIELD, "foo@bar" );
+        projectNotifier.setConfiguration( config );
+        List<ProjectNotifier> projectNotifiers = new ArrayList<ProjectNotifier>();
+        projectNotifiers.add( projectNotifier );
+        context.setNotifier( projectNotifiers );
 
-        context.put( ContinuumNotificationDispatcher.CONTEXT_BUILD_OUTPUT, buildOutput );
+        //context.put( ContinuumNotificationDispatcher.CONTEXT_BUILD_OUTPUT, buildOutput );
 
-        context.put( "buildHost", "foo.bar.com" );
+        //context.put( "buildHost", "foo.bar.com" );
 
         // ----------------------------------------------------------------------
         //
         // ----------------------------------------------------------------------
 
-        Notifier notifier = (Notifier) lookup( Notifier.ROLE, "mail" );
+        Notifier notifier = (Notifier) lookup( Notifier.class.getName(), "mail" );
+
+        ( (MailContinuumNotifier) notifier ).setBuildHost( "foo.bar.com" );
 
-        notifier.sendNotification( ContinuumNotificationDispatcher.MESSAGE_ID_BUILD_COMPLETE, recipients, context );
+        notifier.sendMessage( ContinuumNotificationDispatcher.MESSAGE_ID_BUILD_COMPLETE, context );
 
         // ----------------------------------------------------------------------
         //
@@ -157,7 +182,7 @@
 
         assertEquals( 1, to.size() );
 
-        assertEquals( "foo@bar", ( (MailMessage.Address) to.get( 0 ) ).getMailbox() );
+        //assertEquals( "foo@bar", ( (MailMessage.Address) to.get( 0 ) ).getMailbox() );
 
         assertNull( ( (MailMessage.Address) to.get( 0 ) ).getName() );
 

Modified: continuum/trunk/continuum-core/src/test/resources/org/apache/maven/continuum/buildcontroller/DefaultBuildControllerTest.xml
URL: http://svn.apache.org/viewvc/continuum/trunk/continuum-core/src/test/resources/org/apache/maven/continuum/buildcontroller/DefaultBuildControllerTest.xml?rev=674722&r1=674721&r2=674722&view=diff
==============================================================================
--- continuum/trunk/continuum-core/src/test/resources/org/apache/maven/continuum/buildcontroller/DefaultBuildControllerTest.xml (original)
+++ continuum/trunk/continuum-core/src/test/resources/org/apache/maven/continuum/buildcontroller/DefaultBuildControllerTest.xml Mon Jul  7 22:17:34 2008
@@ -19,12 +19,12 @@
 
 <plexus>
   <components>
-    <component>
+    <!-- component>
       <role>org.codehaus.plexus.notification.RecipientSource</role>
       <implementation>org.apache.maven.continuum.notification.ContinuumRecipientSource</implementation>
       <configuration>
         <toOverride>nobody@localhost</toOverride>
       </configuration>
-    </component>
+    </component -->
   </components>
 </plexus>

Modified: continuum/trunk/continuum-core/src/test/resources/org/apache/maven/continuum/notification/ContinuumNotificationDispatcherTest.xml
URL: http://svn.apache.org/viewvc/continuum/trunk/continuum-core/src/test/resources/org/apache/maven/continuum/notification/ContinuumNotificationDispatcherTest.xml?rev=674722&r1=674721&r2=674722&view=diff
==============================================================================
--- continuum/trunk/continuum-core/src/test/resources/org/apache/maven/continuum/notification/ContinuumNotificationDispatcherTest.xml (original)
+++ continuum/trunk/continuum-core/src/test/resources/org/apache/maven/continuum/notification/ContinuumNotificationDispatcherTest.xml Mon Jul  7 22:17:34 2008
@@ -20,28 +20,12 @@
 <plexus>
   <components>
     <component>
-      <role>org.codehaus.plexus.notification.RecipientSource</role>
-      <implementation>org.apache.maven.continuum.notification.ContinuumRecipientSource</implementation>
-      <configuration>
-        <toOverride>nobody@localhost</toOverride>
-      </configuration>
-    </component>
-
-    <component>
       <role>org.codehaus.plexus.mailsender.MailSender</role>
       <implementation>org.codehaus.plexus.mailsender.test.MockMailSender</implementation>
     </component>
 
     <component>
-      <role>org.codehaus.plexus.notification.RecipientSource</role>
-      <implementation>org.apache.maven.continuum.notification.ContinuumRecipientSource</implementation>
-      <configuration>
-        <toOverride>nobody@localhost</toOverride>
-      </configuration>
-    </component>
-
-    <component>
-      <role>org.codehaus.plexus.notification.notifier.Notifier</role>
+      <role>org.apache.maven.continuum.notification.Notifier</role>
       <role-hint>mail</role-hint>
       <implementation>org.apache.maven.continuum.notification.mail.MailContinuumNotifier</implementation>
       <requirements>
@@ -61,12 +45,16 @@
         <requirement>
           <role>org.apache.maven.continuum.Continuum</role>
         </requirement>
+        <requirement>
+          <role>org.apache.maven.continuum.reports.surefire.ReportTestSuiteGenerator</role>
+        </requirement>
       </requirements>
       <configuration>
         <fromMailbox>continuum@localhost</fromMailbox>
         <fromName>Continuum</fromName>
         <timestampFormat>EEE, d MMM yyyy HH:mm:ss Z</timestampFormat>
         <includeBuildResult>true</includeBuildResult>
+        <toOverride>nobody@localhost</toOverride>
       </configuration>
     </component>
 

Modified: continuum/trunk/continuum-core/src/test/resources/org/apache/maven/continuum/notification/mail/MailContinuumNotifierTest.xml
URL: http://svn.apache.org/viewvc/continuum/trunk/continuum-core/src/test/resources/org/apache/maven/continuum/notification/mail/MailContinuumNotifierTest.xml?rev=674722&r1=674721&r2=674722&view=diff
==============================================================================
--- continuum/trunk/continuum-core/src/test/resources/org/apache/maven/continuum/notification/mail/MailContinuumNotifierTest.xml (original)
+++ continuum/trunk/continuum-core/src/test/resources/org/apache/maven/continuum/notification/mail/MailContinuumNotifierTest.xml Mon Jul  7 22:17:34 2008
@@ -26,15 +26,7 @@
     </component>
 
     <component>
-      <role>org.codehaus.plexus.notification.RecipientSource</role>
-      <implementation>org.apache.maven.continuum.notification.ContinuumRecipientSource</implementation>
-      <configuration>
-        <toOverride>nobody@localhost</toOverride>
-      </configuration>
-    </component>
-
-    <component>
-      <role>org.codehaus.plexus.notification.notifier.Notifier</role>
+      <role>org.apache.maven.continuum.notification.Notifier</role>
       <role-hint>mail</role-hint>
       <implementation>org.apache.maven.continuum.notification.mail.MailContinuumNotifier</implementation>
       <requirements>

Modified: continuum/trunk/continuum-notifiers/continuum-notifier-api/pom.xml
URL: http://svn.apache.org/viewvc/continuum/trunk/continuum-notifiers/continuum-notifier-api/pom.xml?rev=674722&r1=674721&r2=674722&view=diff
==============================================================================
--- continuum/trunk/continuum-notifiers/continuum-notifier-api/pom.xml (original)
+++ continuum/trunk/continuum-notifiers/continuum-notifier-api/pom.xml Mon Jul  7 22:17:34 2008
@@ -26,4 +26,10 @@
   <modelVersion>4.0.0</modelVersion>
   <artifactId>continuum-notifier-api</artifactId>
   <name>Continuum Notifier API</name>
+  <dependencies>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+	</dependency>
+  </dependencies>
 </project>
\ No newline at end of file

Modified: continuum/trunk/continuum-notifiers/continuum-notifier-api/src/main/java/org/apache/maven/continuum/notification/AbstractContinuumNotifier.java
URL: http://svn.apache.org/viewvc/continuum/trunk/continuum-notifiers/continuum-notifier-api/src/main/java/org/apache/maven/continuum/notification/AbstractContinuumNotifier.java?rev=674722&r1=674721&r2=674722&view=diff
==============================================================================
--- continuum/trunk/continuum-notifiers/continuum-notifier-api/src/main/java/org/apache/maven/continuum/notification/AbstractContinuumNotifier.java (original)
+++ continuum/trunk/continuum-notifiers/continuum-notifier-api/src/main/java/org/apache/maven/continuum/notification/AbstractContinuumNotifier.java Mon Jul  7 22:17:34 2008
@@ -20,6 +20,7 @@
  */
 
 import org.apache.maven.continuum.ContinuumException;
+import org.apache.maven.continuum.configuration.ConfigurationException;
 import org.apache.maven.continuum.configuration.ConfigurationLoadingException;
 import org.apache.maven.continuum.configuration.ConfigurationService;
 import org.apache.maven.continuum.model.project.BuildDefinition;
@@ -29,14 +30,25 @@
 import org.apache.maven.continuum.project.ContinuumProjectState;
 import org.apache.maven.continuum.store.ContinuumStore;
 import org.apache.maven.continuum.store.ContinuumStoreException;
-import org.codehaus.plexus.notification.NotificationException;
-import org.codehaus.plexus.notification.notifier.AbstractNotifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.util.List;
 
 public abstract class AbstractContinuumNotifier
-    extends AbstractNotifier
+    implements Notifier
 {
+    public static String ADDRESS_FIELD = "address";
+
+    public static String COMMITTER_FIELD = "committers";
+
+    private Logger log = LoggerFactory.getLogger( getClass() );
+
+    /**
+     * @plexus.requirement
+     */
+    private ConfigurationService configurationService;
+
     /**
      * @plexus.requirement role-hint="jdo"
      */
@@ -47,6 +59,27 @@
      */
     private boolean alwaysSend = false;
 
+    protected String getBuildOutput( Project project, BuildResult buildResult )
+    {
+        try
+        {
+            if ( buildResult.getEndTime() != 0 )
+            {
+                return configurationService.getBuildOutput( buildResult.getId(), project.getId() );
+            }
+            else
+            {
+                return "";
+            }
+        }
+        catch ( ConfigurationException e )
+        {
+            String msg = "Error while population the notification context.";
+            log.error( msg, e );
+            return msg;
+        }
+    }
+
     /**
      * Returns url of the last build
      *
@@ -149,8 +182,11 @@
         }
 
         // Send if the state has changed
-        getLogger().debug(
-            "Current build state: " + build.getState() + ", previous build state: " + previousBuild.getState() );
+        if ( log.isDebugEnabled() )
+        {
+            log.debug(
+                "Current build state: " + build.getState() + ", previous build state: " + previousBuild.getState() );
+        }
 
         if ( build.getState() != previousBuild.getState() )
         {
@@ -177,7 +213,7 @@
             return true;
         }
 
-        getLogger().info( "Same state, not sending message." );
+        log.info( "Same state, not sending message." );
 
         return false;
     }
@@ -190,7 +226,8 @@
         {
             if ( buildDef != null )
             {
-                builds = getContinuumStore().getBuildResultsByBuildDefinition( project.getId(), buildDef.getId(), 0, 2 );
+                builds =
+                    getContinuumStore().getBuildResultsByBuildDefinition( project.getId(), buildDef.getId(), 0, 2 );
 
                 if ( builds.size() < 2 )
                 {

Added: continuum/trunk/continuum-notifiers/continuum-notifier-api/src/main/java/org/apache/maven/continuum/notification/MessageContext.java
URL: http://svn.apache.org/viewvc/continuum/trunk/continuum-notifiers/continuum-notifier-api/src/main/java/org/apache/maven/continuum/notification/MessageContext.java?rev=674722&view=auto
==============================================================================
--- continuum/trunk/continuum-notifiers/continuum-notifier-api/src/main/java/org/apache/maven/continuum/notification/MessageContext.java (added)
+++ continuum/trunk/continuum-notifiers/continuum-notifier-api/src/main/java/org/apache/maven/continuum/notification/MessageContext.java Mon Jul  7 22:17:34 2008
@@ -0,0 +1,82 @@
+package org.apache.maven.continuum.notification;
+
+/*
+ * 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.continuum.model.project.BuildDefinition;
+import org.apache.maven.continuum.model.project.BuildResult;
+import org.apache.maven.continuum.model.project.Project;
+import org.apache.maven.continuum.model.project.ProjectNotifier;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
+ * @version $Id$
+ */
+public class MessageContext
+{
+    private Project project;
+
+    private BuildDefinition buildDefinition;
+
+    private List<ProjectNotifier> notifiers;
+
+    private BuildResult buildResult;
+
+    public Project getProject()
+    {
+        return project;
+    }
+
+    public void setProject( Project project )
+    {
+        this.project = project;
+    }
+
+    public BuildDefinition getBuildDefinition()
+    {
+        return buildDefinition;
+    }
+
+    public void setBuildDefinition( BuildDefinition buildDefinition )
+    {
+        this.buildDefinition = buildDefinition;
+    }
+
+    public List<ProjectNotifier> getNotifiers()
+    {
+        return notifiers;
+    }
+
+    public void setNotifier( List<ProjectNotifier> notifiers )
+    {
+        this.notifiers = notifiers;
+    }
+
+    public BuildResult getBuildResult()
+    {
+        return buildResult;
+    }
+
+    public void setBuildResult( BuildResult buildResult )
+    {
+        this.buildResult = buildResult;
+    }
+}

Propchange: continuum/trunk/continuum-notifiers/continuum-notifier-api/src/main/java/org/apache/maven/continuum/notification/MessageContext.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: continuum/trunk/continuum-notifiers/continuum-notifier-api/src/main/java/org/apache/maven/continuum/notification/MessageContext.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: continuum/trunk/continuum-notifiers/continuum-notifier-api/src/main/java/org/apache/maven/continuum/notification/NotificationException.java
URL: http://svn.apache.org/viewvc/continuum/trunk/continuum-notifiers/continuum-notifier-api/src/main/java/org/apache/maven/continuum/notification/NotificationException.java?rev=674722&view=auto
==============================================================================
--- continuum/trunk/continuum-notifiers/continuum-notifier-api/src/main/java/org/apache/maven/continuum/notification/NotificationException.java (added)
+++ continuum/trunk/continuum-notifiers/continuum-notifier-api/src/main/java/org/apache/maven/continuum/notification/NotificationException.java Mon Jul  7 22:17:34 2008
@@ -0,0 +1,38 @@
+package org.apache.maven.continuum.notification;
+
+/*
+ * 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.
+ */
+
+/**
+ * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
+ * @version $Id$
+ */
+public class NotificationException
+    extends Exception
+{
+    public NotificationException( String message )
+    {
+        super( message );
+    }
+
+    public NotificationException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+}

Propchange: continuum/trunk/continuum-notifiers/continuum-notifier-api/src/main/java/org/apache/maven/continuum/notification/NotificationException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: continuum/trunk/continuum-notifiers/continuum-notifier-api/src/main/java/org/apache/maven/continuum/notification/NotificationException.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: continuum/trunk/continuum-notifiers/continuum-notifier-api/src/main/java/org/apache/maven/continuum/notification/Notifier.java
URL: http://svn.apache.org/viewvc/continuum/trunk/continuum-notifiers/continuum-notifier-api/src/main/java/org/apache/maven/continuum/notification/Notifier.java?rev=674722&view=auto
==============================================================================
--- continuum/trunk/continuum-notifiers/continuum-notifier-api/src/main/java/org/apache/maven/continuum/notification/Notifier.java (added)
+++ continuum/trunk/continuum-notifiers/continuum-notifier-api/src/main/java/org/apache/maven/continuum/notification/Notifier.java Mon Jul  7 22:17:34 2008
@@ -0,0 +1,32 @@
+package org.apache.maven.continuum.notification;
+
+/*
+ * 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.
+ */
+
+/**
+ * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
+ * @version $Id$
+ */
+public interface Notifier
+{
+    String getType();
+
+    void sendMessage( String messageId, MessageContext context )
+        throws NotificationException;
+}

Propchange: continuum/trunk/continuum-notifiers/continuum-notifier-api/src/main/java/org/apache/maven/continuum/notification/Notifier.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: continuum/trunk/continuum-notifiers/continuum-notifier-api/src/main/java/org/apache/maven/continuum/notification/Notifier.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision