001package 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 022import java.util.ArrayList; 023import java.util.HashMap; 024import java.util.List; 025import java.util.Map; 026 027import org.apache.maven.artifact.ArtifactUtils; 028import org.apache.maven.model.Plugin; 029import org.apache.maven.plugin.descriptor.MojoDescriptor; 030import org.apache.maven.plugin.descriptor.PluginDescriptor; 031import org.codehaus.plexus.component.annotations.Component; 032import org.codehaus.plexus.component.repository.ComponentDescriptor; 033import org.eclipse.aether.RepositorySystemSession; 034import org.eclipse.aether.repository.LocalRepository; 035import org.eclipse.aether.repository.RemoteRepository; 036import org.eclipse.aether.repository.WorkspaceRepository; 037 038/** 039 * Caches raw plugin descriptors. A raw plugin descriptor is a descriptor that has just been extracted from the plugin 040 * artifact and does not contain any runtime specific data. The cache must not be used for descriptors that hold runtime 041 * data like the plugin realm. <strong>Warning:</strong> This is an internal utility interface that is only public for 042 * technical reasons, it is not part of the public API. In particular, this interface can be changed or deleted without 043 * prior notice. 044 * 045 * @since 3.0 046 * @author Benjamin Bentmann 047 */ 048@Component( role = PluginDescriptorCache.class ) 049public class DefaultPluginDescriptorCache 050 implements PluginDescriptorCache 051{ 052 053 private Map<Key, PluginDescriptor> descriptors = new HashMap<Key, PluginDescriptor>( 128 ); 054 055 public void flush() 056 { 057 descriptors.clear(); 058 } 059 060 public Key createKey( Plugin plugin, List<RemoteRepository> repositories, RepositorySystemSession session ) 061 { 062 return new CacheKey( plugin, repositories, session ); 063 } 064 065 public PluginDescriptor get( Key cacheKey ) 066 { 067 return clone( descriptors.get( cacheKey ) ); 068 } 069 070 public void put( Key cacheKey, PluginDescriptor pluginDescriptor ) 071 { 072 descriptors.put( cacheKey, clone( pluginDescriptor ) ); 073 } 074 075 protected static PluginDescriptor clone( PluginDescriptor original ) 076 { 077 PluginDescriptor clone = null; 078 079 if ( original != null ) 080 { 081 clone = new PluginDescriptor(); 082 083 clone.setGroupId( original.getGroupId() ); 084 clone.setArtifactId( original.getArtifactId() ); 085 clone.setVersion( original.getVersion() ); 086 clone.setGoalPrefix( original.getGoalPrefix() ); 087 clone.setInheritedByDefault( original.isInheritedByDefault() ); 088 089 clone.setName( original.getName() ); 090 clone.setDescription( original.getDescription() ); 091 clone.setRequiredMavenVersion( original.getRequiredMavenVersion() ); 092 093 clone.setPluginArtifact( ArtifactUtils.copyArtifactSafe( original.getPluginArtifact() ) ); 094 095 clone.setComponents( clone( original.getMojos(), clone ) ); 096 clone.setId( original.getId() ); 097 clone.setIsolatedRealm( original.isIsolatedRealm() ); 098 clone.setSource( original.getSource() ); 099 100 clone.setDependencies( original.getDependencies() ); 101 } 102 103 return clone; 104 } 105 106 private static List<ComponentDescriptor<?>> clone( List<MojoDescriptor> mojos, PluginDescriptor pluginDescriptor ) 107 { 108 List<ComponentDescriptor<?>> clones = null; 109 110 if ( mojos != null ) 111 { 112 clones = new ArrayList<ComponentDescriptor<?>>( mojos.size() ); 113 114 for ( MojoDescriptor mojo : mojos ) 115 { 116 MojoDescriptor clone = mojo.clone(); 117 clone.setPluginDescriptor( pluginDescriptor ); 118 clones.add( clone ); 119 } 120 } 121 122 return clones; 123 } 124 125 private static final class CacheKey 126 implements Key 127 { 128 129 private final String groupId; 130 131 private final String artifactId; 132 133 private final String version; 134 135 private final WorkspaceRepository workspace; 136 137 private final LocalRepository localRepo; 138 139 private final List<RemoteRepository> repositories; 140 141 private final int hashCode; 142 143 public CacheKey( Plugin plugin, List<RemoteRepository> repositories, RepositorySystemSession session ) 144 { 145 groupId = plugin.getGroupId(); 146 artifactId = plugin.getArtifactId(); 147 version = plugin.getVersion(); 148 149 workspace = CacheUtils.getWorkspace( session ); 150 localRepo = session.getLocalRepository(); 151 this.repositories = new ArrayList<RemoteRepository>( repositories.size() ); 152 for ( RemoteRepository repository : repositories ) 153 { 154 if ( repository.isRepositoryManager() ) 155 { 156 this.repositories.addAll( repository.getMirroredRepositories() ); 157 } 158 else 159 { 160 this.repositories.add( repository ); 161 } 162 } 163 164 int hash = 17; 165 hash = hash * 31 + groupId.hashCode(); 166 hash = hash * 31 + artifactId.hashCode(); 167 hash = hash * 31 + version.hashCode(); 168 hash = hash * 31 + hash( workspace ); 169 hash = hash * 31 + localRepo.hashCode(); 170 hash = hash * 31 + CacheUtils.repositoriesHashCode( repositories ); 171 this.hashCode = hash; 172 } 173 174 @Override 175 public int hashCode() 176 { 177 return hashCode; 178 } 179 180 @Override 181 public boolean equals( Object obj ) 182 { 183 if ( this == obj ) 184 { 185 return true; 186 } 187 188 if ( !( obj instanceof CacheKey ) ) 189 { 190 return false; 191 } 192 193 CacheKey that = (CacheKey) obj; 194 195 return eq( this.artifactId, that.artifactId ) && eq( this.groupId, that.groupId ) 196 && eq( this.version, that.version ) && eq( this.localRepo, that.localRepo ) 197 && eq( this.workspace, that.workspace ) 198 && CacheUtils.repositoriesEquals( this.repositories, that.repositories ); 199 } 200 201 @Override 202 public String toString() 203 { 204 return groupId + ':' + artifactId + ':' + version; 205 } 206 207 private static int hash( Object obj ) 208 { 209 return obj != null ? obj.hashCode() : 0; 210 } 211 212 private static <T> boolean eq( T s1, T s2 ) 213 { 214 return s1 != null ? s1.equals( s2 ) : s2 == null; 215 } 216 217 } 218 219}