View Javadoc

1   /*
2    * Copyright 2005,2009 Ivan SZKIBA
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.ini4j;
17  
18  import org.ini4j.spi.IniFormatter;
19  import org.ini4j.spi.IniHandler;
20  import org.ini4j.spi.IniParser;
21  import org.ini4j.spi.RegBuilder;
22  
23  import java.io.File;
24  import java.io.FileNotFoundException;
25  import java.io.FileOutputStream;
26  import java.io.IOException;
27  import java.io.InputStream;
28  import java.io.InputStreamReader;
29  import java.io.InterruptedIOException;
30  import java.io.OutputStream;
31  import java.io.OutputStreamWriter;
32  import java.io.Reader;
33  import java.io.Writer;
34  
35  import java.net.URL;
36  
37  public class Reg extends BasicRegistry implements Registry, Persistable, Configurable
38  {
39      private static final long serialVersionUID = -1485602876922985912L;
40      protected static final String DEFAULT_SUFFIX = ".reg";
41      protected static final String TMP_PREFIX = "reg-";
42      private static final int STDERR_BUFF_SIZE = 8192;
43      private static final String PROP_OS_NAME = "os.name";
44      private static final boolean WINDOWS = Config.getSystemProperty(PROP_OS_NAME, "Unknown").startsWith("Windows");
45      private static final char CR = '\r';
46      private static final char LF = '\n';
47      private Config _config;
48      private File _file;
49  
50      public Reg()
51      {
52          Config cfg = Config.getGlobal().clone();
53  
54          cfg.setEscape(false);
55          cfg.setGlobalSection(false);
56          cfg.setEmptyOption(true);
57          cfg.setMultiOption(true);
58          cfg.setStrictOperator(true);
59          cfg.setEmptySection(true);
60          cfg.setPathSeparator(KEY_SEPARATOR);
61          cfg.setFileEncoding(FILE_ENCODING);
62          cfg.setLineSeparator(LINE_SEPARATOR);
63          _config = cfg;
64      }
65  
66      public Reg(String registryKey) throws IOException
67      {
68          this();
69          read(registryKey);
70      }
71  
72      public Reg(File input) throws IOException, InvalidFileFormatException
73      {
74          this();
75          _file = input;
76          load();
77      }
78  
79      public Reg(URL input) throws IOException, InvalidFileFormatException
80      {
81          this();
82          load(input);
83      }
84  
85      public Reg(InputStream input) throws IOException, InvalidFileFormatException
86      {
87          this();
88          load(input);
89      }
90  
91      public Reg(Reader input) throws IOException, InvalidFileFormatException
92      {
93          this();
94          load(input);
95      }
96  
97      public static boolean isWindows()
98      {
99          return WINDOWS;
100     }
101 
102     @Override public Config getConfig()
103     {
104         return _config;
105     }
106 
107     public void setConfig(Config value)
108     {
109         _config = value;
110     }
111 
112     @Override public File getFile()
113     {
114         return _file;
115     }
116 
117     @Override public void setFile(File value)
118     {
119         _file = value;
120     }
121 
122     @Override public void load() throws IOException, InvalidFileFormatException
123     {
124         if (_file == null)
125         {
126             throw new FileNotFoundException();
127         }
128 
129         load(_file);
130     }
131 
132     @Override public void load(InputStream input) throws IOException, InvalidFileFormatException
133     {
134         load(new InputStreamReader(input, getConfig().getFileEncoding()));
135     }
136 
137     @Override public void load(URL input) throws IOException, InvalidFileFormatException
138     {
139         load(new InputStreamReader(input.openStream(), getConfig().getFileEncoding()));
140     }
141 
142     @Override public void load(Reader input) throws IOException, InvalidFileFormatException
143     {
144         int newline = 2;
145         StringBuilder buff = new StringBuilder();
146 
147         for (int c = input.read(); c != -1; c = input.read())
148         {
149             if (c == LF)
150             {
151                 newline--;
152                 if (newline == 0)
153                 {
154                     break;
155                 }
156             }
157             else if ((c != CR) && (newline != 1))
158             {
159                 buff.append((char) c);
160             }
161         }
162 
163         if (buff.length() == 0)
164         {
165             throw new InvalidFileFormatException("Missing version header");
166         }
167 
168         if (!buff.toString().equals(getVersion()))
169         {
170             throw new InvalidFileFormatException("Unsupported version: " + buff.toString());
171         }
172 
173         IniParser.newInstance(getConfig()).parse(input, newBuilder());
174     }
175 
176     @Override public void load(File input) throws IOException, InvalidFileFormatException
177     {
178         load(input.toURI().toURL());
179     }
180 
181     public void read(String registryKey) throws IOException
182     {
183         File tmp = createTempFile();
184 
185         try
186         {
187             regExport(registryKey, tmp);
188             load(tmp);
189         }
190         finally
191         {
192             tmp.delete();
193         }
194     }
195 
196     @Override public void store() throws IOException
197     {
198         if (_file == null)
199         {
200             throw new FileNotFoundException();
201         }
202 
203         store(_file);
204     }
205 
206     @Override public void store(OutputStream output) throws IOException
207     {
208         store(new OutputStreamWriter(output, getConfig().getFileEncoding()));
209     }
210 
211     @Override public void store(Writer output) throws IOException
212     {
213         output.write(getVersion());
214         output.write(getConfig().getLineSeparator());
215         output.write(getConfig().getLineSeparator());
216         store(IniFormatter.newInstance(output, getConfig()));
217     }
218 
219     @Override public void store(File output) throws IOException
220     {
221         OutputStream stream = new FileOutputStream(output);
222 
223         store(stream);
224         stream.close();
225     }
226 
227     public void write() throws IOException
228     {
229         File tmp = createTempFile();
230 
231         try
232         {
233             store(tmp);
234             regImport(tmp);
235         }
236         finally
237         {
238             tmp.delete();
239         }
240     }
241 
242     protected IniHandler newBuilder()
243     {
244         return RegBuilder.newInstance(this);
245     }
246 
247     @Override boolean isTreeMode()
248     {
249         return getConfig().isTree();
250     }
251 
252     @Override char getPathSeparator()
253     {
254         return getConfig().getPathSeparator();
255     }
256 
257     @Override boolean isPropertyFirstUpper()
258     {
259         return getConfig().isPropertyFirstUpper();
260     }
261 
262     void exec(String[] args) throws IOException
263     {
264         Process proc = Runtime.getRuntime().exec(args);
265 
266         try
267         {
268             int status = proc.waitFor();
269 
270             if (status != 0)
271             {
272                 Reader in = new InputStreamReader(proc.getErrorStream());
273                 char[] buff = new char[STDERR_BUFF_SIZE];
274                 int n = in.read(buff);
275 
276                 in.close();
277                 throw new IOException(new String(buff, 0, n).trim());
278             }
279         }
280         catch (InterruptedException x)
281         {
282             throw (IOException) (new InterruptedIOException().initCause(x));
283         }
284     }
285 
286     private File createTempFile() throws IOException
287     {
288         File ret = File.createTempFile(TMP_PREFIX, DEFAULT_SUFFIX);
289 
290         ret.deleteOnExit();
291 
292         return ret;
293     }
294 
295     private void regExport(String registryKey, File file) throws IOException
296     {
297         requireWindows();
298         exec(new String[] { "cmd", "/c", "reg", "export", registryKey, file.getAbsolutePath() });
299     }
300 
301     private void regImport(File file) throws IOException
302     {
303         requireWindows();
304         exec(new String[] { "cmd", "/c", "reg", "import", file.getAbsolutePath() });
305     }
306 
307     private void requireWindows()
308     {
309         if (!WINDOWS)
310         {
311             throw new UnsupportedOperationException("Unsupported operating system or runtime environment");
312         }
313     }
314 }