blob: f482d4c501b80c82021591ff0972d4a1c983aa6c [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.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
import com.motorola.studio.android.common.log.StudioLogger;
import com.motorolamobility.studio.android.certmanager.CertificateManagerActivator;
import com.motorolamobility.studio.android.certmanager.views.KeystoreManagerView;
/**
* Saves the state of the {@link KeystoreManagerView} with:
* - the keystores mapped
* - the last backup date from a keystore
*/
class SaveStateManager
{
private static final String FILE_COMMENT = "-- Signing and keys view persistence --";
private static final String STATE_FILENAME = "state.properties";
private final File persistenceFile = new File(System.getProperty("user.home") + File.separator
+ "." + CertificateManagerActivator.PLUGIN_ID, STATE_FILENAME);
private static final String KEYSTORE_TYPE = "keystore_type=";
private static final String BACKUP_DATE = "backup_date=";
protected class ViewStateEntry
{
private final File keystoreFile;
private String keystoreType;
private Date backupDate;
public ViewStateEntry(File keystoreFile)
{
this.keystoreFile = keystoreFile;
}
public ViewStateEntry(File keystoreFile, String keystoreType)
{
this.keystoreFile = keystoreFile;
this.keystoreType = keystoreType;
}
/**
* @return the backupDate
*/
public Date getBackupDate()
{
return backupDate;
}
/**
* @param backupDate the backupDate to set
*/
public void setBackupDate(Date backupDate)
{
this.backupDate = backupDate;
}
/**
* @return the keystoreType
*/
public String getKeystoreType()
{
return keystoreType;
}
/**
* @param keystoreType the keystoreType to set
*/
public void setKeystoreType(String keystoreType)
{
this.keystoreType = keystoreType;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
return "ViewStateEntry [keystoreFile=" + keystoreFile + ", keystoreType="
+ keystoreType + ", backupDate=" + backupDate + "]";
}
/**
* @return the keystoreFile
*/
protected File getKeystoreFile()
{
return keystoreFile;
}
}
private static SaveStateManager _instance;
/**
* This class is a singleton.
* @return The unique instance of this class.
* */
public synchronized static SaveStateManager getInstance() throws IOException
{
if (_instance == null)
{
_instance = new SaveStateManager();
}
return _instance;
}
private SaveStateManager() throws IOException
{
//create folder if it does not exist
if (!persistenceFile.getParentFile().exists())
{
persistenceFile.getParentFile().mkdirs();
}
if (!persistenceFile.exists())
{
//init file
persistenceFile.createNewFile();
store(new Properties());
}
}
private String write(ViewStateEntry entry)
{
StringBuffer buffer = new StringBuffer();
if (entry.getKeystoreType() != null)
{
buffer.append(KEYSTORE_TYPE + entry.getKeystoreType() + File.pathSeparator);
}
if (entry.getBackupDate() != null)
{
buffer.append(BACKUP_DATE + entry.getBackupDate().getTime());
}
return buffer.toString();
}
/**
* List all mapped keystores.
* @throws IOException If there are problems loading the persistence file.
*/
public Set<File> getMappedKeystores() throws IOException
{
Set<File> mappedKeystores = new HashSet<File>();
Properties properties = load();
Enumeration<Object> enumeration = properties.keys();
while (enumeration.hasMoreElements())
{
Object k = enumeration.nextElement();
if (k instanceof String)
{
String key = (String) k;
File keystoreFile = new File(key);
mappedKeystores.add(keystoreFile);
}
}
return mappedKeystores;
}
/**
* Get a representation of the entry saved in the persistence.
* @param keystoreFile The file that will have its state retrieved.
* @return
* @throws IOException If there are problems loading the persistence file.
*/
public ViewStateEntry getEntry(File keystoreFile) throws IOException
{
Properties properties = load();
Object v = properties.get(keystoreFile.getAbsolutePath());
ViewStateEntry entry = null;
if (v instanceof String)
{
String value = (String) v;
StringTokenizer stringTokenizer = new StringTokenizer(value, File.pathSeparator);
entry = new ViewStateEntry(keystoreFile);
while (stringTokenizer.hasMoreTokens())
{
String token = stringTokenizer.nextToken();
if (token.contains(KEYSTORE_TYPE))
{
token = token.substring(KEYSTORE_TYPE.length());
entry.setKeystoreType(token);
}
else if (token.contains(BACKUP_DATE))
{
token = token.substring(BACKUP_DATE.length());
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(Long.parseLong(token));
Date date = calendar.getTime();
entry.setBackupDate(date);
}
}
}
return entry;
}
/**
* Check if a keystore is mapped on the persistence mechanism.
* @param keystoreFile The keystore to be checked.
* @return true if keystore mapped, false otherwise
* @throws IOException If there are problems loading the persistence file.
*/
public boolean isKeystoreMapped(File keystoreFile) throws IOException
{
Properties properties = load();
return properties.containsKey(keystoreFile.getAbsolutePath());
}
/**
* Adds (maps) a keystore.
* @param keystoreFile The keystore to be added to the persistence mechanism.
* @param keystoreType The type of the keystore.
* @throws IOException If there are problems loading the persistence file.
*/
public void addEntry(File keystoreFile, String keystoreType) throws IOException
{
ViewStateEntry stateEntry = new ViewStateEntry(keystoreFile, keystoreType);
addEntry(keystoreFile, stateEntry);
}
private void addEntry(File keystoreFile, ViewStateEntry stateEntry) throws IOException
{
Properties prop = load();
prop.setProperty(keystoreFile.getAbsolutePath(), write(stateEntry));
store(prop);
}
/**
* Removes a keystore from the persistence mechanism.
* @param keystoreFile
* @throws IOException
*/
public void removeEntry(File keystoreFile) throws IOException
{
Properties properties = load();
properties.remove(keystoreFile.getAbsolutePath());
store(properties);
}
/**
* Sets backup date from a keystore
* @param keystoreFile The keystore file.
* @param backupDate The date of the backup.
* @throws IOException If there are problems loading the persistence file.
*/
public void setBackupDate(File keystoreFile, Date backupDate) throws IOException
{
ViewStateEntry entry = getEntry(keystoreFile);
entry.setBackupDate(backupDate);
addEntry(keystoreFile, entry);
}
private Properties load() throws IOException
{
FileInputStream in = null;
Properties props = new Properties();
try
{
in = new FileInputStream(persistenceFile);
props.loadFromXML(in);
}
finally
{
if (in != null)
{
in.close();
}
}
return props;
}
private void store(Properties prop) throws IOException
{
FileOutputStream out = null;
try
{
out = new FileOutputStream(persistenceFile);
prop.storeToXML(out, FILE_COMMENT);
}
finally
{
if (out != null)
{
try
{
out.close();
}
catch (IOException e)
{
StudioLogger.error("Could not close stream while saving properties. "
+ e.getMessage());
}
}
}
}
}