Java tutorial
/* # Copyright (c) 2007-2013 Cyrus Daboo. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. */ package org.bedework.util.deployment; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.logging.Log; import org.w3c.dom.Document; import org.xml.sax.InputSource; import java.io.File; import java.io.IOException; import java.io.Reader; import java.nio.file.CopyOption; import java.nio.file.FileAlreadyExistsException; import java.nio.file.FileSystemLoopException; import java.nio.file.FileVisitOption; import java.nio.file.FileVisitResult; import java.nio.file.FileVisitor; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.FileTime; import java.util.EnumSet; import java.util.Formatter; import java.util.Properties; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import static java.nio.file.FileVisitResult.CONTINUE; import static java.nio.file.FileVisitResult.SKIP_SUBTREE; import static java.nio.file.StandardCopyOption.COPY_ATTRIBUTES; import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; class Utils { private final boolean debug; private final Log logger; public Utils(final Log logger) { this.logger = logger; debug = logger.isDebugEnabled(); } public Path createFile(final String path) throws Throwable { final Path pathToFile = Paths.get(path); Files.createDirectories(pathToFile.getParent()); return Files.createFile(pathToFile); } public boolean empty(final String path) { return delete(new File(path), false); } public boolean makeDir(final String path) throws Throwable { final File f = new File(path); if (!f.exists()) { return f.mkdir(); } if (!f.isDirectory()) { throw new Exception(f.getAbsolutePath() + " must be a directory"); } return false; } public File directory(final String path) throws Throwable { final File f = new File(path); if (!f.exists() || !f.isDirectory()) { throw new MojoExecutionException(f.getAbsolutePath() + " must exist and be a directory"); } return f; } public File subDirectory(final String path, final String name) throws Throwable { final Path p = Paths.get(path, name); final File f = p.toFile(); if (!f.exists() || !f.isDirectory()) { throw new Exception(name + " in " + path + " must exist and be a directory"); } return f; } public File subDirectory(final File f, final String name, final boolean mustExist) throws Throwable { final File dir = new File(f.getAbsolutePath(), name); if (dir.exists() && !dir.isDirectory()) { throw new Exception(name + " in " + f.getAbsolutePath() + " must be a directory"); } if (!dir.exists() && mustExist) { throw new Exception(name + " in " + f.getAbsolutePath() + " must exist and be a directory"); } return dir; } public File file(final File dir, final String name, final boolean mustExist) throws Throwable { final File f = new File(dir.getAbsolutePath(), name); if (f.exists() && !f.isFile()) { throw new Exception(name + " in " + f.getAbsolutePath() + " must be a file"); } if (!f.exists() && mustExist) { throw new Exception(name + " in " + f.getAbsolutePath() + " must exist and be a file"); } return f; } public File fileOrDir(final File dir, final String name) throws Throwable { final File f = new File(dir.getAbsolutePath(), name); if (!f.exists()) { throw new Exception(name + " in " + f.getAbsolutePath() + " must exist"); } return dir; } public File file(final String path) throws Throwable { final File f = new File(path); if (!f.exists() || !f.isFile()) { throw new Exception(path + " must exist and be a file"); } return f; } /** Parse a reader and return the DOM representation. * * @param rdr Reader * @param nameSpaced true if this document has namespaces * @return Document Parsed body or null for no body * @exception Throwable Some error occurred. */ public Document parseXml(final Reader rdr, final boolean nameSpaced) throws Throwable { if (rdr == null) { // No content? return null; } final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(nameSpaced); final DocumentBuilder builder = factory.newDocumentBuilder(); return builder.parse(new InputSource(rdr)); } /** If it's a file - delete it. * If it's a directory delete the contents and if deleteThis is true * delete the directory as well. * * @param file file/dir * @param deleteThis true to delete directory * @return true if something deleted */ public boolean delete(final File file, final boolean deleteThis) { final File[] flist; if (file == null) { return false; } if (file.isFile()) { return file.delete(); } if (!file.isDirectory()) { return false; } flist = file.listFiles(); if (flist != null && flist.length > 0) { for (final File f : flist) { if (!delete(f, true)) { return false; } } } if (!deleteThis) { return true; } return file.delete(); } private final static CopyOption[] copyOptionAttributes = new CopyOption[] { REPLACE_EXISTING, COPY_ATTRIBUTES }; /** * A {@code FileVisitor} that copies a file-tree ("cp -r") */ private class DirCopier implements FileVisitor<Path> { private final Path in; private final Path out; private final boolean outExists; DirCopier(final Path in, final Path out, final boolean outExists) { this.in = in; this.out = out; this.outExists = outExists; } @Override public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attrs) { // before visiting entries in a directory we copy the directory final Path newdir = out.resolve(in.relativize(dir)); try { // if ((newdir.compareTo(out) == 0) && outExists) { // return CONTINUE; // } //Utils.debug("**** Visit dir " + dir); final File nd = newdir.toFile(); if (nd.exists()) { if (nd.isDirectory()) { return CONTINUE; } error(dir.toString() + " already exists and is not a directory"); return SKIP_SUBTREE; } //Utils.debug("**** Copy dir " + dir); Files.copy(dir, newdir, copyOptionAttributes); } catch (final FileAlreadyExistsException faee) { error("File already exists" + faee.getFile()); } catch (final Throwable t) { error("Unable to create: " + newdir + ": " + t); return SKIP_SUBTREE; } return CONTINUE; } @Override public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) { //Utils.debug("**** Copy file " + file); copyFile(file, out.resolve(in.relativize(file))); return CONTINUE; } @Override public FileVisitResult postVisitDirectory(final Path dir, final IOException exc) { // fix up modification time of directory when done if (exc == null) { final Path newdir = out.resolve(in.relativize(dir)); try { final FileTime time = Files.getLastModifiedTime(dir); Files.setLastModifiedTime(newdir, time); } catch (final Throwable t) { error("Unable to copy all attributes to: " + newdir + ": " + t); } } return CONTINUE; } @Override public FileVisitResult visitFileFailed(final Path file, final IOException exc) { if (exc instanceof FileSystemLoopException) { error("cycle detected: " + file); } else { error("Unable to copy: " + file + "; " + exc); } return CONTINUE; } } public void copy(final Path inPath, final Path outPath, final boolean outExists) throws Throwable { final EnumSet<FileVisitOption> opts = EnumSet.of(FileVisitOption.FOLLOW_LINKS); final DirCopier tc = new DirCopier(inPath, outPath, outExists); Files.walkFileTree(inPath, opts, Integer.MAX_VALUE, tc); } void copyFile(final Path in, final Path out) { // if (Files.notExists(out)) { try { Files.copy(in, out, copyOptionAttributes); } catch (final Throwable t) { error("Unable to copy: " + in + " to " + out + ": " + t); } // } } public class DeletingFileVisitor extends SimpleFileVisitor<Path> { @Override public FileVisitResult visitFile(final Path file, final BasicFileAttributes attributes) throws IOException { if (attributes.isRegularFile()) { Files.delete(file); } return FileVisitResult.CONTINUE; } @Override public FileVisitResult postVisitDirectory(final Path directory, final IOException ioe) throws IOException { Files.delete(directory); return FileVisitResult.CONTINUE; } @Override public FileVisitResult visitFileFailed(final Path file, final IOException ioe) throws IOException { error("Unable to delete: " + file + ": " + ioe); return FileVisitResult.CONTINUE; } } public void deleteAll(final Path dir) throws Throwable { final DeletingFileVisitor delFileVisitor = new DeletingFileVisitor(); Files.walkFileTree(dir, delFileVisitor); } /** Return a Properties object containing all those properties that * match the given prefix. The property name will have the prefix * replaced by the new prefix. * * @param props source properties * @param prefix to match * @param newPrefix replacement * @return never null */ public static Properties filter(final Properties props, final String prefix, final String newPrefix) { final Properties res = new Properties(); for (final String pname : props.stringPropertyNames()) { if (pname.startsWith(prefix)) { res.setProperty(newPrefix + pname.substring(prefix.length()), props.getProperty(pname)); } } return res; } /** Delete any files on the given path that have a name part that * matches the split name. Allows us to remove old versions. * * @param dirPath the directory * @param sn the split name * @throws Throwable */ void deleteMatching(final String dirPath, final SplitName sn) throws Throwable { if ((sn.prefix.length() < 3) || (sn.suffix.length() < 3)) { throw new Exception("Suspect name " + sn); } final File dir = directory(dirPath); final String[] names = dir.list(); for (final String nm : names) { if (nm.startsWith(sn.prefix) && nm.endsWith(sn.suffix)) { final Path p = Paths.get(dirPath, nm); deleteAll(p); } } } void print(final String fmt, final Object... params) { final Formatter f = new Formatter(); info(f.format(fmt, params).toString()); } void info(final String msg) { logger.info(msg); } void error(final String msg) { logger.error(msg); } void debug(final String msg) { if (debug) { logger.debug(msg); } } void warn(final String msg) { logger.warn(msg); } void assertion(final boolean test, final String fmt, final Object... params) { if (test) { return; } final Formatter f = new Formatter(); throw new RuntimeException(f.format(fmt, params).toString()); } int getInt(final String val) { try { return Integer.valueOf(val); } catch (final Throwable ignored) { throw new RuntimeException("Failed to parse as Integer " + val); } } }