New upstream version 2.1.18
Markus Koschany
2 years ago
27 | 27 | <groupId>org.jboss.logmanager</groupId> |
28 | 28 | <artifactId>jboss-logmanager</artifactId> |
29 | 29 | <packaging>jar</packaging> |
30 | <version>2.1.15.Final</version> | |
30 | <version>2.1.18.Final</version> | |
31 | 31 | |
32 | 32 | <parent> |
33 | 33 | <groupId>org.jboss</groupId> |
57 | 57 | <org.jboss.test.port>4560</org.jboss.test.port> |
58 | 58 | <org.jboss.test.alt.port>14560</org.jboss.test.alt.port> |
59 | 59 | |
60 | <maven.compiler.source>1.8</maven.compiler.source> | |
61 | <maven.compiler.target>1.8</maven.compiler.target> | |
60 | <maven.compiler.source>8</maven.compiler.source> | |
61 | <maven.compiler.target>8</maven.compiler.target> | |
62 | 62 | |
63 | 63 | <jdk.min.version>9</jdk.min.version> |
64 | 64 | </properties> |
219 | 219 | <artifactId>maven-javadoc-plugin</artifactId> |
220 | 220 | <configuration> |
221 | 221 | <doclint>none</doclint> |
222 | <javadocExecutable>${java.home}${file.separator}bin</javadocExecutable> | |
222 | 223 | </configuration> |
223 | 224 | </plugin> |
224 | 225 | <plugin> |
43 | 43 | */ |
44 | 44 | abstract class AbstractPropertyConfiguration<T, C extends AbstractPropertyConfiguration<T, C>> extends AbstractBasicConfiguration<T, C> implements ObjectConfigurable<T>, PropertyConfigurable { |
45 | 45 | private final Class<? extends T> actualClass; |
46 | private final ClassLoader classLoader; | |
46 | 47 | private final String moduleName; |
47 | 48 | private final String className; |
48 | 49 | private final String[] constructorProperties; |
60 | 61 | final ClassLoader classLoader; |
61 | 62 | if (moduleName != null) try { |
62 | 63 | classLoader = ModuleFinder.getClassLoader(moduleName); |
64 | this.classLoader = classLoader; | |
63 | 65 | } catch (Throwable e) { |
64 | 66 | throw new IllegalArgumentException(String.format("Failed to load module \"%s\" for %s \"%s\"", moduleName, getDescription(), name), e); |
65 | 67 | } |
66 | 68 | else { |
67 | 69 | classLoader = getClass().getClassLoader(); |
70 | this.classLoader = null; | |
68 | 71 | } |
69 | 72 | final Class<? extends T> actualClass; |
70 | 73 | try { |
88 | 91 | final Class<?>[] paramTypes = new Class<?>[length]; |
89 | 92 | for (int i = 0; i < length; i++) { |
90 | 93 | final String property = constructorProperties[i]; |
91 | final Class<?> type = getConstructorPropertyType(actualClass, property); | |
94 | final Class<?> type = WrappedAction.execute(() -> getConstructorPropertyType(actualClass, property), classLoader); | |
92 | 95 | if (type == null) { |
93 | 96 | throw new IllegalArgumentException(String.format("No property named \"%s\" for %s \"%s\"", property, getDescription(), getName())); |
94 | 97 | } |
95 | 98 | paramTypes[i] = type; |
96 | 99 | } |
97 | final Constructor<? extends T> constructor; | |
98 | try { | |
99 | constructor = actualClass.getConstructor(paramTypes); | |
100 | } catch (Exception e) { | |
101 | throw new IllegalArgumentException(String.format("Failed to locate constructor in class \"%s\" for %s \"%s\"", className, getDescription(), getName()), e); | |
102 | } | |
100 | final Constructor<? extends T> constructor = WrappedAction.execute(() -> { | |
101 | try { | |
102 | return actualClass.getConstructor(paramTypes); | |
103 | } catch (Exception e) { | |
104 | throw new IllegalArgumentException(String.format("Failed to locate constructor in class \"%s\" for %s \"%s\"", className, getDescription(), getName()), e); | |
105 | } | |
106 | }, classLoader); | |
103 | 107 | final Object[] params = new Object[length]; |
104 | 108 | for (int i = 0; i < length; i++) { |
105 | 109 | final String property = constructorProperties[i]; |
110 | 114 | final Object value = getConfiguration().getValue(actualClass, property, paramTypes[i], valueExpression, true).getObject(); |
111 | 115 | params[i] = value; |
112 | 116 | } |
113 | try { | |
114 | return constructor.newInstance(params); | |
115 | } catch (Exception e) { | |
116 | throw new IllegalArgumentException(String.format("Failed to instantiate class \"%s\" for %s \"%s\"", className, getDescription(), getName()), e); | |
117 | } | |
117 | return WrappedAction.execute(() -> { | |
118 | try { | |
119 | return constructor.newInstance(params); | |
120 | } catch (Exception e) { | |
121 | throw new IllegalArgumentException(String.format("Failed to instantiate class \"%s\" for %s \"%s\"", className, getDescription(), getName()), e); | |
122 | } | |
123 | }, classLoader); | |
118 | 124 | } |
119 | 125 | |
120 | 126 | public void applyPreCreate(final T param) { |
188 | 194 | private void setPropertyValueExpression(final String propertyName, final ValueExpression<String> expression) { |
189 | 195 | final boolean replacement = properties.containsKey(propertyName); |
190 | 196 | final boolean constructorProp = contains(constructorProperties, propertyName); |
191 | final Method setter = getPropertySetter(actualClass, propertyName); | |
197 | final Method setter = WrappedAction.execute(() -> getPropertySetter(actualClass, propertyName), classLoader); | |
192 | 198 | if (setter == null && ! constructorProp) { |
193 | 199 | throw new IllegalArgumentException(String.format("No property \"%s\" setter found for %s \"%s\"", propertyName, getDescription(), getName())); |
194 | 200 | } |
198 | 204 | if (setter == null) { |
199 | 205 | return ObjectProducer.NULL_PRODUCER; |
200 | 206 | } |
201 | final Class<?> propertyType = getPropertyType(actualClass, propertyName); | |
202 | if (propertyType == null) { | |
203 | throw new IllegalArgumentException(String.format("No property \"%s\" type could be determined for %s \"%s\"", propertyName, getDescription(), getName())); | |
204 | } | |
205 | return getConfiguration().getValue(actualClass, propertyName, propertyType, expression, false); | |
206 | } | |
207 | ||
208 | public void applyPreCreate(final ObjectProducer param) { | |
209 | addPostConfigurationActions(); | |
210 | } | |
211 | ||
212 | public void applyPostCreate(final ObjectProducer param) { | |
213 | if (setter != null) { | |
214 | final T instance = getRefs().get(getName()); | |
215 | try { | |
216 | setter.invoke(instance, param.getObject()); | |
217 | } catch (Throwable e) { | |
218 | StandardOutputStreams.printError(e, "Failed to invoke setter %s with value %s%n.", setter.getName(), param.getObject()); | |
219 | } | |
220 | } | |
221 | } | |
222 | ||
223 | public void rollback() { | |
224 | final Class<?> propertyType = getPropertyType(actualClass, propertyName); | |
225 | if (propertyType == null) { | |
226 | // We don't want the rest of the rollback to fail so we'll just log a message | |
227 | StandardOutputStreams.printError("No property \"%s\" type could be determined for %s \"%s\"", propertyName, getDescription(), getName()); | |
228 | return; | |
229 | } | |
230 | final ObjectProducer producer; | |
231 | if (replacement) { | |
232 | properties.put(propertyName, oldValue); | |
233 | producer = getConfiguration().getValue(actualClass, propertyName, propertyType, oldValue, true); | |
234 | } else { | |
235 | properties.remove(propertyName); | |
236 | producer = getDefaultValue(propertyType); | |
237 | } | |
238 | if (setter != null) { | |
239 | // Get the reference instance, the old value and reset to the old value | |
240 | final T instance = getRefs().get(getName()); | |
241 | if (instance != null) { | |
242 | try { | |
243 | setter.invoke(instance, producer.getObject()); | |
244 | } catch (Throwable e) { | |
245 | StandardOutputStreams.printError(e, "Failed to invoke setter %s with value %s%n.", setter.getName(), producer.getObject()); | |
246 | } | |
247 | } else { | |
248 | // If the instance is not available don't keep the property | |
249 | properties.remove(propertyName); | |
250 | } | |
251 | } | |
252 | } | |
253 | }); | |
254 | } | |
255 | ||
256 | public boolean hasProperty(final String propertyName) { | |
257 | return properties.containsKey(propertyName); | |
258 | } | |
259 | ||
260 | public boolean removeProperty(final String propertyName) { | |
261 | if (isRemoved()) { | |
262 | throw new IllegalArgumentException(String.format("Cannot remove property \"%s\" on %s \"%s\" (removed)", propertyName, getDescription(), getName())); | |
263 | } | |
264 | final Method setter = getPropertySetter(actualClass, propertyName); | |
265 | if (setter == null) { | |
266 | throw new IllegalArgumentException(String.format("No property \"%s\" setter found for %s \"%s\"", propertyName, getDescription(), getName())); | |
267 | } | |
268 | final ValueExpression<String> oldValue = properties.remove(propertyName); | |
269 | if (oldValue != null) { | |
270 | getConfiguration().addAction(new ConfigAction<ObjectProducer>() { | |
271 | public ObjectProducer validate() throws IllegalArgumentException { | |
207 | return WrappedAction.execute(() -> { | |
272 | 208 | final Class<?> propertyType = getPropertyType(actualClass, propertyName); |
273 | 209 | if (propertyType == null) { |
274 | 210 | throw new IllegalArgumentException(String.format("No property \"%s\" type could be determined for %s \"%s\"", propertyName, getDescription(), getName())); |
275 | 211 | } |
276 | return getDefaultValue(propertyType); | |
277 | } | |
278 | ||
279 | public void applyPreCreate(final ObjectProducer param) { | |
280 | addPostConfigurationActions(); | |
281 | } | |
282 | ||
283 | public void applyPostCreate(final ObjectProducer param) { | |
284 | final T instance = getRefs().get(getName()); | |
285 | try { | |
286 | setter.invoke(instance, param.getObject()); | |
287 | } catch (Throwable e) { | |
288 | StandardOutputStreams.printError(e, "Failed to invoke setter %s with value %s%n.", setter.getName(), param.getObject()); | |
289 | } | |
290 | } | |
291 | ||
292 | public void rollback() { | |
293 | // We need to once again determine the property type | |
212 | return getConfiguration().getValue(actualClass, propertyName, propertyType, expression, false); | |
213 | }, classLoader); | |
214 | } | |
215 | ||
216 | public void applyPreCreate(final ObjectProducer param) { | |
217 | addPostConfigurationActions(); | |
218 | } | |
219 | ||
220 | public void applyPostCreate(final ObjectProducer param) { | |
221 | if (setter != null) { | |
222 | WrappedAction.execute(() -> { | |
223 | final T instance = getRefs().get(getName()); | |
224 | try { | |
225 | setter.invoke(instance, param.getObject()); | |
226 | } catch (Throwable e) { | |
227 | StandardOutputStreams.printError(e, "Failed to invoke setter %s with value %s%n.", setter.getName(), param.getObject()); | |
228 | } | |
229 | }, classLoader); | |
230 | } | |
231 | } | |
232 | ||
233 | public void rollback() { | |
234 | WrappedAction.execute(() -> { | |
294 | 235 | final Class<?> propertyType = getPropertyType(actualClass, propertyName); |
295 | 236 | if (propertyType == null) { |
296 | 237 | // We don't want the rest of the rollback to fail so we'll just log a message |
297 | 238 | StandardOutputStreams.printError("No property \"%s\" type could be determined for %s \"%s\"", propertyName, getDescription(), getName()); |
298 | 239 | return; |
299 | 240 | } |
300 | // Get the reference instance, the old value and reset to the old value | |
301 | final T instance = getRefs().get(getName()); | |
302 | final ObjectProducer producer = getConfiguration().getValue(actualClass, propertyName, propertyType, oldValue, true); | |
303 | try { | |
304 | setter.invoke(instance, producer.getObject()); | |
305 | } catch (Throwable e) { | |
306 | StandardOutputStreams.printError(e, "Failed to invoke setter %s with value %s%n.", setter.getName(), producer.getObject()); | |
241 | final ObjectProducer producer; | |
242 | if (replacement) { | |
243 | properties.put(propertyName, oldValue); | |
244 | producer = getConfiguration().getValue(actualClass, propertyName, propertyType, oldValue, true); | |
245 | } else { | |
246 | properties.remove(propertyName); | |
247 | producer = getDefaultValue(propertyType); | |
307 | 248 | } |
249 | if (setter != null) { | |
250 | // Get the reference instance, the old value and reset to the old value | |
251 | final T instance = getRefs().get(getName()); | |
252 | if (instance != null) { | |
253 | try { | |
254 | setter.invoke(instance, producer.getObject()); | |
255 | } catch (Throwable e) { | |
256 | StandardOutputStreams.printError(e, "Failed to invoke setter %s with value %s%n.", setter.getName(), producer.getObject()); | |
257 | } | |
258 | } else { | |
259 | // If the instance is not available don't keep the property | |
260 | properties.remove(propertyName); | |
261 | } | |
262 | } | |
263 | }, classLoader); | |
264 | } | |
265 | }); | |
266 | } | |
267 | ||
268 | public boolean hasProperty(final String propertyName) { | |
269 | return properties.containsKey(propertyName); | |
270 | } | |
271 | ||
272 | public boolean removeProperty(final String propertyName) { | |
273 | if (isRemoved()) { | |
274 | throw new IllegalArgumentException(String.format("Cannot remove property \"%s\" on %s \"%s\" (removed)", propertyName, getDescription(), getName())); | |
275 | } | |
276 | final Method setter = WrappedAction.execute(() -> getPropertySetter(actualClass, propertyName), classLoader); | |
277 | if (setter == null) { | |
278 | throw new IllegalArgumentException(String.format("No property \"%s\" setter found for %s \"%s\"", propertyName, getDescription(), getName())); | |
279 | } | |
280 | final ValueExpression<String> oldValue = properties.remove(propertyName); | |
281 | if (oldValue != null) { | |
282 | getConfiguration().addAction(new ConfigAction<ObjectProducer>() { | |
283 | public ObjectProducer validate() throws IllegalArgumentException { | |
284 | return WrappedAction.execute(() -> { | |
285 | final Class<?> propertyType = getPropertyType(actualClass, propertyName); | |
286 | if (propertyType == null) { | |
287 | throw new IllegalArgumentException(String.format("No property \"%s\" type could be determined for %s \"%s\"", propertyName, getDescription(), getName())); | |
288 | } | |
289 | return getDefaultValue(propertyType); | |
290 | }, classLoader); | |
291 | } | |
292 | ||
293 | public void applyPreCreate(final ObjectProducer param) { | |
294 | addPostConfigurationActions(); | |
295 | } | |
296 | ||
297 | public void applyPostCreate(final ObjectProducer param) { | |
298 | WrappedAction.execute(() -> { | |
299 | final T instance = getRefs().get(getName()); | |
300 | try { | |
301 | setter.invoke(instance, param.getObject()); | |
302 | } catch (Throwable e) { | |
303 | StandardOutputStreams.printError(e, "Failed to invoke setter %s with value %s%n.", setter.getName(), param.getObject()); | |
304 | } | |
305 | }, classLoader); | |
306 | } | |
307 | ||
308 | public void rollback() { | |
309 | WrappedAction.execute(() -> { | |
310 | // We need to once again determine the property type | |
311 | final Class<?> propertyType = getPropertyType(actualClass, propertyName); | |
312 | if (propertyType == null) { | |
313 | // We don't want the rest of the rollback to fail so we'll just log a message | |
314 | StandardOutputStreams.printError("No property \"%s\" type could be determined for %s \"%s\"", propertyName, getDescription(), getName()); | |
315 | return; | |
316 | } | |
317 | // Get the reference instance, the old value and reset to the old value | |
318 | final T instance = getRefs().get(getName()); | |
319 | final ObjectProducer producer = getConfiguration().getValue(actualClass, propertyName, propertyType, oldValue, true); | |
320 | try { | |
321 | setter.invoke(instance, producer.getObject()); | |
322 | } catch (Throwable e) { | |
323 | StandardOutputStreams.printError(e, "Failed to invoke setter %s with value %s%n.", setter.getName(), producer.getObject()); | |
324 | } | |
325 | }, classLoader); | |
308 | 326 | } |
309 | 327 | }); |
310 | 328 | return true; |
338 | 356 | } |
339 | 357 | configuration.addAction(new ConfigAction<Method>() { |
340 | 358 | public Method validate() throws IllegalArgumentException { |
341 | try { | |
342 | return actualClass.getMethod(methodName); | |
343 | } catch (NoSuchMethodException e) { | |
344 | throw new IllegalArgumentException(String.format("Method '%s' not found on '%s'", methodName, actualClass.getName())); | |
345 | } | |
359 | return WrappedAction.execute(() -> { | |
360 | try { | |
361 | return actualClass.getMethod(methodName); | |
362 | } catch (NoSuchMethodException e) { | |
363 | throw new IllegalArgumentException(String.format("Method '%s' not found on '%s'", methodName, actualClass.getName())); | |
364 | } | |
365 | }, classLoader); | |
346 | 366 | } |
347 | 367 | |
348 | 368 | public void applyPreCreate(final Method param) { |
382 | 402 | public Map<String, Method> validate() throws IllegalArgumentException { |
383 | 403 | final Map<String, Method> result = new LinkedHashMap<String, Method>(); |
384 | 404 | for (String methodName : names) { |
385 | try { | |
386 | result.put(methodName, actualClass.getMethod(methodName)); | |
387 | } catch (NoSuchMethodException e) { | |
388 | throw new IllegalArgumentException(String.format("Method '%s' not found on '%s'", methodName, actualClass.getName())); | |
389 | } | |
390 | ||
405 | WrappedAction.execute(() -> { | |
406 | try { | |
407 | result.put(methodName, actualClass.getMethod(methodName)); | |
408 | } catch (NoSuchMethodException e) { | |
409 | throw new IllegalArgumentException(String.format("Method '%s' not found on '%s'", methodName, actualClass.getName())); | |
410 | } | |
411 | }, classLoader); | |
391 | 412 | } |
392 | 413 | return result; |
393 | 414 | } |
470 | 491 | } |
471 | 492 | |
472 | 493 | public void applyPostCreate(final Method param) { |
473 | final T instance = getRefs().get(getName()); | |
474 | try { | |
475 | param.invoke(instance); | |
476 | } catch (Throwable e) { | |
477 | StandardOutputStreams.printError(e, "Failed to invoke method %s%n.", param.getName()); | |
478 | } | |
494 | WrappedAction.execute(() -> { | |
495 | final T instance = getRefs().get(getName()); | |
496 | try { | |
497 | param.invoke(instance); | |
498 | } catch (Throwable e) { | |
499 | StandardOutputStreams.printError(e, "Failed to invoke method %s%n.", param.getName()); | |
500 | } | |
501 | }, classLoader); | |
479 | 502 | } |
480 | 503 | |
481 | 504 | public void rollback() { |
492 | 515 | return getConfiguration().removePostConfigurationActions(name); |
493 | 516 | } |
494 | 517 | |
495 | static Class<?> getPropertyType(Class<?> clazz, String propertyName) { | |
518 | private static Class<?> getPropertyType(Class<?> clazz, String propertyName) { | |
496 | 519 | final Method setter = getPropertySetter(clazz, propertyName); |
497 | 520 | return setter != null ? setter.getParameterTypes()[0] : null; |
498 | 521 | } |
499 | 522 | |
500 | static Class<?> getConstructorPropertyType(Class<?> clazz, String propertyName) { | |
523 | private static Class<?> getConstructorPropertyType(Class<?> clazz, String propertyName) { | |
501 | 524 | final Method getter = getPropertyGetter(clazz, propertyName); |
502 | 525 | return getter != null ? getter.getReturnType() : getPropertyType(clazz, propertyName); |
503 | 526 | } |
504 | 527 | |
505 | static Method getPropertySetter(Class<?> clazz, String propertyName) { | |
528 | private static Method getPropertySetter(Class<?> clazz, String propertyName) { | |
506 | 529 | final String upperPropertyName = Character.toUpperCase(propertyName.charAt(0)) + propertyName.substring(1); |
507 | 530 | final String set = "set" + upperPropertyName; |
508 | 531 | for (Method method : clazz.getMethods()) { |
513 | 536 | return null; |
514 | 537 | } |
515 | 538 | |
516 | static Method getPropertyGetter(Class<?> clazz, String propertyName) { | |
539 | private static Method getPropertyGetter(Class<?> clazz, String propertyName) { | |
517 | 540 | final String upperPropertyName = Character.toUpperCase(propertyName.charAt(0)) + propertyName.substring(1); |
518 | 541 | final Pattern pattern = Pattern.compile("(get|has|is)(" + Pattern.quote(upperPropertyName) + ")"); |
519 | 542 | for (Method method : clazz.getMethods()) { |
374 | 374 | } |
375 | 375 | final int index = handlerNames.indexOf(name); |
376 | 376 | handlerNames.remove(index); |
377 | configuration.addAction(new ConfigAction<Void>() { | |
378 | public Void validate() throws IllegalArgumentException { | |
379 | return null; | |
380 | } | |
381 | ||
382 | public void applyPreCreate(final Void param) { | |
383 | addPostConfigurationActions(); | |
384 | } | |
385 | ||
386 | public void applyPostCreate(final Void param) { | |
377 | configuration.addAction(new ConfigAction<Handler>() { | |
378 | public Handler validate() throws IllegalArgumentException { | |
379 | final Map<String, Handler> handlerRefs = configuration.getHandlerRefs(); | |
380 | return handlerRefs.get(name); | |
381 | } | |
382 | ||
383 | public void applyPreCreate(final Handler param) { | |
384 | addPostConfigurationActions(); | |
385 | } | |
386 | ||
387 | public void applyPostCreate(final Handler param) { | |
387 | 388 | final Map<String, Handler> handlerRefs = configuration.getHandlerRefs(); |
388 | 389 | final ExtHandler handler = (ExtHandler) handlerRefs.get(getName()); |
389 | handler.removeHandler(handlerRefs.get(name)); | |
390 | handler.removeHandler(param); | |
390 | 391 | } |
391 | 392 | |
392 | 393 | public void rollback() { |
309 | 309 | } |
310 | 310 | final int index = handlerNames.indexOf(name); |
311 | 311 | handlerNames.remove(index); |
312 | configuration.addAction(new ConfigAction<Void>() { | |
313 | public Void validate() throws IllegalArgumentException { | |
314 | return null; | |
315 | } | |
316 | ||
317 | public void applyPreCreate(final Void param) { | |
318 | } | |
319 | ||
320 | public void applyPostCreate(final Void param) { | |
312 | configuration.addAction(new ConfigAction<Handler>() { | |
313 | public Handler validate() throws IllegalArgumentException { | |
321 | 314 | final Map<String, Handler> handlerRefs = configuration.getHandlerRefs(); |
315 | return handlerRefs.get(name); | |
316 | } | |
317 | ||
318 | public void applyPreCreate(final Handler param) { | |
319 | } | |
320 | ||
321 | public void applyPostCreate(final Handler param) { | |
322 | 322 | final Map<String, Logger> loggerRefs = configuration.getLoggerRefs(); |
323 | final Logger logger = (Logger) loggerRefs.get(getName()); | |
324 | logger.removeHandler(handlerRefs.get(name)); | |
323 | final Logger logger = loggerRefs.get(getName()); | |
324 | logger.removeHandler(param); | |
325 | 325 | } |
326 | 326 | |
327 | 327 | public void rollback() { |
0 | /* | |
1 | * JBoss, Home of Professional Open Source. | |
2 | * | |
3 | * Copyright 2021 Red Hat, Inc., and individual contributors | |
4 | * as indicated by the @author tags. | |
5 | * | |
6 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
7 | * you may not use this file except in compliance with the License. | |
8 | * You may obtain a copy of the License at | |
9 | * | |
10 | * http://www.apache.org/licenses/LICENSE-2.0 | |
11 | * | |
12 | * Unless required by applicable law or agreed to in writing, software | |
13 | * distributed under the License is distributed on an "AS IS" BASIS, | |
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
15 | * See the License for the specific language governing permissions and | |
16 | * limitations under the License. | |
17 | */ | |
18 | ||
19 | package org.jboss.logmanager.config; | |
20 | ||
21 | import java.security.AccessController; | |
22 | import java.security.PrivilegedAction; | |
23 | import java.util.function.Supplier; | |
24 | ||
25 | /** | |
26 | * @author <a href="mailto:jperkins@redhat.com">James R. Perkins</a> | |
27 | */ | |
28 | class WrappedAction { | |
29 | ||
30 | /** | |
31 | * Executes the action with the {@linkplain Thread#getContextClassLoader() TCCL} set to the class loader of the type. | |
32 | * | |
33 | * @param action the action to run | |
34 | * @param cl the class loader to use for the TCCL | |
35 | * @param <R> the return type | |
36 | * | |
37 | * @return the value from the action | |
38 | */ | |
39 | static <R> R execute(final Supplier<R> action, final ClassLoader cl) { | |
40 | if (cl == null) { | |
41 | return action.get(); | |
42 | } | |
43 | final ClassLoader current = getTccl(); | |
44 | try { | |
45 | setTccl(cl); | |
46 | return action.get(); | |
47 | } finally { | |
48 | setTccl(current); | |
49 | } | |
50 | } | |
51 | ||
52 | /** | |
53 | * Executes the action with the {@linkplain Thread#getContextClassLoader() TCCL} set to the class loader of the type. | |
54 | * | |
55 | * @param action the action to run | |
56 | * @param cl the class loader to use for the TCCL | |
57 | */ | |
58 | static void execute(final Runnable action, final ClassLoader cl) { | |
59 | if (cl == null) { | |
60 | action.run(); | |
61 | } else { | |
62 | final ClassLoader current = getTccl(); | |
63 | try { | |
64 | setTccl(cl); | |
65 | action.run(); | |
66 | } finally { | |
67 | setTccl(current); | |
68 | } | |
69 | } | |
70 | } | |
71 | ||
72 | private static ClassLoader getTccl() { | |
73 | if (System.getSecurityManager() == null) { | |
74 | return Thread.currentThread().getContextClassLoader(); | |
75 | } | |
76 | return AccessController.doPrivileged((PrivilegedAction<ClassLoader>) () -> Thread.currentThread().getContextClassLoader()); | |
77 | } | |
78 | ||
79 | private static void setTccl(final ClassLoader cl) { | |
80 | if (System.getSecurityManager() == null) { | |
81 | Thread.currentThread().setContextClassLoader(cl); | |
82 | } else { | |
83 | AccessController.doPrivileged((PrivilegedAction<Object>) () -> { | |
84 | Thread.currentThread().setContextClassLoader(cl); | |
85 | return null; | |
86 | }); | |
87 | } | |
88 | } | |
89 | } |
105 | 105 | |
106 | 106 | private void renderStackTrace(final StackTraceElement[] parentStack, final Throwable child, final String caption, final String prefix) { |
107 | 107 | if (seen.contains(child)) { |
108 | builder.append("\t[CIRCULAR REFERENCE:") | |
108 | builder.append(prefix) | |
109 | .append(caption) | |
110 | .append("[CIRCULAR REFERENCE: ") | |
109 | 111 | .append(child) |
110 | 112 | .append(']'); |
111 | 113 | newLine(); |
21 | 21 | import java.io.File; |
22 | 22 | import java.io.FileNotFoundException; |
23 | 23 | import java.io.IOException; |
24 | import java.io.UncheckedIOException; | |
25 | import java.security.AccessControlContext; | |
26 | import java.security.AccessController; | |
27 | import java.security.PrivilegedAction; | |
24 | 28 | import java.text.SimpleDateFormat; |
25 | 29 | import java.util.Calendar; |
26 | 30 | import java.util.Date; |
35 | 39 | */ |
36 | 40 | public class PeriodicRotatingFileHandler extends FileHandler { |
37 | 41 | |
42 | private final AccessControlContext acc = AccessController.getContext(); | |
38 | 43 | private SimpleDateFormat format; |
39 | 44 | private String nextSuffix; |
40 | 45 | private Period period = Period.NEVER; |
127 | 132 | * @throws IllegalArgumentException if the suffix is not valid |
128 | 133 | */ |
129 | 134 | public void setSuffix(String suffix) throws IllegalArgumentException { |
130 | final SuffixRotator suffixRotator = SuffixRotator.parse(suffix); | |
135 | final SuffixRotator suffixRotator = SuffixRotator.parse(acc, suffix); | |
131 | 136 | final String dateSuffix = suffixRotator.getDatePattern(); |
132 | 137 | final SimpleDateFormat format = new SimpleDateFormat(dateSuffix); |
133 | 138 | format.setTimeZone(timeZone); |
190 | 195 | private void rollOver() { |
191 | 196 | try { |
192 | 197 | final File file = getFile(); |
198 | if (file == null) { | |
199 | // no file is set; a direct output stream or writer was specified | |
200 | return; | |
201 | } | |
193 | 202 | // first, close the original file (some OSes won't let you move/rename a file that is open) |
194 | setFile(null); | |
203 | setFileInternal(null); | |
195 | 204 | // next, rotate it |
196 | suffixRotator.rotate(getErrorManager(), file.toPath(), nextSuffix); | |
205 | suffixRotator.rotate(SecurityActions.getErrorManager(acc, this), file.toPath(), nextSuffix); | |
197 | 206 | // start new file |
198 | setFile(file); | |
207 | setFileInternal(file); | |
199 | 208 | } catch (IOException e) { |
200 | 209 | reportError("Unable to rotate log file", e, ErrorManager.OPEN_FAILURE); |
201 | 210 | } |
291 | 300 | this.timeZone = timeZone; |
292 | 301 | } |
293 | 302 | |
303 | private void setFileInternal(final File file) throws FileNotFoundException { | |
304 | // At this point we should have already checked the security required | |
305 | if (System.getSecurityManager() == null) { | |
306 | super.setFile(file); | |
307 | } else { | |
308 | AccessController.doPrivileged((PrivilegedAction<Void>) () -> { | |
309 | try { | |
310 | super.setFile(file); | |
311 | } catch (FileNotFoundException e) { | |
312 | throw new UncheckedIOException(e); | |
313 | } | |
314 | return null; | |
315 | }, acc); | |
316 | } | |
317 | } | |
318 | ||
294 | 319 | private static <T extends Comparable<? super T>> T min(T a, T b) { |
295 | 320 | return a.compareTo(b) <= 0 ? a : b; |
296 | 321 | } |
22 | 22 | import java.io.FileNotFoundException; |
23 | 23 | import java.io.IOException; |
24 | 24 | import java.io.OutputStream; |
25 | import java.io.UncheckedIOException; | |
26 | import java.security.AccessControlContext; | |
27 | import java.security.AccessController; | |
28 | import java.security.PrivilegedAction; | |
25 | 29 | import java.util.logging.ErrorManager; |
26 | 30 | |
27 | 31 | import org.jboss.logmanager.ExtLogRecord; |
37 | 41 | * @author <a href="mailto:jperkins@redhat.com">James R. Perkins</a> |
38 | 42 | */ |
39 | 43 | public class PeriodicSizeRotatingFileHandler extends PeriodicRotatingFileHandler { |
44 | private final AccessControlContext acc = AccessController.getContext(); | |
40 | 45 | // by default, rotate at 10MB |
41 | 46 | private long rotateSize = 0xa0000L; |
42 | 47 | private int maxBackupIndex = 1; |
147 | 152 | */ |
148 | 153 | @Override |
149 | 154 | public void setFile(final File file) throws FileNotFoundException { |
155 | checkAccess(this); | |
150 | 156 | synchronized (outputLock) { |
151 | 157 | // Check for a rotate |
152 | 158 | if (rotateOnBoot && maxBackupIndex > 0 && file != null && file.exists() && file.length() > 0L) { |
154 | 160 | final SuffixRotator suffixRotator = getSuffixRotator(); |
155 | 161 | if (suffixRotator != SuffixRotator.EMPTY && suffix != null) { |
156 | 162 | // Make sure any previous files are closed before we attempt to rotate |
157 | setFileInternal(null); | |
163 | setFileInternal(null, false); | |
164 | // Previous actions have already performed | |
158 | 165 | suffixRotator.rotate(getErrorManager(), file.toPath(), suffix, maxBackupIndex); |
159 | 166 | } |
160 | 167 | } |
161 | setFileInternal(file); | |
168 | setFileInternal(file, false); | |
162 | 169 | } |
163 | 170 | } |
164 | 171 | |
223 | 230 | return; |
224 | 231 | } |
225 | 232 | // close the old file. |
226 | setFileInternal(null); | |
227 | getSuffixRotator().rotate(getErrorManager(), file.toPath(), getNextSuffix(), maxBackupIndex); | |
233 | setFileInternal(null, true); | |
234 | getSuffixRotator().rotate(SecurityActions.getErrorManager(acc, this), file.toPath(), getNextSuffix(), maxBackupIndex); | |
228 | 235 | // start with new file. |
229 | setFileInternal(file); | |
236 | setFileInternal(file, true); | |
230 | 237 | } catch (IOException e) { |
231 | 238 | reportError("Unable to rotate log file", e, ErrorManager.OPEN_FAILURE); |
232 | 239 | } |
233 | 240 | } |
234 | 241 | } |
235 | 242 | |
236 | private void setFileInternal(final File file) throws FileNotFoundException { | |
237 | super.setFile(file); | |
238 | if (outputStream != null) | |
239 | outputStream.currentSize = file == null ? 0L : file.length(); | |
243 | private void setFileInternal(final File file, final boolean doPrivileged) throws FileNotFoundException { | |
244 | if (System.getSecurityManager() == null || !doPrivileged) { | |
245 | super.setFile(file); | |
246 | if (outputStream != null) { | |
247 | outputStream.currentSize = file == null ? 0L : file.length(); | |
248 | } | |
249 | } else { | |
250 | AccessController.doPrivileged((PrivilegedAction<Void>) () -> { | |
251 | try { | |
252 | super.setFile(file); | |
253 | if (outputStream != null) { | |
254 | outputStream.currentSize = file == null ? 0L : file.length(); | |
255 | } | |
256 | } catch (FileNotFoundException e) { | |
257 | throw new UncheckedIOException(e); | |
258 | } | |
259 | return null; | |
260 | }, acc); | |
261 | } | |
240 | 262 | } |
241 | 263 | } |
0 | /* | |
1 | * JBoss, Home of Professional Open Source. | |
2 | * | |
3 | * Copyright 2020 Red Hat, Inc., and individual contributors | |
4 | * as indicated by the @author tags. | |
5 | * | |
6 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
7 | * you may not use this file except in compliance with the License. | |
8 | * You may obtain a copy of the License at | |
9 | * | |
10 | * http://www.apache.org/licenses/LICENSE-2.0 | |
11 | * | |
12 | * Unless required by applicable law or agreed to in writing, software | |
13 | * distributed under the License is distributed on an "AS IS" BASIS, | |
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
15 | * See the License for the specific language governing permissions and | |
16 | * limitations under the License. | |
17 | */ | |
18 | ||
19 | package org.jboss.logmanager.handlers; | |
20 | ||
21 | import java.security.AccessControlContext; | |
22 | import java.security.AccessController; | |
23 | import java.security.PrivilegedAction; | |
24 | import java.util.function.Supplier; | |
25 | import java.util.logging.ErrorManager; | |
26 | import java.util.logging.Handler; | |
27 | ||
28 | /** | |
29 | * @author <a href="mailto:jperkins@redhat.com">James R. Perkins</a> | |
30 | */ | |
31 | class SecurityActions { | |
32 | ||
33 | static ErrorManager getErrorManager(final AccessControlContext acc, final Handler handler) { | |
34 | Supplier<ErrorManager> supplier = () -> { | |
35 | if (System.getSecurityManager() == null) { | |
36 | return handler.getErrorManager(); | |
37 | } | |
38 | return AccessController.doPrivileged((PrivilegedAction<ErrorManager>) handler::getErrorManager, acc); | |
39 | }; | |
40 | return new LazyErrorManager(supplier); | |
41 | } | |
42 | ||
43 | private static class LazyErrorManager extends ErrorManager { | |
44 | private final Supplier<ErrorManager> supplier; | |
45 | private volatile ErrorManager delegate; | |
46 | ||
47 | private LazyErrorManager(final Supplier<ErrorManager> supplier) { | |
48 | this.supplier = supplier; | |
49 | } | |
50 | ||
51 | @Override | |
52 | public synchronized void error(final String msg, final Exception ex, final int code) { | |
53 | getDelegate().error(msg, ex, code); | |
54 | } | |
55 | ||
56 | private ErrorManager getDelegate() { | |
57 | if (delegate == null) { | |
58 | synchronized (this) { | |
59 | if (delegate == null) { | |
60 | delegate = supplier.get(); | |
61 | } | |
62 | } | |
63 | } | |
64 | return delegate; | |
65 | } | |
66 | } | |
67 | } |
24 | 24 | import java.io.FileNotFoundException; |
25 | 25 | import org.jboss.logmanager.ExtLogRecord; |
26 | 26 | |
27 | import java.io.UncheckedIOException; | |
28 | import java.security.AccessControlContext; | |
29 | import java.security.AccessController; | |
30 | import java.security.PrivilegedAction; | |
27 | 31 | import java.util.logging.ErrorManager; |
28 | 32 | |
29 | 33 | public class SizeRotatingFileHandler extends FileHandler { |
34 | private final AccessControlContext acc = AccessController.getContext(); | |
30 | 35 | // by default, rotate at 10MB |
31 | 36 | private long rotateSize = 0xa0000L; |
32 | 37 | private int maxBackupIndex = 1; |
135 | 140 | * @throws RuntimeException if there is an attempt to rotate file and the rotation fails |
136 | 141 | */ |
137 | 142 | public void setFile(final File file) throws FileNotFoundException { |
143 | checkAccess(this); | |
138 | 144 | synchronized (outputLock) { |
139 | 145 | // Check for a rotate |
140 | 146 | if (rotateOnBoot && maxBackupIndex > 0 && file != null && file.exists() && file.length() > 0L) { |
141 | 147 | // Make sure any previous files are closed before we attempt to rotate |
142 | setFileInternal(null); | |
148 | setFileInternal(null, false); | |
143 | 149 | suffixRotator.rotate(getErrorManager(), file.toPath(), maxBackupIndex); |
144 | 150 | } |
145 | setFileInternal(file); | |
151 | setFileInternal(file, false); | |
146 | 152 | } |
147 | 153 | } |
148 | 154 | |
227 | 233 | public void setSuffix(final String suffix) { |
228 | 234 | checkAccess(this); |
229 | 235 | synchronized (outputLock) { |
230 | this.suffixRotator = SuffixRotator.parse(suffix); | |
236 | this.suffixRotator = SuffixRotator.parse(acc, suffix); | |
231 | 237 | } |
232 | 238 | } |
233 | 239 | |
243 | 249 | return; |
244 | 250 | } |
245 | 251 | // close the old file. |
246 | setFileInternal(null); | |
247 | suffixRotator.rotate(getErrorManager(), file.toPath(), maxBackupIndex); | |
252 | setFileInternal(null, true); | |
253 | suffixRotator.rotate(SecurityActions.getErrorManager(acc, this), file.toPath(), maxBackupIndex); | |
248 | 254 | // start with new file. |
249 | setFileInternal(file); | |
255 | setFileInternal(file, true); | |
250 | 256 | } catch (IOException e) { |
251 | 257 | reportError("Unable to rotate log file", e, ErrorManager.OPEN_FAILURE); |
252 | 258 | } |
253 | 259 | } |
254 | 260 | } |
255 | 261 | |
256 | private void setFileInternal(final File file) throws FileNotFoundException { | |
257 | super.setFile(file); | |
258 | if (outputStream != null) | |
259 | outputStream.currentSize = file == null ? 0L : file.length(); | |
262 | private void setFileInternal(final File file, final boolean doPrivileged) throws FileNotFoundException { | |
263 | if (System.getSecurityManager() == null || !doPrivileged) { | |
264 | super.setFile(file); | |
265 | if (outputStream != null) { | |
266 | outputStream.currentSize = file == null ? 0L : file.length(); | |
267 | } | |
268 | } else { | |
269 | AccessController.doPrivileged((PrivilegedAction<Void>) () -> { | |
270 | try { | |
271 | super.setFile(file); | |
272 | if (outputStream != null) { | |
273 | outputStream.currentSize = file == null ? 0L : file.length(); | |
274 | } | |
275 | } catch (FileNotFoundException e) { | |
276 | throw new UncheckedIOException(e); | |
277 | } | |
278 | return null; | |
279 | }, acc); | |
280 | } | |
260 | 281 | } |
261 | 282 | } |
20 | 20 | |
21 | 21 | import java.io.IOException; |
22 | 22 | import java.io.InputStream; |
23 | import java.io.OutputStream; | |
24 | import java.io.UncheckedIOException; | |
23 | 25 | import java.nio.charset.StandardCharsets; |
24 | 26 | import java.nio.file.Files; |
25 | 27 | import java.nio.file.Path; |
26 | 28 | import java.nio.file.Paths; |
27 | 29 | import java.nio.file.StandardCopyOption; |
30 | import java.security.AccessControlContext; | |
31 | import java.security.AccessController; | |
32 | import java.security.PrivilegedAction; | |
28 | 33 | import java.text.SimpleDateFormat; |
29 | 34 | import java.util.Date; |
30 | 35 | import java.util.Locale; |
52 | 57 | /** |
53 | 58 | * An empty rotation suffix. |
54 | 59 | */ |
55 | static final SuffixRotator EMPTY = new SuffixRotator("", "", "", CompressionType.NONE); | |
56 | ||
60 | static final SuffixRotator EMPTY = new SuffixRotator(AccessController.getContext(), "", "", "", CompressionType.NONE); | |
61 | ||
62 | private final AccessControlContext acc; | |
57 | 63 | private final String originalSuffix; |
58 | 64 | private final String datePattern; |
59 | 65 | private final SimpleDateFormat formatter; |
60 | 66 | private final String compressionSuffix; |
61 | 67 | private final CompressionType compressionType; |
62 | 68 | |
63 | private SuffixRotator(final String originalSuffix, final String datePattern, final String compressionSuffix, final CompressionType compressionType) { | |
69 | private SuffixRotator(final AccessControlContext acc, final String originalSuffix, final String datePattern, | |
70 | final String compressionSuffix, final CompressionType compressionType) { | |
71 | this.acc = acc; | |
64 | 72 | this.originalSuffix = originalSuffix; |
65 | 73 | this.datePattern = datePattern; |
66 | 74 | this.compressionSuffix = compressionSuffix; |
79 | 87 | * |
80 | 88 | * @return the file rotator used to determine the suffix parts and rotate the file. |
81 | 89 | */ |
82 | static SuffixRotator parse(final String suffix) { | |
90 | static SuffixRotator parse(final AccessControlContext acc, final String suffix) { | |
83 | 91 | if (suffix == null || suffix.isEmpty()) { |
84 | 92 | return EMPTY; |
85 | 93 | } |
102 | 110 | } |
103 | 111 | } |
104 | 112 | if (compressionSuffix.isEmpty() && datePattern.isEmpty()) { |
105 | return new SuffixRotator(suffix, suffix, "", CompressionType.NONE); | |
106 | } | |
107 | return new SuffixRotator(suffix, datePattern, compressionSuffix, compressionType); | |
113 | return new SuffixRotator(acc, suffix, suffix, "", CompressionType.NONE); | |
114 | } | |
115 | return new SuffixRotator(acc, suffix, datePattern, compressionSuffix, compressionType); | |
108 | 116 | } |
109 | 117 | |
110 | 118 | /** |
155 | 163 | try { |
156 | 164 | archiveGzip(source, target); |
157 | 165 | // Delete the file after it's archived to behave like a file move or rename |
158 | Files.delete(source); | |
166 | deleteFile(source); | |
159 | 167 | } catch (Exception e) { |
160 | 168 | errorManager.error(String.format("Failed to compress %s to %s. Compressed file may be left on the " + |
161 | 169 | "filesystem corrupted.", source, target), e, ErrorManager.WRITE_FAILURE); |
164 | 172 | try { |
165 | 173 | archiveZip(source, target); |
166 | 174 | // Delete the file after it's archived to behave like a file move or rename |
167 | Files.delete(source); | |
175 | deleteFile(source); | |
168 | 176 | } catch (Exception e) { |
169 | 177 | errorManager.error(String.format("Failed to compress %s to %s. Compressed file may be left on the " + |
170 | 178 | "filesystem corrupted.", source, target), e, ErrorManager.WRITE_FAILURE); |
218 | 226 | final String fileWithSuffix = source.toAbsolutePath() + rotationSuffix; |
219 | 227 | final Path lastFile = Paths.get(fileWithSuffix + "." + maxBackupIndex + compressionSuffix); |
220 | 228 | try { |
221 | Files.deleteIfExists(lastFile); | |
229 | deleteFile(lastFile); | |
222 | 230 | } catch (Exception e) { |
223 | 231 | errorManager.error(String.format("Failed to delete file %s", lastFile), e, ErrorManager.GENERIC_FAILURE); |
224 | 232 | } |
225 | 233 | for (int i = maxBackupIndex - 1; i >= 1; i--) { |
226 | 234 | final Path src = Paths.get(fileWithSuffix + "." + i + compressionSuffix); |
227 | if (Files.exists(src)) { | |
235 | if (fileExists(src)) { | |
228 | 236 | final Path target = Paths.get(fileWithSuffix + "." + (i + 1) + compressionSuffix); |
229 | 237 | move(errorManager, src, target); |
230 | 238 | } |
241 | 249 | } |
242 | 250 | |
243 | 251 | private void move(final ErrorManager errorManager, final Path src, final Path target) { |
244 | try { | |
245 | Files.move(src, target, StandardCopyOption.REPLACE_EXISTING); | |
246 | } catch (Exception e) { | |
247 | // Report the error, but allow the rotation to continue | |
248 | errorManager.error(String.format("Failed to move file %s to %s.", src, target), e, ErrorManager.GENERIC_FAILURE); | |
249 | } | |
250 | } | |
251 | ||
252 | ||
253 | private static void archiveGzip(final Path source, final Path target) throws IOException { | |
252 | if (System.getSecurityManager() == null) { | |
253 | try { | |
254 | Files.move(src, target, StandardCopyOption.REPLACE_EXISTING); | |
255 | } catch (Exception e) { | |
256 | // Report the error, but allow the rotation to continue | |
257 | errorManager.error(String.format("Failed to move file %s to %s.", src, target), e, ErrorManager.GENERIC_FAILURE); | |
258 | } | |
259 | } else { | |
260 | AccessController.doPrivileged(new MoveFileAction(errorManager, src, target), acc); | |
261 | } | |
262 | } | |
263 | ||
264 | ||
265 | private void archiveGzip(final Path source, final Path target) throws IOException { | |
254 | 266 | final byte[] buff = new byte[512]; |
255 | try (final GZIPOutputStream out = new GZIPOutputStream(Files.newOutputStream(target), true)) { | |
256 | try (final InputStream in = Files.newInputStream(source)) { | |
267 | try (final GZIPOutputStream out = new GZIPOutputStream(newOutputStream(target), true)) { | |
268 | try (final InputStream in = newInputStream(source)) { | |
257 | 269 | int len; |
258 | 270 | while ((len = in.read(buff)) != -1) { |
259 | 271 | out.write(buff, 0, len); |
263 | 275 | } |
264 | 276 | } |
265 | 277 | |
266 | private static void archiveZip(final Path source, final Path target) throws IOException { | |
278 | private void archiveZip(final Path source, final Path target) throws IOException { | |
267 | 279 | final byte[] buff = new byte[512]; |
268 | try (final ZipOutputStream out = new ZipOutputStream(Files.newOutputStream(target), StandardCharsets.UTF_8)) { | |
280 | try (final ZipOutputStream out = new ZipOutputStream(newOutputStream(target), StandardCharsets.UTF_8)) { | |
269 | 281 | final ZipEntry entry = new ZipEntry(source.getFileName().toString()); |
270 | 282 | out.putNextEntry(entry); |
271 | try (final InputStream in = Files.newInputStream(source)) { | |
283 | try (final InputStream in = newInputStream(source)) { | |
272 | 284 | int len; |
273 | 285 | while ((len = in.read(buff)) != -1) { |
274 | 286 | out.write(buff, 0, len); |
277 | 289 | out.closeEntry(); |
278 | 290 | } |
279 | 291 | } |
292 | ||
293 | @SuppressWarnings("UnusedReturnValue") | |
294 | private boolean deleteFile(final Path path) throws IOException { | |
295 | if (System.getSecurityManager() == null) { | |
296 | return Files.deleteIfExists(path); | |
297 | } | |
298 | return AccessController.doPrivileged(new DeleteFileAction(path), acc); | |
299 | } | |
300 | ||
301 | private boolean fileExists(final Path file) { | |
302 | if (System.getSecurityManager() == null) { | |
303 | return Files.exists(file); | |
304 | } | |
305 | return AccessController.doPrivileged(new FileExistsAction(file), acc); | |
306 | } | |
307 | ||
308 | private InputStream newInputStream(final Path file) throws IOException { | |
309 | if (System.getSecurityManager() == null) { | |
310 | return Files.newInputStream(file); | |
311 | } | |
312 | return AccessController.doPrivileged(new InputStreamAction(file), acc); | |
313 | } | |
314 | ||
315 | private OutputStream newOutputStream(final Path file) throws IOException { | |
316 | if (System.getSecurityManager() == null) { | |
317 | return Files.newOutputStream(file); | |
318 | } | |
319 | return AccessController.doPrivileged(new OutputStreamAction(file), acc); | |
320 | } | |
321 | ||
322 | private static class DeleteFileAction implements PrivilegedAction<Boolean> { | |
323 | private final Path file; | |
324 | ||
325 | private DeleteFileAction(final Path file) { | |
326 | this.file = file; | |
327 | } | |
328 | ||
329 | @Override | |
330 | public Boolean run() { | |
331 | try { | |
332 | return Files.deleteIfExists(file); | |
333 | } catch (IOException e) { | |
334 | throw new UncheckedIOException(e); | |
335 | } | |
336 | } | |
337 | } | |
338 | ||
339 | private static class MoveFileAction implements PrivilegedAction<Path> { | |
340 | private final ErrorManager errorManager; | |
341 | private final Path source; | |
342 | private final Path target; | |
343 | ||
344 | private MoveFileAction(final ErrorManager errorManager, final Path source, final Path target) { | |
345 | this.errorManager = errorManager; | |
346 | this.source = source; | |
347 | this.target = target; | |
348 | } | |
349 | ||
350 | @Override | |
351 | public Path run() { | |
352 | try { | |
353 | return Files.move(source, target, StandardCopyOption.REPLACE_EXISTING); | |
354 | } catch (Exception e) { | |
355 | // Report the error, but allow the rotation to continue | |
356 | errorManager.error(String.format("Failed to move file %s to %s.", source, target), e, ErrorManager.GENERIC_FAILURE); | |
357 | } | |
358 | return null; | |
359 | } | |
360 | } | |
361 | ||
362 | private static class FileExistsAction implements PrivilegedAction<Boolean> { | |
363 | private final Path file; | |
364 | ||
365 | private FileExistsAction(final Path file) { | |
366 | this.file = file; | |
367 | } | |
368 | ||
369 | @Override | |
370 | public Boolean run() { | |
371 | return Files.exists(file); | |
372 | } | |
373 | } | |
374 | ||
375 | private static class InputStreamAction implements PrivilegedAction<InputStream> { | |
376 | private final Path file; | |
377 | ||
378 | private InputStreamAction(final Path file) { | |
379 | this.file = file; | |
380 | } | |
381 | ||
382 | @Override | |
383 | public InputStream run() { | |
384 | try { | |
385 | return Files.newInputStream(file); | |
386 | } catch (IOException e) { | |
387 | throw new UncheckedIOException(e); | |
388 | } | |
389 | } | |
390 | } | |
391 | ||
392 | private static class OutputStreamAction implements PrivilegedAction<OutputStream> { | |
393 | private final Path file; | |
394 | ||
395 | private OutputStreamAction(final Path file) { | |
396 | this.file = file; | |
397 | } | |
398 | ||
399 | @Override | |
400 | public OutputStream run() { | |
401 | try { | |
402 | return Files.newOutputStream(file); | |
403 | } catch (IOException e) { | |
404 | throw new UncheckedIOException(e); | |
405 | } | |
406 | } | |
407 | } | |
280 | 408 | } |
83 | 83 | |
84 | 84 | private void renderStackTrace(final StackTraceElement[] parentStack, final Throwable child, final String caption, final String prefix) { |
85 | 85 | if (seen.contains(child)) { |
86 | builder.append("\t[CIRCULAR REFERENCE:") | |
86 | builder.append(prefix) | |
87 | .append(caption) | |
88 | .append("[CIRCULAR REFERENCE: ") | |
87 | 89 | .append(child) |
88 | 90 | .append(']'); |
89 | 91 | newLine(); |
244 | 244 | formatter = new PatternFormatter("%e"); |
245 | 245 | cause.addSuppressed(suppressedLevel1); |
246 | 246 | formatted = formatter.format(record); |
247 | Assert.assertTrue(formatted.contains("CIRCULAR REFERENCE:java.lang.IllegalStateException: suppressedLevel1")); | |
247 | Assert.assertTrue(formatted.contains("CIRCULAR REFERENCE: java.lang.IllegalStateException: suppressedLevel1")); | |
248 | 248 | } |
249 | 249 | |
250 | 250 | @Test |
Binary diff not shown
Binary diff not shown
Binary diff not shown
Binary diff not shown