blob: 33ada4525a1f1bf32c4eff5e9387b6a4bfa43631 [file] [log] [blame]
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.motorolamobility.studio.android.certmanager.command;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.KeyStore;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.osgi.util.NLS;
import org.eclipse.ui.PlatformUI;
import com.motorola.studio.android.common.log.StudioLogger;
import com.motorola.studio.android.common.utilities.EclipseUtils;
import com.motorola.studio.android.common.utilities.FileUtil;
import com.motorolamobility.studio.android.certmanager.CertificateManagerActivator;
import com.motorolamobility.studio.android.certmanager.core.KeyStoreManager;
import com.motorolamobility.studio.android.certmanager.event.KeyStoreModelEvent.EventType;
import com.motorolamobility.studio.android.certmanager.event.KeyStoreModelEventManager;
import com.motorolamobility.studio.android.certmanager.exception.KeyStoreManagerException;
import com.motorolamobility.studio.android.certmanager.i18n.CertificateManagerNLS;
import com.motorolamobility.studio.android.certmanager.ui.dialogs.RestoreBackupDialog;
import com.motorolamobility.studio.android.certmanager.ui.model.IKeyStore;
import com.motorolamobility.studio.android.certmanager.ui.model.ITreeNode;
import com.motorolamobility.studio.android.certmanager.ui.model.KeyStoreNode;
import com.motorolamobility.studio.android.certmanager.ui.model.SigningAndKeysModelManager;
/**
* Handler to execute the restore backup wizard.
* */
public class RestoreBackupHandler extends AbstractHandler implements IHandler
{
Date lastBackupDate = new Date();
@Override
public Object execute(ExecutionEvent event) throws ExecutionException
{
RestoreBackupDialog dialog =
new RestoreBackupDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow()
.getShell());
int diagReturn = dialog.open();
if (diagReturn == Dialog.OK)
{
File archiveFile = dialog.getArchiveFile();
File destinationFile = dialog.getDestinationDir();
List<String> selectedKeyStores = dialog.getSelectedKeyStores();
restoreBackup(archiveFile, destinationFile, selectedKeyStores);
}
return null;
}
private void restoreBackup(File archiveFile, File destinationFile,
List<String> selectedKeyStores)
{
boolean extractionSuccess = false;
File typePropertiesFile = new File(destinationFile, BackupHandler.KS_TYPES_FILENAME); //$NON-NLS-1$
try
{
extractionSuccess =
FileUtil.extractZipArchive(archiveFile, destinationFile,
Arrays.asList(new String[]
{
BackupHandler.KS_TYPES_FILENAME
}), new NullProgressMonitor());
extractionSuccess =
FileUtil.extractZipArchive(archiveFile, destinationFile, selectedKeyStores,
new NullProgressMonitor());
}
catch (IOException e)
{
//roll back: delete files, if they were created
rollBackDeleteExtractedFiles(destinationFile, selectedKeyStores);
EclipseUtils
.showErrorDialog(
CertificateManagerNLS.RestoreBackupHandler_Error_Restoring_Backup_Title,
NLS.bind(
CertificateManagerNLS.RestoreBackupHandler_Error_Restoring_Backup_Message,
archiveFile),
new Status(
IStatus.ERROR,
CertificateManagerNLS.RestoreBackupHandler_Error_Restoring_Backup_Status,
CertificateManagerActivator.PLUGIN_ID, e));
}
if (extractionSuccess)
{
Properties properties = null;
if ((typePropertiesFile != null) && !typePropertiesFile.exists())
{
showWarningAboutNonIdentifiedKeystoreType(selectedKeyStores);
}
properties = loadTypeProperties(typePropertiesFile, properties);
//recover last backup date
getDateFromProperties(properties);
List<String> nonIdentifiedKeystoreTypes = new ArrayList<String>();
for (String keyStoreFileName : selectedKeyStores)
{
File keyStoreFile = new File(destinationFile, keyStoreFileName);
String ksType = null;
if (properties != null)
{
ksType = (String) properties.get(keyStoreFileName);
if (ksType == null)
{
//type not found at metadata
nonIdentifiedKeystoreTypes.add(keyStoreFileName);
}
}
if (ksType == null)
{
ksType = KeyStoreManager.getInstance().getDefaultType(); // set the keystore type to be the default type
}
KeyStoreNode keyStoreNode = new KeyStoreNode(keyStoreFile, ksType);
keyStoreNode.setLastBackupDate(lastBackupDate);
boolean map = true;
try
{
List<IKeyStore> keyStores = KeyStoreManager.getInstance().getKeyStores();
for (IKeyStore keyStore : keyStores)
{
if (keyStore.getFile().equals(keyStoreFile))
{
//updates keystore type if necessary
if ((ksType != null)
&& (ksType.compareToIgnoreCase(keyStore.getType()) != 0))
{
keyStore.setType(ksType);
}
KeyStoreModelEventManager.getInstance().fireEvent((ITreeNode) keyStore,
EventType.COLLAPSE);
map = false;
keyStore.setLastBackupDate(lastBackupDate);
}
}
if (map)
{
SigningAndKeysModelManager.getInstance().mapKeyStore(keyStoreNode);
}
}
catch (KeyStoreManagerException e)
{
EclipseUtils
.showErrorDialog(
CertificateManagerNLS.RestoreBackupHandler_Error_Mapping_Title,
CertificateManagerNLS.RestoreBackupHandler_Error_Mapping_Message,
new Status(
IStatus.ERROR,
CertificateManagerNLS.RestoreBackupHandler_Error_Mapping_Status,
CertificateManagerActivator.PLUGIN_ID, e));
if (map)
{
//roll back operation - undo mapping if keystore was mapped during backup
SigningAndKeysModelManager.getInstance().unmapKeyStore(keyStoreNode);
}
}
}
if ((nonIdentifiedKeystoreTypes != null) && !nonIdentifiedKeystoreTypes.isEmpty())
{
showWarningAboutNonIdentifiedKeystoreType(nonIdentifiedKeystoreTypes);
}
}
else
{
//roll back: delete files, if they were created
rollBackDeleteExtractedFiles(destinationFile, selectedKeyStores);
EclipseUtils
.showErrorDialog(
CertificateManagerNLS.RestoreBackupHandler_Error_Restoring_Backup_Title,
NLS.bind(
CertificateManagerNLS.RestoreBackupHandler_Error_Restoring_Backup_Message,
archiveFile));
}
}
private void rollBackDeleteExtractedFiles(File destinationFile, List<String> selectedKeyStores)
{
//roll back: delete files, if they were created
File ksTypeDest = new File(destinationFile, BackupHandler.KS_TYPES_FILENAME);
if (ksTypeDest.exists())
{
//roll back: delete Kstypes
ksTypeDest.delete();
}
for (String keyStoreFileName : selectedKeyStores)
{
//roll back: delete extract files
File keyStoreFile = new File(destinationFile, keyStoreFileName);
if (keyStoreFile.exists())
{
keyStoreFile.delete();
}
}
}
private void getDateFromProperties(Properties properties)
{
if (properties != null)
{
//KsTypes.csv available
String lastString = properties.getProperty("lastBackupDate");
Long time = new Long(lastString);
lastBackupDate.setTime(time);
}
else
{
//KsTypes.csv not available
StudioLogger.debug("KsTypes.csv not available to get lastBackupDate properties");
}
}
/**
* Shows warning stating that some keystores will use default keystore type.
* @param selectedKeyStores
*/
private void showWarningAboutNonIdentifiedKeystoreType(List<String> selectedKeyStores)
{
EclipseUtils
.showWarningDialog(
CertificateManagerNLS.RestoreBackupHandler_RestoreIssue_WarningTitle,
CertificateManagerNLS
.bind(CertificateManagerNLS.RestoreBackupHandler_RestoreIssue_MissingMetadataFile_WarningDescription,
selectedKeyStores, KeyStore.getDefaultType()));
}
private Properties loadTypeProperties(File typePropertiesFile, Properties properties)
{
if ((typePropertiesFile != null) && typePropertiesFile.exists())
{
FileInputStream propInStream = null;
properties = new Properties();
try
{
propInStream = new FileInputStream(typePropertiesFile);
properties.load(propInStream);
typePropertiesFile.delete();
}
catch (FileNotFoundException e)
{
properties = null;
}
catch (IOException e)
{
properties = null;
}
finally
{
if (propInStream != null)
{
try
{
propInStream.close();
}
catch (IOException e)
{
StudioLogger.error("Could not close steam while loading type properties. "
+ e.getMessage());
}
typePropertiesFile.delete();
}
}
}
return properties;
}
}