Coverage Report - net.fckeditor.FCKeditor
 
Classes in this File Line Coverage Branch Coverage Complexity
FCKeditor
17%
18/105
23%
6/26
2,118
 
 1  
 /*
 2  
  * FCKeditor - The text editor for Internet - http://www.fckeditor.net
 3  
  * Copyright (C) 2004-2010 Frederico Caldeira Knabben
 4  
  * 
 5  
  * == BEGIN LICENSE ==
 6  
  * 
 7  
  * Licensed under the terms of any of the following licenses at your
 8  
  * choice:
 9  
  * 
 10  
  *  - GNU General Public License Version 2 or later (the "GPL")
 11  
  *    http://www.gnu.org/licenses/gpl.html
 12  
  * 
 13  
  *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
 14  
  *    http://www.gnu.org/licenses/lgpl.html
 15  
  * 
 16  
  *  - Mozilla Public License Version 1.1 or later (the "MPL")
 17  
  *    http://www.mozilla.org/MPL/MPL-1.1.html
 18  
  * 
 19  
  * == END LICENSE ==
 20  
  */
 21  
 package net.fckeditor;
 22  
 
 23  
 import javax.servlet.http.HttpServletRequest;
 24  
 
 25  
 import net.fckeditor.handlers.PropertiesLoader;
 26  
 import net.fckeditor.tool.Compatibility;
 27  
 import net.fckeditor.tool.Utils;
 28  
 import net.fckeditor.tool.XHtmlTagTool;
 29  
 
 30  
 /**
 31  
  * Java representation of the <a href="http://docs.fckeditor.net/FCKeditor_2.x/Developers_Guide/Server_Side_Integration#FCKeditor_Creator"
 32  
  * target="_blank">FCKeditor</a>. This representation reflects the editor in an
 33  
  * object-oriented way. It can be configured as any other JavaBean type class.
 34  
  * The final output of this class is HTML code.<br />
 35  
  * <strong>Note:</strong> It's your responsibility to supply reasonable and
 36  
  * valid values, only {@code request}, {@code instanceName} and {@code inputName}
 37  
  * will be checked for sanity.
 38  
  * 
 39  
  * @version $Id: FCKeditor.java 4785 2009-12-21 20:10:28Z mosipov $
 40  
  */
 41  
 public class FCKeditor {
 42  
 
 43  6
         private FCKeditorConfig fckConfig = new FCKeditorConfig();
 44  
         private String instanceName;
 45  
         private String inputName;
 46  
         private HttpServletRequest request;
 47  
 
 48  
         // defaults
 49  6
         private String value = Utils.EMPTY_STRING;
 50  6
         private String toolbarSet = PropertiesLoader.getEditorToolbarSet();
 51  6
         private String width = PropertiesLoader.getEditorWidth();
 52  6
         private String height = PropertiesLoader.getEditorHeight();
 53  6
         private String basePath = PropertiesLoader.getEditorBasePath();
 54  
 
 55  
         /**
 56  
          * Class constructor with all parameters.
 57  
          * 
 58  
          * @param request
 59  
          *            current user request instance
 60  
          * @param instanceName
 61  
          *            the unique name of this editor
 62  
          * @param inputName
 63  
          *            the name for the underlying input element. See
 64  
          *            {@link #setInputName(String)} for details.
 65  
          * @param width
 66  
          *            the desired editor width (CSS-style value)
 67  
          * @param height
 68  
          *            the desired editor height (CSS-style value)
 69  
          * @param toolbarSet
 70  
          *            the desired toolbar set name
 71  
          * @param value
 72  
          *            the HTML markup of this editor. Markup will be properly
 73  
          *            escaped.
 74  
          * @param basePath
 75  
          *            the base path of this editor, absolute to the context
 76  
          * @throws IllegalArgumentException
 77  
          *             if instanceName is empty or not a valid XHTML id
 78  
          */
 79  
         public FCKeditor(HttpServletRequest request, String instanceName,
 80  
                         String inputName, String width, String height, String toolbarSet,
 81  
                         String value, String basePath) {
 82  
                 
 83  0
                 this(request, instanceName, inputName);
 84  0
                 this.width = width;
 85  0
                 this.height = height;
 86  0
                 this.toolbarSet = toolbarSet;
 87  0
                 this.value = value;
 88  0
                 this.basePath = basePath;
 89  
                 
 90  0
         }
 91  
 
 92  
         /**
 93  
          * Class constructor with a extended set of parameters.
 94  
          * 
 95  
          * @param request
 96  
          *            current user request instance
 97  
          * @param instanceName
 98  
          *            the unique name of this editor
 99  
          * @param width
 100  
          *            the desired editor width (CSS-style value)
 101  
          * @param height
 102  
          *            the desired editor height (CSS-style value)
 103  
          * @param toolbarSet
 104  
          *            the desired toolbar set name
 105  
          * @param value
 106  
          *            the HTML markup of this editor. Markup will be properly
 107  
          *            escaped.
 108  
          * @param basePath
 109  
          *            the base path of this editor, absolute to the context
 110  
          * @throws IllegalArgumentException
 111  
          *             if instanceName is empty or not a valid XHTML id
 112  
          */
 113  
         public FCKeditor(final HttpServletRequest request,
 114  
                         final String instanceName, final String width, final String height,
 115  
                         final String toolbarSet, final String value, final String basePath) {
 116  
 
 117  0
                 this(request, instanceName, null, width, height, toolbarSet, value,
 118  
                                 basePath);
 119  
 
 120  0
         }
 121  
 
 122  
         /**
 123  
          * Class constructor with a minimal set of parameters.
 124  
          * 
 125  
          * Omitted parameters will be set to default values.
 126  
          * 
 127  
          * @param request
 128  
          *            current user request instance
 129  
          * @param instanceName
 130  
          *            the unique name of this editor
 131  
          * @throws IllegalArgumentException
 132  
          *             if instanceName is empty or not a valid HTML id
 133  
          */
 134  6
         public FCKeditor(final HttpServletRequest request, final String instanceName) {
 135  
 
 136  6
                 if (request == null)
 137  1
                         throw new NullPointerException("the request cannot be null");
 138  5
                 this.request = request;
 139  
 
 140  5
                 setInstanceName(instanceName);
 141  
 
 142  1
         }
 143  
 
 144  
         /**
 145  
          * Class constructor with a basic set of parameters.
 146  
          * 
 147  
          * Omitted parameters will be set to default values.
 148  
          * 
 149  
          * @param request
 150  
          *            current user request instance
 151  
          * @param instanceName
 152  
          *            the unique name of this editor
 153  
          * @param inputName
 154  
          *            the name for the underlying input element. See
 155  
          *            {@link #setInputName(String)} for details.
 156  
          * @throws IllegalArgumentException
 157  
          *             if instanceName is empty or not a valid HTML id
 158  
          */
 159  
         public FCKeditor(HttpServletRequest request, String instanceName,
 160  
                         String inputName) {
 161  0
                 this(request, instanceName);
 162  0
                 setInputName(inputName);
 163  0
         }
 164  
 
 165  
         /**
 166  
          * Sets the unique name of this editor.
 167  
          * 
 168  
          * @param instanceName
 169  
          *            the unique name of this editor
 170  
          * @throws IllegalArgumentException
 171  
          *             if instanceName is empty or not a valid XHTML id
 172  
          */
 173  
         public void setInstanceName(final String instanceName) {
 174  5
                 if (Utils.isEmpty(instanceName))
 175  2
                         throw new IllegalArgumentException("instanceName cannot be empty");
 176  3
                 if (!instanceName.matches("\\p{Alpha}[\\p{Alnum}:_.-]*"))
 177  2
                         throw new IllegalArgumentException(
 178  
                                         "instanceName must be a valid XHTML id containing only \"\\p{Alpha}[\\p{Alnum}:_.-]*\"");
 179  1
                 this.instanceName = instanceName;
 180  1
         }
 181  
         
 182  
         /**
 183  
          * Sets the name for the underlying input element. Empty strings will be
 184  
          * ignored and field will be reset to {@code instanceName}.
 185  
          * 
 186  
          * @param inputName
 187  
          *            the name for the underlying input element
 188  
          */
 189  
         public void setInputName(final String inputName) {
 190  0
                 if (Utils.isEmpty(inputName))
 191  0
                         this.inputName = instanceName;
 192  
                 else
 193  0
                         this.inputName = inputName;
 194  0
         }
 195  
 
 196  
         /**
 197  
          * Sets the initial value to be edited as HTML markup.
 198  
          * 
 199  
          * @param value
 200  
          *            the HTML markup of this editor. Markup will be properly
 201  
          *            escaped.
 202  
          */
 203  
         public void setValue(final String value) {
 204  0
                 this.value = value;
 205  0
         }
 206  
 
 207  
         /**
 208  
          * Sets the base path of this editor. The base path reflects the location of
 209  
          * the editor files absolute to the context root <i>not</i> the server root.
 210  
          * 
 211  
          * @param basePath
 212  
          *            the base path of this editor, absolute to the context
 213  
          */
 214  
         public void setBasePath(final String basePath) {
 215  0
                 this.basePath = basePath;
 216  0
         }
 217  
 
 218  
         /**
 219  
          * Sets the name of the toolbar set of this editor.
 220  
          * 
 221  
          * @param toolbarSet
 222  
          *            the desired toolbar set name
 223  
          */
 224  
         public void setToolbarSet(final String toolbarSet) {
 225  0
                 this.toolbarSet = toolbarSet;
 226  0
         }
 227  
 
 228  
         /**
 229  
          * Sets the width of this editor. This value can be any valid CSS width
 230  
          * value.
 231  
          * 
 232  
          * @param width
 233  
          *            the desired editor width (CSS-style value)
 234  
          */
 235  
         public void setWidth(final String width) {
 236  0
                 this.width = width;
 237  0
         }
 238  
 
 239  
         /**
 240  
          * Sets the height of this editor. This value can be any valid CSS height
 241  
          * value.
 242  
          * 
 243  
          * @param height
 244  
          *            the desired editor height (CSS-style value)
 245  
          */
 246  
         public void setHeight(final String height) {
 247  0
                 this.height = height;
 248  0
         }
 249  
 
 250  
         /**
 251  
          * Returns a configuration option. See {@link FCKeditorConfig} for more
 252  
          * details.
 253  
          * 
 254  
          * @param name
 255  
          *            the name of the parameter (case-sensitive)
 256  
          * @return the value represented by this parameter, else null
 257  
          */
 258  
         public String getConfig(String name) {
 259  0
                 return fckConfig.get(name);
 260  
         }
 261  
 
 262  
         /**
 263  
          * Sets a configuration option. See {@link FCKeditorConfig} for more
 264  
          * details.
 265  
          * 
 266  
          * @param name
 267  
          *            the name of the config option (case-sensitive)
 268  
          * @param value
 269  
          *            the value of the config option. Null values will be ignored.
 270  
          */
 271  
         public void setConfig(String name, String value) {
 272  0
                 if (value != null)
 273  0
                         fckConfig.put(name, value);
 274  0
         }
 275  
 
 276  
         /**
 277  
          * Escapes base XML entities as specified <a
 278  
          * href="http://en.wikipedia.org/wiki/Xml#Entity_references">here</a>.
 279  
          * 
 280  
          * @param str
 281  
          *            string to escape, empty strings will be ignored
 282  
          * @return escaped string
 283  
          */
 284  
         private String escapeXml(String str) {
 285  
 
 286  0
                 if (Utils.isEmpty(str))
 287  0
                         return str;
 288  
 
 289  0
                 StringBuffer sb = new StringBuffer();
 290  
 
 291  0
                 int len = str.length();
 292  
                 char c;
 293  
 
 294  0
                 for (int i = 0; i < len; i++) {
 295  
 
 296  0
                         c = str.charAt(i);
 297  0
                         switch (c) {
 298  
                         case '&':
 299  0
                                 sb.append("&amp;");
 300  0
                                 break;
 301  
                         case '<':
 302  0
                                 sb.append("&lt;");
 303  0
                                 break;
 304  
                         case '>':
 305  0
                                 sb.append("&gt;");
 306  0
                                 break;
 307  
                         case '"':
 308  0
                                 sb.append("&quot;");
 309  0
                                 break;
 310  
                         // XML actually defines &apos; as entity for the apostrophe but we
 311  
                         // user rather the numerical reference to avoid XHTML 1.0 validation
 312  
                         // problems
 313  
                         case '\'':
 314  0
                                 sb.append("&#39;");
 315  0
                                 break;
 316  
                         default:
 317  0
                                 sb.append(c);
 318  
                                 break;
 319  
                         }
 320  
                 }
 321  
 
 322  0
                 return sb.toString();
 323  
         }
 324  
 
 325  
         /**
 326  
          * Creates the HTML representation of this editor instance. First of all,
 327  
          * this method determines whether the request browser is supported.
 328  
          * According to the result an appropriate HTML representation is assembled
 329  
          * and returned.
 330  
          * 
 331  
          * @return HTML representation of this editor instance
 332  
          */
 333  
         @Override
 334  
         public String toString() {
 335  0
                 StringBuffer strEditor = new StringBuffer();
 336  
 
 337  0
                 strEditor.append("<div>");
 338  0
                 String encodedValue = escapeXml(value);
 339  
                 
 340  
                 /*
 341  
                  * We have to reset inputName to make sure that a potentially reassigned
 342  
                  * instanceName has been propagated to empty field.
 343  
                  */
 344  0
                 setInputName(inputName);
 345  
 
 346  0
                 if (Compatibility.isCompatibleBrowser(request)) {
 347  0
                         strEditor.append(createInputForVariable(instanceName, inputName,
 348  
                                         encodedValue));
 349  
 
 350  
                         // create config HTML
 351  0
                         String configStr = fckConfig.getUrlParams();
 352  0
                         if (Utils.isNotEmpty(configStr))
 353  0
                                 strEditor.append(createInputForVariable(instanceName
 354  
                                                 .concat("___Config"), null, configStr));
 355  
 
 356  
                         // create IFrame
 357  0
                         StringBuffer editorLink = new StringBuffer(request.getContextPath());
 358  0
                         editorLink.append(basePath);
 359  0
                         editorLink.append("/editor/fckeditor.html?InstanceName=").append(
 360  
                                         instanceName);
 361  0
                         if (Utils.isNotEmpty(toolbarSet))
 362  0
                                 editorLink.append("&amp;Toolbar=").append(toolbarSet);
 363  
 
 364  0
                         XHtmlTagTool iframeTag = new XHtmlTagTool("iframe",
 365  
                                         XHtmlTagTool.SPACE);
 366  0
                         iframeTag.addAttribute("id", instanceName.concat("___Frame"));
 367  0
                         iframeTag.addAttribute("src", editorLink.toString());
 368  0
                         iframeTag.addAttribute("width", width);
 369  0
                         iframeTag.addAttribute("height", height);
 370  0
                         iframeTag.addAttribute("frameborder", "0");
 371  0
                         iframeTag.addAttribute("scrolling", "no");
 372  0
                         strEditor.append(iframeTag);
 373  
 
 374  0
                 } else {
 375  0
                         XHtmlTagTool textareaTag = new XHtmlTagTool("textarea",
 376  
                                         encodedValue);
 377  0
                         textareaTag.addAttribute("name", inputName);
 378  0
                         textareaTag.addAttribute("rows", "4");
 379  0
                         textareaTag.addAttribute("cols", "40");
 380  0
                         textareaTag.addAttribute("wrap", "virtual");
 381  0
                         textareaTag.addAttribute("style", "width: ".concat(width).concat(
 382  
                                         "; height: ").concat(height));
 383  
                 }
 384  0
                 strEditor.append("</div>");
 385  0
                 return strEditor.toString();
 386  
         }
 387  
 
 388  
         /**
 389  
          * Creates the HTML representation of this editor instance.
 390  
          * 
 391  
          * @see #toString()
 392  
          * @return HTML representation of this editor instance
 393  
          */
 394  
         public String createHtml() {
 395  0
                 return toString();
 396  
         }
 397  
 
 398  
         /**
 399  
          * Creates a hidden input element for the given attributes.
 400  
          * @param id
 401  
          *            id attribute of the input tag
 402  
          * @param name
 403  
          *            name attribute of the input tag
 404  
          * @param value
 405  
          *            value attribute of the input tag
 406  
          * 
 407  
          * @return the produced XHTML tag
 408  
          */
 409  
         private String createInputForVariable(final String id, final String name,
 410  
                         final String value) {
 411  0
                 XHtmlTagTool tag = new XHtmlTagTool("input");
 412  0
                 tag.addAttribute("id", id);
 413  0
                 tag.addAttribute("name", name);
 414  0
                 tag.addAttribute("value", value);
 415  0
                 tag.addAttribute("type", "hidden");
 416  0
                 return tag.toString();
 417  
         }
 418  
 }