1.1 --- a/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/UnmarshallingContext.java Thu Aug 08 10:10:38 2013 -0700 1.2 +++ b/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/UnmarshallingContext.java Fri Aug 23 09:57:21 2013 +0100 1.3 @@ -1,5 +1,5 @@ 1.4 /* 1.5 - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. 1.6 + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 1.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 * 1.9 * This code is free software; you can redistribute it and/or modify it 1.10 @@ -35,6 +35,8 @@ 1.11 import java.util.List; 1.12 import java.util.Map; 1.13 import java.util.concurrent.Callable; 1.14 +import java.util.logging.Level; 1.15 +import java.util.logging.Logger; 1.16 1.17 import javax.xml.XMLConstants; 1.18 import javax.xml.bind.JAXBElement; 1.19 @@ -51,6 +53,7 @@ 1.20 import com.sun.istack.internal.Nullable; 1.21 import com.sun.istack.internal.SAXParseException2; 1.22 import com.sun.xml.internal.bind.IDResolver; 1.23 +import com.sun.xml.internal.bind.Util; 1.24 import com.sun.xml.internal.bind.api.AccessorException; 1.25 import com.sun.xml.internal.bind.api.ClassResolver; 1.26 import com.sun.xml.internal.bind.unmarshaller.InfosetScanner; 1.27 @@ -59,6 +62,8 @@ 1.28 import com.sun.xml.internal.bind.v2.runtime.Coordinator; 1.29 import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl; 1.30 import com.sun.xml.internal.bind.v2.runtime.JaxBeanInfo; 1.31 +import java.util.logging.Level; 1.32 +import java.util.logging.Logger; 1.33 1.34 import org.xml.sax.ErrorHandler; 1.35 import org.xml.sax.SAXException; 1.36 @@ -76,6 +81,8 @@ 1.37 public final class UnmarshallingContext extends Coordinator 1.38 implements NamespaceContext, ValidationEventHandler, ErrorHandler, XmlVisitor, XmlVisitor.TextPredictor { 1.39 1.40 + private static final Logger logger = Logger.getLogger(UnmarshallingContext.class.getName()); 1.41 + 1.42 /** 1.43 * Root state. 1.44 */ 1.45 @@ -177,6 +184,14 @@ 1.46 public @Nullable ClassLoader classLoader; 1.47 1.48 /** 1.49 + * The variable introduced to avoid reporting n^10 similar errors. 1.50 + * After error is reported counter is decremented. When it became 0 - errors should not be reported any more. 1.51 + * 1.52 + * volatile is required to ensure that concurrent threads will see changed value 1.53 + */ 1.54 + private static volatile int errorsCounter = 10; 1.55 + 1.56 + /** 1.57 * State information for each element. 1.58 */ 1.59 public final class State { 1.60 @@ -260,21 +275,32 @@ 1.61 return UnmarshallingContext.this; 1.62 } 1.63 1.64 + @SuppressWarnings("LeakingThisInConstructor") 1.65 private State(State prev) { 1.66 this.prev = prev; 1.67 - if(prev!=null) 1.68 + if (prev!=null) { 1.69 prev.next = this; 1.70 + } 1.71 } 1.72 1.73 private void push() { 1.74 - if(next==null) 1.75 + if (logger.isLoggable(Level.FINEST)) { 1.76 + logger.log(Level.FINEST, "State.push"); 1.77 + } 1.78 + if (next==null) { 1.79 + assert current == this; 1.80 allocateMoreStates(); 1.81 + } 1.82 + nil = false; 1.83 State n = next; 1.84 n.numNsDecl = nsLen; 1.85 current = n; 1.86 } 1.87 1.88 private void pop() { 1.89 + if (logger.isLoggable(Level.FINEST)) { 1.90 + logger.log(Level.FINEST, "State.pop"); 1.91 + } 1.92 assert prev!=null; 1.93 loader = null; 1.94 nil = false; 1.95 @@ -381,8 +407,9 @@ 1.96 assert current.next==null; 1.97 1.98 State s = current; 1.99 - for( int i=0; i<8; i++ ) 1.100 + for (int i=0; i<8; i++) { 1.101 s = new State(s); 1.102 + } 1.103 } 1.104 1.105 public void clearStates() { 1.106 @@ -436,6 +463,7 @@ 1.107 } 1.108 } 1.109 1.110 + @Override 1.111 public void startDocument(LocatorEx locator, NamespaceContext nsContext) throws SAXException { 1.112 if(locator!=null) 1.113 this.locator = locator; 1.114 @@ -449,8 +477,6 @@ 1.115 isUnmarshalInProgress = true; 1.116 nsLen=0; 1.117 1.118 - setThreadAffinity(); 1.119 - 1.120 if(expectedType!=null) 1.121 root.loader = EXPECTED_TYPE_ROOT_LOADER; 1.122 else 1.123 @@ -459,6 +485,7 @@ 1.124 idResolver.startDocument(this); 1.125 } 1.126 1.127 + @Override 1.128 public void startElement(TagName tagName) throws SAXException { 1.129 pushCoordinator(); 1.130 try { 1.131 @@ -486,6 +513,7 @@ 1.132 current.loader.startElement(current,tagName); 1.133 } 1.134 1.135 + @Override 1.136 public void text(CharSequence pcdata) throws SAXException { 1.137 State cur = current; 1.138 pushCoordinator(); 1.139 @@ -502,6 +530,7 @@ 1.140 } 1.141 } 1.142 1.143 + @Override 1.144 public final void endElement(TagName tagName) throws SAXException { 1.145 pushCoordinator(); 1.146 try { 1.147 @@ -526,6 +555,7 @@ 1.148 } 1.149 } 1.150 1.151 + @Override 1.152 public void endDocument() throws SAXException { 1.153 runPatchers(); 1.154 idResolver.endDocument(); 1.155 @@ -537,14 +567,13 @@ 1.156 1.157 // at the successful completion, scope must be all closed 1.158 assert root==current; 1.159 - 1.160 - resetThreadAffinity(); 1.161 } 1.162 1.163 /** 1.164 * You should be always calling this through {@link TextPredictor}. 1.165 */ 1.166 @Deprecated 1.167 + @Override 1.168 public boolean expectText() { 1.169 return current.loader.expectText; 1.170 } 1.171 @@ -553,10 +582,12 @@ 1.172 * You should be always getting {@link TextPredictor} from {@link XmlVisitor}. 1.173 */ 1.174 @Deprecated 1.175 + @Override 1.176 public TextPredictor getPredictor() { 1.177 return this; 1.178 } 1.179 1.180 + @Override 1.181 public UnmarshallingContext getContext() { 1.182 return this; 1.183 } 1.184 @@ -650,6 +681,7 @@ 1.185 event.getLinkedException() ) ); 1.186 } 1.187 1.188 + @Override 1.189 public boolean handleEvent(ValidationEvent event) { 1.190 try { 1.191 // if the handler says "abort", we will not return the object. 1.192 @@ -680,6 +712,7 @@ 1.193 handleEvent(new ValidationEventImpl(ValidationEvent.ERROR,msg,locator.getLocation())); 1.194 } 1.195 1.196 + @Override 1.197 protected ValidationEventLocator getLocation() { 1.198 return locator.getLocation(); 1.199 } 1.200 @@ -801,6 +834,7 @@ 1.201 private String[] nsBind = new String[16]; 1.202 private int nsLen=0; 1.203 1.204 + @Override 1.205 public void startPrefixMapping( String prefix, String uri ) { 1.206 if(nsBind.length==nsLen) { 1.207 // expand the buffer 1.208 @@ -811,6 +845,7 @@ 1.209 nsBind[nsLen++] = prefix; 1.210 nsBind[nsLen++] = uri; 1.211 } 1.212 + @Override 1.213 public void endPrefixMapping( String prefix ) { 1.214 nsLen-=2; 1.215 } 1.216 @@ -868,6 +903,7 @@ 1.217 1.218 // NamespaceContext2 implementation 1.219 // 1.220 + @Override 1.221 public Iterator<String> getPrefixes(String uri) { 1.222 // TODO: could be implemented much faster 1.223 // wrap it into unmodifiable list so that the remove method 1.224 @@ -899,6 +935,7 @@ 1.225 return a; 1.226 } 1.227 1.228 + @Override 1.229 public String getPrefix(String uri) { 1.230 if( uri==null ) 1.231 throw new IllegalArgumentException(); 1.232 @@ -919,6 +956,7 @@ 1.233 return null; 1.234 } 1.235 1.236 + @Override 1.237 public String getNamespaceURI(String prefix) { 1.238 if (prefix == null) 1.239 throw new IllegalArgumentException(); 1.240 @@ -1059,6 +1097,7 @@ 1.241 return getInstance().getJAXBContext().getValidRootNames(); 1.242 } 1.243 1.244 + @Override 1.245 public void receive(State state, Object o) { 1.246 if(state.backup!=null) { 1.247 ((JAXBElement<Object>)state.backup).setValue(o); 1.248 @@ -1095,6 +1134,7 @@ 1.249 state.loader = new XsiNilLoader(context.expectedType.getLoader(null,true)); 1.250 } 1.251 1.252 + @Override 1.253 public void receive(State state, Object o) { 1.254 JAXBElement e = (JAXBElement)state.target; 1.255 e.setValue(o); 1.256 @@ -1233,4 +1273,27 @@ 1.257 return null; 1.258 } 1.259 1.260 + /** 1.261 + * Based on current {@link Logger} {@link Level} and errorCounter value determines if error should be reported. 1.262 + * 1.263 + * If the method called and return true it is expected that error will be reported. And that's why 1.264 + * errorCounter is automatically decremented during the check. 1.265 + * 1.266 + * NOT THREAD SAFE!!! In case of heave concurrency access several additional errors could be reported. It's not expected to be the 1.267 + * problem. Otherwise add synchronization here. 1.268 + * 1.269 + * @return true in case if {@link Level#FINEST} is set OR we haven't exceed errors reporting limit. 1.270 + */ 1.271 + public boolean shouldErrorBeReported() throws SAXException { 1.272 + if (logger.isLoggable(Level.FINEST)) 1.273 + return true; 1.274 + 1.275 + if (errorsCounter >= 0) { 1.276 + --errorsCounter; 1.277 + if (errorsCounter == 0) // it's possible to miss this because of concurrency. If required add synchronization here 1.278 + handleEvent(new ValidationEventImpl(ValidationEvent.WARNING, Messages.ERRORS_LIMIT_EXCEEDED.format(), 1.279 + getLocator().getLocation(), null), true); 1.280 + } 1.281 + return errorsCounter >= 0; 1.282 + } 1.283 }