001package com.identityworksllc.iiq.common.cache;
002
003import com.identityworksllc.iiq.common.Utilities;
004import org.apache.commons.logging.Log;
005import org.apache.commons.logging.LogFactory;
006import sailpoint.api.SailPointContext;
007import sailpoint.api.SailPointFactory;
008import sailpoint.object.SailPointObject;
009import sailpoint.tools.GeneralException;
010
011import java.lang.reflect.Modifier;
012
013/**
014 * A cache generator to automatically pull and cache SailPoint objects
015 * @param <T> The cached object type, which must be a concrete subclass of SailPointObject
016 */
017@SuppressWarnings("unused")
018public class SailPointObjectCacheGenerator<T extends SailPointObject> implements CacheGenerator<T> {
019
020        /**
021         * Class logger
022         */
023        private static final Log log = LogFactory.getLog(SailPointObjectCacheGenerator.class);
024
025        /**
026         * The object type being generated
027         */
028        private final Class<T> objectType;
029
030        /**
031         * Constructs a new Sailpoint cache generator for this object type
032         * @param type The object type
033         * @throws IllegalArgumentException if the input type is not a concrete subclass of SailPointObject
034         */
035        public SailPointObjectCacheGenerator(Class<T> type) {
036                if (Modifier.isAbstract(type.getModifiers())) {
037                        throw new IllegalArgumentException("The type passed to " + SailPointObjectCacheGenerator.class.getName() + " must be a concrete type");
038                }
039                this.objectType = type;
040        }
041
042        /**
043         * Gets the value for the given key. The Key can be either a name or an ID. This
044         * method must be invoked in a thread that has a SailPointContext.
045         *
046         * If the key is not a string, or if no such object exists, null will be returned.
047         *
048         * The object will be detached via {@link Utilities#detach(SailPointContext, SailPointObject)}.
049         *
050         * @param key The key for which to retrieve a value
051         * @return The object, or null if there is an issue loading it
052         */
053        @SuppressWarnings("unchecked")
054        @Override
055        public T getValue(Object key) {
056                try {
057                        if (key instanceof String) {
058                                SailPointContext context = SailPointFactory.getCurrentContext();
059                                if (context == null) {
060                                        throw new IllegalStateException("This factory method must be invoked in a thread that has a SailPointContext");
061                                }
062                                SailPointObject object = context.getObject(objectType, (String)key);
063                                if (object != null) {
064                                        object.clearPersistentIdentity();
065                                        object = Utilities.detach(context, object);
066                                        return (T) object;
067                                } else {
068                                        if (log.isWarnEnabled()) {
069                                                log.warn("No such object: type [" + objectType.getName() + "], name or ID [" + key + "]");
070                                        }
071                                }
072                        }
073                } catch(GeneralException e) {
074                        log.error("Unable to load SailPointObject for caching", e);
075                        return null;
076                }
077                return null;
078        }
079        
080}