private Injectable getRootDisabledInjectable(Injectable inj, final Collection<String> problems, final Map<String, Injectable> customProvidedInjectables) { while (inj.getDependencies().size() == 1) { final Dependency dep = inj.getDependencies().iterator().next(); if (DependencyType.ProducerMember.equals(dep.getDependencyType())) { inj = resolveDependency((BaseDependency) dep, inj, problems, customProvidedInjectables); } } return inj; }
private void linkInjectableReferences() { logger.debug("Linking {} references in dependencies...", injectableReferences.size()); final Set<InjectableReference> linked = new HashSet<>(injectableReferences.size()); for (final Injectable injectable : injectablesByName.values()) { for (final Dependency dep : injectable.getDependencies()) { final BaseDependency baseDep = BaseDependency.as(dep); if (!linked.contains(baseDep.injectable)) { logger.debug("Processing dependency: {}", baseDep); linkInjectableReference(baseDep.injectable); linked.add(baseDep.injectable); } } } }
private void addDependency(final Injectable injectable, final Dependency dependency) { assert (injectable instanceof InjectableImpl); if (InjectableType.Disabled.equals(injectable.getInjectableType()) && (!DependencyType.ProducerMember.equals(dependency.getDependencyType()) || !injectable.getDependencies().isEmpty())) { throw new RuntimeException("The injectable, " + injectable + ", is disabled." + " A disabled injectable may only have a single dependency if it is produced by a disabled bean."); } final InjectableImpl injectableAsImpl = (InjectableImpl) injectable; injectableAsImpl.dependencies.add(BaseDependency.class.cast(dependency)); }
private void resolveDependencies() { logger.debug("Resolving dependencies for {} injectables...", injectablesByName.size()); final Set<Injectable> visited = new HashSet<>(); final Set<String> transientInjectableNames = new HashSet<>(); final List<String> dependencyProblems = new ArrayList<>(); final Map<String, Injectable> customProvidedInjectables = new IdentityHashMap<>(); for (final Injectable injectable : injectablesByName.values()) { if (injectable.isExtension()) { transientInjectableNames.add(injectable.getFactoryName()); } if (!visited.contains(injectable)) { logger.debug("Resolving {} dependencies for: {}", injectable.getDependencies().size(), injectable); for (final Dependency dep : injectable.getDependencies()) { resolveDependency(BaseDependency.as(dep), injectable, dependencyProblems, customProvidedInjectables); } } } injectablesByName.keySet().removeAll(transientInjectableNames); injectablesByName.putAll(customProvidedInjectables); if (!dependencyProblems.isEmpty()) { throw new RuntimeException(GraphUtil.buildMessageFromProblems(dependencyProblems)); } }
@Override protected List<Statement> generateCreateInstanceStatements(final ClassStructureBuilder<?> bodyBlockBuilder, final Injectable injectable, final DependencyGraph graph, final InjectionContext injectionContext) { final Multimap<DependencyType, Dependency> depsByType = separateByType(injectable.getDependencies()); if (depsByType.get(DependencyType.ProducerMember).size() != 1) { throw new RuntimeException("A produced type must have exactly 1 producing instance but " + depsByType.get(DependencyType.ProducerMember).size() + " were found."); } final ProducerInstanceDependency producerInstanceDep = (ProducerInstanceDependency) depsByType.get(DependencyType.ProducerMember).iterator().next(); final Injectable producerInjectable = producerInstanceDep.getInjectable(); final MetaClassMember producingMember = producerInstanceDep.getProducingMember(); if (producingMember instanceof MetaField) { return fieldCreateInstanceStatements((MetaField) producingMember, producerInjectable, injectable, bodyBlockBuilder); } else if (producingMember instanceof MetaMethod) { return methodCreateInstanceStatements((MetaMethod) producingMember, producerInjectable, injectable, depsByType.get(DependencyType.ProducerParameter), bodyBlockBuilder); } else { throw new RuntimeException("Unrecognized producing member: " + producingMember); } }
@Override public void validate(final Injectable injectable, final Collection<String> problems) { for (final Dependency dep : injectable.getDependencies()) { if (dep.getInjectable().loadAsync()) { problems.add("The bean " + injectable + " is not @LoadAsync but depends on the @LoadAsync bean " + dep.getInjectable()); } } } }
private void removeUnreachableInjectables(final ReachabilityStrategy strategy) { logger.debug("Removing unreachable injectables from dependency graph using {} strategy.", strategy); final Set<String> reachableNames = new HashSet<>(); final Queue<Injectable> processingQueue = new LinkedList<>(); final Predicate<Injectable> reachabilityRoot = reachabilityRootPredicate(strategy); for (final Injectable injectable : injectablesByName.values()) { if (reachabilityRoot.test(injectable) && !reachableNames.contains(injectable.getFactoryName()) && !InjectableType.Disabled.equals(injectable.getInjectableType())) { processingQueue.add(injectable); do { final Injectable processedInjectable = processingQueue.poll(); reachableNames.add(processedInjectable.getFactoryName()); logger.trace("Marked as reachable: {}", processedInjectable); for (final Dependency dep : processedInjectable.getDependencies()) { final Injectable resolvedDep = GraphUtil.getResolvedDependency(dep, processedInjectable); if (!reachableNames.contains(resolvedDep.getFactoryName())) { processingQueue.add(resolvedDep); } } } while (processingQueue.size() > 0); } } final int initialSize = injectablesByName.size(); injectablesByName.keySet().retainAll(reachableNames); logger.debug("Removed {} unreachable injectables.", initialSize - injectablesByName.size()); }
@Override protected List<Statement> generateDestroyInstanceStatements(final ClassStructureBuilder<?> bodyBlockBuilder, final Injectable injectable, final DependencyGraph graph, final InjectionContext injectionContext) { final List<Statement> destroyInstanceStmts = new ArrayList<>(); final Multimap<DependencyType, Dependency> depsByType = separateByType(injectable.getDependencies()); final Collection<Dependency> producerMemberDeps = depsByType.get(DependencyType.ProducerMember); if (producerMemberDeps.size() != 1) { throw new RuntimeException("A produced type must have exactly 1 producing instance but " + producerMemberDeps.size() + " were found."); } final Collection<Dependency> disposerMethodDeps = depsByType.get(DependencyType.DisposerMethod); if (disposerMethodDeps.size() > 1) { // TODO error message with matching disposer names. throw new RuntimeException(); } else if (disposerMethodDeps.size() == 1) { final DisposerMethodDependency disposerDep = (DisposerMethodDependency) disposerMethodDeps.iterator().next(); final MetaMethod disposer = disposerDep.getDisposerMethod(); controller.ensureMemberExposed(disposer); final Statement invocation = controller.exposedMethodStmt( controller.getReferenceStmt(PRODUCER_INSTANCE, disposer.getDeclaringClass()), disposer, getDisposerParams(disposer, depsByType.get(DependencyType.DisposerParameter), bodyBlockBuilder.getClassDefinition())); destroyInstanceStmts.add(invocation); } return destroyInstanceStmts; }
@Override protected List<Statement> generateCreateInstanceStatements(final ClassStructureBuilder<?> bodyBlockBuilder, final Injectable injectable, final DependencyGraph graph, final InjectionContext injectionContext) { final Multimap<DependencyType, Dependency> dependenciesByType = separateByType(injectable.getDependencies()); final Collection<Dependency> constructorDependencies = dependenciesByType.get(DependencyType.Constructor); final Collection<Dependency> fieldDependencies = dependenciesByType.get(DependencyType.Field); final Collection<Dependency> setterDependencies = dependenciesByType.get(DependencyType.SetterParameter); final List<Statement> createInstanceStatements = new ArrayList<>(); constructInstance(injectable, constructorDependencies, createInstanceStatements); injectFieldDependencies(injectable, fieldDependencies, createInstanceStatements, bodyBlockBuilder); injectSetterMethodDependencies(injectable, setterDependencies, createInstanceStatements, bodyBlockBuilder); addInitializationStatements(createInstanceStatements); addReturnStatement(createInstanceStatements); return createInstanceStatements; }
private static void traceConstituentHashContents(final Injectable injectable, final String name) { log.trace("Begin trace of hashContent for {}", name); log.trace("Combined content: {}", injectable.hashContent()); log.trace("HashContent for injectable type: {}", injectable.getInjectedType().hashContent()); for (final Dependency dep : injectable.getDependencies()) { log.trace("HashContent for {} dep of type {}: {}", dep.getDependencyType().toString(), dep.getInjectable().getInjectedType(), dep.getInjectable().getInjectedType().hashContent()); } log.trace("End trace of hashContent for {}", name); }
private static void validateDependentScopedInjectable(final Injectable injectable, final Set<Injectable> visiting, final Set<Injectable> visited, final Collection<String> problems, final boolean onlyConstuctorDeps) { if (InjectableType.Disabled.equals(injectable.getInjectableType())) { visited.add(injectable); return; } if (visiting.contains(injectable)) { problems.add(createCycleMessage(visiting, injectable)); return; } visiting.add(injectable); for (final Dependency dep : injectable.getDependencies()) { if (onlyConstuctorDeps && !dep.getDependencyType().equals(DependencyType.Constructor)) { continue; } final Injectable resolved = GraphUtil.getResolvedDependency(dep, injectable); if (!visited.contains(resolved)) { if (dep.getDependencyType().equals(DependencyType.ProducerMember)) { validateDependentScopedInjectable(resolved, visiting, visited, problems, true); } else if (resolved.getWiringElementTypes().contains(WiringElementType.PseudoScopedBean)) { validateDependentScopedInjectable(resolved, visiting, visited, problems, false); } } } visiting.remove(injectable); visited.add(injectable); }
protected Injectable getProviderInjectable(final Injectable depInjectable) { for (final Dependency dep : depInjectable.getDependencies()) { if (dep.getDependencyType().equals(DependencyType.ProducerMember)) { final MetaClass providerType = dep.getInjectable().getInjectedType(); if (providerType.isAssignableTo(getProviderRawType())) { return dep.getInjectable(); } else { throw new RuntimeException("Unrecognized contextual provider type " + providerType.getFullyQualifiedName()); } } } throw new RuntimeException(); }
private MetaConstructor getAccessibleConstructor(final Injectable injectable) { final MetaClass type = injectable.getInjectedType(); final MetaConstructor noArgConstr = getAccessibleNoArgConstructor(type); if (noArgConstr != null) { return noArgConstr; } for (final Dependency dep : injectable.getDependencies()) { if (dep.getDependencyType().equals(DependencyType.Constructor)) { final MetaConstructor injectableConstr = (MetaConstructor) ((ParamDependency) dep).getParameter().getDeclaringMember(); return (injectableConstr.isPublic() || injectableConstr.isProtected()) ? injectableConstr : null; } } return null; }
private static Statement getAccessStatementForAutoBoundDataBinder(final Decorable decorable, final FactoryController controller) { final Injectable enclosingInjectable = decorable.getEnclosingInjectable(); for (final Dependency dep : enclosingInjectable.getDependencies()) { switch (dep.getDependencyType()) { case Constructor:
private static Statement getAccessStatementForAutoBoundDataBinder(final Decorable decorable, final FactoryController controller) { final Injectable enclosingInjectable = decorable.getEnclosingInjectable(); for (final Dependency dep : enclosingInjectable.getDependencies()) { switch (dep.getDependencyType()) { case Constructor:
private void registerAsyncFactory(final Injectable injectable, final IOCProcessingContext processingContext, @SuppressWarnings("rawtypes") final BlockBuilder curMethod, final MetaClass factoryClass) { final Statement handle = generateFactoryHandle(injectable, curMethod); final Statement loader = generateFactoryLoader(injectable, factoryClass); curMethod.append(loadVariable("asyncBeanManagerSetup").invoke("registerAsyncBean", handle, loader)); for (final Dependency dep : injectable.getDependencies()) { if (dep.getInjectable().loadAsync()) { curMethod.append(loadVariable("asyncBeanManagerSetup").invoke("registerAsyncDependency", injectable.getFactoryName(), dep.getInjectable().getFactoryName())); } } }