/* * SchemaValidation.java */ package gov.nist.registry.common2.xml; import gov.nist.registry.common2.MetadataTypes; import gov.nist.registry.common2.exception.XdsInternalException; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.PrintStream; import java.io.StringReader; import java.net.URL; import org.apache.axiom.om.OMElement; import org.apache.xerces.parsers.DOMParser; import org.openhealthtools.openexchange.config.PropertyFacade; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import com.misyshealthcare.connect.util.StringUtil; public class SchemaValidation implements MetadataTypes { public static String validate(OMElement ele, int metadataType) throws XdsInternalException { return validate_local(ele, metadataType); } // The only known use case for localhost validation failing is when this is called from // xdstest2 in which case it is trying to call home to reference the schema files. // What is really needed is a configuration parm that points the reference to the local filesystem // and include the schema files in the xdstest2tool environment. // port 80 does not exist for requests on-machine (on the server). only requests coming in from // off-machine go through the firewall where the port translation happens. // even though this says validate_local, it is used by all requests public static String validate_local(OMElement ele, int metadataType) throws XdsInternalException { String msg; msg = SchemaValidation.run(ele.toString(), metadataType); return msg; } // empty string as result means no errors static private String run(String metadata, int metadataType) throws XdsInternalException { MyErrorHandler errors = null; DOMParser p = null; //Check System property first which takes a priority String localSchema = System.getenv("xds.schema.dir"); if (localSchema == null) localSchema = System.getProperty("xds.schema.dir"); if (localSchema == null) { String SchemaLoc = PropertyFacade.getString("xds.schema.dir"); if (!StringUtil.goodString(SchemaLoc)) { throw new XdsInternalException("The xds.schema.dir property is not defined in openxds.properties"); } URL repoPath = SchemaValidation.class.getResource(SchemaLoc); if (repoPath != null) { localSchema = repoPath.getPath(); } else { File file =new File(SchemaLoc); try{ localSchema = file.getCanonicalPath(); }catch (Exception e) { throw new XdsInternalException("I/O exception occured while getting the canonical path - " + e.getMessage(), e); } } } if (!StringUtil.goodString(localSchema)) { throw new XdsInternalException("The xds.schema.dir property is invalid"); } // Decode schema location String schemaLocation; switch (metadataType) { case METADATA_TYPE_Rb: schemaLocation = "urn:oasis:names:tc:ebxml-regrep:xsd:lcm:3.0 " + ((localSchema == null) ? "/v3/lcm.xsd": localSchema + "/v3/lcm.xsd"); break; case METADATA_TYPE_PR: case METADATA_TYPE_R: schemaLocation = "urn:oasis:names:tc:ebxml-regrep:registry:xsd:2.1 " + ((localSchema == null) ? "/v2/rs.xsd" : localSchema + "/v2/rs.xsd"); break; case METADATA_TYPE_Q: schemaLocation = "urn:oasis:names:tc:ebxml-regrep:query:xsd:2.1 " + ((localSchema == null) ? "/v2/query.xsd " : localSchema + "/v2/query.xsd " ) + "urn:oasis:names:tc:ebxml-regrep:registry:xsd:2.1 " + ((localSchema == null) ? "/v2/rs.xsd" : localSchema + "/v2/rs.xsd" ) ; break; case METADATA_TYPE_SQ: schemaLocation = "urn:oasis:names:tc:ebxml-regrep:xsd:query:3.0 " + ((localSchema == null) ? "/v3/query.xsd " : localSchema + "/v3/query.xsd " ) + "urn:oasis:names:tc:ebxml-regrep:xsd:rs:3.0 " + ((localSchema == null) ? "/v3/rs.xsd" : localSchema + "/v3/rs.xsd" ); break; case METADATA_TYPE_RET: schemaLocation = "urn:ihe:iti:xds-b:2007 " + ((localSchema == null) ? "/v3/XDS.b_DocumentRepository.xsd " : localSchema + "/v3/XDS.b_DocumentRepository.xsd ") + "urn:oasis:names:tc:ebxml-regrep:xsd:rs:3.0 " + ((localSchema == null) ? "/v3/rs.xsd" : localSchema + "/v3/rs.xsd" ); break; case AUDIT_LOG: schemaLocation = "noNamespaceSchemaLocation " + ((localSchema == null) ? "/audit/healthcare-security-audit.xsd " : localSchema + "/audit/healthcare-security-audit.xsd "); break; default: throw new XdsInternalException("SchemaValidation: invalid metadata type = " + metadataType); } schemaLocation += " urn:oasis:names:tc:ebxml-regrep:xsd:rim:3.0 " + ((localSchema == null) ? "/v3/rim.xsd" : localSchema + "/v3/rim.xsd"); schemaLocation += " http://schemas.xmlsoap.org/soap/envelope/ " + ((localSchema == null) ? "/v3/soap.xsd" : localSchema + "/v3/soap.xsd"); schemaLocation += " http://docs.oasis-open.org/wsn/b-2 " + ((localSchema == null) ? "/wsn/b-2.xsd" : localSchema + "/wsn/b-2.xsd"); schemaLocation += " http://docs.oasis-open.org/wsn/br-2 " + ((localSchema == null) ? "/wsn/br-2.xsd" : localSchema + "/wsn/br-2.xsd"); schemaLocation += " http://docs.oasis-open.org/wsn/t-1 " + ((localSchema == null) ? "/wsn/t-1.xsd" : localSchema + "/wsn/t-1.xsd"); // build parse to do schema validation try { p=new DOMParser(); } catch (Exception e) { throw new XdsInternalException("DOMParser failed: " + e.getMessage()); } try { p.setFeature( "http://xml.org/sax/features/validation", true ); p.setFeature("http://apache.org/xml/features/validation/schema", true); p.setProperty("http://apache.org/xml/properties/schema/external-schemaLocation", schemaLocation); errors = new MyErrorHandler(); errors.setSchemaFile(schemaLocation); p.setErrorHandler( errors ); } catch (SAXException e) { throw new XdsInternalException("SchemaValidation: error in setting up parser property: SAXException thrown with message: " + e.getMessage()); } // run parser and collect parser and schema errors try { // translate urn:uuid: to urn_uuid_ since the colons really screw up schema stuff String metadata2 = metadata.replaceAll("urn:uuid:", "urn_uuid_"); InputSource is = new InputSource(new StringReader(metadata2)); p.parse(is); } catch (Exception e) { throw new XdsInternalException("SchemaValidation: XML parser/Schema validation error: " + exception_details(e)); } String errs = errors.getErrors(); // if (errs.length() != 0) { // errs = errs + "\n" + metadata.substring(1,500); // } return errs; } protected static String exception_details(Exception e) { if (e == null) return "No stack trace available"; ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintStream ps = new PrintStream(baos); e.printStackTrace(ps); return "Exception thrown: " + e.getClass().getName() + "\n" + e.getMessage() + "\n" + new String(baos.toByteArray()); } }