View Javadoc

1   package pl.caltha.forms.internal.ui;
2   
3   import java.io.ByteArrayInputStream;
4   import java.io.ByteArrayOutputStream;
5   import java.io.PrintWriter;
6   import java.io.StringWriter;
7   import java.util.Properties;
8   
9   import org.w3c.tidy.Tidy;
10  import org.xml.sax.Attributes;
11  
12  import pl.caltha.forms.ConstructionException;
13  import pl.caltha.forms.FormsService;
14  import pl.caltha.forms.internal.model.InstanceImpl;
15  import pl.caltha.forms.internal.util.TidyWrapper;
16  
17  /***
18   * HTML input control. Includes:
19   * <ul>
20   *      <li><code>htmlarea</code></li>
21   * </ul>
22   *
23   * @author <a href="mailto:zwierzem@ngo.pl">Damian Gajda</a>
24   * @version $Id: NodeControlHTML.java,v 1.2 2005/01/20 16:44:52 pablo Exp $
25   */
26  public class NodeControlHTML extends NodeControl
27  {
28      public NodeControlHTML(String type, Attributes atts)
29      throws ConstructionException
30      {
31          super(type, atts);
32      }
33  
34      /*** Tidy configuration. */
35      private static Properties tidyConfiguration;
36      /*** PoolService is used to pool jTidy objects. */
37  
38      //------------------------------------------------------------------------
39      // Control methods
40      //
41      /*** Key for Tidy error log state value. */
42      private String TIDY_ERROR_LOG = "htmlarea.tidyErrorLog";
43  
44      void setValue(InstanceImpl instance, String value)
45      {
46          // clean last error log
47          org.dom4j.Node contextNode = ((ReferenceSingle)ref).getContextNode(instance);
48          instance.setStateValue(contextNode, TIDY_ERROR_LOG, null);
49  
50          // do HTML processing
51          // 1. clean up the value using jTidy
52          // 1.1. get tidy
53          TidyWrapper tidyWrap = new TidyWrapper();
54  
55          try
56          {
57              // 1.2. setup tidy
58              Tidy tidy = tidyWrap.getTidy();
59              tidy.setConfigurationFromProps(tidyConfiguration);
60              tidy.setCharEncoding(org.w3c.tidy.Configuration.UTF8);
61              tidy.setXHTML(true);
62              tidy.setShowWarnings(false);
63              // 1.3. setup streams
64              ByteArrayInputStream inputStream = new ByteArrayInputStream(value.getBytes("UTF-8"));
65              ByteArrayOutputStream outputStream = new ByteArrayOutputStream(value.length()+256);
66              // 1.4. setup error information writer
67              StringWriter errorWriter = new StringWriter(256);
68              tidy.setErrout(new PrintWriter(errorWriter));
69              // 1.5. run cleanup
70              tidy.parse(inputStream, outputStream);
71              // 2. set the value
72              String outputValue;
73              // 2.1. check tidy if there were any errors.
74              if(tidy.getParseErrors() > 0)
75              {
76                  // user must correct the HTML
77                  outputValue = value;
78                  // set error information in state because ErrorCollector
79                  // does not allow to store errors explicitly
80                  String errorLog = errorWriter.toString();
81                  instance.setStateValue(contextNode, TIDY_ERROR_LOG, errorLog);
82              }
83              else
84              // 2.2. get cleaned HTML as String
85              {
86                outputValue = outputStream.toString("UTF-8");
87              }
88              // 2.3. Remove HTML headers and footers
89              outputValue = stripHTMLHead(outputValue);
90              
91              super.setValue(instance, outputValue);
92          }
93          catch(java.io.UnsupportedEncodingException e)
94          {
95              // should never happen
96          }
97          
98          // return tidy wrapper to the pool
99          
100     }
101 
102     /*** Removes everything but <code>&lt;body&gt;</code> tag contents. */
103     private String stripHTMLHead(String htmlDoc)
104     {
105         int bodyStartIndex = htmlDoc.indexOf("<body");
106         int bodyEndIndex = htmlDoc.indexOf("</body>");
107 
108         if(bodyStartIndex > -1)
109         {
110             for(int i = bodyStartIndex; i < bodyEndIndex; i++)
111             {
112                 if(htmlDoc.charAt(i) == '>')
113                 {
114                     bodyStartIndex = i+1;
115                     break;
116                 }
117             }
118 
119             if(bodyStartIndex < bodyEndIndex)
120             {
121                 return htmlDoc.substring(bodyStartIndex, bodyEndIndex);
122             }
123         }
124         
125         return htmlDoc;
126     }
127     
128     public boolean hasError(InstanceImpl instance)
129     {
130         return (getTidyErrorLog(instance) != null);
131     }
132 
133     public String getTidyErrorLog(InstanceImpl instance)
134     {
135         org.dom4j.Node contextNode = ((ReferenceSingle)ref).getContextNode(instance);
136         return (String)(instance.getStateValue(contextNode, TIDY_ERROR_LOG));
137     }
138 
139     //------------------------------------------------------------------------
140     // methods used by UIBuilder
141 
142     /*** Gets a Tidy instance which will be used by this control.
143      */
144     protected void init(UI ui)
145     throws ConstructionException
146     {
147         super.init(ui);
148         FormsService formToolService = ui.getForm().getFormToolService();
149         if(tidyConfiguration == null)
150         {
151             tidyConfiguration = formToolService.getTidyConfiguration();
152         }
153     }
154 }