package fr.titionfire.ffsaf.domain.service; import fr.titionfire.ffsaf.data.model.ClubModel; import fr.titionfire.ffsaf.data.model.LicenceModel; import fr.titionfire.ffsaf.data.model.MembreModel; import fr.titionfire.ffsaf.data.repository.ClubRepository; import fr.titionfire.ffsaf.data.repository.CombRepository; import fr.titionfire.ffsaf.rest.exception.DNotFoundException; import fr.titionfire.ffsaf.utils.Utils; import io.quarkus.hibernate.reactive.panache.common.WithSession; import io.smallrye.mutiny.Uni; import io.smallrye.mutiny.unchecked.Unchecked; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import jakarta.ws.rs.core.HttpHeaders; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import org.eclipse.microprofile.config.inject.ConfigProperty; import org.hibernate.reactive.mutiny.Mutiny; import org.jboss.logging.Logger; import java.io.*; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; import java.util.UUID; import java.util.concurrent.TimeUnit; @WithSession @ApplicationScoped public class PDFService { private static final Logger LOGGER = Logger.getLogger(PDFService.class); @Inject CombRepository combRepository; @Inject ClubRepository clubRepository; @ConfigProperty(name = "upload_dir") String media; @ConfigProperty(name = "pdf-maker.jar-path") String pdfMakerJarPath; @ConfigProperty(name = "pdf-maker.sign-file") String sign_file; public Uni getLicencePdf(String subject) { return getLicencePdf(combRepository.find("userId = ?1", subject).firstResult() .call(m -> Mutiny.fetch(m.getLicences()))); } public Uni getLicencePdf(Uni uniBase) { return uniBase .map(Unchecked.function(m -> { LicenceModel licence = m.getLicences().stream() .filter(licenceModel -> licenceModel.getSaison() == Utils.getSaison() && licenceModel.isValidate()) .findFirst() .orElseThrow(() -> new DNotFoundException("Pas de licence pour la saison en cours")); try { byte[] buff = make_pdf(m, licence); if (buff == null) throw new IOException("Error making pdf"); String mimeType = "application/pdf"; Response.ResponseBuilder resp = Response.ok(buff); resp.type(MediaType.APPLICATION_OCTET_STREAM); resp.header(HttpHeaders.CONTENT_LENGTH, buff.length); resp.header(HttpHeaders.CONTENT_TYPE, mimeType); resp.header(HttpHeaders.CONTENT_DISPOSITION, "inline; " + "filename=\"Attestation d'adhésion " + Utils.getSaison() + "-" + (Utils.getSaison() + 1) + " de " + m.getLname() + " " + m.getFname() + ".pdf\""); return resp.build(); } catch (Exception e) { throw new IOException(e); } })); } private byte[] make_pdf(MembreModel m, LicenceModel licence) throws IOException, InterruptedException { List cmd = new ArrayList<>(); cmd.add("java"); cmd.add("-jar"); cmd.add(pdfMakerJarPath); UUID uuid = UUID.randomUUID(); cmd.add("/tmp/" + uuid + ".pdf"); cmd.add("membre"); cmd.add(m.getFname()); cmd.add(m.getLname()); cmd.add(m.getGenre().str); cmd.add(m.getCategorie().getName()); cmd.add(licence.getCertificate() == null ? "" : licence.getCertificate()); cmd.add(Utils.getSaison() + ""); cmd.add(m.getLicence() + ""); cmd.add(m.getClub().getName()); cmd.add(m.getClub().getNo_affiliation() + ""); cmd.add(m.getBirth_date() == null ? "--" : new SimpleDateFormat("dd/MM/yyyy").format(m.getBirth_date())); FilenameFilter filter = (directory, filename) -> filename.startsWith(m.getId() + "."); File[] files = new File(media, "ppMembre").listFiles(filter); if (files != null && files.length > 0) { File file = files[0]; cmd.add(file.getAbsolutePath()); } else { cmd.add("/dev/null"); } return getPdf(cmd, uuid); } public Uni getAffiliationPdf(String subject) { return getAffiliationPdf( combRepository.find("userId = ?1", subject).firstResult() .invoke(Unchecked.consumer(m -> { if (m == null || m.getClub() == null) throw new DNotFoundException("Club non trouvé"); })) .map(MembreModel::getClub) .call(m -> Mutiny.fetch(m.getAffiliations()))); } public Uni getAffiliationPdf(long id) { return getAffiliationPdf( clubRepository.findById(id) .invoke(Unchecked.consumer(m -> { if (m == null) throw new DNotFoundException("Club non trouvé"); })) .call(m -> Mutiny.fetch(m.getAffiliations()))); } private Uni getAffiliationPdf(Uni uniBase) { return uniBase .map(Unchecked.function(m -> { if (m.getAffiliations().stream() .noneMatch(licenceModel -> licenceModel.getSaison() == Utils.getSaison())) throw new DNotFoundException("Pas d'affiliation pour la saison en cours"); try { byte[] buff = make_pdf(m); if (buff == null) throw new IOException("Error making pdf"); String mimeType = "application/pdf"; Response.ResponseBuilder resp = Response.ok(buff); resp.type(MediaType.APPLICATION_OCTET_STREAM); resp.header(HttpHeaders.CONTENT_LENGTH, buff.length); resp.header(HttpHeaders.CONTENT_TYPE, mimeType); resp.header(HttpHeaders.CONTENT_DISPOSITION, "inline; " + "filename=\"Attestation d'affiliation " + Utils.getSaison() + "-" + (Utils.getSaison() + 1) + " de " + m.getName() + ".pdf\""); return resp.build(); } catch (Exception e) { throw new IOException(e); } })); } private byte[] make_pdf(ClubModel m) throws IOException, InterruptedException { List cmd = new ArrayList<>(); cmd.add("java"); cmd.add("-jar"); cmd.add(pdfMakerJarPath); UUID uuid = UUID.randomUUID(); cmd.add("/tmp/" + uuid + ".pdf"); cmd.add("club"); cmd.add(m.getName()); cmd.add(Utils.getSaison() + ""); cmd.add(m.getNo_affiliation() + ""); cmd.add(new File(sign_file).getAbsolutePath()); return getPdf(cmd, uuid); } static byte[] getPdf(List cmd, UUID uuid) throws IOException, InterruptedException { ProcessBuilder processBuilder = new ProcessBuilder(cmd); processBuilder.redirectErrorStream(true); Process process = processBuilder.start(); BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); StringBuilder builder = new StringBuilder(); Thread t = new Thread(() -> { try { String line; while ((line = reader.readLine()) != null) builder.append(line).append("\n"); } catch (Exception ignored) { } }); t.start(); int code = -1; if (!process.waitFor(30, TimeUnit.SECONDS)) { process.destroy(); builder.append("Timeout..."); } else { code = process.exitValue(); } if (t.isAlive()) t.interrupt(); PDFService.LOGGER.debug("PDF maker: " + builder); if (code != 0) { throw new IOException("Error code: " + code); } else { File file = new File("/tmp/" + uuid + ".pdf"); try (FileInputStream fis = new FileInputStream(file)) { byte[] buff = fis.readAllBytes(); //noinspection ResultOfMethodCallIgnored file.delete(); return buff; } catch (IOException e) { //noinspection ResultOfMethodCallIgnored file.delete(); } return null; } } }