mirror of https://github.com/apache/maven.git
[MNG-7459] Revert "[MNG-7347] SessionScoped beans should be singletons for a given session (#621)"
This reverts commit faf5d5d274
.
This commit is contained in:
parent
3dd0afd897
commit
1c22f94522
|
@ -89,12 +89,8 @@ public class LifecycleModuleBuilder
|
||||||
|
|
||||||
// session may be different from rootSession seeded in DefaultMaven
|
// session may be different from rootSession seeded in DefaultMaven
|
||||||
// explicitly seed the right session here to make sure it is used by Guice
|
// explicitly seed the right session here to make sure it is used by Guice
|
||||||
final boolean scoped = session != rootSession;
|
sessionScope.enter( reactorContext.getSessionScopeMemento() );
|
||||||
if ( scoped )
|
|
||||||
{
|
|
||||||
sessionScope.enter();
|
|
||||||
sessionScope.seed( MavenSession.class, session );
|
sessionScope.seed( MavenSession.class, session );
|
||||||
}
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -147,11 +143,8 @@ public class LifecycleModuleBuilder
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
|
||||||
if ( scoped )
|
|
||||||
{
|
{
|
||||||
sessionScope.exit();
|
sessionScope.exit();
|
||||||
}
|
|
||||||
|
|
||||||
session.setCurrentProject( null );
|
session.setCurrentProject( null );
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,8 @@ public class LifecycleStarter
|
||||||
ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
|
ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
|
||||||
ReactorBuildStatus reactorBuildStatus = new ReactorBuildStatus( session.getProjectDependencyGraph() );
|
ReactorBuildStatus reactorBuildStatus = new ReactorBuildStatus( session.getProjectDependencyGraph() );
|
||||||
reactorContext =
|
reactorContext =
|
||||||
new ReactorContext( result, projectIndex, oldContextClassLoader, reactorBuildStatus );
|
new ReactorContext( result, projectIndex, oldContextClassLoader, reactorBuildStatus,
|
||||||
|
sessionScope.memento() );
|
||||||
|
|
||||||
String builderId = session.getRequest().getBuilderId();
|
String builderId = session.getRequest().getBuilderId();
|
||||||
Builder builder = builders.get( builderId );
|
Builder builder = builders.get( builderId );
|
||||||
|
|
|
@ -20,6 +20,7 @@ package org.apache.maven.lifecycle.internal;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import org.apache.maven.execution.MavenExecutionResult;
|
import org.apache.maven.execution.MavenExecutionResult;
|
||||||
|
import org.apache.maven.session.scope.internal.SessionScope;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Context that is fixed for the entire reactor build.
|
* Context that is fixed for the entire reactor build.
|
||||||
|
@ -39,13 +40,17 @@ public class ReactorContext
|
||||||
|
|
||||||
private final ReactorBuildStatus reactorBuildStatus;
|
private final ReactorBuildStatus reactorBuildStatus;
|
||||||
|
|
||||||
|
private final SessionScope.Memento sessionScope;
|
||||||
|
|
||||||
public ReactorContext( MavenExecutionResult result, ProjectIndex projectIndex,
|
public ReactorContext( MavenExecutionResult result, ProjectIndex projectIndex,
|
||||||
ClassLoader originalContextClassLoader, ReactorBuildStatus reactorBuildStatus )
|
ClassLoader originalContextClassLoader, ReactorBuildStatus reactorBuildStatus,
|
||||||
|
SessionScope.Memento sessionScope )
|
||||||
{
|
{
|
||||||
this.result = result;
|
this.result = result;
|
||||||
this.projectIndex = projectIndex;
|
this.projectIndex = projectIndex;
|
||||||
this.originalContextClassLoader = originalContextClassLoader;
|
this.originalContextClassLoader = originalContextClassLoader;
|
||||||
this.reactorBuildStatus = reactorBuildStatus;
|
this.reactorBuildStatus = reactorBuildStatus;
|
||||||
|
this.sessionScope = sessionScope;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReactorBuildStatus getReactorBuildStatus()
|
public ReactorBuildStatus getReactorBuildStatus()
|
||||||
|
@ -68,4 +73,11 @@ public class ReactorContext
|
||||||
return originalContextClassLoader;
|
return originalContextClassLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 3.3.0
|
||||||
|
*/
|
||||||
|
public SessionScope.Memento getSessionScopeMemento()
|
||||||
|
{
|
||||||
|
return sessionScope;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,16 +19,16 @@ package org.apache.maven.session.scope.internal;
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
|
||||||
|
|
||||||
import com.google.inject.Key;
|
import com.google.inject.Key;
|
||||||
import com.google.inject.OutOfScopeException;
|
import com.google.inject.OutOfScopeException;
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
import com.google.inject.Scope;
|
import com.google.inject.Scope;
|
||||||
|
import com.google.inject.util.Providers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SessionScope
|
* SessionScope
|
||||||
|
@ -36,6 +36,18 @@ import com.google.inject.Scope;
|
||||||
public class SessionScope
|
public class SessionScope
|
||||||
implements Scope
|
implements Scope
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @since 3.3.0
|
||||||
|
*/
|
||||||
|
public static class Memento
|
||||||
|
{
|
||||||
|
final Map<Key<?>, Provider<?>> seeded;
|
||||||
|
|
||||||
|
Memento( final Map<Key<?>, Provider<?>> seeded )
|
||||||
|
{
|
||||||
|
this.seeded = Collections.unmodifiableMap( new HashMap<>( seeded ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static final Provider<Object> SEEDED_KEY_PROVIDER = () ->
|
private static final Provider<Object> SEEDED_KEY_PROVIDER = () ->
|
||||||
{
|
{
|
||||||
|
@ -45,99 +57,106 @@ public class SessionScope
|
||||||
/**
|
/**
|
||||||
* ScopeState
|
* ScopeState
|
||||||
*/
|
*/
|
||||||
protected static final class ScopeState
|
private static final class ScopeState
|
||||||
{
|
{
|
||||||
private final Map<Key<?>, CachingProvider<?>> provided = new ConcurrentHashMap<>();
|
private final Map<Key<?>, Provider<?>> seeded = new HashMap<>();
|
||||||
|
|
||||||
public <T> void seed( Class<T> clazz, Provider<T> value )
|
private final Map<Key<?>, Object> provided = new HashMap<>();
|
||||||
{
|
|
||||||
provided.put( Key.get( clazz ), new CachingProvider<>( value ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings( "unchecked" )
|
private final ThreadLocal<LinkedList<ScopeState>> values = new ThreadLocal<>();
|
||||||
public <T> Provider<T> scope( Key<T> key, Provider<T> unscoped )
|
|
||||||
{
|
|
||||||
Provider<?> provider = provided.computeIfAbsent( key, k -> new CachingProvider<>( unscoped ) );
|
|
||||||
return ( Provider<T> ) provider;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Collection<CachingProvider<?>> providers()
|
|
||||||
{
|
|
||||||
return provided.values();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final List<ScopeState> values = new CopyOnWriteArrayList<>();
|
|
||||||
|
|
||||||
public void enter()
|
public void enter()
|
||||||
{
|
{
|
||||||
values.add( 0, new ScopeState() );
|
LinkedList<ScopeState> stack = values.get();
|
||||||
|
if ( stack == null )
|
||||||
|
{
|
||||||
|
stack = new LinkedList<>();
|
||||||
|
values.set( stack );
|
||||||
|
}
|
||||||
|
stack.addFirst( new ScopeState() );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ScopeState getScopeState()
|
/**
|
||||||
|
* @since 3.3.0
|
||||||
|
*/
|
||||||
|
public void enter( Memento memento )
|
||||||
{
|
{
|
||||||
if ( values.isEmpty() )
|
enter();
|
||||||
{
|
getScopeState().seeded.putAll( memento.seeded );
|
||||||
throw new OutOfScopeException( "Cannot access session scope outside of a scoping block" );
|
|
||||||
}
|
}
|
||||||
return values.get( 0 );
|
|
||||||
|
private ScopeState getScopeState()
|
||||||
|
{
|
||||||
|
LinkedList<ScopeState> stack = values.get();
|
||||||
|
if ( stack == null || stack.isEmpty() )
|
||||||
|
{
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
return stack.getFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void exit()
|
public void exit()
|
||||||
{
|
{
|
||||||
if ( values.isEmpty() )
|
final LinkedList<ScopeState> stack = values.get();
|
||||||
|
if ( stack == null || stack.isEmpty() )
|
||||||
{
|
{
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
values.remove( 0 );
|
stack.removeFirst();
|
||||||
|
if ( stack.isEmpty() )
|
||||||
|
{
|
||||||
|
values.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 3.3.0
|
||||||
|
*/
|
||||||
|
public Memento memento()
|
||||||
|
{
|
||||||
|
LinkedList<ScopeState> stack = values.get();
|
||||||
|
return new Memento( stack != null ? stack.getFirst().seeded : Collections.emptyMap() );
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> void seed( Class<T> clazz, Provider<T> value )
|
public <T> void seed( Class<T> clazz, Provider<T> value )
|
||||||
{
|
{
|
||||||
getScopeState().seed( clazz, value );
|
getScopeState().seeded.put( Key.get( clazz ), value );
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> void seed( Class<T> clazz, final T value )
|
public <T> void seed( Class<T> clazz, final T value )
|
||||||
{
|
{
|
||||||
seed( clazz, ( Provider<T> ) () -> value );
|
getScopeState().seeded.put( Key.get( clazz ), Providers.of( value ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> Provider<T> scope( final Key<T> key, final Provider<T> unscoped )
|
public <T> Provider<T> scope( final Key<T> key, final Provider<T> unscoped )
|
||||||
{
|
{
|
||||||
// Lazy evaluating provider
|
return () ->
|
||||||
return () -> getScopeState().scope( key, unscoped ).get();
|
{
|
||||||
|
LinkedList<ScopeState> stack = values.get();
|
||||||
|
if ( stack == null || stack.isEmpty() )
|
||||||
|
{
|
||||||
|
throw new OutOfScopeException( "Cannot access " + key + " outside of a scoping block" );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static class CachingProvider<T> implements Provider<T>
|
ScopeState state = stack.getFirst();
|
||||||
{
|
|
||||||
private final Provider<T> provider;
|
|
||||||
private volatile T value;
|
|
||||||
|
|
||||||
CachingProvider( Provider<T> provider )
|
Provider<?> seeded = state.seeded.get( key );
|
||||||
|
|
||||||
|
if ( seeded != null )
|
||||||
{
|
{
|
||||||
this.provider = provider;
|
return (T) seeded.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public T value()
|
T provided = (T) state.provided.get( key );
|
||||||
|
if ( provided == null && unscoped != null )
|
||||||
{
|
{
|
||||||
return value;
|
provided = unscoped.get();
|
||||||
|
state.provided.put( key, provided );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
return provided;
|
||||||
public T get()
|
};
|
||||||
{
|
|
||||||
if ( value == null )
|
|
||||||
{
|
|
||||||
synchronized ( this )
|
|
||||||
{
|
|
||||||
if ( value == null )
|
|
||||||
{
|
|
||||||
value = provider.get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings( { "unchecked" } )
|
@SuppressWarnings( { "unchecked" } )
|
||||||
|
|
|
@ -1,81 +0,0 @@
|
||||||
package org.apache.maven.session.scope.internal;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 javax.inject.Provider;
|
|
||||||
|
|
||||||
import com.google.inject.Key;
|
|
||||||
import com.google.inject.OutOfScopeException;
|
|
||||||
import org.apache.maven.model.building.DefaultModelSourceTransformer;
|
|
||||||
import org.apache.maven.model.building.ModelSourceTransformer;
|
|
||||||
import org.apache.maven.model.locator.DefaultModelLocator;
|
|
||||||
import org.apache.maven.model.locator.ModelLocator;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotSame;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
|
||||||
|
|
||||||
public class SessionScopeTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testScope() throws Exception
|
|
||||||
{
|
|
||||||
SessionScope scope = new SessionScope();
|
|
||||||
|
|
||||||
assertThrows( OutOfScopeException.class, () -> scope.seed( ModelLocator.class, new DefaultModelLocator() ) );
|
|
||||||
|
|
||||||
Provider<ModelLocator> pml = scope.scope( Key.get( ModelLocator.class), DefaultModelLocator::new );
|
|
||||||
assertNotNull( pml );
|
|
||||||
assertThrows( OutOfScopeException.class, pml::get );
|
|
||||||
|
|
||||||
Provider<ModelSourceTransformer> pmst = scope.scope( Key.get( ModelSourceTransformer.class ), DefaultModelSourceTransformer::new );
|
|
||||||
assertNotNull( pmst );
|
|
||||||
|
|
||||||
scope.enter();
|
|
||||||
|
|
||||||
final DefaultModelLocator dml1 = new DefaultModelLocator();
|
|
||||||
scope.seed( ModelLocator.class, dml1 );
|
|
||||||
|
|
||||||
assertSame( dml1, pml.get() );
|
|
||||||
|
|
||||||
ModelSourceTransformer mst1 = pmst.get();
|
|
||||||
assertSame( mst1, pmst.get() );
|
|
||||||
Provider<ModelSourceTransformer> pmst1 = scope.scope( Key.get( ModelSourceTransformer.class ), DefaultModelSourceTransformer::new );
|
|
||||||
assertNotNull( pmst1 );
|
|
||||||
assertSame( mst1, pmst1.get() );
|
|
||||||
|
|
||||||
scope.enter();
|
|
||||||
|
|
||||||
pmst1 = scope.scope( Key.get( ModelSourceTransformer.class ), DefaultModelSourceTransformer::new );
|
|
||||||
assertNotNull( pmst1 );
|
|
||||||
assertNotSame( mst1, pmst1.get() );
|
|
||||||
|
|
||||||
scope.exit();
|
|
||||||
|
|
||||||
assertSame( mst1, pmst.get() );
|
|
||||||
|
|
||||||
scope.exit();
|
|
||||||
|
|
||||||
assertThrows( OutOfScopeException.class, pmst::get );
|
|
||||||
assertThrows( OutOfScopeException.class, () -> scope.seed( ModelLocator.class, new DefaultModelLocator() ) );
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue