1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.custom.inputHtml;
20
21 import javax.faces.FacesException;
22 import javax.faces.application.Resource;
23 import javax.faces.component.NamingContainer;
24 import javax.faces.component.UIViewRoot;
25 import javax.faces.component.UniqueIdVendor;
26 import javax.faces.context.ExternalContext;
27 import javax.faces.context.FacesContext;
28 import javax.faces.event.ComponentSystemEvent;
29 import javax.faces.event.ListenerFor;
30
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
34 import org.apache.myfaces.component.html.ext.HtmlInputText;
35 import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
36 import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
37 import org.apache.myfaces.shared_tomahawk.renderkit.html.util.FormInfo;
38 import org.apache.myfaces.shared_tomahawk.renderkit.html.util.JavascriptUtils;
39 import org.apache.myfaces.tomahawk.application.PreRenderViewAddResourceEvent;
40 import org.apache.myfaces.tomahawk.util.TomahawkResourceUtils;
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 @JSFComponent(
60 name = "t:inputHtml",
61 tagClass = "org.apache.myfaces.custom.inputHtml.InputHtmlTag",
62 composite=true)
63 @ListenerFor(systemEventClass=PreRenderViewAddResourceEvent.class)
64 public class InputHtml extends HtmlInputText implements NamingContainer, UniqueIdVendor {
65 public static final String COMPONENT_TYPE = "org.apache.myfaces.InputHtml";
66
67 public static final String DEFAULT_RENDERER_TYPE = "org.apache.myfaces.InputHtml";
68
69 private static final String INPUT_HTML_LIBRARY = "oam.custom.inputHtml";
70 private static final String INPUT_HTML_LIBRARY_KUPU_DRAWERS = "oam.custom.inputHtml.kupudrawers";
71
72 private static final Log log = LogFactory.getLog(HtmlInputText.class);
73
74 public InputHtml() {
75 setRendererType(DEFAULT_RENDERER_TYPE);
76 }
77
78 @Override
79 public void setRendererType(String rendererType)
80 {
81 if (!"javax.faces.Composite".equals(rendererType))
82 {
83 super.setRendererType(rendererType);
84 }
85 }
86
87 public void processEvent(ComponentSystemEvent event)
88 {
89 super.processEvent(event);
90 if (event instanceof PreRenderViewAddResourceEvent)
91 {
92 InputHtml editor = (InputHtml) event.getComponent();
93 if( !HtmlRendererUtils.isDisplayValueOnly(editor) && !useFallback(editor))
94 {
95 FacesContext facesContext = FacesContext.getCurrentInstance();
96
97
98 TomahawkResourceUtils.addOutputStylesheetResource(facesContext, INPUT_HTML_LIBRARY, "myFacesKupustyles.css");
99
100 TomahawkResourceUtils.addOutputStylesheetResource(facesContext, INPUT_HTML_LIBRARY, "kupudrawerstyles.css");
101
102 TomahawkResourceUtils.addOutputStylesheetResource(facesContext, INPUT_HTML_LIBRARY, "myFaces.css");
103
104
105 TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "sarissa.js");
106
107 TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "sarissa_ieemu_xpath.js");
108
109 TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "kupuhelpers.js");
110
111 TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "kupueditor.js");
112
113 TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "kupubasetools.js");
114
115 TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "kupuloggers.js");
116
117 TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "kupunoi18n.js");
118
119
120 TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "kupucleanupexpressions.js");
121
122 TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "kupucontentfilters.js");
123
124 if (editor.isShowAnyToolBox())
125 {
126
127 TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "kuputoolcollapser.js");
128 }
129
130 TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "kupucontextmenu.js");
131
132
133 TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "kupuinit.js");
134
135 TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "kupustart.js");
136
137
138 TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "kupusourceedit.js");
139
140 TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "kupuspellchecker.js");
141
142 TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "kupudrawers.js");
143
144
145 TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "kupuundo.js");
146
147 TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "diff_match_patch.js");
148
149
150 TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "myFacesUtils.js");
151
152 if( editor.getStyle()!=null ){
153
154
155
156
157
158 TomahawkResourceUtils.addInlineOutputStylesheetResource(facesContext,
159 "#kupu-editor{height: inherit;}\n"+
160 "div.kupu-fulleditor{"+editor.getStyle()+"}");
161 }
162 }
163 }
164 }
165
166 private static boolean useFallback(InputHtml editor){
167
168 return editor.getFallback().equals("true");
169 }
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238 public String getKupuConfig()
239 {
240 StringBuilder builder = new StringBuilder();
241 builder.append("<xml id=\"kupuconfig\" class=\"kupuconfig\">");
242 builder.append("<kupuconfig>");
243 builder.append("<dst>fulldoc.html</dst>");
244 builder.append("<use_css>1</use_css>");
245 builder.append("<reload_after_save>0</reload_after_save>");
246 builder.append("<strict_output>1</strict_output>");
247 builder.append("<content_type>application/xhtml+xml</content_type>");
248 builder.append("<compatible_singletons>1</compatible_singletons>");
249 builder.append("<table_classes>");
250 builder.append("<class>plain</class>");
251 builder.append("<class>listing</class>");
252 builder.append("<class>grid</class>");
253 builder.append("<class>data</class>");
254 builder.append("</table_classes>");
255
256 builder.append("<cleanup_expressions>");
257 builder.append("<set>");
258 builder.append("<name>Convert single quotes to curly ones</name>");
259 builder.append("<expression>");
260 builder.append("<reg>");
261 builder.append("(\\W)'");
262 builder.append("</reg>");
263 builder.append("<replacement>");
264 builder.append("\1‘");
265 builder.append("</replacement>");
266 builder.append("</expression>");
267 builder.append("<expression>");
268 builder.append("<reg>");
269 builder.append("'");
270 builder.append("</reg>");
271 builder.append("<replacement>");
272 builder.append("’");
273 builder.append("</replacement>");
274 builder.append("</expression>");
275 builder.append("</set>");
276 builder.append("<set>");
277 builder.append("<name>Reduce whitespace</name>");
278 builder.append("<expression>");
279 builder.append("<reg>");
280 builder.append("[\n\r\t]");
281 builder.append("</reg>");
282 builder.append("<replacement>");
283 builder.append("\\x20");
284 builder.append("</replacement>");
285 builder.append("</expression>");
286 builder.append("<expression>");
287 builder.append("<reg>");
288 builder.append("[ ]{2}");
289 builder.append("</reg>");
290 builder.append("<replacement>");
291 builder.append("\\x20");
292 builder.append("</replacement>");
293 builder.append("</expression>");
294 builder.append("</set>");
295 builder.append("</cleanup_expressions>");
296
297 FacesContext context = getFacesContext();
298 Resource resource = context.getApplication().getResourceHandler()
299 .createResource("drawer.xsl",
300 INPUT_HTML_LIBRARY_KUPU_DRAWERS);
301 builder.append("<image_xsl_uri>" + resource.getRequestPath()
302 + "</image_xsl_uri>");
303 builder.append("<link_xsl_uri>" + resource.getRequestPath()
304 + "</link_xsl_uri>");
305
306 resource = context.getApplication().getResourceHandler()
307 .createResource("imagelibrary.xml",
308 INPUT_HTML_LIBRARY_KUPU_DRAWERS);
309 builder.append("<image_libraries_uri>" + resource.getRequestPath()
310 + "</image_libraries_uri>");
311
312 resource = context.getApplication().getResourceHandler()
313 .createResource("linklibrary.xml",
314 INPUT_HTML_LIBRARY_KUPU_DRAWERS);
315 builder.append("<link_libraries_uri>" + resource.getRequestPath()
316 + "</link_libraries_uri>");
317
318 builder.append("<search_images_uri> </search_images_uri>");
319 builder.append("<search_links_uri> </search_links_uri>");
320
321 builder.append("</kupuconfig>");
322 builder.append("</xml>");
323 return builder.toString();
324 }
325
326
327 public String getDisplayValueOnlyText()
328 {
329 return getHtmlBody(RendererUtils.getStringValue(getFacesContext(), this));
330 }
331
332 public String getFallbackText()
333 {
334 String text = RendererUtils.getStringValue(getFacesContext(), this);
335 return htmlToPlainText(text, this);
336 }
337
338 public String getHiddenText()
339 {
340 return RendererUtils.getStringValue(getFacesContext(), this);
341 }
342
343 private static String htmlToPlainText(String html, InputHtml editor){
344 return editor.getHtmlBody( html )
345 .replaceAll("<br.*>","\n")
346 .replaceAll("<.+?>", "");
347 }
348
349
350 public String getFormId()
351 {
352 FormInfo parentFormInfo = RendererUtils.findNestingForm(this, getFacesContext());
353 if(parentFormInfo == null)
354 throw new FacesException("InputHtml must be embedded in a form.");
355 return parentFormInfo.getFormName();
356 }
357
358 public String getEncodedText()
359 {
360 String text = this.getValueAsHtmlDocument(getFacesContext());
361 return (text == null) ? "" : JavascriptUtils.encodeString( text );
362
363 }
364
365
366
367
368
369
370
371 public String createUniqueId(FacesContext context, String seed)
372 {
373 StringBuilder bld = new StringBuilder();
374
375
376 if(seed==null)
377 {
378 Long uniqueIdCounter = (Long) getStateHelper().get(PropertyKeys.uniqueIdCounter);
379 uniqueIdCounter = (uniqueIdCounter == null) ? 0 : uniqueIdCounter;
380 getStateHelper().put(PropertyKeys.uniqueIdCounter, (uniqueIdCounter+1L));
381 return bld.append(UIViewRoot.UNIQUE_ID_PREFIX).append(uniqueIdCounter).toString();
382 }
383
384 else
385 {
386 return bld.append(UIViewRoot.UNIQUE_ID_PREFIX).append(seed).toString();
387 }
388 }
389
390
391
392
393
394
395
396
397 public String getFallback(){
398 return (String) getStateHelper().eval(PropertyKeys.fallback, "false");
399 }
400 public void setFallback(String _fallback){
401 getStateHelper().put(PropertyKeys.fallback, _fallback);
402 }
403
404
405
406
407
408
409
410
411 public String getType(){
412 return (String) getStateHelper().eval(PropertyKeys.type, "fragment");
413 }
414 public void setType(String _type){
415 getStateHelper().put(PropertyKeys.type, _type);
416 }
417 public boolean isTypeDocument(){
418 return getType().equals("document");
419 }
420
421
422
423
424
425
426 public boolean isAllowEditSource(){
427 return (Boolean) getStateHelper().eval(PropertyKeys.allowEditSource, Boolean.TRUE);
428 }
429 public void setAllowEditSource(boolean allowEditSource){
430 getStateHelper().put(PropertyKeys.allowEditSource, allowEditSource);
431 }
432
433
434
435
436
437
438 public boolean isAllowExternalLinks(){
439 return (Boolean) getStateHelper().eval(PropertyKeys.allowExternalLinks, Boolean.TRUE);
440 }
441 public void setAllowExternalLinks(boolean allowExternalLinks){
442 getStateHelper().put(PropertyKeys.allowExternalLinks, allowExternalLinks);
443 }
444
445
446
447
448
449
450 public boolean isAddKupuLogo(){
451 return (Boolean) getStateHelper().eval(PropertyKeys.addKupuLogo, Boolean.TRUE);
452 }
453 public void setAddKupuLogo(boolean addKupuLogo){
454 getStateHelper().put(PropertyKeys.addKupuLogo, addKupuLogo);
455 }
456
457
458
459
460
461
462 public boolean isShowAllToolBoxes(){
463 return (Boolean) getStateHelper().eval(PropertyKeys.showAllToolBoxes, Boolean.FALSE);
464 }
465 public void setShowAllToolBoxes(boolean showAllToolBoxes){
466 getStateHelper().put(PropertyKeys.showAllToolBoxes, showAllToolBoxes);
467 }
468
469
470
471
472
473
474 public boolean isShowPropertiesToolBox(){
475 if( isShowAllToolBoxes() )
476 return true;
477
478 return (Boolean) getStateHelper().eval(PropertyKeys.showPropertiesToolBox, Boolean.FALSE);
479 }
480
481 public void setShowPropertiesToolBox(boolean showPropertiesToolBox){
482 getStateHelper().put(PropertyKeys.showPropertiesToolBox, showPropertiesToolBox);
483 }
484
485
486
487
488
489
490 public boolean isShowLinksToolBox(){
491 if( isShowAllToolBoxes() )
492 return true;
493
494 return (Boolean) getStateHelper().eval(PropertyKeys.showLinksToolBox, Boolean.FALSE);
495 }
496
497 public void setShowLinksToolBox(boolean showLinksToolBox){
498 getStateHelper().put(PropertyKeys.showLinksToolBox, showLinksToolBox);
499 }
500
501
502
503
504
505
506 public boolean isShowImagesToolBox(){
507 if( isShowAllToolBoxes() )
508 return true;
509
510 return (Boolean) getStateHelper().eval(PropertyKeys.showImagesToolBox, Boolean.FALSE);
511 }
512 public void setShowImagesToolBox(boolean showImagesToolBox){
513 getStateHelper().put(PropertyKeys.showImagesToolBox, showImagesToolBox);
514 }
515
516
517
518
519
520
521 public boolean isShowTablesToolBox(){
522 if( isShowAllToolBoxes() )
523 return true;
524
525 return (Boolean) getStateHelper().eval(PropertyKeys.showTablesToolBox, Boolean.FALSE);
526 }
527 public void setShowTablesToolBox(boolean showTablesToolBox){
528 getStateHelper().put(PropertyKeys.showTablesToolBox, showTablesToolBox);
529 }
530
531
532
533
534
535
536 public boolean isShowCleanupExpressionsToolBox(){
537 if( isShowAllToolBoxes() )
538 return true;
539
540 return (Boolean) getStateHelper().eval(PropertyKeys.showCleanupExpressionsToolBox, Boolean.FALSE);
541 }
542 public void setShowCleanupExpressionsToolBox(boolean showCleanupExpressionsToolBox){
543 getStateHelper().put(PropertyKeys.showCleanupExpressionsToolBox, showCleanupExpressionsToolBox);
544 }
545
546
547
548
549
550
551 public boolean isShowDebugToolBox(){
552 if( isShowAllToolBoxes() )
553 return true;
554
555 return (Boolean) getStateHelper().eval(PropertyKeys.showDebugToolBox, Boolean.FALSE);
556 }
557 public void setShowDebugToolBox(boolean showTablesToolBox){
558 getStateHelper().put(PropertyKeys.showDebugToolBox, showTablesToolBox);
559 }
560
561 public boolean isShowAnyToolBox(){
562 return isShowAllToolBoxes()
563 || isShowPropertiesToolBox()
564 || isShowLinksToolBox()
565 || isShowImagesToolBox()
566 || isShowTablesToolBox()
567 || isShowCleanupExpressionsToolBox()
568 || isShowDebugToolBox();
569 }
570
571 public String getValueAsHtmlDocument(FacesContext context){
572 String val = RendererUtils.getStringValue(context, this);
573 if( isHtmlDocument( val ) )
574 return val;
575
576 return "<html><body>"+(val==null ? "" : val)+"</body></html>";
577 }
578
579 private static boolean isHtmlDocument(String text){
580 if( text == null )
581 return false;
582
583 if( text.indexOf("<body>")!=-1 || text.indexOf("<body ")!=-1
584 || text.indexOf("<BODY>")!=-1 || text.indexOf("<BODY ")!=-1 )
585 return true;
586
587 return false;
588 }
589
590 public String getValueFromDocument(String text){
591 if( text == null )
592 return "";
593
594 if( isTypeDocument() )
595 return text.trim();
596
597 if( !isHtmlDocument(text) )
598 return text.trim();
599
600
601 String fragment = getHtmlBody( text );
602 if( fragment.endsWith("<br />") )
603 return fragment.substring(0, fragment.length()-6);
604 return fragment;
605 }
606
607 String getHtmlBody(String html){
608 html = html.trim();
609 if( html.length() == 0 )
610 return "";
611
612 String lcText = html.toLowerCase();
613 int textLength = lcText.length();
614 int bodyStartIndex = -1;
615 while(bodyStartIndex < textLength){
616 bodyStartIndex++;
617 bodyStartIndex = lcText.indexOf("<body", bodyStartIndex);
618 if( bodyStartIndex == -1 )
619 break;
620
621 bodyStartIndex += 5;
622 char c = lcText.charAt(bodyStartIndex);
623 if( c=='>' )
624 break;
625
626 if( c!=' ' && c!='\t' )
627 continue;
628
629 bodyStartIndex = lcText.indexOf('>', bodyStartIndex);
630 break;
631 }
632 bodyStartIndex++;
633
634 int bodyEndIndex = lcText.lastIndexOf("</body>")-1;
635
636 if( bodyStartIndex<0 || bodyEndIndex<0
637 || bodyStartIndex > bodyEndIndex
638 || bodyStartIndex>=textLength || bodyEndIndex>=textLength ){
639
640 if( lcText.indexOf("<body/>")!=-1 || lcText.indexOf("<body />")!=-1 )
641 return "";
642
643 int htmlStartIndex = lcText.indexOf("<html>");
644 int htmlEndIndex = lcText.indexOf("</html>");
645 if( htmlStartIndex != -1 && htmlEndIndex > htmlStartIndex )
646 return html.substring(htmlStartIndex+6, htmlEndIndex);
647
648 if( isTypeDocument() )
649 log.warn("Couldn't extract HTML body from :\n"+html);
650 return html.trim();
651 }
652
653 return html.substring(bodyStartIndex, bodyEndIndex+1).trim();
654 }
655
656 protected enum PropertyKeys
657 {
658 fallback,
659 type,
660 allowEditSource,
661 allowExternalLinks,
662 addKupuLogo,
663 showAllToolBoxes,
664 showPropertiesToolBox,
665 showLinksToolBox,
666 showImagesToolBox,
667 showTablesToolBox,
668 showCleanupExpressionsToolBox,
669 showDebugToolBox,
670 uniqueIdCounter
671 }
672 }