1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107 package com.ivata.mask.web.tag.html;
108 import java.io.BufferedInputStream;
109 import java.io.IOException;
110 import java.io.InputStreamReader;
111 import java.net.MalformedURLException;
112 import java.net.URL;
113 import java.net.URLConnection;
114 import java.util.HashMap;
115 import java.util.Iterator;
116 import java.util.Map;
117
118 import javax.servlet.http.HttpSession;
119 import javax.servlet.jsp.JspException;
120 import javax.servlet.jsp.JspWriter;
121 import javax.servlet.jsp.PageContext;
122 import javax.servlet.jsp.tagext.BodyContent;
123
124 import org.apache.struts.taglib.TagUtils;
125 import org.apache.struts.taglib.html.BaseHandlerTag;
126 import org.apache.struts.taglib.html.BaseInputTag;
127 import org.apache.struts.taglib.html.LinkTag;
128
129 import com.ivata.mask.util.StringHandling;
130 import com.ivata.mask.web.browser.Browser;
131 import com.ivata.mask.web.format.HTMLFormatter;
132 /***
133 * <p>
134 * Provides the functionality of an <code>iframe</code> tag for those browsers
135 * which support it, and displays the tag body, or the contents of the
136 * <code>URL</code> referenced, for those which do not.
137 * </p>
138 *
139 * <p>
140 * If you specify a <code>URL</code> via one of the <code>SecureLinkTag</code>
141 * attributes, this will be displayed as the contents of the iframe, otherwise
142 * the tag body is used.
143 * </p>
144 *
145 * <p>
146 * <b>Note: </b> it is the tag body which appears in the resultant
147 * <code>iframe</code>, unlike the <code>HTML</code> implementation (where
148 * the tag body is a comment for older browsers)
149 * </p>
150 *
151 * <p>
152 * <b>Tag attributes: </b> <br/><table cellpadding='2' cellspacing='5'
153 * border='0' align='center' width='85%'>
154 * <tr class='TableHeadingColor'>
155 * <th>attribute</th>
156 * <th>reqd.</th>
157 * <th>param. class</th>
158 * <th width='100%'>description</th>
159 * </tr>
160 * <tr class='TableRowColor'>
161 * <td>align</td>
162 * <td>false</td>
163 * <td><code>java.lang.String</code></td>
164 * <td>Alignment of the iframe contents. If this has the value
165 * <code>"block"</code>, indicates the contents should fill the entire
166 * iframe.</td>
167 * </tr>
168 * <tr class='TableRowColor'>
169 * <td>formAction</td>
170 * <td>false</td>
171 * <td><code>java.lang.String</code></td>
172 * <td>Specify this tag attribute to define the action of a form which will
173 * surround the iframe contents. The action should be specified relative to the
174 * web application context path</td>
175 * </tr>
176 * <tr class='TableRowColor'>
177 * <td>formName</td>
178 * <td>false</td>
179 * <td><code>java.lang.String</code></td>
180 * <td>Specify this tag attribute to create a form with the given name. The
181 * action can be specified using the <code>formAction</code> attribute and the
182 * target using <code>formTarget</code>.</td>
183 * </tr>
184 * <tr class='TableRowColor'>
185 * <td>formTarget</td>
186 * <td>false</td>
187 * <td><code>java.lang.String</code></td>
188 * <td>Specify this tag attribute to define the target of a form which will
189 * surround the iframe contents.</td>
190 * </tr>
191 * <tr class='TableRowColor'>
192 * <td>frameName</td>
193 * <td>false</td>
194 * <td><code>java.lang.String</code></td>
195 * <td>Specify this tag attribute to set the name of the iframe.</td>
196 * </tr>
197 * <tr class='TableRowColor'>
198 * <td>height</td>
199 * <td>false</td>
200 * <td><code>java.lang.String</code></td>
201 * <td>This attribute represents the height of this frame, though its actual
202 * interpretation depends on the {@linkcom.ivata.mask.web.theme.Theme theme}
203 * implementation..</td>
204 * </tr>
205 * <tr class='TableRowColor'>
206 * <td>width</td>
207 * <td>false</td>
208 * <td><code>java.lang.String</code></td>
209 * <td>This attribute represents the width of this frame, though its actual
210 * interpretation depends on the {@linkcom.ivata.mask.web.theme.Theme theme}
211 * implementation..</td>
212 * </tr>
213 * </table>
214 * </p>
215 *
216 * @since ivata masks 0.4 (2003-01-25)
217 * @author Colin MacLeod
218 * <a href='mailto:colin.macleod@ivata.com'>colin.macleod@ivata.com</a>
219 * @version $Revision: 1.4 $
220 */
221 public class IFrameTag extends LinkTag {
222 /***
223 * <p>
224 * Include the output from another <code>URL</code> within the current
225 * page.
226 * </p>
227 *
228 * @param uRLParam
229 * the URL to include. All of the output from this
230 * <code>URL</code> is read in and sent to <code>out</code>.
231 * @param out
232 * <code>JspWriter</code> to write output to.
233 * @throws IOException
234 * if there is a problem either reading the input or writing the
235 * output.
236 */
237 private static void include(final String uRLParam,
238 final JspWriter out) throws IOException {
239 URLConnection connection = null;
240 connection = (new URL(uRLParam.toString())).openConnection();
241 connection.setAllowUserInteraction(false);
242 connection.setDoInput(true);
243 connection.setDoOutput(false);
244 connection.connect();
245
246
247 InputStreamReader reader = new InputStreamReader(
248 new BufferedInputStream(connection.getInputStream()));
249 while (true) {
250 int ch = reader.read();
251 if (ch < 0) {
252 break;
253 }
254 out.write(ch);
255 }
256 }
257 /***
258 * <p>
259 * Alignment of the iframe contents.
260 * </p>
261 *
262 * <p>
263 * Set to <code>"left"</code>,<code>"left"</code>, or
264 * <code>"center"</code> to align the iframe contents in that way. Setting
265 * this to <code>"block"</code> causes the contents to expand to the full
266 * width of the iframe.
267 * </p>
268 */
269 private String align = "center";
270 /***
271 * <p>
272 * Specify this tag attribute to define the action of a form which will
273 * surround the iframe contents. The action should be specified relative to
274 * the web application context path.
275 * </p>
276 *
277 * <p>
278 * <b>Note: </b> the form will only be created if the <code>formName</code>
279 * attribute is set and the browser supports <code><iframe></code>
280 * tags.
281 * </p>
282 */
283 private String formAction = null;
284 /***
285 * <p>
286 * Specify this tag attribute to create a form with the given name. The
287 * action can be specified using the <code>formAction</code> attribute and
288 * the target using <code>formTarget</code>.
289 * </p>
290 */
291 private String formName = null;
292 /***
293 * <p>
294 * Specify this tag attribute to define the target of a form which will
295 * surround the iframe contents.
296 * </p>
297 *
298 * <p>
299 * <b>Note: </b> the form will only be created if the <code>formName</code>
300 * attribute is set and the browser supports <code><iframe></code>
301 * tags.
302 * </p>
303 */
304 private String formTarget = "_parent";
305 /***
306 * <p>
307 * This tag attribute specified the height of the frame.
308 * </p>
309 */
310 private String height = null;
311 /***
312 * <p>
313 * Implementation attribute. Stores the names of contained mask tags,
314 * indexed by the <code>styleId</code> attribute.
315 * </p>
316 *
317 * <p>
318 * This is used to dynamically create extra hidden fields in
319 * <code>doEndTag</code> to let fields be contained within the iframe and
320 * still have their values submitted with the main form.
321 * </p>
322 */
323 private HashMap maskTagNames = new HashMap();
324 /***
325 * <p>
326 * Vertical alignment of the iframe contents.
327 * </p>
328 *
329 * <p>
330 * Set to <code>"top"</code>,<code>"bottom"</code>, or
331 * <code>"center"</code> to align the iframe contents in that way.
332 * </p>
333 */
334 private String valign = "center";
335 /***
336 * <p>
337 * This tag attribute specified the width of the frame.
338 * </p>
339 */
340 private String width = null;
341 /***
342 * <p>
343 * Implementation method. This method creates a hidden field matching the
344 * passed field's name, id and value. It also adds
345 * <strong>JavaScript</strong> to the original method's
346 * <code>onchange</code> attribute so the value of the hidden field is
347 * updated.
348 * </p>
349 *
350 * <p>
351 * This lets fields be transparently (well, fairly) contained within
352 * iframes.
353 * </p>
354 *
355 * @param maskTagParam tag to be added to the iframe, so it can be
356 * automatically updated using JavaScript.
357 * @param pageContext
358 * current page context for the tag .
359 * @throws JspException if the mask tag type is not compatible with this
360 * routine (Radio buttons are not implemented yet).
361 */
362 public final void addMaskTag(final BaseHandlerTag maskTagParam,
363 final PageContext pageContext) throws JspException {
364
365 if (ButtonTag.class.isInstance(maskTagParam)
366 || LabelTag.class.isInstance(maskTagParam)
367
368 || SubmitTag.class.isInstance(maskTagParam)
369 || ResetTag.class.isInstance(maskTagParam)) {
370 return;
371 }
372
373
374 Browser browser = (Browser) pageContext.getSession().getAttribute(
375 "browser");
376
377
378 if ((browser == null) || !browser.canDisplayIFrames()) {
379 return;
380 }
381 String onChange = StringHandling.getNotNull(maskTagParam.getOnchange(),
382 "").trim();
383
384 if ((onChange.length() > 0) && (!onChange.endsWith(";"))) {
385 onChange += ";";
386 }
387
388 String styleId = maskTagParam.getStyleId();
389 if (styleId == null) {
390
391 return;
392 }
393 String key = null;
394 String name = null;
395 String value = null;
396
397 if (RadioTag.class.isInstance(maskTagParam)) {
398 RadioTag radio = (RadioTag) maskTagParam;
399 name = radio.getProperty();
400
401 key = name;
402
403 throw new JspException("ERROR: Radio buttons are not implemented "
404 + "when used within iframes.");
405 } else if (CheckboxTag.class.isInstance(maskTagParam)) {
406 CheckboxTag checkBox = (CheckboxTag) maskTagParam;
407 name = checkBox.getProperty();
408 value = checkBox.getValue();
409 key = styleId;
410 } else if (MultiboxTag.class.isInstance(maskTagParam)) {
411 MultiboxTag multiBox = (MultiboxTag) maskTagParam;
412 name = multiBox.getProperty();
413 value = multiBox.getValue();
414 key = styleId;
415 } else if (SelectTag.class.isInstance(maskTagParam)) {
416 SelectTag select = (SelectTag) maskTagParam;
417 name = select.getProperty();
418 value = select.getValue();
419 key = styleId;
420 } else {
421 BaseInputTag inputTag = (BaseInputTag) maskTagParam;
422 name = inputTag.getProperty();
423 value = inputTag.getValue();
424 key = styleId;
425 }
426 onChange = "updateParentField('" + styleId + "');" + onChange;
427 maskTagParam.setOnchange(onChange);
428 maskTagNames.put(key, name);
429 }
430 /***
431 * <p>
432 * Overriddent to analyze the tag body and use it as the body of the iframe
433 * if present. This method is called after the JSP engine processes the body
434 * content of the tag.
435 * </p>
436 *
437 * @exception JspException
438 * encapsulates any exception when calling
439 * {@link #writeTagBodyContent writeTagBodyContent}.
440 * @return <code>SKIP_BODY</code> since we only ever want to evaluate this
441 * tag once.
442 * @see #writeTagBodyContent(JspWriter out, BodyContent bodyContent)
443 */
444 public int doAfterBody() throws JspException {
445
446
447 BodyContent bodyContent = getBodyContent();
448 if (bodyContent != null) {
449 String bodyText = bodyContent.getString();
450 if (!StringHandling.isNullOrEmpty(bodyText)) {
451
452
453 bodyText += "<script language='JavaScript'>\n";
454 bodyText += " <!--\n";
455 for (Iterator i = maskTagNames.keySet().iterator();
456 i.hasNext();) {
457 bodyText += "updateParentField('" + i.next() + "');\n";
458 }
459 bodyText += " //-->\n";
460 bodyText += "</script>\n";
461
462 String frameName = getLinkName();
463 if (StringHandling.isNullOrEmpty(frameName)) {
464 throw new JspException(
465 "ERROR in IFrameTag: you must specify a frame name "
466 + "to use the body text.");
467 }
468 pageContext.getSession().setAttribute(frameName, bodyText);
469 HashMap map = new HashMap();
470 map.put("sessionAttribute", frameName);
471 if (formName != null) {
472 map.put("formName", formName);
473 if (formAction != null) {
474 map.put("formAction", formAction);
475 }
476 if (formTarget != null) {
477 map.put("formTarget", formTarget);
478 }
479 }
480 map.put("align", align);
481 map.put("valign", valign);
482 pageContext.setAttribute("iframeMap", map);
483 this.setName("iframeMap");
484 setPage("/util/iframeContent.jsp");
485 }
486 }
487
488 return SKIP_BODY;
489 }
490 /***
491 * <p>
492 * Overridden to actually output the <code>HTML</code> code on the basis
493 * of the input parameters.
494 * </p>
495 *
496 * @return <code>EVAL_PAGE</code> since we always want to evaluate the
497 * page after this tag.
498 *
499 * @throws JspException
500 * if there is an error writing to <code>out.print()</code>
501 */
502 public int doEndTag() throws JspException {
503 HttpSession session = (HttpSession) pageContext.getSession();
504 Browser browser = (Browser) session.getAttribute("browser");
505 if (browser == null) {
506 throw new JspException("ERROR in IFrameTag: browser is null in "
507 + "session.");
508 }
509
510
511 String styleClass = this.getStyleClass();
512 if (styleClass != null) {
513 String mapName = getName();
514 Map params;
515 TagUtils tagUtils = TagUtils.getInstance();
516 if (StringHandling.isNullOrEmpty(mapName)) {
517 mapName = "iframeMap";
518 setName(mapName);
519 params = new HashMap();
520 pageContext.setAttribute(mapName, params,
521 PageContext.REQUEST_SCOPE);
522 } else {
523 params = (Map) tagUtils.lookup(pageContext, mapName, null);
524 }
525 params.put("class", styleClass);
526 }
527 String uRL = this.calculateURL();
528 JspWriter out = pageContext.getOut();
529 StringBuffer attributes = new StringBuffer(HTMLFormatter
530 .getAttributeNotNull("class", styleClass));
531 attributes.append(HTMLFormatter.getAttributeNotNull("id", this
532 .getStyleId()));
533 attributes.append(HTMLFormatter.getAttributeNotNull("name", this
534 .getLinkName()));
535 attributes.append(HTMLFormatter.getAttributeNotNull("onblur", this
536 .getOnblur()));
537 attributes.append(HTMLFormatter.getAttributeNotNull("onchange", this
538 .getOnchange()));
539 attributes.append(HTMLFormatter.getAttributeNotNull("onclick", this
540 .getOnclick()));
541 attributes.append(HTMLFormatter.getAttributeNotNull("ondblclick", this
542 .getOndblclick()));
543 attributes.append(HTMLFormatter.getAttributeNotNull("onfocus", this
544 .getOnfocus()));
545 attributes.append(HTMLFormatter.getAttributeNotNull("onkeydown", this
546 .getOnkeydown()));
547 attributes.append(HTMLFormatter.getAttributeNotNull("onkeyup", this
548 .getOnkeyup()));
549 attributes.append(HTMLFormatter.getAttributeNotNull("onmousedown", this
550 .getOnmousedown()));
551 attributes.append(HTMLFormatter.getAttributeNotNull("onmousemove", this
552 .getOnmousemove()));
553 attributes.append(HTMLFormatter.getAttributeNotNull("onmouseout", this
554 .getOnmouseout()));
555 attributes.append(HTMLFormatter.getAttributeNotNull("onmouseover", this
556 .getOnmouseover()));
557 attributes.append(HTMLFormatter.getAttributeNotNull("onmouseup", this
558 .getOnmouseup()));
559 attributes.append(HTMLFormatter.getAttributeNotNull("onselect", this
560 .getOnselect()));
561 attributes.append(HTMLFormatter.getAttributeNotNull("style", this
562 .getStyle()));
563 attributes.append(HTMLFormatter.getAttributeNotNull("target", this
564 .getTarget()));
565 attributes.append(HTMLFormatter.getAttributeNotNull("title", this
566 .getTitle()));
567 attributes.append(HTMLFormatter.getAttributeNotNull("width", width));
568 attributes.append(HTMLFormatter.getAttributeNotNull("height", height));
569 if (browser.canDisplayFrames()) {
570 try {
571 out.print("<iframe src='");
572 out.print(uRL);
573 out.print("'");
574 out.print(attributes);
575 out.print("></iframe>");
576 } catch (IOException e) {
577 throw new JspException(e);
578 }
579 try {
580
581
582 for (Iterator i = maskTagNames.keySet().iterator();
583 i.hasNext();) {
584 String key = (String) i.next();
585 out.print("<input type='hidden' id='");
586 out.print(key);
587 out.print("' name='");
588 out.print(maskTagNames.get(key));
589 out.print("'/>");
590 }
591 } catch (IOException e) {
592 throw new JspException(e);
593 }
594 } else {
595 try {
596 out.print("<span ");
597 out.print(attributes);
598 out.print(">");
599 include(uRL.toString(), out);
600 out.print("</span>");
601 } catch (MalformedURLException e) {
602 throw new JspException(e);
603 } catch (IOException e) {
604 throw new JspException(e);
605 }
606 }
607
608 return EVAL_PAGE;
609 }
610 /***
611 * <p>
612 * Overridden to prevent the superclass implementation from executing.
613 * </p>
614 *
615 * @return <code>EVAL_BODY_BUFFERED</code>.
616 *
617 * @throws JspException
618 * if either <code>valueKey</code> or <code>titleKey</code>
619 * have not been set, or as thrown by superclass method.
620 */
621 public int doStartTag() throws JspException {
622 return EVAL_BODY_BUFFERED;
623 }
624 /***
625 * <p>
626 * Alignment of the iframe contents.
627 * </p>
628 *
629 * <p>
630 * Set to <code>"left"</code>,<code>"left"</code>, or
631 * <code>"center"</code> to align the iframe contents in that way. Setting
632 * this to <code>"block"</code> causes the contents to expand to the full
633 * width of the iframe.
634 * </p>
635 *
636 * @return the current value of align.
637 */
638 public String getAlign() {
639 return align;
640 }
641 /***
642 * <p>
643 * Specify this tag attribute to define the action of a form which will
644 * surround the iframe contents. The action should be specified relative to
645 * the web application context path.
646 * </p>
647 *
648 * <p>
649 * <b>Note: </b> the form will only be created if the <code>formName</code>
650 * attribute is set and the browser supports <code><iframe></code>
651 * tags.
652 * </p>
653 *
654 * @return the current value of formAction.
655 */
656 public String getFormAction() {
657 return formAction;
658 }
659 /***
660 * <p>
661 * Specify this tag attribute to create a form with the given name. The
662 * action can be specified using the <code>formAction</code> attribute and
663 * the target using <code>formTarget</code>.
664 * </p>
665 *
666 * @return the current value of formName.
667 */
668 public String getFormName() {
669 return formName;
670 }
671 /***
672 * <p>
673 * Specify this tag attribute to define the target of a form which will
674 * surround the iframe contents.
675 * </p>
676 *
677 * <p>
678 * <b>Note: </b> the form will only be created if the <code>formName</code>
679 * attribute is set and the browser supports <code><iframe></code>
680 * tags.
681 * </p>
682 *
683 * @return the current value of formTarget.
684 */
685 public String getFormTarget() {
686 return formTarget;
687 }
688 /***
689 * <p>
690 * This tag attribute specified the height of the frame.
691 * </p>
692 *
693 * @return the current value of height.
694 */
695 public String getHeight() {
696 return height;
697 }
698 /***
699 * <p>
700 * Vertical alignment of the iframe contents.
701 * </p>
702 *
703 * <p>
704 * Set to <code>"top"</code>,<code>"bottom"</code>, or
705 * <code>"center"</code> to align the iframe contents in that way.
706 * </p>
707 *
708 * @return the current value of valign.
709 */
710 public String getValign() {
711 return valign;
712 }
713 /***
714 * <p>
715 * This tag attribute specified the width of the frame.
716 * </p>
717 *
718 * @return the current value of width.
719 */
720 public String getWidth() {
721 return width;
722 }
723 /***
724 * <p>
725 * Alignment of the iframe contents.
726 * </p>
727 *
728 * <p>
729 * Set to <code>"left"</code>,<code>"left"</code>, or
730 * <code>"center"</code> to align the iframe contents in that way. Setting
731 * this to <code>"block"</code> causes the contents to expand to the full
732 * width of the iframe.
733 * </p>
734 *
735 * @param alignParam
736 * the new value of align.
737 */
738 public void setAlign(final String alignParam) {
739 this.align = alignParam;
740 }
741 /***
742 * <p>
743 * Specify this tag attribute to define the action of a form which will
744 * surround the iframe contents. The action should be specified relative to
745 * the web application context path.
746 * </p>
747 *
748 * <p>
749 * <b>Note: </b> the form will only be created if the <code>formName</code>
750 * attribute is set and the browser supports <code><iframe></code>
751 * tags.
752 * </p>
753 *
754 * @param formActionParam
755 * the new value of formAction.
756 */
757 public void setFormAction(final String formActionParam) {
758 this.formAction = formActionParam;
759 }
760 /***
761 * <p>
762 * Specify this tag attribute to create a form with the given name. The
763 * action can be specified using the <code>formAction</code> attribute and
764 * the target using <code>formTarget</code>.
765 * </p>
766 *
767 * @param formNameParam
768 * the new value of formName.
769 */
770 public void setFormName(final String formNameParam) {
771 this.formName = formNameParam;
772 }
773 /***
774 * <p>
775 * Specify this tag attribute to define the target of a form which will
776 * surround the iframe contents.
777 * </p>
778 *
779 * <p>
780 * <b>Note: </b> the form will only be created if the <code>formName</code>
781 * attribute is set and the browser supports <code><iframe></code>
782 * tags.
783 * </p>
784 *
785 * @param formTargetParam
786 * the new value of formTarget.
787 */
788 public void setFormTarget(final String formTargetParam) {
789 this.formTarget = formTargetParam;
790 }
791 /***
792 * <p>
793 * Specify this tag attribute to set the name of the iframe created.
794 * </p>
795 *
796 * @param frameName
797 * the new value of frameName.
798 */
799 public void setFrameName(final String frameName) {
800 setLinkName(frameName);
801 }
802 /***
803 * <p>
804 * This tag attribute specified the height of the frame.
805 * </p>
806 *
807 * @param heightParam
808 * the new value of height.
809 */
810 public void setHeight(final String heightParam) {
811 this.height = heightParam;
812 }
813 /***
814 * <p>
815 * Vertical alignment of the iframe contents.
816 * </p>
817 *
818 * <p>
819 * Set to <code>"top"</code>,<code>"bottom"</code>, or
820 * <code>"center"</code> to align the iframe contents in that way.
821 * </p>
822 *
823 * @param valignParam
824 * the new value of valign.
825 */
826 public void setValign(final String valignParam) {
827 this.valign = valignParam;
828 }
829 /***
830 * <p>
831 * This tag attribute specified the width of the frame.
832 * </p>
833 *
834 * @param widthParam
835 * the new value of width.
836 */
837 public void setWidth(final String widthParam) {
838 this.width = widthParam;
839 }
840 }
841