src/jdk.jpackage/share/classes/jdk/jpackage/internal/IOUtils.java
branchJDK-8200758-branch
changeset 58696 61c44899b4eb
parent 58417 67ffaf3a2b75
child 58762 0fe62353385b
equal deleted inserted replaced
58695:64adf683bc7b 58696:61c44899b4eb
    24  */
    24  */
    25 
    25 
    26 package jdk.jpackage.internal;
    26 package jdk.jpackage.internal;
    27 
    27 
    28 import java.io.*;
    28 import java.io.*;
       
    29 import java.lang.reflect.InvocationHandler;
       
    30 import java.lang.reflect.Method;
       
    31 import java.lang.reflect.Proxy;
    29 import java.nio.channels.FileChannel;
    32 import java.nio.channels.FileChannel;
    30 import java.nio.file.FileVisitResult;
    33 import java.nio.file.FileVisitResult;
    31 import java.nio.file.Files;
    34 import java.nio.file.Files;
    32 import java.nio.file.Path;
    35 import java.nio.file.Path;
    33 import java.nio.file.SimpleFileVisitor;
    36 import java.nio.file.SimpleFileVisitor;
    34 import java.nio.file.attribute.BasicFileAttributes;
    37 import java.nio.file.attribute.BasicFileAttributes;
    35 import java.util.ArrayList;
    38 import java.util.*;
    36 import java.util.List;
    39 import javax.xml.stream.XMLOutputFactory;
       
    40 import javax.xml.stream.XMLStreamException;
       
    41 import javax.xml.stream.XMLStreamWriter;
    37 
    42 
    38 /**
    43 /**
    39  * IOUtils
    44  * IOUtils
    40  *
    45  *
    41  * A collection of static utility methods.
    46  * A collection of static utility methods.
   219         if (!file.canWrite()) {
   224         if (!file.canWrite()) {
   220             throw new PackagerException("error.cannot-write-to-output-dir",
   225             throw new PackagerException("error.cannot-write-to-output-dir",
   221                     file.getAbsolutePath());
   226                     file.getAbsolutePath());
   222         }
   227         }
   223     }
   228     }
       
   229 
       
   230     public static Path replaceSuffix(Path path, String suffix) {
       
   231         Path parent = path.getParent();
       
   232         String filename = path.getFileName().toString().replaceAll("\\.[^.]*$", "")
       
   233                 + Optional.ofNullable(suffix).orElse("");
       
   234         return parent != null ? parent.resolve(filename) : Path.of(filename);
       
   235     }
       
   236 
       
   237     public static Path addSuffix(Path path, String suffix) {
       
   238         Path parent = path.getParent();
       
   239         String filename = path.getFileName().toString() + suffix;
       
   240         return parent != null ? parent.resolve(filename) : Path.of(filename);
       
   241     }
       
   242 
       
   243     @FunctionalInterface
       
   244     public static interface XmlConsumer {
       
   245         void accept(XMLStreamWriter xml) throws IOException, XMLStreamException;
       
   246     }
       
   247 
       
   248     public static void createXml(Path dstFile, XmlConsumer xmlConsumer) throws
       
   249             IOException {
       
   250         XMLOutputFactory xmlFactory = XMLOutputFactory.newInstance();
       
   251         try (Writer w = new BufferedWriter(new FileWriter(dstFile.toFile()))) {
       
   252             // Wrap with pretty print proxy
       
   253             XMLStreamWriter xml = (XMLStreamWriter) Proxy.newProxyInstance(
       
   254                     XMLStreamWriter.class.getClassLoader(), new Class<?>[]{
       
   255                 XMLStreamWriter.class}, new PrettyPrintHandler(
       
   256                     xmlFactory.createXMLStreamWriter(w)));
       
   257 
       
   258             xml.writeStartDocument();
       
   259             xmlConsumer.accept(xml);
       
   260             xml.writeEndDocument();
       
   261             xml.flush();
       
   262             xml.close();
       
   263         } catch (XMLStreamException ex) {
       
   264             throw new IOException(ex);
       
   265         } catch (IOException ex) {
       
   266             throw ex;
       
   267         }
       
   268     }
       
   269 
       
   270     private static class PrettyPrintHandler implements InvocationHandler {
       
   271 
       
   272         PrettyPrintHandler(XMLStreamWriter target) {
       
   273             this.target = target;
       
   274         }
       
   275 
       
   276         @Override
       
   277         public Object invoke(Object proxy, Method method, Object[] args) throws
       
   278                 Throwable {
       
   279             switch (method.getName()) {
       
   280                 case "writeStartElement":
       
   281                     // update state of parent node
       
   282                     if (depth > 0) {
       
   283                         hasChildElement.put(depth - 1, true);
       
   284                     }
       
   285                     // reset state of current node
       
   286                     hasChildElement.put(depth, false);
       
   287                     // indent for current depth
       
   288                     target.writeCharacters(EOL);
       
   289                     target.writeCharacters(repeat(depth, INDENT));
       
   290                     depth++;
       
   291                     break;
       
   292                 case "writeEndElement":
       
   293                     depth--;
       
   294                     if (hasChildElement.get(depth) == true) {
       
   295                         target.writeCharacters(EOL);
       
   296                         target.writeCharacters(repeat(depth, INDENT));
       
   297                     }
       
   298                     break;
       
   299                 case "writeProcessingInstruction":
       
   300                 case "writeEmptyElement":
       
   301                     // update state of parent node
       
   302                     if (depth > 0) {
       
   303                         hasChildElement.put(depth - 1, true);
       
   304                     }
       
   305                     // indent for current depth
       
   306                     target.writeCharacters(EOL);
       
   307                     target.writeCharacters(repeat(depth, INDENT));
       
   308                     break;
       
   309                 default:
       
   310                     break;
       
   311             }
       
   312             method.invoke(target, args);
       
   313             return null;
       
   314         }
       
   315 
       
   316         private static String repeat(int d, String s) {
       
   317             StringBuilder sb = new StringBuilder();
       
   318             while (d-- > 0) {
       
   319                 sb.append(s);
       
   320             }
       
   321             return sb.toString();
       
   322         }
       
   323 
       
   324         private final XMLStreamWriter target;
       
   325         private int depth = 0;
       
   326         private final Map<Integer, Boolean> hasChildElement = new HashMap<>();
       
   327         private static final String INDENT = "  ";
       
   328         private static final String EOL = "\n";
       
   329     }
   224 }
   330 }