View Javadoc
1   package com.soebes.maven.extensions;
2   
3   import java.io.BufferedWriter;
4   import java.io.File;
5   import java.io.FileWriter;
6   import java.io.IOException;
7   import java.util.ArrayList;
8   import java.util.List;
9   import java.util.Properties;
10  
11  import javax.inject.Named;
12  import javax.inject.Singleton;
13  
14  import org.apache.maven.eventspy.AbstractEventSpy;
15  import org.apache.maven.execution.ExecutionEvent;
16  import org.apache.maven.execution.ExecutionEvent.Type;
17  import org.eclipse.aether.RepositoryEvent;
18  import org.eclipse.aether.RepositoryEvent.EventType;
19  import org.eclipse.aether.artifact.Artifact;
20  import org.slf4j.Logger;
21  import org.slf4j.LoggerFactory;
22  
23  /**
24   * @author Karl Heinz Marbaise <a href="mailto:khmarbaise@apache.org">khmarbaise@apache.org</a>
25   */
26  @Named
27  @Singleton
28  public class DeploymentRecorderExtension
29      extends AbstractEventSpy
30  {
31      private static final String DPRE = "deployment-recorder-extension";
32      
33      private final Logger LOGGER = LoggerFactory.getLogger( getClass() );
34  
35      private File rootDirectory;
36  
37      private List<Artifact> recordedDeploys;
38  
39      public DeploymentRecorderExtension()
40      {
41          LOGGER.debug( "{} ctor called.", DPRE );
42          this.recordedDeploys = new ArrayList<>();
43      }
44  
45      @Override
46      public void init( Context context )
47          throws Exception
48      {
49          super.init( context );
50          LOGGER.info( "{} Version {} started.", DPRE, DeploymentRecorderExtensionVersion.getVersion() );
51  
52          // Is this always in the context? Based on Maven Core yes.
53          String workingDirectory = (String) context.getData().get( "workingDirectory" );
54          LOGGER.debug( "{}: workingDirectory: {}", DPRE, workingDirectory );
55  
56          Properties systemProperties = (Properties) context.getData().get( "systemProperties" );
57          // This is only available from 3.3.+
58          String multiModuleProjectDirectory = systemProperties.getProperty( "maven.multiModuleProjectDirectory" );
59          rootDirectory = new File( multiModuleProjectDirectory );
60          LOGGER.debug( "{}: multiModuleProjectDirectory: {}", DPRE, multiModuleProjectDirectory );
61      }
62  
63      @Override
64      public void onEvent( Object event )
65          throws Exception
66      {
67          try
68          {
69              if ( event instanceof ExecutionEvent )
70              {
71                  executionEventHandler( (ExecutionEvent) event );
72              }
73              else if ( event instanceof org.eclipse.aether.RepositoryEvent )
74              {
75                  repositoryEventHandler( (RepositoryEvent) event );
76              }
77              else
78              {
79                  // TODO: What kind of event we haven't considered?
80                  LOGGER.debug( "{}: Event {}", DPRE, event.getClass().getCanonicalName() );
81              }
82          }
83          catch ( Exception e )
84          {
85              LOGGER.error( DPRE + ": Exception", e );
86          }
87      }
88  
89      @Override
90      public void close()
91      {
92          LOGGER.debug( "{}: done.", DPRE );
93      }
94  
95      private String getId( Artifact artifact )
96      {
97          StringBuilder sb = new StringBuilder( artifact.getGroupId() );
98          sb.append( ':' );
99          sb.append( artifact.getArtifactId() );
100         sb.append( ':' );
101         sb.append( artifact.getExtension() );
102         sb.append( ':' );
103         sb.append( artifact.getVersion() );
104         sb.append( ':' );
105         sb.append( artifact.getBaseVersion() );
106         // classifier can be != null but empty!
107         if ( artifact.getClassifier() != null && artifact.getClassifier().trim().length() > 0)
108         {
109             sb.append( ':' );
110             sb.append( artifact.getClassifier() );
111         }
112         return sb.toString();
113     }
114 
115     private void repositoryEventHandler( org.eclipse.aether.RepositoryEvent repositoryEvent )
116     {
117         EventType type = repositoryEvent.getType();
118         switch ( type )
119         {
120             case ARTIFACT_DEPLOYED:
121                 recordedDeploys.add( repositoryEvent.getArtifact() );
122                 break;
123 
124             case ARTIFACT_DOWNLOADING:
125             case ARTIFACT_DOWNLOADED:
126             case ARTIFACT_DEPLOYING:
127             case ARTIFACT_INSTALLING:
128             case ARTIFACT_INSTALLED:
129             case METADATA_DEPLOYING:
130             case METADATA_DEPLOYED:
131             case METADATA_DOWNLOADING:
132             case METADATA_DOWNLOADED:
133             case METADATA_INSTALLING:
134             case METADATA_INSTALLED:
135             case ARTIFACT_RESOLVING:
136             case ARTIFACT_RESOLVED:
137             case ARTIFACT_DESCRIPTOR_INVALID:
138             case ARTIFACT_DESCRIPTOR_MISSING:
139             case METADATA_RESOLVED:
140             case METADATA_RESOLVING:
141             case METADATA_INVALID:
142                 // Those events are not recorded.
143                 break;
144 
145             default:
146                 LOGGER.error( "{}: repositoryEventHandler {}", DPRE, type );
147                 break;
148         }
149     }
150 
151     private void writeDeploymentRecorderFile()
152     {
153         //TODO: Make it configurable?
154         File target = new File( this.rootDirectory, "target" );
155 
156         if ( !target.exists() )
157         {
158             target.mkdirs();
159         }
160         //TODO: Make this name configurable?
161         File recorderFile = new File( target, "deploy-recorder.lst" );
162 
163         try ( FileWriter fw = new FileWriter( recorderFile ); BufferedWriter bos = new BufferedWriter( fw ) )
164         {
165             for ( Artifact artifact : recordedDeploys )
166             {
167                 bos.write( getId( artifact ) );
168                 bos.newLine();
169             }
170         }
171         catch ( IOException e )
172         {
173             LOGGER.error( "IOException", e );
174         }
175     }
176 
177     private void executionEventHandler( ExecutionEvent executionEvent )
178     {
179         Type type = executionEvent.getType();
180         switch ( type )
181         {
182             case SessionEnded:
183                 writeDeploymentRecorderFile();
184                 break;
185 
186             case ProjectDiscoveryStarted:
187             case SessionStarted:
188             case ForkStarted:
189             case ForkFailed:
190             case ForkSucceeded:
191             case ForkedProjectStarted:
192             case ForkedProjectFailed:
193             case ForkedProjectSucceeded:
194             case MojoStarted:
195             case MojoFailed:
196             case MojoSucceeded:
197             case MojoSkipped:
198             case ProjectStarted:
199             case ProjectFailed:
200             case ProjectSucceeded:
201             case ProjectSkipped:
202                 break;
203 
204             default:
205                 LOGGER.error( "{}: executionEventHandler: {}", DPRE, type );
206                 break;
207         }
208 
209     }
210 
211 }