Skip to content

Commit

Permalink
[MRESOLVER-227] Refactor NamedLockFactorySelector to a managed component
Browse files Browse the repository at this point in the history
This closes #135
  • Loading branch information
cstamas authored and michael-o committed Nov 23, 2021
1 parent d024af7 commit b7a5b41
Show file tree
Hide file tree
Showing 8 changed files with 236 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@
import org.eclipse.aether.internal.impl.SimpleLocalRepositoryManagerFactory;
import org.eclipse.aether.internal.impl.slf4j.Slf4jLoggerFactory;
import org.eclipse.aether.internal.impl.synccontext.DefaultSyncContextFactory;
import org.eclipse.aether.internal.impl.synccontext.NamedLockFactorySelector;
import org.eclipse.aether.internal.impl.synccontext.named.NamedLockFactorySelector;
import org.eclipse.aether.internal.impl.synccontext.named.SimpleNamedLockFactorySelector;
import org.eclipse.aether.spi.connector.checksum.ChecksumPolicyProvider;
import org.eclipse.aether.spi.connector.layout.RepositoryLayoutFactory;
import org.eclipse.aether.spi.connector.layout.RepositoryLayoutProvider;
Expand Down Expand Up @@ -222,7 +223,7 @@ public DefaultServiceLocator()
addService( LocalRepositoryManagerFactory.class, EnhancedLocalRepositoryManagerFactory.class );
addService( LoggerFactory.class, Slf4jLoggerFactory.class );
addService( TrackingFileManager.class, DefaultTrackingFileManager.class );
addService( NamedLockFactorySelector.class, NamedLockFactorySelector.class );
addService( NamedLockFactorySelector.class, SimpleNamedLockFactorySelector.class );
}

private <T> Entry<T> getEntry( Class<T> type, boolean create )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@
import org.eclipse.aether.internal.impl.DefaultTrackingFileManager;
import org.eclipse.aether.internal.impl.TrackingFileManager;
import org.eclipse.aether.internal.impl.synccontext.DefaultSyncContextFactory;
import org.eclipse.aether.internal.impl.synccontext.NamedLockFactorySelector;
import org.eclipse.aether.internal.impl.synccontext.named.NamedLockFactorySelector;
import org.eclipse.aether.internal.impl.synccontext.named.SimpleNamedLockFactorySelector;
import org.eclipse.aether.internal.impl.synccontext.named.GAVNameMapper;
import org.eclipse.aether.internal.impl.synccontext.named.DiscriminatingNameMapper;
import org.eclipse.aether.internal.impl.synccontext.named.NameMapper;
Expand Down Expand Up @@ -158,7 +159,7 @@ protected void configure()
.to( EnhancedLocalRepositoryManagerFactory.class ).in( Singleton.class );
bind( TrackingFileManager.class ).to( DefaultTrackingFileManager.class ).in( Singleton.class );

bind( NamedLockFactorySelector.class ).in( Singleton.class );
bind( NamedLockFactorySelector.class ).to( SimpleNamedLockFactorySelector.class ).in( Singleton.class );
bind( SyncContextFactory.class ).to( DefaultSyncContextFactory.class ).in( Singleton.class );
bind( org.eclipse.aether.impl.SyncContextFactory.class )
.to( org.eclipse.aether.internal.impl.synccontext.legacy.DefaultSyncContextFactory.class )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.SyncContext;
import org.eclipse.aether.internal.impl.synccontext.named.NamedLockFactoryAdapter;
import org.eclipse.aether.internal.impl.synccontext.named.NamedLockFactorySelector;
import org.eclipse.aether.spi.locator.Service;
import org.eclipse.aether.spi.locator.ServiceLocator;
import org.eclipse.aether.spi.synccontext.SyncContextFactory;
Expand All @@ -53,9 +54,7 @@ public DefaultSyncContextFactory( final NamedLockFactorySelector selector )
{
this.namedLockFactoryAdapter = new NamedLockFactoryAdapter(
selector.getSelectedNameMapper(),
selector.getSelectedNamedLockFactory(),
NamedLockFactorySelector.TIME,
NamedLockFactorySelector.TIME_UNIT
selector.getSelectedNamedLockFactory()
);
}

Expand All @@ -71,9 +70,7 @@ public void initService( final ServiceLocator locator )
locator.getService( NamedLockFactorySelector.class ) );
this.namedLockFactoryAdapter = new NamedLockFactoryAdapter(
selector.getSelectedNameMapper(),
selector.getSelectedNamedLockFactory(),
NamedLockFactorySelector.TIME,
NamedLockFactorySelector.TIME_UNIT
selector.getSelectedNamedLockFactory()
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.eclipse.aether.metadata.Metadata;
import org.eclipse.aether.named.NamedLock;
import org.eclipse.aether.named.NamedLockFactory;
import org.eclipse.aether.util.ConfigUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -39,30 +40,27 @@
*/
public final class NamedLockFactoryAdapter
{
private final NameMapper nameMapper;
public static final String TIME_KEY = "aether.syncContext.named.time";

private final NamedLockFactory namedLockFactory;
public static final long DEFAULT_TIME = 30L;

private final long time;
public static final String TIME_UNIT_KEY = "aether.syncContext.named.time.unit";

private final TimeUnit timeUnit;
public static final TimeUnit DEFAULT_TIME_UNIT = TimeUnit.SECONDS;

public NamedLockFactoryAdapter( final NameMapper nameMapper, final NamedLockFactory namedLockFactory,
final long time, final TimeUnit timeUnit )
private final NameMapper nameMapper;

private final NamedLockFactory namedLockFactory;

public NamedLockFactoryAdapter( final NameMapper nameMapper, final NamedLockFactory namedLockFactory )
{
this.nameMapper = Objects.requireNonNull( nameMapper );
this.namedLockFactory = Objects.requireNonNull( namedLockFactory );
if ( time < 0L )
{
throw new IllegalArgumentException( "time cannot be negative" );
}
this.time = time;
this.timeUnit = Objects.requireNonNull( timeUnit );
}

public SyncContext newInstance( final RepositorySystemSession session, final boolean shared )
{
return new AdaptedLockSyncContext( session, shared, nameMapper, namedLockFactory, time, timeUnit );
return new AdaptedLockSyncContext( session, shared, nameMapper, namedLockFactory );
}

public void shutdown()
Expand All @@ -80,8 +78,6 @@ private static class AdaptedLockSyncContext implements SyncContext

private final NameMapper lockNaming;

private final SessionAwareNamedLockFactory sessionAwareNamedLockFactory;

private final NamedLockFactory namedLockFactory;

private final long time;
Expand All @@ -91,18 +87,32 @@ private static class AdaptedLockSyncContext implements SyncContext
private final Deque<NamedLock> locks;

private AdaptedLockSyncContext( final RepositorySystemSession session, final boolean shared,
final NameMapper lockNaming, final NamedLockFactory namedLockFactory,
final long time, final TimeUnit timeUnit )
final NameMapper lockNaming, final NamedLockFactory namedLockFactory )
{
this.session = session;
this.shared = shared;
this.lockNaming = lockNaming;
this.sessionAwareNamedLockFactory = namedLockFactory instanceof SessionAwareNamedLockFactory
? (SessionAwareNamedLockFactory) namedLockFactory : null;
this.namedLockFactory = namedLockFactory;
this.time = time;
this.timeUnit = timeUnit;
this.time = getTime( session );
this.timeUnit = getTimeUnit( session );
this.locks = new ArrayDeque<>();

if ( time < 0L )
{
throw new IllegalArgumentException( "time cannot be negative" );
}
}

private long getTime( final RepositorySystemSession session )
{
return ConfigUtils.getLong( session, DEFAULT_TIME, TIME_KEY );
}

private TimeUnit getTimeUnit( final RepositorySystemSession session )
{
return TimeUnit.valueOf( ConfigUtils.getString(
session, DEFAULT_TIME_UNIT.name(), TIME_UNIT_KEY
) );
}

@Override
Expand All @@ -118,8 +128,7 @@ public void acquire( Collection<? extends Artifact> artifacts, Collection<? exte
int acquiredLockCount = 0;
for ( String key : keys )
{
NamedLock namedLock = sessionAwareNamedLockFactory != null ? sessionAwareNamedLockFactory
.getLock( session, key ) : namedLockFactory.getLock( key );
NamedLock namedLock = namedLockFactory.getLock( key );
try
{
LOGGER.trace( "Acquiring {} lock for '{}'",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,21 @@
* under the License.
*/

import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.named.NamedLock;
import org.eclipse.aether.named.NamedLockFactory;

/**
* A {@link NamedLockFactory} that wants to make use of {@link RepositorySystemSession}.
* Selector for {@link NamedLockFactory} and {@link NameMapper} that selects and exposes selected ones. Essentially
* all the named locks configuration is here. Implementations may use different strategies to perform selection.
*/
public interface SessionAwareNamedLockFactory extends NamedLockFactory
public interface NamedLockFactorySelector
{
/**
* Creates or reuses existing {@link NamedLock}. Returns instance MUST BE treated as "resource", best in
* try-with-resource block.
*
* @param session the repository system session, must not be {@code null}
* @param name the lock name, must not be {@code null}
* @return named the lock instance, never {@code null}
* Returns the selected {@link NamedLockFactory}, never null.
*/
NamedLock getLock( RepositorySystemSession session, String name );
NamedLockFactory getSelectedNamedLockFactory();

/**
* Returns the selected {@link NameMapper}, never null.
*/
NameMapper getSelectedNameMapper();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package org.eclipse.aether.internal.impl.synccontext.named;

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.eclipse.aether.named.NamedLockFactory;
import org.eclipse.aether.named.providers.LocalReadWriteLockNamedLockFactory;
import org.eclipse.aether.named.providers.LocalSemaphoreNamedLockFactory;
import org.eclipse.aether.named.providers.NoopNamedLockFactory;

import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import java.util.HashMap;
import java.util.Map;

/**
* Simple selector implementation that uses Java system properties and sane default values.
*/
@Singleton
@Named
public final class SimpleNamedLockFactorySelector
implements NamedLockFactorySelector
{
public static final String FACTORY_KEY = "aether.syncContext.named.factory";

public static final String NAME_MAPPER_KEY = "aether.syncContext.named.nameMapper";

private final NamedLockFactory namedLockFactory;

private final NameMapper nameMapper;

/**
* Constructor used with DI, where factories are injected and selected based on key.
*/
@Inject
public SimpleNamedLockFactorySelector( final Map<String, NamedLockFactory> factories,
final Map<String, NameMapper> nameMappers )
{
this.namedLockFactory = selectNamedLockFactory( factories, getFactoryName() );
this.nameMapper = selectNameMapper( nameMappers, getNameMapperName() );
}

/**
* Returns selected factory name (or sane default) using System property value of {@link #FACTORY_KEY} and defaults
* to {@link LocalReadWriteLockNamedLockFactory#NAME}.
*/
private String getFactoryName()
{
return System.getProperty( FACTORY_KEY, LocalReadWriteLockNamedLockFactory.NAME );
}

/**
* Returns selected name mapper name (or sane default) using System property value of {@link #NAME_MAPPER_KEY} and
* defaults to {@link GAVNameMapper#NAME}.
*/
private String getNameMapperName()
{
return System.getProperty( NAME_MAPPER_KEY, GAVNameMapper.NAME );
}

/**
* Default constructor for ServiceLocator.
*/
public SimpleNamedLockFactorySelector()
{
Map<String, NamedLockFactory> factories = new HashMap<>();
factories.put( NoopNamedLockFactory.NAME, new NoopNamedLockFactory() );
factories.put( LocalReadWriteLockNamedLockFactory.NAME, new LocalReadWriteLockNamedLockFactory() );
factories.put( LocalSemaphoreNamedLockFactory.NAME, new LocalSemaphoreNamedLockFactory() );
this.namedLockFactory = selectNamedLockFactory( factories, getFactoryName() );

Map<String, NameMapper> nameMappers = new HashMap<>();
nameMappers.put( StaticNameMapper.NAME, new StaticNameMapper() );
nameMappers.put( GAVNameMapper.NAME, new GAVNameMapper() );
nameMappers.put( DiscriminatingNameMapper.NAME, new DiscriminatingNameMapper( new GAVNameMapper() ) );
this.nameMapper = selectNameMapper( nameMappers, getNameMapperName() );
}

/**
* Returns the selected {@link NamedLockFactory}, never null.
*/
@Override
public NamedLockFactory getSelectedNamedLockFactory()
{
return namedLockFactory;
}

/**
* Returns the selected {@link NameMapper}, never null.
*/
@Override
public NameMapper getSelectedNameMapper()
{
return nameMapper;
}

private NamedLockFactory selectNamedLockFactory( final Map<String, NamedLockFactory> factories,
final String factoryName )
{
NamedLockFactory factory = factories.get( factoryName );
if ( factory == null )
{
throw new IllegalArgumentException( "Unknown NamedLockFactory name: " + factoryName
+ ", known ones: " + factories.keySet() );
}
return factory;
}

private NameMapper selectNameMapper( final Map<String, NameMapper> nameMappers,
final String mapperName )
{
NameMapper nameMapper = nameMappers.get( mapperName );
if ( nameMapper == null )
{
throw new IllegalArgumentException( "Unknown NameMapper name: " + mapperName
+ ", known ones: " + nameMappers.keySet() );
}
return nameMapper;
}
}

0 comments on commit b7a5b41

Please sign in to comment.