<commit_before>package com.cloud.utils.db;

import com.cloud.utils.DateUtil;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.Ternary;
import com.cloud.utils.component.ComponentLifecycle;
import com.cloud.utils.component.ComponentLifecycleBase;
import com.cloud.utils.component.ComponentMethodInterceptable;
import com.cloud.utils.crypt.DBEncryptionUtil;
import com.cloud.utils.db.SearchCriteria.SelectType;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.Ip;
import com.cloud.utils.net.NetUtils;

import javax.naming.ConfigurationException;
import javax.persistence.AttributeOverride;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.EntityExistsException;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.Table;
import javax.persistence.TableGenerator;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.CallbackFilter;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.Factory;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.NoOp;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * GenericDaoBase is a simple way to implement DAOs.  It DOES NOT
 * support the full EJB3 spec.  It borrows some of the annotations from
 * the EJB3 spec to produce a set of SQLs so developers don't have to
 * copy and paste the same code over and over again.  Of course,
 * GenericDaoBase is completely at the mercy of the annotations you add
 * to your entity bean.  If GenericDaoBase does not fit your needs, then
 * don't extend from it.
 * <p>
 * GenericDaoBase attempts to achieve the following:
 * 1. If you use _allFieldsStr in your SQL statement and use to() to convert
 * the result to the entity bean, you don't ever have to worry about
 * missing fields because its automatically taken from the entity bean's
 * annotations.
 * 2. You don't have to rewrite the same insert and select query strings
 * in all of your DAOs.
 * 3. You don't have to match the '?' (you know what I'm talking about) to
 * the fields in the insert statement as that's taken care of for you.
 * <p>
 * GenericDaoBase looks at the following annotations:
 * 1. Table - just name
 * 2. Column - just name
 * 3. GeneratedValue - any field with this annotation is not inserted.
 * 4. SequenceGenerator - sequence generator
 * 5. Id
 * 6. SecondaryTable
 * <p>
 * Sometime later, I might look into injecting the SQLs as needed but right
 * now we have to construct them at construction time.  The good thing is that
 * the DAOs are suppose to be one per jvm so the time is all during the
 * initial load.
 **/
@DB
public abstract class GenericDaoBase<T, ID extends Serializable> extends ComponentLifecycleBase implements GenericDao<T, ID>, ComponentMethodInterceptable {
    protected final static TimeZone s_gmtTimeZone = TimeZone.getTimeZone("GMT");
    protected final static Map<Class<?>, GenericDao<?, ? extends Serializable>> s_daoMaps = new ConcurrentHashMap<>(71);
    protected final static CallbackFilter s_callbackFilter = new UpdateFilter();
    protected static final String FOR_UPDATE_CLAUSE = " FOR UPDATE ";
    protected static final String SHARE_MODE_CLAUSE = " LOCK IN SHARE MODE";
    protected static final String SELECT_LAST_INSERT_ID_SQL = "SELECT LAST_INSERT_ID()";
    protected static final SequenceFetcher s_seqFetcher = SequenceFetcher.getInstance();
    private final static Logger s_logger = LoggerFactory.getLogger(GenericDaoBase.class);
    // This is private on purpose.  Everyone should use createPartialSelectSql()
    private final Pair<StringBuilder, Attribute[]> _partialSelectSql;
    private final Pair<StringBuilder, Attribute[]> _partialQueryCacheSelectSql;
    protected Class<T> _entityBeanType;
    protected String _table;
    protected String _tables;
    protected Field[] _embeddedFields;
    protected StringBuilder _discriminatorClause;
    protected Map<String, Object> _discriminatorValues;
    protected String _selectByIdSql;
    protected String _count;
    protected String _distinctIdSql;
    protected Field _idField;
    protected List<Pair<String, Attribute[]>> _insertSqls;
    protected Pair<String, Attribute> _removed;
    protected Pair<String, Attribute[]> _removeSql;
    protected List<Pair<String, Attribute[]>> _deleteSqls;
    protected Map<String, Attribute[]> _idAttributes;
    protected Map<String, TableGenerator> _tgs;
    protected Map<String, Attribute> _allAttributes;
    protected List<Attribute> _ecAttributes;
    protected Map<Pair<String, String>, Attribute> _allColumns;
    protected Enhancer _enhancer;
    protected Factory _factory;
    protected Enhancer _searchEnhancer;
    protected int _timeoutSeconds;
    protected Cache _cache;

    protected GenericDaoBase() {
        super();
        final Type t = getClass().getGenericSuperclass();
        if (t instanceof ParameterizedType) {
            _entityBeanType = (Class<T>) ((ParameterizedType) t).getActualTypeArguments()[0];
        } else if (((Class<?>) t).getGenericSuperclass() instanceof ParameterizedType) {
            _entityBeanType = (Class<T>) ((ParameterizedType) ((Class<?>) t).getGenericSuperclass()).getActualTypeArguments()[0];
        } else {
            _entityBeanType = (Class<T>) ((ParameterizedType) ((Class<?>) ((Class<?>) t).getGenericSuperclass()).getGenericSuperclass()).getActualTypeArguments()[0];
        }

        s_daoMaps.put(_entityBeanType, this);
        final Class<?>[] interphaces = _entityBeanType.getInterfaces();
        if (interphaces != null) {
            for (final Class<?> interphace : interphaces) {
                s_daoMaps.put(interphace, this);
            }
        }

        _table = DbUtil.getTableName(_entityBeanType);

        final SqlGenerator generator = new SqlGenerator(_entityBeanType);
        _partialSelectSql = generator.buildSelectSql(false);
        _count = generator.buildCountSql();
        _distinctIdSql = generator.buildDistinctIdSql();
        _partialQueryCacheSelectSql = generator.buildSelectSql(true);
        _embeddedFields = generator.getEmbeddedFields();
        _insertSqls = generator.buildInsertSqls();
        final Pair<StringBuilder, Map<String, Object>> dc = generator.buildDiscriminatorClause();
        _discriminatorClause = dc.first().length() == 0 ? null : dc.first();
        _discriminatorValues = dc.second();

        _idAttributes = generator.getIdAttributes();
        _idField = _idAttributes.get(_table).length > 0 ? _idAttributes.get(_table)[0].field : null;

        _tables = generator.buildTableReferences();

        _allAttributes = generator.getAllAttributes();
        _allColumns = generator.getAllColumns();

        _selectByIdSql = buildSelectByIdSql(createPartialSelectSql(null, true));
        _removeSql = generator.buildRemoveSql();
        _deleteSqls = generator.buildDeleteSqls();
        _removed = generator.getRemovedAttribute();
        _tgs = generator.getTableGenerators();
        _ecAttributes = generator.getElementCollectionAttributes();

        TableGenerator tg = this.getClass().getAnnotation(TableGenerator.class);
        if (tg != null) {
            _tgs.put(tg.name(), tg);
        }
        tg = this.getClass().getSuperclass().getAnnotation(TableGenerator.class);
        if (tg != null) {
            _tgs.put(tg.name(), tg);
        }

        final Callback[] callbacks = new Callback[]{NoOp.INSTANCE, new UpdateBuilder(this)};

        _enhancer = new Enhancer();
        _enhancer.setSuperclass(_entityBeanType);
        _enhancer.setCallbackFilter(s_callbackFilter);
        _enhancer.setCallbacks(callbacks);
        _factory = (Factory) _enhancer.create();

        _searchEnhancer = new Enhancer();
        _searchEnhancer.setSuperclass(_entityBeanType);
        _searchEnhancer.setCallback(new UpdateBuilder(this));

        if (s_logger.isTraceEnabled()) {
            s_logger.trace("Select SQL: " + _partialSelectSql.first().toString());
            s_logger.trace("Remove SQL: " + (_removeSql != null ? _removeSql.first() : "No remove sql"));
            s_logger.trace("Select by Id SQL: " + _selectByIdSql);
            s_logger.trace("Table References: " + _tables);
            s_logger.trace("Insert SQLs:");
            for (final Pair<String, Attribute[]> insertSql : _insertSqls) {
                s_logger.trace(insertSql.first());
            }

            s_logger.trace("Delete SQLs");
            for (final Pair<String, Attribute[]> deletSql : _deleteSqls) {
                s_logger.trace(deletSql.first());
            }

            s_logger.trace("Collection SQLs");
            for (final Attribute attr : _ecAttributes) {
                final EcInfo info = (EcInfo) attr.attache;
                s_logger.trace(info.insertSql);
                s_logger.trace(info.selectSql);
            }
        }

        setRunLevel(ComponentLifecycle.RUN_LEVEL_SYSTEM);
    }

    @DB()
    protected String buildSelectByIdSql(final StringBuilder sql) {
        if (_idField == null) {
            return null;
        }

        if (_idField.getAnnotation(EmbeddedId.class) == null) {
            sql.append(_table).append(".").append(DbUtil.getColumnName(_idField, null)).append(" = ? ");
        } else {
            final Class<?> clazz = _idField.getClass();
            final AttributeOverride[] overrides = DbUtil.getAttributeOverrides(_idField);
            for (final Field field : clazz.getDeclaredFields()) {
                sql.append(_table).append(".").append(DbUtil.getColumnName(field, overrides)).append(" = ? AND ");
            }
            sql.delete(sql.length() - 4, sql.length());
        }

        return sql.toString();
    }

    @Override
    @DB()
    public <J> GenericSearchBuilder<T, J> createSearchBuilder(final Class<J> resultType) {
        return new GenericSearchBuilder<>(_entityBeanType, resultType);
    }

    @DB()
    protected StringBuilder createPartialSelectSql(final SearchCriteria<?> sc, final boolean whereClause) {
        final StringBuilder sql = new StringBuilder(_partialSelectSql.first());
        if (sc != null && !sc.isSelectAll()) {
            sql.delete(7, sql.indexOf(" FROM"));
            sc.getSelect(sql, 7);
        }

        if (!whereClause) {
            sql.delete(sql.length() - (_discriminatorClause == null ? 6 : 4), sql.length());
        }

        return sql;
    }

    public static <J> GenericDao<? extends J, ? extends Serializable> getDao(final Class<J> entityType) {
        final
        GenericDao<? extends J, ? extends Serializable> dao = (GenericDao<? extends J, ? extends Serializable>) s_daoMaps.get(entityType);
        assert dao != null : "Unable to find DAO for " + entityType + ".  Are you sure you waited for the DAO to be initialized before asking for it?";
        return dao;
    }

    @Override
    public Map<String, Attribute> getAllAttributes() {
        return _allAttributes;
    }

    /**<commit_msg>Log request for DAO object<commit_after>package com.cloud.utils.db;

import com.cloud.utils.DateUtil;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.Ternary;
import com.cloud.utils.component.ComponentLifecycle;
import com.cloud.utils.component.ComponentLifecycleBase;
import com.cloud.utils.component.ComponentMethodInterceptable;
import com.cloud.utils.crypt.DBEncryptionUtil;
import com.cloud.utils.db.SearchCriteria.SelectType;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.Ip;
import com.cloud.utils.net.NetUtils;

import javax.naming.ConfigurationException;
import javax.persistence.AttributeOverride;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.EntityExistsException;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.Table;
import javax.persistence.TableGenerator;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.CallbackFilter;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.Factory;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.NoOp;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * GenericDaoBase is a simple way to implement DAOs.  It DOES NOT
 * support the full EJB3 spec.  It borrows some of the annotations from
 * the EJB3 spec to produce a set of SQLs so developers don't have to
 * copy and paste the same code over and over again.  Of course,
 * GenericDaoBase is completely at the mercy of the annotations you add
 * to your entity bean.  If GenericDaoBase does not fit your needs, then
 * don't extend from it.
 * <p>
 * GenericDaoBase attempts to achieve the following:
 * 1. If you use _allFieldsStr in your SQL statement and use to() to convert
 * the result to the entity bean, you don't ever have to worry about
 * missing fields because its automatically taken from the entity bean's
 * annotations.
 * 2. You don't have to rewrite the same insert and select query strings
 * in all of your DAOs.
 * 3. You don't have to match the '?' (you know what I'm talking about) to
 * the fields in the insert statement as that's taken care of for you.
 * <p>
 * GenericDaoBase looks at the following annotations:
 * 1. Table - just name
 * 2. Column - just name
 * 3. GeneratedValue - any field with this annotation is not inserted.
 * 4. SequenceGenerator - sequence generator
 * 5. Id
 * 6. SecondaryTable
 * <p>
 * Sometime later, I might look into injecting the SQLs as needed but right
 * now we have to construct them at construction time.  The good thing is that
 * the DAOs are suppose to be one per jvm so the time is all during the
 * initial load.
 **/
@DB
public abstract class GenericDaoBase<T, ID extends Serializable> extends ComponentLifecycleBase implements GenericDao<T, ID>, ComponentMethodInterceptable {
    protected final static TimeZone s_gmtTimeZone = TimeZone.getTimeZone("GMT");
    protected final static Map<Class<?>, GenericDao<?, ? extends Serializable>> s_daoMaps = new ConcurrentHashMap<>(71);
    protected final static CallbackFilter s_callbackFilter = new UpdateFilter();
    protected static final String FOR_UPDATE_CLAUSE = " FOR UPDATE ";
    protected static final String SHARE_MODE_CLAUSE = " LOCK IN SHARE MODE";
    protected static final String SELECT_LAST_INSERT_ID_SQL = "SELECT LAST_INSERT_ID()";
    protected static final SequenceFetcher s_seqFetcher = SequenceFetcher.getInstance();
    private final static Logger s_logger = LoggerFactory.getLogger(GenericDaoBase.class);
    // This is private on purpose.  Everyone should use createPartialSelectSql()
    private final Pair<StringBuilder, Attribute[]> _partialSelectSql;
    private final Pair<StringBuilder, Attribute[]> _partialQueryCacheSelectSql;
    protected Class<T> _entityBeanType;
    protected String _table;
    protected String _tables;
    protected Field[] _embeddedFields;
    protected StringBuilder _discriminatorClause;
    protected Map<String, Object> _discriminatorValues;
    protected String _selectByIdSql;
    protected String _count;
    protected String _distinctIdSql;
    protected Field _idField;
    protected List<Pair<String, Attribute[]>> _insertSqls;
    protected Pair<String, Attribute> _removed;
    protected Pair<String, Attribute[]> _removeSql;
    protected List<Pair<String, Attribute[]>> _deleteSqls;
    protected Map<String, Attribute[]> _idAttributes;
    protected Map<String, TableGenerator> _tgs;
    protected Map<String, Attribute> _allAttributes;
    protected List<Attribute> _ecAttributes;
    protected Map<Pair<String, String>, Attribute> _allColumns;
    protected Enhancer _enhancer;
    protected Factory _factory;
    protected Enhancer _searchEnhancer;
    protected int _timeoutSeconds;
    protected Cache _cache;

    protected GenericDaoBase() {
        super();
        final Type t = getClass().getGenericSuperclass();
        if (t instanceof ParameterizedType) {
            _entityBeanType = (Class<T>) ((ParameterizedType) t).getActualTypeArguments()[0];
        } else if (((Class<?>) t).getGenericSuperclass() instanceof ParameterizedType) {
            _entityBeanType = (Class<T>) ((ParameterizedType) ((Class<?>) t).getGenericSuperclass()).getActualTypeArguments()[0];
        } else {
            _entityBeanType = (Class<T>) ((ParameterizedType) ((Class<?>) ((Class<?>) t).getGenericSuperclass()).getGenericSuperclass()).getActualTypeArguments()[0];
        }

        s_daoMaps.put(_entityBeanType, this);
        final Class<?>[] interfaceClasses = _entityBeanType.getInterfaces();
        if (interfaceClasses != null) {
            for (final Class<?> interfaceClass : interfaceClasses) {
                s_daoMaps.put(interfaceClass, this);
            }
        }

        _table = DbUtil.getTableName(_entityBeanType);

        final SqlGenerator generator = new SqlGenerator(_entityBeanType);
        _partialSelectSql = generator.buildSelectSql(false);
        _count = generator.buildCountSql();
        _distinctIdSql = generator.buildDistinctIdSql();
        _partialQueryCacheSelectSql = generator.buildSelectSql(true);
        _embeddedFields = generator.getEmbeddedFields();
        _insertSqls = generator.buildInsertSqls();
        final Pair<StringBuilder, Map<String, Object>> dc = generator.buildDiscriminatorClause();
        _discriminatorClause = dc.first().length() == 0 ? null : dc.first();
        _discriminatorValues = dc.second();

        _idAttributes = generator.getIdAttributes();
        _idField = _idAttributes.get(_table).length > 0 ? _idAttributes.get(_table)[0].field : null;

        _tables = generator.buildTableReferences();

        _allAttributes = generator.getAllAttributes();
        _allColumns = generator.getAllColumns();

        _selectByIdSql = buildSelectByIdSql(createPartialSelectSql(null, true));
        _removeSql = generator.buildRemoveSql();
        _deleteSqls = generator.buildDeleteSqls();
        _removed = generator.getRemovedAttribute();
        _tgs = generator.getTableGenerators();
        _ecAttributes = generator.getElementCollectionAttributes();

        TableGenerator tg = this.getClass().getAnnotation(TableGenerator.class);
        if (tg != null) {
            _tgs.put(tg.name(), tg);
        }
        tg = this.getClass().getSuperclass().getAnnotation(TableGenerator.class);
        if (tg != null) {
            _tgs.put(tg.name(), tg);
        }

        final Callback[] callbacks = new Callback[]{NoOp.INSTANCE, new UpdateBuilder(this)};

        _enhancer = new Enhancer();
        _enhancer.setSuperclass(_entityBeanType);
        _enhancer.setCallbackFilter(s_callbackFilter);
        _enhancer.setCallbacks(callbacks);
        _factory = (Factory) _enhancer.create();

        _searchEnhancer = new Enhancer();
        _searchEnhancer.setSuperclass(_entityBeanType);
        _searchEnhancer.setCallback(new UpdateBuilder(this));

        if (s_logger.isTraceEnabled()) {
            s_logger.trace("Select SQL: " + _partialSelectSql.first().toString());
            s_logger.trace("Remove SQL: " + (_removeSql != null ? _removeSql.first() : "No remove sql"));
            s_logger.trace("Select by Id SQL: " + _selectByIdSql);
            s_logger.trace("Table References: " + _tables);
            s_logger.trace("Insert SQLs:");
            for (final Pair<String, Attribute[]> insertSql : _insertSqls) {
                s_logger.trace(insertSql.first());
            }

            s_logger.trace("Delete SQLs");
            for (final Pair<String, Attribute[]> deletSql : _deleteSqls) {
                s_logger.trace(deletSql.first());
            }

            s_logger.trace("Collection SQLs");
            for (final Attribute attr : _ecAttributes) {
                final EcInfo info = (EcInfo) attr.attache;
                s_logger.trace(info.insertSql);
                s_logger.trace(info.selectSql);
            }
        }

        setRunLevel(ComponentLifecycle.RUN_LEVEL_SYSTEM);
    }

    @DB()
    protected String buildSelectByIdSql(final StringBuilder sql) {
        if (_idField == null) {
            return null;
        }

        if (_idField.getAnnotation(EmbeddedId.class) == null) {
            sql.append(_table).append(".").append(DbUtil.getColumnName(_idField, null)).append(" = ? ");
        } else {
            final Class<?> clazz = _idField.getClass();
            final AttributeOverride[] overrides = DbUtil.getAttributeOverrides(_idField);
            for (final Field field : clazz.getDeclaredFields()) {
                sql.append(_table).append(".").append(DbUtil.getColumnName(field, overrides)).append(" = ? AND ");
            }
            sql.delete(sql.length() - 4, sql.length());
        }

        return sql.toString();
    }

    @Override
    @DB()
    public <J> GenericSearchBuilder<T, J> createSearchBuilder(final Class<J> resultType) {
        return new GenericSearchBuilder<>(_entityBeanType, resultType);
    }

    @DB()
    protected StringBuilder createPartialSelectSql(final SearchCriteria<?> sc, final boolean whereClause) {
        final StringBuilder sql = new StringBuilder(_partialSelectSql.first());
        if (sc != null && !sc.isSelectAll()) {
            sql.delete(7, sql.indexOf(" FROM"));
            sc.getSelect(sql, 7);
        }

        if (!whereClause) {
            sql.delete(sql.length() - (_discriminatorClause == null ? 6 : 4), sql.length());
        }

        return sql;
    }

    public static <J> GenericDao<? extends J, ? extends Serializable> getDao(final Class<J> entityType) {
        final GenericDao<? extends J, ? extends Serializable> dao = (GenericDao<? extends J, ? extends Serializable>) s_daoMaps.get(entityType);
        if (dao == null) {
            s_logger.info("Unable to find DAO for {}", entityType);
        }
        return dao;
    }

    @Override
    public Map<String, Attribute> getAllAttributes() {
        return _allAttributes;
    }

    /**
{'fraction_non_alphanumeric': 0.10337332274380304, 'fraction_numerical': 0.0021736404297119927, 'mean_word_length': 3.489397635578908, 'pattern_counts': {'":': 0, '<': 103, '<?xml version=': 0, '>': 105, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '985153', 'n_tokens_mistral': 6715, 'n_tokens_neox': 6668, 'n_words': 1747}