1 38 package com.gargoylesoftware.htmlunit.javascript; 39 40 import com.gargoylesoftware.htmlunit.Assert; 41 import com.gargoylesoftware.htmlunit.BrowserVersion; 42 import java.io.InputStream; 43 import java.util.HashMap; 44 import java.util.Map; 45 import javax.xml.parsers.DocumentBuilder; 46 import javax.xml.parsers.DocumentBuilderFactory; 47 import org.apache.commons.logging.Log; 48 import org.apache.commons.logging.LogFactory; 49 import org.xml.sax.InputSource; 50 import org.xml.sax.SAXParseException; 51 import org.w3c.dom.Element; 52 import org.w3c.dom.Node; 53 54 60 public final class JavaScriptConfiguration { 61 private static org.w3c.dom.Document XmlDocument_; 62 private static final Object INITIALIZATION_LOCK = new Object(); 63 64 65 public static final int ENABLED = 1; 66 67 68 public static final int DISABLED = 2; 69 70 71 public static final int NOT_FOUND = 3; 72 73 private static Map ConfigurationMap_ = new HashMap(11); 74 75 76 private JavaScriptConfiguration() { 77 synchronized(INITIALIZATION_LOCK) { 78 if( XmlDocument_ == null ) { 79 XmlDocument_ = loadConfiguration(); 80 } 81 } 82 83 if( XmlDocument_ == null ) { 84 throw new IllegalStateException("Configuration was not initialized - see log for details"); 85 } 86 } 87 88 89 private org.w3c.dom.Document loadConfiguration() { 90 try { 91 final InputStream inputStream = getConfigurationFileAsStream(); 92 if( inputStream == null ) { 93 getLog().error("Unable to load JavaScriptConfiguration.xml"); 94 return null; 95 } 96 final InputSource inputSource = new InputSource(inputStream); 97 98 final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 99 factory.setNamespaceAware( true ); 100 factory.setValidating( false ); 101 102 final DocumentBuilder documentBuilder = factory.newDocumentBuilder(); 103 documentBuilder.setErrorHandler( new StrictErrorHandler() ); 104 105 return documentBuilder.parse( inputSource ); 106 } 107 catch( final SAXParseException parseException ) { 108 getLog().error( "line=[" + parseException.getLineNumber() 109 + "] columnNumber=[" + parseException.getColumnNumber() 110 + "] systemId=[" + parseException.getSystemId() 111 + "] publicId=[" + parseException.getPublicId() + "]", parseException ); 112 } 113 catch( final Exception e ) { 114 getLog().error("Error when loading JavascriptConfiguration.xml", e); 115 } 116 117 return null; 118 } 119 120 121 126 public static JavaScriptConfiguration getInstance( final BrowserVersion browserVersion ) { 127 JavaScriptConfiguration configuration 128 = (JavaScriptConfiguration)ConfigurationMap_.get(browserVersion); 129 130 if( configuration == null ) { 131 configuration = new JavaScriptConfiguration(); 132 ConfigurationMap_.put( browserVersion, configuration ); 133 } 134 return configuration; 135 } 136 137 138 private Log getLog() { 139 return LogFactory.getLog(getClass()); 140 } 141 142 143 private int getState( 144 final Class hostClass, 145 final String type, 146 final String typeName, 147 final String booleanAttributeName ) { 148 149 Assert.notNull("hostClass", hostClass); 150 Assert.notNull("typeName", typeName); 151 152 Element classElement = getClassElement(getClassName(hostClass)); 153 while( classElement != null ) { 154 155 final Element functionElement = getElementByTypeAndName(classElement, type, typeName); 156 if( functionElement != null ) { 157 if( booleanAttributeName == null ) { 158 return ENABLED; 159 } 160 else if( getBooleanAttribute(functionElement,booleanAttributeName ) ) { 161 return ENABLED; 162 } 163 else { 164 return DISABLED; 165 } 166 } 167 168 final String superClassName = classElement.getAttribute("extends"); 169 classElement = null; 170 if( superClassName != null && superClassName.length() != 0 ) { 171 classElement = getClassElement(superClassName); 172 } 173 } 174 175 return NOT_FOUND; 176 } 177 178 179 186 public int getReadablePropertyNameState( final Class hostClass, final String name ) { 187 return getState(hostClass, "property", name, "readable"); 188 } 189 190 191 198 public int getWritablePropertyNameState( final Class hostClass, final String name ) { 199 return getState(hostClass, "property", name, "writable"); 200 } 201 202 203 210 public int getFunctionNameState( final Class hostClass, final String name ) { 211 return getState(hostClass, "function", name, null); 212 } 213 214 215 private boolean getBooleanAttribute( final Element classElement, final String attributeName ) { 216 Assert.notNull("classElement", classElement); 217 Assert.notNull("attributeName", attributeName); 218 219 final String value = classElement.getAttribute(attributeName); 220 if( "true".equals(value) ) { 221 return true; 222 } 223 else if( "false".equals(value) ) { 224 return false; 225 } 226 else { 227 throw new IllegalStateException("Unexpected value for attribute [" 228 +attributeName+"] on element ["+classElement+"] value=["+value+"]"); 229 } 230 } 231 232 233 private InputStream getConfigurationFileAsStream() { 234 return getClass().getResourceAsStream("JavaScriptConfiguration.xml"); 235 } 236 237 238 private String getClassName( final Class hostClass ) { 239 Assert.notNull("hostClass", hostClass); 240 241 final String className = hostClass.getName(); 242 final int index = className.lastIndexOf("."); 243 if( index == -1 ) { 244 throw new IllegalArgumentException("hostClass does not contain a dot ["+className+"]"); 245 } 246 247 return className.substring( index + 1 ); 248 } 249 250 251 private Element getClassElement( final String className ) { 252 Node node = XmlDocument_.getDocumentElement().getFirstChild(); 253 while( node != null ) { 254 if( node instanceof Element ) { 255 final Element element = (Element)node; 256 if( element.getTagName().equals("class") && className.equals(element.getAttribute("name") )) { 257 return element; 258 } 259 } 260 node = node.getNextSibling(); 261 } 262 getLog().warn("Unexpected class ["+className+"]"); 263 return null; 264 } 265 266 267 private Element getElementByTypeAndName( final Element root, final String type, final String name ) { 268 Assert.notNull("type", type); 269 Assert.notNull("name", name); 270 271 Node node = root.getFirstChild(); 272 while( node != null ) { 273 if( node instanceof Element ) { 274 final Element element = (Element)node; 275 if( element.getTagName().equals(type) && name.equals(element.getAttribute("name") ) ) { 276 return element; 277 } 278 } 279 node = node.getNextSibling(); 280 } 281 return null; 282 } 283 } 284 | Popular Tags |