| /************************************************************************ |
| * |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER |
| * |
| * Copyright 2008, 2010 Oracle and/or its affiliates. All rights reserved. |
| * |
| * Use is subject to license terms. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| * use this file except in compliance with the License. You may obtain a copy |
| * of the License at http://www.apache.org/licenses/LICENSE-2.0. You can also |
| * obtain a copy of the License at http://odftoolkit.org/docs/license.txt |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| ************************************************************************/ |
| |
| package org.odftoolkit.odfvalidator; |
| |
| import java.util.HashSet; |
| import java.util.Vector; |
| import org.odftoolkit.odfdom.dom.OdfDocumentNamespace; |
| import org.xml.sax.Attributes; |
| import org.xml.sax.SAXException; |
| import org.xml.sax.helpers.AttributesImpl; |
| import org.xml.sax.helpers.XMLFilterImpl; |
| |
| class ForeignContentFilter extends XMLFilterImpl { |
| |
| private static final String OFFICE_NAMESPACE_URI = OdfDocumentNamespace.OFFICE.getUri(); |
| private static final String TEXT_NAMESPACE_URI = OdfDocumentNamespace.TEXT.getUri(); |
| |
| private static final String H = "h"; |
| private static final String P = "p"; |
| |
| private static final String PROCESS_CONTENT = "process-content"; |
| private static final String TRUE = "true"; |
| |
| // Set of ODF namespace URIs |
| private static HashSet<String> m_aODFNamespaceSet = null; |
| |
| // This list contains a boolean for all ancestor foreign elements. |
| // That boolean values specifies whether the element content is processed or not. |
| private Vector<Boolean> m_aAlienElementProcessContents = null; |
| |
| // This list contains a boolean for all ancestor elements. |
| // That boolean values specifies whether the element is a text:h ot text:p |
| // element itself or has a text:h or text:p ancestor element. |
| private Vector<Boolean> m_aParagraphAncestorElements = null; |
| |
| private ForeignContentListener m_aForeignContentListener = null; |
| |
| private OdfVersion m_aVersion = null; |
| private Logger m_aLogger; |
| |
| /** Creates a new instance of NamespaceFilter */ |
| ForeignContentFilter( Logger aLogger, OdfVersion aVersion, ForeignContentListener aForeignContentListener ) { |
| m_aLogger = aLogger; |
| m_aVersion = aVersion; |
| m_aForeignContentListener = aForeignContentListener; |
| |
| m_aAlienElementProcessContents = new Vector<Boolean>(); |
| m_aParagraphAncestorElements = new Vector<Boolean>(); |
| |
| m_aODFNamespaceSet = new HashSet<String>(); |
| m_aODFNamespaceSet.add( OdfDocumentNamespace.OFFICE.getUri() ); |
| m_aODFNamespaceSet.add( OdfDocumentNamespace.STYLE.getUri() ); |
| m_aODFNamespaceSet.add( OdfDocumentNamespace.TEXT.getUri() ); |
| m_aODFNamespaceSet.add( OdfDocumentNamespace.TABLE.getUri() ); |
| m_aODFNamespaceSet.add( OdfDocumentNamespace.DRAW.getUri() ); |
| m_aODFNamespaceSet.add( OdfDocumentNamespace.FO.getUri() ); |
| m_aODFNamespaceSet.add( OdfDocumentNamespace.DC.getUri() ); |
| m_aODFNamespaceSet.add( OdfDocumentNamespace.META.getUri() ); |
| m_aODFNamespaceSet.add( OdfDocumentNamespace.NUMBER.getUri() ); |
| m_aODFNamespaceSet.add( OdfDocumentNamespace.SVG.getUri() ); |
| m_aODFNamespaceSet.add( OdfDocumentNamespace.CHART.getUri() ); |
| m_aODFNamespaceSet.add( OdfDocumentNamespace.DR3D.getUri() ); |
| m_aODFNamespaceSet.add( OdfDocumentNamespace.FORM.getUri() ); |
| m_aODFNamespaceSet.add( OdfDocumentNamespace.PRESENTATION.getUri() ); |
| m_aODFNamespaceSet.add( OdfDocumentNamespace.SMIL.getUri() ); |
| m_aODFNamespaceSet.add( OdfDocumentNamespace.CONFIG.getUri() ); |
| m_aODFNamespaceSet.add( OdfDocumentNamespace.SCRIPT.getUri() ); |
| m_aODFNamespaceSet.add( OdfDocumentNamespace.XLINK.getUri() ); |
| m_aODFNamespaceSet.add( OdfDocumentNamespace.XFORMS.getUri() ); |
| if( m_aVersion.compareTo( OdfVersion.V1_2 ) >= 0 ) |
| { |
| m_aODFNamespaceSet.add( OdfDocumentNamespace.XHTML.getUri() ); |
| m_aODFNamespaceSet.add( OdfDocumentNamespace.GRDDL.getUri() ); |
| m_aODFNamespaceSet.add( OdfDocumentNamespace.DB.getUri() ); |
| m_aODFNamespaceSet.add( javax.xml.XMLConstants.XML_NS_URI ); |
| } |
| } |
| |
| |
| @Override |
| public void endElement(String aUri, String aLocalName, String aQName) throws SAXException { |
| if( isAlienNamespace(aUri) ) |
| { |
| m_aAlienElementProcessContents.removeElementAt( m_aAlienElementProcessContents.size()-1 ); |
| } |
| else |
| { |
| if( isProcessContent() ) |
| super.endElement(aUri,aLocalName,aQName); |
| } |
| } |
| |
| |
| @Override |
| public void startElement(String aUri, String aLocalName, String aQName, Attributes aAtts) throws SAXException |
| { |
| boolean bProcessContent = isProcessContent(); |
| |
| if( isAlienNamespace(aUri) ) |
| { |
| if( bProcessContent ) |
| { |
| String aProcessContentValue = aAtts.getValue( OFFICE_NAMESPACE_URI, PROCESS_CONTENT ); |
| if( m_aVersion.compareTo( OdfVersion.V1_2 ) >= 0 ) |
| { |
| bProcessContent = aProcessContentValue != null ? aProcessContentValue.equals(TRUE) : true; |
| } |
| else |
| { |
| bProcessContent = aProcessContentValue == null || aProcessContentValue.equals(TRUE); |
| } |
| |
| if( m_aForeignContentListener!= null ) |
| m_aForeignContentListener.foreignElementDetected(aUri, aLocalName, aQName, aAtts); |
| m_aLogger.logInfo( String.format("extension element <%s> found, element is ignored, element content is %s.",aQName,bProcessContent?"processed":"is ignored"), false); |
| } |
| m_aAlienElementProcessContents.addElement( bProcessContent ); |
| } |
| else if( bProcessContent ) |
| { |
| Attributes aOldAtts = aAtts; |
| |
| AttributesImpl aNewAtts = null; |
| int i = aOldAtts.getLength(); |
| while( i>0 ) { |
| --i; |
| String aAttrUri = aOldAtts.getURI(i); |
| if ( isAlienNamespace( aAttrUri ) ) { |
| if (aNewAtts == null) { |
| aNewAtts = new AttributesImpl(aOldAtts); |
| aAtts = aNewAtts; |
| } |
| if( m_aForeignContentListener!= null ) |
| m_aForeignContentListener.foreignAttributeDetected(aAttrUri, aOldAtts.getLocalName(i), aOldAtts.getQName(i), aOldAtts.getValue(i)); |
| m_aLogger.logInfo( String.format("extension attribute '%s' of element <%s> found and ignored.",aAtts.getQName(i),aQName), false); |
| aNewAtts.removeAttribute(i); |
| } |
| } |
| |
| boolean bParagraphAncestor = hasParagraphAncestorElement(); |
| bParagraphAncestor |= ((aLocalName.equals(P) || aLocalName.equals(H)) && aUri.equals(TEXT_NAMESPACE_URI)); |
| m_aParagraphAncestorElements.add(bParagraphAncestor); |
| |
| super.startElement(aUri, aLocalName, aQName, aAtts); |
| } |
| } |
| |
| |
| |
| private boolean isAlienNamespace( String aUri ) |
| { |
| return !m_aODFNamespaceSet.contains(aUri); |
| } |
| |
| private boolean isProcessContent() |
| { |
| return m_aAlienElementProcessContents.isEmpty() ? true : m_aAlienElementProcessContents.lastElement(); |
| } |
| |
| private boolean hasParagraphAncestorElement() |
| { |
| return m_aParagraphAncestorElements.isEmpty() ? false : m_aParagraphAncestorElements.lastElement(); |
| } |
| |
| @Override |
| public void characters(char[] aChars, int nStart, int nLength) throws SAXException { |
| if( isProcessContent() ) |
| super.characters(aChars, nStart, nLength); |
| } |
| |
| } |