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

org.htmlunit.html.HtmlLink Maven / Gradle / Ivy

Go to download

XLT (Xceptance LoadTest) is an extensive load and performance test tool developed and maintained by Xceptance.

There is a newer version: 8.4.1
Show newest version
/*
 * 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.CSS_DISPLAY_BLOCK2;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Locale;
import java.util.Map;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.htmlunit.BrowserVersion;
import org.htmlunit.SgmlPage;
import org.htmlunit.WebClient;
import org.htmlunit.WebRequest;
import org.htmlunit.WebResponse;
import org.htmlunit.css.CssStyleSheet;
import org.htmlunit.cssparser.dom.MediaListImpl;
import org.htmlunit.javascript.AbstractJavaScriptEngine;
import org.htmlunit.javascript.PostponedAction;
import org.htmlunit.javascript.host.event.Event;
import org.htmlunit.javascript.host.html.HTMLLinkElement;
import org.htmlunit.util.StringUtils;
import org.htmlunit.xml.XmlPage;

/**
 * Wrapper for the HTML element "link". Note: This is not a clickable link,
 * that one is an HtmlAnchor
 *
 * @author Mike Bowler
 * @author David K. Taylor
 * @author Christian Sell
 * @author Ahmed Ashour
 * @author Marc Guillemot
 * @author Frank Danek
 * @author Ronald Brill
 */
public class HtmlLink extends HtmlElement {
    private static final Log LOG = LogFactory.getLog(HtmlLink.class);

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

    /**
     * The associated style sheet (only valid for links of type
     * <link rel="stylesheet" type="text/css" href="..." />).
     */
    private CssStyleSheet sheet_;

    /**
     * Creates an instance of HtmlLink
     *
     * @param qualifiedName the qualified name of the element type to instantiate
     * @param page the HtmlPage that contains this element
     * @param attributes the initial attributes
     */
    HtmlLink(final String qualifiedName, final SgmlPage page,
            final Map attributes) {
        super(qualifiedName, page, attributes);
    }

    /**
     * Returns the value of the attribute {@code charset}. Refer to the
     * HTML 4.01
     * documentation for details on the use of this attribute.
     *
     * @return the value of the attribute {@code charset}
     * or an empty string if that attribute isn't defined.
     */
    public final String getCharsetAttribute() {
        return getAttributeDirect("charset");
    }

    /**
     * Returns the value of the attribute {@code href}. Refer to the
     * HTML 4.01
     * documentation for details on the use of this attribute.
     *
     * @return the value of the attribute {@code href}
     * or an empty string if that attribute isn't defined.
     */
    public final String getHrefAttribute() {
        return getAttributeDirect("href");
    }

    /**
     * Returns the value of the attribute {@code hreflang}. Refer to the
     * HTML 4.01
     * documentation for details on the use of this attribute.
     *
     * @return the value of the attribute {@code hreflang}
     * or an empty string if that attribute isn't defined.
     */
    public final String getHrefLangAttribute() {
        return getAttributeDirect("hreflang");
    }

    /**
     * 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 {@code rel}. Refer to the
     * HTML 4.01
     * documentation for details on the use of this attribute.
     *
     * @return the value of the attribute {@code rel}
     * or an empty string if that attribute isn't defined.
     */
    public final String getRelAttribute() {
        return getAttributeDirect("rel");
    }

    /**
     * Returns the value of the attribute {@code rev}. Refer to the
     * HTML 4.01
     * documentation for details on the use of this attribute.
     *
     * @return the value of the attribute {@code rev}
     * or an empty string if that attribute isn't defined.
     */
    public final String getRevAttribute() {
        return getAttributeDirect("rev");
    }

    /**
     * Returns the value of the attribute {@code media}. Refer to the
     * HTML 4.01
     * documentation for details on the use of this attribute.
     *
     * @return the value of the attribute {@code media}
     * or an empty string if that attribute isn't defined.
     */
    public final String getMediaAttribute() {
        return getAttributeDirect("media");
    }

    /**
     * Returns the value of the attribute {@code target}. Refer to the
     * HTML 4.01
     * documentation for details on the use of this attribute.
     *
     * @return the value of the attribute {@code target}
     * or an empty string if that attribute isn't defined.
     */
    public final String getTargetAttribute() {
        return getAttributeDirect("target");
    }

    /**
     * POTENIAL PERFORMANCE KILLER - DOWNLOADS THE RESOURCE - USE AT YOUR OWN RISK.
* If the linked content is not already downloaded it triggers a download. Then it stores the response * for later use.
* * @param downloadIfNeeded indicates if a request should be performed this hasn't been done previously * @return {@code null} if no download should be performed and when this wasn't already done; the response * received when performing a request for the content referenced by this tag otherwise * @throws IOException if an error occurs while downloading the content */ public WebResponse getWebResponse(final boolean downloadIfNeeded) throws IOException { return getWebResponse(downloadIfNeeded, null); } /** * INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.
* * If the linked content is not already downloaded it triggers a download. Then it stores the response * for later use.
* * @param downloadIfNeeded indicates if a request should be performed this hasn't been done previously * @param request the request; if null getWebRequest() is called to create one * @return {@code null} if no download should be performed and when this wasn't already done; the response * received when performing a request for the content referenced by this tag otherwise * @throws IOException if an error occurs while downloading the content */ public WebResponse getWebResponse(final boolean downloadIfNeeded, WebRequest request) throws IOException { final WebClient webclient = getPage().getWebClient(); if (null == request) { request = getWebRequest(); } if (downloadIfNeeded) { try { final WebResponse response = webclient.loadWebResponse(request); if (response.isSuccess()) { executeEvent(Event.TYPE_LOAD); } else { executeEvent(Event.TYPE_ERROR); } return response; } catch (final IOException e) { executeEvent(Event.TYPE_ERROR); throw e; } } // retrieve the response, from the cache if available return webclient.getCache().getCachedResponse(request); } /** * Returns the request which will allow us to retrieve the content referenced by the {@code href} attribute. * @return the request which will allow us to retrieve the content referenced by the {@code href} attribute * @throws MalformedURLException in case of problem resolving the URL */ public WebRequest getWebRequest() throws MalformedURLException { final HtmlPage page = (HtmlPage) getPage(); final URL url = page.getFullyQualifiedUrl(getHrefAttribute()); final BrowserVersion browser = page.getWebClient().getBrowserVersion(); final WebRequest request = new WebRequest(url, browser.getCssAcceptHeader(), browser.getAcceptEncodingHeader()); // use the page encoding even if this is a GET requests request.setCharset(page.getCharset()); request.setRefererlHeader(page.getUrl()); return request; } /** * {@inheritDoc} */ @Override public DisplayStyle getDefaultStyleDisplay() { if (hasFeature(CSS_DISPLAY_BLOCK2)) { return DisplayStyle.NONE; } return DisplayStyle.INLINE; } /** * {@inheritDoc} */ @Override public boolean mayBeDisplayed() { return false; } private void executeEvent(final String type) { final HTMLLinkElement link = getScriptableObject(); final Event event = new Event(this, type); link.executeEventLocally(event); } /** * {@inheritDoc} */ @Override public void onAllChildrenAddedToPage(final boolean postponed) { if (getOwnerDocument() instanceof XmlPage) { return; } if (LOG.isDebugEnabled()) { LOG.debug("Link node added: " + asXml()); } if (!isStyleSheetLink()) { if (LOG.isDebugEnabled()) { LOG.debug("Link type '" + getRelAttribute() + "' not supported (" + asXml().replaceAll("[\\r\\n]", "") + ")."); } return; } final WebClient webClient = getPage().getWebClient(); if (!webClient.getOptions().isCssEnabled()) { if (LOG.isDebugEnabled()) { LOG.debug("Stylesheet Link found but ignored because css support is disabled (" + asXml().replaceAll("[\\r\\n]", "") + ")."); } return; } if (!webClient.isJavaScriptEngineEnabled()) { if (LOG.isDebugEnabled()) { LOG.debug("Stylesheet Link found but ignored because javascript engine is disabled (" + asXml().replaceAll("[\\r\\n]", "") + ")."); } return; } final PostponedAction action = new PostponedAction(getPage(), "Loading of link " + this) { @Override public void execute() { final HTMLLinkElement linkElem = HtmlLink.this.getScriptableObject(); // force loading, caching inside the link linkElem.getSheet(); } }; final AbstractJavaScriptEngine engine = webClient.getJavaScriptEngine(); if (postponed) { engine.addPostponedAction(action); } else { try { action.execute(); } catch (final RuntimeException e) { throw e; } catch (final Exception e) { throw new RuntimeException(e); } } } /** * Returns the associated style sheet (only valid for links of type * <link rel="stylesheet" type="text/css" href="..." />). * @return the associated style sheet */ public CssStyleSheet getSheet() { if (sheet_ == null) { sheet_ = CssStyleSheet.loadStylesheet(this, this, null); } return sheet_; } /** * @return true if the rel attribute is 'stylesheet' */ public boolean isStyleSheetLink() { String rel = getRelAttribute(); if (rel != null) { rel = rel.toLowerCase(Locale.ROOT); return ArrayUtils.contains(StringUtils.splitAtBlank(rel), "stylesheet"); } return false; } /** *

Experimental API: May be changed in next release * and may not yet work perfectly!

* * Verifies if the provided node is a link node pointing to an active stylesheet. * * @return true if the provided node is a stylesheet link */ public boolean isActiveStyleSheetLink() { if (isStyleSheetLink()) { final String media = getMediaAttribute(); if (org.apache.commons.lang3.StringUtils.isBlank(media)) { return true; } final MediaListImpl mediaList = CssStyleSheet.parseMedia(media, getPage().getWebClient()); return CssStyleSheet.isActive(mediaList, getPage().getEnclosingWindow()); } return false; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy