I am trying to utilize PropertiesConfiguration to manipulate property files in coldfusion. Using org.apache.commons.configuration version 1.10.
propertyFile = "usergui.properties";
config = createObject("java","org.apache.commons.configuration.PropertiesConfiguration").init(propertyFile);
I am getting to matching function init that takes a string. I have tried doing java.io.file.
I figured it out problem was that I didn't include all the dependencies. DUH!
function updatePropFile(string propFile, struct propStruct, struct removeStruct){
propertyFile = propFile;
javaFile = createObject("java", "java.io.File").init(propertyFile);
fileStream = createObject("java", "java.io.FileInputStream").init(javaFile);
config = createObject("java","org.apache.commons.configuration.PropertiesConfiguration").init(javaFile);
configLayout = config.getLayout();
for(key in propStruct){
if(config.containsKey(key)){
config.setProperty(key, propStruct[key]);
}else{
config.addProperty(key, propStruct[key]);
}
}
for(key in removeStruct){
if(config.containsKey(key)){
/* clear prop and add as comment */
value = config.getProperty(key).toString();
config.clearProperty(key);
config.addProperty('##'&key, key & "=" & value);
}
}
configLayout.save(createObject("java", "java.io.FileWriter").init(propFile, false));
}
Related
Say that I have the following two configuration files:
File 1:
key1 = ${common.key1}
key2 = ${common.key2}
File 2:
common.key1 = value1
common.key2 = value2
And I have the following code:
import org.apache.commons.configuration.PropertiesConfiguration;
...
PropertiesConfiguration newConfig = new PropertiesConfiguration();
File configFile1 = new File("...paht to file 1");
File configFile2 = new File("...path to file 2");
newConfig.setDelimiterParsingDisabled(true);
newConfig.load(configFile2);
newConfig.load(configFile1);
Iterator<String> props = newConfig.getKeys();
while (props.hasNext()) {
String propName = props.next();
String propValue = newConfig.getProperty(propName).toString();
System.out.println(propName + " = " + propValue);
}
I have the following output:
common.key1 = value1
common.key2 = value2
key1 = ${common.key1}
key2 = ${common.key2}
Why the placeholders are not resolved ?
See this page in the documentation, which says:
Below is some more information related to variable interpolation users should be aware of:
...
Variable interpolation is done by all property access methods. One exception is the generic getProperty() method which returns the raw property value.
And that's exactly what you are using in your code.
The API docs of getProperty() mentions this as well:
Gets a property from the configuration. ... On this level variable substitution is not yet performed.
Use other methods available in PropertiesConfiguration to get the actual, interpolated value. For example, call getProperties() on the PropertiesConfiguration to convert it to a java.util.Properties object and iterate on that instead.
It is also possible to use it in generic way with placeholders substitution like below:
config.get(Object.class, propName);
Unlike getProperty method the get method with Object.class parameter will return value of original class with variables interpolated.
I have a simple annotation processor that needs to read a configuration file from the same project as the annotated classes. Example structure:
- myproject
- src
- main
- java
- my.package.SourceFile
- resources
- config.json
In the annotation processor, I try to read the file:
FileObject resource = processingEnv.getFiler().getResource(StandardLocation.SOURCE_PATH, "", "config.json");
but it throws FileNotFoundException. I also tried other paths, such as ../resources/config.json, (which throws Invalid relative name: ../resources/config.json). And I tried putting the config file in src/main/java (and even src/main/java/my/package) instead, which I don't like, but that also still throws FileNotFoundException.
It would already help if I could get filer.getResource() to tell me where it's looking. To find that out, I tried generating a file:
filer.createResource(StandardLocation.SOURCE_OUTPUT, "", "dummy");
which generated in myproject/build/classes/main/dummy. Unfortunately, I can't generate in SOURCE_PATH, so that doesn't help with finding this out.
I'd expect that the stuff from src/main/resources gets copied to target/classes during the build (prior to annotation processing). In that case you can open them like this:
ProcessingEnvironment pe = ...;
FileObject fileObject = pe.getFiler()
.getResource( StandardLocation.CLASS_OUTPUT, "", "config.json" );
InputStream jsonStream = fileObject.openInputStream();
I've looked at this with one of the Project Lombok developers. If anyone knows annotation processing, it's them ;)
Our conclusion was, that the JavacFileManager that handles the request internally, does not have a path to resolve StandardLocation.SOURCE_PATH to. We're not sure, but it might be related to building with Gradle.
I had the same problem and was searching for solution for a while and found this cool hack that does the trick for Android
And below you can see my solution from pure Java/Kotlin project
fun ProcessingEnvironment.getResourcesDirectory(): File {
val dummySourceFile = filer.createSourceFile("dummy" + System.currentTimeMillis())
var dummySourceFilePath = dummySourceFile.toUri().toString()
if (dummySourceFilePath.startsWith("file:")) {
if (!dummySourceFilePath.startsWith("file://")) {
dummySourceFilePath = "file://" + dummySourceFilePath.substring("file:".length)
}
} else {
dummySourceFilePath = "file://$dummySourceFilePath"
}
val cleanURI = URI(dummySourceFilePath)
val dummyFile = File(cleanURI)
val projectRoot = dummyFile.parentFile.parentFile.parentFile.parentFile.parentFile
return File(projectRoot.absolutePath + "/resources")
}
Following function works for me with annotation processor being triggered by gradle, it's not the pretties one but works:
private fun resolveApplicationPropertiesFile(): File {
val projectRoot = Path.of(processingEnv.filer.getResource(StandardLocation.CLASS_OUTPUT, "", "doesntmatter")
.toUri())
.parent
.parent
.parent
.parent
.parent
.parent
val properties = Path.of(projectRoot.toString(), "src", "main", "resources", "application.yml")
return properties.toFile()
}
where processingEnv is a member of AbstractProcessor
If your element is instance of TypeElement,then you can use these code to find your source code
FileObject fileObject = processingEnv.getFiler().getResource(
StandardLocation.SOURCE_PATH, element.getEnclosingElement().toString(),
element.getSimpleName() + ".java");
element.getEnclosingElement() is your class package, eg: com.fool
element.getSimpleName() is your class name, eg: Person
then you can print them:
CharSequence content = fileObject.getCharContent(true);
Im working with exporting and importing Orient DB using java. I could export a whole database. But when i specify to export a specified class it export that class only. Sub classes are not exported. Here is the code:
ODatabaseDocumentTx db = new ODatabaseDocumentTx("remote:localhost/sampleDataBase").open("admin", "admin");
ODatabaseExport export = new ODatabaseExport(db, "DataCont/FinalTry.gz", listener);
Set<String> a= new HashSet<String>();
a.add("Employee".toUpperCase());
export.setIncludeClasses(a);
export.exportDatabase();
export.close();
So is this suppose to be or am i doing anything wrong?
Checking the source code for ODatabaseExport it does seem that it only takes clusters/records which are exactly of the type specified with setIncludeClasses(). For instance in exportRecords():
ODocument doc = (ODocument) rec;
final String className = doc.getClassName() != null ? doc.getClassName().toUpperCase() : null;
if (includeClasses != null) {
if (!includeClasses.contains(className))
continue;
} else if (excludeClasses != null) {
if (excludeClasses.contains(className))
continue;
}
They have similar checks in several other places in that class. This would mean that you need to put into the a set all the classes you want to export yourself.
You can add this piece of code if want to export all subclasses too:
Set<String> classesToExport = new HashSet<>();
classesToExport.add("Employee".toUpperCase());
OSchema oSchema = db.getMetadata().getSchema();
for (String className : classesToExport) {
OClass clazz = oSchema.getClass(className);
for(OClass subClass : clazz.getAllBaseClasses()){
//String subClassName = subClass.getName();
String subClassName = subClass.getName().toUpperCase();
if(!classesToExport.contains(subClassName)){
classesToExport.add(subClassName);
}
}
}
I want to append a value to following Key like this:
[Section]
Key=value1,value2
I tried Wini and Section getAll() and putAll() functions but it always replaces value1 with value2 instead of appending value2. And I did' t find any tutorial about this online. How can I do this using ini4j? Or another jni writinig and parsing library?
I finally treated it as a single Key-value pair and appended to the string after "Key=".
This topic is a little old, but I'm faced exact the same problem, so...
To read all:
//open the file
Ini ini = new Ini(new File(iniFileName));
//load all values at once
Ini.Section names = ini.get("mySectionX");
myStr[] = names.getAll("myKey1", String[].class);
To put all (with the same ini and names):
//if myStr[] have changes
names.putAll("myKey1", myStr);
At final you gonna have the ini file like this ("myKey1" is ALWAYS the same):
[mySectionX]
myKey1 = value1
myKey1 = value2
myKey1 = value3
Adding more information,
if you want o create a new file:
Ini ini = new Ini();
ini.setComment(" Main comment "); //comment about the file
//add a section comment, a section and a value
ini.putComment("mySectionX", " Comment about the section");
ini.put("mySectionX", "myKey1", "value1");
//adding many parameters at one in a section
String[] keyList = {value1, value2, value3};
ini.add("mySectionY");
Ini.Section names = ini.get("mySectionY");
names.putAll("myKey1", keyList); //put all new elements at once
...
ini.store(new File(iniFileName));
I'm storing my app settings in properties file that I use in Ant and in the Java app. Maybe it's not good pratice, but I find it very handy to avoid duplications. The file contains variables such as:
usefulstuff.dir = ${user.home}/usefulstuff
So that other people can run the program on *nix systems, provided that they have the usefulstuff folder in their home directory.
Now, the fascinating thing is that this properties file works fine in Ant (the variable gets resolved to /home/username), while when I load the same file directly in the Java app, I get a string containing ${user.home}/usefulstuff, which is not very useful indeed.
I load the props with this code in Ant:
<loadproperties srcFile="myProps.properties"/>
And in the Java app:
FileInputStream ins = new FileInputStream(propFilePath);
myProps.load(ins);
ins.close();
Am I missing anything? Maybe is there a better way to load properties in a Java app than load()?
I don't think it's particularly "fascinating" that this works in Ant - Ant is deliberately written to do so:
Properties are key-value-pairs where Apache Ant tries to expand ${key} to value at runtime.
and
Ant provides access to all system properties as if they had been defined using a <property> task. For example, ${os.name} expands to the name of the operating system.
If you want the same behaviour, you'll need to implement the same sort of logic. It's possible that you could use the classes from Ant directly, if they do what you want - and if you're happy to ship the relevant binaries (and abide by the licence).
Otherwise, you might want to use a regular expression to find all the matches - or (probably simpler) iterate over all of the system properties and do a simple replacement on them.
As Jon said, it should be straighforward to write the property handling yourself. For eg:
import java.util.*;
public class PropertiesTest
{
public static void main(String[] args)
{
Properties props = new Properties();
props.setProperty("foo", "foo/${os.name}/baz/${os.version}");
props.setProperty("bar", "bar/${user.country}/baz/${user.country}");
System.out.println("BEFORE:");
printProperties(props);
resolveSystemProperties(props);
System.out.println("\n\nAFTER:");
printProperties(props);
}
static void resolveSystemProperties(Properties props)
{
Map<String, String> sysProps = readSystemProperties();
Set<String> sysPropRefs = sysProps.keySet();
Enumeration names = props.propertyNames();
while (names.hasMoreElements())
{
String name = (String) names.nextElement();
String value = props.getProperty(name);
for (String ref : sysPropRefs)
{
if (value.contains(ref))
{
value = value.replace(ref, sysProps.get(ref));
}
}
props.setProperty(name, value);
}
}
static Map<String, String> readSystemProperties()
{
Properties props = System.getProperties();
Map<String, String> propsMap =
new HashMap<String, String>(props.size());
Enumeration names = props.propertyNames();
while (names.hasMoreElements())
{
String name = (String) names.nextElement();
propsMap.put("${" + name + "}", props.getProperty(name));
}
return propsMap;
}
static void printProperties(Properties props)
{
Enumeration names = props.propertyNames();
while (names.hasMoreElements())
{
String name = (String) names.nextElement();
String value = props.getProperty(name);
System.out.println(name + " => " + value);
}
}
}