package org.codehaus.plexus.component.collections;
/*
* Copyright 2001-2006 Codehaus Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import static com.google.common.base.ReferenceType.STRONG;
import static com.google.common.base.ReferenceType.WEAK;
import com.google.common.collect.ReferenceMap;
import org.codehaus.plexus.MutablePlexusContainer;
import org.codehaus.plexus.component.repository.ComponentDescriptor;
import org.codehaus.plexus.component.repository.ComponentDescriptorListener;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import java.util.ArrayList;
import java.util.Collection;
import static java.util.Collections.unmodifiableList;
import static java.util.Collections.unmodifiableMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
public class LiveMap<T>
implements ConcurrentMap<String, T>
{
/** The reference to the PlexusContainer */
private final MutablePlexusContainer container;
/** The type of the components held by this collection */
private final Class<T> type;
/** The role hint of the components we are holding in this Collection. */
private final List<String> roleHints;
/** The component that requires this collection of components */
private final String hostComponent;
private final ConcurrentMap<String, T> components = new ReferenceMap<String, T>( STRONG, WEAK );
private final Map<String, T> immutableComponents = unmodifiableMap( components );
private final ConcurrentMap<ComponentDescriptor<? extends T>, T> componentsByDescriptor =
new ReferenceMap<ComponentDescriptor<? extends T>, T>( STRONG, WEAK );
public LiveMap( MutablePlexusContainer container, Class<T> type, List<String> roleHints, String hostComponent )
{
this.container = container;
this.type = type;
if ( roleHints == null )
{
this.roleHints = null;
}
else
{
this.roleHints = unmodifiableList( new ArrayList<String>( roleHints ) );
}
this.hostComponent = hostComponent;
container.addComponentDescriptorListener( new LiveMapDescriptorListener() );
}
public String getHostComponent()
{
return hostComponent;
}
public boolean isEmpty()
{
return immutableComponents.isEmpty();
}
public int size()
{
return immutableComponents.size();
}
public boolean containsKey( Object key )
{
return immutableComponents.containsKey( key );
}
public boolean containsValue( Object value )
{
return immutableComponents.containsValue( value );
}
public T get( Object key )
{
return immutableComponents.get( key );
}
public Set<String> keySet()
{
return immutableComponents.keySet();
}
public Collection<T> values()
{
return immutableComponents.values();
}
public Set<Entry<String, T>> entrySet()
{
return immutableComponents.entrySet();
}
public boolean equals( Object o )
{
return this == o || ( o instanceof Map && immutableComponents.equals( o ) );
}
public int hashCode()
{
return immutableComponents.hashCode();
}
public String toString()
{
return immutableComponents.toString();
}
//
// Unsupported Operations -- Map is immutable
//
public T put( String key, T value )
{
throw new UnsupportedOperationException();
}
public T putIfAbsent( String key, T value )
{
throw new UnsupportedOperationException();
}
public void putAll( Map<? extends String, ? extends T> t )
{
throw new UnsupportedOperationException();
}
public T remove( Object k )
{
throw new UnsupportedOperationException();
}
public boolean remove( Object key, Object value )
{
throw new UnsupportedOperationException();
}
public boolean replace( String key, T oldValue, T newValue )
{
throw new UnsupportedOperationException();
}
public T replace( String key, T value )
{
throw new UnsupportedOperationException();
}
public void clear()
{
throw new UnsupportedOperationException();
}
private class LiveMapDescriptorListener implements ComponentDescriptorListener<T>
{
public Class<T> getType()
{
return type;
}
public List<String> getRoleHints()
{
return roleHints;
}
public synchronized void componentDescriptorAdded( ComponentDescriptor<? extends T> descriptor )
{
String roleHint = descriptor.getRoleHint();
if ( !components.containsKey( roleHint ) && ( roleHints == null || roleHints.contains( roleHint ) ) )
{
T component = null;
try
{
component = container.lookup( descriptor );
}
catch ( ComponentLookupException ignored )
{
// ignored - component can't be created which
}
components.put( roleHint, component );
componentsByDescriptor.put( descriptor, component );
}
}
public synchronized void componentDescriptorRemoved( ComponentDescriptor<? extends T> descriptor )
{
T component = componentsByDescriptor.remove( descriptor );
if ( component != null )
{
components.remove( descriptor.getRoleHint(), component );
}
}
}
}