pax_global_header00006660000000000000000000000064130106613740014513gustar00rootroot0000000000000052 comment=f2196bcc14d38b085ea5e57407b1ec441cd99703 sejda-injector-1.0.2/000077500000000000000000000000001301066137400144145ustar00rootroot00000000000000sejda-injector-1.0.2/.gitignore000066400000000000000000000001641301066137400164050ustar00rootroot00000000000000*.class .classpath .project .launch .settings/ target/ .externalToolBuilders/ # Package Files # *.jar *.war *.ear sejda-injector-1.0.2/.travis.yml000066400000000000000000000000571301066137400165270ustar00rootroot00000000000000language: java sudo: false jdk: - oraclejdk8 sejda-injector-1.0.2/LICENSE000066400000000000000000000240411301066137400154220ustar00rootroot00000000000000Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: You must give any other recipients of the Work or Derivative Works a copy of this License; and You must cause any modified files to carry prominent notices stating that You changed the files; and You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] 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. sejda-injector-1.0.2/README.md000066400000000000000000000006371301066137400157010ustar00rootroot00000000000000Sejda-injector (http://www.sejda.org) ===== [![Build Status](https://travis-ci.org/torakiki/pdfsam-injector.png)](https://travis-ci.org/torakiki/pdfsam-injector) [![License](http://img.shields.io/badge/license-APLv2-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) A simple dependency injection engine based on [Feather](https://github.com/zsoltherpai/feather) and used in [PDFsam](http://pdfsam.org). sejda-injector-1.0.2/development/000077500000000000000000000000001301066137400167365ustar00rootroot00000000000000sejda-injector-1.0.2/development/eclipse/000077500000000000000000000000001301066137400203625ustar00rootroot00000000000000sejda-injector-1.0.2/development/eclipse/checkstyle plugin/000077500000000000000000000000001301066137400237775ustar00rootroot00000000000000sejda-injector-1.0.2/development/eclipse/checkstyle plugin/checkstyle.xml000066400000000000000000000105061301066137400266610ustar00rootroot00000000000000 sejda-injector-1.0.2/development/eclipse/checkstyle plugin/suppression.xml000066400000000000000000000003611301066137400271130ustar00rootroot00000000000000 sejda-injector-1.0.2/development/eclipse/code_format.xml000066400000000000000000000716461301066137400234040ustar00rootroot00000000000000 sejda-injector-1.0.2/development/eclipse/codetemplates.xml000066400000000000000000000125471301066137400237460ustar00rootroot00000000000000sejda-injector-1.0.2/development/eclipse/eclipse_compiler_settings.epf000066400000000000000000000053451301066137400263230ustar00rootroot00000000000000#Sat Jul 23 15:11:52 CEST 2011 /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=error /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error \!/= /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.emptyStatement=warning /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=enabled /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.enumIdentifier=error /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.fieldHiding=warning /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=disabled /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.assertIdentifier=error /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=disabled /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=warning /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=error /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=disabled /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.compliance=1.6 /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.unusedImport=error /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.source=1.6 file_export_version=3.0 @org.eclipse.jdt.core=3.6.2.v_A76_R36x sejda-injector-1.0.2/pom.xml000066400000000000000000000112231301066137400157300ustar00rootroot00000000000000 4.0.0 org.sejda sejda-injector jar sejda-injector 1.0.2 A simple dependency injection engine based on Feather http://www.sejda.org GitHub https://github.com/torakiki/sejda-injector/ sejda http://www.sejda.org Apache License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0 repo ASLv2 UTF-8 scm:git:git@github.com:torakiki/sejda-injector.git scm:git:git@github.com:torakiki/sejda-injector.git scm:git:git@github.com:torakiki/sejda-injector.git v1.0.2 torakiki Andrea Vacondio andrea.vacondio@gmail.com sonatype-nexus-snapshots https://oss.sonatype.org/content/repositories/snapshots bintray https://api.bintray.com/maven/sejdapdf/maven/sejda release org.apache.maven.plugins maven-javadoc-plugin 2.10.3 attach-javadocs jar org.apache.maven.plugins maven-release-plugin 2.5.2 v@{project.version} true clean install org.apache.maven.plugins maven-gpg-plugin 1.6 sign-artifacts verify sign org.apache.maven.plugins maven-compiler-plugin 3.3 1.8 1.8 true lines,vars,source org.apache.maven.plugins maven-jar-plugin 2.6 org.apache.maven.plugins maven-source-plugin 2.4 attach-sources jar-no-fork org.slf4j slf4j-api 1.7.21 ch.qos.logback logback-classic 1.1.7 test org.mockito mockito-core 1.10.19 test junit junit 4.12 test org.hamcrest hamcrest-core 1.3 test javax.inject javax.inject 1 sejda-injector-1.0.2/src/000077500000000000000000000000001301066137400152035ustar00rootroot00000000000000sejda-injector-1.0.2/src/main/000077500000000000000000000000001301066137400161275ustar00rootroot00000000000000sejda-injector-1.0.2/src/main/java/000077500000000000000000000000001301066137400170505ustar00rootroot00000000000000sejda-injector-1.0.2/src/main/java/org/000077500000000000000000000000001301066137400176375ustar00rootroot00000000000000sejda-injector-1.0.2/src/main/java/org/sejda/000077500000000000000000000000001301066137400207255ustar00rootroot00000000000000sejda-injector-1.0.2/src/main/java/org/sejda/injector/000077500000000000000000000000001301066137400225425ustar00rootroot00000000000000sejda-injector-1.0.2/src/main/java/org/sejda/injector/Auto.java000066400000000000000000000020701301066137400243140ustar00rootroot00000000000000/* * 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 org.sejda.injector; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import javax.inject.Singleton; /** * Configure the injector to automatically create the singleton instance * * @author Andrea Vacondio */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.METHOD, ElementType.TYPE }) @Singleton public @interface Auto { } sejda-injector-1.0.2/src/main/java/org/sejda/injector/Components.java000066400000000000000000000022021301066137400255260ustar00rootroot00000000000000/* * 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 org.sejda.injector; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Condiguration instances can be annotated with classes to tell the injector it should scan those classes. * * @author Andrea Vacondio * */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface Components { /** * Classes to scan and add to the injector */ Class[] value() default {}; } sejda-injector-1.0.2/src/main/java/org/sejda/injector/InjectionException.java000066400000000000000000000014711301066137400272110ustar00rootroot00000000000000/* * 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 org.sejda.injector; public class InjectionException extends RuntimeException { InjectionException(String message) { super(message); } InjectionException(String message, Throwable cause) { super(message, cause); } } sejda-injector-1.0.2/src/main/java/org/sejda/injector/Injector.java000066400000000000000000000341621301066137400251700ustar00rootroot00000000000000/* * 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 org.sejda.injector; import static java.util.Collections.singleton; import static java.util.Objects.isNull; import static java.util.Objects.nonNull; import static java.util.Optional.ofNullable; import static java.util.stream.Collectors.joining; import static java.util.stream.Stream.concat; import static java.util.stream.Stream.of; import java.io.Closeable; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Queue; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import javax.inject.Inject; import javax.inject.Provider; import javax.inject.Qualifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Injector implements Closeable { private static final Logger LOG = LoggerFactory.getLogger(Injector.class); private static final Queue CONFIGURATIONS = new ConcurrentLinkedQueue<>(); private static final Map, Class> COMPONENTS = new ConcurrentHashMap<>(); private final Map, Provider> providers = new ConcurrentHashMap<>(); private final Map, Object> singletons = new ConcurrentHashMap<>(); private final Set> autos = new HashSet<>(); public static void addConfig(Object... configurations) { Arrays.stream(configurations).forEach(CONFIGURATIONS::add); } public static void addConfig(Iterable configurations) { for (Object config : configurations) { CONFIGURATIONS.add(config); } } /** * Adds the given components classes to the injectable ones * * @param components */ public static void add(Class... components) { Arrays.stream(components).forEach(c -> COMPONENTS.put(c, c)); } /** * @return the context started with the given additional configurations */ public static Injector start(Object... configurations) { Injector.addConfig(configurations); return Injector.start(); } /** * @return the context started with the given additional configurations */ public static Injector start(Iterable configurations) { Injector.addConfig(configurations); return Injector.start(); } /** * @return the context started with the previously provided configuration */ public static Injector start() { LOG.debug("Starting injector with {} configuration modules", CONFIGURATIONS.size()); return new Injector(); } @Override public void close() { LOG.debug("Closing injector"); this.providers.clear(); this.singletons.clear(); } private Injector() { providers.put(Key.of(Injector.class), () -> this); try { for (final Object config : CONFIGURATIONS) { if (config instanceof Class) { throw new InjectionException(String.format("%s provided as class instead of an instance.", ((Class) config).getName())); } for (Method providerMethod : providers(config.getClass())) { providerMethod(config, providerMethod); } ofNullable(config.getClass().getAnnotation(Components.class)).map(c -> c.value()) .filter(Objects::nonNull).ifPresent(Injector::add); } LOG.debug("Parsing {} components", COMPONENTS.size()); COMPONENTS.keySet().forEach(this::provider); LOG.trace("Parsed components classes"); } finally { CONFIGURATIONS.clear(); COMPONENTS.clear(); } LOG.debug("Autocreating {} singletons", autos.size()); autos.forEach(k -> providers.get(k).get()); autos.clear(); } /** * @return an instance of type */ public T instance(Class type) { return provider(Key.of(type), null).get(); } /** * @return instance specified by key (type and qualifier) */ public T instance(Key key) { return provider(key, null).get(); } /** * @return an instance of type */ @SuppressWarnings("unchecked") public List instancesOfType(Class type) { return (List) listProvider(Key.of(type)).get(); } /** * @return provider of type */ public Provider provider(Class type) { return provider(Key.of(type), null); } /** * @return provider of key (type, qualifier) */ public Provider provider(Key key) { return provider(key, null); } @SuppressWarnings("unchecked") private Provider provider(final Key key, Set> chain) { if (!providers.containsKey(key)) { if (nonNull(key.qualifier)) { throw new InjectionException("Unable to find provider for " + key); } final Constructor constructor = constructor(key); final Provider[] paramProviders = paramProviders(key, constructor.getParameterTypes(), constructor.getGenericParameterTypes(), constructor.getParameterAnnotations(), chain); providers.put(key, singletonProvider(key, !key.type.isAnnotationPresent(Prototype.class) || key.type.isAnnotationPresent(Auto.class), () -> { try { return constructor.newInstance(params(paramProviders)); } catch (Exception e) { throw new InjectionException(String.format("Can't instantiate %s", key.toString()), e); } })); if (key.type.isAnnotationPresent(Auto.class)) { LOG.trace("To be autocreated {}", key); autos.add(key); } } return (Provider) providers.get(key); } private void providerMethod(final Object module, final Method m) { final Key key = Key.of(m.getReturnType(), qualifier(m.getAnnotations())); if (providers.containsKey(key)) { throw new InjectionException( String.format("%s has multiple providers, configuration %s", key.toString(), module.getClass())); } boolean singleton = !(m.isAnnotationPresent(Prototype.class) || m.getReturnType().isAnnotationPresent(Prototype.class)) || (m.isAnnotationPresent(Auto.class) || m.getReturnType().isAnnotationPresent(Auto.class)); final Provider[] paramProviders = paramProviders(key, m.getParameterTypes(), m.getGenericParameterTypes(), m.getParameterAnnotations(), Collections.singleton(key)); providers.put(key, singletonProvider(key, singleton, () -> { try { return m.invoke(module, params(paramProviders)); } catch (Exception e) { throw new InjectionException(String.format("Can't instantiate %s with provider", key.toString()), e); } })); if (m.isAnnotationPresent(Auto.class) || m.getReturnType().isAnnotationPresent(Auto.class)) { LOG.trace("To be autocreated {}", key); autos.add(key); } } @SuppressWarnings("unchecked") private Provider singletonProvider(final Key key, boolean singleton, final Provider provider) { if (singleton) { return () -> { if (!singletons.containsKey(key)) { synchronized (singletons) { if (!singletons.containsKey(key)) { singletons.put(key, provider.get()); } } } return (T) singletons.get(key); }; } return provider; } @SuppressWarnings({ "rawtypes", "unchecked" }) private Provider> listProvider(final Key key) { return () -> { List items = new ArrayList<>(); providers.keySet().stream().filter(k -> key.type.isAssignableFrom(k.type)).map(providers::get) .map(p -> p.get()).forEach(i -> items.add(i)); return items; }; } private Provider[] paramProviders(final Key key, Class[] parameterClasses, Type[] parameterTypes, Annotation[][] annotations, final Set> chain) { Provider[] providers = new Provider[parameterTypes.length]; for (int i = 0; i < parameterTypes.length; ++i) { Class parameterClass = parameterClasses[i]; Annotation qualifier = qualifier(annotations[i]); Optional> parametrizedType = Optional.empty(); if (Provider.class.equals(parameterClass) || List.class.equals(parameterClass)) { Type type = ((ParameterizedType) parameterTypes[i]).getActualTypeArguments()[0]; if (!(type instanceof Class)) { throw new InjectionException("Unable to inject parameterized type \"" + type.toString() + "\""); } parametrizedType = ofNullable((Class) type); } // we handle special cases of a Provider and unqualified List if (parametrizedType.isPresent() && (Provider.class.equals(parameterClass) || (List.class.equals(parameterClass) && isNull(qualifier)))) { final Key newKey = Key.of(parametrizedType.get(), qualifier); if (Provider.class.equals(parameterClass)) { providers[i] = () -> { return provider(newKey, null); }; } if (List.class.equals(parameterClass)) { providers[i] = listProvider(newKey); } } else { final Key newKey = Key.of(parameterClass, qualifier); final Set> newChain = append(chain, key); if (newChain.contains(newKey)) { throw new InjectionException(String.format("Circular dependency: %s", chain(newChain, newKey))); } providers[i] = () -> { return provider(newKey, newChain).get(); }; } } return providers; } private static Object[] params(Provider[] paramProviders) { Object[] params = new Object[paramProviders.length]; for (int i = 0; i < paramProviders.length; ++i) { params[i] = paramProviders[i].get(); } return params; } private static Set> append(Set> set, Key newKey) { if (set != null && !set.isEmpty()) { Set> appended = new LinkedHashSet<>(set); appended.add(newKey); return appended; } else { return singleton(newKey); } } private static String chain(Set> chain, Key lastKey) { return concat(chain.stream().map(Key::toString), of(lastKey.toString())).collect(joining(" -> ")); } private static Constructor constructor(Key key) { Constructor inject = null; Constructor noarg = null; for (Constructor c : key.type.getDeclaredConstructors()) { if (c.isAnnotationPresent(Inject.class)) { if (inject == null) { inject = c; } else { throw new InjectionException(String.format("%s has multiple @Inject constructors", key.type)); } } else if (c.getParameterTypes().length == 0) { noarg = c; } } Constructor constructor = inject != null ? inject : noarg; if (constructor != null) { constructor.setAccessible(true); return constructor; } else { throw new InjectionException(String.format( "%s doesn't have an @Inject or no-arg constructor, or a configured provider", key.type.getName())); } } private static Set providers(Class type) { Class current = type; Set providers = new HashSet<>(); while (!current.equals(Object.class)) { for (Method method : current.getDeclaredMethods()) { if (method.isAnnotationPresent(Provides.class) && (type.equals(current) || !providerInSubClass(method, providers))) { method.setAccessible(true); providers.add(method); } } current = current.getSuperclass(); } return providers; } private static Annotation qualifier(Annotation[] annotations) { for (Annotation annotation : annotations) { if (annotation.annotationType().isAnnotationPresent(Qualifier.class)) { return annotation; } } return null; } private static boolean providerInSubClass(Method method, Set discoveredMethods) { for (Method discovered : discoveredMethods) { if (discovered.getName().equals(method.getName()) && Arrays.equals(method.getParameterTypes(), discovered.getParameterTypes())) { return true; } } return false; } } sejda-injector-1.0.2/src/main/java/org/sejda/injector/Key.java000066400000000000000000000054101301066137400241350ustar00rootroot00000000000000/* * 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 org.sejda.injector; import java.lang.annotation.Annotation; import javax.inject.Named; public class Key { final Class type; final Class qualifier; final String name; private Key(Class type, Class qualifier, String name) { this.type = type; this.qualifier = qualifier; this.name = name; } /** * @return Key for a given type */ public static Key of(Class type) { return new Key<>(type, null, null); } /** * @return Key for a given type and qualifier annotation type */ public static Key of(Class type, Class qualifier) { return new Key<>(type, qualifier, null); } /** * @return Key for a given type and name (@Named value) */ public static Key of(Class type, String name) { return new Key<>(type, Named.class, name); } static Key of(Class type, Annotation qualifier) { if (qualifier == null) { return Key.of(type); } else { return qualifier.annotationType().equals(Named.class) ? Key.of(type, ((Named) qualifier).value()) : Key.of(type, qualifier.annotationType()); } } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Key key = (Key) o; if (!type.equals(key.type)) return false; if (qualifier != null ? !qualifier.equals(key.qualifier) : key.qualifier != null) return false; return !(name != null ? !name.equals(key.name) : key.name != null); } @Override public int hashCode() { int result = type.hashCode(); result = 31 * result + (qualifier != null ? qualifier.hashCode() : 0); result = 31 * result + (name != null ? name.hashCode() : 0); return result; } @Override public String toString() { String suffix = name != null ? "@\"" + name + "\"" : qualifier != null ? "@" + qualifier.getSimpleName() : ""; return type.getName() + suffix; } }sejda-injector-1.0.2/src/main/java/org/sejda/injector/Prototype.java000066400000000000000000000017111301066137400254120ustar00rootroot00000000000000/* * 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 org.sejda.injector; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import javax.inject.Scope; /** * Identifies a type that the injector instantiates every time the type is requested. * * @see javax.inject.Scope @Scope */ @Scope @Documented @Retention(RUNTIME) public @interface Prototype { } sejda-injector-1.0.2/src/main/java/org/sejda/injector/Provides.java000066400000000000000000000013241301066137400252000ustar00rootroot00000000000000/* * 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 org.sejda.injector; import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Provides { } sejda-injector-1.0.2/src/test/000077500000000000000000000000001301066137400161625ustar00rootroot00000000000000sejda-injector-1.0.2/src/test/java/000077500000000000000000000000001301066137400171035ustar00rootroot00000000000000sejda-injector-1.0.2/src/test/java/org/000077500000000000000000000000001301066137400176725ustar00rootroot00000000000000sejda-injector-1.0.2/src/test/java/org/sejda/000077500000000000000000000000001301066137400207605ustar00rootroot00000000000000sejda-injector-1.0.2/src/test/java/org/sejda/injector/000077500000000000000000000000001301066137400225755ustar00rootroot00000000000000sejda-injector-1.0.2/src/test/java/org/sejda/injector/AmbiguousModuleTest.java000066400000000000000000000010221301066137400273740ustar00rootroot00000000000000package org.sejda.injector; import org.junit.Test; import org.sejda.injector.InjectionException; import org.sejda.injector.Injector; import org.sejda.injector.Provides; public class AmbiguousModuleTest { @Test(expected = InjectionException.class) public void ambiguousModule() { Injector.start(new Module()); } public static class Module { @Provides String foo() { return "foo"; } @Provides String bar() { return "bar"; } } } sejda-injector-1.0.2/src/test/java/org/sejda/injector/AutoProviderTest.java000066400000000000000000000022171301066137400267250ustar00rootroot00000000000000package org.sejda.injector; import static org.mockito.Mockito.verify; import java.util.function.Consumer; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; import org.sejda.injector.Auto; import org.sejda.injector.Components; import org.sejda.injector.Injector; import org.sejda.injector.Provides; public class AutoProviderTest { private static Consumer HIT; @Before public void setUp() { HIT = Mockito.mock(Consumer.class); } @Test public void autoCreatedAnnotatedClass() { Injector injector = Injector.start(new Config()); verify(HIT).accept("hit"); } @Test public void autoCreatedAnnotatedConfig() { Injector injector = Injector.start(new ConfigComponent()); verify(HIT).accept("hit"); } public class Config { @Provides public AnnotatedClass sing() { return new AnnotatedClass(); } } @Components({ AnnotatedClass.class }) public class ConfigComponent { } @Auto public static class AnnotatedClass { AnnotatedClass() { HIT.accept("hit"); } } } sejda-injector-1.0.2/src/test/java/org/sejda/injector/CircularDependencyTest.java000066400000000000000000000032461301066137400300500ustar00rootroot00000000000000package org.sejda.injector; import static org.junit.Assert.assertNotNull; import javax.inject.Inject; import javax.inject.Provider; import org.junit.Test; import org.sejda.injector.InjectionException; import org.sejda.injector.Injector; public class CircularDependencyTest { @Test(expected = InjectionException.class) public void circularDependencyCaught() { Injector injector = Injector.start(); injector.instance(Circle1.class); } @Test public void circularDependencyWithProviderAllowed() { Injector injector = Injector.start(); CircleWithProvider1 circle1 = injector.instance(CircleWithProvider1.class); assertNotNull(circle1.circleWithProvider2.circleWithProvider1.get()); } public static class Circle1 { private final Circle2 circle2; @Inject public Circle1(Circle2 circle2) { this.circle2 = circle2; } } public static class Circle2 { private final Circle1 circle1; @Inject public Circle2(Circle1 circle1) { this.circle1 = circle1; } } public static class CircleWithProvider1 { private final CircleWithProvider2 circleWithProvider2; @Inject public CircleWithProvider1(CircleWithProvider2 circleWithProvider2) { this.circleWithProvider2 = circleWithProvider2; } } public static class CircleWithProvider2 { private final Provider circleWithProvider1; @Inject public CircleWithProvider2(Provider circleWithProvider1) { this.circleWithProvider1 = circleWithProvider1; } } } sejda-injector-1.0.2/src/test/java/org/sejda/injector/DependencyTest.java000066400000000000000000000016401301066137400263570ustar00rootroot00000000000000package org.sejda.injector; import static org.junit.Assert.assertNotNull; import javax.inject.Provider; import org.junit.Test; import org.sejda.injector.InjectionException; import org.sejda.injector.Injector; public class DependencyTest { @Test public void dependencyInstance() { Injector injector = Injector.start(); assertNotNull(injector.instance(Plain.class)); } @Test public void provider() { Injector injector = Injector.start(); Provider plainProvider = injector.provider(Plain.class); assertNotNull(plainProvider.get()); } @Test(expected = InjectionException.class) public void unknown() { Injector injector = Injector.start(); injector.instance(Unknown.class); } public static class Plain { } public static class Unknown { public Unknown(String noSuitableConstructor) { } } } sejda-injector-1.0.2/src/test/java/org/sejda/injector/InjectorTest.java000066400000000000000000000017061301066137400260610ustar00rootroot00000000000000package org.sejda.injector; import static org.junit.Assert.assertEquals; import org.junit.Test; import org.sejda.injector.InjectionException; import org.sejda.injector.Injector; import org.sejda.injector.Provides; public class InjectorTest { @Test(expected = InjectionException.class) public void classAsConfig() { Injector.addConfig(String.class); Injector.start(); } @Test(expected = InjectionException.class) public void closed() { Injector.addConfig(new Config()); Injector injector = Injector.start(); assertEquals("ChuckNorris", injector.instance(Obj.class).val); injector.close(); injector.instance(Obj.class); } public class Config { @Provides public Obj obj() { return new Obj("ChuckNorris"); } } private static class Obj { final String val; Obj(String val) { this.val = val; } } } sejda-injector-1.0.2/src/test/java/org/sejda/injector/ListInjectionTest.java000066400000000000000000000036751301066137400270710ustar00rootroot00000000000000package org.sejda.injector; import static org.junit.Assert.assertEquals; import java.util.Arrays; import java.util.List; import javax.inject.Inject; import javax.inject.Named; import org.junit.Test; import org.sejda.injector.InjectionException; import org.sejda.injector.Injector; import org.sejda.injector.Key; import org.sejda.injector.Provides; public class ListInjectionTest { @Test public void listOfInjected() { Injector injector = Injector.start(new Config()); assertEquals(2, injector.instance(A.class).list.size()); } @Test public void instancesOfType() { Injector injector = Injector.start(new Config()); assertEquals(2, injector.instancesOfType(Base.class).size()); } @Test(expected = InjectionException.class) public void invalidType() { Injector injector = Injector.start(new Config()); injector.instance(B.class).list.size(); } @Test public void qualifiedListOfInjected() { Injector injector = Injector.start(new Config()); assertEquals(4, injector.instance(Key.of(List.class, "aList")).size()); } public static class A { private final List list; @Inject public A(List list) { this.list = list; } } public static class B { private final List list; @Inject public B(List list) { this.list = list; } } public static class Config { @Provides Sub1 sub1() { return new Sub1(); } @Provides Sub2 sub2() { return new Sub2(); } @Provides @Named("aList") List qualifiedList() { return Arrays.asList("a", "b", "c", "d"); } } public static class Base { } public static class Sub1 extends Base { } public static class Sub2 extends Base { } } sejda-injector-1.0.2/src/test/java/org/sejda/injector/ModuleOverrideTest.java000066400000000000000000000023071301066137400272270ustar00rootroot00000000000000package org.sejda.injector; import static org.junit.Assert.assertEquals; import org.junit.Test; import org.sejda.injector.Injector; import org.sejda.injector.Provides; public class ModuleOverrideTest { @Test public void dependencyOverridenByModule() { Injector injector = Injector.start(new PlainStubOverrideModule()); assertEquals(PlainStub.class, injector.instance(Plain.class).getClass()); } @Test public void moduleOverwrittenBySubClass() { assertEquals("foo", Injector.start(new FooModule()).instance(String.class)); assertEquals("bar", Injector.start(new FooOverrideModule()).instance(String.class)); } public static class Plain { } public static class PlainStub extends Plain { } public static class PlainStubOverrideModule { @Provides public Plain plain(PlainStub plainStub) { return plainStub; } } public static class FooModule { @Provides String foo() { return "foo"; } } public static class FooOverrideModule extends FooModule { @Provides @Override String foo() { return "bar"; } } } sejda-injector-1.0.2/src/test/java/org/sejda/injector/NamedDependencyTest.java000066400000000000000000000024661301066137400273330ustar00rootroot00000000000000package org.sejda.injector; import static org.junit.Assert.assertEquals; import javax.inject.Inject; import javax.inject.Named; import org.junit.Test; import org.sejda.injector.InjectionException; import org.sejda.injector.Injector; import org.sejda.injector.Key; import org.sejda.injector.Provides; public class NamedDependencyTest { @Test public void namedInstanceWithModule() { Injector injector = Injector.start(new HelloWorldModule()); assertEquals("Hello!", injector.instance(Key.of(String.class, "hello"))); assertEquals("Hi!", injector.instance(Key.of(String.class, "hi"))); assertEquals("Hello!", injector.instance(Bean.class).s); } @Test(expected = InjectionException.class) public void failingName() { Injector injector = Injector.start(new HelloWorldModule()); injector.instance(Key.of(String.class, "ChuckNorris")); } public static class HelloWorldModule { @Provides @Named("hello") String hello() { return "Hello!"; } @Provides @Named("hi") String hi() { return "Hi!"; } } public static class Bean { private final String s; @Inject public Bean(@Named("hello") String s) { this.s = s; } } } sejda-injector-1.0.2/src/test/java/org/sejda/injector/PojoProvidedThroughModuleTest.java000066400000000000000000000022431301066137400314140ustar00rootroot00000000000000package org.sejda.injector; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import org.junit.Test; import org.sejda.injector.InjectionException; import org.sejda.injector.Injector; import org.sejda.injector.Provides; public class PojoProvidedThroughModuleTest { @Test(expected = InjectionException.class) public void pojoNotProvided() { Injector injector = Injector.start(); injector.instance(Pojo.class); } @Test public void pojoProvided() { Injector injector = Injector.start(new Module()); assertNotNull(injector.instance(Pojo.class)); } @Test public void dependecyInjected() { Injector injector = Injector.start(new Module()); assertEquals("foo", injector.instance(String.class)); } public static class Module { @Provides Pojo pojo() { return new Pojo("foo"); } @Provides String myString(Pojo pojo) { return pojo.foo; } } public static class Pojo { private final String foo; public Pojo(String foo) { this.foo = foo; } } } sejda-injector-1.0.2/src/test/java/org/sejda/injector/PolymorphicDependencyTest.java000066400000000000000000000020371301066137400306060ustar00rootroot00000000000000package org.sejda.injector; import static org.junit.Assert.assertEquals; import javax.inject.Inject; import javax.inject.Named; import org.junit.Test; import org.sejda.injector.Injector; import org.sejda.injector.Key; import org.sejda.injector.Provides; public class PolymorphicDependencyTest { @Test public void multipleImplementations() { Injector injector = Injector.start(new Module()); assertEquals(FooA.class, injector.instance(Key.of(Foo.class, "A")).getClass()); assertEquals(FooB.class, injector.instance(Key.of(Foo.class, "B")).getClass()); } public static class Module { @Provides @Named("A") Foo a(FooA fooA) { return fooA; } @Provides @Named("B") Foo a(FooB fooB) { return fooB; } } interface Foo { } public static class FooA implements Foo { @Inject public FooA() { } } public static class FooB implements Foo { @Inject public FooB() { } } } sejda-injector-1.0.2/src/test/java/org/sejda/injector/ProviderInjectionTest.java000066400000000000000000000012051301066137400277330ustar00rootroot00000000000000package org.sejda.injector; import static org.junit.Assert.assertNotNull; import javax.inject.Inject; import javax.inject.Provider; import org.junit.Test; import org.sejda.injector.Injector; public class ProviderInjectionTest { @Test public void providerInjected() { Injector injector = Injector.start(); assertNotNull(injector.instance(A.class).plainProvider.get()); } public static class A { private final Provider plainProvider; @Inject public A(Provider plainProvider) { this.plainProvider = plainProvider; } } public static class B { } } sejda-injector-1.0.2/src/test/java/org/sejda/injector/QualifiedDependencyTest.java000066400000000000000000000030701301066137400302020ustar00rootroot00000000000000package org.sejda.injector; import static org.junit.Assert.assertEquals; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import javax.inject.Inject; import javax.inject.Qualifier; import org.junit.Test; import org.sejda.injector.Injector; import org.sejda.injector.Key; import org.sejda.injector.Provides; public class QualifiedDependencyTest { @Test public void qualifiedInstances() { Injector injector = Injector.start(new Module()); assertEquals(FooA.class, injector.instance(Key.of(Foo.class, A.class)).getClass()); assertEquals(FooB.class, injector.instance(Key.of(Foo.class, B.class)).getClass()); } @Test public void injectedQualified() { Injector injector = Injector.start(new Module()); Dummy dummy = injector.instance(Dummy.class); assertEquals(FooB.class, dummy.foo.getClass()); } interface Foo { } public static class FooA implements Foo { } public static class FooB implements Foo { } @Qualifier @Retention(RetentionPolicy.RUNTIME) @interface A { } @Qualifier @Retention(RetentionPolicy.RUNTIME) @interface B { } public static class Module { @Provides @A Foo a(FooA fooA) { return fooA; } @Provides @B Foo b(FooB fooB) { return fooB; } } public static class Dummy { private final Foo foo; @Inject public Dummy(@B Foo foo) { this.foo = foo; } } } sejda-injector-1.0.2/src/test/java/org/sejda/injector/SingletonTest.java000066400000000000000000000025311301066137400262430ustar00rootroot00000000000000package org.sejda.injector; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import javax.inject.Provider; import org.junit.Test; import org.sejda.injector.Injector; import org.sejda.injector.Prototype; import org.sejda.injector.Provides; public class SingletonTest { @Test public void nonSingleton() { Injector injector = Injector.start(); assertNotEquals(injector.instance(ProtoPlain.class), injector.instance(ProtoPlain.class)); } @Test public void nonSingletonConfig() { Injector injector = Injector.start(new Config()); assertNotEquals(injector.instance(Plain.class), injector.instance(Plain.class)); } @Test public void singletonByDefault() { Injector injector = Injector.start(); assertEquals(injector.instance(Plain.class), injector.instance(Plain.class)); } @Test public void singletonThroughProvider() { Injector injector = Injector.start(); Provider provider = injector.provider(Plain.class); assertEquals(provider.get(), provider.get()); } @Prototype public static class ProtoPlain { } public static class Plain { } public class Config { @Provides @Prototype Plain plain() { return new Plain(); } } } sejda-injector-1.0.2/src/test/java/org/sejda/injector/TransitiveDependencyTest.java000066400000000000000000000012541301066137400304310ustar00rootroot00000000000000package org.sejda.injector; import static org.junit.Assert.assertNotNull; import javax.inject.Inject; import org.junit.Test; import org.sejda.injector.Injector; public class TransitiveDependencyTest { @Test public void transitive() { Injector injector = Injector.start(); A a = injector.instance(A.class); assertNotNull(a.b.c); } public static class A { private final B b; @Inject public A(B b) { this.b = b; } } public static class B { private final C c; @Inject public B(C c) { this.c = c; } } public static class C { } } sejda-injector-1.0.2/src/test/resources/000077500000000000000000000000001301066137400201745ustar00rootroot00000000000000sejda-injector-1.0.2/src/test/resources/logback-test.xml000066400000000000000000000005161301066137400232770ustar00rootroot00000000000000 %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n