|
| 1 | +# Java Properties |
| 2 | + |
| 3 | +Java Properties is a drop-in replacement of the ubiquitous |
| 4 | +[`java.util.Properties`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Properties.html) |
| 5 | +that everybody knows and loves (hates?). |
| 6 | + |
| 7 | +It's an alternative implementation whose most important advantage over its standard Java sibling is that |
| 8 | +it fully supports comments in input **and** output. |
| 9 | + |
| 10 | +Meaning that a properties table like this can not only be read, but also created, changed |
| 11 | +and be written back without losing any of the comments or formatting. |
| 12 | + |
| 13 | +```properties |
| 14 | +# Server configuration file |
| 15 | + |
| 16 | +# Host name for remote server |
| 17 | +remoteHost=myserver.example.com |
| 18 | + |
| 19 | +# Port number |
| 20 | +remotePort=8080 |
| 21 | + |
| 22 | +# Password hash algorithm to use |
| 23 | +# (choose between MD5, SHA256 or SHA512) |
| 24 | +passwordHash=SHA512 |
| 25 | +``` |
| 26 | +### Setup |
| 27 | + |
| 28 | +Add it to your build file with: |
| 29 | + |
| 30 | +```xml |
| 31 | +<dependency> |
| 32 | + <groupId>org.codejive</groupId> |
| 33 | + <artifactId>java-properties</artifactId> |
| 34 | + <version>0.0.2</version> |
| 35 | +</dependency> |
| 36 | +``` |
| 37 | + |
| 38 | +or |
| 39 | + |
| 40 | +```groovy |
| 41 | +implementation 'org.codejive:java-properties:0.0.2' |
| 42 | +``` |
| 43 | + |
| 44 | +And add this import to your code: |
| 45 | + |
| 46 | +```java |
| 47 | +import org.codejive.Properties; |
| 48 | +``` |
| 49 | + |
| 50 | +### Usage |
| 51 | + |
| 52 | +After which you can do something like: |
| 53 | + |
| 54 | +```java |
| 55 | +Properties p = new Properties(); |
| 56 | +p.setProperty("port", "8080"); |
| 57 | +p.setComment("port", "Port number to use for the server"); |
| 58 | +``` |
| 59 | + |
| 60 | +or just directly in a single line: |
| 61 | + |
| 62 | +```java |
| 63 | +Properties p = new Properties(); |
| 64 | +p.setProperty("port", "8080", "Port number to use for the server"); |
| 65 | +``` |
| 66 | + |
| 67 | +And if you would write this out: |
| 68 | + |
| 69 | +```java |
| 70 | +p.store(System.out) |
| 71 | +``` |
| 72 | + |
| 73 | +you'll get: |
| 74 | + |
| 75 | +```properties |
| 76 | +# Port number to use for the server |
| 77 | +port=8080 |
| 78 | +``` |
| 79 | + |
| 80 | +You can also set multi-line comments simply like this: |
| 81 | + |
| 82 | +```java |
| 83 | +p.setComment("port", "Port number to", "use for the server"); |
| 84 | +p.setProperty("port", "8080", "Port number to", "use for the server"); |
| 85 | +``` |
| 86 | + |
| 87 | +which would both result in: |
| 88 | + |
| 89 | +```properties |
| 90 | +# Port number to |
| 91 | +# use for the server |
| 92 | +port=8080 |
| 93 | +``` |
| 94 | + |
| 95 | +Retrieving values is simple: |
| 96 | + |
| 97 | +```java |
| 98 | +p.get("port"); // Returns "8080" |
| 99 | +p.getProperty("port"); // Also returns "8080" |
| 100 | +p.getComment("port") // Returns ["Port number to", "use for the server"] |
| 101 | +``` |
| 102 | + |
| 103 | +### Comments |
| 104 | + |
| 105 | +Comments are considered either "free" or "attached", which you could see as either being |
| 106 | +just part of the file or attached to a property. For example: |
| 107 | + |
| 108 | +```properties |
| 109 | +# A header comment (free) |
| 110 | + |
| 111 | +one=First value (that has no comment) |
| 112 | + |
| 113 | +# Another free comment |
| 114 | + |
| 115 | +# An attached comment |
| 116 | +two=Second value |
| 117 | +``` |
| 118 | + |
| 119 | +Any comments that directly precede a property, so no empty lines in between, are considered |
| 120 | +"attached" to that property, which also means the comment can be retrieved using `props.getComment(key)`. |
| 121 | +On the other hand "free" comments are not attached to anything and there's no way to retrieve their |
| 122 | +values except when they are written out using `store()` or `list()`. |
| 123 | + |
| 124 | +This is also the reason that, when using `store()` with a comment, eg. `props.store(out, "The first line")`, |
| 125 | +it will actually insert an empty line after that comment, so it won't be considered attached to |
| 126 | +the first property. |
| 127 | + |
| 128 | +Another thing to take into account is that when retrieving comment, by using `getComment(key)`, you'll get a |
| 129 | +list of strings that will include the comment character. So, for example in the table above, running |
| 130 | +`getComment("two")` will return `"# An attached comment"`. |
| 131 | + |
| 132 | +In the same way, when setting comments, either by using `setComment(key, comment)` or |
| 133 | +`setProperty(key, value, comment)`, the comment lines are expected to start with a comment character. |
| 134 | +Fortunately, it isn't an error to pass in lines that do not start with a comment character and the code will |
| 135 | +try its best to figure out what comment character to use and prepend that to the lines. |
| 136 | + |
| 137 | +### Compatibility |
| 138 | + |
| 139 | +The `org.codejive.Properties` class is mostly a drop-in replacement of `java.util.Properties` with only |
| 140 | +a couple of differences: |
| 141 | + |
| 142 | + - the API now uses `String` everywhere instead of having `Object` in certain places |
| 143 | + - the class does **not** extend `Hashtable`, it's a completely outdated class that shouldn't be used anymore |
| 144 | + - the `store()` methods do **not** write a timestamp at the top of the output |
| 145 | + - the `store()` methods **will** write an empty line between any comments at the top of the output and the actual data |
| 146 | + |
| 147 | +### Development |
| 148 | + |
| 149 | +To build the project simply run: |
| 150 | + |
| 151 | +```shell |
| 152 | +./mvnw spotless:apply clean install |
| 153 | +``` |
0 commit comments