Java tutorial
/* * Copyright (c) 2002-2016 Gargoyle Software Inc. * * 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 * * 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 com.gargoylesoftware.htmlunit.javascript; import java.lang.reflect.Method; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import net.sourceforge.htmlunit.corejs.javascript.Context; import net.sourceforge.htmlunit.corejs.javascript.FunctionObject; import net.sourceforge.htmlunit.corejs.javascript.Scriptable; import net.sourceforge.htmlunit.corejs.javascript.ScriptableObject; /** * Base class for Rhino host objects in HtmlUnit (not bound to a DOM node). * * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a> * @author David K. Taylor * @author Marc Guillemot * @author Chris Erskine * @author Daniel Gredler * @author Ahmed Ashour * @author Ronald Brill */ public class HtmlUnitScriptable extends ScriptableObject { private static final Log LOG = LogFactory.getLog(HtmlUnitScriptable.class); private String className_; /** * Returns the JavaScript class name. * @return the JavaScript class name */ @Override public String getClassName() { if (className_ != null) { return className_; } if (getPrototype() != null) { return getPrototype().getClassName(); } String className = getClass().getSimpleName(); if (className.isEmpty()) { // for anonymous class className = getClass().getSuperclass().getSimpleName(); } return className; } /** * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.</span><br> * * Sets the class name. * @param className the class name. */ public void setClassName(final String className) { className_ = className; } /** * {@inheritDoc} * Same as base implementation, but includes all methods inherited from super classes as well. */ @Override public void defineProperty(final String propertyName, final Class<?> clazz, int attributes) { final int length = propertyName.length(); if (length == 0) { throw new IllegalArgumentException(); } final char[] buf = new char[3 + length]; propertyName.getChars(0, length, buf, 3); buf[3] = Character.toUpperCase(buf[3]); buf[0] = 'g'; buf[1] = 'e'; buf[2] = 't'; final String getterName = new String(buf); buf[0] = 's'; final String setterName = new String(buf); final Method[] methods = clazz.getMethods(); final Method getter = findMethod(methods, getterName); final Method setter = findMethod(methods, setterName); if (setter == null) { attributes |= ScriptableObject.READONLY; } defineProperty(propertyName, null, getter, setter, attributes); } /** * {@inheritDoc} * Same as base implementation, but includes all methods inherited from super classes as well. */ @Override public void defineFunctionProperties(final String[] names, final Class<?> clazz, final int attributes) { final Method[] methods = clazz.getMethods(); for (final String name : names) { final Method method = findMethod(methods, name); if (method == null) { throw Context.reportRuntimeError("Method \"" + name + "\" not found in \"" + clazz.getName() + '"'); } final FunctionObject f = new FunctionObject(name, method, this); defineProperty(name, f, attributes); } } /** * Returns the method with the specified name. */ private static Method findMethod(final Method[] methods, final String name) { for (Method m : methods) { if (m.getName().equals(name)) { return m; } } return null; } /** * {@inheritDoc} */ @Override public void setParentScope(final Scriptable m) { final Scriptable oldScope = getParentScope(); super.setParentScope(m); final Scriptable topLevelScope = getTopLevelScope(this); if (topLevelScope.getParentScope() != null) { LOG.warn("Detected cycle in parent scopes for window: " + this + ", ignoring the call of this setter."); super.setParentScope(oldScope); return; } } /** * {@inheritDoc} */ @Override public Object getDefaultValue(final Class<?> typeHint) { return "[object " + getClassName() + "]"; } }