PageRenderTime 42ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 1ms

/projects/netbeans-7.3/php.smarty/src/org/netbeans/modules/php/smarty/editor/TplEditorSupport.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 367 lines | 228 code | 43 blank | 96 comment | 31 complexity | 78a0af65393bb7383ca2171d43fd9987 MD5 | raw file
  1. /*
  2. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  3. *
  4. * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
  5. *
  6. * The contents of this file are subject to the terms of either the GNU
  7. * General Public License Version 2 only ("GPL") or the Common
  8. * Development and Distribution License("CDDL") (collectively, the
  9. * "License"). You may not use this file except in compliance with the
  10. * License. You can obtain a copy of the License at
  11. * http://www.netbeans.org/cddl-gplv2.html
  12. * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  13. * specific language governing permissions and limitations under the
  14. * License. When distributing the software, include this License Header
  15. * Notice in each file and include the License file at
  16. * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
  17. * particular file as subject to the "Classpath" exception as provided
  18. * by Sun in the GPL Version 2 section of the License file that
  19. * accompanied this code. If applicable, add the following below the
  20. * License Header, with the fields enclosed by brackets [] replaced by
  21. * your own identifying information:
  22. * "Portions Copyrighted [year] [name of copyright owner]"
  23. *
  24. * Contributor(s):
  25. *
  26. * The Original Software is NetBeans. The Initial Developer of the Original
  27. * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  28. * Microsystems, Inc. All Rights Reserved.
  29. *
  30. * If you wish your version of this file to be governed by only the CDDL
  31. * or only the GPL Version 2, indicate your decision by adding
  32. * "[Contributor] elects to include this software in this distribution
  33. * under the [CDDL or GPL Version 2] license." If you do not indicate a
  34. * single choice of license, a recipient has the option to distribute
  35. * your version of this file under either the CDDL, the GPL Version 2 or
  36. * to extend the choice of license to its licensees as provided above.
  37. * However, if you add GPL Version 2 code and therefore, elected the GPL
  38. * Version 2 license, then the option applies only if the new code is
  39. * made subject to such option by the copyright holder.
  40. */
  41. package org.netbeans.modules.php.smarty.editor;
  42. import java.io.IOException;
  43. import java.io.ObjectInput;
  44. import java.io.OutputStream;
  45. import java.io.OutputStreamWriter;
  46. import java.io.Writer;
  47. import java.nio.charset.Charset;
  48. import java.nio.charset.CharsetEncoder;
  49. import java.util.logging.Level;
  50. import java.util.logging.Logger;
  51. import javax.swing.text.BadLocationException;
  52. import javax.swing.text.Document;
  53. import javax.swing.text.EditorKit;
  54. import javax.swing.text.StyledDocument;
  55. import org.netbeans.api.queries.FileEncodingQuery;
  56. import org.netbeans.core.api.multiview.MultiViews;
  57. import org.openide.DialogDisplayer;
  58. import org.openide.NotifyDescriptor;
  59. import org.openide.cookies.EditCookie;
  60. import org.openide.cookies.EditorCookie;
  61. import org.openide.cookies.OpenCookie;
  62. import org.openide.cookies.PrintCookie;
  63. import org.openide.cookies.SaveCookie;
  64. import org.openide.filesystems.FileObject;
  65. import org.openide.filesystems.FileLock;
  66. import org.openide.nodes.Node.Cookie;
  67. import org.openide.text.CloneableEditor;
  68. import org.openide.text.CloneableEditorSupport;
  69. import org.openide.text.DataEditorSupport;
  70. import org.openide.util.NbBundle;
  71. import org.openide.util.UserCancelException;
  72. import org.openide.windows.CloneableOpenSupport;
  73. /**
  74. * Editor support for TPL data objects. Most code of this class was get from
  75. * HtmlEditorSupport - especially encoding support.
  76. *
  77. * @author Martin Fousek <marfous@netbeans.org>
  78. */
  79. public final class TplEditorSupport extends DataEditorSupport implements OpenCookie, EditCookie, EditorCookie.Observable, PrintCookie {
  80. private static final String DOCUMENT_SAVE_ENCODING = "Document_Save_Encoding";
  81. private static final String UTF_8_ENCODING = "UTF-8";
  82. /** SaveCookie for this support instance. The cookie is adding/removing
  83. * data object's cookie set depending on if modification flag was set/unset.
  84. * It also invokes beforeSave() method on the TplDataObject to give it
  85. * a chance to eg. reflect changes in 'charset' attribute
  86. * */
  87. private final SaveCookie saveCookie = new SaveCookie() {
  88. /** Implements <code>SaveCookie</code> interface. */
  89. @Override
  90. public void save() throws IOException {
  91. try {
  92. saveDocument();
  93. } catch (UserCancelException uce) {
  94. //just ignore
  95. }
  96. }
  97. };
  98. /** Constructor. */
  99. TplEditorSupport(TplDataObject obj) {
  100. super(obj, null, new Environment(obj));
  101. setMIMEType(obj.getPrimaryFile().getMIMEType());
  102. }
  103. @Override
  104. protected Pane createPane() {
  105. return (CloneableEditorSupport.Pane) MultiViews.createCloneableMultiView(TplDataLoader.MIME_TYPE, getDataObject());
  106. }
  107. @Override
  108. protected boolean asynchronousOpen() {
  109. return true;
  110. }
  111. @Override
  112. public void saveDocument() throws IOException {
  113. updateEncoding();
  114. super.saveDocument();
  115. // DataObject.setModified() already called as part of super.saveDocument(). The save action is now asynchronous
  116. // in the IDE and super.saveDocument() checks for possible extra document modifications performed during save
  117. // and sets the DO.modified flag accordingly.
  118. // TplEditorSupport.this.getDataObject().setModified(false);
  119. }
  120. void updateEncoding() throws UserCancelException {
  121. //try to find encoding specification in the editor content
  122. String documentContent = getDocumentText();
  123. String encoding = TplDataObject.findEncoding(documentContent);
  124. String feqEncoding = FileEncodingQuery.getEncoding(getDataObject().getPrimaryFile()).name();
  125. String finalEncoding = null;
  126. if (encoding != null) {
  127. //found encoding specified in the file content by meta tag
  128. if (!isSupportedEncoding(encoding) || !canEncode(documentContent, encoding)) {
  129. //test if the file can be saved by the original encoding or if it needs to be saved using utf-8
  130. finalEncoding = canEncode(documentContent, feqEncoding) ? feqEncoding : UTF_8_ENCODING;
  131. NotifyDescriptor nd = new NotifyDescriptor.Confirmation(NbBundle.getMessage(TplEditorSupport.class, "MSG_unsupportedEncodingSave", new Object[]{getDataObject().getPrimaryFile().getNameExt(), encoding, finalEncoding, finalEncoding.equals(UTF_8_ENCODING) ? "" : " the original"}), NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.WARNING_MESSAGE);
  132. nd.setValue(NotifyDescriptor.NO_OPTION);
  133. DialogDisplayer.getDefault().notify(nd);
  134. if (nd.getValue() != NotifyDescriptor.YES_OPTION) {
  135. throw new UserCancelException();
  136. }
  137. } else {
  138. finalEncoding = encoding;
  139. }
  140. } else {
  141. //no encoding specified in the file, use FEQ value
  142. if (!canEncode(documentContent, feqEncoding)) {
  143. NotifyDescriptor nd = new NotifyDescriptor.Confirmation(NbBundle.getMessage(TplEditorSupport.class, "MSG_badCharConversionSave", new Object[]{getDataObject().getPrimaryFile().getNameExt(), feqEncoding}), NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.WARNING_MESSAGE);
  144. nd.setValue(NotifyDescriptor.NO_OPTION);
  145. DialogDisplayer.getDefault().notify(nd);
  146. if (nd.getValue() != NotifyDescriptor.YES_OPTION) {
  147. throw new UserCancelException();
  148. } else {
  149. finalEncoding = UTF_8_ENCODING;
  150. }
  151. } else {
  152. finalEncoding = feqEncoding;
  153. }
  154. }
  155. //FEQ cannot be run in saveFromKitToStream since document is locked for writing,
  156. //so setting the FEQ result to document property
  157. Document document = getDocument();
  158. if (document != null) {
  159. document.putProperty(DOCUMENT_SAVE_ENCODING, finalEncoding);
  160. }
  161. }
  162. private String getDocumentText() {
  163. String text = "";
  164. try {
  165. StyledDocument doc = getDocument();
  166. if (doc != null) {
  167. text = doc.getText(doc.getStartPosition().getOffset(), doc.getLength());
  168. }
  169. } catch (BadLocationException e) {
  170. Logger.getLogger("global").log(Level.WARNING, null, e);
  171. }
  172. return text;
  173. }
  174. private boolean canEncode(String docText, String encoding) {
  175. CharsetEncoder encoder = Charset.forName(encoding).newEncoder();
  176. return encoder.canEncode(docText);
  177. }
  178. private boolean isSupportedEncoding(String encoding) {
  179. boolean supported;
  180. try {
  181. supported = java.nio.charset.Charset.isSupported(encoding);
  182. } catch (java.nio.charset.IllegalCharsetNameException e) {
  183. supported = false;
  184. }
  185. return supported;
  186. }
  187. @Override
  188. public void open() {
  189. String encoding = ((TplDataObject) getDataObject()).getFileEncoding();
  190. String feqEncoding = FileEncodingQuery.getEncoding(getDataObject().getPrimaryFile()).name();
  191. if (encoding != null && !isSupportedEncoding(encoding)) {
  192. // if(!canDecodeFile(getDataObject().getPrimaryFile(), feqEncoding)) {
  193. // feqEncoding = UTF_8_ENCODING;
  194. // }
  195. NotifyDescriptor nd = new NotifyDescriptor.Confirmation(
  196. NbBundle.getMessage(TplEditorSupport.class, "MSG_unsupportedEncodingLoad", //NOI18N
  197. new Object[]{getDataObject().getPrimaryFile().getNameExt(),
  198. encoding,
  199. feqEncoding}),
  200. NotifyDescriptor.YES_NO_OPTION,
  201. NotifyDescriptor.WARNING_MESSAGE);
  202. DialogDisplayer.getDefault().notify(nd);
  203. if (nd.getValue() != NotifyDescriptor.YES_OPTION) {
  204. return; // do not open the file
  205. }
  206. }
  207. // if(!canDecodeFile(getDataObject().getPrimaryFile(), feqEncoding)) {
  208. // feqEncoding = UTF_8_ENCODING;
  209. // }
  210. super.open();
  211. }
  212. /**
  213. * @inheritDoc
  214. */
  215. @Override
  216. protected void saveFromKitToStream(StyledDocument doc, EditorKit kit, OutputStream stream) throws IOException, BadLocationException {
  217. String foundEncoding = (String) doc.getProperty(DOCUMENT_SAVE_ENCODING);
  218. String usedEncoding = foundEncoding != null ? foundEncoding : UTF_8_ENCODING;
  219. final Charset c = Charset.forName(usedEncoding);
  220. final Writer w = new OutputStreamWriter(stream, c);
  221. try {
  222. kit.write(w, doc, 0, doc.getLength());
  223. } finally {
  224. w.close();
  225. }
  226. }
  227. @Override
  228. protected StyledDocument createStyledDocument(EditorKit kit) {
  229. StyledDocument doc = super.createStyledDocument(kit);
  230. // see TplKit.createDefaultDocument;
  231. Runnable postInitRunnable = (Runnable) doc.getProperty("postInitRunnable"); //NOI18N
  232. if (postInitRunnable != null) {
  233. postInitRunnable.run();
  234. }
  235. return doc;
  236. }
  237. /**
  238. * Overrides superclass method. Adds adding of save cookie if the document has been marked modified.
  239. * @return true if the environment accepted being marked as modified
  240. * or false if it has refused and the document should remain unmodified
  241. */
  242. @Override
  243. protected boolean notifyModified() {
  244. if (!super.notifyModified()) {
  245. return false;
  246. }
  247. addSaveCookie();
  248. return true;
  249. }
  250. /** Overrides superclass method. Adds removing of save cookie. */
  251. @Override
  252. protected void notifyUnmodified() {
  253. super.notifyUnmodified();
  254. removeSaveCookie();
  255. }
  256. /** Helper method. Adds save cookie to the data object. */
  257. private void addSaveCookie() {
  258. TplDataObject obj = (TplDataObject) getDataObject();
  259. // Adds save cookie to the data object.
  260. if (obj.getCookie(SaveCookie.class) == null) {
  261. obj.getCookieSet0().add(saveCookie);
  262. obj.setModified(true);
  263. }
  264. }
  265. /** Helper method. Removes save cookie from the data object. */
  266. private void removeSaveCookie() {
  267. TplDataObject obj = (TplDataObject) getDataObject();
  268. // Remove save cookie from the data object.
  269. Cookie cookie = obj.getCookie(SaveCookie.class);
  270. if (cookie != null && cookie.equals(saveCookie)) {
  271. obj.getCookieSet0().remove(saveCookie);
  272. obj.setModified(false);
  273. }
  274. }
  275. /** Nested class. Environment for this support. Extends <code>DataEditorSupport.Env</code> abstract class. */
  276. private static class Environment extends DataEditorSupport.Env {
  277. private static final long serialVersionUID = 3035543158452715818L;
  278. /** Constructor. */
  279. public Environment(TplDataObject obj) {
  280. super(obj);
  281. }
  282. /** Implements abstract superclass method. */
  283. @Override
  284. protected FileObject getFile() {
  285. return getDataObject().getPrimaryFile();
  286. }
  287. /** Implements abstract superclass method.*/
  288. @Override
  289. protected FileLock takeLock() throws IOException {
  290. return ((TplDataObject) getDataObject()).getPrimaryEntry().takeLock();
  291. }
  292. /**
  293. * Overrides superclass method.
  294. * @return text editor support (instance of enclosing class)
  295. */
  296. @Override
  297. public CloneableOpenSupport findCloneableOpenSupport() {
  298. return getDataObject().getCookie(TplEditorSupport.class);
  299. }
  300. } // End of nested Environment class.
  301. /** A method to create a new component. Overridden in subclasses.
  302. * @return the {@link TplEditor} for this support
  303. */
  304. @Override
  305. protected CloneableEditor createCloneableEditor() {
  306. return new TplEditor(this);
  307. }
  308. public static class TplEditor extends CloneableEditor {
  309. public TplEditor() {
  310. }
  311. /** Creates new editor */
  312. public TplEditor(TplEditorSupport s) {
  313. super(s);
  314. initialize();
  315. }
  316. private void initialize() {
  317. }
  318. @Override
  319. public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
  320. super.readExternal(in);
  321. initialize();
  322. }
  323. }
  324. }