View Javadoc
1   package org.apache.maven.plugin;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.File;
23  import java.util.ArrayList;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.Objects;
27  import java.util.concurrent.ConcurrentHashMap;
28  
29  import javax.inject.Named;
30  import javax.inject.Singleton;
31  
32  import org.apache.maven.artifact.Artifact;
33  import org.apache.maven.project.ExtensionDescriptor;
34  import org.apache.maven.project.MavenProject;
35  import org.codehaus.plexus.classworlds.realm.ClassRealm;
36  import org.codehaus.plexus.classworlds.realm.NoSuchRealmException;
37  import org.codehaus.plexus.personality.plexus.lifecycle.phase.Disposable;
38  
39  /**
40   * Default extension realm cache implementation. Assumes cached data does not change.
41   */
42  @Named
43  @Singleton
44  public class DefaultExtensionRealmCache
45      implements ExtensionRealmCache, Disposable
46  {
47      /**
48       * CacheKey
49       */
50      protected static class CacheKey
51          implements Key
52      {
53  
54          private final List<File> files;
55  
56          private final List<Long> timestamps;
57  
58          private final List<Long> sizes;
59  
60          private final List<String> ids;
61  
62          private final int hashCode;
63  
64          public CacheKey( List<Artifact> extensionArtifacts )
65          {
66              this.files = new ArrayList<>( extensionArtifacts.size() );
67              this.timestamps = new ArrayList<>( extensionArtifacts.size() );
68              this.sizes = new ArrayList<>( extensionArtifacts.size() );
69              this.ids = new ArrayList<>( extensionArtifacts.size() );
70  
71              for ( Artifact artifact : extensionArtifacts )
72              {
73                  File file = artifact.getFile();
74                  files.add( file );
75                  timestamps.add( ( file != null ) ? Long.valueOf( file.lastModified() ) : Long.valueOf( 0 ) );
76                  sizes.add( ( file != null ) ? Long.valueOf( file.length() ) : Long.valueOf( 0 ) );
77                  ids.add( artifact.getVersion() );
78              }
79  
80              this.hashCode =
81                  31 * files.hashCode() + 31 * ids.hashCode() + 31 * timestamps.hashCode() + 31 * sizes.hashCode();
82          }
83  
84          @Override
85          public int hashCode()
86          {
87              return hashCode;
88          }
89  
90          @Override
91          public boolean equals( Object o )
92          {
93              if ( o == this )
94              {
95                  return true;
96              }
97  
98              if ( !( o instanceof CacheKey ) )
99              {
100                 return false;
101             }
102 
103             CacheKey other = (CacheKey) o;
104 
105             return ids.equals( other.ids ) && files.equals( other.files ) && timestamps.equals( other.timestamps )
106                 && sizes.equals( other.sizes );
107         }
108 
109         @Override
110         public String toString()
111         {
112             return files.toString();
113         }
114     }
115 
116     protected final Map<Key, CacheRecord> cache = new ConcurrentHashMap<>();
117 
118     @Override
119     public Key createKey( List<Artifact> extensionArtifacts )
120     {
121         return new CacheKey( extensionArtifacts );
122     }
123 
124     public CacheRecord get( Key key )
125     {
126         return cache.get( key );
127     }
128 
129     public CacheRecord put( Key key, ClassRealm extensionRealm, ExtensionDescriptor extensionDescriptor,
130                             List<Artifact> artifacts )
131     {
132         Objects.requireNonNull( extensionRealm, "extensionRealm cannot be null" );
133 
134         if ( cache.containsKey( key ) )
135         {
136             throw new IllegalStateException( "Duplicate extension realm for extension " + key );
137         }
138 
139         CacheRecord record = new CacheRecord( extensionRealm, extensionDescriptor, artifacts );
140 
141         cache.put( key, record );
142 
143         return record;
144     }
145 
146     public void flush()
147     {
148         for ( CacheRecord record : cache.values() )
149         {
150             ClassRealm realm = record.getRealm();
151             try
152             {
153                 realm.getWorld().disposeRealm( realm.getId() );
154             }
155             catch ( NoSuchRealmException e )
156             {
157                 // ignore
158             }
159         }
160         cache.clear();
161     }
162 
163     public void register( MavenProject project, Key key, CacheRecord record )
164     {
165         // default cache does not track extension usage
166     }
167 
168     public void dispose()
169     {
170         flush();
171     }
172 
173 }