Merge branch '1.5.x'

pull/8185/merge
Andy Wilkinson 8 years ago
commit aacdeaea4e

@ -16,6 +16,7 @@
package org.springframework.boot.autoconfigure.condition; package org.springframework.boot.autoconfigure.condition;
import java.security.AccessControlException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -90,53 +91,30 @@ class OnClassCondition extends SpringBootCondition
// additional thread seems to offer the best performance. More threads make // additional thread seems to offer the best performance. More threads make
// things worse // things worse
int split = autoConfigurationClasses.length / 2; int split = autoConfigurationClasses.length / 2;
GetOutcomesThread thread = new GetOutcomesThread(autoConfigurationClasses, 0, OutcomesResolver firstHalfResolver = createOutcomesResolver(
split, autoConfigurationMetadata); autoConfigurationClasses, 0, split, autoConfigurationMetadata);
thread.start(); OutcomesResolver secondHalfResolver = new StandardOutcomesResolver(
ConditionOutcome[] secondHalf = getOutcomes(autoConfigurationClasses, split, autoConfigurationClasses, split, autoConfigurationClasses.length,
autoConfigurationClasses.length, autoConfigurationMetadata); autoConfigurationMetadata, this.beanClassLoader);
try { ConditionOutcome[] secondHalf = secondHalfResolver.resolveOutcomes();
thread.join(); ConditionOutcome[] firstHalf = firstHalfResolver.resolveOutcomes();
}
catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
ConditionOutcome[] firstHalf = thread.getResult();
ConditionOutcome[] outcomes = new ConditionOutcome[autoConfigurationClasses.length]; ConditionOutcome[] outcomes = new ConditionOutcome[autoConfigurationClasses.length];
System.arraycopy(firstHalf, 0, outcomes, 0, firstHalf.length); System.arraycopy(firstHalf, 0, outcomes, 0, firstHalf.length);
System.arraycopy(secondHalf, 0, outcomes, split, secondHalf.length); System.arraycopy(secondHalf, 0, outcomes, split, secondHalf.length);
return outcomes; return outcomes;
} }
private ConditionOutcome[] getOutcomes(final String[] autoConfigurationClasses, private OutcomesResolver createOutcomesResolver(String[] autoConfigurationClasses,
int start, int end, AutoConfigurationMetadata autoConfigurationMetadata) { int start, int end, AutoConfigurationMetadata autoConfigurationMetadata) {
ConditionOutcome[] outcomes = new ConditionOutcome[end - start]; OutcomesResolver outcomesResolver = new StandardOutcomesResolver(
for (int i = start; i < end; i++) { autoConfigurationClasses, start, end, autoConfigurationMetadata,
String autoConfigurationClass = autoConfigurationClasses[i]; this.beanClassLoader);
Set<String> candidates = autoConfigurationMetadata
.getSet(autoConfigurationClass, "ConditionalOnClass");
if (candidates != null) {
outcomes[i - start] = getOutcome(candidates);
}
}
return outcomes;
}
private ConditionOutcome getOutcome(Set<String> candidates) {
try { try {
List<String> missing = getMatches(candidates, MatchType.MISSING, return new ThreadedOutcomesResolver(outcomesResolver);
this.beanClassLoader);
if (!missing.isEmpty()) {
return ConditionOutcome
.noMatch(ConditionMessage.forCondition(ConditionalOnClass.class)
.didNotFind("required class", "required classes")
.items(Style.QUOTE, missing));
}
} }
catch (Exception ex) { catch (AccessControlException ex) {
// We'll get another chance later return outcomesResolver;
} }
return null;
} }
@Override @Override
@ -262,7 +240,45 @@ class OnClassCondition extends SpringBootCondition
} }
private class GetOutcomesThread extends Thread { private interface OutcomesResolver {
ConditionOutcome[] resolveOutcomes();
}
private static final class ThreadedOutcomesResolver implements OutcomesResolver {
private final Thread thread;
private volatile ConditionOutcome[] outcomes;
private ThreadedOutcomesResolver(final OutcomesResolver outcomesResolver) {
this.thread = new Thread(new Runnable() {
@Override
public void run() {
ThreadedOutcomesResolver.this.outcomes = outcomesResolver
.resolveOutcomes();
}
});
this.thread.start();
}
@Override
public ConditionOutcome[] resolveOutcomes() {
try {
this.thread.join();
}
catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
return this.outcomes;
}
}
private final class StandardOutcomesResolver implements OutcomesResolver {
private final String[] autoConfigurationClasses; private final String[] autoConfigurationClasses;
@ -272,25 +288,55 @@ class OnClassCondition extends SpringBootCondition
private final AutoConfigurationMetadata autoConfigurationMetadata; private final AutoConfigurationMetadata autoConfigurationMetadata;
private ConditionOutcome[] outcomes; private final ClassLoader beanClassLoader;
GetOutcomesThread(String[] autoConfigurationClasses, int start, int end, private StandardOutcomesResolver(String[] autoConfigurationClasses, int start,
AutoConfigurationMetadata autoConfigurationMetadata) { int end, AutoConfigurationMetadata autoConfigurationMetadata,
ClassLoader beanClassLoader) {
this.autoConfigurationClasses = autoConfigurationClasses; this.autoConfigurationClasses = autoConfigurationClasses;
this.start = start; this.start = start;
this.end = end; this.end = end;
this.autoConfigurationMetadata = autoConfigurationMetadata; this.autoConfigurationMetadata = autoConfigurationMetadata;
this.beanClassLoader = beanClassLoader;
} }
@Override @Override
public void run() { public ConditionOutcome[] resolveOutcomes() {
this.outcomes = getOutcomes(this.autoConfigurationClasses, this.start, return getOutcomes(this.autoConfigurationClasses, this.start, this.end,
this.end, this.autoConfigurationMetadata); this.autoConfigurationMetadata);
} }
public ConditionOutcome[] getResult() { private ConditionOutcome[] getOutcomes(final String[] autoConfigurationClasses,
return this.outcomes; int start, int end, AutoConfigurationMetadata autoConfigurationMetadata) {
ConditionOutcome[] outcomes = new ConditionOutcome[end - start];
for (int i = start; i < end; i++) {
String autoConfigurationClass = autoConfigurationClasses[i];
Set<String> candidates = autoConfigurationMetadata
.getSet(autoConfigurationClass, "ConditionalOnClass");
if (candidates != null) {
outcomes[i - start] = getOutcome(candidates);
}
}
return outcomes;
}
private ConditionOutcome getOutcome(Set<String> candidates) {
try {
List<String> missing = getMatches(candidates, MatchType.MISSING,
this.beanClassLoader);
if (!missing.isEmpty()) {
return ConditionOutcome.noMatch(
ConditionMessage.forCondition(ConditionalOnClass.class)
.didNotFind("required class", "required classes")
.items(Style.QUOTE, missing));
}
}
catch (Exception ex) {
// We'll get another chance later
}
return null;
} }
} }
} }

Loading…
Cancel
Save