PageRenderTime 29ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/netbeans-7.3/editor.settings.storage/src/org/netbeans/modules/editor/settings/storage/preferences/PreferencesStorage.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 396 lines | 266 code | 59 blank | 71 comment | 70 complexity | c2b692eb11e41649eb3fd710a22afbb1 MD5 | raw file
  1. /*
  2. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  3. *
  4. * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
  5. *
  6. * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  7. * Other names may be trademarks of their respective owners.
  8. *
  9. * The contents of this file are subject to the terms of either the GNU
  10. * General Public License Version 2 only ("GPL") or the Common
  11. * Development and Distribution License("CDDL") (collectively, the
  12. * "License"). You may not use this file except in compliance with the
  13. * License. You can obtain a copy of the License at
  14. * http://www.netbeans.org/cddl-gplv2.html
  15. * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  16. * specific language governing permissions and limitations under the
  17. * License. When distributing the software, include this License Header
  18. * Notice in each file and include the License file at
  19. * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
  20. * particular file as subject to the "Classpath" exception as provided
  21. * by Oracle in the GPL Version 2 section of the License file that
  22. * accompanied this code. If applicable, add the following below the
  23. * License Header, with the fields enclosed by brackets [] replaced by
  24. * your own identifying information:
  25. * "Portions Copyrighted [year] [name of copyright owner]"
  26. *
  27. * Contributor(s):
  28. *
  29. * The Original Software is NetBeans. The Initial Developer of the Original
  30. * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  31. * Microsystems, Inc. All Rights Reserved.
  32. *
  33. * If you wish your version of this file to be governed by only the CDDL
  34. * or only the GPL Version 2, indicate your decision by adding
  35. * "[Contributor] elects to include this software in this distribution
  36. * under the [CDDL or GPL Version 2] license." If you do not indicate a
  37. * single choice of license, a recipient has the option to distribute
  38. * your version of this file under either the CDDL, the GPL Version 2 or
  39. * to extend the choice of license to its licensees as provided above.
  40. * However, if you add GPL Version 2 code and therefore, elected the GPL
  41. * Version 2 license, then the option applies only if the new code is
  42. * made subject to such option by the copyright holder.
  43. */
  44. package org.netbeans.modules.editor.settings.storage.preferences;
  45. import java.util.ArrayList;
  46. import java.util.Collections;
  47. import java.util.HashMap;
  48. import java.util.HashSet;
  49. import java.util.List;
  50. import java.util.Map;
  51. import java.util.Set;
  52. import java.util.TreeMap;
  53. import java.util.logging.Logger;
  54. import org.netbeans.lib.editor.util.CharacterConversions;
  55. import org.netbeans.modules.editor.settings.storage.spi.StorageDescription;
  56. import org.netbeans.modules.editor.settings.storage.spi.StorageReader;
  57. import org.netbeans.modules.editor.settings.storage.spi.StorageWriter;
  58. import org.netbeans.modules.editor.settings.storage.spi.TypedValue;
  59. import org.netbeans.modules.editor.settings.storage.spi.support.StorageSupport;
  60. import org.openide.filesystems.FileObject;
  61. import org.openide.xml.XMLUtil;
  62. import org.w3c.dom.Document;
  63. import org.w3c.dom.Element;
  64. import org.w3c.dom.Node;
  65. import org.xml.sax.Attributes;
  66. import org.xml.sax.SAXException;
  67. /**
  68. *
  69. * @author Vita Stejskal
  70. */
  71. @org.openide.util.lookup.ServiceProvider(service=org.netbeans.modules.editor.settings.storage.spi.StorageDescription.class)
  72. public final class PreferencesStorage implements StorageDescription<String, TypedValue> {
  73. private static final Logger LOG = Logger.getLogger(PreferencesStorage.class.getName());
  74. public static final String ID = "Preferences"; //NOI18N
  75. // ---------------------------------------------------------
  76. // StorageDescription implementation
  77. // ---------------------------------------------------------
  78. public PreferencesStorage() {
  79. }
  80. public String getId() {
  81. return ID;
  82. }
  83. public boolean isUsingProfiles() {
  84. return false;
  85. }
  86. public String getMimeType() {
  87. return MIME_TYPE;
  88. }
  89. public String getLegacyFileName() {
  90. return "properties.xml"; //NOI18N
  91. }
  92. public StorageReader<String, TypedValue> createReader(FileObject f, String mimePath) {
  93. if (MIME_TYPE.equals(f.getMIMEType())) {
  94. return new Reader(f, mimePath);
  95. } else {
  96. // assume legacy file
  97. return new LegacyReader(f, mimePath);
  98. }
  99. }
  100. public StorageWriter<String, TypedValue> createWriter(FileObject f, String mimePath) {
  101. return new Writer();
  102. }
  103. // ---------------------------------------------------------
  104. // Private implementation
  105. // ---------------------------------------------------------
  106. private static final String E_ROOT = "editor-preferences"; //NOI18N
  107. private static final String E_ENTRY = "entry"; //NOI18N
  108. private static final String E_VALUE = "value"; //NOI18N
  109. private static final String A_NAME = "name"; //NOI18N
  110. private static final String A_VALUE = "value"; //NOI18N
  111. private static final String A_VALUE_ID = "valueId"; //NOI18N
  112. private static final String A_JAVA_TYPE = "javaType"; //NOI18N
  113. private static final String A_CATEGORY = "category"; //NOI18N
  114. private static final String A_REMOVE = "remove"; //NOI18N
  115. private static final String A_XML_SPACE = "xml:space"; //NOI18N
  116. private static final String V_PRESERVE = "preserve"; //NOI18N
  117. private static final String PUBLIC_ID = "-//NetBeans//DTD Editor Preferences 1.0//EN"; //NOI18N
  118. private static final String SYSTEM_ID = "http://www.netbeans.org/dtds/EditorPreferences-1_0.dtd"; //NOI18N
  119. private static final String MIME_TYPE = "text/x-nbeditor-preferences"; //NOI18N
  120. private static abstract class PreferencesReader extends StorageReader<String, TypedValue> {
  121. protected PreferencesReader(FileObject f, String mimePath) {
  122. super(f, mimePath);
  123. }
  124. public abstract Map<String, TypedValue> getAdded();
  125. public abstract Set<String> getRemoved();
  126. }
  127. private static final class Reader extends PreferencesReader {
  128. private Map<String, TypedValue> entriesMap = new HashMap<String, TypedValue>();
  129. private Set<String> removedEntries = new HashSet<String>();
  130. // The entry being processed
  131. private String name = null;
  132. private String value = null;
  133. private String javaType = null;
  134. private String apiCategory = null;
  135. private StringBuilder text = null;
  136. private StringBuilder cdataText = null;
  137. private boolean insideCdata = false;
  138. public Reader(FileObject f, String mimePath) {
  139. super(f, mimePath);
  140. }
  141. public Map<String, TypedValue> getAdded() {
  142. return entriesMap;
  143. }
  144. public Set<String> getRemoved() {
  145. return removedEntries;
  146. }
  147. public @Override void characters(char[] ch, int start, int length) throws SAXException {
  148. if (text != null) {
  149. text.append(ch, start, length);
  150. if (insideCdata) {
  151. cdataText.append(ch, start, length);
  152. }
  153. }
  154. }
  155. public @Override void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
  156. if (qName.equals(E_ROOT)) {
  157. // We don't read anything from the root
  158. } else if (qName.equals(E_ENTRY)) {
  159. boolean removed = Boolean.valueOf(attributes.getValue(A_REMOVE));
  160. name = null;
  161. value = null;
  162. javaType = null;
  163. text = null;
  164. cdataText = null;
  165. if (removed) {
  166. String entryName = attributes.getValue(A_NAME);
  167. removedEntries.add(entryName);
  168. } else {
  169. // Read the name
  170. name = attributes.getValue(A_NAME);
  171. // Read the value and localize it
  172. String valueId = attributes.getValue(A_VALUE_ID);
  173. if (valueId != null) {
  174. String localizedValue = StorageSupport.getLocalizingBundleMessage(
  175. getProcessedFile(), valueId, null);
  176. if (localizedValue != null) {
  177. value = localizedValue;
  178. }
  179. }
  180. String valueValue = attributes.getValue(A_VALUE);
  181. if (valueValue != null) {
  182. if (value == null) {
  183. value = valueValue;
  184. } else {
  185. LOG.warning("The 'valueId' attribute specified valid resource bundle key, ignoring the 'value' attribute!"); //NOI18N
  186. }
  187. }
  188. // Read the type of the value
  189. javaType = attributes.getValue(A_JAVA_TYPE);
  190. // Read the API category
  191. apiCategory = attributes.getValue(A_CATEGORY);
  192. }
  193. } else if (name != null && qName.equals(E_VALUE)) {
  194. // Initiate the new builder for the entry value
  195. if (value == null) {
  196. text = new StringBuilder();
  197. cdataText = new StringBuilder();
  198. insideCdata = false;
  199. } else {
  200. LOG.warning("The 'value' or 'valueId' attribute was specified, ignoring the <value/> element!"); //NOI18N
  201. }
  202. }
  203. }
  204. public @Override void endElement(String uri, String localName, String qName) throws SAXException {
  205. if (qName.equals(E_ROOT)) {
  206. // We don't read anything from the root
  207. } else if (qName.equals(E_ENTRY)) {
  208. if (name != null) {
  209. if (value != null) {
  210. if (!entriesMap.containsKey(name)) {
  211. TypedValue typedValue = new TypedValue(CharacterConversions.lineSeparatorToLineFeed(value), javaType);
  212. if (apiCategory != null && apiCategory.length() > 0) {
  213. typedValue.setApiCategory(checkApiCategory(apiCategory));
  214. }
  215. entriesMap.put(name, typedValue);
  216. } else {
  217. LOG.warning("Ignoring duplicate editor preferences entry '" + name + "'!"); //NOI18N
  218. }
  219. } else {
  220. LOG.warning("Ignoring editor preferences entry '" + name + "' that does not specify any value!"); //NOI18N
  221. }
  222. }
  223. } else if (qName.equals(E_VALUE)) {
  224. if (text != null) {
  225. value = cdataText.length() > 0 ? cdataText.toString() : text.toString();
  226. }
  227. }
  228. }
  229. public @Override void startCDATA() throws SAXException {
  230. if (cdataText != null) {
  231. insideCdata = true;
  232. }
  233. }
  234. public @Override void endCDATA() throws SAXException {
  235. if (cdataText != null) {
  236. insideCdata = false;
  237. }
  238. }
  239. // for the list see EditorPreferences-1_0.dtd
  240. private static final String [] ALL_API_CATEGORIES = new String [] { "private", "stable", "devel", "friend", "deprecated" }; //NOI18N
  241. private static String checkApiCategory(String apiCategory) {
  242. for(String c : ALL_API_CATEGORIES) {
  243. if (c.equalsIgnoreCase(apiCategory)) {
  244. return c;
  245. }
  246. }
  247. return ALL_API_CATEGORIES[0];
  248. }
  249. } // End of Reader class
  250. private static final class LegacyReader extends PreferencesReader {
  251. private static final String EL_ROOT = "properties"; //NOI18N
  252. private static final String EL_PROPERTY = "property"; //NOI18N
  253. private static final String AL_NAME = "name"; //NOI18N
  254. private static final String AL_CLASS = "class"; //NOI18N we can safely ignore this
  255. private static final String AL_VALUE = "value"; //NOI18N
  256. private Map<String, TypedValue> entriesMap = new HashMap<String, TypedValue>();
  257. // The entry being processed
  258. private String name = null;
  259. private String value = null;
  260. private String javaType = null;
  261. public LegacyReader(FileObject f, String mimePath) {
  262. super(f, mimePath);
  263. }
  264. public Map<String, TypedValue> getAdded() {
  265. return entriesMap;
  266. }
  267. public Set<String> getRemoved() {
  268. return Collections.<String>emptySet();
  269. }
  270. public @Override void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
  271. if (qName.equals(EL_ROOT)) {
  272. // We don't read anything from the root
  273. } else if (qName.equals(EL_PROPERTY)) {
  274. name = attributes.getValue(AL_NAME);
  275. value = attributes.getValue(AL_VALUE);
  276. javaType = attributes.getValue(AL_CLASS);
  277. }
  278. }
  279. public @Override void endElement(String uri, String localName, String qName) throws SAXException {
  280. if (qName.equals(EL_ROOT)) {
  281. // We don't read anything from the root
  282. } else if (qName.equals(EL_PROPERTY)) {
  283. if (name != null && value != null) {
  284. entriesMap.put(name, new TypedValue(value, javaType));
  285. } else {
  286. LOG.warning("Ignoring editor preferences legacy entry {'" + name + "', '" + value + "'}!"); //NOI18N
  287. }
  288. }
  289. }
  290. } // End of LegacyReader class
  291. private static final class Writer extends StorageWriter<String, TypedValue> {
  292. public Writer() {
  293. }
  294. public Document getDocument() {
  295. Document doc = XMLUtil.createDocument(E_ROOT, null, PUBLIC_ID, SYSTEM_ID);
  296. Node root = doc.getElementsByTagName(E_ROOT).item(0);
  297. TreeMap<String, TypedValue> added = new TreeMap<String, TypedValue>(getAdded());
  298. for(String name : added.keySet()) {
  299. Element element = doc.createElement(E_ENTRY);
  300. root.appendChild(element);
  301. // Store entry's name
  302. element.setAttribute(A_NAME, name);
  303. // Store entry's value
  304. String value = getAdded().get(name).getValue();
  305. if (value.length() > 0) {
  306. Element valueElement = doc.createElement(E_VALUE);
  307. valueElement.appendChild(doc.createCDATASection(
  308. CharacterConversions.lineFeedToLineSeparator(value)));
  309. element.appendChild(valueElement);
  310. } else {
  311. element.setAttribute(name, value);
  312. }
  313. // Store entry's value type (if any)
  314. String javaType = getAdded().get(name).getJavaType();
  315. if (javaType != null && javaType.length() > 0) {
  316. element.setAttribute(A_JAVA_TYPE, javaType);
  317. }
  318. // Store entry's API stability (if any)
  319. String apiCategory = getAdded().get(name).getApiCategory();
  320. if (apiCategory != null && apiCategory.length() > 0) {
  321. element.setAttribute(A_CATEGORY, apiCategory);
  322. }
  323. // Just some XML crap to preserve whitespace
  324. element.setAttribute(A_XML_SPACE, V_PRESERVE);
  325. }
  326. List<String> removed = new ArrayList<String>(getRemoved());
  327. Collections.sort(removed);
  328. for(String name : removed) {
  329. Element element = doc.createElement(E_ENTRY);
  330. root.appendChild(element);
  331. element.setAttribute(A_NAME, name);
  332. element.setAttribute(A_REMOVE, Boolean.TRUE.toString());
  333. }
  334. return doc;
  335. }
  336. } // End of Writer class
  337. }