All Downloads are FREE. Search and download functionalities are using the official Maven repository.

no.ks.fiks.dokumentlager.klient.DokumentlagerKlient Maven / Gradle / Ivy

Go to download

Klient for opplasting, sletting og nedlasting av dokumenter fra Fiks Dokumentlager

The newest version!
package no.ks.fiks.dokumentlager.klient;

import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import no.ks.fiks.dokumentlager.klient.model.*;
import no.ks.kryptering.CMSKrypteringImpl;
import no.ks.kryptering.CMSStreamKryptering;
import org.jetbrains.annotations.NotNull;
import org.slf4j.MDC;

import java.io.*;
import java.security.Provider;
import java.security.Security;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Base64;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.*;

@Slf4j
@SuppressWarnings("WeakerAccess")
public class DokumentlagerKlient implements Closeable {

    private static final int END_OF_STREAM = -1;
    private final Provider provider = Security.getProvider("BC");
    private X509Certificate publicCertificate = null;

    private final DokumentlagerApi api;
    private final ExecutorService executor;
    private final CMSStreamKryptering kryptering;

    private DokumentlagerKlient(@NonNull DokumentlagerApi dokumentlagerApi,
                                @NonNull ExecutorService executor,
                                @NonNull CMSStreamKryptering kryptering) {
        this.api = dokumentlagerApi;
        this.executor = executor;
        this.kryptering = kryptering;
    }

    public static DokumentlagerKlientBuilder builder() {
        return new DokumentlagerKlientBuilder();
    }

    public DokumentlagerResponse upload(@NonNull InputStream dokumentStream,
                                                                      @NonNull DokumentMetadataUpload metadata,
                                                                      @NonNull UUID fiksOrganisasjonId,
                                                                      @NonNull UUID kontoId) {
        return upload(dokumentStream, metadata, fiksOrganisasjonId, kontoId, false);
    }

    public DokumentlagerResponse uploadAlreadyEncrypted(@NonNull InputStream dokumentStream,
                                                                                      @NonNull DokumentMetadataUpload metadata,
                                                                                      @NonNull UUID fiksOrganisasjonId,
                                                                                      @NonNull UUID kontoId) {
        log.debug("Starting upload...");
        DokumentlagerResponse response = api.uploadDokument(dokumentStream, metadata, fiksOrganisasjonId, kontoId, true);
        log.debug("Upload completed");
        return response;
    }

    public DokumentlagerResponse upload(@NonNull InputStream dokumentStream,
                                                                      @NonNull DokumentMetadataUpload metadata,
                                                                      @NonNull UUID fiksOrganisasjonId,
                                                                      @NonNull UUID kontoId,
                                                                      boolean skalKrypteres) {
        Future krypteringFuture = null;
        InputStream inputStream = dokumentStream;

        if (metadata.getSikkerhetsniva() != null && metadata.getSikkerhetsniva() > 3 && !skalKrypteres) {
            log.info("Dokument will be encrypted as sikkerhetsnivå is greater than 3");
            skalKrypteres = true;
        }

        try (DokumentlagerPipedInputStream pipedInputStream = new DokumentlagerPipedInputStream();
             PipedOutputStream pipedOutputStream = new PipedOutputStream(pipedInputStream)) {

            if (skalKrypteres) {
                if (publicCertificate == null) {
                    publicCertificate = getPublicKeyAsX509Certificate().getResult();
                }

                inputStream = pipedInputStream;
                krypteringFuture = executor.submit(() -> krypter(dokumentStream, pipedInputStream, pipedOutputStream, MDC.getCopyOfContextMap()));
            }

            try (PushbackInputStream pis = new PushbackInputStream(inputStream)) {
                int read = pis.read();
                if(read == END_OF_STREAM){
                    throw new EmptyDokumentException();
                }
                pis.unread(read);
                DokumentlagerResponse response = api.uploadDokument(pis, metadata, fiksOrganisasjonId, kontoId, skalKrypteres);
                log.debug("Upload completed");

                if (krypteringFuture != null) {
                    log.debug("Waiting for encryption thread to terminate...");
                    krypteringFuture.get(10, TimeUnit.SECONDS);
                    log.debug("Encryption thread terminated");
                }
                return response;
            }
        }  catch (IOException e){
            throw new DokumentlagerIOException(e.getMessage(),e);
        }  catch (InterruptedException | ExecutionException | TimeoutException e) {
            log.error("Upload failed", e);
            throw new RuntimeException(e);
        }
        finally {
            avbrytKrypteringFuture(krypteringFuture);
        }
    }

    private static void avbrytKrypteringFuture(Future krypteringFuture) {
        if (krypteringFuture != null && !krypteringFuture.isDone()) {
            log.debug("Cancelling encryption future");
            boolean cancelled = krypteringFuture.cancel(true);
            log.info("Encryption future cancelled, result: {}", cancelled);
        }
    }

    private void krypter(@NotNull InputStream dokumentStream, DokumentlagerPipedInputStream pipedInputStream, PipedOutputStream pipedOutputStream, Map contextMap) {
        Optional.ofNullable(contextMap).ifPresent(MDC::setContextMap);
        try {
            log.debug("Starting encryption...");
            kryptering.krypterData(pipedOutputStream, dokumentStream, publicCertificate, provider);
            log.info("Encryption completed...");
        } catch (Exception e) {
            log.error("Encryption failed, setting exception on encrypted InputStream", e);
            pipedInputStream.setException(e);
        } finally {
            try {
                log.debug("Closing encryption OutputStream");
                pipedOutputStream.close();
                log.debug("Encryption OutputStream closed");
            } catch (IOException e) {
                log.error("Failed closing encryption OutputStream", e);
                throw new RuntimeException(e);
            } finally {
                MDC.clear();
            }
        }
    }

    public DokumentlagerResponse updateMetadata(@NonNull UUID fiksOrganisasjonId,
                                                      @NonNull UUID kontoId,
                                                      @NonNull UUID dokumentId,
                                                      @NonNull DokumentMetadataUpdate metadata) {
        return api.updateDokumentMetadata(fiksOrganisasjonId, kontoId, dokumentId, metadata);
    }

    public DokumentlagerResponse delete(@NonNull UUID fiksOrganisasjonId,
                                              @NonNull UUID kontoId,
                                              @NonNull UUID dokumentId) {
        return api.deleteDokument(fiksOrganisasjonId, kontoId, dokumentId);
    }

    public DokumentlagerResponse deleteDokumenterByKorrelasjonsid(@NonNull UUID fiksOrganisasjonId,
                                              @NonNull UUID kontoId,
                                              @NonNull UUID korrelasjonsid) {
        return api.deleteDokumenterByKorrelasjonsid(fiksOrganisasjonId, kontoId, korrelasjonsid);
    }

    public DokumentlagerResponse getPublicKey() {
        return api.getPublicKey();
    }

    public DokumentlagerResponse getPublicKeyAsX509Certificate() {
        DokumentlagerResponse publicKeyResponse = getPublicKey();
        String publicKey = publicKeyResponse.getResult();

        try {
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            Base64.Decoder base64 = Base64.getMimeDecoder();

            byte[] buffer = base64.decode(
                    publicKey.replace("-----BEGIN CERTIFICATE-----", "")
                            .replace("-----END CERTIFICATE-----", ""));

            return DokumentlagerResponse.builder()
                    .httpStatus(publicKeyResponse.getHttpStatus())
                    .result((X509Certificate) certificateFactory.generateCertificate(new ByteArrayInputStream(buffer)))
                    .build();

        } catch (CertificateException e) {
            throw new RuntimeException(e);
        }

    }

    public DokumentlagerResponse download(@NonNull UUID dokumentId) {
        return api.downloadDokument(dokumentId);
    }

    public DokumentlagerResponse downloadLazy(@NonNull UUID dokumentId) {
        return api.downloadDokumentLazy(dokumentId);
    }

    public DokumentlagerResponse downloadMetadata(@NonNull UUID dokumentId) {
        return api.downloadDokumentMetadata(dokumentId);
    }

    public DokumentlagerResponse sokDokumenterMedKorrelasjonsid(UUID fiksOrganisasjonId,
                                                                              UUID kontoId,
                                                                              UUID korrelasjonsid,
                                                                              Integer fra,
                                                                              Integer til) {
        return api.sokDokumenterMedKorrelasjonsid(fiksOrganisasjonId, kontoId, korrelasjonsid, fra, til);
    }

    @Override
    public void close() throws IOException {
        api.close();
        executor.shutdown();
    }

    public static class DokumentlagerKlientBuilder {

        private static final int DEFAULT_THREAD_POOL_SIZE = 4;

        private DokumentlagerApi api;
        private CMSStreamKryptering kryptering;
        private ExecutorService executor;

        private DokumentlagerKlientBuilder() {
        }

        public DokumentlagerKlientBuilder api(DokumentlagerApi api) {
            this.api = api;
            return this;
        }

        public DokumentlagerKlientBuilder kryptering(CMSStreamKryptering kryptering) {
            this.kryptering = kryptering;
            return this;
        }

        public DokumentlagerKlientBuilder executor(ExecutorService executor) {
            this.executor = executor;
            return this;
        }

        public DokumentlagerKlient build() {
            if (kryptering == null) {
                kryptering = new CMSKrypteringImpl();
            }
            if (executor == null) {
                executor = Executors.newFixedThreadPool(DEFAULT_THREAD_POOL_SIZE);
            }
            return new DokumentlagerKlient(api, executor, kryptering);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy