/** If the LINK refers to a stylesheet document, this method loads and parses it. */ protected void processLink() { this.styleSheet = null; String rel = this.getAttribute(HtmlAttributeProperties.REL); if (rel != null) { String cleanRel = rel.trim().toLowerCase(); boolean isStyleSheet = cleanRel.equals("stylesheet"); boolean isAltStyleSheet = cleanRel.equals("alternate stylesheet"); boolean isAppendixStyleSheet = cleanRel.equals("appendix stylesheet"); if (isStyleSheet || isAltStyleSheet || isAppendixStyleSheet) { UserAgentContext uacontext = this.getUserAgentContext(); if (uacontext.isExternalCSSEnabled()) { String media = this.getMedia(); if (CSSUtilities.matchesMedia(media, uacontext)) { HTMLDocumentImpl doc = (HTMLDocumentImpl) this.getOwnerDocument(); try { CSSStyleSheet sheet = CSSUtilities.parse(this.getHref(), doc); CSSStyleSheetImpl sheetImpl = null; if (sheet != null) { doc.addStyleSheet(sheet); this.styleSheet = sheet; if (sheet instanceof CSSStyleSheetImpl) { sheetImpl = (CSSStyleSheetImpl) sheet; if (isAltStyleSheet) { sheetImpl.setDisabled(true); } else { sheetImpl.setDisabled(disabled); } URL baseURL = new URL(doc.getBaseURI()); URL scriptURL = Urls.createURL(baseURL, getHref()); if (scriptURL != null) sheetImpl.setHref(scriptURL.toString()); doc.addStyleSheet(sheetImpl); } else { if (isAltStyleSheet) { sheet.setDisabled(true); } else { sheet.setDisabled(this.disabled); } doc.addStyleSheet(sheet); } } } catch (MalformedURLException mfe) { this.warn( "Will not parse CSS. URI=[" + this.getHref() + "] with BaseURI=[" + doc.getBaseURI() + "] does not appear to be a valid URI."); } catch (Throwable err) { this.warn("Unable to parse CSS. URI=[" + this.getHref() + "].", err); } } } } } }
/** * Adds the rule. * * @param styleSheet the style sheet * @param rule the rule * @throws MalformedURLException the malformed url exception * @throws UnsupportedEncodingException */ private final void addRule(CSSStyleSheet styleSheet, CSSRule rule) throws MalformedURLException, UnsupportedEncodingException { HTMLDocumentImpl document = this.document; if (rule instanceof CSSStyleRule) { CSSStyleRule sr = (CSSStyleRule) rule; String selectorList = sr.getSelectorText(); StringTokenizer commaTok = new StringTokenizer(selectorList, ","); while (commaTok.hasMoreTokens()) { String selectorPart = commaTok.nextToken().toLowerCase(); ArrayList<SimpleSelector> simpleSelectors = null; String lastSelectorText = null; StringTokenizer tok = new StringTokenizer(selectorPart, " \t\r\n"); if (tok.hasMoreTokens()) { simpleSelectors = new ArrayList<SimpleSelector>(); SimpleSelector prevSelector = null; SELECTOR_FOR: for (; ; ) { String token = tok.nextToken(); if (">".equals(token)) { if (prevSelector != null) { prevSelector.setSelectorType(SimpleSelector.PARENT); } continue SELECTOR_FOR; } else if ("+".equals(token)) { if (prevSelector != null) { prevSelector.setSelectorType(SimpleSelector.PRECEEDING_SIBLING); } continue SELECTOR_FOR; } int colonIdx = token.indexOf(':'); String simpleSelectorText = colonIdx == -1 ? token : token.substring(0, colonIdx); String pseudoElement = colonIdx == -1 ? null : token.substring(colonIdx + 1); prevSelector = new SimpleSelector(simpleSelectorText, pseudoElement); simpleSelectors.add(prevSelector); if (!tok.hasMoreTokens()) { lastSelectorText = simpleSelectorText; break; } } } if (lastSelectorText != null) { int dotIdx = lastSelectorText.indexOf('.'); if (dotIdx != -1) { String elemtl = lastSelectorText.substring(0, dotIdx); String classtl = lastSelectorText.substring(dotIdx + 1); this.addClassRule(elemtl, classtl, sr, simpleSelectors); } else { int poundIdx = lastSelectorText.indexOf('#'); if (poundIdx != -1) { String elemtl = lastSelectorText.substring(0, poundIdx); String idtl = lastSelectorText.substring(poundIdx + 1); this.addIdRule(elemtl, idtl, sr, simpleSelectors); } else { String elemtl = lastSelectorText; this.addElementRule(elemtl, sr, simpleSelectors); } } } } // TODO: Attribute selectors } else if (rule instanceof CSSImportRule) { UserAgentContext uacontext = document.getUserAgentContext(); if (uacontext.isExternalCSSEnabled()) { CSSImportRule importRule = (CSSImportRule) rule; if (CSSUtilities.matchesMedia(importRule.getMedia(), uacontext)) { String href = importRule.getHref(); CSSStyleSheet sheet = null; try { sheet = CSSUtilities.parse(href, document); } catch (Exception err) { logger.severe("Unable to parse CSS. URI=[" + href + "]." + err); } if (sheet != null) { this.addStyleSheet(sheet); } } } } else if (rule instanceof CSSMediaRule) { CSSMediaRule mrule = (CSSMediaRule) rule; MediaList mediaList = mrule.getMedia(); if (CSSUtilities.matchesMedia(mediaList, document.getUserAgentContext())) { CSSRuleList ruleList = mrule.getCssRules(); int length = ruleList.getLength(); for (int i = 0; i < length; i++) { CSSRule subRule = ruleList.item(i); this.addRule(styleSheet, subRule); } } } }