/* * Copyright (c) 2012 Chris Ellison, Mike Deats, Liron Yahdav, Ryan Neal, * Brandon Sutherlin, Scott Griffin * * This software is released under the MIT license * (http://www.opensource.org/licenses/mit-license.php) * * Created on Mar 26, 2012 */ package edu.cmu.sv.arinc838.validation; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamReader; import edu.cmu.sv.arinc838.binary.BdfFile; import edu.cmu.sv.arinc838.crc.CrcCalculator; import edu.cmu.sv.arinc838.dao.FileDefinitionDao; import edu.cmu.sv.arinc838.dao.IntegrityDefinitionDao; import edu.cmu.sv.arinc838.dao.IntegrityDefinitionDao.IntegrityType; import edu.cmu.sv.arinc838.dao.SoftwareDefinitionFileDao; import edu.cmu.sv.arinc838.dao.SoftwareDescriptionDao; import edu.cmu.sv.arinc838.dao.TargetHardwareDefinitionDao; import edu.cmu.sv.arinc838.util.Converter; import edu.cmu.sv.arinc838.validation.CrcValidator.ChecksumValidationException; public class SoftwareDefinitionFileValidator { private DataValidator dataVal; public SoftwareDefinitionFileValidator(DataValidator dataVal) { this.dataVal = dataVal; } /** * Validates that the header conforms to the spec. This includes the * attributes (e.g. schemaLocation) the namespace (e.g. xsi, sdf) and the * encoding/version (utf-8, 1.0). * * @param xmlFile * @return * @throws Exception */ public List<Exception> validateXmlFileHeader(File xmlFile) throws Exception { XMLStreamReader xsr = null; FileInputStream fileInputStream = null; List<Exception> errors = new ArrayList<Exception>(); try { fileInputStream = new FileInputStream(xmlFile); xsr = XMLInputFactory.newInstance().createXMLStreamReader( fileInputStream); xsr.nextTag(); // move to the root } catch (Exception e) { if (xsr != null) { xsr.close(); } if (fileInputStream != null) { fileInputStream.close(); } errors.add(e); return errors; // can't work if the xsr can't be created } // attribute check errors.addAll(dataVal.validateXmlHeaderAttributes(xsr)); // namespace check errors.addAll(dataVal.validateXmlHeaderNamespaces(xsr)); xsr.close(); fileInputStream.close(); return errors; } public List<Exception> validateSdfFile(SoftwareDefinitionFileDao sdfDao, String sourceFile, BdfFile bdfFile) { List<Exception> errors = new ArrayList<Exception>(); try { dataVal.validateFileFormatVersion(sdfDao.getFileFormatVersion()); } catch (IllegalArgumentException e) { errors.add(e); } boolean isXdfFile = sourceFile.split("\\.")[1].equals("XDF"); errors.addAll(validateSoftwareDescription( sdfDao.getSoftwareDescription(), sourceFile)); errors.addAll(validateTargetHardwareDefinitions( sdfDao.getTargetHardwareDefinitions(), sourceFile)); errors.addAll(validateFileDefinitions(sdfDao.getFileDefinitions(), sdfDao, isXdfFile)); errors.addAll(validateSdfIntegrityDefinition(sdfDao, bdfFile)); errors.addAll(validateLspIntegrityDefinition(sdfDao, bdfFile)); return errors; } public List<Exception> validateSoftwareDescription( SoftwareDescriptionDao softwareDesc, String sourceFile) { List<Exception> errors = new ArrayList<Exception>(); try { dataVal.validateSoftwarePartNumber(softwareDesc .getSoftwarePartnumber()); } catch (IllegalArgumentException e) { errors.add(e); } String partNumberAsFile = softwareDesc.getSoftwarePartnumber().replace( "-", ""); String partNumberAsXDF = partNumberAsFile + ".XDF"; String partNumberAsBDF = partNumberAsFile + ".BDF"; if (!partNumberAsXDF.equals(sourceFile) && !partNumberAsBDF.equals(sourceFile)) { errors.add(new IllegalArgumentException( "Source file name did not match software part number. File name was '" + sourceFile + "', expected '" + partNumberAsXDF + "' or '" + partNumberAsBDF + "'.")); } errors.addAll(validateStr64k(softwareDesc.getSoftwareTypeDescription(), sourceFile)); try { dataVal.validateHexbin32(softwareDesc.getSoftwareTypeId()); } catch (IllegalArgumentException e) { errors.add(e); } return errors; } private List<Exception> validateStr64k(String value, String sourceFile) { String extension = sourceFile.split("\\.")[1]; if (extension.equals("XDF")) { return dataVal.validateStr64kXml(value); } else { return dataVal.validateStr64kBinary(value); } } public List<Exception> validateTargetHardwareDefinitions( List<TargetHardwareDefinitionDao> thwDefs, String sourceFile) { List<Exception> errors = new ArrayList<Exception>(); for (TargetHardwareDefinitionDao thwDef : thwDefs) { if (thwDef.getPositions() == null) { continue; } for (String position : thwDef.getPositions()) { errors.addAll(validateStr64k(position, sourceFile)); } } return errors; } public List<Exception> validateFileDefinitions( List<FileDefinitionDao> fileDefs, SoftwareDefinitionFileDao sdfDao, boolean isXdf) { List<Exception> errors = new ArrayList<Exception>(); try { dataVal.validateList1(fileDefs); } catch (IllegalArgumentException e) { errors.add(e); } errors.addAll(dataVal.validateDataFileNamesAreUnique(fileDefs)); for (FileDefinitionDao fileDef : fileDefs) { errors.addAll(validateFileDefinition(fileDef, sdfDao, isXdf)); } return errors; } public List<Exception> validateSdfIntegrityDefinition( SoftwareDefinitionFileDao sdf, BdfFile bdf) { List<Exception> errors = new ArrayList<Exception>(); errors.addAll(validateIntegrityDefStructure(sdf .getSdfIntegrityDefinition())); if (bdf != null) { try { CrcValidator.validateSdfCrc(sdf, bdf); } catch (Exception e) { errors.add(e); } } return errors; } public List<Exception> validateLspIntegrityDefinition( SoftwareDefinitionFileDao sdf, BdfFile bdf) { List<Exception> errors = new ArrayList<Exception>(); errors.addAll(validateIntegrityDefStructure(sdf .getLspIntegrityDefinition())); if (bdf != null) { try { CrcValidator.validateLspCrc(sdf, bdf); } catch (Exception e) { errors.add(e); } } return errors; } public List<Exception> validateFileDefinition(FileDefinitionDao fileDef, SoftwareDefinitionFileDao sdfDao, boolean isXdf) { List<Exception> errors = new ArrayList<Exception>(); errors.addAll(dataVal.validateDataFileName(fileDef.getFileName())); try { dataVal.validateUint32(fileDef.getFileSize()); } catch (IllegalArgumentException e) { IllegalArgumentException exceptionToAdd = new IllegalArgumentException( "Checksum for file " + fileDef.getFileName() + " was invalid! Error was '" + e.getMessage() + "'."); errors.add(exceptionToAdd); } byte[] data = null; if (!isXdf) { try { data = CrcCalculator.readFile(new File(sdfDao.getPath(), fileDef.getFileName())); } catch (IOException e) { IOException exceptionToAdd = new IOException( "Error reading file " + fileDef.getFileName() + "! Error was '" + e.getMessage() + "'."); errors.add(exceptionToAdd); data = null; // don't validate CRC if there was an error reading // the // file } } List<Exception> integDefErrors = validateIntegrityDefinition( fileDef.getFileIntegrityDefinition(), data); if (integDefErrors != null) { for (Exception e : integDefErrors) { Exception exceptionToAdd = e; if (e.getClass() == ChecksumValidationException.class) { exceptionToAdd = new ChecksumValidationException( "Checksum for file " + fileDef.getFileName() + " was invalid! Error was '" + e.getMessage() + "'."); } else if (e.getClass() == IllegalArgumentException.class) { exceptionToAdd = new IllegalArgumentException( "Checksum for file " + fileDef.getFileName() + " was invalid! Error was '" + e.getMessage() + "'."); } errors.add(exceptionToAdd); } } return errors; } public List<Exception> validateIntegrityDefinition( IntegrityDefinitionDao integDef, byte[] data) { List<Exception> errors = new ArrayList<Exception>(); errors.addAll(validateIntegrityDefStructure(integDef)); if (data != null) { try { IntegrityType type = IntegrityType.fromLong(integDef .getIntegrityType()); long value = Converter.checksumBytesToLong(integDef); switch (type) { case CRC16: CrcValidator.validateCrc16((int) value, data); break; case CRC32: CrcValidator.validateCrc32(value, data); break; case CRC64: CrcValidator.validateCrc64(value, data); break; default: errors.add(new IllegalArgumentException( "Invalid integrity type " + integDef.getIntegrityType())); } } catch (Exception e) { errors.add(e); } } return errors; } protected List<Exception> validateIntegrityDefStructure( IntegrityDefinitionDao integDef) { List<Exception> errors = new ArrayList<Exception>(); try { dataVal.validateIntegrityType(integDef.getIntegrityType()); } catch (IllegalArgumentException e) { errors.add(e); } try { dataVal.validateIntegrityValue(integDef.getIntegrityValue()); } catch (IllegalArgumentException e) { errors.add(e); } return errors; } }