Crossfire JXClient, Trunk
XmlConfigUtils.java
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * - Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * - Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * - Neither the name of Oracle nor the names of its
16  * contributors may be used to endorse or promote products derived
17  * from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 /*
33  * This source code is provided to illustrate the usage of a given feature
34  * or technique and has been deliberately simplified. Additional steps
35  * required for a production-quality application, such as security checks,
36  * input validation and proper error handling, might not be present in
37  * this sample code.
38  */
39 
40 
41 package com.sun.jmx.examples.scandir.config;
42 
43 import java.io.ByteArrayInputStream;
44 import java.io.ByteArrayOutputStream;
45 import java.io.File;
46 import java.io.FileOutputStream;
47 import java.io.IOException;
48 import java.io.InputStream;
49 import java.io.OutputStream;
50 import java.util.logging.Logger;
51 import javax.xml.bind.JAXBContext;
52 import javax.xml.bind.JAXBException;
53 import javax.xml.bind.Marshaller;
54 import javax.xml.bind.Unmarshaller;
55 
62 public class XmlConfigUtils {
63 
69  public static final String NAMESPACE =
70  "jmx:com.sun.jmx.examples.scandir.config";
74  private static final Logger LOG =
75  Logger.getLogger(XmlConfigUtils.class.getName());
76 
77  // Our JAXBContext.
78  private static JAXBContext context;
79 
80  // The file name of the XML file in which an instance of this object
81  // will read and write XML data.
82  final String file;
83 
89  public XmlConfigUtils(String file) {
90  this.file = file;
91  }
92 
103  public synchronized void writeToFile(ScanManagerConfig bean)
104  throws IOException {
105 
106  // Creates a new file named <file>.new
107  final File f = newXmlTmpFile(file);
108  try {
109  final FileOutputStream out = new FileOutputStream(f);
110  boolean failed = true;
111  try {
112  // writes to <file>.new
113  write(bean,out,false);
114 
115  // no exception: set failed=false for finaly {} block.
116  failed = false;
117  } finally {
118  out.close();
119  // An exception was raised: delete temporary file.
120  if (failed == true) f.delete();
121  }
122 
123  // rename <file> to <file>~ and <file>.new to <file>
124  commit(file,f);
125  } catch (JAXBException x) {
126  final IOException io =
127  new IOException("Failed to write SessionConfigBean to " +
128  file+": "+x,x);
129  throw io;
130  }
131  }
132 
139  public static String toString(Object bean) {
140  try {
141  final ByteArrayOutputStream baos = new ByteArrayOutputStream();
142  final Marshaller m = createMarshaller();
143  m.setProperty(m.JAXB_FRAGMENT,Boolean.TRUE);
144  m.marshal(bean, baos);
145  return baos.toString();
146  } catch (JAXBException x) {
147  final IllegalArgumentException iae =
148  new IllegalArgumentException(
149  "Failed to write SessionConfigBean: "+x,x);
150  throw iae;
151  }
152  }
153 
166  final Object clone = copy(bean);
167  return (ScanManagerConfig)clone;
168  }
169 
180  private static Object copy(Object bean) {
181  try {
182  final ByteArrayOutputStream baos = new ByteArrayOutputStream();
183  final Marshaller m = createMarshaller();
184  m.marshal(bean, baos);
185  final ByteArrayInputStream bais =
186  new ByteArrayInputStream(baos.toByteArray());
187  return createUnmarshaller().unmarshal(bais);
188  } catch (JAXBException x) {
189  final IllegalArgumentException iae =
190  new IllegalArgumentException("Failed to write SessionConfigBean: "+x,x);
191  throw iae;
192  }
193  }
194 
207  final Object clone = copy(bean);
208  return (DirectoryScannerConfig)clone;
209  }
210 
217  public synchronized ScanManagerConfig readFromFile() throws IOException {
218  final File f = new File(file);
219  if (!f.exists())
220  throw new IOException("No such file: "+file);
221  if (!f.canRead())
222  throw new IOException("Can't read file: "+file);
223  try {
224  return read(f);
225  } catch (JAXBException x) {
226  final IOException io =
227  new IOException("Failed to read SessionConfigBean from " +
228  file+": "+x,x);
229  throw io;
230  }
231  }
232 
240  public static ScanManagerConfig read(File f)
241  throws JAXBException {
242  final Unmarshaller u = createUnmarshaller();
243  return (ScanManagerConfig) u.unmarshal(f);
244 
245  }
246 
256  public static void write(ScanManagerConfig bean, OutputStream os,
257  boolean fragment)
258  throws JAXBException {
259  writeXml((Object)bean,os,fragment);
260  }
261 
271  public static void write(ResultRecord bean, OutputStream os, boolean fragment)
272  throws JAXBException {
273  writeXml((Object)bean,os,fragment);
274  }
275 
285  private static void writeXml(Object bean, OutputStream os, boolean fragment)
286  throws JAXBException {
287  final Marshaller m = createMarshaller();
288  if (fragment) m.setProperty(m.JAXB_FRAGMENT,Boolean.TRUE);
289  m.marshal(bean,os);
290  }
291 
292  // Creates a JAXB Unmarshaller.
293  private static Unmarshaller createUnmarshaller() throws JAXBException {
294  return getContext().createUnmarshaller();
295  }
296 
297  // Creates a JAXB Marshaller - for nicely XML formatted output.
298  private static Marshaller createMarshaller() throws JAXBException {
299  final Marshaller m = getContext().createMarshaller();
300  m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,Boolean.TRUE);
301  return m;
302  }
303 
304  // Creates a JAXBContext if needed, and returns it.
305  // The JAXBContext instance we create will be able to handle the
306  // ScanManagerConfig and ResultRecord classes, plus all the property
307  // classes they reference (DirectoryScannerBean etc...).
308  //
309  private static synchronized JAXBContext getContext() throws JAXBException {
310  if (context == null)
311  context = JAXBContext.newInstance(ScanManagerConfig.class,
312  ResultRecord.class);
313  return context;
314  }
315 
316 
317  // Creates a new XML temporary file called <basename>.new
318  // This method is used to implement atomic writing to file.
319  // The usual sequence is:
320  //
321  // Final tmp = newXmlTmpFile(basename);
322  // boolean failed = true;
323  // try {
324  // ... write to 'tmp' ...
325  // // no exception: set failed=false for finaly {} block.
326  // failed = false;
327  // } finally
328  // // failed==true means there was an exception and
329  // // commit won't be called...
330  // if (failed==true) tmp.delete();
331  // }
332  // commit(tmp,basename)
333  //
334  private static File newXmlTmpFile(String basename) throws IOException {
335  final File f = new File(basename+".new");
336  if (!f.createNewFile())
337  throw new IOException("file "+f.getName()+" already exists");
338 
339  try {
340  final OutputStream newStream = new FileOutputStream(f);
341  try {
342  final String decl =
343  "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>";
344  newStream.write(decl.getBytes("UTF-8"));
345  newStream.flush();
346  } finally {
347  newStream.close();
348  }
349  } catch (IOException x) {
350  f.delete();
351  throw x;
352  }
353  return f;
354  }
355 
356  // Commit the temporary file by renaming <basename> to <baesname>~
357  // and tmpFile to <basename>.
358  private static File commit(String basename, File tmpFile)
359  throws IOException {
360  try {
361  final String backupName = basename+"~";
362  final File desired = new File(basename);
363  final File backup = new File(backupName);
364  backup.delete();
365  if (desired.exists()) {
366  if (!desired.renameTo(new File(backupName)))
367  throw new IOException("can't rename to "+backupName);
368  }
369  if (!tmpFile.renameTo(new File(basename)))
370  throw new IOException("can't rename to "+basename);
371  } catch (IOException x) {
372  tmpFile.delete();
373  throw x;
374  }
375  return new File(basename);
376  }
377 
389  public static File createNewXmlFile(String basename) throws IOException {
390  return commit(basename,newXmlTmpFile(basename));
391  }
392 
393 }
com.sun.jmx.examples.scandir.config.XmlConfigUtils.context
static JAXBContext context
Definition: XmlConfigUtils.java:78
com.sun.jmx.examples.scandir.config.XmlConfigUtils.newXmlTmpFile
static File newXmlTmpFile(String basename)
Definition: XmlConfigUtils.java:334
com.sun.jmx.examples.scandir.config.XmlConfigUtils.writeXml
static void writeXml(Object bean, OutputStream os, boolean fragment)
Definition: XmlConfigUtils.java:285
com.sun.jmx.examples.scandir.config.XmlConfigUtils.readFromFile
synchronized ScanManagerConfig readFromFile()
Definition: XmlConfigUtils.java:217
com.sun.jmx.examples.scandir.config.XmlConfigUtils.copy
static Object copy(Object bean)
Definition: XmlConfigUtils.java:180
com.sun.jmx.examples.scandir.config.XmlConfigUtils.createNewXmlFile
static File createNewXmlFile(String basename)
Definition: XmlConfigUtils.java:389
com.sun.jmx.examples.scandir.config.XmlConfigUtils.commit
static File commit(String basename, File tmpFile)
Definition: XmlConfigUtils.java:358
com.sun.jmx.examples.scandir.config.XmlConfigUtils.write
static void write(ResultRecord bean, OutputStream os, boolean fragment)
Definition: XmlConfigUtils.java:271
com.sun.jmx.examples.scandir.config.XmlConfigUtils.LOG
static final Logger LOG
Definition: XmlConfigUtils.java:74
com.sun.jmx.examples.scandir.config.XmlConfigUtils.writeToFile
synchronized void writeToFile(ScanManagerConfig bean)
Definition: XmlConfigUtils.java:103
com.sun.jmx.examples.scandir.config.XmlConfigUtils.createUnmarshaller
static Unmarshaller createUnmarshaller()
Definition: XmlConfigUtils.java:293
com.sun.jmx.examples.scandir.config.XmlConfigUtils.write
static void write(ScanManagerConfig bean, OutputStream os, boolean fragment)
Definition: XmlConfigUtils.java:256
com.sun.jmx.examples.scandir.config.XmlConfigUtils.getContext
static synchronized JAXBContext getContext()
Definition: XmlConfigUtils.java:309
com.sun.jmx.examples.scandir.config.XmlConfigUtils.file
final String file
Definition: XmlConfigUtils.java:82
com.sun.jmx.examples.scandir.config.XmlConfigUtils.XmlConfigUtils
XmlConfigUtils(String file)
Definition: XmlConfigUtils.java:89
com.sun.jmx.examples.scandir.config.ResultRecord
Definition: ResultRecord.java:62
com.sun.jmx.examples.scandir.config.XmlConfigUtils.createMarshaller
static Marshaller createMarshaller()
Definition: XmlConfigUtils.java:298
com.sun.jmx.examples.scandir.config.XmlConfigUtils.xmlClone
static DirectoryScannerConfig xmlClone(DirectoryScannerConfig bean)
Definition: XmlConfigUtils.java:206
com.sun.jmx.examples.scandir.config.XmlConfigUtils.xmlClone
static ScanManagerConfig xmlClone(ScanManagerConfig bean)
Definition: XmlConfigUtils.java:165
com.sun.jmx.examples.scandir.config.XmlConfigUtils.toString
static String toString(Object bean)
Definition: XmlConfigUtils.java:139
com.sun.jmx.examples.scandir.config.XmlConfigUtils.NAMESPACE
static final String NAMESPACE
Definition: XmlConfigUtils.java:69
com.sun.jmx.examples.scandir.config.XmlConfigUtils
Definition: XmlConfigUtils.java:62
com.sun.jmx.examples.scandir.config.DirectoryScannerConfig
Definition: DirectoryScannerConfig.java:67
com.sun.jmx.examples.scandir.config.ScanManagerConfig
Definition: ScanManagerConfig.java:72
com.sun.jmx.examples.scandir.config.XmlConfigUtils.read
static ScanManagerConfig read(File f)
Definition: XmlConfigUtils.java:240