Gluon save properties file - java

I have the following bit of code in Android. It is supposed to create a properties file and set up some properties on app init.
String androidFilePath = settingsFolderPath + File.separator + "my.properties";
File ROOT_DIR = Services.get(StorageService.class)
.orElseThrow(() -> new RuntimeException("Local storage not supported on this device!"))
.getPublicStorage("")
.orElseThrow(() -> new RuntimeException("No local storage found on this device!"));
File settingsFile = new File(ROOT_DIR, androidFilePath);
new File(settingsFile.getParent()).mkdirs();
settingsFile.createNewFile();
Properties properties = new Properties();
String public_lobby = (String) properties.getOrDefault("public_lobby",
InetAddress.getLocalHost().getHostAddress());
properties.put("public_lobby", public_lobby);
String public_lobby_port = (String) properties.getOrDefault("public_lobby_port", String.valueOf(1257));
properties.put("public_lobby_port", public_lobby_port);
OutputStream output = new FileOutputStream(settingsFile.getAbsoluteFile());
properties.store(output, null);
The problem is that when I start the app the properties file is created but never written.
I checked the my manifest and permissions and it seems to me that it is set correctly.
I do not know what to do, please help me.

Related

How to have different properties file for different machines?

So I am working in a team of people on a small school project, and we're developing java/jsp web app with apache.. I created simple properties.config file so I can store values and use them later and it looks something like this:
home_url = http://localhost:8080/to3/
to3_path = C:/Users/User2/Documents/workspace/TO-3
db_url = jdbc:mysql://localhost:3306/to3?useUnicode=true&characterEncoding=UTF-8
Problem I have is when I commit it and someone do a checkout they have to change values for url-s and paths so it fits their machine.. I heard I can make a custom properties file which will override these default values if it recognizes certain machine, but I don't know how to do it.
Thank you all in advance for your help.
Don't commit project settings. Put them in .gitignore and commit a copy of it (e.g. properties.config.sample). Make sure to keep it up to date with any new keys you add, but each developer should make their own untracked copy.
As Amadan point out you should not commit project properties. My suggestion is to create a file with .properties extension and place your properties inside. To use this file in java you can create a class like that
public class MyProperties{
private String homeUrl = "";
private String to3Path = "";
private String dbPath = "";
private final String configPath = System.getProperty("user.home") + File.separator + "my-props.properties";
public void loadProperties(){
try {
Properties prop = new Properties();
InputStream input = null;
File filePath = new File(configPath);
input = new FileInputStream(filePath);
// load a properties file
prop.load(input);
homeUrl = prop.getProperty("home_url");
to3Path = prop.getPropert("to3_path");
dbPath = prop.getProperty("db_url");
}catch (Exception e) {
e.printStackTrace();
}
}
// getters & setters
}
Then in your app you can do
MyProperties props = new MyProperties();
props.loadProperties();
String homeUrl = props.getHomeUrl();
System.getProperty("user.home") will give home path depending on the OS.
For example in windows this is path is C:\Users\yourName
This way all your co-workers can place their own properties in their personal pc inside their home path and you will be able to work without conflicts.

How to attach file to jar that can be edited inside this jar?

I am making a program that works with MySQL database,for now i store URL, login, password e.t.c as public static String. Now i need to make it possible to work on another computer, so database adress will vary, so i need a way to edit it inside programm and save. I would like to use just external txt file, but i don't know how to point it's location.
I decided to make it using Property file, i put it in src/res folder. It work correct while i'm trying it inside Intellij Idea, but when i build jar (artifact) i get java.io.FileNotFoundException
I tried two ways:
This one was just copied
private String getFile(String fileName) {
StringBuilder result = new StringBuilder("");
//Get file from resources folder
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource(fileName).getFile());
System.out.println(file.length());
try (Scanner scanner = new Scanner(file)) {
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
result.append(line).append("\n");
}
scanner.close();
} catch (IOException e) {
e.printStackTrace();
}
return result.toString();
}
System.out.println(obj.getFile("res/cfg.txt"));</code>
And second one using Properties class:
try(FileReader reader = new FileReader("src/res/cfg.txt")) {
Properties properties = new Properties();
properties.load(reader);
System.out.println(properties.get("password"));
}catch (Exception e) {
e.printStackTrace();
System.out.println(e);
}
In both ways i get java.io.FileNotFoundException. What is right way to attach config file like that?
Since the file is inside a .JAR, it can't be accessed via new File(), but you can still read it via the ClassLoader:
Properties properties = new Properties();
try (InputStream stream = getClass().getResourceAsStream("/res/cfg.txt")) {
properties.load(stream);
}
Note that a JAR is read-only. So this approach won't work.
If you want to have editable configuration, you should place your cfg.txt outside the JAR and read it from the filesystem. For example like this:
Properties properties = new Properties();
File appPath = new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().toURI()).getParentFile();
try (InputStream stream = new FileInputStream(new File(appPath, "cfg.txt"))) {
properties.load(stream);
}
There are multiple places your can place your configuration options, and a robust deployment strategy will utilize some (or all) of the following techniques:
Storing configuration files in a well known location relative to the user's home folder as I mentioned in the comments. This works on Windows (C:\Users\efrisch), Linux (/home/efrisch) and Mac (/Users/efrisch)
File f = new File(System.getProperty("user.home"), "my-settings.txt");
Reading environment variables to control it
File f = new File(System.getenv("DEPLOY_DIR"), "my-settings.txt");
Using a decentralized service such as Apache ZooKeeper to store your database settings
Use Standalone JNDI
(or the JNDI built-in to your deployment target)
Use a Connection Pool

System.getProperty("mode") returns "null"

We recently had to set up one of the tomcat servers from scratch. Tomcat version is 8.0.20. Deploying a war file, now System.getProperty("mode") returns "null" where it should return PREPROD.
It should read this "mode" from a mode.properties file which is located in the webapps directory. The two lines commented out show another part of code that does not work anymore on the new tomcat server. I replaced it with code that should work.
//String pathOfWebInf = sce.getServletContext().getRealPath("WEB-INF");
//String pathOfLocalhostFile = pathOfWebInf + File.separator + "classes"
// + File.separator;
String pathOfLocalhostFile = this.getClass().getResource("/").getPath();
String mode = System.getProperty("mode");
String fileName = "localhost-oracle.properties." + mode;
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
encryptor.setPassword("xxx");
Properties dbProps = new EncryptableProperties(encryptor);
try
{
InputStream is = new FileInputStream(pathOfLocalhostFile + fileName);
dbProps.load(is);
} catch (Exception e)
{
throw new IOException("Could not read properties file " + pathOfLocalhostFile + fileName);
}
System.properties is related to all properties in the Computer where the JVM is running... there is no mode key defined there, that is why you get null as value....
check out all the properties in the pc by doing:
final Properties props = System.getProperties();
props.list(System.out);
and verify yourself, there is no mode key in that map...
You have to load mode.properties first, like this way
private Properties mode=null;
mode = new Properties();
mode.load(new FileInputStream(pathtoMODE));
String mode = mode.getProperty("mode");

How do I create a zip file one folder up from the present working directory with NIO?

I'm having trouble using the URI class.
I can create a zip file in c:\ with code like this:
// Properties for archive file we're creating
Map<String, String> archiveProperties = new HashMap<>();
archiveProperties.put("create", "true");
archiveProperties.put("encoding", "UTF-8");
URI archiveLocation = URI.create("jar:file:/" + "my.zip");
// Create archive
FileSystem archive = FileSystems.newFileSystem(archiveLocation, archiveProperties);
But I really want the zip file to be created one directory up, if you will, from the present working directory. I've tried a lot of things, including:
// Properties for archive file we're creating
Map<String, String> archiveProperties = new HashMap<>();
archiveProperties.put("create", "true");
archiveProperties.put("encoding", "UTF-8");
URI archiveLocation = URI.create("jar:file:../" + "my.zip");
// Create archive
FileSystem archive = FileSystems.newFileSystem(archiveLocation, archiveProperties);
But I either get an exception, URI is not hierarchical in this case, or it continues to be created in c:\
I finally came up with a solution, albeit not very pretty:
// Properties for archive file we're creating
Map<String, String> archiveProperties = new HashMap<>();
archiveProperties.put("create", "true");
archiveProperties.put("encoding", "UTF-8");
String filePathName = System.getProperty("user.dir") + FILE_SEPARATOR + ".." + FILE_SEPARATOR + "myfile.zip";
filePathName = filePathName.replace('\\','/');
filePathName = filePathName.replaceAll(" ", "%20");
URI archiveLocation = URI.create("jar:file:///" + filePathName);
// Create archive
FileSystem archive = FileSystems.newFileSystem(archiveLocation, archiveProperties);
Note FILE_SEPARATOR came from System.getProperty(file.separator)
A quick fix will be to use this
URI archiveLocation = URI.create("jar:file:///"+new File(".").getAbsolutePath()+"/../my.zip");

How to load files on multiple platforms properly using Java? [duplicate]

This question already has answers here:
Platform independent paths in Java
(8 answers)
Closed 3 years ago.
I have a java swing database application which needs to be run on Windows and Linux. My database connection details are stored in a XML file and I load them.
This application can load this properties on Linux properly but it is not working on Windows.
How do I load files on multiple platforms properly using Java?
This is the code:
PropertyHandler propertyWriter = new PropertyHandler();
List keys = new ArrayList();
keys.add("ip");
keys.add("database");
Map localProps = propertyWriter.read(keys, "conf" + File.separatorChar + "properties.xml", true);//if false load from the local properties
//get properties from the xml in the internal package
List seKeys = new ArrayList();
seKeys.add("driver");
seKeys.add("username");
seKeys.add("password");
Map seProps = propertyWriter.read(seKeys, "conf" + File.separatorChar + "properties.xml", true);
String dsn = "jdbc:mysql://" + (String) localProps.get("ip") + ":3306/" + (String) localProps.get("database");
jDBCConnectionPool = new JDBCConnectionPool((String) seProps.get("driver"), dsn, (String) seProps.get("username"), (String) seProps.get("password"));
File reader method:
public Map read(List properties, String path, boolean isConfFromClassPath)
{
Properties prop = new Properties();
Map props = new HashMap();
try {
if (isConfFromClassPath) {
InputStream in = this.getClass().getClassLoader().getResourceAsStream(path);
prop.loadFromXML(in);
for (Iterator i = properties.iterator(); i.hasNext();) {
String key = (String) i.next();
props.put(key, prop.getProperty(key));
}
in.close();
} else {
FileInputStream in = new FileInputStream(path);
prop.loadFromXML(in);
for (Iterator i = properties.iterator(); i.hasNext();) {
String key = (String) i.next();
props.put(key, prop.getProperty(key));
}
in.close();
}
} catch (Exception ex) {
ex.printStackTrace();
}
return props;
}
If the file is in a jar file and accessed by the classpath then you should always use /.
The JavaDocs for the ClassLoader.getResource say that "The name of a resource is a '/'-separated path name that identifies the resource."
http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/ClassLoader.html#getResource(java.lang.String)
I'm not sure if there is the proper way, but one way is:
File confDir = new File("conf");
File propFile = new File(confDir, "properties.xml");
But in a scenario as simple as yours, I would just use /
If it's a resource located in classpath, we can load it with following snippet:
getClass().getClassLoader().getResourceAsStream(
"/META-INF/SqlQueryFile.sql")));
You can load all files on multiple platforms without any trouble.
Kindly use Matcher.quoteReplacement(File.separator) for replacing the slash.
It will works for every platform.
String fileLocation = "/src/service/files";
fileLocation = fileLocation.replaceAll("/",Matcher.quoteReplacement(File.separator));
assuming that your file is in conf/properties.xml on Linux and conf\properties.xml on Windows,
use File.pathSeparator instead of File.separator

Categories

Resources