rmannibucau commented on code in PR #1393: URL: https://github.com/apache/maven/pull/1393#discussion_r1466553837
########## api/maven-api-di/src/main/java/org/apache/maven/api/di/Transient.java: ########## @@ -0,0 +1,31 @@ +/* + * 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. + */ +package org.apache.maven.api.di; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +@Target(METHOD) +@Retention(RUNTIME) +@Documented +public @interface Transient {} Review Comment: Needed? why not use a scope (prototype, default, whatever name) ########## maven-di/src/main/java/org/apache/maven/api/di/ProvidesIntoSet.java: ########## @@ -0,0 +1,38 @@ +/* + * 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. + */ +package org.apache.maven.api.di; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import org.apache.maven.di.binding.Multibinders; +import org.apache.maven.di.module.AbstractModule; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * This is a built-in shortcut for {@link Provides provider method} that provides its result as a singleton set + * and adds a {@link Multibinders#toSet() set multibinder} for the provided set key to the module. + * + * @see AbstractModule + */ +@Target(METHOD) +@Retention(RUNTIME) +public @interface ProvidesIntoSet {} Review Comment: guice leak? not sure we need this one ########## maven-di/src/main/java/org/apache/maven/di/module/UniqueQualifierImpl.java: ########## @@ -0,0 +1,50 @@ +/* + * 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. + */ +package org.apache.maven.di.module; + +import java.lang.annotation.Annotation; + +import org.apache.maven.api.annotations.Nullable; + +@SuppressWarnings("ClassExplicitlyAnnotation") +public final class UniqueQualifierImpl implements UniqueQualifier { Review Comment: cant we reuse it as binding too? (a bit like cdi does with annotation literals) ########## api/maven-api-di/src/main/java/org/apache/maven/api/di/Scope.java: ########## @@ -0,0 +1,33 @@ +/* + * 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. + */ +package org.apache.maven.api.di; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +@Target(ANNOTATION_TYPE) +@Retention(RUNTIME) +@Documented +public @interface Scope { + boolean threadsafe() default true; Review Comment: Needed? ########## maven-di/src/main/java/org/apache/maven/di/ResourceLocator.java: ########## @@ -0,0 +1,58 @@ +/* + * 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. + */ +package org.apache.maven.di; + +import java.util.function.Supplier; + +import org.apache.maven.api.annotations.Nullable; + +public interface ResourceLocator { + <T> T getInstance(Key<T> key); + + default <T> T getInstance(Class<T> type) { + return getInstance(Key.of(type)); + } + + <T> @Nullable T getInstanceOrNull(Key<T> key); Review Comment: guess all the next getInstances can be replaced by getOptionalInstance and the cases be managed by `Optional` directly instead of duplicating API? ########## maven-di/src/main/java/org/apache/maven/di/Injector.java: ########## @@ -0,0 +1,613 @@ +/* + * 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. + */ +package org.apache.maven.di; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.*; +import java.util.Map.Entry; +import java.util.concurrent.atomic.AtomicReferenceArray; +import java.util.function.Supplier; +import java.util.function.UnaryOperator; + +import org.apache.maven.api.annotations.Nullable; +import org.apache.maven.di.binding.*; +import org.apache.maven.di.impl.CompiledBinding; +import org.apache.maven.di.impl.CompiledBindingLocator; +import org.apache.maven.di.impl.Preprocessor; +import org.apache.maven.di.module.Module; +import org.apache.maven.di.module.Modules; +import org.apache.maven.di.util.Trie; +import org.apache.maven.di.util.Utils; + +import static java.util.stream.Collectors.toMap; +import static org.apache.maven.di.Scope.UNSCOPED; +import static org.apache.maven.di.util.Types.parameterizedType; + +/** + * Injector is the main working component of the ActiveJ Inject. + * <p> + * It stores a trie of binding graphs and a cache of already made singletons. + * <p> + * Each injector is associated with exactly zero or one instance per {@link Key}. + * <p> + * Injector uses binding graph at the root of the trie to recursively create and then store instances of objects + * associated with some {@link Key keys}. + * Branches of the trie are used to {@link #enterScope enter scopes}. + */ +@SuppressWarnings({"unused", "WeakerAccess", "rawtypes"}) +public final class Injector implements ResourceLocator { + static class ScopeLocalData { + final Scope[] scope; + final Map<Key<?>, Binding<?>> bindings; + final Map<Key<?>, CompiledBinding<?>> compiledBindings; + final Map<Key<?>, Integer> slotMapping; + final int slots; + final CompiledBinding<?>[] eagerSingletons; + + ScopeLocalData( + Scope[] scope, + Map<Key<?>, Binding<?>> bindings, + Map<Key<?>, CompiledBinding<?>> compiledBindings, + Map<Key<?>, Integer> slotMapping, + int slots, + CompiledBinding<?>[] eagerSingletons) { + this.scope = scope; + this.bindings = bindings; + this.compiledBindings = compiledBindings; + this.slotMapping = slotMapping; + this.slots = slots; + this.eagerSingletons = eagerSingletons; + } + } + + final @Nullable Injector parent; + final Trie<Scope, ScopeLocalData> scopeDataTree; + + final Map<Key<?>, Integer> localSlotMapping; + final Map<Key<?>, CompiledBinding<?>> localCompiledBindings; + + final AtomicReferenceArray[] scopeCaches; + + private static Supplier<UnaryOperator<CompiledBinding<?>>> bytecodePostprocessorFactory = UnaryOperator::identity; + + /** + * Enables specialization of compiled bindings. <b>Depends on {@code ActiveJ-Specializer} module</b> + */ + @SuppressWarnings("unchecked") + public static void useSpecializer() { Review Comment: do we use it? if so we should either require it (no reflection) or drop it no? ########## maven-di/src/main/java/org/apache/maven/api/di/Scopes.java: ########## @@ -0,0 +1,38 @@ +/* + * 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. + */ +package org.apache.maven.api.di; + +import java.lang.annotation.Annotation; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * This is a special annotation that allows you to declare bindings in nested scopes + * using {@link Provides provider methods}. + * <p> + * Note that it does not allow you to use stateful scope annotations. + */ +@Retention(RUNTIME) +@Target(ElementType.METHOD) +public @interface Scopes { Review Comment: needed? ########## maven-di/src/main/java/org/apache/maven/di/impl/AbstractCompiledBinding.java: ########## @@ -0,0 +1,60 @@ +/* + * 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. + */ +package org.apache.maven.di.impl; + +import java.util.concurrent.atomic.AtomicReferenceArray; + +@SuppressWarnings("rawtypes") +public abstract class AbstractCompiledBinding<R> implements CompiledBinding<R> { + protected final int scope; + + protected final int index; + + protected AbstractCompiledBinding(int scope, int index) { + this.scope = scope; + this.index = index; + } + + @SuppressWarnings("unchecked") + @Override + public final R getInstance(AtomicReferenceArray[] scopedInstances, int synchronizedScope) { + AtomicReferenceArray array = scopedInstances[scope]; + R instance = (R) array.get(index); + if (instance != null) { + return instance; + } + if (synchronizedScope == scope) { Review Comment: im tempted to drop this notion and just always lock, wdyt? ########## maven-di/src/main/java/org/apache/maven/di/binding/Bindings.java: ########## @@ -0,0 +1,609 @@ +/* + * 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. + */ +package org.apache.maven.di.binding; + +import java.util.*; +import java.util.concurrent.atomic.AtomicReferenceArray; + +import org.apache.maven.api.annotations.Nullable; +import org.apache.maven.di.Key; +import org.apache.maven.di.impl.*; +import org.apache.maven.di.module.Tuples.*; + +@SuppressWarnings({"unchecked", "rawtypes", "Convert2Lambda"}) +public class Bindings { + + public static class BindingToInstance<T> extends Binding<T> { + final T instance; + + BindingToInstance(T instance) { + super(Collections.emptySet()); + this.instance = instance; + } + + @Override + public CompiledBinding<T> compile( + CompiledBindingLocator compiledBindings, boolean threadsafe, int scope, @Nullable Integer slot) { + final T instance = this.instance; + return slot != null + ? new CompiledBinding<T>() { + @Override + public T getInstance(AtomicReferenceArray[] scopedInstances, int synchronizedScope) { + scopedInstances[scope].lazySet(slot, instance); + return instance; + } + } + : new CompiledBinding<T>() { + @Override + public T getInstance(AtomicReferenceArray[] scopedInstances, int synchronizedScope) { + return instance; + } + }; + } + } + + public static class BindingToConstructorN<R> extends Binding<R> { + final TupleConstructorN<R> constructor; + final Key<?>[] dependencies; + + BindingToConstructorN(TupleConstructorN<R> constructor, Key<?>[] dependencies) { + super(new HashSet<>(Arrays.asList(dependencies))); + this.constructor = constructor; + this.dependencies = dependencies; + } + + @Override + public CompiledBinding<R> compile( + CompiledBindingLocator compiledBindings, boolean threadsafe, int scope, @Nullable Integer slot) { + final TupleConstructorN<R> constructor = this.constructor; + final CompiledBinding<?>[] bindings = + Arrays.stream(dependencies).map(compiledBindings::get).toArray(CompiledBinding[]::new); + return slot != null + ? threadsafe + ? scope == 0 + ? new AbstractRootCompiledBinding<R>(slot) { + @Override + protected R doCreateInstance( + AtomicReferenceArray[] scopedInstances, int synchronizedScope) { + Object[] args = new Object[bindings.length]; + for (int i = 0; i < bindings.length; i++) { + args[i] = bindings[i].getInstance(scopedInstances, synchronizedScope); + } + return constructor.create(args); + } + } + : new AbstractCompiledBinding<R>(scope, slot) { + @Override + protected R doCreateInstance( + AtomicReferenceArray[] scopedInstances, int synchronizedScope) { + Object[] args = new Object[bindings.length]; + for (int i = 0; i < bindings.length; i++) { + args[i] = bindings[i].getInstance(scopedInstances, synchronizedScope); + } + return constructor.create(args); + } + } + : new AbstractUnsyncCompiledBinding<R>(scope, slot) { + @Override + protected R doCreateInstance( + AtomicReferenceArray[] scopedInstances, int synchronizedScope) { + Object[] args = new Object[bindings.length]; + for (int i = 0; i < bindings.length; i++) { + args[i] = bindings[i].getInstance(scopedInstances, synchronizedScope); + } + return constructor.create(args); + } + } + : new CompiledBinding<R>() { + @Override + public R getInstance(AtomicReferenceArray[] scopedInstances, int synchronizedScope) { + Object[] args = new Object[bindings.length]; + for (int i = 0; i < bindings.length; i++) { + args[i] = bindings[i].getInstance(scopedInstances, synchronizedScope); + } + return constructor.create(args); + } + }; + } + } + + public static class BindingToConstructor0<R> extends Binding<R> { + final TupleConstructor0<R> constructor; + + BindingToConstructor0(TupleConstructor0<R> constructor) { + super(Collections.emptySet()); + this.constructor = constructor; + } + + @Override + public CompiledBinding<R> compile( + CompiledBindingLocator compiledBindings, boolean threadsafe, int scope, @Nullable Integer slot) { + final TupleConstructor0<R> constructor = this.constructor; + return slot != null + ? threadsafe + ? scope == 0 + ? new AbstractRootCompiledBinding<R>(slot) { + @Override + protected R doCreateInstance( + AtomicReferenceArray[] scopedInstances, int synchronizedScope) { + return constructor.create(); + } + } + : new AbstractCompiledBinding<R>(scope, slot) { + @Override + protected R doCreateInstance( + AtomicReferenceArray[] scopedInstances, int synchronizedScope) { + return constructor.create(); + } + } + : new AbstractUnsyncCompiledBinding<R>(scope, slot) { + @Override + protected R doCreateInstance( + AtomicReferenceArray[] scopedInstances, int synchronizedScope) { + return constructor.create(); + } + } + : new CompiledBinding<R>() { + @Override + public R getInstance(AtomicReferenceArray[] scopedInstances, int synchronizedScope) { + return constructor.create(); + } + }; + } + } + + public static class BindingToConstructor1<R, T1> extends Binding<R> { Review Comment: do we need all these flavors? -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
