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 }