PageRenderTime 45ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/myfaces_core-2.1.10/src/myfaces-impl-2.1.10-sources/org/apache/myfaces/view/facelets/compiler/TextUnit.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 650 lines | 507 code | 60 blank | 83 comment | 85 complexity | c15fb51bbd1a34aaa0050dbbac2e02c5 MD5 | raw file
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19. package org.apache.myfaces.view.facelets.compiler;
  20. import java.util.ArrayList;
  21. import java.util.Iterator;
  22. import java.util.List;
  23. import java.util.Stack;
  24. import javax.el.ELException;
  25. import javax.faces.application.FacesMessage;
  26. import javax.faces.view.facelets.CompositeFaceletHandler;
  27. import javax.faces.view.facelets.FaceletHandler;
  28. import javax.faces.view.facelets.Tag;
  29. import javax.faces.view.facelets.TagAttribute;
  30. import javax.faces.view.facelets.TagException;
  31. import org.apache.myfaces.shared.renderkit.html.HTML;
  32. import org.apache.myfaces.view.facelets.el.ELText;
  33. /**
  34. *
  35. * @author Jacob Hookom
  36. * @version $Id: TextUnit.java 1390212 2012-09-25 23:17:29Z lu4242 $
  37. */
  38. final class TextUnit extends CompilationUnit
  39. {
  40. private final StringBuffer buffer;
  41. private final StringBuffer textBuffer;
  42. private final List<Instruction> instructionBuffer;
  43. private final Stack<Tag> tags;
  44. private final List<Object> children;
  45. private boolean startTagOpen;
  46. private final String alias;
  47. private final String id;
  48. private final List<Object> messages;
  49. private final boolean escapeInlineText;
  50. private final boolean compressSpaces;
  51. public TextUnit(String alias, String id)
  52. {
  53. this(alias,id,true);
  54. }
  55. public TextUnit(String alias, String id, boolean escapeInlineText)
  56. {
  57. this(alias,id,escapeInlineText,false);
  58. }
  59. public TextUnit(String alias, String id, boolean escapeInlineText, boolean compressSpaces)
  60. {
  61. this.alias = alias;
  62. this.id = id;
  63. this.buffer = new StringBuffer();
  64. this.textBuffer = new StringBuffer();
  65. this.instructionBuffer = new ArrayList<Instruction>();
  66. this.tags = new Stack<Tag>();
  67. this.children = new ArrayList<Object>();
  68. this.startTagOpen = false;
  69. this.messages = new ArrayList<Object>(4);
  70. this.escapeInlineText = escapeInlineText;
  71. this.compressSpaces = compressSpaces;
  72. }
  73. public FaceletHandler createFaceletHandler()
  74. {
  75. this.flushBufferToConfig(true);
  76. if (this.children.size() == 0)
  77. {
  78. return LEAF;
  79. }
  80. FaceletHandler[] h = new FaceletHandler[this.children.size()];
  81. Object obj;
  82. for (int i = 0; i < h.length; i++)
  83. {
  84. obj = this.children.get(i);
  85. if (obj instanceof FaceletHandler)
  86. {
  87. h[i] = (FaceletHandler) obj;
  88. }
  89. else
  90. {
  91. h[i] = ((CompilationUnit) obj).createFaceletHandler();
  92. }
  93. }
  94. if (h.length == 1)
  95. {
  96. return h[0];
  97. }
  98. return new CompositeFaceletHandler(h);
  99. }
  100. private void addInstruction(Instruction instruction)
  101. {
  102. this.flushTextBuffer(false);
  103. this.instructionBuffer.add(instruction);
  104. }
  105. private void flushTextBuffer(boolean child)
  106. {
  107. if (this.textBuffer.length() > 0)
  108. {
  109. String s = this.textBuffer.toString();
  110. if (child)
  111. {
  112. s = trimRight(s);
  113. }
  114. if (s.length() > 0)
  115. {
  116. if (!compressSpaces)
  117. {
  118. //Do it as usual.
  119. ELText txt = ELText.parse(s);
  120. if (txt != null)
  121. {
  122. if (txt.isLiteral())
  123. {
  124. if (escapeInlineText)
  125. {
  126. this.instructionBuffer.add(new LiteralTextInstruction(txt.toString()));
  127. }
  128. else
  129. {
  130. this.instructionBuffer.add(new LiteralNonExcapedTextInstruction(txt.toString()));
  131. }
  132. }
  133. else
  134. {
  135. this.instructionBuffer.add(new TextInstruction(this.alias, txt ));
  136. }
  137. }
  138. }
  139. else
  140. {
  141. // First check if the text contains EL before build something, and if contains
  142. // an EL expression, compress it before build the ELText.
  143. if (s != null && s.length() > 0)
  144. {
  145. if (ELText.isLiteral(s))
  146. {
  147. if (escapeInlineText)
  148. {
  149. this.instructionBuffer.add(new LiteralTextInstruction(s));
  150. }
  151. else
  152. {
  153. this.instructionBuffer.add(new LiteralNonExcapedTextInstruction(s));
  154. }
  155. }
  156. else
  157. {
  158. s = compressELText(s);
  159. this.instructionBuffer.add(new TextInstruction(this.alias, ELText.parse(s) ));
  160. }
  161. }
  162. }
  163. }
  164. }
  165. this.textBuffer.setLength(0);
  166. }
  167. public void write(String text)
  168. {
  169. this.finishStartTag();
  170. this.textBuffer.append(text);
  171. this.buffer.append(text);
  172. }
  173. public void writeInstruction(String text)
  174. {
  175. this.finishStartTag();
  176. ELText el = ELText.parse(text);
  177. if (el.isLiteral())
  178. {
  179. this.addInstruction(new LiteralXMLInstruction(text));
  180. }
  181. else
  182. {
  183. this.addInstruction(new XMLInstruction(el));
  184. }
  185. this.buffer.append(text);
  186. }
  187. public void writeComment(String text)
  188. {
  189. this.finishStartTag();
  190. ELText el = ELText.parse(text);
  191. if (el.isLiteral())
  192. {
  193. this.addInstruction(new LiteralCommentInstruction(text));
  194. }
  195. else
  196. {
  197. this.addInstruction(new CommentInstruction(el));
  198. }
  199. this.buffer.append("<!--" + text + "-->");
  200. }
  201. public void startTag(Tag tag)
  202. {
  203. // finish any previously written tags
  204. this.finishStartTag();
  205. // push this tag onto the stack
  206. this.tags.push(tag);
  207. // write it out
  208. this.buffer.append('<');
  209. this.buffer.append(tag.getQName());
  210. this.addInstruction(new StartElementInstruction(tag.getQName()));
  211. TagAttribute[] attrs = tag.getAttributes().getAll();
  212. if (attrs.length > 0)
  213. {
  214. for (int i = 0; i < attrs.length; i++)
  215. {
  216. String qname = attrs[i].getQName();
  217. String value = attrs[i].getValue();
  218. this.buffer.append(' ').append(qname).append("=\"").append(value).append("\"");
  219. ELText txt = ELText.parse(value);
  220. if (txt != null)
  221. {
  222. if (txt.isLiteral())
  223. {
  224. this.addInstruction(new LiteralAttributeInstruction(qname, txt.toString()));
  225. }
  226. else
  227. {
  228. this.addInstruction(new AttributeInstruction(this.alias, qname, txt));
  229. }
  230. }
  231. }
  232. }
  233. if (!messages.isEmpty())
  234. {
  235. for (Iterator<Object> it = messages.iterator(); it.hasNext();)
  236. {
  237. Object[] message = (Object[])it.next();
  238. this.addInstruction(new AddFacesMessageInstruction((FacesMessage.Severity) message[0],
  239. (String)message[1], (String)message[2]));
  240. it.remove();
  241. }
  242. }
  243. // notify that we have an open tag
  244. this.startTagOpen = true;
  245. }
  246. private void finishStartTag()
  247. {
  248. if (this.tags.size() > 0 && this.startTagOpen)
  249. {
  250. this.buffer.append(">");
  251. this.startTagOpen = false;
  252. }
  253. }
  254. public void endTag()
  255. {
  256. Tag tag = (Tag) this.tags.pop();
  257. if (HTML.BODY_ELEM.equalsIgnoreCase(tag.getQName()))
  258. {
  259. this.addInstruction(new BodyEndElementInstruction(tag.getQName()));
  260. }
  261. else
  262. {
  263. this.addInstruction(new EndElementInstruction(tag.getQName()));
  264. }
  265. if (this.startTagOpen)
  266. {
  267. this.buffer.append("/>");
  268. this.startTagOpen = false;
  269. }
  270. else
  271. {
  272. this.buffer.append("</").append(tag.getQName()).append('>');
  273. }
  274. }
  275. public void addChild(CompilationUnit unit)
  276. {
  277. // if we are adding some other kind of unit
  278. // then we need to capture our buffer into a UITextHandler
  279. this.finishStartTag();
  280. this.flushBufferToConfig(true);
  281. this.children.add(unit);
  282. }
  283. protected void flushBufferToConfig(boolean child)
  284. {
  285. // NEW IMPLEMENTATION
  286. if (true)
  287. {
  288. this.flushTextBuffer(child);
  289. int size = this.instructionBuffer.size();
  290. if (size > 0)
  291. {
  292. try
  293. {
  294. String s = this.buffer.toString();
  295. if (child)
  296. {
  297. s = trimRight(s);
  298. }
  299. ELText txt = ELText.parse(s);
  300. if (txt != null)
  301. {
  302. if (compressSpaces)
  303. {
  304. // Use the logic behind the instructions to remove unnecessary instructions
  305. // containing only spaces, or recreating new ones containing only the necessary
  306. // spaces.
  307. size = compressSpaces(instructionBuffer, size);
  308. }
  309. Instruction[] instructions = (Instruction[]) this.instructionBuffer
  310. .toArray(new Instruction[size]);
  311. this.children.add(new UIInstructionHandler(this.alias, this.id, instructions, txt));
  312. this.instructionBuffer.clear();
  313. }
  314. }
  315. catch (ELException e)
  316. {
  317. if (this.tags.size() > 0)
  318. {
  319. throw new TagException((Tag) this.tags.peek(), e.getMessage());
  320. }
  321. else
  322. {
  323. throw new ELException(this.alias + ": " + e.getMessage(), e.getCause());
  324. }
  325. }
  326. }
  327. // KEEP THESE SEPARATE SO LOGIC DOESN'T GET FUBARED
  328. }
  329. else if (this.buffer.length() > 0)
  330. {
  331. String s = this.buffer.toString();
  332. if (s.trim().length() > 0)
  333. {
  334. if (child)
  335. {
  336. s = trimRight(s);
  337. }
  338. if (s.length() > 0)
  339. {
  340. try
  341. {
  342. ELText txt = ELText.parse(s);
  343. if (txt != null)
  344. {
  345. if (txt.isLiteral())
  346. {
  347. this.children.add(new UILiteralTextHandler(txt.toString()));
  348. }
  349. else
  350. {
  351. this.children.add(new UITextHandler(this.alias, txt));
  352. }
  353. }
  354. }
  355. catch (ELException e)
  356. {
  357. if (this.tags.size() > 0)
  358. {
  359. throw new TagException((Tag) this.tags.peek(), e.getMessage());
  360. }
  361. else
  362. {
  363. throw new ELException(this.alias + ": " + e.getMessage(), e.getCause());
  364. }
  365. }
  366. }
  367. }
  368. }
  369. // ALWAYS CLEAR FOR BOTH IMPL
  370. this.buffer.setLength(0);
  371. }
  372. public boolean isClosed()
  373. {
  374. return this.tags.empty();
  375. }
  376. private final static String trimRight(String s)
  377. {
  378. int i = s.length() - 1;
  379. while (i >= 0 && Character.isWhitespace(s.charAt(i)))
  380. {
  381. i--;
  382. }
  383. if (i >= 0)
  384. {
  385. return s;
  386. }
  387. else
  388. {
  389. return "";
  390. }
  391. /*
  392. if (i == s.length() - 1)
  393. {
  394. return s;
  395. }
  396. else
  397. {
  398. return s.substring(0, i + 1);
  399. }*/
  400. }
  401. final static String compressELText(String text)
  402. {
  403. int firstCharLocation = getFirstTextCharLocationIgnoringSpacesTabsAndCarriageReturn(text);
  404. int lastCharLocation = getLastTextCharLocationIgnoringSpacesTabsAndCarriageReturn(text);
  405. if (firstCharLocation == 0 && lastCharLocation == text.length()-1)
  406. {
  407. return text;
  408. }
  409. else
  410. {
  411. if (lastCharLocation+1 < text.length())
  412. {
  413. lastCharLocation = lastCharLocation+1;
  414. }
  415. if (firstCharLocation == 0)
  416. {
  417. return text.substring(firstCharLocation, lastCharLocation+1);
  418. }
  419. else
  420. {
  421. return text.substring(0,1)+text.substring(firstCharLocation, lastCharLocation+1);
  422. }
  423. }
  424. }
  425. /*
  426. final static ELText compressELText(ELText parsedText, String text)
  427. {
  428. int firstCharLocation = getFirstTextCharLocationIgnoringSpacesTabsAndCarriageReturn(text);
  429. int lastCharLocation = getLastTextCharLocationIgnoringSpacesTabsAndCarriageReturn(text);
  430. if (firstCharLocation == 0 && lastCharLocation == text.length()-1)
  431. {
  432. return parsedText;
  433. }
  434. else
  435. {
  436. if (lastCharLocation+1 < text.length())
  437. {
  438. lastCharLocation = lastCharLocation+1;
  439. }
  440. if (firstCharLocation == 0)
  441. {
  442. return ELText.parse(text.substring(firstCharLocation, lastCharLocation+1));
  443. }
  444. else
  445. {
  446. return ELText.parse(text.substring(0,1)+text.substring(firstCharLocation, lastCharLocation+1));
  447. }
  448. }
  449. }
  450. */
  451. final static int compressSpaces(List<Instruction> instructionBuffer, int size)
  452. {
  453. boolean addleftspace = true;
  454. boolean addrightspace = false;
  455. for (int i = 0; i < size; i++)
  456. {
  457. Instruction ins = instructionBuffer.get(i);
  458. if (i+1 == size)
  459. {
  460. addrightspace = true;
  461. }
  462. //boolean isNextStartExpression = i+1<size ?
  463. // (this.instructions[i+1] instanceof StartElementInstruction) : false;
  464. if (ins instanceof LiteralTextInstruction)
  465. {
  466. String text = ((LiteralTextInstruction)ins).getText();
  467. int firstCharLocation = getFirstTextCharLocationIgnoringSpacesTabsAndCarriageReturn(text);
  468. if (firstCharLocation == text.length() && text.length() > 1)
  469. {
  470. // All the instruction is space, replace with an instruction
  471. // with only one space
  472. if (addleftspace || addrightspace)
  473. {
  474. instructionBuffer.set(i, new LiteralTextInstruction(text.substring(0,1)));
  475. }
  476. else
  477. {
  478. instructionBuffer.remove(i);
  479. i--;
  480. size--;
  481. }
  482. }
  483. else if (firstCharLocation > 0)
  484. {
  485. int lastCharLocation = getLastTextCharLocationIgnoringSpacesTabsAndCarriageReturn(text);
  486. // If right space, increment in 1
  487. if (lastCharLocation+1 < text.length())
  488. {
  489. lastCharLocation = lastCharLocation+1;
  490. }
  491. instructionBuffer.set(i, new LiteralTextInstruction(
  492. text.substring(0,1)+text.substring(firstCharLocation, lastCharLocation+1)));
  493. }
  494. else
  495. {
  496. int lastCharLocation = getLastTextCharLocationIgnoringSpacesTabsAndCarriageReturn(text);
  497. // If right space, increment in 1
  498. if (lastCharLocation+1 < text.length())
  499. {
  500. lastCharLocation = lastCharLocation+1;
  501. }
  502. instructionBuffer.set(i, new LiteralTextInstruction(
  503. text.substring(firstCharLocation, lastCharLocation+1)));
  504. }
  505. }
  506. else if (ins instanceof LiteralNonExcapedTextInstruction)
  507. {
  508. String text = ((LiteralTextInstruction)ins).getText();
  509. int firstCharLocation = getFirstTextCharLocationIgnoringSpacesTabsAndCarriageReturn(text);
  510. if (firstCharLocation == text.length())
  511. {
  512. // All the instruction is space, replace with an instruction
  513. // with only one space
  514. if (addleftspace || addrightspace)
  515. {
  516. instructionBuffer.set(i, new LiteralNonExcapedTextInstruction(text.substring(0,1)));
  517. }
  518. else
  519. {
  520. instructionBuffer.remove(i);
  521. i--;
  522. size--;
  523. }
  524. }
  525. else if (firstCharLocation > 1)
  526. {
  527. int lastCharLocation = getLastTextCharLocationIgnoringSpacesTabsAndCarriageReturn(text);
  528. // If right space, increment in 1
  529. if (lastCharLocation+1 < text.length())
  530. {
  531. lastCharLocation = lastCharLocation+1;
  532. }
  533. instructionBuffer.set(i, new LiteralNonExcapedTextInstruction(
  534. text.substring(0,1)+text.substring(firstCharLocation, lastCharLocation+1)));
  535. }
  536. else
  537. {
  538. int lastCharLocation = getLastTextCharLocationIgnoringSpacesTabsAndCarriageReturn(text);
  539. // If right space, increment in 1
  540. if (lastCharLocation+1 < text.length())
  541. {
  542. lastCharLocation = lastCharLocation+1;
  543. }
  544. instructionBuffer.set(i, new LiteralNonExcapedTextInstruction(
  545. text.substring(firstCharLocation, lastCharLocation+1)));
  546. }
  547. }
  548. addleftspace = false;
  549. }
  550. return size;
  551. }
  552. private static int getFirstTextCharLocationIgnoringSpacesTabsAndCarriageReturn(String text)
  553. {
  554. for (int i = 0; i < text.length(); i++)
  555. {
  556. if (Character.isWhitespace(text.charAt(i)))
  557. {
  558. continue;
  559. }
  560. else
  561. {
  562. return i;
  563. }
  564. }
  565. return text.length();
  566. }
  567. private static int getLastTextCharLocationIgnoringSpacesTabsAndCarriageReturn(String text)
  568. {
  569. for (int i = text.length()-1; i >= 0; i--)
  570. {
  571. if (Character.isWhitespace(text.charAt(i)))
  572. {
  573. continue;
  574. }
  575. else
  576. {
  577. return i;
  578. }
  579. }
  580. return 0;
  581. }
  582. public String toString()
  583. {
  584. return "TextUnit[" + this.children.size() + "]";
  585. }
  586. public void addMessage(FacesMessage.Severity severity, String summary, String detail)
  587. {
  588. this.messages.add(new Object[]{severity, summary, detail});
  589. }
  590. }