1 /* 2 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.xml.internal.xsom.util; 27 28 import com.sun.xml.internal.xsom.XSAnnotation; 29 import com.sun.xml.internal.xsom.parser.AnnotationContext; 30 import com.sun.xml.internal.xsom.parser.AnnotationParser; 31 import com.sun.xml.internal.xsom.parser.AnnotationParserFactory; 32 import javax.xml.XMLConstants; 33 import org.w3c.dom.Document; 34 import org.w3c.dom.Element; 35 import org.w3c.dom.Node; 36 import org.xml.sax.ContentHandler; 37 import org.xml.sax.EntityResolver; 38 import org.xml.sax.ErrorHandler; 39 40 import javax.xml.transform.TransformerConfigurationException; 41 import javax.xml.transform.dom.DOMResult; 42 import javax.xml.transform.sax.SAXTransformerFactory; 43 import javax.xml.transform.sax.TransformerHandler; 44 45 /** 46 * {@link AnnotationParserFactory} that parses annotations into a W3C DOM. 47 * 48 * <p> 49 * If you use this parser factory, you'll get {@link Element} that represents 50 * <xs:annotation> from {@link XSAnnotation#getAnnotation()}. 51 * 52 * <p> 53 * When multiple <xs:annotation>s are found for the given schema component, 54 * you'll see all <xs:appinfo>s and <xs:documentation>s combined under 55 * one <xs:annotation> element. 56 * 57 * @author Kohsuke Kawaguchi 58 */ 59 public class DomAnnotationParserFactory implements AnnotationParserFactory { 60 61 public AnnotationParser create() { 62 return new AnnotationParserImpl(); 63 } 64 65 public AnnotationParser create(boolean disableSecureProcessing) { 66 return new AnnotationParserImpl(disableSecureProcessing); 67 } 68 69 private static final ContextClassloaderLocal<SAXTransformerFactory> stf = new ContextClassloaderLocal<SAXTransformerFactory>() { 70 @Override 71 protected SAXTransformerFactory initialValue() throws Exception { 72 return (SAXTransformerFactory) SAXTransformerFactory.newInstance(); 73 } 74 }; 75 76 private static class AnnotationParserImpl extends AnnotationParser { 77 78 /** 79 * Identity transformer used to parse SAX into DOM. 80 */ 81 private final TransformerHandler transformer; 82 private DOMResult result; 83 84 AnnotationParserImpl() { 85 this(false); 86 } 87 88 AnnotationParserImpl(boolean disableSecureProcessing) { 89 try { 90 SAXTransformerFactory factory = stf.get(); 91 factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, disableSecureProcessing); 92 transformer = factory.newTransformerHandler(); 93 } catch (TransformerConfigurationException e) { 94 throw new Error(e); // impossible 95 } 96 } 97 98 public ContentHandler getContentHandler(AnnotationContext context, String parentElementName, ErrorHandler errorHandler, EntityResolver entityResolver) { 99 result = new DOMResult(); 100 transformer.setResult(result); 101 return transformer; 102 } 103 104 public Object getResult(Object existing) { 105 Document dom = (Document)result.getNode(); 106 Element e = dom.getDocumentElement(); 107 if(existing instanceof Element) { 108 // merge all the children 109 Element prev = (Element) existing; 110 Node anchor = e.getFirstChild(); 111 while(prev.getFirstChild()!=null) { 112 Node move = prev.getFirstChild(); 113 e.insertBefore(e.getOwnerDocument().adoptNode(move), anchor ); 114 } 115 } 116 return e; 117 } 118 } 119 }