Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#30, Jersey 2.26 support on 2.x #36

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,10 @@
</scm>

<properties>
<servlet.version>3.1.0</servlet.version>
<!-- careful jersey 2.26 moved to jax-rs 2.1 and even though the versionning
does not show it, this is a huge upgrade -->
<jax.rs.version>2.0.1</jax.rs.version>
<jersey.version>2.25.1</jersey.version>
<resteasy.version>3.1.4.Final</resteasy.version>
<servlet.version>4.0.0</servlet.version>
<jax.rs.version>2.1</jax.rs.version>
<jersey.version>2.26</jersey.version>
<resteasy.version>3.5.0.Final</resteasy.version>
<pac4j.version>2.2.1</pac4j.version>
<java.version>1.8</java.version>
</properties>
Expand Down Expand Up @@ -130,12 +128,18 @@
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<!-- grizzly optional dependencies -->
<dependency>
<groupId>org.glassfish.grizzly</groupId>
<artifactId>grizzly-http-server</artifactId>
<!-- same version as in jersey -->
<version>2.3.28</version>
<version>2.4.0</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,77 +1,79 @@
package org.pac4j.jax.rs.jersey.features;

import java.util.List;
import java.util.Optional;
import java.util.function.Supplier;

import javax.inject.Inject;
import javax.inject.Singleton;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.ext.Providers;

import org.glassfish.hk2.api.Factory;
import org.glassfish.hk2.api.InjectionResolver;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.hk2.api.TypeLiteral;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.internal.inject.AbstractBinder;
import org.glassfish.jersey.internal.inject.InjectionResolver;
import org.glassfish.jersey.internal.util.ReflectionHelper;
import org.glassfish.jersey.internal.util.collection.ClassTypePair;
import org.glassfish.jersey.server.internal.inject.AbstractContainerRequestValueFactory;
import org.glassfish.jersey.server.internal.inject.AbstractValueFactoryProvider;
import org.glassfish.jersey.server.ContainerRequest;
import org.glassfish.jersey.server.internal.inject.AbstractValueParamProvider;
import org.glassfish.jersey.server.internal.inject.MultivaluedParameterExtractorProvider;
import org.glassfish.jersey.server.internal.inject.ParamInjectionResolver;
import org.glassfish.jersey.server.model.Parameter;
import org.glassfish.jersey.server.spi.internal.ValueFactoryProvider;
import org.glassfish.jersey.server.spi.internal.ValueParamProvider;
import org.pac4j.core.profile.CommonProfile;
import org.pac4j.core.profile.ProfileManager;
import org.pac4j.jax.rs.annotations.Pac4JProfile;
import org.pac4j.jax.rs.annotations.Pac4JProfileManager;
import org.pac4j.jax.rs.helpers.RequestJaxRsContext;
import org.pac4j.jax.rs.helpers.RequestCommonProfile;
import org.pac4j.jax.rs.helpers.RequestProfileManager;
import org.pac4j.jax.rs.helpers.RequestJaxRsContext;
import org.pac4j.jax.rs.helpers.RequestPac4JSecurityContext;
import org.pac4j.jax.rs.helpers.RequestProfileManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.ext.Providers;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;

/**
* {@link Pac4JProfile &#64;Pac4JProfile} injection value factory provider.
*
*
* Register a new {@link Binder} in order to enable this.
*
*
* @author Victor Noel - Linagora
* @since 1.0.0
*
*
*/
public class Pac4JValueFactoryProvider {

private static Logger LOG = LoggerFactory.getLogger(Pac4JValueFactoryProvider.class);

static class Pac4JProfileValueFactoryProvider extends AbstractValueFactoryProvider {
static class Pac4JProfileValueFactoryProvider extends AbstractValueParamProvider {

private final ProfileManagerFactoryBuilder manager;
private final OptionalProfileFactoryBuilder optProfile;
private final ProfileFactoryBuilder profile;

@Inject
protected Pac4JProfileValueFactoryProvider(ProfileManagerFactoryBuilder manager,
OptionalProfileFactoryBuilder opt, ProfileFactoryBuilder profile,
MultivaluedParameterExtractorProvider mpep, ServiceLocator locator) {
super(mpep, locator, Parameter.Source.UNKNOWN);
protected Pac4JProfileValueFactoryProvider(
ProfileManagerFactoryBuilder manager,
OptionalProfileFactoryBuilder opt,
ProfileFactoryBuilder profile,
Provider<MultivaluedParameterExtractorProvider> mpep
) {
super(mpep, Parameter.Source.UNKNOWN);
this.manager = manager;
this.optProfile = opt;
this.profile = profile;
}

@Override
protected Factory<?> createValueFactory(Parameter parameter) {
protected Function<ContainerRequest, ?> createValueProvider(Parameter parameter) {
if (parameter.isAnnotationPresent(Pac4JProfileManager.class)) {
if (ProfileManager.class.isAssignableFrom(parameter.getRawType())) {
return manager.get();
}

throw new IllegalStateException("Cannot inject a Pac4J profile manager into a parameter of type "
+ parameter.getRawType().getName());
+ parameter.getRawType().getName());
}

if (parameter.isAnnotationPresent(Pac4JProfile.class)) {
Expand All @@ -88,63 +90,55 @@ protected Factory<?> createValueFactory(Parameter parameter) {
}

throw new IllegalStateException(
"Cannot inject a Pac4J profile into a parameter of type " + parameter.getRawType().getName());
"Cannot inject a Pac4J profile into a parameter of type " + parameter.getRawType().getName());
}

return null;
}
}

static class ProfileManagerInjectionResolver extends ParamInjectionResolver<Pac4JProfileManager> {
ProfileManagerInjectionResolver() {
super(Pac4JProfileValueFactoryProvider.class);
@Inject
ProfileManagerInjectionResolver(
Pac4JProfileValueFactoryProvider valueFactoryProvider,
Provider<ContainerRequest> containerRequestProvider
) {
super(
valueFactoryProvider,
Pac4JProfileManager.class,
containerRequestProvider
);
}
}

static class ProfileInjectionResolver extends ParamInjectionResolver<Pac4JProfile> {
ProfileInjectionResolver() {
super(Pac4JProfileValueFactoryProvider.class);
}
}

public interface OptionalProfileFactory extends Factory<Optional<CommonProfile>> {
@Override
default void dispose(Optional<CommonProfile> instance) {
// do nothing
}
}

public interface ProfileFactory extends Factory<CommonProfile> {
@Override
default void dispose(CommonProfile instance) {
// do nothing
}
}

public interface ProfileManagerFactory extends Factory<ProfileManager<CommonProfile>> {
@Override
default void dispose(ProfileManager<CommonProfile> instance) {
// do nothing
@Inject
ProfileInjectionResolver(
Pac4JProfileValueFactoryProvider valueFactoryProvider,
Provider<ContainerRequest> containerRequestProvider
) {
super(
valueFactoryProvider,
Pac4JProfile.class,
containerRequestProvider
);
}
}

public interface OptionalProfileFactoryBuilder extends Supplier<OptionalProfileFactory> {
public interface OptionalProfileFactory extends Function<ContainerRequest, Optional<CommonProfile>> {}
public interface OptionalProfileFactoryBuilder extends Supplier<OptionalProfileFactory> {}

}
public interface ProfileFactory extends Function<ContainerRequest, CommonProfile> {}
public interface ProfileFactoryBuilder extends Supplier<ProfileFactory> {}

public interface ProfileFactoryBuilder extends Supplier<ProfileFactory> {

}

public interface ProfileManagerFactoryBuilder extends Supplier<ProfileManagerFactory> {

}
public interface ProfileManagerFactory extends Function<ContainerRequest, ProfileManager<CommonProfile>> {}
public interface ProfileManagerFactoryBuilder extends Supplier<ProfileManagerFactory> {}

public static class Binder extends AbstractBinder {

private final ProfileFactoryBuilder profile;
private final OptionalProfileFactoryBuilder optProfile;
private final ProfileManagerFactoryBuilder manager;
private ProfileManagerFactoryBuilder manager;

/**
* Use this in your applications
Expand All @@ -155,7 +149,7 @@ public Binder() {

/**
* Use this if you want to mock the {@link CommonProfile} or the {@link ProfileManager}.
*
*
* @param profile
* a builder for a {@link CommonProfile}, can be <code>null</code> and default will be used.
* @param optProfile
Expand All @@ -165,69 +159,94 @@ public Binder() {
* a builder for a {@link ProfileManager}, can be <code>null</code> and default will be used.
*/
public Binder(ProfileFactoryBuilder profile, OptionalProfileFactoryBuilder optProfile,
ProfileManagerFactoryBuilder manager) {
ProfileManagerFactoryBuilder manager) {
this.profile = profile == null ? ProfileValueFactory::new : profile;
this.optProfile = optProfile == null ? OptionalProfileValueFactory::new : optProfile;
this.manager = manager == null ? ProfileManagerValueFactory::new : manager;
this.manager = manager;
}

/**
* Use this if you want to always return the same {@link CommonProfile} (or none with <code>null</code>).
*
*
* Note that it won't mock the profile coming out of {@link ProfileManager}!
*
*
* @param profile
* a profile, can be <code>null</code>.
*/
public Binder(CommonProfile profile) {
this(() -> () -> profile, () -> () -> Optional.ofNullable(profile), null);
this(() -> (ignored) -> profile, () -> (ignored) -> Optional.ofNullable(profile), null);
}

@Override
protected void configure() {
bind(profile).to(ProfileFactoryBuilder.class);
bind(optProfile).to(OptionalProfileFactoryBuilder.class);
bind(manager).to(ProfileManagerFactoryBuilder.class);

bind(Pac4JProfileValueFactoryProvider.class).to(ValueFactoryProvider.class).in(Singleton.class);
if(manager == null){
bind(DefaultProfileManagerFactoryBuilder.class)
.to(ProfileManagerFactoryBuilder.class)
;
} else {
bind(manager).to(ProfileManagerFactoryBuilder.class);
}

bind(Pac4JProfileValueFactoryProvider.class).to(ValueParamProvider.class).in(Singleton.class);

bind(ProfileInjectionResolver.class).to(new TypeLiteral<InjectionResolver<Pac4JProfile>>() {
}).in(Singleton.class);
bind(ProfileManagerInjectionResolver.class).to(new TypeLiteral<InjectionResolver<Pac4JProfileManager>>() {
}).in(Singleton.class);
bind(ProfileInjectionResolver.class)
.to(new GenericType<InjectionResolver<Pac4JProfile>>(){})
.in(Singleton.class);

bind(ProfileManagerInjectionResolver.class)
.to(new GenericType<InjectionResolver<Pac4JProfileManager>>(){})
.in(Singleton.class);
}
}

static class ProfileManagerValueFactory extends AbstractContainerRequestValueFactory<ProfileManager<CommonProfile>>
implements ProfileManagerFactory {

static class ProfileManagerValueFactory implements ProfileManagerFactory{
@Context
Providers providers;
private Providers providers;

ProfileManagerValueFactory(Providers providers) {
this.providers = providers;
}

@Override
public ProfileManager<CommonProfile> apply(ContainerRequest containerRequest) {
return new RequestProfileManager(new RequestJaxRsContext(providers, containerRequest))
.profileManager();
}
}

static class ProfileValueFactory implements ProfileFactory {
@Override
public ProfileManager<CommonProfile> provide() {
return new RequestProfileManager(new RequestJaxRsContext(providers, getContainerRequest()))
.profileManager();
public CommonProfile apply(ContainerRequest containerRequest) {
return optionalProfile(containerRequest)
.orElseThrow(() -> {
LOG.debug("Cannot inject a Pac4j profile into an unauthenticated request, responding with 401");
return new WebApplicationException(401);
});
}
}

static class ProfileValueFactory extends AbstractContainerRequestValueFactory<CommonProfile>
implements ProfileFactory {
static class OptionalProfileValueFactory implements OptionalProfileFactory {
@Override
public CommonProfile provide() {
return new RequestCommonProfile(new RequestPac4JSecurityContext(getContainerRequest())).profile()
.orElseThrow(() -> {
LOG.debug("Cannot inject a Pac4j profile into an unauthenticated request, responding with 401");
return new WebApplicationException(401);
});
public Optional<CommonProfile> apply(ContainerRequest containerRequest) {
return optionalProfile(containerRequest);
}
}

static class OptionalProfileValueFactory extends AbstractContainerRequestValueFactory<Optional<CommonProfile>>
implements OptionalProfileFactory {
private static Optional<CommonProfile> optionalProfile(ContainerRequest containerRequest) {
RequestPac4JSecurityContext securityContext = new RequestPac4JSecurityContext(containerRequest.getSecurityContext());
return new RequestCommonProfile(securityContext).profile();
}

public static class DefaultProfileManagerFactoryBuilder implements ProfileManagerFactoryBuilder {
@Context
private Providers providers;

@Override
public Optional<CommonProfile> provide() {
return new RequestCommonProfile(new RequestPac4JSecurityContext(getContainerRequest())).profile();
public ProfileManagerFactory get() {
return new ProfileManagerValueFactory(providers);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import javax.ws.rs.core.SecurityContext;
import javax.ws.rs.ext.Providers;

import org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext;
import org.jboss.resteasy.core.interception.PreMatchContainerRequestContext;
import org.jboss.resteasy.spi.HttpRequest;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.pac4j.jax.rs.helpers.RequestJaxRsContext;
Expand Down
Loading