001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019package lucee.runtime.text.xml;
020
021import java.io.IOException;
022
023import lucee.commons.lang.StringUtil;
024import lucee.runtime.exp.XMLException;
025import lucee.runtime.op.Caster;
026import lucee.runtime.type.Array;
027import lucee.runtime.type.ArrayImpl;
028import lucee.runtime.type.Struct;
029import lucee.runtime.type.StructImpl;
030
031import org.xml.sax.InputSource;
032import org.xml.sax.SAXException;
033import org.xml.sax.SAXParseException;
034import org.xml.sax.XMLReader;
035
036
037
038public class XMLValidator extends XMLEntityResolverDefaultHandler {
039
040        @Override
041        public InputSource resolveEntity(String publicID, String systemID)
042                        throws SAXException {
043                //print.out(publicID+":"+systemID);
044                return super.resolveEntity(publicID, systemID);
045        }
046
047        private Array warnings;
048        private Array errors;
049        private Array fatals;
050        private boolean hasErrors;
051        private String strSchema;
052
053        public XMLValidator(InputSource validator, String strSchema) {
054                super(validator);
055                this.strSchema=strSchema;
056        }
057        
058
059        private void release() {
060                warnings=null;
061                errors=null;
062                fatals=null;
063                hasErrors=false;
064        }
065        
066    @Override
067    public void warning(SAXParseException spe)  {
068        log(spe,"Warning",warnings);
069    }
070        
071        @Override
072        public void error(SAXParseException spe) {
073                hasErrors=true;
074        log(spe,"Error",errors);
075    }
076
077    @Override
078    public void fatalError(SAXParseException spe) throws SAXException   {
079                hasErrors=true;
080        log(spe,"Fatal Error",fatals);
081    }
082    
083    private void log(SAXParseException spe, String type,Array array)    {
084        StringBuffer sb = new StringBuffer("["+type+"] ");
085        
086        String id = spe.getSystemId();
087        if(!StringUtil.isEmpty(id)) {
088                int li=id.lastIndexOf('/');
089                if(li!=-1)sb.append(id.substring(li+1));
090                else sb.append(id);
091        }
092        sb.append(':');
093        sb.append(spe.getLineNumber());
094        sb.append(':');
095        sb.append(spe.getColumnNumber());
096        sb.append(": ");
097        sb.append(spe.getMessage());
098        sb.append(" ");
099        array.appendEL(sb.toString());
100    }
101    
102        public Struct validate(InputSource xml) throws XMLException {
103                warnings=new ArrayImpl();
104                errors=new ArrayImpl();
105                fatals=new ArrayImpl();
106                
107                try {
108            XMLReader parser = XMLUtil.createXMLReader("org.apache.xerces.parsers.SAXParser");
109            parser.setContentHandler(this);
110            parser.setErrorHandler(this);
111            parser.setEntityResolver(this);
112            parser.setFeature("http://xml.org/sax/features/validation", true);
113            parser.setFeature("http://apache.org/xml/features/validation/schema", true);
114            parser.setFeature("http://apache.org/xml/features/validation/schema-full-checking", true);
115            //if(!validateNamespace)
116            if(!StringUtil.isEmpty(strSchema))
117                parser.setProperty("http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation", strSchema);
118            parser.parse(xml);
119        }
120        catch(SAXException e) { }
121        catch(IOException e){
122                
123                throw new XMLException(e.getMessage());
124        }
125        
126        // result
127        Struct result = new StructImpl();
128        result.setEL("warnings", warnings);
129        result.setEL("errors", errors);
130        result.setEL("fatalerrors", fatals);
131        result.setEL("status", Caster.toBoolean(!hasErrors));
132        release();
133        return result;
134        }
135
136}