]> git.uio.no Git - ifi-stolz-refaktor.git/blob - case-study/jdt-after/ui/org/eclipse/jdt/internal/ui/preferences/formatter/ProfileStore.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / jdt-after / ui / org / eclipse / jdt / internal / ui / preferences / formatter / ProfileStore.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2011 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11
12 package org.eclipse.jdt.internal.ui.preferences.formatter;
13
14 import java.io.ByteArrayInputStream;
15 import java.io.ByteArrayOutputStream;
16 import java.io.File;
17 import java.io.FileInputStream;
18 import java.io.FileOutputStream;
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.io.OutputStream;
22 import java.io.UnsupportedEncodingException;
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.HashMap;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.Map;
29
30 import javax.xml.parsers.DocumentBuilder;
31 import javax.xml.parsers.DocumentBuilderFactory;
32 import javax.xml.parsers.ParserConfigurationException;
33 import javax.xml.parsers.SAXParser;
34 import javax.xml.parsers.SAXParserFactory;
35 import javax.xml.transform.OutputKeys;
36 import javax.xml.transform.Transformer;
37 import javax.xml.transform.TransformerException;
38 import javax.xml.transform.TransformerFactory;
39 import javax.xml.transform.dom.DOMSource;
40 import javax.xml.transform.stream.StreamResult;
41
42 import org.xml.sax.Attributes;
43 import org.xml.sax.InputSource;
44 import org.xml.sax.SAXException;
45 import org.xml.sax.helpers.DefaultHandler;
46
47 import org.w3c.dom.Document;
48 import org.w3c.dom.Element;
49
50 import org.eclipse.core.runtime.CoreException;
51 import org.eclipse.core.runtime.IStatus;
52 import org.eclipse.core.runtime.preferences.DefaultScope;
53 import org.eclipse.core.runtime.preferences.IEclipsePreferences;
54 import org.eclipse.core.runtime.preferences.IScopeContext;
55
56 import org.eclipse.jdt.ui.JavaUI;
57
58 import org.eclipse.jdt.internal.ui.JavaPlugin;
59 import org.eclipse.jdt.internal.ui.JavaUIException;
60 import org.eclipse.jdt.internal.ui.JavaUIStatus;
61 import org.eclipse.jdt.internal.ui.preferences.formatter.ProfileManager.CustomProfile;
62 import org.eclipse.jdt.internal.ui.preferences.formatter.ProfileManager.Profile;
63
64
65 /**
66  * Can load/store profiles from/to profilesKey
67  */
68 public class ProfileStore {
69
70         /** The default encoding to use */
71         public static final String ENCODING= "UTF-8"; //$NON-NLS-1$
72
73         protected static final String VERSION_KEY_SUFFIX= ".version"; //$NON-NLS-1$
74
75         /**
76          * A SAX event handler to parse the xml format for profiles.
77          */
78         private final static class ProfileDefaultHandler extends DefaultHandler {
79
80                 private List<Profile> fProfiles;
81                 private int fVersion;
82
83                 private String fName;
84                 private Map<String, String> fSettings;
85                 private String fKind;
86
87                 @Override
88                 public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
89
90                         if (qName.equals(XML_NODE_SETTING)) {
91
92                                 final String key= attributes.getValue(XML_ATTRIBUTE_ID);
93                                 final String value= attributes.getValue(XML_ATTRIBUTE_VALUE);
94                                 fSettings.put(key, value);
95
96                         } else if (qName.equals(XML_NODE_PROFILE)) {
97
98                                 fName= attributes.getValue(XML_ATTRIBUTE_NAME);
99                                 fKind= attributes.getValue(XML_ATTRIBUTE_PROFILE_KIND);
100                                 if (fKind == null) //Can only be an CodeFormatterProfile created pre 3.3M2
101                                         fKind= ProfileVersioner.CODE_FORMATTER_PROFILE_KIND;
102
103                                 fSettings= new HashMap<String, String>(200);
104
105                         }
106                         else if (qName.equals(XML_NODE_ROOT)) {
107
108                                 fProfiles= new ArrayList<Profile>();
109                                 try {
110                                         fVersion= Integer.parseInt(attributes.getValue(XML_ATTRIBUTE_VERSION));
111                                 } catch (NumberFormatException ex) {
112                                         throw new SAXException(ex);
113                                 }
114
115                         }
116                 }
117
118                 @Override
119                 public void endElement(String uri, String localName, String qName) {
120                         if (qName.equals(XML_NODE_PROFILE)) {
121                                 fProfiles.add(new CustomProfile(fName, fSettings, fVersion, fKind));
122                                 fName= null;
123                                 fSettings= null;
124                                 fKind= null;
125                         }
126                 }
127
128                 public List<Profile> getProfiles() {
129                         return fProfiles;
130                 }
131
132         }
133
134         /**
135          * Identifiers for the XML file.
136          */
137         private final static String XML_NODE_ROOT= "profiles"; //$NON-NLS-1$
138         private final static String XML_NODE_PROFILE= "profile"; //$NON-NLS-1$
139         private final static String XML_NODE_SETTING= "setting"; //$NON-NLS-1$
140
141         private final static String XML_ATTRIBUTE_VERSION= "version"; //$NON-NLS-1$
142         private final static String XML_ATTRIBUTE_ID= "id"; //$NON-NLS-1$
143         private final static String XML_ATTRIBUTE_NAME= "name"; //$NON-NLS-1$
144         private final static String XML_ATTRIBUTE_PROFILE_KIND= "kind"; //$NON-NLS-1$
145         private final static String XML_ATTRIBUTE_VALUE= "value"; //$NON-NLS-1$
146
147         private final IProfileVersioner fProfileVersioner;
148         private final String fProfilesKey;
149         private final String fProfilesVersionKey;
150
151
152         public ProfileStore(String profilesKey, IProfileVersioner profileVersioner) {
153                 fProfilesKey= profilesKey;
154                 fProfileVersioner= profileVersioner;
155                 fProfilesVersionKey= profilesKey + VERSION_KEY_SUFFIX;
156         }
157
158         /**
159          * @return Returns the collection of profiles currently stored in the preference store or
160          * <code>null</code> if the loading failed. The elements are of type {@link ProfileManager.CustomProfile}
161          * and are all updated to the latest version.
162          * @throws CoreException
163          */
164         public List<Profile> readProfiles(IScopeContext scope) throws CoreException {
165                 return readProfilesFromString(scope.getNode(JavaUI.ID_PLUGIN).get(fProfilesKey, null));
166         }
167
168         public void writeProfiles(Collection<Profile> profiles, IScopeContext instanceScope) throws CoreException {
169                 ByteArrayOutputStream stream= new ByteArrayOutputStream(2000);
170                 try {
171                         writeProfilesToStream(profiles, stream, ENCODING, fProfileVersioner);
172                         String val;
173                         try {
174                                 val= stream.toString(ENCODING);
175                         } catch (UnsupportedEncodingException e) {
176                                 val= stream.toString();
177                         }
178                         IEclipsePreferences uiPreferences = instanceScope.getNode(JavaUI.ID_PLUGIN);
179                         uiPreferences.put(fProfilesKey, val);
180                         uiPreferences.putInt(fProfilesVersionKey, fProfileVersioner.getCurrentVersion());
181                 } finally {
182                         try { stream.close(); } catch (IOException e) { /* ignore */ }
183                 }
184         }
185
186         public List<Profile> readProfilesFromString(String profiles) throws CoreException {
187             if (profiles != null && profiles.length() > 0) {
188                         byte[] bytes;
189                         try {
190                                 bytes= profiles.getBytes(ENCODING);
191                         } catch (UnsupportedEncodingException e) {
192                                 bytes= profiles.getBytes();
193                         }
194                         InputStream is= new ByteArrayInputStream(bytes);
195                         try {
196                                 List<Profile> res= readProfilesFromStream(new InputSource(is));
197                                 if (res != null) {
198                                         for (int i= 0; i < res.size(); i++) {
199                                                 fProfileVersioner.update((CustomProfile) res.get(i));
200                                         }
201                                 }
202                                 return res;
203                         } finally {
204                                 try { is.close(); } catch (IOException e) { /* ignore */ }
205                         }
206                 }
207                 return null;
208     }
209
210
211         /**
212          * Read the available profiles from the internal XML file and return them
213          * as collection or <code>null</code> if the file is not a profile file.
214          * @param file The file to read from
215          * @return returns a list of <code>CustomProfile</code> or <code>null</code>
216          * @throws CoreException
217          */
218         public List<Profile> readProfilesFromFile(File file) throws CoreException {
219                 try {
220                         final FileInputStream reader= new FileInputStream(file);
221                         try {
222                                 return readProfilesFromStream(new InputSource(reader));
223                         } finally {
224                                 try { reader.close(); } catch (IOException e) { /* ignore */ }
225                         }
226                 } catch (IOException e) {
227                         throw createException(e, FormatterMessages.CodingStyleConfigurationBlock_error_reading_xml_message);
228                 }
229         }
230
231         /**
232          * Load profiles from a XML stream and add them to a map or <code>null</code> if the source is not a profile store.
233          * @param inputSource The input stream
234          * @return returns a list of <code>CustomProfile</code> or <code>null</code>
235          * @throws CoreException
236          */
237         public static List<Profile> readProfilesFromStream(InputSource inputSource) throws CoreException {
238
239                 final ProfileDefaultHandler handler= new ProfileDefaultHandler();
240                 try {
241                     final SAXParserFactory factory= SAXParserFactory.newInstance();
242                         final SAXParser parser= factory.newSAXParser();
243                         parser.parse(inputSource, handler);
244                 } catch (SAXException e) {
245                         throw createException(e, FormatterMessages.CodingStyleConfigurationBlock_error_reading_xml_message);
246                 } catch (IOException e) {
247                         throw createException(e, FormatterMessages.CodingStyleConfigurationBlock_error_reading_xml_message);
248                 } catch (ParserConfigurationException e) {
249                         throw createException(e, FormatterMessages.CodingStyleConfigurationBlock_error_reading_xml_message);
250                 }
251                 return handler.getProfiles();
252         }
253
254         /**
255          * Write the available profiles to the internal XML file.
256          * @param profiles List of <code>CustomProfile</code>
257          * @param file File to write
258          * @param encoding the encoding to use
259          * @throws CoreException
260          */
261         public void writeProfilesToFile(Collection<Profile> profiles, File file, String encoding) throws CoreException {
262                 final OutputStream stream;
263                 try {
264                         stream= new FileOutputStream(file);
265                         try {
266                                 writeProfilesToStream(profiles, stream, encoding, fProfileVersioner);
267                         } finally {
268                                 try { stream.close(); } catch (IOException e) { /* ignore */ }
269                         }
270                 } catch (IOException e) {
271                         throw createException(e, FormatterMessages.CodingStyleConfigurationBlock_error_serializing_xml_message);
272                 }
273         }
274
275         public List<Profile> generated_6519699636150707677(ProfileConfigurationBlock profileconfigurationblock, List<Profile> profiles) {
276                 try {
277                 profiles= readProfiles(profileconfigurationblock.fInstanceScope);
278             } catch (CoreException e) {
279                 JavaPlugin.log(e);
280             }
281             if (profiles == null) {
282                 try {
283                         // bug 129427
284                                 profiles= readProfiles(DefaultScope.INSTANCE);
285                 } catch (CoreException e) {
286                         JavaPlugin.log(e);
287                 }
288             }
289         
290             if (profiles == null)
291                 profiles= new ArrayList<Profile>();
292                 return profiles;
293         }
294
295         /**
296          * Save profiles to an XML stream
297          * @param profiles the list of <code>CustomProfile</code>
298          * @param stream the stream to write to
299          * @param encoding the encoding to use
300          * @throws CoreException
301          */
302         public static void writeProfilesToStream(Collection<Profile> profiles, OutputStream stream, String encoding, IProfileVersioner profileVersioner) throws CoreException {
303
304                 try {
305                         final DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance();
306                         final DocumentBuilder builder= factory.newDocumentBuilder();
307                         final Document document= builder.newDocument();
308
309                         final Element rootElement = document.createElement(XML_NODE_ROOT);
310                         rootElement.setAttribute(XML_ATTRIBUTE_VERSION, Integer.toString(profileVersioner.getCurrentVersion()));
311
312                         document.appendChild(rootElement);
313
314                         for(final Iterator<Profile> iter= profiles.iterator(); iter.hasNext();) {
315                                 final Profile profile= iter.next();
316                                 if (profile.isProfileToSave()) {
317                                         final Element profileElement= createProfileElement(profile, document, profileVersioner);
318                                         rootElement.appendChild(profileElement);
319                                 }
320                         }
321
322                         Transformer transformer=TransformerFactory.newInstance().newTransformer();
323                         transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
324                         transformer.setOutputProperty(OutputKeys.ENCODING, encoding);
325                         transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
326                         transformer.transform(new DOMSource(document), new StreamResult(stream));
327                 } catch (TransformerException e) {
328                         throw createException(e, FormatterMessages.CodingStyleConfigurationBlock_error_serializing_xml_message);
329                 } catch (ParserConfigurationException e) {
330                         throw createException(e, FormatterMessages.CodingStyleConfigurationBlock_error_serializing_xml_message);
331                 }
332         }
333
334
335         /*
336          * Create a new profile element in the specified document. The profile is not added
337          * to the document by this method.
338          */
339         private static Element createProfileElement(Profile profile, Document document, IProfileVersioner profileVersioner) {
340                 final Element element= document.createElement(XML_NODE_PROFILE);
341                 element.setAttribute(XML_ATTRIBUTE_NAME, profile.getName());
342                 element.setAttribute(XML_ATTRIBUTE_VERSION, Integer.toString(profile.getVersion()));
343                 element.setAttribute(XML_ATTRIBUTE_PROFILE_KIND, profileVersioner.getProfileKind());
344
345                 final Iterator<String> keyIter= profile.getSettings().keySet().iterator();
346
347                 while (keyIter.hasNext()) {
348                         final String key= keyIter.next();
349                         final String value= profile.getSettings().get(key);
350                         if (value != null) {
351                                 final Element setting= document.createElement(XML_NODE_SETTING);
352                                 setting.setAttribute(XML_ATTRIBUTE_ID, key);
353                                 setting.setAttribute(XML_ATTRIBUTE_VALUE, value);
354                                 element.appendChild(setting);
355                         } else {
356                                 JavaPlugin.logErrorMessage("ProfileStore: Profile does not contain value for key " + key); //$NON-NLS-1$
357                         }
358                 }
359                 return element;
360         }
361
362
363         /*
364          * Creates a UI exception for logging purposes
365          */
366         private static JavaUIException createException(Throwable t, String message) {
367                 return new JavaUIException(JavaUIStatus.createError(IStatus.ERROR, message, t));
368         }
369 }