Package org.projectforge.database

Source Code of org.projectforge.database.MyDatabaseUpdateDao

/////////////////////////////////////////////////////////////////////////////
//
// Project ProjectForge Community Edition
//         www.projectforge.org
//
// Copyright (C) 2001-2014 Kai Reinhard (k.reinhard@micromata.de)
//
// ProjectForge is dual-licensed.
//
// This community edition is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation; version 3 of the License.
//
// This community edition is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
// Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, see http://www.gnu.org/licenses/.
//
/////////////////////////////////////////////////////////////////////////////

package org.projectforge.database;

import java.io.Serializable;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.projectforge.access.AccessChecker;
import org.projectforge.access.AccessException;
import org.projectforge.continuousdb.DatabaseUpdateDao;
import org.projectforge.continuousdb.UpdateEntry;
import org.projectforge.continuousdb.UpdaterConfiguration;
import org.projectforge.core.BaseDO;
import org.projectforge.plugins.core.AbstractPlugin;
import org.projectforge.plugins.core.PluginsRegistry;
import org.projectforge.registry.Registry;
import org.projectforge.user.Login;
import org.projectforge.user.PFUserContext;
import org.projectforge.user.PFUserDO;
import org.projectforge.user.ProjectForgeGroup;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ResultSetExtractor;

/**
* For manipulating the database (patching data etc.)
* @author Kai Reinhard (k.reinhard@micromata.de)
*
*/
public class MyDatabaseUpdateDao extends DatabaseUpdateDao
{
  private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(MyDatabaseUpdateDao.class);

  // private static String CATALOG = null;

  // private static String SCHEMA_PATTERN = null;

  // private static String TABLE_TYPE = "TABLE";

  public MyDatabaseUpdateDao(final UpdaterConfiguration configuration)
  {
    super(configuration);
  }

  private AccessChecker accessChecker;

  private static PFUserDO SYSTEM_ADMIN_PSEUDO_USER = new PFUserDO().setUsername("System admin user only for internal usage");

  public static PFUserDO __internalGetSystemAdminPseudoUser()
  {
    return SYSTEM_ADMIN_PSEUDO_USER;
  }

  @Override
  protected void accessCheck(final boolean writeaccess)
  {
    if (PFUserContext.getUser() == SYSTEM_ADMIN_PSEUDO_USER) {
      // No access check for the system admin pseudo user.
      return;
    }
    if (Login.getInstance().isAdminUser(PFUserContext.getUser()) == false) {
      throw new AccessException(AccessChecker.I18N_KEY_VIOLATION_USER_NOT_MEMBER_OF, ProjectForgeGroup.ADMIN_GROUP.getKey());
    }
    accessChecker.checkRestrictedOrDemoUser();
  }

  /**
   */
  public List<DatabaseUpdateDO> getUpdateHistory()
  {
    accessCheck(false);
    final JdbcTemplate jdbc = new JdbcTemplate(getDataSource());
    final List<Map<String, Object>> dbResult = jdbc.queryForList("select * from t_database_update order by update_date desc");
    final List<DatabaseUpdateDO> result = new ArrayList<DatabaseUpdateDO>();
    for (final Map<String, Object> map : dbResult) {
      final DatabaseUpdateDO entry = new DatabaseUpdateDO();
      entry.setUpdateDate((Date) map.get("update_date"));
      entry.setRegionId((String) map.get("region_id"));
      entry.setVersionString((String) map.get("version"));
      entry.setExecutionResult((String) map.get("execution_result"));
      final PFUserDO executedByUser = Registry.instance().getUserGroupCache().getUser((Integer) map.get("executed_by_user_fk"));
      entry.setExecutedBy(executedByUser);
      entry.setDescription((String) map.get("description"));
      result.add(entry);
    }
    return result;
  }

  /**
   * @see org.projectforge.continuousdb.DatabaseUpdateDao#createMissingIndices()
   */
  @Override
  public int createMissingIndices()
  {
    int result = super.createMissingIndices();
    if (createIndex("idx_timesheet_user_time", "t_timesheet", "user_id, start_time") == true) {
      ++result;
    }
    for (final AbstractPlugin plugin : PluginsRegistry.instance().getPlugins()) {
      if (plugin.isInitialized() == false) {
        // Plug-in not (yet) initialized, skip. this is normal on first start-up phase.
        continue;
      }
      final UpdateEntry updateEntry = plugin.getInitializationUpdateEntry();
      if (updateEntry != null) {
        result += updateEntry.createMissingIndices();
      }
    }
    return result;
  }

  /**
   * There is a bug for Hibernate history with Javassist: Sometimes the data base objects are serialized with the default toString() method
   * instead of using the plain id. This method fixes all wrong data base history entries.
   */
  public int fixDBHistoryEntries()
  {
    accessCheck(true);
    return internalFixDBHistoryEntries();
  }

  /**
   * Without access checking.
   * @see #fixDBHistoryEntries()
   */
  @SuppressWarnings({ "unchecked", "rawtypes"})
  public int internalFixDBHistoryEntries()
  {
    log.info("Fix all broken history entries (if exist).");
    final int counter[] = new int[1];
    counter[0] = 0;
    final JdbcTemplate jdbc = new JdbcTemplate(getDataSource());
    try {
      String sql = " from t_history_property_delta where old_value like 'org.projectforge.%' or new_value like 'org.projectforge.%'";
      jdbc.query("select id, old_value, new_value, property_type" + sql, new ResultSetExtractor() {
        @Override
        public Object extractData(final ResultSet rs) throws SQLException, DataAccessException
        {
          while (rs.next() == true) {
            final int id = rs.getInt("ID");
            final String oldValue = rs.getString("OLD_VALUE");
            final String newValue = rs.getString("NEW_VALUE");
            final Serializable oldId = getObjectId(oldValue);
            final Serializable newId = getObjectId(newValue);
            final String propertyType = rs.getString("PROPERTY_TYPE");
            final int pos = propertyType.indexOf("_$$_javassist_");
            final String newPropertyType;
            if (pos > 0) {
              newPropertyType = propertyType.substring(0, pos);
            } else {
              newPropertyType = null;
            }
            if (oldId == null && newId == null) {
              continue;
            }
            final StringBuffer buf = new StringBuffer();
            boolean first = true;
            buf.append("update t_history_property_delta set ");
            if (oldId != null) {
              buf.append("OLD_VALUE='").append(oldId).append("'");
              first = false;
            }
            if (newId != null) {
              if (first == false) {
                buf.append(", ");
              } else {
                first = false;
              }
              buf.append("NEW_VALUE='").append(newId).append("'");
            }
            if (newPropertyType != null) {
              if (first == false) {
                buf.append(", ");
              } else {
                first = false;
              }
              buf.append("PROPERTY_TYPE='").append(newPropertyType).append("'");
            }
            buf.append(" where ID=").append(id);
            final String sql = buf.toString();
            log.info(sql);
            jdbc.execute(sql);
            counter[0]++;
          }
          return null;
        }
      });
      int no = jdbc.queryForInt("select count(*)" + sql);
      if (no > 0) {
        log.warn("" + no + " of data base history entries aren't fixed.");
      }
      sql = " from t_history_property_delta where property_type like '%_$$_javassist_%'";
      jdbc.query("select id, property_type" + sql, new ResultSetExtractor() {
        @Override
        public Object extractData(final ResultSet rs) throws SQLException, DataAccessException
        {
          while (rs.next() == true) {
            final int id = rs.getInt("ID");
            final String propertyType = rs.getString("PROPERTY_TYPE");
            final int pos = propertyType.indexOf("_$$_javassist_");
            if (pos < 0) {
              log.error("Oups, should not occur.");
              continue;
            }
            final String newPropertyType = propertyType.substring(0, pos);
            final String sql = "update t_history_property_delta set PROPERTY_TYPE='" + newPropertyType + "' where id=" + id;
            log.info(sql);
            jdbc.execute(sql);
            counter[0]++;
          }
          return null;
        }
      });
      no = jdbc.queryForInt("select count(*)" + sql);
      if (no > 0) {
        log.warn("" + no + " of data base history entries aren't fixed.");
      }
    } catch (final Exception ex) {
      log.error(ex.getMessage(), ex);
      return 0;
    }
    return counter[0];
  }

  private Serializable getObjectId(final String serializedObject)
  {
    if (serializedObject == null || serializedObject.startsWith("org.projectforge.") == false || serializedObject.indexOf('@') < 0) {
      return null;
    }
    final String className = serializedObject.substring(0, serializedObject.indexOf('@'));
    Class< ? > clazz = null;
    try {
      clazz = Class.forName(className);
    } catch (final ClassNotFoundException ex) {
      log.error("Can't load class. " + ex, ex);
      return null;
    }
    if (BaseDO.class.isAssignableFrom(clazz) == false) {
      log.error("Unsupported class: " + clazz);
    }
    final Integer id = DatabaseUpdateHelper.getId(serializedObject);
    return id;
  }

  public void setAccessChecker(final AccessChecker accessChecker)
  {
    this.accessChecker = accessChecker;
  }
}
TOP

Related Classes of org.projectforge.database.MyDatabaseUpdateDao

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.