class StringSubstitutionParser {

    @SuppressWarnings("rawtypes")
    public static StringsubsDefinition parse(InputStream configStream)
            throws StringSubstitutionException {
        // If schema information is missing
        if(configStream == null) {
            throw new StringSubstitutionException(_strings.get("invalidStream"));
        }
        try {
            URL schemaUrl = StringSubstitutionParser.class.getClassLoader().getResource(DEFAULT_SCHEMA);
            JAXBContext context = JAXBContext.newInstance(StringsubsDefinition.class.getPackage().getName());
            Unmarshaller unmarshaller = context.createUnmarshaller();
            SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
            Schema schema = schemaFactory.newSchema(schemaUrl);
            unmarshaller.setSchema(schema);
            InputSource is = new InputSource(configStream);
            SAXSource source = new SAXSource(is);
            Object obj = unmarshaller.unmarshal(source);
            return obj instanceof JAXBElement ? (StringsubsDefinition) ((JAXBElement) obj).getValue() : (StringsubsDefinition) obj;
        } catch(SAXException se) {
            throw new StringSubstitutionException(_strings.get("failedToParse", DEFAULT_SCHEMA), se);      
        } catch(JAXBException jaxbe) {
            throw new StringSubstitutionException(_strings.get("failedToParse", DEFAULT_SCHEMA), jaxbe);
        } finally {
            if(configStream != null) {
                try {
                    configStream.close();
                    configStream = null;
                } catch(IOException e) {
                	if (_logger.isLoggable(Level.FINER)) {
                		_logger.log(Level.FINER, _strings.get("errorInClosingStream"));
                	}
                }
            }
        }
    }

}