001package org.apache.maven.project;
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.Collections;
023import java.util.List;
024import java.util.Map;
025import java.util.concurrent.ConcurrentHashMap;
026
027import org.apache.commons.lang3.Validate;
028import org.codehaus.plexus.classworlds.realm.ClassRealm;
029import org.codehaus.plexus.classworlds.realm.NoSuchRealmException;
030import org.codehaus.plexus.component.annotations.Component;
031import org.codehaus.plexus.personality.plexus.lifecycle.phase.Disposable;
032import org.eclipse.aether.graph.DependencyFilter;
033
034/**
035 * Default project realm cache implementation. Assumes cached data does not change.
036 */
037@Component( role = ProjectRealmCache.class )
038public class DefaultProjectRealmCache
039    implements ProjectRealmCache, Disposable
040{
041
042    protected static class CacheKey
043        implements Key
044    {
045
046        private final List<? extends ClassRealm> extensionRealms;
047
048        private final int hashCode;
049
050        public CacheKey( List<? extends ClassRealm> extensionRealms )
051        {
052            this.extensionRealms = ( extensionRealms != null ) ? extensionRealms : Collections.<ClassRealm>emptyList();
053
054            this.hashCode = this.extensionRealms.hashCode();
055        }
056
057        @Override
058        public int hashCode()
059        {
060            return hashCode;
061        }
062
063        @Override
064        public boolean equals( Object o )
065        {
066            if ( o == this )
067            {
068                return true;
069            }
070
071            if ( !( o instanceof CacheKey ) )
072            {
073                return false;
074            }
075
076            CacheKey other = (CacheKey) o;
077
078            return extensionRealms.equals( other.extensionRealms );
079        }
080
081        @Override
082        public String toString()
083        {
084            return extensionRealms.toString();
085        }
086    }
087
088    protected final Map<Key, CacheRecord> cache = new ConcurrentHashMap<>();
089
090    @Override
091    public Key createKey( List<? extends ClassRealm> extensionRealms )
092    {
093        return new CacheKey( extensionRealms );
094    }
095
096    public CacheRecord get( Key key )
097    {
098        return cache.get( key );
099    }
100
101    public CacheRecord put( Key key, ClassRealm projectRealm, DependencyFilter extensionArtifactFilter )
102    {
103        Validate.notNull( projectRealm, "projectRealm cannot be null" );
104
105        if ( cache.containsKey( key ) )
106        {
107            throw new IllegalStateException( "Duplicate project realm for extensions " + key );
108        }
109
110        CacheRecord record = new CacheRecord( projectRealm, extensionArtifactFilter );
111
112        cache.put( key, record );
113
114        return record;
115    }
116
117    public void flush()
118    {
119        for ( CacheRecord record : cache.values() )
120        {
121            ClassRealm realm = record.realm;
122            try
123            {
124                realm.getWorld().disposeRealm( realm.getId() );
125            }
126            catch ( NoSuchRealmException e )
127            {
128                // ignore
129            }
130        }
131        cache.clear();
132    }
133
134    public void register( MavenProject project, Key key, CacheRecord record )
135    {
136        // default cache does not track record usage
137    }
138
139    @Override
140    public void dispose()
141    {
142        flush();
143    }
144
145}