use of org.apache.sling.models.impl.model.ModelClass in project sling by apache.
the class AdapterImplementations method addAll.
/**
* Add implementation mapping for the given adapter types.
* @param implType Implementation type
* @param adapterTypes Adapter types
* @result true if adapters were successfully added
*/
@SuppressWarnings("unchecked")
boolean addAll(Class<?> implType, Class<?>... adapterTypes) {
ModelClass<?> modelClass = null;
try {
modelClass = new ModelClass(implType, sortedStaticInjectAnnotationProcessorFactories);
} catch (Exception e) {
log.warn("Unable to reflect on " + implType.getName(), e);
return false;
} catch (NoClassDefFoundError e) {
log.warn("Unable to reflect on " + implType.getName(), e);
return false;
}
for (Class<?> adapterType : adapterTypes) {
String key = adapterType.getName();
if (adapterType == implType) {
modelClasses.put(key, modelClass);
} else {
// although we already use a ConcurrentMap synchronize explicitly because we apply non-atomic operations on it
synchronized (adapterImplementations) {
ConcurrentNavigableMap<String, ModelClass<?>> implementations = adapterImplementations.get(key);
if (implementations == null) {
// to have a consistent ordering independent of bundle loading use a ConcurrentSkipListMap that sorts by class name
implementations = new ConcurrentSkipListMap<String, ModelClass<?>>();
adapterImplementations.put(key, implementations);
}
implementations.put(implType.getName(), modelClass);
}
}
}
return true;
}
use of org.apache.sling.models.impl.model.ModelClass in project sling by apache.
the class ModelAdapterFactory method internalCreateModel.
@SuppressWarnings("unchecked")
private <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<ModelType>(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<ModelType>(new ModelClassException(msg));
}
boolean isAdaptable = false;
Model modelAnnotation = modelClass.getModelAnnotation();
if (modelAnnotation.cache()) {
Map<Class, Object> adaptableCache = adapterCache.get(adaptable);
if (adaptableCache != null) {
ModelType cachedObject = (ModelType) adaptableCache.get(requestedType);
if (cachedObject != null) {
return new Result<ModelType>(cachedObject);
}
}
}
Class<?>[] declaredAdaptable = modelAnnotation.adaptables();
for (Class<?> clazz : declaredAdaptable) {
if (clazz.isInstance(adaptable)) {
isAdaptable = true;
}
}
if (!isAdaptable) {
String msg = String.format("Adaptables (%s) are not acceptable for the model class: %s", StringUtils.join(declaredAdaptable), modelClass.getType());
return new Result<ModelType>(new InvalidAdaptableException(msg));
} else {
RuntimeException t = validateModel(adaptable, modelClass.getType(), modelAnnotation);
if (t != null) {
return new Result<ModelType>(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()) {
Map<Class, Object> adaptableCache = adapterCache.get(adaptable);
if (adaptableCache == null) {
adaptableCache = new ConcurrentHashMap<Class, Object>(INNER_CACHE_INITIAL_CAPACITY);
adapterCache.put(adaptable, adaptableCache);
}
adaptableCache.put(requestedType, model);
}
result = new Result<ModelType>(model);
} else {
return new Result<ModelType>(handlerResult.getThrowable());
}
} else {
try {
result = createObject(adaptable, modelClass);
if (result.wasSuccessful() && modelAnnotation.cache()) {
Map<Class, Object> adaptableCache = adapterCache.get(adaptable);
if (adaptableCache == null) {
adaptableCache = new ConcurrentHashMap<Class, Object>(INNER_CACHE_INITIAL_CAPACITY);
adapterCache.put(adaptable, adaptableCache);
}
adaptableCache.put(requestedType, result.getValue());
}
} catch (Exception e) {
String msg = String.format("Unable to create model %s", modelClass.getType());
return new Result<ModelType>(new ModelClassException(msg, e));
}
}
}
return result;
} finally {
threadInvocationCounter.decrease();
}
}
use of org.apache.sling.models.impl.model.ModelClass in project sling by apache.
the class AdapterImplementations method lookup.
/**
* Lookup the best-matching implementation for the given adapter type by enquiring the {@link ImplementationPicker} services.
* @param adapterType Adapter type
* @param adaptable Adaptable for reference
* @return Implementation type or null if none detected
*/
@SuppressWarnings("unchecked")
public <ModelType> ModelClass<ModelType> lookup(Class<ModelType> adapterType, Object adaptable) {
String key = adapterType.getName();
// lookup in cache for models without adapter classes
ModelClass<ModelType> modelClass = (ModelClass<ModelType>) modelClasses.get(key);
if (modelClass != null) {
return modelClass;
}
// not found? look in cache with adapter classes
ConcurrentNavigableMap<String, ModelClass<?>> implementations = adapterImplementations.get(key);
if (implementations == null || implementations.isEmpty()) {
return null;
}
Collection<ModelClass<?>> implementationsCollection = implementations.values();
ModelClass<?>[] implementationWrappersArray = implementationsCollection.toArray(new ModelClass<?>[implementationsCollection.size()]);
// prepare array for implementation picker
Class<?>[] implementationsArray = new Class<?>[implementationsCollection.size()];
for (int i = 0; i < implementationWrappersArray.length; i++) {
implementationsArray[i] = implementationWrappersArray[i].getType();
}
for (ImplementationPicker picker : this.sortedImplementationPickers) {
Class<?> implementation = picker.pick(adapterType, implementationsArray, adaptable);
if (implementation != null) {
for (int i = 0; i < implementationWrappersArray.length; i++) {
if (implementation == implementationWrappersArray[i].getType()) {
return (ModelClass<ModelType>) implementationWrappersArray[i];
}
}
}
}
return null;
}
Aggregations