BasisregistratieFileUploadActionBean.java
package nl.b3p.brmo.service.stripes;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import javax.sql.DataSource;
import net.sourceforge.stripes.action.ActionBean;
import net.sourceforge.stripes.action.ActionBeanContext;
import net.sourceforge.stripes.action.DefaultHandler;
import net.sourceforge.stripes.action.DontValidate;
import net.sourceforge.stripes.action.FileBean;
import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.action.SimpleMessage;
import net.sourceforge.stripes.action.StrictBinding;
import net.sourceforge.stripes.validation.Validate;
import nl.b3p.brmo.loader.BrmoFramework;
import nl.b3p.brmo.loader.ProgressUpdateListener;
import nl.b3p.brmo.loader.util.BrmoDuplicaatLaadprocesException;
import nl.b3p.brmo.loader.util.BrmoException;
import nl.b3p.brmo.loader.util.BrmoLeegBestandException;
import nl.b3p.brmo.service.util.ConfigUtil;
import org.apache.commons.io.input.CloseShieldInputStream;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.commons.lang3.mutable.MutableLong;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Action voor het handmatig uploaden van bestanden met basisregistratiegegevens via een formulier.
*/
@StrictBinding
public class BasisregistratieFileUploadActionBean implements ActionBean {
private static final int ZIP_HEADER = 0x504b0304;
private static final Log log = LogFactory.getLog(BasisregistratieFileUploadActionBean.class);
private ActionBeanContext context;
@Validate(required = true)
private String basisregistratie;
@Validate(required = true)
private FileBean bestand;
@DefaultHandler
@DontValidate
public Resolution form() {
return new ForwardResolution("/WEB-INF/jsp/bestand/form.jsp");
}
public Resolution upload() throws BrmoException {
DataSource ds = ConfigUtil.getDataSourceStaging();
BrmoFramework brmo = new BrmoFramework(ds, null, null);
ZipInputStream zip = null;
ZipEntry entry = null;
int errors = 0;
int empty = 0;
int duplicate = 0;
final int ERROR_LIMIT = 5;
try {
final MutableLong theTotal = new MutableLong(0);
int extractedFiles = 0;
final ProgressUpdateListener totalAdder =
new ProgressUpdateListener() {
@Override
public void total(long total) {
theTotal.setValue(theTotal.getValue() + total);
}
@Override
public void progress(long progress) {}
@Override
public void exception(Throwable t) {}
};
// Check of bestand begint met ZIP header
InputStream in = new BufferedInputStream(bestand.getInputStream());
in.mark(4);
int header = new DataInputStream(in).readInt();
in.reset();
if (header == ZIP_HEADER) {
// Pak .xml bestanden in ZIP uit en verwerk deze
zip = new ZipInputStream(in);
try {
entry = zip.getNextEntry();
while (entry != null) {
if (!entry.getName().toLowerCase().endsWith(".xml")) {
log.warn("Overslaan zip entry geen XML: " + entry.getName());
} else {
log.debug("Lezen XML bestand uit zip: " + entry.getName());
try {
brmo.loadFromStream(
basisregistratie,
CloseShieldInputStream.wrap(zip),
bestand.getFileName() + "/" + entry.getName(),
totalAdder,
null);
} catch (BrmoLeegBestandException e) {
log.info("Negeer ZIP entry " + entry.getName() + ": " + e.getMessage());
empty++;
} catch (BrmoDuplicaatLaadprocesException e) {
log.info("Negeer ZIP entry " + entry.getName() + ": duplicaat laadproces");
duplicate++;
} catch (BrmoException e) {
errors++;
log.error(
"BrmoException bij laden ZIP entry "
+ entry.getName()
+ (errors > ERROR_LIMIT ? "; afbreken" : "; doorgaan met volgende"),
e);
if (errors > ERROR_LIMIT) {
throw new BrmoException(
"Maximum aantal fouten ("
+ ERROR_LIMIT
+ ") bereikt bij inladen ZIP bestanden, inladen afgebroken. Controleer brmo-service.log",
e);
}
}
extractedFiles++;
}
entry = zip.getNextEntry();
}
} finally {
zip.close();
}
} else {
// Geen ZIP, direct BR XML laden
brmo.loadFromStream(basisregistratie, in, bestand.getFileName(), totalAdder, null);
}
List<String> warnings = new ArrayList<>();
if (errors > 0) {
warnings.add(
"let op: "
+ errors
+ " bericht"
+ (errors > 1 ? "en" : "")
+ " niet ingeladen wegens fouten");
}
if (empty > 0) {
warnings.add(
"let op: "
+ empty
+ (empty > 1 ? " lege berichten" : " leeg bericht")
+ " overgeslagen");
}
if (duplicate > 0) {
warnings.add(
"let op: "
+ duplicate
+ (duplicate > 1 ? " duplicate berichten" : " duplicaat bericht")
+ " overgeslagen");
}
String warning =
warnings.isEmpty()
? ""
: ", "
+ String.join(", ", warnings.toArray(new String[] {}))
+ ", zie log voor bestandsnamen uit ZIP en details!";
getContext()
.getMessages()
.add(
new SimpleMessage(
"Bestand "
+ bestand.getFileName()
+ " is ingelezen, "
+ theTotal.getValue()
+ " berichten"
+ (extractedFiles > 0
? " (uit " + extractedFiles + " uitgepakte XML bestanden)"
: "")
+ warning));
log.info(
String.format(
"Stored %s data from file \"%s\" uploaded via form",
basisregistratie, bestand.getFileName()));
} catch (Exception ex) {
String msg =
"Fout bij inlezen bestand "
+ (zip != null && entry != null
? entry.getName() + " uit ZIP bestand " + bestand.getFileName()
: bestand.getFileName());
log.error(msg, ex);
getContext()
.getMessages()
.add(new SimpleMessage(msg + ": " + ExceptionUtils.getRootCauseMessage(ex)));
} finally {
try {
bestand.delete();
} catch (IOException e) {
// ignore
}
brmo.closeBrmoFramework();
}
return new ForwardResolution("/WEB-INF/jsp/bestand/form.jsp");
}
// <editor-fold defaultstate="collapsed" desc="getters en setters">
@Override
public ActionBeanContext getContext() {
return context;
}
@Override
public void setContext(ActionBeanContext context) {
this.context = context;
}
public String getBasisregistratie() {
return basisregistratie;
}
public void setBasisregistratie(String basisregistratie) {
this.basisregistratie = basisregistratie;
}
public FileBean getBestand() {
return bestand;
}
public void setBestand(FileBean bestand) {
this.bestand = bestand;
}
// </editor-fold>
}