how to store java.util.prefs.Preferences in file? - java

I'm using java.util.prefs.Preferences for application preferences.
And I need ability to edit those preferences manually.
Is it possible to store it into file instead of Windows Registry?
Or I should use another mechanism instead of java.util.prefs.Preferences?

If you want to continue using the Preferences API, but write to a file, you will need a new PreferencesFactory, as detailed in this SO post.

You are going to want to use the following two method :
Preferences.exportSubtree(OutputStream os)
and
Preferences.importPreferences(InputStream is)

This code should help you [http://java.sun.com/developer/technicalArticles/releases/preferences/]:
public class PrefSave {
private static final String PACKAGE = "/pl/test";
public static void main(String[] args) {
doThings(Preferences.systemRoot().node(PACKAGE));
doThings(Preferences.userRoot().node(PACKAGE));
}
public static void doThings(Preferences prefs) {
prefs.putBoolean("Key0", false);
prefs.put("Key1", "Value1");
prefs.putInt("Key2", 2);
Preferences grandparentPrefs = prefs.parent().parent();
grandparentPrefs.putDouble("ParentKey0", Math.E);
grandparentPrefs.putFloat("ParentKey1", (float) Math.PI);
grandparentPrefs.putLong("ParentKey2", Long.MAX_VALUE);
String fileNamePrefix = "System";
if (prefs.isUserNode()) {
fileNamePrefix = "User";
}
try {
OutputStream osTree = new BufferedOutputStream(
new FileOutputStream(fileNamePrefix + "Tree.xml"));
grandparentPrefs.exportSubtree(osTree);
osTree.close();
OutputStream osNode = new BufferedOutputStream(
new FileOutputStream(fileNamePrefix + "Node.xml"));
grandparentPrefs.exportNode(osNode);
osNode.close();
} catch (IOException ioEx) {
// ignore
} catch (BackingStoreException bsEx) {
// ignore too
}
}

Try the following class which allows you to use some simple put() and get() functions using a local configuration.xml file.
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.InvalidPropertiesFormatException;
import java.util.Properties;
public class SimpleProperties
{
private String propertiesFilePath;
private Properties properties;
public SimpleProperties() throws InvalidPropertiesFormatException, IOException
{
propertiesFilePath = "configuration.xml";
properties = new Properties();
try
{
properties.loadFromXML(new FileInputStream(propertiesFilePath));
} catch (InvalidPropertiesFormatException e)
{
}
}
public void put(String key, String value) throws FileNotFoundException, IOException
{
properties.setProperty(key, value);
store();
}
public String get(String key)
{
return properties.getProperty(key);
}
private void store() throws FileNotFoundException, IOException
{
String commentText = "Program parameters";
properties.storeToXML(new FileOutputStream(propertiesFilePath), commentText);
}
}

It is explained in another post, here
Properties prop = new Properties();
InputStream in = getClass().getResourceAsStream("foo.properties");
prop.load(in);
in.close()

I think you can use property files instead. They are stored in the file system. You can define the path you want. And you can edit it by hand. See this question for more details.

A while back I had to come up with an implementation of the Preferences class that would read settings from but not write to the registry. I derived a ReadOnlyPreferences class from AbstractPreferences to accomplish this. Later, I needed this exact same functionality you require to go to/from files. I just extended my ReadOnlyPreferences class to override sync() and flush() to keep the file in sync. The cool part about this it would use the exact same logic to apply defaults to the values just like the usual use of the prefs since nothing actually existed in the registry to read. I kept the file in sync by using exportSubtree() and importPreferences() from the base class to do all the heavy lifting for me.
I am sorry I cannot post the code as I don't own it but I used the encrypted preferences stuff you can find at the following link as a start point. That's what I did and it took me about an hour to distill it down to just what I needed which was mainly throwing code away which is much easier than writing code! It is also published in Dr Dobbs at the following link if you don't want to click on the first one. I just never saw an easy place on the dobbs article to download the entire source. Regardless, the article is the best I've seen for extending the preferences stuff.
http://www.panix.com/~mito/articles/#ep
http://www.drdobbs.com/security/encrypted-preferences-in-java/184416587?pgno=4

Related

Generating a new java class by writing java program in another java class [duplicate]

This question already has answers here:
How do I create a file and write to it?
(35 answers)
Closed 3 years ago.
I want to create a java program that generates another java class in the same project. For example in the class Dragon.java, i want to write java code that creates another java class called fire.java. I do not want to use any GUI from eclipse, just pure code that generates another class from the execution of written programming in java.
I have tried making objects of a non existent class in hopes of the program automatically producing a class with that name.
Again, it doesn't have to be just a java class, is there a way to make other forms of files also? for example fol.flow, or of different names.
Creating a new Java file is easy. You can use any FileWriter technique. But what need to be taken care of is that new Java file is valid java file and can be compiled to class file.
This link has working example of doing the same.
import java.io.*;
import java.util.*;
import java.lang.reflect.*;
public class MakeTodayClass {
Date today = new Date();
String todayMillis = Long.toString(today.getTime());
String todayClass = "z_" + todayMillis;
String todaySource = todayClass + ".java";
public static void main (String args[]){
MakeTodayClass mtc = new MakeTodayClass();
mtc.createIt();
if (mtc.compileIt()) {
System.out.println("Running " + mtc.todayClass + ":\n\n");
mtc.runIt();
}
else
System.out.println(mtc.todaySource + " is bad.");
}
public void createIt() {
try {
FileWriter aWriter = new FileWriter(todaySource, true);
aWriter.write("public class "+ todayClass + "{");
aWriter.write(" public void doit() {");
aWriter.write(" System.out.println(\""+todayMillis+"\");");
aWriter.write(" }}\n");
aWriter.flush();
aWriter.close();
}
catch(Exception e){
e.printStackTrace();
}
}
public boolean compileIt() {
String [] source = { new String(todaySource)};
ByteArrayOutputStream baos= new ByteArrayOutputStream();
new sun.tools.javac.Main(baos,source[0]).compile(source);
// if using JDK >= 1.3 then use
// public static int com.sun.tools.javac.Main.compile(source);
return (baos.toString().indexOf("error")==-1);
}
public void runIt() {
try {
Class params[] = {};
Object paramsObj[] = {};
Class thisClass = Class.forName(todayClass);
Object iClass = thisClass.newInstance();
Method thisMethod = thisClass.getDeclaredMethod("doit", params);
thisMethod.invoke(iClass, paramsObj);
}
catch (Exception e) {
e.printStackTrace();
}
}
}
At first I thought you wanted code generation, but you simply want to write to files or create them?
The simplest code to create file and write to it:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
public class Testing {
public static void main(String[] args) throws IOException {
Files.writeString(Paths.get("D://output.txt"), "some text to write", StandardOpenOption.CREATE);
}
}
It uses only java standard classes, you don't need any libraries or anything external. Just make sure to write to the valid path, where you have access.
If you want to generate files with java code, you can just do it with the method above, but creating the String with code content is really hard, there are libraries for it and they are not easy to use for beginners. For example javapoet. I personally used javaparser, it has a lot of other possibilities besides generating code.

Serenity screenplay pattern- upload file

We are trying cucumber serenity framework for end to end tests. I am fairly new the technology and I tired this simple code below.
actor.attemptsTo(Enter.theValue(path).into(Upload));
where path is the location of file i am trying to upload using browser's upload widget.Has anyone ever managed to perform actions like this using serenity screen play pattern.
Its really making us think of giving up serenity and just use cucumber-selenium framework as I can easily perform this using Upload.sendkeys(path);
Any help is much appreciated. Thanks in advance.
AS requested: Listing Steps:
public class ListingSteps
{
#Before
public void set_the_stage() {
OnStage.setTheStage(new OnlineCast());
}
#Given("^(.*) is able to click import products$") public void userIsAbleToClick(String actorName) throws Throwable
{
theActorCalled(actorName).wasAbleTo(Start.theApplication());
}
#When("^s?he imports a single item successfully$") public void heImportsASingleItemSuccessfully() throws Throwable
{
theActorInTheSpotlight().attemptsTo(Import.spreadsheet());
}
#Then("^(.*) are listed on ebay and amazon with all the right information$") public void itemsAreListedOnEbayAndAmazonWithAllTheRightInformation(String actorName, String SKU)
throws Throwable
{
//pending
}
Ignore then for now as its work in progress.
Import class:
public class Import implements Task
{
protected String path =
"C:\\somePathToFile\\populated_excel.xlsx";
public static Import spreadsheet()
{
return instrumented(Import.class);
}
#Override public <T extends Actor> void performAs(T actorName)
{
actorName.attemptsTo(Click.on(Products.ProductsScreen));
actorName.attemptsTo(Click.on(Products.Upload));
actorName.attemptsTo(Enter.theValue(path).into(Browse).thenHit(Keys.RETURN));//this is the line which is giving errors
actorName.attemptsTo(Click.on(Products.UploadButton));
}
}
Target Browse
public class Products
{
public static Target Browse = Target.the("browse file").locatedBy("//input[#type='file']");
}
Did you try removing these lines?
actorName.attemptsTo(Click.on(Products.ProductsScreen));
actorName.attemptsTo(Click.on(Products.Upload));
You don't need to open the upload file component, only write the file path directly to the input file element and perform the submit.
The way I managed to get this working was by using the FileToUpload class:
import net.thucydides.core.pages.components.FileToUpload;
FileToUpload fileToUpload = new FileToUpload(driver, fileName);
fileToUpload.fromLocalMachine().to(webElement);
I got this working with a simple:
import java.nio.file.*;
Path data = null;
try {
data = Paths.get(ClassLoader.getSystemResource(file).toURI());
} catch (URISyntaxException ignore) {}
ACTOR.attemptsTo(Upload.theFile(data).to(target));
file is an actual file that exists on your classpath, in src/test/resources if you have a Maven project.
target is something like:
Target.the("Image upload").located(By.xpath("//input[#type='file']"));

Using a separate java files methods

This question is about Android, although i dont think that this is android-specific.
I have a project that i want to use two files with: MainActivity.java and filetools.java . I have three methods in filetools.java, read, write and append.
I want to be able to do something like this in my MainActivity:
filetools.write("/sdcard/file.txt", "something");
The code for MainActivity is just the package, imports, the class, and onCreate.
The code for filetools:
package com.tylerr147.FileRW;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Scanner;
public class filetools
{
public String read(String fName){
try{
File mFile = new File(fName);
String content = new Scanner(mFile).useDelimiter("\\Z").next();
return content;
}catch(Exception e) {
return "There was an error retrieving your file. The proccess returned this error:\n"+e.toString();
}
}
public boolean write(String loc, String stuff) {
File mfile = new File(loc);
try {
mfile.createNewFile();
FileOutputStream f = new FileOutputStream(mfile);
OutputStreamWriter f2 = new OutputStreamWriter(f);
f2.append(stuff);
f2.close();
f.close();
} catch(IOException e) {
return false;
}
return true;
}
public void append(String filename, String content) {
write(filename, read(filename)+content);
}
}
Another thing i would like to be able to do is to have a completely different app by the package com.app.importer
how could i do something like
import com.app.importer;
importerAppsMethod();
I have found a few posts on stackoverflow, but they do not help.
Importing my custom class and calling it's method?
There are a few more, and i have searched and can not find anything that works for me. Any help is appreciated
I am putting #ishmaelMakitla comment intocan answer.
To do something like filetools.write("/sdcard/file.txt", "something"); - you need to declare the write method as static. For example: public static boolean write(String loc, String stuff). You may have to do the same for all other methods if you want similar behavior. Is this what you are looking for?

Eliminate hardcoded file paths and urls in web development

I'm currently developing a web site using servlets & spring framework. As usual it contains lots of files (jsp, js, css, images, various resources etc).
I'm trying to avoid writing any hardcoded path, or domain in any file ...
For example as you may know when a request is handled you 'forward' it to a jsp page (it's path probably will be hardcoded). Other examples are imports images/css/js etc in jsp files ...
Is there any general way (or tools) to avoid hardcoded paths/urls so any refactorings won't cause troubles?
EDIT
I use netbeans 7.1.2 ... Unfortunately netbeans only helps with pure java code. When working with jsp files things are limited, and if you add custom tag files and Jsp 2.0 EL is like programming in console mode :p
In the JSP files themselves, you can avoid nearly all hardcoded domain / urls by using JSTL
For example, when creating a link to another page, you would do it like this:
Refer an Entrepreneur!
This means that, regardless of where your webapp is, the link will always have the right url. For example, in my development box this link would be:
http://localhost:8080/accounts/referrals/send.html
But on my production server, it resolves correctly to:
http://wwww.mydomain.com/referrals/send.html
You can see that in my dev server, the webapp context is under /accounts, but on the production machine, it's just under / as the webapp is under the root context.
You can read a small tutorial here
Properties file is always a good option so that you have to make changes if any only at one point.
If you are referencing any static contents (js, images, css, etc), you don't have to hardcode the entire file path. Instead, you can do this:-
<img src="${pageContext.request.contextPath}/resources/images/test.jpg"/>
The rest of the file paths (Hibernate domain mappings, forwarded page in Spring controller, etc) should be relative to your project structure, and most IDEs are smart enough to refactor them without problem... or at least in my case, IntelliJ seems to handle of all that for me.
At some point of time, you need to ask yourself, how much of hardcoding is acceptable vs not acceptable? Further, I wouldn't try to stray too far away from the Spring/Hibernate recommended solutions. If you make everything too abstract, you have a different set of problem to deal with and it becomes counterproductive to other peers that may be inheriting your project in the future.
Actually I just came up with an idea. Since netbeans does analysis and shows dependencies on java code, maybe it's better to handle all paths & domains as java variables.
I've created a package on my project named FileResolver and inside I have one class for each file type on my project (eg one class for Jsp files, one for Css files etc). Inside those files I'll record & hardcode all paths of all files in public static final String variables. Sample:
public class Jsps {
public class layouts{
public static final String main = "layouts/main.jsp";
}
public class pages{
public static final String error = "pages/error.jsp";
public static final String login = "pages/login.jsp";
public static final String register = "pages/register.jsp";
}
...
}
All over my project I should use the variables instead of paths. Then anytime I refactor a file, I'll have only one file to change is the mapping value in those variables ...
And if somethime I need to change the variable, netbeans will refactor all of them in the project at once ...
I think this will work just fine since I keep my project clean from file paths and the only thing I have to worry about is the mapping in that file of the variables to appropriate file paths.
EDIT
I'll write a simple parser to create those java files instead of writting by hand for all files ... I'll update when I finish it
UPDATE
Here is my FileResolverGenerator
public class FileResolverGenerator {
private static final String newFilePath = "C:/Users/Foo/Desktop/Jsps.java";
private static final String scanRootFolder = "C:/Users/Foo/Desktop/myProject/web/WEB-INF/jsp";
private static final String varValueReplaceSource = "C:/Users/Foo/Desktop/myProject/web/WEB-INF/jsp/";
private static final String varValueReplaceTarget = "";
private static final boolean valueAlign = true;
private static final int varNameSpaces = 15;
public static void main(String[] args){
try {
// Create file and a writer
File f = new File(newFilePath);
f.createNewFile();
bw = new BufferedWriter( new FileWriter(f) );
// Execute
filesParser( new File(scanRootFolder) );
// 'Burn' file
bw.close();
} catch (FileNotFoundException ex) {
Logger.getLogger(ResolverGenerator.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(ResolverGenerator.class.getName()).log(Level.SEVERE, null, ex);
}
}
// ================================================================================================ //
// ============================================= WORK ============================================= //
// ================================================================================================ //
private static void filesParser(File rootFolder) throws FileNotFoundException, IOException{
folderIn(rootFolder);
// Files first
if(!rootFolder.exists()) throw new FileNotFoundException();
for(File f : rootFolder.listFiles()){
if(f==null){ return; }
if(f.isDirectory()){ continue; }
else if(f.isFile()){ writeFileVariable(f); }
}
// Folders next
for(File f : rootFolder.listFiles()){
if(f==null){ return; }
if(f.isDirectory()){ filesParser(f); }
else if(f.isFile()){ continue; }
}
folderOut(rootFolder);
}
// ================================================================================================ //
// ============================================ PRINTS ============================================ //
// ================================================================================================ //
private static BufferedWriter bw;
private static int tabCount = 0;
private static void folderIn(File f) throws IOException{
bw.append("\n\n");
for(int i=0; i<tabCount; i++)
bw.append("\t");
bw.append("public class "+f.getName()+"{\n");
tabCount++;
}
private static void folderOut(File f) throws IOException{
tabCount--;
for(int i=0; i<tabCount; i++)
bw.append("\t");
bw.append("}\n");
}
private static void writeFileVariable(File f) throws IOException{
String varName = f.getName().split("\\.")[0].replaceAll("-", "");
String varValue = f.getPath().replaceAll("\\\\","/")
.replace(varValueReplaceSource.replaceAll("\\\\","/"),varValueReplaceTarget.replaceAll("\\\\","/"));
for(int i=0; i<tabCount; i++)
bw.append("\t");
bw.append("public static final String "+varName+" = ");
if(valueAlign){
for(int i=0; i<varNameSpaces-varName.length(); i++) bw.append(" ");
bw.append("\t"); }
bw.append("\""+varValue+"\";\n");
}
}
Just to be specific ... This scans all files under "/WEB-INF/jsp/" and creates a java file having all jsp files 'registered' to public static final String variables with each path ... The idea is to use the generated java file as reference for all jsps are in project ... always use these variables instead of hardcoded paths ..
This has nothing to do with the project or any project. It's just a tool which saves you
time, instead of doing this by hand for every file in the project.
I also created another class ResolverConsistencyChecker, which takes all variables and checks if the filepath is correct (file exists) ... since we didn't made any changes to filenames and filepaths all tests are passed.
This method should run when testing project for 'errors'
public class ResolverConsistencyChecker {
private static Class checkClass = Jsps.class;
private static String fullPathPrefix = "C:/Users/Foo/Desktop/myProject/web/WEB-INF/jsp/";
public static void main(String[] args){
try {
filesChecker( checkClass );
System.out.println( "Tests passed. All files locations are valid" );
} catch (FileNotFoundException ex) {
Logger.getLogger(ResolverConsistencyChecker.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(ResolverConsistencyChecker.class.getName()).log(Level.SEVERE, null, ex);
}
}
// ================================================================================================ //
// ============================================= WORK ============================================= //
// ================================================================================================ //
private static void filesChecker(Class rootClass) throws FileNotFoundException, IOException{
// Check file paths in current class depth
for(Field f : rootClass.getFields()){
try {
String fullFilePath = fullPathPrefix+f.get(f.getName()).toString();
File file = new File( fullFilePath );
if( !file.exists() )
throw new FileNotFoundException("Variable: '"+f.getName()+"'\nFile "+fullFilePath);
} catch (IllegalArgumentException ex) {
Logger.getLogger(ResolverConsistencyChecker.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
Logger.getLogger(ResolverConsistencyChecker.class.getName()).log(Level.SEVERE, null, ex);
}
}
// Check for embedded classes
for(Class c : rootClass.getClasses()){
filesChecker(c);
}
}
}

better way to point to folders and files in a properties file?

I was wondering if there is a better way to have a point to PATH in a properties file. Consider the following code:
public class Properties
{
//MIKE
public final static String PATH_TO_FILE_A = "C:\\programmer_MIKE\fileA.txt";
public final static String PATH_TO_FILE_B = "C:\\programmer_MIKE\fileB.txt";
//BILL
//public final static String PATH_TO_FILE_A = "/Users/BILL/Desktop/fileA.txt";
//public final static String PATH_TO_FILE_B = "/Users/BILL/Desktop/fileB.txt";
}
when any developer need to invoke FILE_A he simply does:
File file = new File(Properties.PATH_TO_FILE_A);
this works ok for BILL if he commented out MIKE's PATH_TO_FILE_A.
Q: is there a better design? If BILL committed his work including the Properties file - he will cause a problem to MIKE (no worries, he'll get a Coffee Latte later on).
the FILES are big (2-4Gb) and we don't want to put them in our repository (svn) and sometimes there are simply temporary folder to create a PDF so we don't want to put them in a "./docs" path.
Thanks for any pointer!
If for whatever reason you really must have hardcoded paths, then you could store them in some kind of map indexed by username. Something like:
public class Properties {
private static Map<String, DeveloperPaths> properties = create();
private static Map<String, DeveloperPaths> create() {
Map<String, DeveloperPaths> properties = new HashMap<String, DeveloperPaths>();
properties.put("mike", new DeveloperPaths(
"C:\\programmer_MIKE\fileA.txt",
"C:\\programmer_MIKE\fileB.txt")
);
properties.put("bill", new DeveloperPaths(
"/Users/BILL/Desktop/fileA.txt",
"/Users/BILL/Desktop/fileB.txt")
);
return properties;
}
public static File FileA()
{
String user = System.getProperty("user.name");
return properties.get(user).fileA;
}
public static File FileB()
{
String user = System.getProperty("user.name");
return properties.get(user).fileB;
}
}
class DeveloperPaths {
public File fileA;
public File fileB;
public DeveloperPaths(String pathA, String pathB) {
fileA = new File(pathA);
fileB = new File(pathB);
}
}
Then, the code to access each path would be identical regardless of developer, for example:
File myFile = Properties.fileA();
Normally paths are configurable entites and should be stored in property file.
Property files has a build in support in java and it uses Properties object for storing that information.
You can read the property file at startup or init (or similar) method of your application and read the proeprties from property file. This will make your configuration dynamic and anyone would be able to change it.
You can create a static method and call it on startup like:
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class GetProperties {
public static Properties prop = new Properties();
public static void init() {
InputStream inputStream = GetProperties.class.getClassLoader().getResourceAsStream("application.properties");
try {
prop.load(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Things like this should be configured externally and/or passed in via parameter, system parameter, or environment variable. Alternatively you could use DI/IoC, but when there's no attached behavior, IMO a config value is plenty.
It's fine to have a hard-coded default, but otherwise stuff like this doesn't belong in code.

Categories