From 56de719913d6c39dc9d913864e8de8cb6ba6b599 Mon Sep 17 00:00:00 2001 From: "Henning P. Schmiedehausen" Date: Sat, 14 May 2022 13:52:22 -0700 Subject: [PATCH] Support for jakarta.inject.Provider Adds support for jakarta providers. These can be used interchangeably with their native and javax.inject counterparts. --- core/src/com/google/inject/Provider.java | 2 +- .../inject/binder/LinkedBindingBuilder.java | 21 +++ .../inject/internal/BindingBuilder.java | 34 ++++ .../inject/internal/BindingProcessor.java | 67 ++++++- .../internal/BoundJeeProviderFactory.java | 85 +++++++++ ...ernalFactoryToJeeInitializableAdapter.java | 65 +++++++ .../JeeProviderInstanceBindingImpl.java | 140 ++++++++++++++ .../internal/JeeProviderInternalFactory.java | 91 ++++++++++ .../LinkedJeeProviderBindingImpl.java | 152 ++++++++++++++++ .../com/google/inject/internal/MoreTypes.java | 5 +- .../inject/internal/ProviderMethod.java | 11 ++ .../google/inject/internal/RealMapBinder.java | 12 ++ .../inject/internal/RealMultibinder.java | 12 ++ .../inject/internal/RealOptionalBinder.java | 22 +++ .../inject/spi/BindingTargetVisitor.java | 13 ++ .../spi/DefaultBindingTargetVisitor.java | 10 + .../spi/JeeProviderInstanceBinding.java | 43 +++++ .../inject/spi/JeeProviderKeyBinding.java | 34 ++++ .../spi/ProviderWithExtensionVisitor.java | 3 + .../google/inject/spi/SpiBindingsTest.java | 171 +++++++++++++++++- .../assistedinject/FactoryProvider2.java | 11 ++ .../inject/servlet/jee/FilterDefinition.java | 17 ++ .../servlet/jee/InternalServletModule.java | 2 +- .../inject/servlet/jee/ServletDefinition.java | 17 ++ .../inject/servlet/FilterDefinition.java | 17 ++ .../inject/servlet/ServletDefinition.java | 17 ++ 26 files changed, 1066 insertions(+), 8 deletions(-) create mode 100644 core/src/com/google/inject/internal/BoundJeeProviderFactory.java create mode 100644 core/src/com/google/inject/internal/InternalFactoryToJeeInitializableAdapter.java create mode 100644 core/src/com/google/inject/internal/JeeProviderInstanceBindingImpl.java create mode 100644 core/src/com/google/inject/internal/JeeProviderInternalFactory.java create mode 100644 core/src/com/google/inject/internal/LinkedJeeProviderBindingImpl.java create mode 100644 core/src/com/google/inject/spi/JeeProviderInstanceBinding.java create mode 100644 core/src/com/google/inject/spi/JeeProviderKeyBinding.java diff --git a/core/src/com/google/inject/Provider.java b/core/src/com/google/inject/Provider.java index 4ce1e31501..5974c31b35 100644 --- a/core/src/com/google/inject/Provider.java +++ b/core/src/com/google/inject/Provider.java @@ -38,7 +38,7 @@ * @param the type of object this provides * @author crazybob@google.com (Bob Lee) */ -public interface Provider extends javax.inject.Provider { +public interface Provider extends javax.inject.Provider, jakarta.inject.Provider { /** * Provides an instance of {@code T}. diff --git a/core/src/com/google/inject/binder/LinkedBindingBuilder.java b/core/src/com/google/inject/binder/LinkedBindingBuilder.java index 219e145a58..df84bbb866 100644 --- a/core/src/com/google/inject/binder/LinkedBindingBuilder.java +++ b/core/src/com/google/inject/binder/LinkedBindingBuilder.java @@ -69,6 +69,27 @@ ScopedBindingBuilder toProvider( /** See the EDSL examples at {@link com.google.inject.Binder}. */ ScopedBindingBuilder toProvider(Key> providerKey); + /** See the EDSL examples at {@link com.google.inject.Binder}. This method is called toJeeProvider to avoid clashes with {@link #toProvider(Provider)}. */ + default ScopedBindingBuilder toJeeProvider(jakarta.inject.Provider provider) { + throw new UnsupportedOperationException("not implemented"); + } + + /** See the EDSL examples at {@link com.google.inject.Binder}. This method is called toJeeProvider to avoid clashes with {@link #toProvider(Class)}. */ + default ScopedBindingBuilder toJeeProvider(Class> providerType) { + return toJeeProvider(Key.get(providerType)); + } + + /** See the EDSL examples at {@link com.google.inject.Binder}. This method is called toJeeProvider to avoid clashes with {@link #toProvider(TypeLiteral)}. */ + default ScopedBindingBuilder toJeeProvider( + TypeLiteral> providerType) { + return toJeeProvider(Key.get(providerType)); + } + + /** See the EDSL examples at {@link com.google.inject.Binder}. This method is called toJeeProvider to avoid clashes with {@link #toProvider(Key)}. */ + default ScopedBindingBuilder toJeeProvider(Key> providerKey) { + throw new UnsupportedOperationException("not implemented"); + } + /** * See the EDSL examples at {@link com.google.inject.Binder}. * diff --git a/core/src/com/google/inject/internal/BindingBuilder.java b/core/src/com/google/inject/internal/BindingBuilder.java index 2ef3ecaeb6..a93208da34 100644 --- a/core/src/com/google/inject/internal/BindingBuilder.java +++ b/core/src/com/google/inject/internal/BindingBuilder.java @@ -153,6 +153,40 @@ public BindingBuilder toProvider( return this; } + @Override + public BindingBuilder toJeeProvider(jakarta.inject.Provider provider) { + checkNotNull(provider, "provider"); + checkNotTargetted(); + + // lookup the injection points, adding any errors to the binder's errors list + Set injectionPoints; + try { + injectionPoints = InjectionPoint.forInstanceMethodsAndFields(provider.getClass()); + } catch (ConfigurationException e) { + copyErrorsToBinder(e); + injectionPoints = e.getPartialValue(); + } + + BindingImpl base = getBinding(); + setBinding( + new JeeProviderInstanceBindingImpl( + base.getSource(), base.getKey(), base.getScoping(), injectionPoints, provider)); + return this; + } + + @Override + public BindingBuilder toJeeProvider( + Key> providerKey) { + checkNotNull(providerKey, "providerKey"); + checkNotTargetted(); + + BindingImpl base = getBinding(); + setBinding( + new LinkedJeeProviderBindingImpl( + base.getSource(), base.getKey(), base.getScoping(), providerKey)); + return this; + } + @Override public ScopedBindingBuilder toConstructor(Constructor constructor) { return toConstructor(constructor, TypeLiteral.get(constructor.getDeclaringClass())); diff --git a/core/src/com/google/inject/internal/BindingProcessor.java b/core/src/com/google/inject/internal/BindingProcessor.java index 101b7a17b2..3e872316e4 100644 --- a/core/src/com/google/inject/internal/BindingProcessor.java +++ b/core/src/com/google/inject/internal/BindingProcessor.java @@ -25,6 +25,8 @@ import com.google.inject.spi.ExposedBinding; import com.google.inject.spi.InjectionPoint; import com.google.inject.spi.InstanceBinding; +import com.google.inject.spi.JeeProviderInstanceBinding; +import com.google.inject.spi.JeeProviderKeyBinding; import com.google.inject.spi.LinkedKeyBinding; import com.google.inject.spi.PrivateElements; import com.google.inject.spi.ProviderBinding; @@ -53,9 +55,12 @@ final class BindingProcessor extends AbstractBindingProcessor { public Boolean visit(Binding command) { Class rawType = command.getKey().getTypeLiteral().getRawType(); if (Void.class.equals(rawType)) { - if (command instanceof ProviderInstanceBinding - && ((ProviderInstanceBinding) command).getUserSuppliedProvider() - instanceof ProviderMethod) { + if ((command instanceof ProviderInstanceBinding + && ((ProviderInstanceBinding) command).getUserSuppliedProvider() + instanceof ProviderMethod) + || (command instanceof JeeProviderInstanceBinding + && ((JeeProviderInstanceBinding) command).getUserSuppliedProvider() + instanceof ProviderMethod)) { errors.voidProviderMethod(); } else { errors.missingConstantValues(); @@ -141,6 +146,35 @@ public Boolean visit(ProviderInstanceBinding binding) { return true; } + @Override + public Boolean visit(JeeProviderInstanceBinding binding) { + prepareBinding(); + jakarta.inject.Provider provider = binding.getUserSuppliedProvider(); + if (provider instanceof InternalProviderInstanceBindingImpl.Factory) { + @SuppressWarnings("unchecked") + InternalProviderInstanceBindingImpl.Factory asProviderMethod = + (InternalProviderInstanceBindingImpl.Factory) provider; + return visitInternalProviderInstanceBindingFactory(asProviderMethod); + } + Set injectionPoints = binding.getInjectionPoints(); + Initializable> initializable = + initializer.>requestInjection( + injector, provider, null, source, injectionPoints); + // always visited with Binding + @SuppressWarnings("unchecked") + InternalFactory factory = + new InternalFactoryToJeeInitializableAdapter( + initializable, + source, + injector.provisionListenerStore.get((JeeProviderInstanceBinding) binding)); + InternalFactory scopedFactory = + Scoping.scope(key, injector, factory, source, scoping); + putBinding( + new JeeProviderInstanceBindingImpl( + injector, key, source, scopedFactory, scoping, provider, injectionPoints)); + return true; + } + @Override public Boolean visit(ProviderKeyBinding binding) { prepareBinding(); @@ -169,6 +203,33 @@ public Boolean visit(ProviderKeyBinding binding) { } @Override + public Boolean visit(JeeProviderKeyBinding binding) { + prepareBinding(); + Key> providerKey = + binding.getProviderKey(); + // always visited with Binding + @SuppressWarnings("unchecked") + BoundJeeProviderFactory boundProviderFactory = + new BoundJeeProviderFactory<>( + injector, + providerKey, + source, + injector.provisionListenerStore.get((JeeProviderKeyBinding) binding)); + processedBindingData.addCreationListener(boundProviderFactory); + InternalFactory scopedFactory = + Scoping.scope( + key, + injector, + boundProviderFactory, + source, + scoping); + putBinding( + new LinkedJeeProviderBindingImpl<>( + injector, key, source, scopedFactory, scoping, providerKey)); + return true; + } + + @Override public Boolean visit(LinkedKeyBinding binding) { prepareBinding(); Key linkedKey = binding.getLinkedKey(); diff --git a/core/src/com/google/inject/internal/BoundJeeProviderFactory.java b/core/src/com/google/inject/internal/BoundJeeProviderFactory.java new file mode 100644 index 0000000000..c1017374b1 --- /dev/null +++ b/core/src/com/google/inject/internal/BoundJeeProviderFactory.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2022 Google Inc. + * + * 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. + */ + +package com.google.inject.internal; + +import com.google.inject.Key; +import com.google.inject.internal.InjectorImpl.JitLimitation; +import com.google.inject.spi.Dependency; +import jakarta.inject.Provider; + +/** + * Delegates to a custom factory which is also bound in the injector. + */ +final class BoundJeeProviderFactory extends JeeProviderInternalFactory implements + CreationListener { + + final Key> providerKey; + private final ProvisionListenerStackCallback provisionCallback; + private final InjectorImpl injector; + private InternalFactory> providerFactory; + + BoundJeeProviderFactory( + InjectorImpl injector, + Key> providerKey, + Object source, + ProvisionListenerStackCallback provisionCallback) { + super(source); + this.provisionCallback = provisionCallback; + this.injector = injector; + this.providerKey = providerKey; + } + + @Override + public void notify(Errors errors) { + try { + providerFactory = + injector.getInternalFactory( + providerKey, errors.withSource(source), JitLimitation.NEW_OR_EXISTING_JIT); + } catch (ErrorsException e) { + errors.merge(e.getErrors()); + } + } + + @Override + public T get(InternalContext context, Dependency dependency, boolean linked) + throws InternalProvisionException { + try { + Provider provider = providerFactory.get(context, dependency, true); + return circularGet(provider, context, dependency, provisionCallback); + } catch (InternalProvisionException ipe) { + throw ipe.addSource(providerKey); + } + } + + @Override + protected T provision( + Provider provider, + Dependency dependency, + ConstructionContext constructionContext) + throws InternalProvisionException { + try { + return super.provision(provider, dependency, constructionContext); + } catch (RuntimeException userException) { + throw InternalProvisionException.errorInProvider(userException); + } + } + + @Override + public String toString() { + return providerKey.toString(); + } +} diff --git a/core/src/com/google/inject/internal/InternalFactoryToJeeInitializableAdapter.java b/core/src/com/google/inject/internal/InternalFactoryToJeeInitializableAdapter.java new file mode 100644 index 0000000000..6e68a93957 --- /dev/null +++ b/core/src/com/google/inject/internal/InternalFactoryToJeeInitializableAdapter.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2022 Google Inc. + * + * 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. + */ + +package com.google.inject.internal; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.inject.spi.Dependency; +import com.google.inject.spi.ProviderInstanceBinding; + +/** + * Adapts {@link ProviderInstanceBinding} providers, ensuring circular proxies fail (or proxy) + * properly. + */ +final class InternalFactoryToJeeInitializableAdapter extends JeeProviderInternalFactory { + + private final ProvisionListenerStackCallback provisionCallback; + private final Initializable> initializable; + + public InternalFactoryToJeeInitializableAdapter( + Initializable> initializable, + Object source, + ProvisionListenerStackCallback provisionCallback) { + super(source); + this.provisionCallback = provisionCallback; + this.initializable = checkNotNull(initializable, "provider"); + } + + @Override + public T get(InternalContext context, Dependency dependency, boolean linked) + throws InternalProvisionException { + return circularGet(initializable.get(), context, dependency, provisionCallback); + } + + @Override + protected T provision( + jakarta.inject.Provider provider, + Dependency dependency, + ConstructionContext constructionContext) + throws InternalProvisionException { + try { + return super.provision(provider, dependency, constructionContext); + } catch (RuntimeException userException) { + throw InternalProvisionException.errorInProvider(userException).addSource(source); + } + } + + @Override + public String toString() { + return initializable.toString(); + } +} diff --git a/core/src/com/google/inject/internal/JeeProviderInstanceBindingImpl.java b/core/src/com/google/inject/internal/JeeProviderInstanceBindingImpl.java new file mode 100644 index 0000000000..abe5c9953a --- /dev/null +++ b/core/src/com/google/inject/internal/JeeProviderInstanceBindingImpl.java @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2022 Google Inc. + * + * 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. + */ + +package com.google.inject.internal; + +import static com.google.inject.internal.GuiceInternal.GUICE_INTERNAL; +import static com.google.inject.spi.Elements.withTrustedSource; + +import com.google.common.base.MoreObjects; +import com.google.common.base.Objects; +import com.google.common.collect.ImmutableSet; +import com.google.inject.Binder; +import com.google.inject.Key; +import com.google.inject.spi.BindingTargetVisitor; +import com.google.inject.spi.Dependency; +import com.google.inject.spi.HasDependencies; +import com.google.inject.spi.InjectionPoint; +import com.google.inject.spi.JeeProviderInstanceBinding; +import com.google.inject.spi.ProviderWithExtensionVisitor; +import java.util.Set; + +class JeeProviderInstanceBindingImpl extends BindingImpl implements + JeeProviderInstanceBinding { + + final jakarta.inject.Provider providerInstance; + final ImmutableSet injectionPoints; + + public JeeProviderInstanceBindingImpl( + InjectorImpl injector, + Key key, + Object source, + InternalFactory internalFactory, + Scoping scoping, + jakarta.inject.Provider providerInstance, + Set injectionPoints) { + super(injector, key, source, internalFactory, scoping); + this.providerInstance = providerInstance; + this.injectionPoints = ImmutableSet.copyOf(injectionPoints); + } + + public JeeProviderInstanceBindingImpl( + Object source, + Key key, + Scoping scoping, + Set injectionPoints, + jakarta.inject.Provider providerInstance) { + + super(source, key, scoping); + this.injectionPoints = ImmutableSet.copyOf(injectionPoints); + this.providerInstance = providerInstance; + } + + @Override + public V acceptTargetVisitor(BindingTargetVisitor visitor) { + if (providerInstance instanceof ProviderWithExtensionVisitor) { + return ((ProviderWithExtensionVisitor) providerInstance) + .acceptExtensionVisitor(visitor, this); + } else { + return visitor.visit(this); + } + } + + @Override + public jakarta.inject.Provider getUserSuppliedProvider() { + return providerInstance; + } + + @Override + public Set getInjectionPoints() { + return injectionPoints; + } + + @Override + public Set> getDependencies() { + return providerInstance instanceof HasDependencies + ? ImmutableSet.copyOf(((HasDependencies) providerInstance).getDependencies()) + : Dependency.forInjectionPoints(injectionPoints); + } + + @Override + public BindingImpl withScoping(Scoping scoping) { + return new JeeProviderInstanceBindingImpl( + getSource(), getKey(), scoping, injectionPoints, providerInstance); + } + + @Override + public BindingImpl withKey(Key key) { + return new JeeProviderInstanceBindingImpl( + getSource(), key, getScoping(), injectionPoints, providerInstance); + } + + @Override + public void applyTo(Binder binder) { + getScoping() + .applyTo( + withTrustedSource(GUICE_INTERNAL, binder, getSource()) + .bind(getKey()) + .toJeeProvider(getUserSuppliedProvider())); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(JeeProviderInstanceBinding.class) + .add("key", getKey()) + .add("source", getSource()) + .add("scope", getScoping()) + .add("provider", providerInstance) + .toString(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof JeeProviderInstanceBindingImpl) { + JeeProviderInstanceBindingImpl o = (JeeProviderInstanceBindingImpl) obj; + return getKey().equals(o.getKey()) + && getScoping().equals(o.getScoping()) + && Objects.equal(providerInstance, o.providerInstance); + } else { + return false; + } + } + + @Override + public int hashCode() { + return Objects.hashCode(getKey(), getScoping()); + } +} diff --git a/core/src/com/google/inject/internal/JeeProviderInternalFactory.java b/core/src/com/google/inject/internal/JeeProviderInternalFactory.java new file mode 100644 index 0000000000..7dcbc05dea --- /dev/null +++ b/core/src/com/google/inject/internal/JeeProviderInternalFactory.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2022 Google Inc. + * + * 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. + */ + +package com.google.inject.internal; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.inject.internal.ProvisionListenerStackCallback.ProvisionCallback; +import com.google.inject.spi.Dependency; +import jakarta.inject.Provider; +import javax.annotation.Nullable; + +/** + * Base class for InternalFactories that are used by Providers, to handle circular dependencies. + */ +abstract class JeeProviderInternalFactory implements InternalFactory { + + protected final Object source; + + JeeProviderInternalFactory(Object source) { + this.source = checkNotNull(source, "source"); + } + + protected T circularGet( + final Provider provider, + InternalContext context, + final Dependency dependency, + @Nullable ProvisionListenerStackCallback provisionCallback) + throws InternalProvisionException { + final ConstructionContext constructionContext = context.getConstructionContext(this); + + // We have a circular reference between constructors. Return a proxy. + if (constructionContext.isConstructing()) { + Class expectedType = dependency.getKey().getTypeLiteral().getRawType(); + // TODO: if we can't proxy this object, can we proxy the other object? + @SuppressWarnings("unchecked") + T proxyType = (T) constructionContext.createProxy(context.getInjectorOptions(), expectedType); + return proxyType; + } + + // Optimization: Don't go through the callback stack if no one's listening. + constructionContext.startConstruction(); + try { + if (provisionCallback == null) { + return provision(provider, dependency, constructionContext); + } else { + return provisionCallback.provision( + context, + new ProvisionCallback() { + @Override + public T call() throws InternalProvisionException { + return provision(provider, dependency, constructionContext); + } + }); + } + } finally { + constructionContext.removeCurrentReference(); + constructionContext.finishConstruction(); + } + } + + /** + * Provisions a new instance. Subclasses should override this to catch exceptions and rethrow as + * ErrorsExceptions. + */ + protected T provision( + Provider provider, + Dependency dependency, + ConstructionContext constructionContext) + throws InternalProvisionException { + T t = provider.get(); + if (t == null && !dependency.isNullable()) { + InternalProvisionException.onNullInjectedIntoNonNullableDependency(source, dependency); + } + constructionContext.setProxyDelegates(t); + return t; + } +} diff --git a/core/src/com/google/inject/internal/LinkedJeeProviderBindingImpl.java b/core/src/com/google/inject/internal/LinkedJeeProviderBindingImpl.java new file mode 100644 index 0000000000..dca8c837eb --- /dev/null +++ b/core/src/com/google/inject/internal/LinkedJeeProviderBindingImpl.java @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2022 Google Inc. + * + * 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. + */ + +package com.google.inject.internal; + +import static com.google.inject.internal.GuiceInternal.GUICE_INTERNAL; +import static com.google.inject.spi.Elements.withTrustedSource; + +import com.google.common.base.MoreObjects; +import com.google.common.base.Objects; +import com.google.common.collect.ImmutableSet; +import com.google.inject.Binder; +import com.google.inject.Key; +import com.google.inject.spi.BindingTargetVisitor; +import com.google.inject.spi.Dependency; +import com.google.inject.spi.HasDependencies; +import com.google.inject.spi.JeeProviderKeyBinding; +import com.google.inject.spi.ProviderKeyBinding; +import java.util.Set; + +final class LinkedJeeProviderBindingImpl extends BindingImpl + implements JeeProviderKeyBinding, HasDependencies, DelayedInitialize { + + final Key> providerKey; + final DelayedInitialize delayedInitializer; + + private LinkedJeeProviderBindingImpl( + InjectorImpl injector, + Key key, + Object source, + InternalFactory internalFactory, + Scoping scoping, + Key> providerKey, + DelayedInitialize delayedInitializer) { + super(injector, key, source, internalFactory, scoping); + this.providerKey = providerKey; + this.delayedInitializer = delayedInitializer; + } + + public LinkedJeeProviderBindingImpl( + InjectorImpl injector, + Key key, + Object source, + InternalFactory internalFactory, + Scoping scoping, + Key> providerKey) { + this(injector, key, source, internalFactory, scoping, providerKey, null); + } + + LinkedJeeProviderBindingImpl( + Object source, + Key key, + Scoping scoping, + Key> providerKey) { + super(source, key, scoping); + this.providerKey = providerKey; + this.delayedInitializer = null; + } + + static LinkedJeeProviderBindingImpl createWithInitializer( + InjectorImpl injector, + Key key, + Object source, + InternalFactory internalFactory, + Scoping scoping, + Key> providerKey, + DelayedInitialize delayedInitializer) { + return new LinkedJeeProviderBindingImpl( + injector, key, source, internalFactory, scoping, providerKey, delayedInitializer); + } + + @Override + public V acceptTargetVisitor(BindingTargetVisitor visitor) { + return visitor.visit(this); + } + + @Override + public Key> getProviderKey() { + return providerKey; + } + + @Override + public void initialize(InjectorImpl injector, Errors errors) throws ErrorsException { + if (delayedInitializer != null) { + delayedInitializer.initialize(injector, errors); + } + } + + @Override + public Set> getDependencies() { + return ImmutableSet.>of(Dependency.get(providerKey)); + } + + @Override + public BindingImpl withScoping(Scoping scoping) { + return new LinkedJeeProviderBindingImpl(getSource(), getKey(), scoping, providerKey); + } + + @Override + public BindingImpl withKey(Key key) { + return new LinkedJeeProviderBindingImpl(getSource(), key, getScoping(), providerKey); + } + + @Override + public void applyTo(Binder binder) { + getScoping() + .applyTo( + withTrustedSource(GUICE_INTERNAL, binder, getSource()) + .bind(getKey()) + .toJeeProvider(getProviderKey())); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(JeeProviderKeyBinding.class) + .add("key", getKey()) + .add("source", getSource()) + .add("scope", getScoping()) + .add("provider", providerKey) + .toString(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof LinkedJeeProviderBindingImpl) { + LinkedJeeProviderBindingImpl o = (LinkedJeeProviderBindingImpl) obj; + return getKey().equals(o.getKey()) + && getScoping().equals(o.getScoping()) + && Objects.equal(providerKey, o.providerKey); + } else { + return false; + } + } + + @Override + public int hashCode() { + return Objects.hashCode(getKey(), getScoping(), providerKey); + } +} diff --git a/core/src/com/google/inject/internal/MoreTypes.java b/core/src/com/google/inject/internal/MoreTypes.java index 04f685e256..f3c89beee9 100644 --- a/core/src/com/google/inject/internal/MoreTypes.java +++ b/core/src/com/google/inject/internal/MoreTypes.java @@ -91,11 +91,12 @@ public static TypeLiteral canonicalizeForKey(TypeLiteral typeLiteral) throw new ConfigurationException(errors.getMessages()); } - if (typeLiteral.getRawType() == javax.inject.Provider.class) { + if (typeLiteral.getRawType() == javax.inject.Provider.class + || typeLiteral.getRawType() == jakarta.inject.Provider.class) { ParameterizedType parameterizedType = (ParameterizedType) type; // the following casts are generally unsafe, but com.google.inject.Provider extends - // javax.inject.Provider and is covariant + // javax.inject.Provider and jakarta.inject.provider and is covariant @SuppressWarnings("unchecked") TypeLiteral guiceProviderType = (TypeLiteral) diff --git a/core/src/com/google/inject/internal/ProviderMethod.java b/core/src/com/google/inject/internal/ProviderMethod.java index c3ad453887..e44acd938a 100644 --- a/core/src/com/google/inject/internal/ProviderMethod.java +++ b/core/src/com/google/inject/internal/ProviderMethod.java @@ -28,6 +28,7 @@ import com.google.inject.spi.BindingTargetVisitor; import com.google.inject.spi.Dependency; import com.google.inject.spi.HasDependencies; +import com.google.inject.spi.JeeProviderInstanceBinding; import com.google.inject.spi.ProviderInstanceBinding; import com.google.inject.spi.ProviderWithExtensionVisitor; import com.google.inject.spi.ProvidesMethodBinding; @@ -200,6 +201,16 @@ public V acceptExtensionVisitor( return visitor.visit(binding); } + @Override + @SuppressWarnings("unchecked") + public V acceptExtensionVisitor( + BindingTargetVisitor visitor, JeeProviderInstanceBinding binding) { + if (visitor instanceof ProvidesMethodTargetVisitor) { + return ((ProvidesMethodTargetVisitor) visitor).visit(this); + } + return visitor.visit(binding); + } + @Override public String toString() { String annotationString = annotation.toString(); diff --git a/core/src/com/google/inject/internal/RealMapBinder.java b/core/src/com/google/inject/internal/RealMapBinder.java index 00b64d3608..a337d0d967 100644 --- a/core/src/com/google/inject/internal/RealMapBinder.java +++ b/core/src/com/google/inject/internal/RealMapBinder.java @@ -34,6 +34,7 @@ import com.google.inject.spi.BindingTargetVisitor; import com.google.inject.spi.Dependency; import com.google.inject.spi.Element; +import com.google.inject.spi.JeeProviderInstanceBinding; import com.google.inject.spi.ProviderInstanceBinding; import com.google.inject.spi.ProviderWithExtensionVisitor; import com.google.inject.util.Types; @@ -857,6 +858,17 @@ public W acceptExtensionVisitor( } } + @Override + @SuppressWarnings("unchecked") + public W acceptExtensionVisitor( + BindingTargetVisitor visitor, JeeProviderInstanceBinding binding) { + if (visitor instanceof MultibindingsTargetVisitor) { + return ((MultibindingsTargetVisitor, W>) visitor).visit(this); + } else { + return visitor.visit(binding); + } + } + @Override public Key> getMapKey() { return bindingSelection.getMapKey(); diff --git a/core/src/com/google/inject/internal/RealMultibinder.java b/core/src/com/google/inject/internal/RealMultibinder.java index fe677468b6..28656acb4e 100644 --- a/core/src/com/google/inject/internal/RealMultibinder.java +++ b/core/src/com/google/inject/internal/RealMultibinder.java @@ -23,6 +23,7 @@ import com.google.inject.multibindings.MultibindingsTargetVisitor; import com.google.inject.spi.BindingTargetVisitor; import com.google.inject.spi.Dependency; +import com.google.inject.spi.JeeProviderInstanceBinding; import com.google.inject.spi.Message; import com.google.inject.spi.ProviderInstanceBinding; import com.google.inject.spi.ProviderWithExtensionVisitor; @@ -318,6 +319,17 @@ public V acceptExtensionVisitor( } } + @SuppressWarnings("unchecked") + @Override + public V acceptExtensionVisitor( + BindingTargetVisitor visitor, JeeProviderInstanceBinding binding) { + if (visitor instanceof MultibindingsTargetVisitor) { + return ((MultibindingsTargetVisitor, V>) visitor).visit(this); + } else { + return visitor.visit(binding); + } + } + @Override public Key> getSetKey() { return bindingSelection.getSetKey(); diff --git a/core/src/com/google/inject/internal/RealOptionalBinder.java b/core/src/com/google/inject/internal/RealOptionalBinder.java index c5af20a455..604165d3ec 100644 --- a/core/src/com/google/inject/internal/RealOptionalBinder.java +++ b/core/src/com/google/inject/internal/RealOptionalBinder.java @@ -38,6 +38,7 @@ import com.google.inject.spi.BindingTargetVisitor; import com.google.inject.spi.Dependency; import com.google.inject.spi.Element; +import com.google.inject.spi.JeeProviderInstanceBinding; import com.google.inject.spi.ProviderInstanceBinding; import com.google.inject.spi.ProviderWithExtensionVisitor; import com.google.inject.util.Types; @@ -298,6 +299,16 @@ public R acceptExtensionVisitor( } } + @Override + public R acceptExtensionVisitor( + BindingTargetVisitor visitor, JeeProviderInstanceBinding binding) { + if (visitor instanceof MultibindingsTargetVisitor) { + return ((MultibindingsTargetVisitor, R>) visitor).visit(this); + } else { + return visitor.visit(binding); + } + } + @Override public boolean containsElement(Element element) { return bindingSelection.containsElement(element); @@ -485,6 +496,17 @@ public R acceptExtensionVisitor( } } + @SuppressWarnings("unchecked") + @Override + public R acceptExtensionVisitor( + BindingTargetVisitor visitor, JeeProviderInstanceBinding binding) { + if (visitor instanceof MultibindingsTargetVisitor) { + return ((MultibindingsTargetVisitor, R>) visitor).visit(this); + } else { + return visitor.visit(binding); + } + } + @Override public Key> getKey() { return optionalKey; diff --git a/core/src/com/google/inject/spi/BindingTargetVisitor.java b/core/src/com/google/inject/spi/BindingTargetVisitor.java index 890aebacd7..96f0b837f9 100644 --- a/core/src/com/google/inject/spi/BindingTargetVisitor.java +++ b/core/src/com/google/inject/spi/BindingTargetVisitor.java @@ -37,6 +37,12 @@ public interface BindingTargetVisitor { */ V visit(ProviderInstanceBinding binding); + /** + * Visit a {@link jakarta.inject.Provider} instance binding. The provider's {@code get} method + * is invoked to resolve injections. This target is found in both module and injector bindings. + */ + V visit(JeeProviderInstanceBinding binding); + /** * Visit a provider key binding. To resolve injections, the provider key is first resolved, then * that provider's {@code get} method is invoked. This target is found in both module and injector @@ -44,6 +50,13 @@ public interface BindingTargetVisitor { */ V visit(ProviderKeyBinding binding); + /** + * Visit a {@link jakarta.inject.Provider} key binding. To resolve injections, the provider key is + * first resolved, then that provider's {@code get} method is invoked. This target is found in + * both module and injector bindings. + */ + V visit(JeeProviderKeyBinding binding); + /** * Visit a linked key binding. The other key's binding is used to resolve injections. This target * is found in both module and injector bindings. diff --git a/core/src/com/google/inject/spi/DefaultBindingTargetVisitor.java b/core/src/com/google/inject/spi/DefaultBindingTargetVisitor.java index 5bd1066124..a2a2d215fd 100644 --- a/core/src/com/google/inject/spi/DefaultBindingTargetVisitor.java +++ b/core/src/com/google/inject/spi/DefaultBindingTargetVisitor.java @@ -44,11 +44,21 @@ public V visit(ProviderInstanceBinding providerInstanceBinding) { return visitOther(providerInstanceBinding); } + @Override + public V visit(JeeProviderInstanceBinding providerInstanceBinding) { + return visitOther(providerInstanceBinding); + } + @Override public V visit(ProviderKeyBinding providerKeyBinding) { return visitOther(providerKeyBinding); } + @Override + public V visit(JeeProviderKeyBinding providerKeyBinding) { + return visitOther(providerKeyBinding); + } + @Override public V visit(LinkedKeyBinding linkedKeyBinding) { return visitOther(linkedKeyBinding); diff --git a/core/src/com/google/inject/spi/JeeProviderInstanceBinding.java b/core/src/com/google/inject/spi/JeeProviderInstanceBinding.java new file mode 100644 index 0000000000..68741038c1 --- /dev/null +++ b/core/src/com/google/inject/spi/JeeProviderInstanceBinding.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2022 Google Inc. + * + * 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. + */ + +package com.google.inject.spi; + +import com.google.inject.Binding; +import com.google.inject.Provider; +import java.util.Set; + +/** + * A binding to a {@link jakarta.inject.Provider} instance. The provider's {@code get} method is + * invoked to resolve injections. + */ +public interface JeeProviderInstanceBinding extends Binding, HasDependencies { + + /** + * Returns the user-supplied, unscoped provider. + * + * @since 4.0 + */ + jakarta.inject.Provider getUserSuppliedProvider(); + + /** + * Returns the field and method injection points of the provider, injected at injector-creation + * time only. + * + * @return a possibly empty set + */ + Set getInjectionPoints(); +} diff --git a/core/src/com/google/inject/spi/JeeProviderKeyBinding.java b/core/src/com/google/inject/spi/JeeProviderKeyBinding.java new file mode 100644 index 0000000000..4e6e2159b7 --- /dev/null +++ b/core/src/com/google/inject/spi/JeeProviderKeyBinding.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2022 Google Inc. + * + * 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. + */ + +package com.google.inject.spi; + +import com.google.inject.Binding; +import com.google.inject.Key; + +/** + * A binding to a provider key. To resolve injections, the provider key is first resolved, then that + * provider's {@code get} method is invoked. + */ +public interface JeeProviderKeyBinding extends Binding { + + /** + * Returns the key used to resolve the provider's binding. That binding can be retrieved from an + * injector using + * {@link com.google.inject.Injector#getBinding(Key) Injector.getBinding(providerKey)} + */ + Key> getProviderKey(); +} diff --git a/core/src/com/google/inject/spi/ProviderWithExtensionVisitor.java b/core/src/com/google/inject/spi/ProviderWithExtensionVisitor.java index 582515ecba..7ea9aa33fa 100644 --- a/core/src/com/google/inject/spi/ProviderWithExtensionVisitor.java +++ b/core/src/com/google/inject/spi/ProviderWithExtensionVisitor.java @@ -58,4 +58,7 @@ public interface ProviderWithExtensionVisitor extends Provider { */ V acceptExtensionVisitor( BindingTargetVisitor visitor, ProviderInstanceBinding binding); + + V acceptExtensionVisitor( + BindingTargetVisitor visitor, JeeProviderInstanceBinding binding); } diff --git a/core/test/com/google/inject/spi/SpiBindingsTest.java b/core/test/com/google/inject/spi/SpiBindingsTest.java index 4d7d26a11d..65cb8ec26c 100644 --- a/core/test/com/google/inject/spi/SpiBindingsTest.java +++ b/core/test/com/google/inject/spi/SpiBindingsTest.java @@ -29,7 +29,6 @@ import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Module; -import com.google.inject.Provider; import com.google.inject.Scope; import com.google.inject.Scopes; import com.google.inject.Singleton; @@ -42,6 +41,7 @@ import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Logger; +import javax.inject.Provider; import junit.framework.AssertionFailedError; import junit.framework.TestCase; @@ -129,6 +129,35 @@ public Void visit(ProviderInstanceBinding binding) { }); } + public void testToJeeProviderBinding() { + final jakarta.inject.Provider stringProvider = new JeeStringProvider(); + + checkInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toJeeProvider(stringProvider); + } + }, + new FailingElementVisitor() { + @Override + public Void visit(Binding binding) { + assertTrue(binding instanceof JeeProviderInstanceBinding); + checkBindingSource(binding); + assertEquals(Key.get(String.class), binding.getKey()); + binding.acceptTargetVisitor( + new FailingTargetVisitor() { + @Override + public Void visit(JeeProviderInstanceBinding binding) { + assertSame(stringProvider, binding.getUserSuppliedProvider()); + return null; + } + }); + return null; + } + }); + } + public void testToProviderKeyBinding() { checkInjector( new AbstractModule() { @@ -156,6 +185,33 @@ public Void visit(ProviderKeyBinding binding) { }); } + public void testToJeeProviderKeyBinding() { + checkInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toJeeProvider(JeeStringProvider.class); + } + }, + new FailingElementVisitor() { + @Override + public Void visit(Binding binding) { + assertTrue(binding instanceof JeeProviderKeyBinding); + checkBindingSource(binding); + assertEquals(Key.get(String.class), binding.getKey()); + binding.acceptTargetVisitor( + new FailingTargetVisitor() { + @Override + public Void visit(JeeProviderKeyBinding binding) { + assertEquals(Key.get(JeeStringProvider.class), binding.getProviderKey()); + return null; + } + }); + return null; + } + }); + } + public void testToKeyBinding() { final Key aKey = Key.get(String.class, Names.named("a")); final Key bKey = Key.get(String.class, Names.named("b")); @@ -300,6 +356,31 @@ public Void visit(ProviderBinding> binding) { }); } + public void testJeeProviderBinding() { + Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class).toInstance("A"); + } + }); + + Key> providerOfStringKey = new Key>() {}; + Binding> binding = injector.getBinding(providerOfStringKey); + assertEquals(providerOfStringKey, binding.getKey()); + checkBindingSource(binding); + assertTrue(binding instanceof ProviderBinding); + binding.acceptTargetVisitor( + new FailingTargetVisitor>() { + @Override + public Void visit(ProviderBinding> binding) { + assertEquals(Key.get(String.class), binding.getProvidedKey()); + return null; + } + }); + } + public void testScopes() { checkInjector( new AbstractModule() { @@ -411,6 +492,15 @@ public V acceptExtensionVisitor( } } + @SuppressWarnings("unchecked") // Safe because V is fixed to String + @Override + public V acceptExtensionVisitor( + BindingTargetVisitor visitor, + JeeProviderInstanceBinding binding) { + fail(); + return null; + } + @Override public String get() { return "FooBar"; @@ -444,6 +534,78 @@ public Void visit(ProviderBinding> binding) { assertEquals("visited", binding.acceptTargetVisitor(new FailingSpiTargetVisitor())); } + public void testJeeExtensionSpi() { + final AtomicBoolean visiting = new AtomicBoolean(false); + + final Injector injector = + Guice.createInjector( + new AbstractModule() { + @Override + protected void configure() { + bind(String.class) + .toJeeProvider( + new ProviderWithExtensionVisitor() { + @SuppressWarnings("unchecked") // Safe because V is fixed to String + @Override + public V acceptExtensionVisitor( + BindingTargetVisitor visitor, + JeeProviderInstanceBinding binding) { + assertSame(this, binding.getUserSuppliedProvider()); + // We can't always check for FailingSpiTargetVisitor, + // because constructing the injector visits here, and we need + // to process the binding as normal + if (visiting.get()) { + assertTrue( + "visitor: " + visitor, + visitor instanceof FailingSpiTargetVisitor); + return (V) "visited"; + } else { + return visitor.visit(binding); + } + } + + @SuppressWarnings("unchecked") // Safe because V is fixed to String + @Override + public V acceptExtensionVisitor( + BindingTargetVisitor visitor, + ProviderInstanceBinding binding) { + fail(); + return null; + } + + @Override + public String get() { + return "FooBar"; + } + }); + } + }); + + visiting.set(true); + + // Check for Provider binding -- that is still a ProviderBinding. + Key> providerOfStringKey = new Key>() {}; + Binding> providerBinding = injector.getBinding(providerOfStringKey); + assertEquals(providerOfStringKey, providerBinding.getKey()); + checkBindingSource(providerBinding); + assertTrue("binding: " + providerBinding, providerBinding instanceof ProviderBinding); + providerBinding.acceptTargetVisitor( + new FailingTargetVisitor>() { + @Override + public Void visit(ProviderBinding> binding) { + assertEquals(Key.get(String.class), binding.getProvidedKey()); + return null; + } + }); + + // Check for String binding -- that one is ProviderInstanceBinding, and gets hooked + Binding binding = injector.getBinding(String.class); + assertEquals(Key.get(String.class), binding.getKey()); + checkBindingSource(binding); + assertTrue(binding instanceof JeeProviderInstanceBinding); + assertEquals("visited", binding.acceptTargetVisitor(new FailingSpiTargetVisitor())); + } + private static class FailingSpiTargetVisitor extends DefaultBindingTargetVisitor { @Override protected String visitOther(Binding binding) { @@ -490,6 +652,13 @@ public String get() { } } + private static class JeeStringProvider implements jakarta.inject.Provider { + @Override + public String get() { + return "J"; + } + } + private static class C {} private static class D extends C { diff --git a/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryProvider2.java b/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryProvider2.java index 91ba86b1b0..ed359c41f3 100644 --- a/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryProvider2.java +++ b/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryProvider2.java @@ -50,6 +50,7 @@ import com.google.inject.spi.Dependency; import com.google.inject.spi.HasDependencies; import com.google.inject.spi.InjectionPoint; +import com.google.inject.spi.JeeProviderInstanceBinding; import com.google.inject.spi.Message; import com.google.inject.spi.ProviderInstanceBinding; import com.google.inject.spi.ProviderWithExtensionVisitor; @@ -535,6 +536,16 @@ public V acceptExtensionVisitor( return visitor.visit(binding); } + @Override + @SuppressWarnings("unchecked") + public V acceptExtensionVisitor( + BindingTargetVisitor visitor, JeeProviderInstanceBinding binding) { + if (visitor instanceof AssistedInjectTargetVisitor) { + return ((AssistedInjectTargetVisitor) visitor).visit((AssistedInjectBinding) this); + } + return visitor.visit(binding); + } + private void validateFactoryReturnType(Errors errors, Class returnType, Class factoryType) { if (Modifier.isPublic(factoryType.getModifiers()) && !Modifier.isPublic(returnType.getModifiers())) { diff --git a/extensions/jakarta-servlet/src/com/google/inject/servlet/jee/FilterDefinition.java b/extensions/jakarta-servlet/src/com/google/inject/servlet/jee/FilterDefinition.java index 81d43d102a..4855e166d6 100644 --- a/extensions/jakarta-servlet/src/com/google/inject/servlet/jee/FilterDefinition.java +++ b/extensions/jakarta-servlet/src/com/google/inject/servlet/jee/FilterDefinition.java @@ -20,6 +20,7 @@ import com.google.inject.Key; import com.google.inject.Scopes; import com.google.inject.spi.BindingTargetVisitor; +import com.google.inject.spi.JeeProviderInstanceBinding; import com.google.inject.spi.ProviderInstanceBinding; import com.google.inject.spi.ProviderWithExtensionVisitor; import java.util.Collections; @@ -81,6 +82,22 @@ public V acceptExtensionVisitor( } } + @Override + public V acceptExtensionVisitor( + BindingTargetVisitor visitor, JeeProviderInstanceBinding binding) { + if (visitor instanceof ServletModuleTargetVisitor) { + if (filterInstance != null) { + return ((ServletModuleTargetVisitor) visitor) + .visit(new InstanceFilterBindingImpl(initParams, filterInstance, patternMatcher)); + } else { + return ((ServletModuleTargetVisitor) visitor) + .visit(new LinkedFilterBindingImpl(initParams, filterKey, patternMatcher)); + } + } else { + return visitor.visit(binding); + } + } + private boolean shouldFilter(String uri) { return uri != null && patternMatcher.matches(uri); } diff --git a/extensions/jakarta-servlet/src/com/google/inject/servlet/jee/InternalServletModule.java b/extensions/jakarta-servlet/src/com/google/inject/servlet/jee/InternalServletModule.java index f4a7730ecf..9e1603e7e5 100644 --- a/extensions/jakarta-servlet/src/com/google/inject/servlet/jee/InternalServletModule.java +++ b/extensions/jakarta-servlet/src/com/google/inject/servlet/jee/InternalServletModule.java @@ -96,7 +96,7 @@ protected void configure() { bind(ManagedServletPipeline.class); bind(FilterPipeline.class).to(ManagedFilterPipeline.class).asEagerSingleton(); - bind(ServletContext.class).toProvider(BackwardsCompatibleServletContextProvider.class); + bind(ServletContext.class).toJeeProvider(BackwardsCompatibleServletContextProvider.class); bind(BackwardsCompatibleServletContextProvider.class); } diff --git a/extensions/jakarta-servlet/src/com/google/inject/servlet/jee/ServletDefinition.java b/extensions/jakarta-servlet/src/com/google/inject/servlet/jee/ServletDefinition.java index 7e6232d235..62e7225bf5 100644 --- a/extensions/jakarta-servlet/src/com/google/inject/servlet/jee/ServletDefinition.java +++ b/extensions/jakarta-servlet/src/com/google/inject/servlet/jee/ServletDefinition.java @@ -22,6 +22,7 @@ import com.google.inject.Key; import com.google.inject.Scopes; import com.google.inject.spi.BindingTargetVisitor; +import com.google.inject.spi.JeeProviderInstanceBinding; import com.google.inject.spi.ProviderInstanceBinding; import com.google.inject.spi.ProviderWithExtensionVisitor; import java.io.IOException; @@ -91,6 +92,22 @@ public V acceptExtensionVisitor( } } + @Override + public V acceptExtensionVisitor( + BindingTargetVisitor visitor, JeeProviderInstanceBinding binding) { + if (visitor instanceof ServletModuleTargetVisitor) { + if (servletInstance != null) { + return ((ServletModuleTargetVisitor) visitor) + .visit(new InstanceServletBindingImpl(initParams, servletInstance, patternMatcher)); + } else { + return ((ServletModuleTargetVisitor) visitor) + .visit(new LinkedServletBindingImpl(initParams, servletKey, patternMatcher)); + } + } else { + return visitor.visit(binding); + } + } + boolean shouldServe(String uri) { return uri != null && patternMatcher.matches(uri); } diff --git a/extensions/servlet/src/com/google/inject/servlet/FilterDefinition.java b/extensions/servlet/src/com/google/inject/servlet/FilterDefinition.java index 03ead930a0..80dee544c3 100644 --- a/extensions/servlet/src/com/google/inject/servlet/FilterDefinition.java +++ b/extensions/servlet/src/com/google/inject/servlet/FilterDefinition.java @@ -20,6 +20,7 @@ import com.google.inject.Key; import com.google.inject.Scopes; import com.google.inject.spi.BindingTargetVisitor; +import com.google.inject.spi.JeeProviderInstanceBinding; import com.google.inject.spi.ProviderInstanceBinding; import com.google.inject.spi.ProviderWithExtensionVisitor; import java.util.Collections; @@ -81,6 +82,22 @@ public V acceptExtensionVisitor( } } + @Override + public V acceptExtensionVisitor( + BindingTargetVisitor visitor, JeeProviderInstanceBinding binding) { + if (visitor instanceof ServletModuleTargetVisitor) { + if (filterInstance != null) { + return ((ServletModuleTargetVisitor) visitor) + .visit(new InstanceFilterBindingImpl(initParams, filterInstance, patternMatcher)); + } else { + return ((ServletModuleTargetVisitor) visitor) + .visit(new LinkedFilterBindingImpl(initParams, filterKey, patternMatcher)); + } + } else { + return visitor.visit(binding); + } + } + private boolean shouldFilter(String uri) { return uri != null && patternMatcher.matches(uri); } diff --git a/extensions/servlet/src/com/google/inject/servlet/ServletDefinition.java b/extensions/servlet/src/com/google/inject/servlet/ServletDefinition.java index 68e134b1bb..484aab32fe 100644 --- a/extensions/servlet/src/com/google/inject/servlet/ServletDefinition.java +++ b/extensions/servlet/src/com/google/inject/servlet/ServletDefinition.java @@ -22,6 +22,7 @@ import com.google.inject.Key; import com.google.inject.Scopes; import com.google.inject.spi.BindingTargetVisitor; +import com.google.inject.spi.JeeProviderInstanceBinding; import com.google.inject.spi.ProviderInstanceBinding; import com.google.inject.spi.ProviderWithExtensionVisitor; import java.io.IOException; @@ -91,6 +92,22 @@ public V acceptExtensionVisitor( } } + @Override + public V acceptExtensionVisitor( + BindingTargetVisitor visitor, JeeProviderInstanceBinding binding) { + if (visitor instanceof ServletModuleTargetVisitor) { + if (servletInstance != null) { + return ((ServletModuleTargetVisitor) visitor) + .visit(new InstanceServletBindingImpl(initParams, servletInstance, patternMatcher)); + } else { + return ((ServletModuleTargetVisitor) visitor) + .visit(new LinkedServletBindingImpl(initParams, servletKey, patternMatcher)); + } + } else { + return visitor.visit(binding); + } + } + boolean shouldServe(String uri) { return uri != null && patternMatcher.matches(uri); }