in src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java [357:434]
<ModelType> Result<ModelType> internalCreateModel(final Object adaptable, final Class<ModelType> requestedType) {
Result<ModelType> result;
ThreadInvocationCounter threadInvocationCounter = invocationCountThreadLocal.get();
if (threadInvocationCounter.isMaximumReached()) {
String msg = String.format("Adapting %s to %s failed, too much recursive invocations (>=%s).",
adaptable, requestedType, threadInvocationCounter.maxRecursionDepth);
return new Result<>(new ModelClassException(msg));
}
threadInvocationCounter.increase();
try {
// check if a different implementation class was registered for this adapter type
ModelClass<ModelType> modelClass = getImplementationTypeForAdapterType(requestedType, adaptable);
if (!modelClass.hasModelAnnotation()) {
String msg = String.format("Provided Adapter class does not have a Model annotation: %s", modelClass.getType());
return new Result<>(new ModelClassException(msg));
}
boolean isAdaptable = false;
Model modelAnnotation = modelClass.getModelAnnotation();
Map<Class<?>, SoftReference<Object>> adaptableCache = null;
if (modelAnnotation.cache()) {
adaptableCache = getOrCreateCache(adaptable);
SoftReference<Object> softReference = adaptableCache.get(modelClass.getType());
if (softReference != null) {
ModelType cachedObject = (ModelType) softReference.get();
if (cachedObject != null) {
return new Result<>(cachedObject);
}
}
}
Class<?>[] declaredAdaptable = modelAnnotation.adaptables();
for (Class<?> clazz : declaredAdaptable) {
if (clazz.isInstance(adaptable)) {
isAdaptable = true;
}
}
if (!isAdaptable) {
String msg = String.format("Given adaptable (%s) is not acceptable for the model class: %s which only supports adaptables %s", adaptable.getClass(), modelClass.getType(), StringUtils.join(declaredAdaptable));
return new Result<>(new InvalidAdaptableException(msg));
} else {
RuntimeException t = validateModel(adaptable, modelClass.getType(), modelAnnotation);
if (t != null) {
return new Result<>(t);
}
if (modelClass.getType().isInterface()) {
Result<InvocationHandler> handlerResult = createInvocationHandler(adaptable, modelClass);
if (handlerResult.wasSuccessful()) {
ModelType model = (ModelType) Proxy.newProxyInstance(modelClass.getType().getClassLoader(), new Class<?>[] { modelClass.getType() }, handlerResult.getValue());
if (modelAnnotation.cache() && adaptableCache != null) {
adaptableCache.put(modelClass.getType(), new SoftReference<>(model));
}
result = new Result<>(model);
} else {
return new Result<>(handlerResult.getThrowable());
}
} else {
try {
result = createObject(adaptable, modelClass);
if (result.wasSuccessful() && modelAnnotation.cache() && adaptableCache != null) {
adaptableCache.put(modelClass.getType(), new SoftReference<>(result.getValue()));
}
} catch (Exception e) {
String msg = String.format("Unable to create model %s", modelClass.getType());
return new Result<>(new ModelClassException(msg, e));
}
}
}
return result;
} finally {
threadInvocationCounter.decrease();
}
}