package org.openlca.app.wizards.io; import java.io.File; import java.lang.reflect.InvocationTargetException; import java.util.UUID; import org.apache.commons.io.FileUtils; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.wizard.Wizard; import org.eclipse.ui.IImportWizard; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.PlatformUI; import org.openlca.app.App; import org.openlca.app.M; import org.openlca.app.db.Database; import org.openlca.app.devtools.python.Python; import org.openlca.app.navigation.Navigator; import org.openlca.app.rcp.images.Icon; import org.openlca.app.util.Question; import org.openlca.core.database.IDatabase; import org.openlca.core.database.derby.DerbyDatabase; import org.openlca.io.olca.DatabaseImport; import org.openlca.updates.Update; import org.openlca.updates.UpdateHelper; import org.openlca.updates.UpdateMetaInfo; import org.openlca.updates.VersionState; import org.openlca.updates.legacy.Upgrades; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.zeroturnaround.zip.ZipUtil; /** * Wizards for the import of data from an openLCA database to another openLCA * database. */ public class DbImportWizard extends Wizard implements IImportWizard { private Logger log = LoggerFactory.getLogger(this.getClass()); private DbImportPage page; @Override public void init(IWorkbench iWorkbench, IStructuredSelection iStructuredSelection) { setWindowTitle(M.DatabaseImport); setDefaultPageImageDescriptor(Icon.IMPORT_ZIP_WIZARD .descriptor()); setNeedsProgressMonitor(true); } @Override public boolean performFinish() { if (Database.get() == null) { org.openlca.app.util.Error.showBox(M.NoDatabaseOpened, M.DBImportNoTarget); return true; } try { DbImportPage.ImportConfig config = page.getConfig(); ConnectionDispatch connectionDispatch = createConnection(config); boolean canRun = canRun(config, connectionDispatch); if (!canRun) { connectionDispatch.close(); return false; } ImportDispatch importDispatch = new ImportDispatch( connectionDispatch); getContainer().run(true, true, importDispatch); Navigator.refresh(); return true; } catch (Exception e) { log.error("database import failed", e); return false; } } private boolean canRun(DbImportPage.ImportConfig config, ConnectionDispatch connectionDispatch) { VersionState state = connectionDispatch.getSourceState(); if (state == VersionState.UP_TO_DATE) return true; if (state == null || state == VersionState.ERROR) { org.openlca.app.util.Error.showBox(M.ConnectionFailed, M.DBImportNoTargetConnectionFailedMessage); return false; } if (state == VersionState.HIGHER_VERSION) { org.openlca.app.util.Error .showBox( M.VersionNewer, M.DBImportVersionNewerMessage); return false; } if (config.mode == config.FILE_MODE) return true; return Question .ask(M.UpdateDatabase, M.DBImportUpdateDatabaseQuestion); } private ConnectionDispatch createConnection(DbImportPage.ImportConfig config) throws Exception { ConnectionDispatch connectionDispatch = new ConnectionDispatch(config); PlatformUI.getWorkbench().getProgressService() .busyCursorWhile(connectionDispatch); return connectionDispatch; } @Override public void addPages() { page = new DbImportPage(); addPage(page); } private class ImportDispatch implements IRunnableWithProgress { private IDatabase sourceDb; private VersionState sourceState; private ConnectionDispatch connectionDispatch; ImportDispatch(ConnectionDispatch connectionDispatch) { this.sourceDb = connectionDispatch.getSource(); this.sourceState = connectionDispatch.getSourceState(); this.connectionDispatch = connectionDispatch; } @Override public void run(IProgressMonitor monitor) throws InvocationTargetException, OperationCanceledException { try { Database.getIndexUpdater().beginTransaction(); monitor.beginTask(M.ImportDatabase, IProgressMonitor.UNKNOWN); checkAndExecuteUpdates(monitor); monitor.subTask(M.ImportData + "..."); DatabaseImport dbImport = new DatabaseImport(sourceDb, Database.get()); log.trace("run data import"); dbImport.run(); monitor.subTask(M.CloseDatabase); connectionDispatch.close(); monitor.done(); } catch (Exception e) { throw new InvocationTargetException(e); } finally { Database.getIndexUpdater().endTransaction(); } } private void checkAndExecuteUpdates(IProgressMonitor monitor) throws Exception { switch (sourceState) { case NEEDS_UPGRADE: monitor.subTask(M.UpdateDatabase); Upgrades.runUpgrades(sourceDb); case NEEDS_UPDATE: monitor.subTask(M.UpdateDatabase); UpdateHelper updates = new UpdateHelper(sourceDb, App.getCalculationContext(), Python.getDir()); for (UpdateMetaInfo update : updates.getNewAndRequired()) { execute(update, updates); } default: } } private void execute(UpdateMetaInfo metaInfo, UpdateHelper updates) { for (String depRefId : metaInfo.dependencies) { Update dep = updates.getForRefId(depRefId); execute(dep.metaInfo, updates); } Update update = updates.getForRefId(metaInfo.refId); updates.execute(update); } } /** * Creates the initial resources and opens a database connection to the * source database of the import. */ private class ConnectionDispatch implements IRunnableWithProgress { private DbImportPage.ImportConfig config; private File tempDbFolder; private IDatabase source; ConnectionDispatch(DbImportPage.ImportConfig config) { this.config = config; } public IDatabase getSource() { return source; } public VersionState getSourceState() { return VersionState.checkVersion(source); } @Override public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { log.trace("connect to source database"); try { if (config.mode == config.FILE_MODE) source = connectToFolder(); else source = config.databaseConfiguration.createInstance(); } catch (Exception e) { log.error("Failed to connect to source database", e); throw new InvocationTargetException(e); } } private IDatabase connectToFolder() { File zipFile = config.file; File tempDir = new File(System.getProperty("java.io.tmpdir")); tempDbFolder = new File(tempDir, UUID.randomUUID().toString()); tempDbFolder.mkdirs(); log.trace("unpack zolca file to {}", tempDbFolder); ZipUtil.unpack(zipFile, tempDbFolder); return new DerbyDatabase(tempDbFolder); } void close() throws Exception { log.trace("close source database"); source.close(); if (tempDbFolder != null) { log.trace("delete temporary db-folder {}", tempDbFolder); FileUtils.deleteDirectory(tempDbFolder); } } } }