001    package org.apache.maven.plugin;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     *  http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    import java.util.ArrayList;
023    import java.util.Collections;
024    import java.util.List;
025    import java.util.Map;
026    import java.util.concurrent.ConcurrentHashMap;
027    
028    import org.apache.maven.artifact.Artifact;
029    import org.apache.maven.model.Plugin;
030    import org.apache.maven.project.MavenProject;
031    import org.codehaus.plexus.classworlds.realm.ClassRealm;
032    import org.codehaus.plexus.component.annotations.Component;
033    import org.sonatype.aether.RepositorySystemSession;
034    import org.sonatype.aether.graph.DependencyFilter;
035    import org.sonatype.aether.repository.LocalRepository;
036    import org.sonatype.aether.repository.RemoteRepository;
037    import org.sonatype.aether.repository.WorkspaceRepository;
038    
039    /**
040     * Default PluginCache implementation. Assumes cached data does not change.
041     */
042    @Component( role = PluginRealmCache.class )
043    public class DefaultPluginRealmCache
044        implements PluginRealmCache
045    {
046    
047        protected static class CacheKey
048            implements Key
049        {
050    
051            private final Plugin plugin;
052    
053            private final WorkspaceRepository workspace;
054    
055            private final LocalRepository localRepo;
056    
057            private final List<RemoteRepository> repositories;
058    
059            private final ClassLoader parentRealm;
060    
061            private final Map<String, ClassLoader> foreignImports;
062    
063            private final DependencyFilter filter;
064    
065            private final int hashCode;
066    
067            public CacheKey( Plugin plugin, ClassLoader parentRealm, Map<String, ClassLoader> foreignImports,
068                             DependencyFilter dependencyFilter, List<RemoteRepository> repositories,
069                             RepositorySystemSession session )
070            {
071                this.plugin = plugin.clone();
072                this.workspace = CacheUtils.getWorkspace( session );
073                this.localRepo = session.getLocalRepository();
074                this.repositories = new ArrayList<RemoteRepository>( repositories.size() );
075                for ( RemoteRepository repository : repositories )
076                {
077                    if ( repository.isRepositoryManager() )
078                    {
079                        this.repositories.addAll( repository.getMirroredRepositories() );
080                    }
081                    else
082                    {
083                        this.repositories.add( repository );
084                    }
085                }
086                this.parentRealm = parentRealm;
087                this.foreignImports =
088                    ( foreignImports != null ) ? foreignImports : Collections.<String, ClassLoader> emptyMap();
089                this.filter = dependencyFilter;
090    
091                int hash = 17;
092                hash = hash * 31 + CacheUtils.pluginHashCode( plugin );
093                hash = hash * 31 + hash( workspace );
094                hash = hash * 31 + hash( localRepo );
095                hash = hash * 31 + CacheUtils.repositoriesHashCode( repositories );
096                hash = hash * 31 + hash( parentRealm );
097                hash = hash * 31 + this.foreignImports.hashCode();
098                hash = hash * 31 + hash( dependencyFilter );
099                this.hashCode = hash;
100            }
101    
102            @Override
103            public String toString()
104            {
105                return plugin.getId();
106            }
107    
108            @Override
109            public int hashCode()
110            {
111                return hashCode;
112            }
113    
114            private static int hash( Object obj )
115            {
116                return obj != null ? obj.hashCode() : 0;
117            }
118    
119            @Override
120            public boolean equals( Object o )
121            {
122                if ( o == this )
123                {
124                    return true;
125                }
126    
127                if ( !( o instanceof CacheKey ) )
128                {
129                    return false;
130                }
131    
132                CacheKey that = (CacheKey) o;
133    
134                return parentRealm == that.parentRealm && CacheUtils.pluginEquals( plugin, that.plugin )
135                    && eq( workspace, that.workspace ) && eq( localRepo, that.localRepo )
136                    && CacheUtils.repositoriesEquals( this.repositories, that.repositories ) && eq( filter, that.filter )
137                    && eq( foreignImports, that.foreignImports );
138            }
139    
140            private static <T> boolean eq( T s1, T s2 )
141            {
142                return s1 != null ? s1.equals( s2 ) : s2 == null;
143            }
144    
145        }
146    
147        protected final Map<Key, CacheRecord> cache = new ConcurrentHashMap<Key, CacheRecord>();
148    
149        public Key createKey( Plugin plugin, ClassLoader parentRealm, Map<String, ClassLoader> foreignImports,
150                              DependencyFilter dependencyFilter, List<RemoteRepository> repositories,
151                              RepositorySystemSession session )
152        {
153            return new CacheKey( plugin, parentRealm, foreignImports, dependencyFilter, repositories, session );
154        }
155    
156        public CacheRecord get( Key key )
157        {
158            return cache.get( key );
159        }
160    
161        public CacheRecord put( Key key, ClassRealm pluginRealm, List<Artifact> pluginArtifacts )
162        {
163            if ( pluginRealm == null || pluginArtifacts == null )
164            {
165                throw new IllegalArgumentException();
166            }
167    
168            if ( cache.containsKey( key ) )
169            {
170                throw new IllegalStateException( "Duplicate plugin realm for plugin " + key );
171            }
172    
173            CacheRecord record = new CacheRecord( pluginRealm, pluginArtifacts );
174    
175            cache.put( key, record );
176    
177            return record;
178        }
179    
180        public void flush()
181        {
182            cache.clear();
183        }
184    
185        protected static int pluginHashCode( Plugin plugin )
186        {
187            return CacheUtils.pluginHashCode( plugin );
188        }
189    
190        protected static boolean pluginEquals( Plugin a, Plugin b )
191        {
192            return CacheUtils.pluginEquals( a, b );
193        }
194    
195        public void register( MavenProject project, CacheRecord record )
196        {
197            // default cache does not track plugin usage
198        }
199    
200    }