Package org.ejbca.core.ejb.upgrade

Source Code of org.ejbca.core.ejb.upgrade.UpgradeSessionBean

/*************************************************************************
*                                                                       *
*  EJBCA: The OpenSource Certificate Authority                          *
*                                                                       *
*  This software is free software; you can redistribute it and/or       *
*  modify it under the terms of the GNU Lesser General Public           *
*  License as published by the Free Software Foundation; either         *
*  version 2.1 of the License, or any later version.                    *
*                                                                       *
*  See terms of license at gnu.org.                                     *
*                                                                       *
*************************************************************************/

package org.ejbca.core.ejb.upgrade;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.apache.log4j.Logger;
import org.ejbca.core.ejb.JBossUnmarshaller;
import org.ejbca.core.ejb.JndiHelper;
import org.ejbca.core.ejb.ca.caadmin.CertificateProfileData;
import org.ejbca.core.ejb.hardtoken.HardTokenData;
import org.ejbca.core.ejb.hardtoken.HardTokenIssuerData;
import org.ejbca.core.ejb.log.LogConfigurationData;
import org.ejbca.core.ejb.ra.raadmin.AdminPreferencesData;
import org.ejbca.core.ejb.ra.raadmin.EndEntityProfileData;
import org.ejbca.core.ejb.ra.raadmin.GlobalConfigurationData;
import org.ejbca.core.model.log.Admin;
import org.ejbca.core.model.log.LogConfiguration;
import org.ejbca.util.JDBCUtil;
import org.ejbca.util.SqlExecutor;

/**
* The upgrade session bean is used to upgrade the database between EJBCA
* releases.
*
* @version $Id: UpgradeSessionBean.java 11337 2011-02-10 22:37:15Z jeklund $
*/
@Stateless(mappedName = JndiHelper.APP_JNDI_PREFIX + "UpgradeSessionRemote")
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public class UpgradeSessionBean implements UpgradeSessionLocal, UpgradeSessionRemote {

    private static final Logger log = Logger.getLogger(UpgradeSessionBean.class);

    @PersistenceContext(unitName = "ejbca")
    private EntityManager entityManager;

    @Resource
    private SessionContext sessionContext;

    private UpgradeSessionLocal upgradeSession;

    @PostConstruct
    public void ejbCreate() {
      upgradeSession = sessionContext.getBusinessObject(UpgradeSessionLocal.class);
    }

    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
    @Override
    public boolean upgrade(Admin admin, String dbtype, String sOldVersion, boolean isPost) {
        if (log.isTraceEnabled()) {
            log.trace(">upgrade(" + admin.toString() + ")");
        }
        try {
            log.debug("Upgrading from version=" + sOldVersion);
            final int oldVersion;
            {
                final String[] oldVersionArray = sOldVersion.split("\\."); // Split around the '.'-char
                oldVersion = Integer.parseInt(oldVersionArray[0]) * 100 + Integer.parseInt(oldVersionArray[1]);
            }
            if (isPost) {
                return postUpgrade(oldVersion);
            }
            return upgrade(dbtype, oldVersion);
        } finally {
            log.trace("<upgrade()");
        }
    }

    private boolean postUpgrade(int oldVersion) {
        if (oldVersion < 311) {
            log.error("Only upgrade from EJBCA 3.11.x is supported in EJBCA 4.0.x.");
            return false;
        }
        // Upgrade database change between EJBCA 3.11.x and EJBCA 4.0.x if needed
        if (oldVersion <= 400) {
            return postMigrateDatabase400();
        }
        return false;
    }

    private boolean upgrade(String dbtype, int oldVersion) {
        if (oldVersion <= 311) {
            log.error("Only upgrade from EJBCA 3.11.x is supported in EJBCA 4.0.x.");
            return false;
        }
        // Seamless upgrade between EJBCA 3.11.x and EJBCA 4.0.x
        return true;
    }

    /**
     * Called from other migrate methods, don't call this directly, call from an
     * interface-method
     *
     * Not used in EJBCA 4.0.x, but will probably be in EJBCA 4.1.x
     */
    private boolean migrateDatabase(String resource) {
        // Fetch the resource file with SQL to modify the database tables
        InputStream in = this.getClass().getResourceAsStream(resource);
        if (in == null) {
            log.error("Can not read resource for database '" + resource + "', this database probably does not need table definition changes.");
            // no error
            return true;
        }
        // Migrate database tables to new columns etc
        Connection con = null;
        log.info("Start migration of database.");
        try {
            InputStreamReader inreader = new InputStreamReader(in);
            con = JDBCUtil.getDBConnection();
            SqlExecutor sqlex = new SqlExecutor(con, false);
            sqlex.runCommands(inreader);
        } catch (SQLException e) {
            log.error("SQL error during database migration: ", e);
            return false;
        } catch (IOException e) {
            log.error("IO error during database migration: ", e);
            return false;
        } finally {
            JDBCUtil.close(con);
        }
        return true;
    }

    /**
     * (ECA-200:) In EJB 2.1 JBoss CMP used it's own serialization method for all Object/BLOB fields.
     *
     * This affects the following entity fields:
     * - CertificateProfileData.data
     * - HardTokenData.data
     * - HardTokenIssuerData.data
     * - LogConfigurationData.logConfiguration
     * - AdminPreferencesData.data
     * - EndEntityProfileData.data
     * - GlobalConfigurationData.data
     *
     * NOTE: You only need to run this if you upgrade a JBoss installation.
     */
    private boolean postMigrateDatabase400() {
      log.error("(this is not an error) Starting post upgrade from ejbca 3.11.x to ejbca 4.0.x");
      boolean ret = true;
      upgradeSession.postMigrateDatabase400SmallTables()// Migrate small tables in a new transaction
      log.info(" Processing HardTokenData entities.");
      log.info(" - Building a list of entities.");
      final List<String> tokenSNs = HardTokenData.findAllTokenSN(entityManager);
      int position = 0;
      final int chunkSize = 1000;
      while (position < tokenSNs.size()) {
          log.info(" - Processing entity " + position + " to " + Math.min(position+chunkSize-1, tokenSNs.size()-1) + ".");
          // Migrate HardTokenData table in chunks, each running in a new transaction
        upgradeSession.postMigrateDatabase400HardTokenData(getSubSet(tokenSNs, position, chunkSize));
        position += chunkSize;
      }
      log.error("(this is not an error) Finished post upgrade from ejbca 3.11.x to ejbca 4.0.x with result: "+ret);
        return ret;
    }
   
    /** @return a subset of the source list with index as its first item and index+count-1 as its last. */
    private <T> List<T> getSubSet(final List<T> source, final int index, final int count) {
      List<T> ret = new ArrayList<T>(count);
      for (int i=0; i<count; i++) {
        ret.add(source.get(index + i));
      }
      return ret;
    }

    @Override
    public void postMigrateDatabase400SmallTables() {
      log.info(" Processing CertificateProfileData entities.");
      final List<CertificateProfileData> cpds = CertificateProfileData.findAll(entityManager);
      for (CertificateProfileData cpd : cpds) {
        cpd.setDataUnsafe(JBossUnmarshaller.extractObject(HashMap.class, cpd.getDataUnsafe()));
      }
      log.info(" Processing HardTokenIssuerData entities.");
      final List<HardTokenIssuerData> htids = HardTokenIssuerData.findAll(entityManager);
      for (HardTokenIssuerData htid : htids) {
        htid.setDataUnsafe(JBossUnmarshaller.extractObject(HashMap.class, htid.getDataUnsafe()));
      }
      log.info(" Processing LogConfigurationData entities.");
      final List<LogConfigurationData> lcds = LogConfigurationData.findAll(entityManager);
      for (LogConfigurationData lcd : lcds) {
        lcd.setLogConfigurationUnsafe(JBossUnmarshaller.extractObject(LogConfiguration.class, lcd.getLogConfigurationUnsafe()));
      }
      log.info(" Processing AdminPreferencesData entities.");
      final List<AdminPreferencesData> apds = AdminPreferencesData.findAll(entityManager);
      for (AdminPreferencesData apd : apds) {
        apd.setDataUnsafe(JBossUnmarshaller.extractObject(HashMap.class, apd.getDataUnsafe()));
      }
      log.info(" Processing EndEntityProfileData entities.");
      final List<EndEntityProfileData> eepds = EndEntityProfileData.findAll(entityManager);
      for (EndEntityProfileData eepd : eepds) {
        eepd.setDataUnsafe(JBossUnmarshaller.extractObject(HashMap.class, eepd.getDataUnsafe()));
      }
      log.info(" Processing GlobalConfigurationData entities.");
      GlobalConfigurationData gcd = GlobalConfigurationData.findByConfigurationId(entityManager, "0");
      gcd.setDataUnsafe(JBossUnmarshaller.extractObject(HashMap.class, gcd.getDataUnsafe()));
    }
   
    @Override
    public void postMigrateDatabase400HardTokenData(List<String> subSet) {
      for (String tokenSN : subSet) {
        HardTokenData htd = HardTokenData.findByTokenSN(entityManager, tokenSN);
        if (htd != null) {
            htd.setDataUnsafe(JBossUnmarshaller.extractObject(HashMap.class, htd.getDataUnsafe()));
        } else {
            log.warn("Hard token was removed during processing. Ignoring token with serial number '" + tokenSN + "'.");
        }
      }
    }
}
TOP

Related Classes of org.ejbca.core.ejb.upgrade.UpgradeSessionBean

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.