/* * * Copyright (c) 2013 - 2017 Lijun Liao * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License version 3 * as published by the Free Software Foundation with the addition of the * following permission added to Section 15 as permitted in Section 7(a): * * FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY * THE AUTHOR LIJUN LIAO. LIJUN LIAO DISCLAIMS THE WARRANTY OF NON INFRINGEMENT * OF THIRD PARTY RIGHTS. * * This program 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * The interactive user interfaces in modified source and object code versions * of this program must display Appropriate Legal Notices, as required under * Section 5 of the GNU Affero General Public License. * * You can be released from the requirements of the license by purchasing * a commercial license. Buying such a license is mandatory as soon as you * develop commercial activities involving the XiPKI software without * disclosing the source code of your own applications. * * For more information, please contact Lijun Liao at this * address: lijun.liao@gmail.com */ package org.xipki.pki.ca.dbtool.port.ca; import java.io.File; import java.io.InputStream; import java.math.BigInteger; import java.security.cert.CRLException; import java.security.cert.CertificateException; import java.security.cert.X509CRL; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Types; import java.util.StringTokenizer; import java.util.concurrent.atomic.AtomicBoolean; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; import javax.xml.stream.XMLStreamException; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1Integer; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.x509.BasicConstraints; import org.bouncycastle.asn1.x509.Certificate; import org.bouncycastle.asn1.x509.Extension; import org.bouncycastle.asn1.x509.TBSCertificate; import org.bouncycastle.util.encoders.Base64; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xipki.commons.common.ProcessLog; import org.xipki.commons.common.util.IoUtil; import org.xipki.commons.common.util.ParamUtil; import org.xipki.commons.common.util.StringUtil; import org.xipki.commons.common.util.XmlUtil; import org.xipki.commons.datasource.DataSourceWrapper; import org.xipki.commons.datasource.springframework.dao.DataAccessException; import org.xipki.commons.security.FpIdCalculator; import org.xipki.commons.security.HashAlgoType; import org.xipki.commons.security.util.X509Util; import org.xipki.pki.ca.dbtool.jaxb.ca.CertStoreType; import org.xipki.pki.ca.dbtool.jaxb.ca.CertStoreType.DeltaCRLCache; import org.xipki.pki.ca.dbtool.jaxb.ca.CertStoreType.PublishQueue; import org.xipki.pki.ca.dbtool.jaxb.ca.DeltaCRLCacheEntryType; import org.xipki.pki.ca.dbtool.jaxb.ca.ToPublishType; import org.xipki.pki.ca.dbtool.port.DbPortFileNameIterator; import org.xipki.pki.ca.dbtool.port.DbPorter; import org.xipki.pki.ca.dbtool.xmlio.DbiXmlReader; import org.xipki.pki.ca.dbtool.xmlio.IdentifidDbObjectType; import org.xipki.pki.ca.dbtool.xmlio.InvalidDataObjectException; import org.xipki.pki.ca.dbtool.xmlio.ca.CaUserType; import org.xipki.pki.ca.dbtool.xmlio.ca.CaUsersReader; import org.xipki.pki.ca.dbtool.xmlio.ca.CertType; import org.xipki.pki.ca.dbtool.xmlio.ca.CertsReader; import org.xipki.pki.ca.dbtool.xmlio.ca.CrlType; import org.xipki.pki.ca.dbtool.xmlio.ca.CrlsReader; import org.xipki.pki.ca.dbtool.xmlio.ca.RequestCertType; import org.xipki.pki.ca.dbtool.xmlio.ca.RequestCertsReader; import org.xipki.pki.ca.dbtool.xmlio.ca.RequestType; import org.xipki.pki.ca.dbtool.xmlio.ca.RequestsReader; import org.xipki.pki.ca.dbtool.xmlio.ca.UserType; import org.xipki.pki.ca.dbtool.xmlio.ca.UsersReader; /** * @author Lijun Liao * @since 2.0.0 */ class CaCertStoreDbImporter extends AbstractCaCertStoreDbPorter { private static final Logger LOG = LoggerFactory.getLogger(CaConfigurationDbImporter.class); private static final String SQL_ADD_CERT = "INSERT INTO CERT (ID,ART,LUPDATE,SN,SUBJECT,FP_S,FP_RS,NBEFORE,NAFTER,REV,RR,RT,RIT," + "PID,CA_ID,RID,UID,FP_K,EE,RTYPE,TID)" + " VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; private static final String SQL_ADD_CRAW = "INSERT INTO CRAW (CID,SHA1,REQ_SUBJECT,CERT) VALUES (?,?,?,?)"; private static final String SQL_ADD_CRL = "INSERT INTO CRL (ID,CA_ID,CRL_NO,THISUPDATE,NEXTUPDATE,DELTACRL,BASECRL_NO,CRL)" + " VALUES (?,?,?,?,?,?,?,?)"; private static final String SQL_ADD_USER = "INSERT INTO TUSER (ID,NAME,ACTIVE,PASSWORD) VALUES (?,?,?,?)"; private static final String SQL_ADD_CAUSER = "INSERT INTO CA_HAS_USER (ID,CA_ID,USER_ID,PERMISSION,PROFILES) VALUES (?,?,?,?,?)"; private static final String SQL_ADD_REQUEST = "INSERT INTO REQUEST (ID,LUPDATE,DATA) VALUES (?,?,?)"; private static final String SQL_ADD_REQCERT = "INSERT INTO REQCERT (ID,RID,CID) VALUES (?,?,?)"; private final Unmarshaller unmarshaller; private final boolean resume; private final int numCertsPerCommit; CaCertStoreDbImporter(final DataSourceWrapper datasource, final Unmarshaller unmarshaller, final String srcDir, final int numCertsPerCommit, final boolean resume, final AtomicBoolean stopMe, final boolean evaluateOnly) throws Exception { super(datasource, srcDir, stopMe, evaluateOnly); this.unmarshaller = ParamUtil.requireNonNull("unmarshaller", unmarshaller); this.numCertsPerCommit = ParamUtil.requireMin("numCertsPerCommit", numCertsPerCommit, 1); this.resume = resume; File processLogFile = new File(baseDir, DbPorter.IMPORT_PROCESS_LOG_FILENAME); if (resume) { if (!processLogFile.exists()) { throw new Exception("could not process with '--resume' option"); } } else { if (processLogFile.exists()) { throw new Exception("please either specify '--resume' option or delete the file " + processLogFile.getPath() + " first"); } } } public void importToDb() throws Exception { CertStoreType certstore; try { @SuppressWarnings("unchecked") JAXBElement<CertStoreType> root = (JAXBElement<CertStoreType>) unmarshaller.unmarshal(new File(baseDir, FILENAME_CA_CERTSTORE)); certstore = root.getValue(); } catch (JAXBException ex) { throw XmlUtil.convert(ex); } if (certstore.getVersion() > VERSION) { throw new Exception("could not import CertStore greater than " + VERSION + ": " + certstore.getVersion()); } File processLogFile = new File(baseDir, DbPorter.IMPORT_PROCESS_LOG_FILENAME); System.out.println("importing CA certstore to database"); try { if (!resume) { dropIndexes(); } CaDbEntryType typeProcessedInLastProcess = null; Integer numProcessedInLastProcess = null; Long idProcessedInLastProcess = null; if (processLogFile.exists()) { byte[] content = IoUtil.read(processLogFile); if (content != null && content.length > 5) { String str = new String(content); StringTokenizer st = new StringTokenizer(str, ":"); String type = st.nextToken(); typeProcessedInLastProcess = CaDbEntryType.valueOf(type); numProcessedInLastProcess = Integer.parseInt(st.nextToken()); idProcessedInLastProcess = Long.parseLong(st.nextToken()); } } boolean entriesFinished = false; // finished for the given type if (typeProcessedInLastProcess != null && idProcessedInLastProcess != null && idProcessedInLastProcess == -1) { numProcessedInLastProcess = 0; idProcessedInLastProcess = 0L; switch (typeProcessedInLastProcess) { case USER: typeProcessedInLastProcess = CaDbEntryType.CAUSER; break; case CAUSER: typeProcessedInLastProcess = CaDbEntryType.CRL; break; case CRL: typeProcessedInLastProcess = CaDbEntryType.CERT; break; case CERT: typeProcessedInLastProcess = CaDbEntryType.REQUEST; break; case REQUEST: typeProcessedInLastProcess = CaDbEntryType.REQCERT; break; case REQCERT: entriesFinished = true; break; default: throw new RuntimeException("unsupported CaDbEntryType " + typeProcessedInLastProcess); } } if (!entriesFinished) { Exception exception = null; if (CaDbEntryType.USER == typeProcessedInLastProcess || typeProcessedInLastProcess == null) { exception = importEntries(CaDbEntryType.USER, certstore, processLogFile, numProcessedInLastProcess, idProcessedInLastProcess); typeProcessedInLastProcess = null; numProcessedInLastProcess = null; idProcessedInLastProcess = null; } CaDbEntryType[] types = new CaDbEntryType[] {CaDbEntryType.CAUSER, CaDbEntryType.CRL, CaDbEntryType.CERT, CaDbEntryType.REQUEST, CaDbEntryType.REQCERT}; for (CaDbEntryType type : types) { if (exception == null && (type == typeProcessedInLastProcess || typeProcessedInLastProcess == null)) { exception = importEntries(type, certstore, processLogFile, numProcessedInLastProcess, idProcessedInLastProcess); } } if (exception != null) { throw exception; } } importPublishQueue(certstore.getPublishQueue()); importDeltaCrlCache(certstore.getDeltaCRLCache()); recoverIndexes(); processLogFile.delete(); } catch (Exception ex) { System.err.println("could not import CA certstore to database"); throw ex; } System.out.println(" imported CA certstore to database"); } // method importToDb private void importPublishQueue(final PublishQueue publishQueue) throws DataAccessException { final String sql = "INSERT INTO PUBLISHQUEUE (CID,PID,CA_ID) VALUES (?,?,?)"; System.out.println("importing table PUBLISHQUEUE"); PreparedStatement ps = prepareStatement(sql); try { for (ToPublishType tbp : publishQueue.getTop()) { try { int idx = 1; ps.setLong(idx++, tbp.getCertId()); ps.setInt(idx++, tbp.getPubId()); ps.setInt(idx++, tbp.getCaId()); ps.execute(); } catch (SQLException ex) { System.err.println("could not import PUBLISHQUEUE with CID=" + tbp.getCertId() + " and PID=" + tbp.getPubId() + ", message: " + ex.getMessage()); throw translate(sql, ex); } } } finally { releaseResources(ps, null); } System.out.println(" imported table PUBLISHQUEUE"); } // method importPublishQueue private void importDeltaCrlCache(final DeltaCRLCache deltaCrlCache) throws DataAccessException { final String sql = "INSERT INTO DELTACRL_CACHE (ID,SN,CA_ID) VALUES (?,?,?)"; System.out.println("importing table DELTACRL_CACHE"); PreparedStatement ps = prepareStatement(sql); try { long id = 1; for (DeltaCRLCacheEntryType entry : deltaCrlCache.getEntry()) { try { int idx = 1; ps.setLong(idx++, id++); ps.setString(idx++, entry.getSerial()); ps.setInt(idx++, entry.getCaId()); ps.execute(); } catch (SQLException ex) { System.err.println("could not import DELTACRL_CACHE with caId=" + entry.getCaId() + " and serial=" + entry.getSerial() + ", message: " + ex.getMessage()); throw translate(sql, ex); } } } finally { releaseResources(ps, null); } System.out.println(" imported table DELTACRL_CACHE"); } // method importDeltaCRLCache private Exception importEntries(final CaDbEntryType type, final CertStoreType certstore, final File processLogFile, final Integer numProcessedInLastProcess, final Long idProcessedInLastProcess) { String tablesText = (CaDbEntryType.CERT == type) ? "tables CERT and CRAW" : "table " + type.getTableName(); try { int numProcessedBefore = 0; long minId = 1; if (idProcessedInLastProcess != null) { minId = idProcessedInLastProcess + 1; numProcessedBefore = numProcessedInLastProcess; } deleteFromTableWithLargerId(type.getTableName(), "ID", minId - 1, LOG); if (type == CaDbEntryType.CERT) { deleteFromTableWithLargerId("CRAW", "CID", minId - 1, LOG); } final long total; String[] sqls; switch (type) { case CERT: total = certstore.getCountCerts(); sqls = new String[] {SQL_ADD_CERT, SQL_ADD_CRAW}; break; case CRL: total = certstore.getCountCrls(); sqls = new String[] {SQL_ADD_CRL}; break; case USER: total = certstore.getCountUsers(); sqls = new String[] {SQL_ADD_USER}; break; case CAUSER: total = certstore.getCountCaUsers(); sqls = new String[] {SQL_ADD_CAUSER}; break; case REQUEST: total = certstore.getCountRequests(); sqls = new String[] {SQL_ADD_REQUEST}; break; case REQCERT: total = certstore.getCountReqCerts(); sqls = new String[] {SQL_ADD_REQCERT}; break; default: throw new RuntimeException("unsupported DbEntryType " + type); } final long remainingTotal = total - numProcessedBefore; final ProcessLog processLog = new ProcessLog(remainingTotal); System.out.println(getImportingText() + "entries to " + tablesText + " from ID " + minId); processLog.printHeader(); DbPortFileNameIterator entriesFileIterator = null; PreparedStatement[] statements = null; try { entriesFileIterator = new DbPortFileNameIterator( baseDir + File.separator + type.getDirName() + ".mf"); statements = new PreparedStatement[sqls.length]; for (int i = 0; i < sqls.length; i++) { statements[i] = prepareStatement(sqls[i]); } while (entriesFileIterator.hasNext()) { String entriesFile = baseDir + File.separator + type.getDirName() + File.separator + entriesFileIterator.next(); // extract the toId from the filename int fromIdx = entriesFile.indexOf('-'); int toIdx = entriesFile.indexOf(".zip"); if (fromIdx != -1 && toIdx != -1) { try { long toId = Integer.parseInt(entriesFile.substring(fromIdx + 1, toIdx)); if (toId < minId) { // try next file continue; } } catch (Exception ex) { LOG.warn("invalid file name '{}', but will still be processed", entriesFile); } } else { LOG.warn("invalid file name '{}', but will still be processed", entriesFile); } try { long lastId = doImportEntries(type, entriesFile, minId, processLogFile, processLog, numProcessedBefore, statements, sqls); minId = lastId + 1; } catch (Exception ex) { System.err.println("\ncould not import entries from file " + entriesFile + ".\nplease continue with the option '--resume'"); LOG.error("Exception", ex); return ex; } } // end for } finally { if (statements != null) { for (PreparedStatement stmt : statements) { if (stmt != null) { releaseResources(stmt, null); } } } if (entriesFileIterator != null) { entriesFileIterator.close(); } } processLog.printTrailer(); echoToFile(type + ":" + (numProcessedBefore + processLog.getNumProcessed()) + ":-1", processLogFile); System.out.println(getImportedText() + processLog.getNumProcessed() + " entries"); return null; } catch (Exception ex) { System.err.println("\nimporting " + tablesText + " has been cancelled due to error,\n" + "please continue with the option '--resume'"); LOG.error("Exception", ex); return ex; } } private long doImportEntries(final CaDbEntryType type, final String entriesZipFile, final long minId, final File processLogFile, final ProcessLog processLog, final int numProcessedInLastProcess, final PreparedStatement[] statements, final String[] sqls) throws Exception { final int numEntriesPerCommit = Math.max(1, Math.round(type.getSqlBatchFactor() * numCertsPerCommit)); ZipFile zipFile = new ZipFile(new File(entriesZipFile)); ZipEntry entriesXmlEntry = zipFile.getEntry("overview.xml"); DbiXmlReader entries; try { entries = createReader(type, zipFile.getInputStream(entriesXmlEntry)); } catch (Exception ex) { try { zipFile.close(); } catch (Exception e2) { LOG.error("could not close ZIP file {}: {}", entriesZipFile, e2.getMessage()); LOG.debug("could not close ZIP file " + entriesZipFile, e2); } throw ex; } disableAutoCommit(); try { int numEntriesInBatch = 0; long lastSuccessfulEntryId = 0; while (entries.hasNext()) { if (stopMe.get()) { throw new InterruptedException("interrupted by the user"); } IdentifidDbObjectType entry = (IdentifidDbObjectType) entries.next(); long id = entry.getId(); if (id < minId) { continue; } numEntriesInBatch++; if (CaDbEntryType.CERT == type) { CertType cert = (CertType) entry; int certArt = (cert.getArt() == null) ? 1 : cert.getArt(); String filename = cert.getFile(); // rawcert ZipEntry certZipEnty = zipFile.getEntry(filename); // rawcert byte[] encodedCert = IoUtil.read(zipFile.getInputStream(certZipEnty)); TBSCertificate tbsCert; try { Certificate cc = Certificate.getInstance(encodedCert); tbsCert = cc.getTBSCertificate(); } catch (RuntimeException ex) { LOG.error("could not parse certificate in file {}", filename); LOG.debug("could not parse certificate in file " + filename, ex); throw new CertificateException(ex.getMessage(), ex); } byte[] encodedKey = tbsCert.getSubjectPublicKeyInfo().getPublicKeyData() .getBytes(); String b64Sha1FpCert = HashAlgoType.SHA1.base64Hash(encodedCert); // cert String subjectText = X509Util.cutX500Name(tbsCert.getSubject(), maxX500nameLen); PreparedStatement psCert = statements[0]; PreparedStatement psRawcert = statements[1]; try { int idx = 1; psCert.setLong(idx++, id); psCert.setInt(idx++, certArt); psCert.setLong(idx++, cert.getUpdate()); psCert.setString(idx++, tbsCert.getSerialNumber().getPositiveValue().toString(16)); psCert.setString(idx++, subjectText); long fpSubject = X509Util.fpCanonicalizedName(tbsCert.getSubject()); psCert.setLong(idx++, fpSubject); if (cert.getFpRs() != null) { psCert.setLong(idx++, cert.getFpRs()); } else { psCert.setNull(idx++, Types.BIGINT); } psCert.setLong(idx++, tbsCert.getStartDate().getDate().getTime() / 1000); psCert.setLong(idx++, tbsCert.getEndDate().getDate().getTime() / 1000); setBoolean(psCert, idx++, cert.getRev()); setInt(psCert, idx++, cert.getRr()); setLong(psCert, idx++, cert.getRt()); setLong(psCert, idx++, cert.getRit()); setInt(psCert, idx++, cert.getPid()); setInt(psCert, idx++, cert.getCaId()); setInt(psCert, idx++, cert.getRid()); setInt(psCert, idx++, cert.getUid()); psCert.setLong(idx++, FpIdCalculator.hash(encodedKey)); Extension extension = tbsCert.getExtensions().getExtension(Extension.basicConstraints); boolean ee = true; if (extension != null) { ASN1Encodable asn1 = extension.getParsedValue(); ee = !BasicConstraints.getInstance(asn1).isCA(); } psCert.setInt(idx++, ee ? 1 : 0); psCert.setInt(idx++, cert.getReqType()); String tidS = null; if (cert.getTid() != null) { tidS = cert.getTid(); } psCert.setString(idx++, tidS); psCert.addBatch(); } catch (SQLException ex) { throw translate(SQL_ADD_CERT, ex); } try { int idx = 1; psRawcert.setLong(idx++, cert.getId()); psRawcert.setString(idx++, b64Sha1FpCert); psRawcert.setString(idx++, cert.getRs()); psRawcert.setString(idx++, Base64.toBase64String(encodedCert)); psRawcert.addBatch(); } catch (SQLException ex) { throw translate(SQL_ADD_CRAW, ex); } } else if (CaDbEntryType.CRL == type) { PreparedStatement psAddCrl = statements[0]; CrlType crl = (CrlType) entry; String filename = crl.getFile(); // CRL ZipEntry zipEnty = zipFile.getEntry(filename); // rawcert byte[] encodedCrl = IoUtil.read(zipFile.getInputStream(zipEnty)); X509CRL x509crl = null; try { x509crl = X509Util.parseCrl(encodedCrl); } catch (Exception ex) { LOG.error("could not parse CRL in file {}", filename); LOG.debug("could not parse CRL in file " + filename, ex); if (ex instanceof CRLException) { throw (CRLException) ex; } else { throw new CRLException(ex.getMessage(), ex); } } try { byte[] octetString = x509crl.getExtensionValue(Extension.cRLNumber.getId()); if (octetString == null) { LOG.warn("CRL without CRL number, ignore it"); continue; } byte[] extnValue = DEROctetString.getInstance(octetString).getOctets(); // CHECKSTYLE:SKIP BigInteger crlNumber = ASN1Integer.getInstance(extnValue) .getPositiveValue(); BigInteger baseCrlNumber = null; octetString = x509crl.getExtensionValue( Extension.deltaCRLIndicator.getId()); if (octetString != null) { extnValue = DEROctetString.getInstance(octetString).getOctets(); baseCrlNumber = ASN1Integer.getInstance(extnValue).getPositiveValue(); } int idx = 1; psAddCrl.setLong(idx++, crl.getId()); psAddCrl.setInt(idx++, crl.getCaId()); psAddCrl.setLong(idx++, crlNumber.longValue()); psAddCrl.setLong(idx++, x509crl.getThisUpdate().getTime() / 1000); if (x509crl.getNextUpdate() != null) { psAddCrl.setLong(idx++, x509crl.getNextUpdate().getTime() / 1000); } else { psAddCrl.setNull(idx++, Types.INTEGER); } if (baseCrlNumber == null) { setBoolean(psAddCrl, idx++, false); psAddCrl.setNull(idx++, Types.BIGINT); } else { setBoolean(psAddCrl, idx++, true); psAddCrl.setLong(idx++, baseCrlNumber.longValue()); } String str = Base64.toBase64String(encodedCrl); psAddCrl.setString(idx++, str); psAddCrl.addBatch(); } catch (SQLException ex) { System.err.println("could not import CRL with ID=" + crl.getId() + ", message: " + ex.getMessage()); throw ex; } } else if (CaDbEntryType.USER == type) { PreparedStatement psAddUser = statements[0]; UserType user = (UserType) entry; try { int idx = 1; psAddUser.setLong(idx++, user.getId()); psAddUser.setString(idx++, user.getName()); setBoolean(psAddUser, idx++, user.getActive()); psAddUser.setString(idx++, user.getPassword()); psAddUser.addBatch(); } catch (SQLException ex) { System.err.println("could not import TUSER with ID=" + user.getId() + ", message: " + ex.getMessage()); throw ex; } } else if (CaDbEntryType.CAUSER == type) { PreparedStatement psAddCaUser = statements[0]; CaUserType causer = (CaUserType) entry; try { int idx = 1; psAddCaUser.setLong(idx++, causer.getId()); psAddCaUser.setInt(idx++, causer.getCaId()); psAddCaUser.setInt(idx++, causer.getUid()); psAddCaUser.setInt(idx++, causer.getPermission()); psAddCaUser.setString(idx++, causer.getProfiles()); psAddCaUser.addBatch(); } catch (SQLException ex) { System.err.println("could not import CA_HAS_USER with ID=" + causer.getId() + ", message: " + ex.getMessage()); throw ex; } } else if (CaDbEntryType.REQUEST == type) { PreparedStatement psAddRequest = statements[0]; RequestType request = (RequestType) entry; String filename = request.getFile(); ZipEntry zipEnty = zipFile.getEntry(filename); byte[] encodedRequest = IoUtil.read(zipFile.getInputStream(zipEnty)); try { int idx = 1; psAddRequest.setLong(idx++, request.getId()); psAddRequest.setLong(idx++, request.getUpdate()); psAddRequest.setString(idx++, Base64.toBase64String(encodedRequest)); psAddRequest.addBatch(); } catch (SQLException ex) { System.err.println("could not import REQUEST with ID=" + request.getId() + ", message: " + ex.getMessage()); throw ex; } } else if (CaDbEntryType.REQCERT == type) { PreparedStatement psAddReqCert = statements[0]; RequestCertType reqCert = (RequestCertType) entry; try { int idx = 1; psAddReqCert.setLong(idx++, reqCert.getId()); psAddReqCert.setLong(idx++, reqCert.getRid()); psAddReqCert.setLong(idx++, reqCert.getCid()); psAddReqCert.addBatch(); } catch (SQLException ex) { System.err.println("could not import REQUEST with ID=" + reqCert.getId() + ", message: " + ex.getMessage()); throw ex; } } else { throw new RuntimeException("Unknown CaDbEntryType " + type); } boolean isLastBlock = !entries.hasNext(); if (numEntriesInBatch > 0 && (numEntriesInBatch % numEntriesPerCommit == 0 || isLastBlock)) { if (evaulateOnly) { for (PreparedStatement m : statements) { m.clearBatch(); } } else { String sql = null; try { for (int i = 0; i < sqls.length; i++) { sql = sqls[i]; statements[i].executeBatch(); } sql = null; commit("(commit import to CA)"); } catch (Throwable th) { rollback(); deleteFromTableWithLargerId(type.getTableName(), "ID", id, LOG); if (CaDbEntryType.CERT == type) { deleteFromTableWithLargerId("CRAW", "CID", id, LOG); } if (th instanceof SQLException) { throw translate(sql, (SQLException) th); } else if (th instanceof Exception) { throw (Exception) th; } else { throw new Exception(th); } } } lastSuccessfulEntryId = id; processLog.addNumProcessed(numEntriesInBatch); numEntriesInBatch = 0; echoToFile(type + ":" + (numProcessedInLastProcess + processLog.getNumProcessed()) + ":" + lastSuccessfulEntryId, processLogFile); processLog.printStatus(); } } // end while return lastSuccessfulEntryId; } finally { recoverAutoCommit(); zipFile.close(); } } // method doImportEntries private static DbiXmlReader createReader(final CaDbEntryType type, final InputStream is) throws XMLStreamException, InvalidDataObjectException { switch (type) { case CERT: return new CertsReader(is); case CRL: return new CrlsReader(is); case USER: return new UsersReader(is); case CAUSER: return new CaUsersReader(is); case REQUEST: return new RequestsReader(is); case REQCERT: return new RequestCertsReader(is); default: throw new RuntimeException("unknown CaDbEntryType " + type); } } private void dropIndexes() throws DataAccessException { long start = System.currentTimeMillis(); datasource.dropIndex(null, "CERT", "IDX_CA_FPK"); datasource.dropIndex(null, "CERT", "IDX_CA_FPS"); datasource.dropIndex(null, "CERT", "IDX_CA_FPRS"); datasource.dropUniqueConstrain(null, "CONST_USER_NAME", "TUSER"); datasource.dropForeignKeyConstraint(null, "FK_CERT_CA1", "CERT"); datasource.dropForeignKeyConstraint(null, "FK_CERT_USER1", "CERT"); datasource.dropUniqueConstrain(null, "CONST_CA_SN", "CERT"); datasource.dropForeignKeyConstraint(null, "FK_CRAW_CERT1", "CRAW"); datasource.dropForeignKeyConstraint(null, "FK_PUBLISHQUEUE_CERT1", "PUBLISHQUEUE"); datasource.dropForeignKeyConstraint(null, "FK_REQCERT_REQ1", "REQCERT"); datasource.dropForeignKeyConstraint(null, "FK_REQCERT_CERT1", "REQCERT"); datasource.dropForeignKeyConstraint(null, "FK_CA_HAS_USER_USER1", "CA_HAS_USER"); datasource.dropForeignKeyConstraint(null, "FK_CA_HAS_USER_CA1", "CA_HAS_USER"); datasource.dropPrimaryKey(null, "PK_CERT", "CERT"); datasource.dropPrimaryKey(null, "PK_CRAW", "CRAW"); datasource.dropPrimaryKey(null, "PK_REQUEST", "REQUEST"); datasource.dropPrimaryKey(null, "PK_REQCERT", "REQCERT"); datasource.dropPrimaryKey(null, "PK_TUSER", "TUSER"); datasource.dropPrimaryKey(null, "PK_CA_HAS_USER", "CA_HAS_USER"); long duration = (System.currentTimeMillis() - start) / 1000; System.out.println(" dropped indexes in " + StringUtil.formatTime(duration, false)); } private void recoverIndexes() throws DataAccessException { long start = System.currentTimeMillis(); datasource.addPrimaryKey(null, "PK_CERT", "CERT", "ID"); datasource.addPrimaryKey(null, "PK_CRAW", "CRAW", "CID"); datasource.addPrimaryKey(null, "PK_REQUEST", "REQUEST", "ID"); datasource.addPrimaryKey(null, "PK_REQCERT", "REQCERT", "ID"); datasource.addPrimaryKey(null, "PK_TUSER", "TUSER", "ID"); datasource.addPrimaryKey(null, "PK_CA_HAS_USER", "CA_HAS_USER", "ID"); datasource.addForeignKeyConstraint(null, "FK_PUBLISHQUEUE_CERT1", "PUBLISHQUEUE", "CID", "CERT", "ID", "CASCADE", "NO ACTION"); datasource.addForeignKeyConstraint(null, "FK_CRAW_CERT1", "CRAW", "CID", "CERT", "ID", "CASCADE", "NO ACTION"); datasource.addForeignKeyConstraint(null, "FK_CERT_CA1", "CERT", "CA_ID", "CA", "ID", "CASCADE", "NO ACTION"); datasource.addForeignKeyConstraint(null, "FK_CERT_USER1", "CERT", "UID", "TUSER", "ID", "CASCADE", "NO ACTION"); datasource.addForeignKeyConstraint(null, "FK_REQCERT_REQ1", "REQCERT", "RID", "REQUEST", "ID", "CASCADE", "NO ACTION"); datasource.addForeignKeyConstraint(null, "FK_REQCERT_CERT1", "REQCERT", "CID", "CERT", "ID", "CASCADE", "NO ACTION"); datasource.addUniqueConstrain(null, "CONST_CA_SN", "CERT", "CA_ID", "SN"); datasource.addForeignKeyConstraint(null, "FK_CA_HAS_USER_USER1", "CA_HAS_USER", "USER_ID", "TUSER", "ID", "CASCADE", "NO ACTION"); datasource.addForeignKeyConstraint(null, "FK_CA_HAS_USER_CA1", "CA_HAS_USER", "CA_ID", "CA", "ID", "CASCADE", "NO ACTION"); datasource.addUniqueConstrain(null, "CONST_USER_NAME", "TUSER", "NAME"); datasource.createIndex(null, "IDX_CA_FPK", "CERT", "CA_ID", "FP_K"); datasource.createIndex(null, "IDX_CA_FPS", "CERT", "CA_ID", "FP_S"); datasource.createIndex(null, "IDX_CA_FPRS", "CERT", "CA_ID", "FP_RS"); long duration = (System.currentTimeMillis() - start) / 1000; System.out.println(" recovered indexes in " + StringUtil.formatTime(duration, false)); } }