108 } |
108 } |
109 } |
109 } |
110 return SIZE_MAX; |
110 return SIZE_MAX; |
111 } |
111 } |
112 |
112 |
113 LogOutput* LogConfiguration::new_output(char* name, const char* options) { |
113 LogOutput* LogConfiguration::new_output(char* name, const char* options, outputStream* errstream) { |
114 const char* type; |
114 const char* type; |
115 char* equals_pos = strchr(name, '='); |
115 char* equals_pos = strchr(name, '='); |
116 if (equals_pos == NULL) { |
116 if (equals_pos == NULL) { |
117 type = "file"; |
117 type = "file"; |
118 } else { |
118 } else { |
119 *equals_pos = '\0'; |
119 *equals_pos = '\0'; |
120 type = name; |
120 type = name; |
121 name = equals_pos + 1; |
121 name = equals_pos + 1; |
122 } |
122 } |
123 |
123 |
|
124 // Check if name is quoted, and if so, strip the quotes |
|
125 char* quote = strchr(name, '"'); |
|
126 if (quote != NULL) { |
|
127 char* end_quote = strchr(name + 1, '"'); |
|
128 if (end_quote == NULL) { |
|
129 errstream->print_cr("Output name has opening quote but is missing a terminating quote."); |
|
130 return NULL; |
|
131 } else if (quote != name || end_quote[1] != '\0') { |
|
132 errstream->print_cr("Output name can not be partially quoted." |
|
133 " Either surround the whole name with quotation marks," |
|
134 " or do not use quotation marks at all."); |
|
135 return NULL; |
|
136 } |
|
137 name++; |
|
138 *end_quote = '\0'; |
|
139 } |
|
140 |
124 LogOutput* output; |
141 LogOutput* output; |
125 if (strcmp(type, "file") == 0) { |
142 if (strcmp(type, "file") == 0) { |
126 output = new LogFileOutput(name); |
143 output = new LogFileOutput(name); |
127 } else { |
144 } else { |
128 // unsupported log output type |
145 errstream->print_cr("Unsupported log output type."); |
129 return NULL; |
146 return NULL; |
130 } |
147 } |
131 |
148 |
132 bool success = output->initialize(options); |
149 bool success = output->initialize(options); |
133 if (!success) { |
150 if (!success) { |
|
151 errstream->print_cr("Initialization of output '%s' using options '%s' failed.", name, options); |
134 delete output; |
152 delete output; |
135 return NULL; |
153 return NULL; |
136 } |
154 } |
137 return output; |
155 return output; |
138 } |
156 } |
272 |
290 |
273 bool LogConfiguration::parse_command_line_arguments(const char* opts) { |
291 bool LogConfiguration::parse_command_line_arguments(const char* opts) { |
274 char* copy = os::strdup_check_oom(opts, mtLogging); |
292 char* copy = os::strdup_check_oom(opts, mtLogging); |
275 |
293 |
276 // Split the option string to its colon separated components. |
294 // Split the option string to its colon separated components. |
277 char* what = NULL; |
295 char* str = copy; |
278 char* output_str = NULL; |
296 char* substrings[4] = {0}; |
279 char* decorators_str = NULL; |
297 for (int i = 0 ; i < 4; i++) { |
280 char* output_options = NULL; |
298 substrings[i] = str; |
281 |
299 |
282 what = copy; |
300 // Find the next colon or quote |
283 char* colon = strchr(what, ':'); |
301 char* next = strpbrk(str, ":\""); |
284 if (colon != NULL) { |
302 while (next != NULL && *next == '"') { |
285 *colon = '\0'; |
303 char* end_quote = strchr(next + 1, '"'); |
286 output_str = colon + 1; |
304 if (end_quote == NULL) { |
287 colon = strchr(output_str, ':'); |
305 log_error(logging)("Missing terminating quote in -Xlog option '%s'", str); |
288 if (colon != NULL) { |
306 os::free(copy); |
289 *colon = '\0'; |
307 return false; |
290 decorators_str = colon + 1; |
|
291 colon = strchr(decorators_str, ':'); |
|
292 if (colon != NULL) { |
|
293 *colon = '\0'; |
|
294 output_options = colon + 1; |
|
295 } |
308 } |
296 } |
309 // Keep searching after the quoted substring |
297 } |
310 next = strpbrk(end_quote + 1, ":\""); |
298 |
311 } |
299 // Parse each argument |
312 |
|
313 if (next != NULL) { |
|
314 *next = '\0'; |
|
315 str = next + 1; |
|
316 } else { |
|
317 break; |
|
318 } |
|
319 } |
|
320 |
|
321 // Parse and apply the separated configuration options |
|
322 char* what = substrings[0]; |
|
323 char* output = substrings[1]; |
|
324 char* decorators = substrings[2]; |
|
325 char* output_options = substrings[3]; |
300 char errbuf[512]; |
326 char errbuf[512]; |
301 stringStream ss(errbuf, sizeof(errbuf)); |
327 stringStream ss(errbuf, sizeof(errbuf)); |
302 bool success = parse_log_arguments(output_str, what, decorators_str, output_options, &ss); |
328 bool success = parse_log_arguments(output, what, decorators, output_options, &ss); |
303 if (!success) { |
329 if (!success) { |
304 errbuf[strlen(errbuf) - 1] = '\0'; // Strip trailing newline. |
330 errbuf[strlen(errbuf) - 1] = '\0'; // Strip trailing newline. |
305 log_error(logging)("%s", errbuf); |
331 log_error(logging)("%s", errbuf); |
306 } |
332 } |
307 |
333 |
338 } |
364 } |
339 } else { |
365 } else { |
340 idx = find_output(outputstr); |
366 idx = find_output(outputstr); |
341 if (idx == SIZE_MAX) { |
367 if (idx == SIZE_MAX) { |
342 char* tmp = os::strdup_check_oom(outputstr, mtLogging); |
368 char* tmp = os::strdup_check_oom(outputstr, mtLogging); |
343 LogOutput* output = new_output(tmp, output_options); |
369 LogOutput* output = new_output(tmp, output_options, errstream); |
344 os::free(tmp); |
370 os::free(tmp); |
345 if (output == NULL) { |
371 if (output == NULL) { |
346 errstream->print("Unable to add output '%s'", outputstr); |
|
347 if (output_options != NULL && strlen(output_options) > 0) { |
|
348 errstream->print(" with options '%s'", output_options); |
|
349 } |
|
350 errstream->cr(); |
|
351 return false; |
372 return false; |
352 } |
373 } |
353 idx = add_output(output); |
374 idx = add_output(output); |
354 } else if (output_options != NULL && strlen(output_options) > 0) { |
375 } else if (output_options != NULL && strlen(output_options) > 0) { |
355 errstream->print_cr("Output options for existing outputs are ignored."); |
376 errstream->print_cr("Output options for existing outputs are ignored."); |