1 /*----------------------------------------------------------------------------
2 Name: Property.h
3 Project: xmlBlaster.org
4 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
5 Comment: Class used to read, store & write (java) properties.
6 -----------------------------------------------------------------------------*/
7 #ifndef _UTIL_PROPERTY_H
8 #define _UTIL_PROPERTY_H
9
10 #include <util/xmlBlasterDef.h>
11 #include <map>
12 #include <string>
13
14 namespace org { namespace xmlBlaster {
15 namespace util {
16
17 /**
18 * The class Property does handle properties in the java-way. It does not
19 * throw any exception. Errors in file-reading, writing etc. are handled
20 * by returning a special value (which for integers is zero and for bool
21 * is false and empty std::strings for std::strings.
22 * <br />
23 * When reading or writing, comments and empty lines are ignored.
24 * When writing, properties are written in alphabetical order (of the
25 * property name).
26 * <br />
27 * In properties like <code>SomeValue-${xy}-somePostValue</code> the <code>${}</code>
28 * are replaced by the value of <code>xy</code>.
29 * <br />
30 * Fills during construction the properties <code>user.home</code> and
31 * <code>file.separator</code> and <code>path.separator</code> and others
32 * as described at method <code>initializeDefaultProperties()</code>.
33 * This simplifies the reuse of the xmlBlaster.properties
34 * which uses those settings from the Java environment.
35 */
36 class Dll_Export Property {
37
38 public: typedef std::map<std::string, std::string, std::less<std::string> > MapType;
39
40 private:
41 MapType properties_;
42
43 /**
44 * Replace all ${...} variables in value.
45 * @param key The property key
46 * @param value the corresponding value
47 * @param env If true the environment is scanned as well
48 */
49 std::string replaceVariable(const std::string &key, const std::string &value, bool env);
50
51 /**
52 * Set a property without replacing ${...} variables in value.
53 * @return false if an old entry existed which was not overwritten
54 */
55 bool setProperty_(const std::string &name, const std::string &value,
56 bool overwrite=true);
57
58 /**
59 * Initialize some default properties, similar to the java virtual machine.
60 * Add some predefined variables to be useful in xmlBlaster.properties as ${user.home} etc:
61 * <pre>
62 * user.home For example "/home/marcel"
63 * user.name Your login name on the OS.
64 * java.io.tmpdir The temporary directory of your OS.
65 * file.separator On UNIX "/", on Windows "\"
66 * path.separator On UNIX ":", on Windows ";"
67 * </pre>
68 */
69 void initializeDefaultProperties();
70
71 protected:
72 /**
73 * returns true if the line is a comment, or if it is empty. Returns
74 * false if the line is a possible property line. "Possible" in the sense
75 * that its validity is not checked yet.
76 */
77 bool isComment(const std::string &line) const {
78 if (line.length() == 0) return false;
79 return (line.c_str()[0] == '#');
80 }
81
82 /**
83 * Filters (throws away) all whitespaces from the specified std::string.
84 */
85 std::string filter(const std::string &line) const {
86 std::string ret;
87 for (std::string::size_type i=0; i<line.length(); i++) {
88 if (line.c_str()[i] != ' ') ret += line.c_str()[i];
89 }
90 return ret;
91 }
92
93
94 /**
95 * gets the property in the line specified in the argument list. It
96 * returns this property as a pair name,value. If the line does not
97 * contain a valid property(for example if the = sign is not present)
98 * then a pair of empty std::strings is returned.
99 */
100 std::pair<const std::string, std::string> getPair(const std::string &line) const {
101 std::string::size_type pos = line.find("=");
102 if ((pos < 2) || (pos >= line.length()) || (isComment(line)) ) {
103 return std::pair<const std::string, std::string>("","");
104 }
105 std::string name, value;
106 name.assign(line, 0, pos);
107 value = line.substr(pos+1);
108 return std::pair<const std::string, std::string>(filter(name), filter(value));
109 }
110
111
112 public:
113
114 /**
115 * The default constructor allocate the storage
116 * std::map for the properties and parses the command line properties.<p />
117 * NOTE: You have to call loadPropertyFile() separatly
118 * @param args Length of argv
119 * @param argv The command line arguments, for example "-protocol SOCKET"
120 */
121 Property(int args=0, const char * const argv[]=0);
122
123 /**
124 * Initialize with the given key/value std::map.
125 * NOTE: You have to call loadPropertyFile() separately
126 * @param propertyMap A std::map which contains key and values pairs,
127 * for example key="protocol" and value="SOCKET"
128 */
129 Property(MapType propMap);
130
131 /*
132 * xmlBlaster.properties is searched in this sequence:
133 * <ul>
134 * <li>the command line parameter '-propertyFile', e.g. "-propertyFile /tmp/xy.properties"</li>
135 * <li>the environment variable 'propertyFile', e.g. "propertyFile=/tmp/xy.properties"</li>
136 * <li>the local directory: ./xmlBlaster.properties</li>
137 * <li>in your home directory, HOME/xmlBlaster.properties</li>
138 * <li>in the $XMLBLASTER_HOME directory</li>
139 * </ul>
140 * Command line properties have precedence<p />
141 * Environment variables are weakest
142 */
143 void loadPropertyFile();
144
145
146 ~Property() {
147 properties_.erase(properties_.begin(), properties_.end());
148 }
149
150 /**
151 * Replace all ${...} variables in value.
152 * @param env If true the environment is scanned as well
153 */
154 void replaceVariables(bool env);
155
156 const MapType& getPropertyMap() const {
157 return properties_;
158 }
159
160 /**
161 * Reads the file specified in filename. If the name is not valid, or if
162 * the system can not write to the specified file, then -1 is returned.
163 * If you specify overwrite=true (the default) then the properties read
164 * from the file are inserted into the properties even if a property
165 * with the same name has been defined earlier.
166 * <p />
167 * Note: The ${...} tokens are not replaced in this method
168 */
169 int readPropertyFile(const std::string &filename, bool overwrite=true);
170
171
172 /**
173 * writes the properties to a file specified in the argument list. If it
174 * could not write to the file, a zero is returned.
175 * Returns the number of properties written to the file.
176 */
177 int writePropertyFile(const char *filename) const ;
178
179
180 /**
181 * Gets the propety with the specified name. If no such property exists,
182 * an empty std::string is returned. If the std::string is not found, it searches
183 * in among the environment variables (only if env is set to true which
184 * is the default). In the property is not found there either, it returns
185 * an empty std::string.
186 */
187 std::string getProperty(const std::string &name, bool env=true);
188
189
190 bool propertyExists(const std::string &name, bool env=true);
191
192
193 int get(const std::string &name, int def) { return getIntProperty(name, def, false); }
194 int getIntProperty(const std::string &name, int def, bool env=true);
195
196 long get(const std::string &name, long def) { return getLongProperty(name, def, false); }
197 long getLongProperty(const std::string &name, long def, bool env=true);
198
199 org::xmlBlaster::util::Timestamp getTimestampProperty(const std::string &name, org::xmlBlaster::util::Timestamp def, bool env=true);
200
201 bool get(const std::string &name, bool def) { return getBoolProperty(name, def, false); }
202 bool getBoolProperty(const std::string &name, bool def, bool env=true);
203
204
205 std::string get(const std::string &name, const char *def) { std::string defS=def; return getStringProperty(name, defS, false); }
206 std::string get(const std::string &name, const std::string &def) { return getStringProperty(name, def, false); }
207 std::string getStringProperty(const std::string &name, const std::string &def,
208 bool env=true);
209
210 /**
211 * To allow templatized getting of properties. It returns true if the property has been found. In that
212 * case, the return value is put into the 'value' argument.
213 */
214 bool getTypedProperty(const std::string& name, std::string& value, bool env=true);
215 bool getTypedProperty(const std::string& name, int& value, bool env=true);
216 bool getTypedProperty(const std::string& name, long& value, bool env=true);
217 bool getTypedProperty(const std::string& name, bool& value, bool env=true);
218 # if __LP64__
219 // long === long long === 64 bit
220 # else
221 bool getTypedProperty(const std::string& name, org::xmlBlaster::util::Timestamp& value, bool env=true);
222 # endif
223
224 bool setProperty(const std::string &name, const std::string &value,
225 bool overwrite=true);
226
227 /**
228 * Loads the properties read from the command line (or another array).
229 * The syntax for passing properties is the same as in java if the
230 * switch javaStyle is true (default). That is "-Dprop1=val1" is
231 * then equivalent as prop1=val1 in a property file. If the switch
232 * javaStyle is false, then the Corba style is chosen, i.e. the
233 * following is correct syntax: "-ORBNameService whatever" (so no
234 * equality sign between name and value).
235 * Errors in syntax are silently ignored (the property just isn't load).
236 *
237 * @param args The length of argv[]
238 * @param argv The command line arguments, argv[0] is the executable name,
239 * for example { "HelloWorld2" "-trace" "true" }
240 * @param sep The property praefix, for example "-" for "-trace true"
241 */
242 int loadCommandLineProps(int args, const char * const argv[], const std::string &sep="-D",
243 bool javaStyle=true);
244
245
246 /**
247 * It searches in the argument list specified by argv the argument
248 * specified by name. If nothing is found it returns -1, otherwise it
249 * returns the index of argv corresponding to what specified in name.
250 */
251 int findArgument(int args, const char * const argv[], const std::string &name) {
252 for (int i=1; i < args; i++) {
253 if (std::string(argv[i]) == name) return i;
254 }
255 return -1;
256 }
257
258 std::string toXml(const std::string& extraOffset="");
259
260 }; // class Property
261
262 }}} // namespace
263
264 #endif // _UTIL_PROPERTY_H
265
266
267
268
syntax highlighted by Code2HTML, v. 0.9.1