Codebase list jboss-logmanager / 5887c68
New upstream version 2.1.18 Markus Koschany 2 years ago
17 changed file(s) with 590 addition(s) and 207 deletion(s). Raw diff Collapse all Expand all
2727 <groupId>org.jboss.logmanager</groupId>
2828 <artifactId>jboss-logmanager</artifactId>
2929 <packaging>jar</packaging>
30 <version>2.1.15.Final</version>
30 <version>2.1.18.Final</version>
3131
3232 <parent>
3333 <groupId>org.jboss</groupId>
5757 <org.jboss.test.port>4560</org.jboss.test.port>
5858 <org.jboss.test.alt.port>14560</org.jboss.test.alt.port>
5959
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>
6262
6363 <jdk.min.version>9</jdk.min.version>
6464 </properties>
219219 <artifactId>maven-javadoc-plugin</artifactId>
220220 <configuration>
221221 <doclint>none</doclint>
222 <javadocExecutable>${java.home}${file.separator}bin</javadocExecutable>
222223 </configuration>
223224 </plugin>
224225 <plugin>
4343 */
4444 abstract class AbstractPropertyConfiguration<T, C extends AbstractPropertyConfiguration<T, C>> extends AbstractBasicConfiguration<T, C> implements ObjectConfigurable<T>, PropertyConfigurable {
4545 private final Class<? extends T> actualClass;
46 private final ClassLoader classLoader;
4647 private final String moduleName;
4748 private final String className;
4849 private final String[] constructorProperties;
6061 final ClassLoader classLoader;
6162 if (moduleName != null) try {
6263 classLoader = ModuleFinder.getClassLoader(moduleName);
64 this.classLoader = classLoader;
6365 } catch (Throwable e) {
6466 throw new IllegalArgumentException(String.format("Failed to load module \"%s\" for %s \"%s\"", moduleName, getDescription(), name), e);
6567 }
6668 else {
6769 classLoader = getClass().getClassLoader();
70 this.classLoader = null;
6871 }
6972 final Class<? extends T> actualClass;
7073 try {
8891 final Class<?>[] paramTypes = new Class<?>[length];
8992 for (int i = 0; i < length; i++) {
9093 final String property = constructorProperties[i];
91 final Class<?> type = getConstructorPropertyType(actualClass, property);
94 final Class<?> type = WrappedAction.execute(() -> getConstructorPropertyType(actualClass, property), classLoader);
9295 if (type == null) {
9396 throw new IllegalArgumentException(String.format("No property named \"%s\" for %s \"%s\"", property, getDescription(), getName()));
9497 }
9598 paramTypes[i] = type;
9699 }
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);
103107 final Object[] params = new Object[length];
104108 for (int i = 0; i < length; i++) {
105109 final String property = constructorProperties[i];
110114 final Object value = getConfiguration().getValue(actualClass, property, paramTypes[i], valueExpression, true).getObject();
111115 params[i] = value;
112116 }
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);
118124 }
119125
120126 public void applyPreCreate(final T param) {
188194 private void setPropertyValueExpression(final String propertyName, final ValueExpression<String> expression) {
189195 final boolean replacement = properties.containsKey(propertyName);
190196 final boolean constructorProp = contains(constructorProperties, propertyName);
191 final Method setter = getPropertySetter(actualClass, propertyName);
197 final Method setter = WrappedAction.execute(() -> getPropertySetter(actualClass, propertyName), classLoader);
192198 if (setter == null && ! constructorProp) {
193199 throw new IllegalArgumentException(String.format("No property \"%s\" setter found for %s \"%s\"", propertyName, getDescription(), getName()));
194200 }
198204 if (setter == null) {
199205 return ObjectProducer.NULL_PRODUCER;
200206 }
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(() -> {
272208 final Class<?> propertyType = getPropertyType(actualClass, propertyName);
273209 if (propertyType == null) {
274210 throw new IllegalArgumentException(String.format("No property \"%s\" type could be determined for %s \"%s\"", propertyName, getDescription(), getName()));
275211 }
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(() -> {
294235 final Class<?> propertyType = getPropertyType(actualClass, propertyName);
295236 if (propertyType == null) {
296237 // We don't want the rest of the rollback to fail so we'll just log a message
297238 StandardOutputStreams.printError("No property \"%s\" type could be determined for %s \"%s\"", propertyName, getDescription(), getName());
298239 return;
299240 }
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);
307248 }
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);
308326 }
309327 });
310328 return true;
338356 }
339357 configuration.addAction(new ConfigAction<Method>() {
340358 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);
346366 }
347367
348368 public void applyPreCreate(final Method param) {
382402 public Map<String, Method> validate() throws IllegalArgumentException {
383403 final Map<String, Method> result = new LinkedHashMap<String, Method>();
384404 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);
391412 }
392413 return result;
393414 }
470491 }
471492
472493 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);
479502 }
480503
481504 public void rollback() {
492515 return getConfiguration().removePostConfigurationActions(name);
493516 }
494517
495 static Class<?> getPropertyType(Class<?> clazz, String propertyName) {
518 private static Class<?> getPropertyType(Class<?> clazz, String propertyName) {
496519 final Method setter = getPropertySetter(clazz, propertyName);
497520 return setter != null ? setter.getParameterTypes()[0] : null;
498521 }
499522
500 static Class<?> getConstructorPropertyType(Class<?> clazz, String propertyName) {
523 private static Class<?> getConstructorPropertyType(Class<?> clazz, String propertyName) {
501524 final Method getter = getPropertyGetter(clazz, propertyName);
502525 return getter != null ? getter.getReturnType() : getPropertyType(clazz, propertyName);
503526 }
504527
505 static Method getPropertySetter(Class<?> clazz, String propertyName) {
528 private static Method getPropertySetter(Class<?> clazz, String propertyName) {
506529 final String upperPropertyName = Character.toUpperCase(propertyName.charAt(0)) + propertyName.substring(1);
507530 final String set = "set" + upperPropertyName;
508531 for (Method method : clazz.getMethods()) {
513536 return null;
514537 }
515538
516 static Method getPropertyGetter(Class<?> clazz, String propertyName) {
539 private static Method getPropertyGetter(Class<?> clazz, String propertyName) {
517540 final String upperPropertyName = Character.toUpperCase(propertyName.charAt(0)) + propertyName.substring(1);
518541 final Pattern pattern = Pattern.compile("(get|has|is)(" + Pattern.quote(upperPropertyName) + ")");
519542 for (Method method : clazz.getMethods()) {
374374 }
375375 final int index = handlerNames.indexOf(name);
376376 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) {
387388 final Map<String, Handler> handlerRefs = configuration.getHandlerRefs();
388389 final ExtHandler handler = (ExtHandler) handlerRefs.get(getName());
389 handler.removeHandler(handlerRefs.get(name));
390 handler.removeHandler(param);
390391 }
391392
392393 public void rollback() {
309309 }
310310 final int index = handlerNames.indexOf(name);
311311 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 {
321314 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) {
322322 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);
325325 }
326326
327327 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 }
105105
106106 private void renderStackTrace(final StackTraceElement[] parentStack, final Throwable child, final String caption, final String prefix) {
107107 if (seen.contains(child)) {
108 builder.append("\t[CIRCULAR REFERENCE:")
108 builder.append(prefix)
109 .append(caption)
110 .append("[CIRCULAR REFERENCE: ")
109111 .append(child)
110112 .append(']');
111113 newLine();
2121 import java.io.File;
2222 import java.io.FileNotFoundException;
2323 import java.io.IOException;
24 import java.io.UncheckedIOException;
25 import java.security.AccessControlContext;
26 import java.security.AccessController;
27 import java.security.PrivilegedAction;
2428 import java.text.SimpleDateFormat;
2529 import java.util.Calendar;
2630 import java.util.Date;
3539 */
3640 public class PeriodicRotatingFileHandler extends FileHandler {
3741
42 private final AccessControlContext acc = AccessController.getContext();
3843 private SimpleDateFormat format;
3944 private String nextSuffix;
4045 private Period period = Period.NEVER;
127132 * @throws IllegalArgumentException if the suffix is not valid
128133 */
129134 public void setSuffix(String suffix) throws IllegalArgumentException {
130 final SuffixRotator suffixRotator = SuffixRotator.parse(suffix);
135 final SuffixRotator suffixRotator = SuffixRotator.parse(acc, suffix);
131136 final String dateSuffix = suffixRotator.getDatePattern();
132137 final SimpleDateFormat format = new SimpleDateFormat(dateSuffix);
133138 format.setTimeZone(timeZone);
190195 private void rollOver() {
191196 try {
192197 final File file = getFile();
198 if (file == null) {
199 // no file is set; a direct output stream or writer was specified
200 return;
201 }
193202 // first, close the original file (some OSes won't let you move/rename a file that is open)
194 setFile(null);
203 setFileInternal(null);
195204 // next, rotate it
196 suffixRotator.rotate(getErrorManager(), file.toPath(), nextSuffix);
205 suffixRotator.rotate(SecurityActions.getErrorManager(acc, this), file.toPath(), nextSuffix);
197206 // start new file
198 setFile(file);
207 setFileInternal(file);
199208 } catch (IOException e) {
200209 reportError("Unable to rotate log file", e, ErrorManager.OPEN_FAILURE);
201210 }
291300 this.timeZone = timeZone;
292301 }
293302
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
294319 private static <T extends Comparable<? super T>> T min(T a, T b) {
295320 return a.compareTo(b) <= 0 ? a : b;
296321 }
2222 import java.io.FileNotFoundException;
2323 import java.io.IOException;
2424 import java.io.OutputStream;
25 import java.io.UncheckedIOException;
26 import java.security.AccessControlContext;
27 import java.security.AccessController;
28 import java.security.PrivilegedAction;
2529 import java.util.logging.ErrorManager;
2630
2731 import org.jboss.logmanager.ExtLogRecord;
3741 * @author <a href="mailto:jperkins@redhat.com">James R. Perkins</a>
3842 */
3943 public class PeriodicSizeRotatingFileHandler extends PeriodicRotatingFileHandler {
44 private final AccessControlContext acc = AccessController.getContext();
4045 // by default, rotate at 10MB
4146 private long rotateSize = 0xa0000L;
4247 private int maxBackupIndex = 1;
147152 */
148153 @Override
149154 public void setFile(final File file) throws FileNotFoundException {
155 checkAccess(this);
150156 synchronized (outputLock) {
151157 // Check for a rotate
152158 if (rotateOnBoot && maxBackupIndex > 0 && file != null && file.exists() && file.length() > 0L) {
154160 final SuffixRotator suffixRotator = getSuffixRotator();
155161 if (suffixRotator != SuffixRotator.EMPTY && suffix != null) {
156162 // 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
158165 suffixRotator.rotate(getErrorManager(), file.toPath(), suffix, maxBackupIndex);
159166 }
160167 }
161 setFileInternal(file);
168 setFileInternal(file, false);
162169 }
163170 }
164171
223230 return;
224231 }
225232 // 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);
228235 // start with new file.
229 setFileInternal(file);
236 setFileInternal(file, true);
230237 } catch (IOException e) {
231238 reportError("Unable to rotate log file", e, ErrorManager.OPEN_FAILURE);
232239 }
233240 }
234241 }
235242
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 }
240262 }
241263 }
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 }
2424 import java.io.FileNotFoundException;
2525 import org.jboss.logmanager.ExtLogRecord;
2626
27 import java.io.UncheckedIOException;
28 import java.security.AccessControlContext;
29 import java.security.AccessController;
30 import java.security.PrivilegedAction;
2731 import java.util.logging.ErrorManager;
2832
2933 public class SizeRotatingFileHandler extends FileHandler {
34 private final AccessControlContext acc = AccessController.getContext();
3035 // by default, rotate at 10MB
3136 private long rotateSize = 0xa0000L;
3237 private int maxBackupIndex = 1;
135140 * @throws RuntimeException if there is an attempt to rotate file and the rotation fails
136141 */
137142 public void setFile(final File file) throws FileNotFoundException {
143 checkAccess(this);
138144 synchronized (outputLock) {
139145 // Check for a rotate
140146 if (rotateOnBoot && maxBackupIndex > 0 && file != null && file.exists() && file.length() > 0L) {
141147 // Make sure any previous files are closed before we attempt to rotate
142 setFileInternal(null);
148 setFileInternal(null, false);
143149 suffixRotator.rotate(getErrorManager(), file.toPath(), maxBackupIndex);
144150 }
145 setFileInternal(file);
151 setFileInternal(file, false);
146152 }
147153 }
148154
227233 public void setSuffix(final String suffix) {
228234 checkAccess(this);
229235 synchronized (outputLock) {
230 this.suffixRotator = SuffixRotator.parse(suffix);
236 this.suffixRotator = SuffixRotator.parse(acc, suffix);
231237 }
232238 }
233239
243249 return;
244250 }
245251 // 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);
248254 // start with new file.
249 setFileInternal(file);
255 setFileInternal(file, true);
250256 } catch (IOException e) {
251257 reportError("Unable to rotate log file", e, ErrorManager.OPEN_FAILURE);
252258 }
253259 }
254260 }
255261
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 }
260281 }
261282 }
2020
2121 import java.io.IOException;
2222 import java.io.InputStream;
23 import java.io.OutputStream;
24 import java.io.UncheckedIOException;
2325 import java.nio.charset.StandardCharsets;
2426 import java.nio.file.Files;
2527 import java.nio.file.Path;
2628 import java.nio.file.Paths;
2729 import java.nio.file.StandardCopyOption;
30 import java.security.AccessControlContext;
31 import java.security.AccessController;
32 import java.security.PrivilegedAction;
2833 import java.text.SimpleDateFormat;
2934 import java.util.Date;
3035 import java.util.Locale;
5257 /**
5358 * An empty rotation suffix.
5459 */
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;
5763 private final String originalSuffix;
5864 private final String datePattern;
5965 private final SimpleDateFormat formatter;
6066 private final String compressionSuffix;
6167 private final CompressionType compressionType;
6268
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;
6472 this.originalSuffix = originalSuffix;
6573 this.datePattern = datePattern;
6674 this.compressionSuffix = compressionSuffix;
7987 *
8088 * @return the file rotator used to determine the suffix parts and rotate the file.
8189 */
82 static SuffixRotator parse(final String suffix) {
90 static SuffixRotator parse(final AccessControlContext acc, final String suffix) {
8391 if (suffix == null || suffix.isEmpty()) {
8492 return EMPTY;
8593 }
102110 }
103111 }
104112 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);
108116 }
109117
110118 /**
155163 try {
156164 archiveGzip(source, target);
157165 // Delete the file after it's archived to behave like a file move or rename
158 Files.delete(source);
166 deleteFile(source);
159167 } catch (Exception e) {
160168 errorManager.error(String.format("Failed to compress %s to %s. Compressed file may be left on the " +
161169 "filesystem corrupted.", source, target), e, ErrorManager.WRITE_FAILURE);
164172 try {
165173 archiveZip(source, target);
166174 // Delete the file after it's archived to behave like a file move or rename
167 Files.delete(source);
175 deleteFile(source);
168176 } catch (Exception e) {
169177 errorManager.error(String.format("Failed to compress %s to %s. Compressed file may be left on the " +
170178 "filesystem corrupted.", source, target), e, ErrorManager.WRITE_FAILURE);
218226 final String fileWithSuffix = source.toAbsolutePath() + rotationSuffix;
219227 final Path lastFile = Paths.get(fileWithSuffix + "." + maxBackupIndex + compressionSuffix);
220228 try {
221 Files.deleteIfExists(lastFile);
229 deleteFile(lastFile);
222230 } catch (Exception e) {
223231 errorManager.error(String.format("Failed to delete file %s", lastFile), e, ErrorManager.GENERIC_FAILURE);
224232 }
225233 for (int i = maxBackupIndex - 1; i >= 1; i--) {
226234 final Path src = Paths.get(fileWithSuffix + "." + i + compressionSuffix);
227 if (Files.exists(src)) {
235 if (fileExists(src)) {
228236 final Path target = Paths.get(fileWithSuffix + "." + (i + 1) + compressionSuffix);
229237 move(errorManager, src, target);
230238 }
241249 }
242250
243251 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 {
254266 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)) {
257269 int len;
258270 while ((len = in.read(buff)) != -1) {
259271 out.write(buff, 0, len);
263275 }
264276 }
265277
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 {
267279 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)) {
269281 final ZipEntry entry = new ZipEntry(source.getFileName().toString());
270282 out.putNextEntry(entry);
271 try (final InputStream in = Files.newInputStream(source)) {
283 try (final InputStream in = newInputStream(source)) {
272284 int len;
273285 while ((len = in.read(buff)) != -1) {
274286 out.write(buff, 0, len);
277289 out.closeEntry();
278290 }
279291 }
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 }
280408 }
8383
8484 private void renderStackTrace(final StackTraceElement[] parentStack, final Throwable child, final String caption, final String prefix) {
8585 if (seen.contains(child)) {
86 builder.append("\t[CIRCULAR REFERENCE:")
86 builder.append(prefix)
87 .append(caption)
88 .append("[CIRCULAR REFERENCE: ")
8789 .append(child)
8890 .append(']');
8991 newLine();
244244 formatter = new PatternFormatter("%e");
245245 cause.addSuppressed(suppressedLevel1);
246246 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"));
248248 }
249249
250250 @Test