/* * * 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; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.net.URL; import java.util.concurrent.atomic.AtomicBoolean; import javax.xml.bind.JAXBException; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import org.bouncycastle.util.encoders.Base64; import org.xipki.commons.common.util.IoUtil; import org.xipki.commons.common.util.ParamUtil; import org.xipki.commons.datasource.DataSourceWrapper; import org.xipki.commons.datasource.springframework.dao.DataAccessException; import org.xipki.pki.ca.dbtool.DbSchemaInfo; import org.xipki.pki.ca.dbtool.DbToolBase; import org.xipki.pki.ca.dbtool.jaxb.ca.FileOrBinaryType; import org.xipki.pki.ca.dbtool.jaxb.ca.FileOrValueType; import org.xml.sax.SAXException; /** * @author Lijun Liao * @since 2.0.0 */ public class DbPorter extends DbToolBase { public enum OcspDbEntryType { CERT("certs", "CERT", 1); private final String dirName; private final String tableName; private final float sqlBatchFactor; private OcspDbEntryType(final String dirName, final String tableName, final float sqlBatchFactor) { this.dirName = dirName; this.tableName = tableName; this.sqlBatchFactor = sqlBatchFactor; } public String getDirName() { return dirName; } public String getTableName() { return tableName; } public float getSqlBatchFactor() { return sqlBatchFactor; } } public enum CaDbEntryType { CERT("certs", "CERT", 1), CRL("crls", "CRL", 0.1f), USER("users", "TUSER", 10), CAUSER("causers", "CA_HAS_USER", 10), REQUEST("requests", "REQUEST", 0.1f), REQCERT("reqcerts", "REQCERT", 50); private final String dirName; private final String tableName; private final float sqlBatchFactor; private CaDbEntryType(final String dirName, final String tableName, final float sqlBatchFactor) { this.dirName = dirName; this.tableName = tableName; this.sqlBatchFactor = sqlBatchFactor; } public String getDirName() { return dirName; } public String getTableName() { return tableName; } public float getSqlBatchFactor() { return sqlBatchFactor; } } public static final String FILENAME_CA_CONFIGURATION = "ca-configuration.xml"; public static final String FILENAME_CA_CERTSTORE = "ca-certstore.xml"; public static final String FILENAME_OCSP_CERTSTORE = "ocsp-certstore.xml"; public static final String DIRNAME_CRL = "crl"; public static final String DIRNAME_CERT = "cert"; public static final String PREFIX_FILENAME_CERTS = "certs-"; public static final String EXPORT_PROCESS_LOG_FILENAME = "export.process"; public static final String IMPORT_PROCESS_LOG_FILENAME = "import.process"; public static final String IMPORT_TO_OCSP_PROCESS_LOG_FILENAME = "import-to-ocsp.process"; public static final int VERSION = 1; protected final boolean evaulateOnly; protected final int dbSchemaVersion; protected final int maxX500nameLen; public DbPorter(final DataSourceWrapper datasource, final String baseDir, final AtomicBoolean stopMe, final boolean evaluateOnly) throws DataAccessException { super(datasource, baseDir, stopMe); this.evaulateOnly = evaluateOnly; DbSchemaInfo dbSchemaInfo = new DbSchemaInfo(datasource); String str = dbSchemaInfo.getVariableValue("VERSION"); this.dbSchemaVersion = Integer.parseInt(str); str = dbSchemaInfo.getVariableValue("X500NAME_MAXLEN"); this.maxX500nameLen = Integer.parseInt(str); } protected FileOrValueType buildFileOrValue(final String content, final String fileName) throws IOException { if (content == null) { return null; } ParamUtil.requireNonNull("fileName", fileName); FileOrValueType ret = new FileOrValueType(); if (content.length() < 256) { ret.setValue(content); return ret; } File file = new File(baseDir, fileName); File parent = file.getParentFile(); if (parent != null && !parent.exists()) { parent.mkdirs(); } IoUtil.save(file, content.getBytes("UTF-8")); ret.setFile(fileName); return ret; } protected String getValue(final FileOrValueType fileOrValue) throws IOException { if (fileOrValue == null) { return null; } if (fileOrValue.getValue() != null) { return fileOrValue.getValue(); } File file = new File(baseDir, fileOrValue.getFile()); return new String(IoUtil.read(file), "UTF-8"); } protected FileOrBinaryType buildFileOrBase64Binary(final String base64Content, final String fileName) throws IOException { if (base64Content == null) { return null; } return buildFileOrBinary(Base64.decode(base64Content), fileName); } protected FileOrBinaryType buildFileOrBinary(final byte[] content, final String fileName) throws IOException { if (content == null) { return null; } ParamUtil.requireNonNull("fileName", fileName); FileOrBinaryType ret = new FileOrBinaryType(); if (content.length < 256) { ret.setBinary(content); return ret; } File file = new File(baseDir, fileName); File parent = file.getParentFile(); if (parent != null && !parent.exists()) { parent.mkdirs(); } IoUtil.save(file, content); ret.setFile(fileName); return ret; } protected byte[] getBinary(final FileOrBinaryType fileOrValue) throws IOException { if (fileOrValue == null) { return null; } if (fileOrValue.getBinary() != null) { return fileOrValue.getBinary(); } File file = new File(baseDir, fileOrValue.getFile()); return IoUtil.read(file); } protected String getImportingText() { return evaulateOnly ? "evaluating import " : "importing "; } protected String getImportedText() { return evaulateOnly ? " evaluated import " : " imported "; } protected String getExportingText() { return evaulateOnly ? "evaluating export " : "exporting "; } protected String getExportedText() { return evaulateOnly ? " evaluated export " : " exported "; } public static final Schema retrieveSchema(final String schemaPath) throws JAXBException { ParamUtil.requireNonNull("schemaPath", schemaPath); URL schemaUrl = DbPorter.class.getResource(schemaPath); final SchemaFactory schemaFact = SchemaFactory.newInstance( javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI); try { return schemaFact.newSchema(schemaUrl); } catch (SAXException ex) { throw new JAXBException("could not load schemas for the specified classes\nDetails:\n" + ex.getMessage()); } } public static void echoToFile(final String content, final File file) throws IOException { ParamUtil.requireNonNull("content", content); ParamUtil.requireNonNull("file", file); FileOutputStream out = null; try { out = new FileOutputStream(file); out.write(content.getBytes()); } finally { if (out != null) { out.flush(); out.close(); } } } }