org.htmlunit.html.HtmlObject Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xlt Show documentation
Show all versions of xlt Show documentation
XLT (Xceptance LoadTest) is an extensive load and performance test tool developed and maintained by Xceptance.
/*
* Copyright (c) 2002-2024 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
* https://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 org.htmlunit.html;
import static org.htmlunit.BrowserVersionFeatures.JS_HTML_OBJECT_VALIDITYSTATE_ISVALID_IGNORES_CUSTOM_ERROR;
import java.applet.Applet;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.htmlunit.AppletConfirmHandler;
import org.htmlunit.FailingHttpStatusCodeException;
import org.htmlunit.SgmlPage;
import org.htmlunit.WebClient;
import org.htmlunit.WebRequest;
import org.htmlunit.WebResponse;
import org.htmlunit.html.applets.AppletClassLoader;
import org.htmlunit.html.applets.AppletStubImpl;
import org.htmlunit.javascript.host.html.HTMLObjectElement;
import org.htmlunit.util.UrlUtils;
import org.htmlunit.xml.XmlPage;
/**
* Wrapper for the HTML element "object".
*
* @author Mike Bowler
* @author David K. Taylor
* @author Christian Sell
* @author Ahmed Ashour
* @author Ronald Brill
* @author Frank Danek
*/
public class HtmlObject extends HtmlElement implements ValidatableElement {
private static final Log LOG = LogFactory.getLog(HtmlObject.class);
private static final String APPLET_TYPE = "application/x-java-applet";
private static final String ARCHIVE = "archive";
private static final String CACHE_ARCHIVE = "cache_archive";
private static final String CODEBASE = "codebase";
/** The HTML tag represented by this element. */
public static final String TAG_NAME = "object";
private Applet applet_;
private String customValidity_;
/**
* Creates an instance of HtmlObject
*
* @param qualifiedName the qualified name of the element type to instantiate
* @param page the HtmlPage that contains this element
* @param attributes the initial attributes
*/
HtmlObject(final String qualifiedName, final SgmlPage page,
final Map attributes) {
super(qualifiedName, page, attributes);
}
/**
* Returns the value of the attribute {@code declare}. Refer to the
* HTML 4.01
* documentation for details on the use of this attribute.
*
* @return the value of the attribute {@code declare}
* or an empty string if that attribute isn't defined.
*/
public final String getDeclareAttribute() {
return getAttributeDirect("declare");
}
/**
* Returns the value of the attribute {@code classid}. Refer to the
* HTML 4.01
* documentation for details on the use of this attribute.
*
* @return the value of the attribute {@code classid}
* or an empty string if that attribute isn't defined.
*/
public final String getClassIdAttribute() {
return getAttributeDirect("classid");
}
/**
* Returns the value of the attribute "codebase". Refer to the
* HTML 4.01
* documentation for details on the use of this attribute.
*
* @return the value of the attribute "codebase"
* or an empty string if that attribute isn't defined.
*/
public final String getCodebaseAttribute() {
return getAttributeDirect("codebase");
}
/**
* Returns the value of the attribute {@code data}. Refer to the
* HTML 4.01
* documentation for details on the use of this attribute.
*
* @return the value of the attribute {@code data}
* or an empty string if that attribute isn't defined.
*/
public final String getDataAttribute() {
return getAttributeDirect("data");
}
/**
* Returns the value of the attribute {@code type}. Refer to the
* HTML 4.01
* documentation for details on the use of this attribute.
*
* @return the value of the attribute {@code type}
* or an empty string if that attribute isn't defined.
*/
public final String getTypeAttribute() {
return getAttributeDirect(TYPE_ATTRIBUTE);
}
/**
* Returns the value of the attribute "codetype". Refer to the
* HTML 4.01
* documentation for details on the use of this attribute.
*
* @return the value of the attribute "codetype"
* or an empty string if that attribute isn't defined.
*/
public final String getCodeTypeAttribute() {
return getAttributeDirect("codetype");
}
/**
* Returns the value of the attribute {@code archive}. Refer to the
* HTML 4.01
* documentation for details on the use of this attribute.
*
* @return the value of the attribute {@code archive}
* or an empty string if that attribute isn't defined.
*/
public final String getArchiveAttribute() {
return getAttributeDirect("archive");
}
/**
* Returns the value of the attribute {@code standby}. Refer to the
* HTML 4.01
* documentation for details on the use of this attribute.
*
* @return the value of the attribute {@code standby}
* or an empty string if that attribute isn't defined.
*/
public final String getStandbyAttribute() {
return getAttributeDirect("standby");
}
/**
* Returns the value of the attribute {@code height}. Refer to the
* HTML 4.01
* documentation for details on the use of this attribute.
*
* @return the value of the attribute {@code height}
* or an empty string if that attribute isn't defined.
*/
public final String getHeightAttribute() {
return getAttributeDirect("height");
}
/**
* Returns the value of the attribute {@code width}. Refer to the
* HTML 4.01
* documentation for details on the use of this attribute.
*
* @return the value of the attribute {@code width}
* or an empty string if that attribute isn't defined.
*/
public final String getWidthAttribute() {
return getAttributeDirect("width");
}
/**
* Returns the value of the attribute {@code usemap}. Refer to the
* HTML 4.01
* documentation for details on the use of this attribute.
*
* @return the value of the attribute {@code usemap}
* or an empty string if that attribute isn't defined.
*/
public final String getUseMapAttribute() {
return getAttributeDirect("usemap");
}
/**
* Returns the value of the attribute {@code name}. Refer to the
* HTML 4.01
* documentation for details on the use of this attribute.
*
* @return the value of the attribute {@code name}
* or an empty string if that attribute isn't defined.
*/
public final String getNameAttribute() {
return getAttributeDirect(NAME_ATTRIBUTE);
}
/**
* Returns the value of the attribute {@code tabindex}. Refer to the
* HTML 4.01
* documentation for details on the use of this attribute.
*
* @return the value of the attribute {@code tabindex}
* or an empty string if that attribute isn't defined.
*/
public final String getTabIndexAttribute() {
return getAttributeDirect("tabindex");
}
/**
* Returns the value of the attribute {@code align}. Refer to the
* HTML 4.01
* documentation for details on the use of this attribute.
*
* @return the value of the attribute {@code align}
* or an empty string if that attribute isn't defined.
*/
public final String getAlignAttribute() {
return getAttributeDirect("align");
}
/**
* Returns the value of the attribute {@code border}. Refer to the
* HTML 4.01
* documentation for details on the use of this attribute.
*
* @return the value of the attribute {@code border}
* or an empty string if that attribute isn't defined.
*/
public final String getBorderAttribute() {
return getAttributeDirect("border");
}
/**
* Returns the value of the attribute {@code hspace}. Refer to the
* HTML 4.01
* documentation for details on the use of this attribute.
*
* @return the value of the attribute {@code hspace}
* or an empty string if that attribute isn't defined.
*/
public final String getHspaceAttribute() {
return getAttributeDirect("hspace");
}
/**
* Returns the value of the attribute {@code vspace}. Refer to the
* HTML 4.01
* documentation for details on the use of this attribute.
*
* @return the value of the attribute {@code vspace}
* or an empty string if that attribute isn't defined.
*/
public final String getVspaceAttribute() {
return getAttributeDirect("vspace");
}
/**
* Initialize the ActiveX(Mock).
* {@inheritDoc}
*/
@Override
public void onAllChildrenAddedToPage(final boolean postponed) {
if (getOwnerDocument() instanceof XmlPage) {
return;
}
if (LOG.isDebugEnabled()) {
LOG.debug("Object node added: " + asXml());
}
final String clsId = getClassIdAttribute();
if (ATTRIBUTE_NOT_DEFINED != clsId && getPage().getWebClient().isJavaScriptEngineEnabled()) {
((HTMLObjectElement) getScriptableObject()).setClassid(clsId);
}
}
/**
* {@inheritDoc}
*/
@Override
public DisplayStyle getDefaultStyleDisplay() {
return DisplayStyle.INLINE;
}
/**
* Gets the applet referenced by this tag. Instantiates it if necessary.
*
* @return the applet or null, if the installed AppletConfirmHandler
* prohibits this applet
* @throws IOException in case of problem
*/
public Applet getApplet() throws IOException {
setupAppletIfNeeded();
return applet_;
}
/**
* Download the associated content specified in the code attribute.
*
* @throws IOException if an error occurs while downloading the content
*/
@SuppressWarnings("unchecked")
private synchronized void setupAppletIfNeeded() throws IOException {
if (applet_ != null) {
return;
}
if (StringUtils.isBlank(getTypeAttribute()) || !getTypeAttribute().startsWith(APPLET_TYPE)) {
return;
}
final HashMap params = new HashMap<>();
params.put(NAME_ATTRIBUTE, getNameAttribute());
params.put("height", getHeightAttribute());
params.put("width", getWidthAttribute());
final DomNodeList paramTags = getElementsByTagName("param");
for (final HtmlElement paramTag : paramTags) {
final HtmlParameter parameter = (HtmlParameter) paramTag;
params.put(parameter.getNameAttribute(), parameter.getValueAttribute());
}
if (StringUtils.isEmpty(params.get(CODEBASE)) && StringUtils.isNotEmpty(getCodebaseAttribute())) {
params.put(CODEBASE, getCodebaseAttribute());
}
if (StringUtils.isEmpty(params.get(ARCHIVE)) && StringUtils.isNotEmpty(getArchiveAttribute())) {
params.put(ARCHIVE, getArchiveAttribute());
}
final HtmlPage page = (HtmlPage) getPage();
final WebClient webclient = page.getWebClient();
final AppletConfirmHandler handler = webclient.getAppletConfirmHandler();
if (null != handler && !handler.confirm(this)) {
return;
}
String appletClassName = getAttributeDirect("code");
if (StringUtils.isEmpty(appletClassName)) {
appletClassName = params.get("code");
}
if (appletClassName.endsWith(".class")) {
appletClassName = appletClassName.substring(0, appletClassName.length() - 6);
}
try (AppletClassLoader appletClassLoader =
new AppletClassLoader(getPage().getEnclosingWindow().getScriptableObject(),
Thread.currentThread().getContextClassLoader())) {
final String documentUrl = page.getUrl().toExternalForm();
String baseUrl = UrlUtils.resolveUrl(documentUrl, ".");
final String codebaseProperty = params.get(CODEBASE);
if (StringUtils.isNotEmpty(codebaseProperty)) {
// codebase can be relative to the page
baseUrl = UrlUtils.resolveUrl(baseUrl, codebaseProperty);
}
if (!baseUrl.endsWith("/")) {
baseUrl = baseUrl + "/";
}
// check archive
List archiveUrls = new ArrayList<>();
String[] archives = org.htmlunit.util.StringUtils.splitAtComma(params.get(ARCHIVE));
if (null != archives) {
for (final String tmpArchive : archives) {
final String tempUrl = UrlUtils.resolveUrl(baseUrl, tmpArchive.trim());
final URL archiveUrl = UrlUtils.toUrlUnsafe(tempUrl);
appletClassLoader.addArchiveToClassPath(archiveUrl);
archiveUrls.add(archiveUrl);
}
}
archives = org.htmlunit.util.StringUtils.splitAtComma(params.get(CACHE_ARCHIVE));
if (null != archives) {
for (final String tmpArchive : archives) {
final String tempUrl = UrlUtils.resolveUrl(baseUrl, tmpArchive.trim());
final URL archiveUrl = UrlUtils.toUrlUnsafe(tempUrl);
appletClassLoader.addArchiveToClassPath(archiveUrl);
archiveUrls.add(archiveUrl);
}
}
archiveUrls = Collections.unmodifiableList(archiveUrls);
// no archive attribute, single class
if (archiveUrls.isEmpty()) {
final String tempUrl = UrlUtils.resolveUrl(baseUrl, getAttributeDirect("code"));
final URL classUrl = UrlUtils.toUrlUnsafe(tempUrl);
final WebResponse response = webclient.loadWebResponse(new WebRequest(classUrl));
try {
webclient.throwFailingHttpStatusCodeExceptionIfNecessary(response);
appletClassLoader.addClassToClassPath(appletClassName, response);
}
catch (final FailingHttpStatusCodeException e) {
// that is what the browser does, the applet only fails, if
// the main class is not loadable
LOG.error(e.getMessage(), e);
}
}
try {
final Class