de.gematik.bbriccs.smartcards.SmartcardArchive Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2024 gematik GmbH
*
* 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 de.gematik.bbriccs.smartcards;
import static java.text.MessageFormat.format;
import de.gematik.bbriccs.crypto.BC;
import de.gematik.bbriccs.smartcards.cfg.SmartcardConfigDto;
import de.gematik.bbriccs.smartcards.exceptions.CardNotFoundException;
import de.gematik.bbriccs.smartcards.exceptions.InvalidSmartcardTypeException;
import de.gematik.bbriccs.utils.ResourceLoader;
import jakarta.annotation.Nullable;
import java.io.File;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
/**
* The SmartcardArchive is a factory for Smartcards, which is used to load, cache and manage
* Smartcards from a given directory.
*/
@Slf4j
public class SmartcardArchive {
private static final Map ARCHIVE_CACHE = new HashMap<>();
@Nullable private static SmartcardArchive defaultArchive = null;
static {
BC.init();
}
private final SmartcardFactory factory;
private final Map smcbCache;
private final Map hbaCache;
private final Map egkCache;
private SmartcardArchive(SmartcardFactory factory) {
this.factory = factory;
this.smcbCache = new HashMap<>();
this.hbaCache = new HashMap<>();
this.egkCache = new HashMap<>();
}
/**
* Initialize the {@link SmartcardArchive} from resources. For this method to work the {@link
* ResourceLoader} must be able to load the smartcards index file {@code
* resources/smartcards/smartcards.json}
*
* @return the SmartcardArchive initialized with the {@code smartcards.json} file from resources
*/
public static SmartcardArchive fromResources() {
if (defaultArchive == null) {
val factory = SmartcardFactory.fromResources();
defaultArchive = new SmartcardArchive(factory);
}
return defaultArchive;
}
/**
* Initialize the {@link SmartcardArchive} with a smartcards index file from a given path.
*
* @param path the path to the smartcards index file or the directory containing the {@code
* smartcards.json} file
* @return the SmartcardArchive initialized with the given smartcards index file
*/
public static SmartcardArchive from(String path) {
return from(Path.of(path).toFile());
}
/**
* Initialize the {@link SmartcardArchive} with a smartcards index file from a given path.
*
* @param archiveFile pointing to the smartcards.json file or the directory containing the
* smartcards.json file
* @return the {@link SmartcardArchive} initialized with the smartcards.json file from the given
* File
*/
public static SmartcardArchive from(File archiveFile) {
return ARCHIVE_CACHE.computeIfAbsent(
archiveFile,
file -> {
val factory = SmartcardFactory.fromFileSystem(file);
return new SmartcardArchive(factory);
});
}
/**
* Get all Smartcard configurations known to this {@link SmartcardArchive} from the smartcards
* index file.
*
* @return a list of all known Smartcard configurations
*/
public List getConfigs() {
return this.factory.getConfigs();
}
/**
* Get all Smartcard configurations known to this {@link SmartcardArchive} for a specific {@link
* SmartcardType}.
*
* @param type of Smartcards
* @return a list of all known Smartcard configurations for the given {@link SmartcardType}
*/
public List getConfigsFor(SmartcardType type) {
return this.factory.getConfigsFor(type);
}
/**
* Get all the ICCSNs of the Smartcards of a specific {@link SmartcardType} known to this {@link
* SmartcardArchive}
*
* @param type of Smartcards
* @return a list of all ICCSNs of the Smartcards of the given {@link SmartcardType}
*/
public List getICCSNsFor(SmartcardType type) {
return this.factory.getConfigsFor(type).stream().map(SmartcardConfigDto::getIccsn).toList();
}
/**
* Get a {@link Smartcard} with {@code classType} and identified by its ICCSN.
*
* @param classType of the Smartcard
* @param iccsn of the Smartcard
* @param the type of Smartcard
* @return the Smartcard identified by the given ICCSN
*/
public T getByICCSN(Class classType, String iccsn) {
if (SmcB.class.isAssignableFrom(classType)) {
return classType.cast(this.getSmcbByICCSN(iccsn));
} else if (Hba.class.isAssignableFrom(classType)) {
return classType.cast(this.getHbaByICCSN(iccsn));
} else if (Egk.class.isAssignableFrom(classType)) {
return classType.cast(this.getEgkByICCSN(iccsn));
} else if (InstituteSmartcard.class.isAssignableFrom(classType)) {
return classType.cast(
this.getByICCSN(iccsn).orElseThrow(() -> new CardNotFoundException(classType, iccsn)));
} else {
val smartcard =
this.getByICCSN(iccsn).orElseThrow(() -> new CardNotFoundException(classType, iccsn));
try {
return classType.cast(smartcard);
} catch (ClassCastException cce) {
log.error(format("Unable to cast Smartcard {0}", smartcard.getIccsn()), cce);
throw new InvalidSmartcardTypeException(classType.getSimpleName());
}
}
}
/**
* Get a {@link Smartcard} with {@link SmartcardType} {@code type} and identified by its ICCSN.
*
* @param type of the Smartcard
* @param iccsn of the Smartcard
* @return the Smartcard identified by the given ICCSN
*/
public Smartcard getSmartcardByICCSN(SmartcardType type, String iccsn) {
return switch (type) {
case SMC_B -> this.getSmcbByICCSN(iccsn);
case HBA -> this.getHbaByICCSN(iccsn);
case EGK -> this.getEgkByICCSN(iccsn);
default -> throw new InvalidSmartcardTypeException(type);
};
}
/**
* Get a {@link Smartcard} safely identified by its ICCSN.
*
* @param iccsn of the Smartcard
* @return {@link Optional} of the {@link Smartcard} if the ICCSN is known to this {@link
* SmartcardArchive} or an empty {@link Optional} otherwise
*/
public Optional getByICCSN(String iccsn) {
return this.getConfigs().stream()
.filter(cfg -> cfg.getIccsn().equals(iccsn))
.findFirst()
.map(cit -> this.getSmartcardByICCSN(cit.getType(), iccsn));
}
/**
* Get a {@link Hba} from this {@link SmartcardArchive} identified by its index.
*
* @param idx of the {@link Hba}
* @return a {@link Hba} from this {@link SmartcardArchive} identified by its index.
*/
public Hba getHba(int idx) {
val hbaConfig = this.factory.getConfigFor(SmartcardType.HBA, idx);
return this.getHbaByICCSN(hbaConfig.getIccsn());
}
/**
* Get a {@link Hba} from this {@link SmartcardArchive} identified by its ICCSN.
*
* @param iccsn of the {@link Hba}
* @return the {@link Hba} with the given ICCSN
*/
public Hba getHbaByICCSN(String iccsn) {
return this.hbaCache.computeIfAbsent(
iccsn, key -> factory.loadSmartcardByIccsn(HbaP12.class, iccsn));
}
/**
* Get all {@link Hba} Smartcards which are configured in this {@link SmartcardArchive}
*
* @return a list of all {@link Hba} Smartcards
*/
public List getHbaCards() {
return this.getConfigsFor(SmartcardType.HBA).stream()
.map(c -> this.getHbaByICCSN(c.getIccsn()))
.toList();
}
/**
* Get a {@link SmcB} from this {@link SmartcardArchive} identified by its index.
*
* @param idx of the {@link SmcB}
* @return a {@link SmcB} from this {@link SmartcardArchive} identified by its index.
*/
public SmcB getSmcB(int idx) {
val smcbConfig = this.factory.getConfigFor(SmartcardType.SMC_B, idx);
return this.getSmcbByICCSN(smcbConfig.getIccsn());
}
/**
* Get a {@link SmcB} from this {@link SmartcardArchive} identified by its ICCSN.
*
* @param iccsn of the {@link SmcB}
* @return the {@link SmcB} with the given ICCSN
*/
public SmcB getSmcbByICCSN(String iccsn) {
return this.smcbCache.computeIfAbsent(
iccsn, key -> factory.loadSmartcardByIccsn(SmcBP12.class, iccsn));
}
/**
* Get all {@link SmcB} Smartcards which are configured in this {@link SmartcardArchive}
*
* @return a list of all {@link SmcB} Smartcards
*/
public List getSmcbCards() {
return this.getConfigsFor(SmartcardType.SMC_B).stream()
.map(c -> this.getSmcbByICCSN(c.getIccsn()))
.toList();
}
/**
* Get a {@link Egk} from this {@link SmartcardArchive} identified by its index.
*
* @param idx of the {@link Egk}
* @return a {@link Egk} from this {@link SmartcardArchive} identified by its index.
*/
public Egk getEgk(int idx) {
val egkConfig = this.factory.getConfigFor(SmartcardType.EGK, idx);
return this.getEgkByICCSN(egkConfig.getIccsn());
}
/**
* Get a {@link Egk} from this {@link SmartcardArchive} identified by its ICCSN.
*
* @param iccsn of the {@link Egk}
* @return the {@link Egk} with the given ICCSN
*/
public Egk getEgkByICCSN(String iccsn) {
return this.egkCache.computeIfAbsent(
iccsn, key -> factory.loadSmartcardByIccsn(EgkP12.class, iccsn));
}
/**
* Get a {@link Egk} from this {@link SmartcardArchive} identified by its KVNR.
*
* @param kvnr of the {@link Egk}
* @return the {@link Egk} with the given KVNR
*/
public Egk getEgkByKvnr(String kvnr) {
return this.egkCache.values().stream()
.filter(egk -> egk.getKvnr().equals(kvnr))
.findFirst()
.orElseGet(
() -> {
val egk = this.factory.loadEgkByKvnr(kvnr);
this.egkCache.put(egk.getIccsn(), egk);
return egk;
});
}
/**
* Get all {@link Egk} Smartcards which are configured in this {@link SmartcardArchive}
*
* @return a list of all {@link Egk} Smartcards
*/
public List getEgkCards() {
return this.getConfigsFor(SmartcardType.EGK).stream()
.map(c -> this.getEgkByICCSN(c.getIccsn()))
.toList();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy