1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.html;
16
17 import java.io.IOException;
18 import java.net.MalformedURLException;
19 import java.net.URL;
20 import java.util.Map;
21
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24 import org.htmlunit.BrowserVersion;
25 import org.htmlunit.SgmlPage;
26 import org.htmlunit.WebClient;
27 import org.htmlunit.WebRequest;
28 import org.htmlunit.WebResponse;
29 import org.htmlunit.css.CssStyleSheet;
30 import org.htmlunit.cssparser.dom.MediaListImpl;
31 import org.htmlunit.javascript.AbstractJavaScriptEngine;
32 import org.htmlunit.javascript.PostponedAction;
33 import org.htmlunit.javascript.host.event.Event;
34 import org.htmlunit.javascript.host.html.HTMLLinkElement;
35 import org.htmlunit.util.ArrayUtils;
36 import org.htmlunit.util.StringUtils;
37 import org.htmlunit.xml.XmlPage;
38
39
40
41
42
43
44
45
46
47
48
49
50
51 public class HtmlLink extends HtmlElement {
52 private static final Log LOG = LogFactory.getLog(HtmlLink.class);
53
54
55 public static final String TAG_NAME = "link";
56
57
58
59
60
61 private CssStyleSheet sheet_;
62
63
64
65
66
67
68
69
70 HtmlLink(final String qualifiedName, final SgmlPage page,
71 final Map<String, DomAttr> attributes) {
72 super(qualifiedName, page, attributes);
73 }
74
75
76
77
78
79
80
81
82
83 public final String getCharsetAttribute() {
84 return getAttributeDirect("charset");
85 }
86
87
88
89
90
91
92
93
94
95 public final String getHrefAttribute() {
96 return getAttributeDirect("href");
97 }
98
99
100
101
102
103
104
105
106
107 public final String getHrefLangAttribute() {
108 return getAttributeDirect("hreflang");
109 }
110
111
112
113
114
115
116
117
118
119 public final String getTypeAttribute() {
120 return getAttributeDirect(TYPE_ATTRIBUTE);
121 }
122
123
124
125
126
127
128
129
130
131 public final String getRelAttribute() {
132 return getAttributeDirect("rel");
133 }
134
135
136
137
138
139
140
141
142
143 public final String getRevAttribute() {
144 return getAttributeDirect("rev");
145 }
146
147
148
149
150
151
152
153
154
155 public final String getMediaAttribute() {
156 return getAttributeDirect("media");
157 }
158
159
160
161
162
163
164
165
166
167 public final String getTargetAttribute() {
168 return getAttributeDirect("target");
169 }
170
171
172
173
174
175
176
177
178
179
180
181 public WebResponse getWebResponse(final boolean downloadIfNeeded) throws IOException {
182 return getWebResponse(downloadIfNeeded, null);
183 }
184
185
186
187
188
189
190
191
192
193
194
195
196
197 public WebResponse getWebResponse(final boolean downloadIfNeeded, WebRequest request) throws IOException {
198 final WebClient webclient = getPage().getWebClient();
199 if (null == request) {
200 request = getWebRequest();
201 }
202
203 if (downloadIfNeeded) {
204 try {
205 final WebResponse response = webclient.loadWebResponse(request);
206 if (response.isSuccess()) {
207 executeEvent(Event.TYPE_LOAD);
208 }
209 else {
210 executeEvent(Event.TYPE_ERROR);
211 }
212 return response;
213 }
214 catch (final IOException e) {
215 executeEvent(Event.TYPE_ERROR);
216 throw e;
217 }
218 }
219
220
221 return webclient.getCache().getCachedResponse(request);
222 }
223
224
225
226
227
228
229 public WebRequest getWebRequest() throws MalformedURLException {
230 final HtmlPage page = (HtmlPage) getPage();
231 final URL url = page.getFullyQualifiedUrl(getHrefAttribute());
232
233 final BrowserVersion browser = page.getWebClient().getBrowserVersion();
234 final WebRequest request = new WebRequest(url, browser.getCssAcceptHeader(), browser.getAcceptEncodingHeader());
235
236 request.setCharset(page.getCharset());
237 request.setRefererHeader(page.getUrl());
238
239 return request;
240 }
241
242
243
244
245 @Override
246 public DisplayStyle getDefaultStyleDisplay() {
247 return DisplayStyle.NONE;
248 }
249
250
251
252
253 @Override
254 public boolean mayBeDisplayed() {
255 return false;
256 }
257
258 private void executeEvent(final String type) {
259 final HTMLLinkElement link = getScriptableObject();
260 final Event event = new Event(this, type);
261 link.executeEventLocally(event);
262 }
263
264
265
266
267 @Override
268 public void onAllChildrenAddedToPage(final boolean postponed) {
269 if (getOwnerDocument() instanceof XmlPage) {
270 return;
271 }
272 if (LOG.isDebugEnabled()) {
273 LOG.debug("Link node added: " + asXml());
274 }
275
276 final boolean isStyleSheetLink = isStyleSheetLink();
277
278 if (isStyleSheetLink) {
279 final WebClient webClient = getPage().getWebClient();
280 if (!webClient.getOptions().isCssEnabled()) {
281 if (LOG.isDebugEnabled()) {
282 LOG.debug("Stylesheet Link found but ignored because css support is disabled ("
283 + asXml().replaceAll("[\\r\\n]", "") + ").");
284 }
285 return;
286 }
287
288 if (!webClient.isJavaScriptEngineEnabled()) {
289 if (LOG.isDebugEnabled()) {
290 LOG.debug("Stylesheet Link found but ignored because javascript engine is disabled ("
291 + asXml().replaceAll("[\\r\\n]", "") + ").");
292 }
293 return;
294 }
295
296 final PostponedAction action = new PostponedAction(getPage(), "Loading of link " + this) {
297 @Override
298 public void execute() {
299 final HTMLLinkElement linkElem = HtmlLink.this.getScriptableObject();
300
301 linkElem.getSheet();
302 }
303 };
304
305 final AbstractJavaScriptEngine<?> engine = webClient.getJavaScriptEngine();
306 if (postponed) {
307 engine.addPostponedAction(action);
308 }
309 else {
310 try {
311 action.execute();
312 }
313 catch (final RuntimeException e) {
314 throw e;
315 }
316 catch (final Exception e) {
317 throw new RuntimeException(e);
318 }
319 }
320
321 return;
322 }
323
324 if (LOG.isDebugEnabled()) {
325 LOG.debug("Link type '" + getRelAttribute() + "' not supported ("
326 + asXml().replaceAll("[\\r\\n]", "") + ").");
327 }
328 }
329
330
331
332
333
334
335 public CssStyleSheet getSheet() {
336 if (sheet_ == null) {
337 sheet_ = CssStyleSheet.loadStylesheet(this, this, null);
338 }
339 return sheet_;
340 }
341
342
343
344
345 public boolean isStyleSheetLink() {
346 final String rel = getRelAttribute();
347 if (rel != null) {
348 return ArrayUtils.containsIgnoreCase(StringUtils.splitAtBlank(rel), "stylesheet");
349 }
350 return false;
351 }
352
353
354
355
356 public boolean isModulePreloadLink() {
357 final String rel = getRelAttribute();
358 if (rel != null) {
359 return ArrayUtils.containsIgnoreCase(StringUtils.splitAtBlank(rel), "modulepreload");
360 }
361 return false;
362 }
363
364
365
366
367
368
369
370
371
372 public boolean isActiveStyleSheetLink() {
373 if (isStyleSheetLink()) {
374 final String media = getMediaAttribute();
375 if (org.apache.commons.lang3.StringUtils.isBlank(media)) {
376 return true;
377 }
378
379 final MediaListImpl mediaList =
380 CssStyleSheet.parseMedia(media, getPage().getWebClient());
381 return CssStyleSheet.isActive(mediaList, getPage().getEnclosingWindow());
382 }
383 return false;
384 }
385 }