package io.oasp.module.security.common.impl.accesscontrol; import io.oasp.module.security.common.api.accesscontrol.AccessControlSchema; import io.oasp.module.security.common.base.accesscontrol.AccessControlSchemaMapper; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.SchemaOutputResolver; import javax.xml.bind.Unmarshaller; import javax.xml.bind.ValidationEvent; import javax.xml.bind.ValidationEventHandler; import javax.xml.transform.Result; import javax.xml.transform.stream.StreamResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This class is a simple wrapper for {@link #read(InputStream) reading} and * {@link #write(AccessControlSchema, OutputStream) writing} the {@link AccessControlSchema} from/to XML. * */ public class AccessControlSchemaXmlMapper implements AccessControlSchemaMapper { /** Logger instance. */ private static final Logger LOG = LoggerFactory.getLogger(AccessControlSchemaXmlMapper.class); private JAXBContext jaxbContext; /** * The constructor. */ public AccessControlSchemaXmlMapper() { super(); try { this.jaxbContext = JAXBContext.newInstance(AccessControlSchema.class); } catch (JAXBException e) { throw new IllegalStateException(e); } } @Override public void write(AccessControlSchema conf, OutputStream out) { try { Marshaller marshaller = this.jaxbContext.createMarshaller(); marshaller.marshal(conf, out); } catch (JAXBException e) { throw new IllegalStateException("Marshalling XML failed!", e); } } @Override public AccessControlSchema read(InputStream in) { try { Unmarshaller unmarshaller = this.jaxbContext.createUnmarshaller(); ValidationEventHandler handler = new ValidationEventHandlerImpl(); unmarshaller.setEventHandler(handler); return (AccessControlSchema) unmarshaller.unmarshal(in); } catch (JAXBException e) { throw new IllegalStateException("Unmarshalling XML failed!", e); } } /** * Generates the XSD (XML Schema Definition) to the given {@link File}. * * @param outFile is the {@link File} to write to. */ public void writeXsd(File outFile) { File folder = outFile.getParentFile(); if (!folder.isDirectory()) { boolean success = folder.mkdirs(); if (!success) { throw new IllegalStateException("Failed to create folder " + folder); } } try (FileOutputStream fos = new FileOutputStream(outFile)) { writeXsd(fos); } catch (Exception e) { throw new IllegalStateException("Failed to generate and write the XSD schema to " + outFile + "!", e); } } /** * Generates the XSD (XML Schema Definition) to the given {@link OutputStream}. * * @param out is the {@link OutputStream} to write to. */ public void writeXsd(final OutputStream out) { SchemaOutputResolver sor = new SchemaOutputResolver() { @Override public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException { StreamResult streamResult = new StreamResult(out); streamResult.setSystemId(suggestedFileName); return streamResult; } }; try { this.jaxbContext.generateSchema(sor); } catch (IOException e) { throw new IllegalStateException("Failed to generate and write the XSD schema!", e); } } /** * Custom implementation of {@link ValidationEventHandler}. */ protected static class ValidationEventHandlerImpl implements ValidationEventHandler { /** * The constructor. */ public ValidationEventHandlerImpl() { super(); } @Override public boolean handleEvent(ValidationEvent event) { if (event != null) { switch (event.getSeverity()) { case ValidationEvent.ERROR: case ValidationEvent.FATAL_ERROR: throw new IllegalArgumentException(event.toString()); case ValidationEvent.WARNING: LOG.warn(event.toString()); break; default: LOG.debug(event.toString()); } } return true; } } }