Search in sources :

Example 1 with ModelClass

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;
}
Also used : ModelClass(org.apache.sling.models.impl.model.ModelClass)

Example 2 with ModelClass

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();
    }
}
Also used : InvocationHandler(java.lang.reflect.InvocationHandler) MissingElementException(org.apache.sling.models.factory.MissingElementException) InvalidAdaptableException(org.apache.sling.models.factory.InvalidAdaptableException) ValidationException(org.apache.sling.models.factory.ValidationException) ExportException(org.apache.sling.models.factory.ExportException) PostConstructException(org.apache.sling.models.factory.PostConstructException) InvocationTargetException(java.lang.reflect.InvocationTargetException) ModelClassException(org.apache.sling.models.factory.ModelClassException) MissingExporterException(org.apache.sling.models.factory.MissingExporterException) MissingElementsException(org.apache.sling.models.factory.MissingElementsException) InvalidModelException(org.apache.sling.models.factory.InvalidModelException) ModelClassException(org.apache.sling.models.factory.ModelClassException) Model(org.apache.sling.models.annotations.Model) ModelClass(org.apache.sling.models.impl.model.ModelClass) InvalidAdaptableException(org.apache.sling.models.factory.InvalidAdaptableException)

Example 3 with ModelClass

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;
}
Also used : ModelClass(org.apache.sling.models.impl.model.ModelClass) ModelClass(org.apache.sling.models.impl.model.ModelClass) ImplementationPicker(org.apache.sling.models.spi.ImplementationPicker)

Aggregations

ModelClass (org.apache.sling.models.impl.model.ModelClass)3 InvocationHandler (java.lang.reflect.InvocationHandler)1 InvocationTargetException (java.lang.reflect.InvocationTargetException)1 Model (org.apache.sling.models.annotations.Model)1 ExportException (org.apache.sling.models.factory.ExportException)1 InvalidAdaptableException (org.apache.sling.models.factory.InvalidAdaptableException)1 InvalidModelException (org.apache.sling.models.factory.InvalidModelException)1 MissingElementException (org.apache.sling.models.factory.MissingElementException)1 MissingElementsException (org.apache.sling.models.factory.MissingElementsException)1 MissingExporterException (org.apache.sling.models.factory.MissingExporterException)1 ModelClassException (org.apache.sling.models.factory.ModelClassException)1 PostConstructException (org.apache.sling.models.factory.PostConstructException)1 ValidationException (org.apache.sling.models.factory.ValidationException)1 ImplementationPicker (org.apache.sling.models.spi.ImplementationPicker)1