From 78e5acc2f86425b42f7e3f6d75667ba77bc85af0 Mon Sep 17 00:00:00 2001 From: nathan Date: Tue, 30 Dec 2014 01:54:26 +0100 Subject: [PATCH] Updated license info. Update license headers in files --- Dorkbox-Util/.classpath | 2 +- Dorkbox-Util/LICENSE | 13 +- Dorkbox-Util/src/dorkbox/util/FileUtil.java | 115 ++++++++--- Dorkbox-Util/src/dorkbox/util/Sys.java | 192 ------------------ .../src/dorkbox/util/crypto/Crypto.java | 15 ++ .../src/dorkbox/util/crypto/CryptoX509.java | 17 +- .../signers/BcECDSAContentSignerBuilder.java | 15 ++ ...BcECDSAContentVerifierProviderBuilder.java | 15 ++ .../dorkbox/util/gwt/GwtSymbolMapParser.java | 23 ++- .../util/properties/PropertiesProvider.java | 19 +- 10 files changed, 199 insertions(+), 227 deletions(-) diff --git a/Dorkbox-Util/.classpath b/Dorkbox-Util/.classpath index e7d4eb3..ad0537e 100644 --- a/Dorkbox-Util/.classpath +++ b/Dorkbox-Util/.classpath @@ -11,7 +11,6 @@ - @@ -25,5 +24,6 @@ + diff --git a/Dorkbox-Util/LICENSE b/Dorkbox-Util/LICENSE index cef1190..70133b9 100644 --- a/Dorkbox-Util/LICENSE +++ b/Dorkbox-Util/LICENSE @@ -66,6 +66,12 @@ + - jOOU, Unsigned Numbers for Java - Apache 2.0 License + https://github.com/jOOQ/jOOU/tree/master/jOOU + Copyright 2011-2013, Lukas Eder, lukas.eder@gmail.com + + + - Kryo - New BSD License https://github.com/EsotericSoftware/kryo Copyright 2008, Nathan Sweet, All rights reserved. @@ -93,7 +99,8 @@ - - jOOU, Unsigned Numbers for Java - Apache 2.0 License - https://github.com/jOOQ/jOOU/tree/master/jOOU - Copyright 2011-2013, Lukas Eder, lukas.eder@gmail.com + - migbase64 - High performance base64 encoder & decoder - BSD License + http://migbase64.sourceforge.net/ + Copyright 2004, Mikael Grev, MiG InfoCom AB. (base64@miginfocom.com) + diff --git a/Dorkbox-Util/src/dorkbox/util/FileUtil.java b/Dorkbox-Util/src/dorkbox/util/FileUtil.java index 87a3064..0b4e55d 100644 --- a/Dorkbox-Util/src/dorkbox/util/FileUtil.java +++ b/Dorkbox-Util/src/dorkbox/util/FileUtil.java @@ -1,3 +1,18 @@ +/* + * Copyright 2010 dorkbox, llc + * + * 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 dorkbox.util; import java.io.BufferedInputStream; @@ -20,7 +35,6 @@ import java.util.zip.ZipInputStream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - /** * File related utilities. * @@ -158,6 +172,12 @@ public class FileUtil { String normalizedIn = normalize(in.getAbsolutePath()); String normalizedout = normalize(out.getAbsolutePath()); + if (normalizedIn.equalsIgnoreCase(normalizedout)) { + logger.warn("Source equals destination! " + normalizedIn); + return out; + } + + // if out doesn't exist, then create it. File parentOut = out.getParentFile(); if (!parentOut.canWrite()) { @@ -174,6 +194,11 @@ public class FileUtil { try { sourceChannel = new FileInputStream(normalizedIn).getChannel(); destinationChannel = new FileOutputStream(normalizedout).getChannel(); + + if (sourceChannel.size() == 0) { + logger2.warn("Source size is ZERO: " + normalizedIn); + } + sourceChannel.transferTo(0, sourceChannel.size(), destinationChannel); } finally { try { @@ -252,7 +277,7 @@ public class FileUtil { /** * Moves a file, overwriting any existing file at the destination. */ - public static File moveFile(String in, String out) { + public static File moveFile(String in, String out) throws IOException { if (in == null || in.isEmpty()) { throw new IllegalArgumentException("in cannot be null."); } @@ -266,7 +291,7 @@ public class FileUtil { /** * Moves a file, overwriting any existing file at the destination. */ - public static File moveFile(File in, File out) { + public static File moveFile(File in, File out) throws IOException { if (in == null) { throw new IllegalArgumentException("in cannot be null."); } @@ -274,17 +299,13 @@ public class FileUtil { throw new IllegalArgumentException("out cannot be null."); } - System.err.println("\t\t: Moving file"); - System.err.println("\t\t: " + in.getAbsolutePath()); - System.err.println("\t\t: " + out.getAbsolutePath()); - if (out.canRead()) { out.delete(); } boolean renameSuccess = renameTo(in, out); if (!renameSuccess) { - throw new RuntimeException("Unable to move file: '" + in.getAbsolutePath() + "' -> '" + out.getAbsolutePath() + "'"); + throw new IOException("Unable to move file: '" + in.getAbsolutePath() + "' -> '" + out.getAbsolutePath() + "'"); } return out; } @@ -300,7 +321,10 @@ public class FileUtil { /** * Copies a directory from one location to another */ - public static void copyDirectory(File src, File dest, String... dirNamesToIgnore) throws IOException { + public static void copyDirectory(File src_, File dest_, String... dirNamesToIgnore) throws IOException { + File src = FileUtil.normalize(src_); + File dest = FileUtil.normalize(dest_); + if (dirNamesToIgnore.length > 0) { String name = src.getName(); for (String ignore : dirNamesToIgnore) { @@ -388,37 +412,80 @@ public class FileUtil { /** * Deletes a file or directory and all files and sub-directories under it. + * @param namesToIgnore if prefaced with a '/', it will ignore as a directory instead of file */ - public static boolean delete(String fileName) { + public static boolean delete(String fileName, String... namesToIgnore) { if (fileName == null) { throw new IllegalArgumentException("fileName cannot be null."); } - return delete(new File(fileName)); + return delete(new File(fileName), namesToIgnore); } /** * Deletes a file or directory and all files and sub-directories under it. + * @param namesToIgnore if prefaced with a '/', it will ignore as a directory instead of file */ - public static boolean delete(File file) { + public static boolean delete(File file, String... namesToIgnore) { + boolean ignored = false; Logger logger2 = logger; if (file.exists() && file.isDirectory()) { File[] files = file.listFiles(); for (int i = 0, n = files.length; i < n; i++) { + boolean delete = true; + String name2 = files[i].getName(); + if (files[i].isDirectory()) { - delete(files[i].getAbsolutePath()); - } else { - if (logger2.isTraceEnabled()) { - logger2.trace("Deleting file: {}", files[i]); + for (String name : namesToIgnore) { + if (name.startsWith("/") && name.equals(name2)) { + if (logger2.isTraceEnabled()) { + logger2.trace("Skipping delete dir: {}", files[i]); + } + ignored = true; + delete = false; + break; + } + } + + if (delete) { + if (logger2.isTraceEnabled()) { + logger2.trace("Deleting dir: {}", files[i]); + } + delete(files[i], namesToIgnore); + } + } else { + for (String name : namesToIgnore) { + if (!name.startsWith("/") && name.equals(name2)) { + if (logger2.isTraceEnabled()) { + logger2.trace("Skipping delete file: {}", files[i]); + } + ignored = true; + delete = false; + break; + } + } + + if (delete) { + if (logger2.isTraceEnabled()) { + logger2.trace("Deleting file: {}", files[i]); + } + files[i].delete(); } - files[i].delete(); } } } + + // don't try to delete the dir if there was an ignored file in it + if (ignored) { + if (logger2.isTraceEnabled()) { + logger2.trace("Skipping deleting file: {}", file); + } + return true; + } + if (logger2.isTraceEnabled()) { logger2.trace("Deleting file: {}", file); } - return file.delete(); } @@ -703,7 +770,7 @@ public class FileUtil { * This is different, in that it returns ALL FILES, instead of ones that just match a specific extension. * @return the list of all files in the root+sub-dirs. */ - public static List parseDir(String rootDirectory) { + public static List parseDir(String rootDirectory) throws IOException { if (rootDirectory == null) { throw new IllegalArgumentException("rootDirectory cannot be null"); } @@ -716,7 +783,7 @@ public class FileUtil { * This is different, in that it returns ALL FILES, instead of ones that just match a specific extension. * @return the list of all files in the root+sub-dirs. */ - public static List parseDir(File rootDirectory) { + public static List parseDir(File rootDirectory) throws IOException { return parseDir(rootDirectory, (String) null); } @@ -724,10 +791,12 @@ public class FileUtil { * Parses the specified root directory for files that end in the extension to match. All of the sub-directories are searched as well. * @return the list of all files in the root+sub-dirs that match the given extension. */ - public static List parseDir(File rootDirectory, String... extensionsToMatch) { + public static List parseDir(File rootDirectory, String... extensionsToMatch) throws IOException { List jarList = new LinkedList(); LinkedList directories = new LinkedList(); + rootDirectory = FileUtil.normalize(rootDirectory.getAbsoluteFile()); + if (rootDirectory.isDirectory()) { directories.add(rootDirectory); @@ -753,7 +822,7 @@ public class FileUtil { } } } else { - System.err.println("Cannot search directory children if the dir is a file name: " + rootDirectory.getAbsolutePath()); + throw new IOException("Cannot search directory children if the dir is a file name: " + rootDirectory.getAbsolutePath()); } @@ -1133,7 +1202,7 @@ public class FileUtil { return null; } - return new File(asString); + return new File(asString).getAbsoluteFile(); } /* diff --git a/Dorkbox-Util/src/dorkbox/util/Sys.java b/Dorkbox-Util/src/dorkbox/util/Sys.java index 26be7a5..78c121c 100644 --- a/Dorkbox-Util/src/dorkbox/util/Sys.java +++ b/Dorkbox-Util/src/dorkbox/util/Sys.java @@ -17,39 +17,30 @@ package dorkbox.util; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.Reader; import java.io.Writer; -import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.net.InetAddress; -import java.net.JarURLConnection; import java.net.NetworkInterface; import java.net.URL; -import java.net.URLConnection; import java.net.UnknownHostException; import java.security.AccessController; import java.security.PrivilegedExceptionAction; import java.util.ArrayList; import java.util.Arrays; import java.util.Enumeration; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.bouncycastle.crypto.digests.SHA256Digest; -import dorkbox.urlHandler.BoxURLConnection; - public class Sys { public static final int javaVersion = getJavaVersion(); public static final boolean isAndroid = getIsAndroid(); @@ -682,189 +673,6 @@ public class Sys { System.err.println(builder.toString()); } - /** - * Finds a list of classes that are annotated with the specified annotation. - */ - public static final List> findAnnotatedClasses(Class annotation) { - return findAnnotatedClasses("", annotation); - } - - /** - * Finds a list of classes in the specific package that are annotated with the specified annotation. - */ - public static final List> findAnnotatedClasses(String packageName, Class annotation) { - // find ALL ServerLoader classes and use reflection to load them. - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - - String noDotsPackageName = packageName; - boolean isEmpty = true; - if (packageName != null && !packageName.isEmpty()) { - noDotsPackageName = packageName.replace('.', '/'); - isEmpty = false; - } else { - noDotsPackageName = ""; // cannot be null! - } - - // look for all annotated classes in the projects package. - try { - LinkedList> annotatedClasses = new LinkedList>(); - - URL url; - Enumeration resources = classLoader.getResources(noDotsPackageName); - - // lengthy, but it will traverse how we want. - while (resources.hasMoreElements()) { - url = resources.nextElement(); - if (url.getProtocol().equals("file")) { - File file = new File(url.getFile()); - if (!isEmpty) { - String relativeToDir = FileUtil.getParentRelativeToDir(file, noDotsPackageName); - if (relativeToDir != null) { - findAnnotatedClassesRecursive(classLoader, noDotsPackageName, annotation, file, relativeToDir, annotatedClasses); - } - } else { - findAnnotatedClassesRecursive(classLoader, noDotsPackageName, annotation, file, file.getAbsolutePath(), annotatedClasses); - } - } else { - findModulesInJar(classLoader, noDotsPackageName, annotation, url, annotatedClasses); - } - } - - return annotatedClasses; - } catch (Exception e) { - System.err.println("Problem finding annotated classes for: " + annotation.getSimpleName()); - System.exit(-1); - } - - return null; - } - - private static final void findAnnotatedClassesRecursive(ClassLoader classLoader, String packageName, - Class annotation, File directory, - String rootPath, - List> annotatedClasses) throws ClassNotFoundException { - - File[] files = directory.listFiles(); - - if (files != null) { - for (File file : files) { - String absolutePath = file.getAbsolutePath(); - String fileName = file.getName(); - - if (file.isDirectory()) { - findAnnotatedClassesRecursive(classLoader, packageName , annotation, file, rootPath, annotatedClasses); - } - else if (isValid(fileName)) { - String classPath = absolutePath.substring(rootPath.length() + 1, absolutePath.length() - 6); - - if (!packageName.isEmpty()) { - if (!classPath.startsWith(packageName)) { - return; - } - } - - String toDots = classPath.replaceAll(File.separator, "."); - - Class clazz = Class.forName(toDots, false, classLoader); - if (clazz.getAnnotation(annotation) != null) { - annotatedClasses.add(clazz); - } - } - } - } - } - - - private static final void findModulesInJar(ClassLoader classLoader, String searchLocation, - Class annotation, URL resource, List> annotatedClasses) - throws IOException, ClassNotFoundException { - - URLConnection connection = resource.openConnection(); - - // Regular JAR - if (connection instanceof JarURLConnection) { - JarURLConnection jarURLConnection = (JarURLConnection) connection; - - JarFile jarFile = jarURLConnection.getJarFile(); - - Enumeration entries = jarFile.entries(); - - // read all the jar entries. - while (entries.hasMoreElements()) { - JarEntry jarEntry = entries.nextElement(); - String name = jarEntry.getName(); - - if (name.startsWith(searchLocation) && // make sure it's at least the correct package - isValid(name)) { - - String classPath = name.replace(File.separatorChar, '.').substring(0, name.lastIndexOf(".")); - - String toDots = classPath.replaceAll(File.separator, "."); - - Class clazz = Class.forName(toDots, false, classLoader); - if (clazz.getAnnotation(annotation) != null) { - annotatedClasses.add(clazz); - } - } - } - jarFile.close(); - } - // Files inside of box deployment - else if (connection instanceof BoxURLConnection) { - BoxURLConnection hiveJarURLConnection = (BoxURLConnection) connection; - - // class files will not have an entry name, which is reserved for resources only - String name = hiveJarURLConnection.getResourceName(); - - if (name.startsWith(searchLocation) && // make sure it's at least the correct package - isValid(name)) { - - String classPath = name.substring(0, name.lastIndexOf('.')); - classPath = classPath.replace('/', '.'); - - Class clazz = Class.forName(classPath, false, classLoader); - if (clazz.getAnnotation(annotation) != null) { - annotatedClasses.add(clazz); - } - } - } - else { - return; - } - } - - /** - * remove directories from the search. make sure it's a class file shortcut so we don't load ALL .class files! - * - **/ - private static boolean isValid(String name) { - - if (name == null) { - return false; - } - - int length = name.length(); - - if (name.charAt(length-1) == '/') { // remove directories from the search.) - return false; - } - - // ALSO, cannot use classes such as "ServerBloah$4.class". - int newLength = length-6; - for (int i=0;iInetAddress object encapsulating what is most likely the machine's LAN IP address. *

diff --git a/Dorkbox-Util/src/dorkbox/util/crypto/Crypto.java b/Dorkbox-Util/src/dorkbox/util/crypto/Crypto.java index e637cbd..c0616ba 100644 --- a/Dorkbox-Util/src/dorkbox/util/crypto/Crypto.java +++ b/Dorkbox-Util/src/dorkbox/util/crypto/Crypto.java @@ -1,3 +1,18 @@ +/* + * Copyright 2010 dorkbox, llc + * + * 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 dorkbox.util.crypto; diff --git a/Dorkbox-Util/src/dorkbox/util/crypto/CryptoX509.java b/Dorkbox-Util/src/dorkbox/util/crypto/CryptoX509.java index 7deef19..f5342a1 100644 --- a/Dorkbox-Util/src/dorkbox/util/crypto/CryptoX509.java +++ b/Dorkbox-Util/src/dorkbox/util/crypto/CryptoX509.java @@ -1,7 +1,20 @@ +/* + * Copyright 2010 dorkbox, llc + * + * 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 dorkbox.util.crypto; - - import java.io.BufferedWriter; import java.io.ByteArrayInputStream; import java.io.FileWriter; diff --git a/Dorkbox-Util/src/dorkbox/util/crypto/signers/BcECDSAContentSignerBuilder.java b/Dorkbox-Util/src/dorkbox/util/crypto/signers/BcECDSAContentSignerBuilder.java index bb51756..6c11b1d 100644 --- a/Dorkbox-Util/src/dorkbox/util/crypto/signers/BcECDSAContentSignerBuilder.java +++ b/Dorkbox-Util/src/dorkbox/util/crypto/signers/BcECDSAContentSignerBuilder.java @@ -1,3 +1,18 @@ +/* + * Copyright 2013 dorkbox, llc + * + * 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 dorkbox.util.crypto.signers; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; diff --git a/Dorkbox-Util/src/dorkbox/util/crypto/signers/BcECDSAContentVerifierProviderBuilder.java b/Dorkbox-Util/src/dorkbox/util/crypto/signers/BcECDSAContentVerifierProviderBuilder.java index 6a3051a..ac43807 100644 --- a/Dorkbox-Util/src/dorkbox/util/crypto/signers/BcECDSAContentVerifierProviderBuilder.java +++ b/Dorkbox-Util/src/dorkbox/util/crypto/signers/BcECDSAContentVerifierProviderBuilder.java @@ -1,3 +1,18 @@ +/* + * Copyright 2013 dorkbox, llc + * + * 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 dorkbox.util.crypto.signers; import java.io.IOException; diff --git a/Dorkbox-Util/src/dorkbox/util/gwt/GwtSymbolMapParser.java b/Dorkbox-Util/src/dorkbox/util/gwt/GwtSymbolMapParser.java index 68e9c69..6bef7c9 100644 --- a/Dorkbox-Util/src/dorkbox/util/gwt/GwtSymbolMapParser.java +++ b/Dorkbox-Util/src/dorkbox/util/gwt/GwtSymbolMapParser.java @@ -1,3 +1,18 @@ +/* + * Copyright 2011 dorkbox, llc + * + * 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 dorkbox.util.gwt; import io.netty.util.CharsetUtil; @@ -13,7 +28,7 @@ public class GwtSymbolMapParser { private final Map symbolMap; public GwtSymbolMapParser() { - symbolMap = new HashMap(); + this.symbolMap = new HashMap(); } /** @@ -56,7 +71,7 @@ public class GwtSymbolMapParser { } public Map getSymbolMap() { - return symbolMap; + return this.symbolMap; } public void processLine(String line) { @@ -107,12 +122,12 @@ public class GwtSymbolMapParser { // also, ignore if the source/dest name are the same, since that doesn't do any good for obfuscated names anyways. if (memberName.isEmpty() && !jsName.equals(className)) { // System.err.println(jsName + " : " + memberName + " : " + className); - symbolMap.put(jsName, className); + this.symbolMap.put(jsName, className); } } else { // version 2 // The list has already been pruned, so always put everything into the symbol map - symbolMap.put(symbolInfo[0], symbolInfo[1]); + this.symbolMap.put(symbolInfo[0], symbolInfo[1]); } } } diff --git a/Dorkbox-Util/src/dorkbox/util/properties/PropertiesProvider.java b/Dorkbox-Util/src/dorkbox/util/properties/PropertiesProvider.java index 28b71ed..dd4914b 100644 --- a/Dorkbox-Util/src/dorkbox/util/properties/PropertiesProvider.java +++ b/Dorkbox-Util/src/dorkbox/util/properties/PropertiesProvider.java @@ -23,17 +23,28 @@ import java.io.FileOutputStream; import java.io.IOException; import java.util.Properties; +import dorkbox.util.FileUtil; + public class PropertiesProvider { // the basePath for properties based settings. In JAVA proper, this is by default relative to the jar location. // in ANDROID dalvik, this must be specified to be the location of the APK plus some extra info. This must be set by the android app. public static String basePath = ""; + private String comments = "Settings and configuration file. Strings must be escape formatted!"; private final Properties properties = new SortedProperties(); private final File propertiesFile; + public PropertiesProvider(String propertiesFile) { + this(new File(propertiesFile)); + } + public PropertiesProvider(File propertiesFile) { - propertiesFile = propertiesFile.getAbsoluteFile(); + if (propertiesFile == null) { + throw new NullPointerException("propertiesFile"); + } + + propertiesFile = FileUtil.normalize(propertiesFile); // make sure the parent dir exists... File parentFile = propertiesFile.getParentFile(); if (parentFile != null) { @@ -45,6 +56,10 @@ public class PropertiesProvider { _load(); } + public void setComments(String comments) { + this.comments = comments; + } + private final void _load() { if (!this.propertiesFile.canRead() || !this.propertiesFile.exists()) { // in this case, our properties file doesn't exist yet... create one! @@ -69,7 +84,7 @@ public class PropertiesProvider { private final void _save() { try { FileOutputStream fos = new FileOutputStream(this.propertiesFile); - this.properties.store(fos, "Settings and configuration file. Strings must be escape formatted!"); + this.properties.store(fos, this.comments); fos.flush(); fos.close();