/*
* Copyright 2011-2017 Amazon Technologies, Inc.
*
* 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://aws.amazon.com/apache2.0
*
* This file 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.amazonaws.eclipse.codecommit.credentials;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.jface.preference.IPreferenceStore;
import com.amazonaws.eclipse.codecommit.CodeCommitPlugin;
import com.amazonaws.eclipse.codecommit.preferences.PreferenceConstants;
import com.amazonaws.eclipse.core.AccountInfo;
import com.amazonaws.eclipse.core.AwsToolkitCore;
import com.amazonaws.eclipse.core.accounts.AccountInfoChangeListener;
import com.amazonaws.util.StringUtils;
/**
* Git credentials manager that manages Git credentials in between memory and disk.
*/
public class GitCredentialsManager {
private static final Map<String, GitCredential> GIT_CREDENTIALS = new HashMap<String, GitCredential>();
public static void init() {
AwsToolkitCore.getDefault().getAccountManager().addAccountInfoChangeListener(
AccountInfoChangeListenerForGitCredentials.INSTANCE);
loadGitCredentials();
mergeAwsProfiles();
}
/**
* Load Git credentials from the Git credentials file and do a merge to the current credentials.
*/
public static void loadGitCredentials() {
File gitCredentialsFile = getGitCredentialsFile();
if (gitCredentialsFile.exists() && gitCredentialsFile.isFile()) {
BufferedReader bufferedReader = null;
try {
bufferedReader = new BufferedReader(new FileReader(gitCredentialsFile));
String line;
int lineNumber = 0;
while ((line = bufferedReader.readLine()) != null) {
++lineNumber;
List<String> tokens = splitStringByComma(line);
if (tokens.size() != 3) {
CodeCommitPlugin.getDefault().logWarning("Invalid csv file: " + gitCredentialsFile.getAbsolutePath(),
new ParseException("The csv file must have three columns!", lineNumber));
} else {
GIT_CREDENTIALS.put(tokens.get(0).trim(), new GitCredential(tokens.get(1).trim(), tokens.get(2).trim()));
}
}
} catch (Exception e) {
AwsToolkitCore.getDefault().reportException("Failed to load gitCredentials file for git credentials!", e);
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
}
}
}
}
}
/**
* Merge AWS account profiles to Git credentials manager.
*/
private static void mergeAwsProfiles() {
Map<String, AccountInfo> accounts = AwsToolkitCore.getDefault().getAccountManager().getAllAccountInfo();
for (Entry<String, AccountInfo> entry : accounts.entrySet()) {
String accountName = entry.getValue().getAccountName();
if (GIT_CREDENTIALS.containsKey(accountName)) continue;
GIT_CREDENTIALS.put(accountName, new GitCredential("", ""));
}
}
public static Map<String, GitCredential> getGitCredentials() {
return GIT_CREDENTIALS;
}
public static GitCredential getGitCredential(String profile) {
return GIT_CREDENTIALS.get(profile);
}
private static File getGitCredentialsFile() {
IPreferenceStore store = CodeCommitPlugin.getDefault().getPreferenceStore();
String filePath = store.getString(PreferenceConstants.GIT_CREDENTIALS_FILE_PREFERENCE_NAME);
return new File(StringUtils.isNullOrEmpty(filePath) ? PreferenceConstants.DEFAULT_GIT_CREDENTIALS_FILE : filePath);
}
public static void saveGitCredentials() {
File gitCredentialsFile = getGitCredentialsFile();
if (!gitCredentialsFile.exists()) {
try {
gitCredentialsFile.createNewFile();
} catch (IOException e) {
AwsToolkitCore.getDefault().reportException("Failed to create gitCredentials file!", e);
}
}
PrintWriter writer = null;
try {
writer = new PrintWriter(new FileWriter(gitCredentialsFile));
for (Entry<String, GitCredential> entry : GIT_CREDENTIALS.entrySet()) {
writer.println(String.format("%s,%s,%s",entry.getKey(), entry.getValue().getUsername(), entry.getValue().getPassword()));
}
writer.flush();
} catch (Exception e) {
AwsToolkitCore.getDefault().logWarning("Failed to write git credential to file!", e);
} finally {
if (writer != null) {
writer.close();
}
}
}
/**
* Listens profile updating event to keep sync up with the Git credentials manager.
*/
private static class AccountInfoChangeListenerForGitCredentials implements AccountInfoChangeListener {
public static AccountInfoChangeListenerForGitCredentials INSTANCE = new AccountInfoChangeListenerForGitCredentials();
private AccountInfoChangeListenerForGitCredentials() {}
public void onAccountInfoChange() {
mergeAwsProfiles();
}
}
/**
* The String.split method incorrectly parses "profile,," to {"profile"} instead of {"profile", "", ""}.
* This helper method correctly parses cvs lines.
*/
private static List<String> splitStringByComma(String str) {
List<String> tokens = new ArrayList<String>();
int fromIndex = 0, endIndex = 0;
while ((endIndex = str.indexOf(',', fromIndex)) > 0) {
tokens.add(str.substring(fromIndex, endIndex));
fromIndex = endIndex + 1;
}
tokens.add(str.substring(fromIndex));
return tokens;
}
}