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