blob: 1d8bae6f9a47ccd3b41675613eba3e6087ff10ee [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.core;
import java.io.File;
import java.io.IOException;
import java.security.KeyStore;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.motorola.studio.android.common.log.StudioLogger;
import com.motorolamobility.studio.android.certmanager.exception.InvalidPasswordException;
import com.motorolamobility.studio.android.certmanager.exception.KeyStoreManagerException;
import com.motorolamobility.studio.android.certmanager.ui.model.IKeyStore;
import com.motorolamobility.studio.android.certmanager.ui.model.KeyStoreNode;
import com.motorolamobility.studio.android.certmanager.ui.model.KeyStoreRootNode;
import com.motorolamobility.studio.android.certmanager.views.KeystoreManagerView;
/**
* Provides a common interface to manipulate keystores.
* Other plugins need to use it (to avoid knowing {@link KeyStoreRootNode} model and {@link SaveStateManager}).
*
* The {@link KeystoreManagerView} also need to call its methods to guarantee persistence of its operations.
*/
public class KeyStoreManager
{
public static final String KEYSTORE_TYPE_PKCS12 = "PKCS12";
public static final String KEYSTORE_TYPE_JCEKS = "JCEKS";
public static final String KEYSTORE_TYPE_JKS = "JKS";
private static final String ERROR_TO_ACCESS_KEYSTORE_MAPPING_PERSISTENCE =
"Error to access keystore mapping persistence";
private static KeyStoreManager _instance;
private List<IKeyStore> keyStores = null;
/**
* This class is a singleton.
* @return The unique instance of this class.
* */
public synchronized static KeyStoreManager getInstance()
{
if (_instance == null)
{
_instance = new KeyStoreManager();
}
return _instance;
}
private KeyStoreManager()
{
}
/**
* Add a new keystore to the manager.
* @param keystore The keystore to be added.
* @throws KeyStoreManagerException if an error occurs while accessing persistence file where keystores are mapped.
*/
public void addKeyStore(IKeyStore keystore) throws KeyStoreManagerException
{
SaveStateManager manager = null;
try
{
manager = SaveStateManager.getInstance();
manager.addEntry(keystore.getFile(), keystore.getType());
getKeyStores().add(keystore);
}
catch (Exception e)
{
throw new KeyStoreManagerException(ERROR_TO_ACCESS_KEYSTORE_MAPPING_PERSISTENCE, e);
}
}
/**
* Remove a keystore from the manager.
* @param keystore The keystore to be removed.
* @throws KeyStoreManagerException if an error occurs while accessing persistence file where keystores are mapped.
*/
public void removeKeyStore(IKeyStore keystore) throws KeyStoreManagerException
{
SaveStateManager manager = null;
try
{
manager = SaveStateManager.getInstance();
manager.removeEntry(keystore.getFile());
getKeyStores().remove(keystore);
}
catch (Exception e)
{
throw new KeyStoreManagerException(ERROR_TO_ACCESS_KEYSTORE_MAPPING_PERSISTENCE, e);
}
}
/**
* Set the date which the keystore was added to a backup file.
* @param keyStore The keystore to be set.
* @param backupDate The date of the backup.
* @throws KeyStoreManagerException If there were problems while persisting the information.
* */
public void setBackupDate(IKeyStore keyStore, Date backupDate) throws KeyStoreManagerException
{
if ((keyStore != null) && (backupDate != null))
{
try
{
SaveStateManager manager = SaveStateManager.getInstance();
manager.setBackupDate(keyStore.getFile(), backupDate);
}
catch (Exception e)
{
throw new KeyStoreManagerException(ERROR_TO_ACCESS_KEYSTORE_MAPPING_PERSISTENCE, e);
}
}
}
/**
* Update the type of a managed keystore, using solely the information provided by the keystore.
* @param keystore The keystore which type needs to be updated.
* @throws KeyStoreManagerException If there were problems while persisting the information.
* */
public void updateKeyStoreType(IKeyStore keyStore) throws KeyStoreManagerException
{
SaveStateManager manager;
try
{
manager = SaveStateManager.getInstance();
if (manager.isKeystoreMapped(keyStore.getFile()))
{
manager.addEntry(keyStore.getFile(), keyStore.getType());
}
}
catch (IOException e)
{
throw new KeyStoreManagerException(ERROR_TO_ACCESS_KEYSTORE_MAPPING_PERSISTENCE, e);
}
}
/**
* @return The list of mapped keystores in the persistence, or empty list if there is no keystore mapped.
* @throws KeyStoreManagerException if an error occurs to access persistence file where keystores are mapped.
*/
public List<IKeyStore> getKeyStores() throws KeyStoreManagerException
{
if (keyStores == null)
{
keyStores = new ArrayList<IKeyStore>();
SaveStateManager manager = null;
try
{
manager = SaveStateManager.getInstance();
if (manager.getMappedKeystores() != null)
{
for (File keystoreFile : manager.getMappedKeystores())
{
SaveStateManager.ViewStateEntry stateEntry = manager.getEntry(keystoreFile);
if (stateEntry != null)
{
IKeyStore keyStoreNode = new KeyStoreNode(keystoreFile);
keyStoreNode.setType(stateEntry.getKeystoreType());
keyStoreNode.setLastBackupDate(stateEntry.getBackupDate());
keyStores.add(keyStoreNode);
}
}
}
}
catch (IOException e)
{
throw new KeyStoreManagerException(ERROR_TO_ACCESS_KEYSTORE_MAPPING_PERSISTENCE, e);
}
}
return keyStores;
}
/**
* Check if a keystore file is already mapped.
* The input parameter is a File, instead of a String, to ensure that File.getCanonicalPath() will be used in the filenames comparison.
* @param keystoreFile A file representing the keystore.
* @return True if the file is already mapped, false otherwise.
* */
public boolean isKeystoreMapped(File keystoreFile)
{
boolean result = false;
SaveStateManager manager = null;
try
{
manager = SaveStateManager.getInstance();
if (manager.getMappedKeystores() != null)
{
for (File mappedKeystoreFile : manager.getMappedKeystores())
{
if (mappedKeystoreFile.getCanonicalPath().equals(
keystoreFile.getCanonicalPath()))
{
result = true;
break;
}
}
}
}
catch (IOException e)
{
result = false;
StudioLogger
.error(getClass(),
"IOException while trying to check if a file is mapped on Signing and Keys view.");
}
return result;
}
/**
* The current available keystore types are:
* <ul>
* <li>JKS</li>
* <li>JCEKS</li>
* <li>PKCS12</li>
* </ul>
* @return The list of available keystore types.
* */
public List<String> getAvailableTypes()
{
List<String> availableKeystoreTypes = new ArrayList<String>();
availableKeystoreTypes.add(KEYSTORE_TYPE_JKS);
availableKeystoreTypes.add(KEYSTORE_TYPE_JCEKS);
availableKeystoreTypes.add(KEYSTORE_TYPE_PKCS12);
if (!availableKeystoreTypes.contains(getDefaultType()))
{
availableKeystoreTypes.add(getDefaultType());
}
return availableKeystoreTypes;
}
/**
* When no store type is specified, the manager define a type that should be used as the default one.
* @return The default keystore type used in the Signing and Keys view.
* */
public String getDefaultType()
{
return KeyStore.getDefaultType().toUpperCase();
}
/**
* Create a new keystore given a file, a store type and a password.
*/
public static IKeyStore createKeyStore(File keyStoreFile, String keyStoreType, char[] password)
throws KeyStoreManagerException
{
IKeyStore keyStoreNode = null;
try
{
KeyStore keyStore = KeyStoreUtils.createKeystore(keyStoreFile, keyStoreType, password);
keyStoreNode = new KeyStoreNode(keyStoreFile, keyStore);
}
catch (InvalidPasswordException e)
{
StudioLogger.error("Invalid password when creating a keystore: " + e.getMessage());
}
return keyStoreNode;
}
/**
* Create a new keystore given a file and a password.
* The store type is set to be the default.
*/
public static IKeyStore createKeyStore(File keyStoreFile, char[] password)
throws KeyStoreManagerException
{
IKeyStore keyStoreNode = null;
try
{
KeyStore keyStore = KeyStoreUtils.createKeystore(keyStoreFile, password);
keyStoreNode = new KeyStoreNode(keyStoreFile, keyStore);
}
catch (InvalidPasswordException e)
{
StudioLogger.error("Invalid password when creating a keystore: " + e.getMessage());
}
return keyStoreNode;
}
}