Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/com/sun/beans/decoder/DocumentHandler.java
38923 views
/*1* Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/24package com.sun.beans.decoder;2526import com.sun.beans.finder.ClassFinder;2728import java.beans.ExceptionListener;2930import java.io.IOException;31import java.io.StringReader;3233import java.lang.ref.Reference;34import java.lang.ref.WeakReference;3536import java.util.ArrayList;37import java.util.HashMap;38import java.util.List;39import java.util.Map;40import java.security.AccessControlContext;41import java.security.AccessController;42import java.security.PrivilegedAction;4344import javax.xml.parsers.ParserConfigurationException;45import javax.xml.parsers.SAXParserFactory;4647import org.xml.sax.Attributes;48import org.xml.sax.InputSource;49import org.xml.sax.SAXException;50import org.xml.sax.helpers.DefaultHandler;5152import sun.misc.SharedSecrets;5354/**55* The main class to parse JavaBeans XML archive.56*57* @since 1.758*59* @author Sergey A. Malenkov60*61* @see ElementHandler62*/63public final class DocumentHandler extends DefaultHandler {64private final AccessControlContext acc = AccessController.getContext();65private final Map<String, Class<? extends ElementHandler>> handlers = new HashMap<>();66private final Map<String, Object> environment = new HashMap<>();67private final List<Object> objects = new ArrayList<>();6869private Reference<ClassLoader> loader;70private ExceptionListener listener;71private Object owner;7273private ElementHandler handler;7475/**76* Creates new instance of document handler.77*/78public DocumentHandler() {79setElementHandler("java", JavaElementHandler.class); // NON-NLS: the element name80setElementHandler("null", NullElementHandler.class); // NON-NLS: the element name81setElementHandler("array", ArrayElementHandler.class); // NON-NLS: the element name82setElementHandler("class", ClassElementHandler.class); // NON-NLS: the element name83setElementHandler("string", StringElementHandler.class); // NON-NLS: the element name84setElementHandler("object", ObjectElementHandler.class); // NON-NLS: the element name8586setElementHandler("void", VoidElementHandler.class); // NON-NLS: the element name87setElementHandler("char", CharElementHandler.class); // NON-NLS: the element name88setElementHandler("byte", ByteElementHandler.class); // NON-NLS: the element name89setElementHandler("short", ShortElementHandler.class); // NON-NLS: the element name90setElementHandler("int", IntElementHandler.class); // NON-NLS: the element name91setElementHandler("long", LongElementHandler.class); // NON-NLS: the element name92setElementHandler("float", FloatElementHandler.class); // NON-NLS: the element name93setElementHandler("double", DoubleElementHandler.class); // NON-NLS: the element name94setElementHandler("boolean", BooleanElementHandler.class); // NON-NLS: the element name9596// some handlers for new elements97setElementHandler("new", NewElementHandler.class); // NON-NLS: the element name98setElementHandler("var", VarElementHandler.class); // NON-NLS: the element name99setElementHandler("true", TrueElementHandler.class); // NON-NLS: the element name100setElementHandler("false", FalseElementHandler.class); // NON-NLS: the element name101setElementHandler("field", FieldElementHandler.class); // NON-NLS: the element name102setElementHandler("method", MethodElementHandler.class); // NON-NLS: the element name103setElementHandler("property", PropertyElementHandler.class); // NON-NLS: the element name104}105106/**107* Returns the class loader used to instantiate objects.108* If the class loader has not been explicitly set109* then {@code null} is returned.110*111* @return the class loader used to instantiate objects112*/113public ClassLoader getClassLoader() {114return (this.loader != null)115? this.loader.get()116: null;117}118119/**120* Sets the class loader used to instantiate objects.121* If the class loader is not set122* then default class loader will be used.123*124* @param loader a classloader to use125*/126public void setClassLoader(ClassLoader loader) {127this.loader = new WeakReference<ClassLoader>(loader);128}129130/**131* Returns the exception listener for parsing.132* The exception listener is notified133* when handler catches recoverable exceptions.134* If the exception listener has not been explicitly set135* then default exception listener is returned.136*137* @return the exception listener for parsing138*/139public ExceptionListener getExceptionListener() {140return this.listener;141}142143/**144* Sets the exception listener for parsing.145* The exception listener is notified146* when handler catches recoverable exceptions.147*148* @param listener the exception listener for parsing149*/150public void setExceptionListener(ExceptionListener listener) {151this.listener = listener;152}153154/**155* Returns the owner of this document handler.156*157* @return the owner of this document handler158*/159public Object getOwner() {160return this.owner;161}162163/**164* Sets the owner of this document handler.165*166* @param owner the owner of this document handler167*/168public void setOwner(Object owner) {169this.owner = owner;170}171172/**173* Returns the handler for the element with specified name.174*175* @param name the name of the element176* @return the corresponding element handler177*/178public Class<? extends ElementHandler> getElementHandler(String name) {179Class<? extends ElementHandler> type = this.handlers.get(name);180if (type == null) {181throw new IllegalArgumentException("Unsupported element: " + name);182}183return type;184}185186/**187* Sets the handler for the element with specified name.188*189* @param name the name of the element190* @param handler the corresponding element handler191*/192public void setElementHandler(String name, Class<? extends ElementHandler> handler) {193this.handlers.put(name, handler);194}195196/**197* Indicates whether the variable with specified identifier is defined.198*199* @param id the identifier200* @return @{code true} if the variable is defined;201* @{code false} otherwise202*/203public boolean hasVariable(String id) {204return this.environment.containsKey(id);205}206207/**208* Returns the value of the variable with specified identifier.209*210* @param id the identifier211* @return the value of the variable212*/213public Object getVariable(String id) {214if (!this.environment.containsKey(id)) {215throw new IllegalArgumentException("Unbound variable: " + id);216}217return this.environment.get(id);218}219220/**221* Sets new value of the variable with specified identifier.222*223* @param id the identifier224* @param value new value of the variable225*/226public void setVariable(String id, Object value) {227this.environment.put(id, value);228}229230/**231* Returns the array of readed objects.232*233* @return the array of readed objects234*/235public Object[] getObjects() {236return this.objects.toArray();237}238239/**240* Adds the object to the list of readed objects.241*242* @param object the object that is readed from XML document243*/244void addObject(Object object) {245this.objects.add(object);246}247248/**249* Disables any external entities.250*/251@Override252public InputSource resolveEntity(String publicId, String systemId) {253return new InputSource(new StringReader(""));254}255256/**257* Prepares this handler to read objects from XML document.258*/259@Override260public void startDocument() {261this.objects.clear();262this.handler = null;263}264265/**266* Parses opening tag of XML element267* using corresponding element handler.268*269* @param uri the namespace URI, or the empty string270* if the element has no namespace URI or271* if namespace processing is not being performed272* @param localName the local name (without prefix), or the empty string273* if namespace processing is not being performed274* @param qName the qualified name (with prefix), or the empty string275* if qualified names are not available276* @param attributes the attributes attached to the element277*/278@Override279public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {280ElementHandler parent = this.handler;281try {282this.handler = getElementHandler(qName).newInstance();283this.handler.setOwner(this);284this.handler.setParent(parent);285}286catch (Exception exception) {287throw new SAXException(exception);288}289for (int i = 0; i < attributes.getLength(); i++)290try {291String name = attributes.getQName(i);292String value = attributes.getValue(i);293this.handler.addAttribute(name, value);294}295catch (RuntimeException exception) {296handleException(exception);297}298299this.handler.startElement();300}301302/**303* Parses closing tag of XML element304* using corresponding element handler.305*306* @param uri the namespace URI, or the empty string307* if the element has no namespace URI or308* if namespace processing is not being performed309* @param localName the local name (without prefix), or the empty string310* if namespace processing is not being performed311* @param qName the qualified name (with prefix), or the empty string312* if qualified names are not available313*/314@Override315public void endElement(String uri, String localName, String qName) {316try {317this.handler.endElement();318}319catch (RuntimeException exception) {320handleException(exception);321}322finally {323this.handler = this.handler.getParent();324}325}326327/**328* Parses character data inside XML element.329*330* @param chars the array of characters331* @param start the start position in the character array332* @param length the number of characters to use333*/334@Override335public void characters(char[] chars, int start, int length) {336if (this.handler != null) {337try {338while (0 < length--) {339this.handler.addCharacter(chars[start++]);340}341}342catch (RuntimeException exception) {343handleException(exception);344}345}346}347348/**349* Handles an exception using current exception listener.350*351* @param exception an exception to handle352* @see #setExceptionListener353*/354public void handleException(Exception exception) {355if (this.listener == null) {356throw new IllegalStateException(exception);357}358this.listener.exceptionThrown(exception);359}360361/**362* Starts parsing of the specified input source.363*364* @param input the input source to parse365*/366public void parse(final InputSource input) {367if ((this.acc == null) && (null != System.getSecurityManager())) {368throw new SecurityException("AccessControlContext is not set");369}370AccessControlContext stack = AccessController.getContext();371SharedSecrets.getJavaSecurityAccess().doIntersectionPrivilege(new PrivilegedAction<Void>() {372public Void run() {373try {374SAXParserFactory.newInstance().newSAXParser().parse(input, DocumentHandler.this);375}376catch (ParserConfigurationException exception) {377handleException(exception);378}379catch (SAXException wrapper) {380Exception exception = wrapper.getException();381if (exception == null) {382exception = wrapper;383}384handleException(exception);385}386catch (IOException exception) {387handleException(exception);388}389return null;390}391}, stack, this.acc);392}393394/**395* Resolves class by name using current class loader.396* This method handles exception using current exception listener.397*398* @param name the name of the class399* @return the object that represents the class400*/401public Class<?> findClass(String name) {402try {403return ClassFinder.resolveClass(name, getClassLoader());404}405catch (ClassNotFoundException exception) {406handleException(exception);407return null;408}409}410}411412413