org.cesecore.certificates.certificatetransparency.CtLogManager Maven / Gradle / Ivy
/*************************************************************************
* *
* CESeCore: CE Security Core *
* *
* This software is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or any later version. *
* *
* See terms of license at gnu.org. *
* *
*************************************************************************/
package org.cesecore.certificates.certificatetransparency;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import org.apache.commons.lang.StringUtils;
/**
* This class is responsible for managing a list of CT logs. The CT logs backed by
* this class can be grouped or reordered and there is functionality for adding
* new CT logs or removing existing ones. This class does not load or store changes
* in a persistent storage, and relies on its creator to load the CT logs from e.g.
* a database or a file.
* @version $Id: CtLogManager.java 28511 2018-03-18 21:24:03Z bastianf $
*/
public class CtLogManager {
private final List ctLogs;
/**
* Create a new CT log manager responsible for a list of logs specified.
* @param ctLogs the logs managed by this CT log manager
*/
public CtLogManager(final List ctLogs) {
this.ctLogs = ctLogs;
}
/**
* Group the CT logs managed by this CT log manager by label. Returns a map
* which maps a label to a list of all CT logs which has this label.
* @return a mapping between labels and CT logs with this label
*/
public LinkedHashMap> getCtLogGroups() {
final LinkedHashMap> logLogMap = new LinkedHashMap<>();
for (final CTLogInfo ctLog : ctLogs) {
if (!logLogMap.containsKey(ctLog.getLabel())) {
logLogMap.put(ctLog.getLabel(), new ArrayList());
}
logLogMap.get(ctLog.getLabel()).add(ctLog);
}
return logLogMap;
}
/**
* Returns all unique labels for the CT logs managed by this CT log manager.
* @return a list of all unique labels
*/
public List getLabels() {
List ret = new ArrayList(getCtLogGroups().keySet());
Collections.sort(ret, new Comparator() {
@Override
public int compare(String label1, String label2) {
return label1.compareToIgnoreCase(label2);
}
});
return ret;
}
/**
* Returns a list of all logs managed by this CT log manager. This list can be
* persisted to a database and used to initialise an identical log manager.
* @return a list of all CT logs
*/
public List getAllCtLogs() {
return ctLogs;
}
/**
* Get a list of CT logs labelled as specified. If no logs have the label specified,
* an empty list will be returned.
* @param label the label of the CT logs to retrieve
* @return a list of CT logs matching the given label, never null
*/
public List getCtLogsByLabel(final String label) {
final List ctLogGroup = getCtLogGroups().get(label);
if (ctLogGroup == null) {
return new ArrayList();
}
return ctLogGroup;
}
/**
* Moves the specified CT log up one step. This method does nothing if the CT log is already
* on top or if the CT log group to which the CT log belongs only contains one log.
* @throws IllegalArgumentException if the CT log given as argument is not managed by this CT log manager
*/
public void moveUp(final CTLogInfo ctLog) {
final List ctLogGroup = getCtLogsByLabel(ctLog.getLabel());
if (!ctLogGroup.contains(ctLog)) {
throw new IllegalArgumentException("The CT log " + ctLog.toString() + " is not managed by this CT log manager.");
}
if (ctLogGroup.size() == 1 || isOnTop(ctLog)) {
return;
}
final CTLogInfo previousCtLog = ctLogGroup.get(ctLogGroup.indexOf(ctLog) - 1);
Collections.swap(ctLogs, ctLogs.indexOf(ctLog), ctLogs.indexOf(previousCtLog));
}
/**
* Moves the specified CT log down one step. This method does nothing if the CT log is already
* on the bottom or if the CT log group to which the CT log belongs only contains one log.
* @throws IllegalArgumentException if the CT log given as argument is not managed by this CT log manager
*/
public void moveDown(final CTLogInfo ctLog) {
final List ctLogGroup = getCtLogsByLabel(ctLog.getLabel());
if (!ctLogGroup.contains(ctLog)) {
throw new IllegalArgumentException("The CT log " + ctLog.toString() + " is not managed by this CT log manager.");
}
if (ctLogGroup.size() == 1 || isOnBottom(ctLog)) {
return;
}
final CTLogInfo nextCtLog = ctLogGroup.get(ctLogGroup.indexOf(ctLog) + 1);
Collections.swap(ctLogs, ctLogs.indexOf(ctLog), ctLogs.indexOf(nextCtLog));
}
/**
* Add a new CT log to this CT log manager. This method will prevent duplicate logs from being added.
* @param ctLog the CT log to add
* @throws DuplicateCtLogException if the CT log to add is a duplicate according to {@link #canAdd(CTLogInfo)}
*/
public void addCtLog(final CTLogInfo ctLog) {
if (!canAdd(ctLog)) {
throw new DuplicateCtLogException("The CT log " + ctLog.toString() + " already exists in the log group '" + ctLog.getLabel() + "'.");
}
ctLogs.add(ctLog);
}
/**
* Removes an existing CT log from this log manager.
* @param ctLog the CT log to remove
* @throws IllegalArgumentException if the CT log is not managed by this CT log manager
*/
public void removeCtLog(final CTLogInfo ctLog) {
if (!ctLogs.contains(ctLog)) {
throw new IllegalArgumentException("The CT log " + ctLog.toString() + " is not managed by this CT log manager.");
}
ctLogs.remove(ctLog);
}
/**
* Determine whether the CT log given as input can be added to this CT log manager. A CT log cannot be added
* if any of the following conditions hold for another CT log:
*
* - The other log has an ID identical to the new CT log
* - The other log is has an identical URL and label as the new CT log
*
* @param the new CT log to check
* @return true if the CT log given as input can be added, false otherwise
*/
public boolean canAdd(final CTLogInfo ctLog) {
for (CTLogInfo existing : ctLogs) {
final boolean hasSameId = existing.getLogId() == ctLog.getLogId();
final boolean urlExistsInCtLogGroup = StringUtils.equals(existing.getUrl(), ctLog.getUrl())
&& StringUtils.equals(existing.getLabel(), ctLog.getLabel());
if (hasSameId || urlExistsInCtLogGroup) {
return false;
}
}
return true;
}
/**
* Determine whether the CT log given as input is on the top in its CT log group.
* @param ctLog the CT log to check
* @return true iff the CT log is on the top in its CT log group
*/
public boolean isOnTop(final CTLogInfo ctLog) {
final List ctLogGroup = getCtLogsByLabel(ctLog.getLabel());
return !ctLogGroup.isEmpty() && ctLogGroup.get(0).equals(ctLog);
}
/**
* Determine whether the CT log given as input is on the bottom in its CT log group.
* @param ctLog the CT log to check
* @return true iff the CT log is on the bottom in its CT log group
*/
public boolean isOnBottom(final CTLogInfo ctLog) {
final List ctLogGroup = getCtLogsByLabel(ctLog.getLabel());
return !ctLogGroup.isEmpty() && ctLogGroup.get(ctLogGroup.size() - 1).equals(ctLog);
}
/**
* Rename a label. This will effectively set the label of CT logs to the
* new label for every CT log with the old label.
* @param oldLabel the label to change
* @param newLabel the new label to set
*/
public void renameLabel(final String oldLabel, final String newLabel) {
for (CTLogInfo ctLog : ctLogs) {
if (oldLabel.equals(ctLog.getLabel())) {
ctLog.setLabel(newLabel);
}
}
}
/**
* Returns the string representation of this object containing
* the CT logs currently managed by this CT log manager.
*/
@Override
public String toString() {
return "CT logs: " + getAllCtLogs().toString();
}
}