All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.gargoylesoftware.htmlunit.html.HtmlImage Maven / Gradle / Ivy

Go to download

Vaadin is a web application framework for Rich Internet Applications (RIA). Vaadin enables easy development and maintenance of fast and secure rich web applications with a stunning look and feel and a wide browser support. It features a server-side architecture with the majority of the logic running on the server. Ajax technology is used at the browser-side to ensure a rich and interactive user experience.

There is a newer version: 1.2.0
Show newest version
/*
 * Copyright (c) 2002-2011 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.html;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Iterator;
import java.util.Map;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpStatus;

import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.SgmlPage;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.WebResponse;
import com.gargoylesoftware.htmlunit.javascript.PostponedAction;
import com.gargoylesoftware.htmlunit.javascript.host.Event;
import com.gargoylesoftware.htmlunit.javascript.host.Node;

/**
 * Wrapper for the HTML element "img".
 *
 * @version $Revision: 6204 $
 * @author Mike Bowler
 * @author David K. Taylor
 * @author Christian Sell
 * @author Ahmed Ashour
 * @author Knut Johannes Dahle
 */
public class HtmlImage extends HtmlElement {

    private static final Log LOG = LogFactory.getLog(HtmlImage.class);

    /** The HTML tag represented by this element. */
    public static final String TAG_NAME = "img";

    private int lastClickX_;
    private int lastClickY_;
    private WebResponse imageWebResponse_;
    private ImageReader imageReader_;
    private boolean downloaded_;
    private boolean onloadInvoked_;

    /**
     * Creates a new instance.
     *
     * @param namespaceURI the URI that identifies an XML namespace
     * @param qualifiedName the qualified name of the element type to instantiate
     * @param page the page that contains this element
     * @param attributes the initial attributes
     */
    HtmlImage(final String namespaceURI, final String qualifiedName, final SgmlPage page,
            final Map attributes) {
        super(namespaceURI, qualifiedName, page, attributes);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void onAddedToPage() {
        doOnLoad();
        super.onAddedToPage();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setAttributeNS(final String namespaceURI, final String qualifiedName, final String value) {
        if ("src".equals(qualifiedName) && value != ATTRIBUTE_NOT_DEFINED && getPage() instanceof HtmlPage) {
            final String oldValue = getAttributeNS(namespaceURI, qualifiedName);
            if (!oldValue.equals(value)) {
                // onload handlers may need to be invoked again, and a new image may need to be downloaded
                onloadInvoked_ = false;
                downloaded_ = false;
            }
        }
        super.setAttributeNS(namespaceURI, qualifiedName, value);
    }

    /**
     * 

INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.

* *

Executes this element's onload handler if it has one. This method also downloads the image * if this element has an onload handler (prior to invoking said handler), because applications * sometimes use images to send information to the server and use the onload handler to get notified * when the information has been received by the server.

* *

See here and * here for the discussion which * lead up to this method.

* *

This method may be called multiple times, but will only attempt to execute the onload * handler the first time it is invoked.

*/ public void doOnLoad() { if (!(getPage() instanceof HtmlPage)) { return; // nothing to do if embedded in XML code } else if (onloadInvoked_) { return; } onloadInvoked_ = true; final HtmlPage htmlPage = (HtmlPage) getPage(); if (hasEventHandlers("onload")) { // An onload handler is defined; we need to download the image and then call the onload handler. boolean ok; try { downloadImageIfNeeded(); final int i = imageWebResponse_.getStatusCode(); ok = (i >= HttpStatus.SC_OK && i < HttpStatus.SC_MULTIPLE_CHOICES) || i == HttpStatus.SC_USE_PROXY; } catch (final IOException e) { ok = false; } // If the download was a success, trigger the onload handler. if (ok) { final Event event = new Event(this, Event.TYPE_LOAD); final Node scriptObject = (Node) getScriptObject(); final PostponedAction action = new PostponedAction(getPage()) { @Override public void execute() throws Exception { scriptObject.executeEvent(event); } }; final String readyState = htmlPage.getReadyState(); if (READY_STATE_LOADING.equals(readyState)) { htmlPage.addAfterLoadAction(action); } else { htmlPage.getWebClient().getJavaScriptEngine().addPostponedAction(action); } } else { if (LOG.isDebugEnabled()) { LOG.debug("Unable to download image for tag " + this + "; not firing onload event."); } } } } /** * Returns the value of the attribute "src". Refer to the * HTML 4.01 * documentation for details on the use of this attribute. * * @return the value of the attribute "src" or an empty string if that attribute isn't defined */ public final String getSrcAttribute() { return getAttribute("src"); } /** * Returns the value of the attribute "alt". Refer to the * HTML 4.01 * documentation for details on the use of this attribute. * * @return the value of the attribute "alt" or an empty string if that attribute isn't defined */ public final String getAltAttribute() { return getAttribute("alt"); } /** * Returns the value of the attribute "name". Refer to the * HTML 4.01 * documentation for details on the use of this attribute. * * @return the value of the attribute "name" or an empty string if that attribute isn't defined */ public final String getNameAttribute() { return getAttribute("name"); } /** * Returns the value of the attribute "longdesc". Refer to the * HTML 4.01 * documentation for details on the use of this attribute. * * @return the value of the attribute "longdesc" or an empty string if that attribute isn't defined */ public final String getLongDescAttribute() { return getAttribute("longdesc"); } /** * Returns the value of the attribute "height". Refer to the * HTML 4.01 * documentation for details on the use of this attribute. * * @return the value of the attribute "height" or an empty string if that attribute isn't defined */ public final String getHeightAttribute() { return getAttribute("height"); } /** * Returns the value of the attribute "width". Refer to the * HTML 4.01 * documentation for details on the use of this attribute. * * @return the value of the attribute "width" or an empty string if that attribute isn't defined */ public final String getWidthAttribute() { return getAttribute("width"); } /** * Returns the value of the attribute "usemap". Refer to the * HTML 4.01 * documentation for details on the use of this attribute. * * @return the value of the attribute "usemap" or an empty string if that attribute isn't defined */ public final String getUseMapAttribute() { return getAttribute("usemap"); } /** * Returns the value of the attribute "ismap". Refer to the * HTML 4.01 * documentation for details on the use of this attribute. * * @return the value of the attribute "ismap" or an empty string if that attribute isn't defined */ public final String getIsmapAttribute() { return getAttribute("ismap"); } /** * Returns the value of the attribute "align". Refer to the * HTML 4.01 * documentation for details on the use of this attribute. * * @return the value of the attribute "align" or an empty string if that attribute isn't defined */ public final String getAlignAttribute() { return getAttribute("align"); } /** * Returns the value of the attribute "border". Refer to the * HTML 4.01 * documentation for details on the use of this attribute. * * @return the value of the attribute "border" or an empty string if that attribute isn't defined */ public final String getBorderAttribute() { return getAttribute("border"); } /** * Returns the value of the attribute "hspace". Refer to the * HTML 4.01 * documentation for details on the use of this attribute. * * @return the value of the attribute "hspace" or an empty string if that attribute isn't defined */ public final String getHspaceAttribute() { return getAttribute("hspace"); } /** * Returns the value of the attribute "vspace". Refer to the * HTML 4.01 * documentation for details on the use of this attribute. * * @return the value of the attribute "vspace" or an empty string if that attribute isn't defined */ public final String getVspaceAttribute() { return getAttribute("vspace"); } /** *

Returns the image's actual height (not the image's {@link #getHeightAttribute() height attribute}).

*

POTENTIAL PERFORMANCE KILLER - DOWNLOADS THE IMAGE - USE AT YOUR OWN RISK

*

If the image has not already been downloaded, this method triggers a download and caches the image.

* * @return the image's actual height * @throws IOException if an error occurs while downloading or reading the image */ public int getHeight() throws IOException { readImageIfNeeded(); return imageReader_.getHeight(0); } /** *

Returns the image's actual width (not the image's {@link #getWidthAttribute() width attribute}).

*

POTENTIAL PERFORMANCE KILLER - DOWNLOADS THE IMAGE - USE AT YOUR OWN RISK

*

If the image has not already been downloaded, this method triggers a download and caches the image.

* * @return the image's actual width * @throws IOException if an error occurs while downloading or reading the image */ public int getWidth() throws IOException { readImageIfNeeded(); return imageReader_.getWidth(0); } /** *

Returns the ImageReader which can be used to read the image contained by this image element.

*

POTENTIAL PERFORMANCE KILLER - DOWNLOADS THE IMAGE - USE AT YOUR OWN RISK

*

If the image has not already been downloaded, this method triggers a download and caches the image.

* * @return the ImageReader which can be used to read the image contained by this image element * @throws IOException if an error occurs while downloading or reading the image */ public ImageReader getImageReader() throws IOException { readImageIfNeeded(); return imageReader_; } /** *

Returns the WebResponse for the image contained by this image element.

*

POTENTIAL PERFORMANCE KILLER - DOWNLOADS THE IMAGE - USE AT YOUR OWN RISK

*

If the image has not already been downloaded and downloadIfNeeded is true, this method * triggers a download and caches the image.

* * @param downloadIfNeeded whether or not the image should be downloaded (if it hasn't already been downloaded) * @return null if no download should be performed and one hasn't already been triggered; otherwise, * the response received when performing a request for the image referenced by this element * @throws IOException if an error occurs while downloading the image */ public WebResponse getWebResponse(final boolean downloadIfNeeded) throws IOException { if (downloadIfNeeded) { downloadImageIfNeeded(); } return imageWebResponse_; } /** *

Downloads the image contained by this image element.

*

POTENTIAL PERFORMANCE KILLER - DOWNLOADS THE IMAGE - USE AT YOUR OWN RISK

*

If the image has not already been downloaded, this method triggers a download and caches the image.

* * @throws IOException if an error occurs while downloading the image */ private void downloadImageIfNeeded() throws IOException { if (!downloaded_) { final HtmlPage page = (HtmlPage) getPage(); final WebClient webclient = page.getWebClient(); final URL url = page.getFullyQualifiedUrl(getSrcAttribute()); final WebRequest request = new WebRequest(url); request.setAdditionalHeader("Referer", page.getWebResponse().getWebRequest().getUrl().toExternalForm()); imageWebResponse_ = webclient.loadWebResponse(request); imageReader_ = null; downloaded_ = true; } } private void readImageIfNeeded() throws IOException { downloadImageIfNeeded(); if (imageReader_ == null) { final ImageInputStream iis = ImageIO.createImageInputStream(imageWebResponse_.getContentAsStream()); final Iterator iter = ImageIO.getImageReaders(iis); if (!iter.hasNext()) { throw new IOException("No image detected in response"); } imageReader_ = iter.next(); imageReader_.setInput(iis); } } /** * Simulates clicking this element at the specified position. This only makes sense for * an image map (currently only server side), where the position matters. This method * returns the page contained by this image's window after the click, which may or may not * be the same as the original page, depending on JavaScript event handlers, etc. * * @param x the x position of the click * @param y the y position of the click * @return the page contained by this image's window after the click * @exception IOException if an IO error occurs */ public Page click(final int x, final int y) throws IOException { lastClickX_ = x; lastClickY_ = y; return super.click(); } /** * Simulates clicking this element at the position (0, 0). This method returns * the page contained by this image's window after the click, which may or may not be the * same as the original page, depending on JavaScript event handlers, etc. * * @return the page contained by this image's window after the click * @exception IOException if an IO error occurs */ @Override @SuppressWarnings("unchecked") public Page click() throws IOException { return click(0, 0); } /** * Performs the click action on the enclosing A tag (if any). * @throws IOException if an IO error occurred */ @Override protected void doClickAction() throws IOException { if (getUseMapAttribute() != ATTRIBUTE_NOT_DEFINED) { // remove initial '#' final String mapName = getUseMapAttribute().substring(1); final HtmlElement doc = ((HtmlPage) getPage()).getDocumentElement(); final HtmlMap map = doc.getOneHtmlElementByAttribute("map", "name", mapName); for (final HtmlElement element : map.getChildElements()) { if (element instanceof HtmlArea) { final HtmlArea area = (HtmlArea) element; if (area.containsPoint(lastClickX_, lastClickY_)) { area.doClickAction(); return; } } } } final HtmlAnchor anchor = (HtmlAnchor) getEnclosingElement("a"); if (anchor == null) { return; } if (getIsmapAttribute() != ATTRIBUTE_NOT_DEFINED) { final String suffix = "?" + lastClickX_ + "," + lastClickY_; anchor.doClickAction(suffix); return; } anchor.doClickAction(); } /** * Saves this image as the specified file. * @param file the file to save to * @throws IOException if an IO error occurs */ public void saveAs(final File file) throws IOException { final ImageReader reader = getImageReader(); ImageIO.write(reader.read(0), reader.getFormatName(), file); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy