diff --git a/core/pom.xml b/core/pom.xml
index a88ab76ea42..210b4942b4e 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -175,6 +175,11 @@
saaj-impl
test
+
+ org.awaitility
+ awaitility
+ test
+
diff --git a/core/src/main/java/org/apache/cxf/bus/extension/ExtensionManagerBus.java b/core/src/main/java/org/apache/cxf/bus/extension/ExtensionManagerBus.java
index 4c12756d6ac..510a3019edc 100644
--- a/core/src/main/java/org/apache/cxf/bus/extension/ExtensionManagerBus.java
+++ b/core/src/main/java/org/apache/cxf/bus/extension/ExtensionManagerBus.java
@@ -40,6 +40,8 @@
import org.apache.cxf.configuration.NullConfigurer;
import org.apache.cxf.feature.Feature;
import org.apache.cxf.interceptor.AbstractBasicInterceptorProvider;
+import org.apache.cxf.io.CachedOutputStreamCleaner;
+import org.apache.cxf.io.DelayedCachedOutputStreamCleaner;
import org.apache.cxf.resource.DefaultResourceManager;
import org.apache.cxf.resource.ObjectTypeResolver;
import org.apache.cxf.resource.PropertiesResolver;
@@ -141,6 +143,11 @@ public InputStream getAsStream(String name) {
if (null == this.getExtension(BindingFactoryManager.class)) {
new BindingFactoryManagerImpl(this);
}
+
+ if (null == this.getExtension(CachedOutputStreamCleaner.class)) {
+ this.extensions.put(CachedOutputStreamCleaner.class, DelayedCachedOutputStreamCleaner.create(this));
+ }
+
extensionManager.load(new String[] {ExtensionManagerImpl.BUS_EXTENSION_RESOURCE});
extensionManager.activateAllByType(ResourceResolver.class);
diff --git a/core/src/main/java/org/apache/cxf/io/CachedConstants.java b/core/src/main/java/org/apache/cxf/io/CachedConstants.java
index 24ba8d8347b..ad18d2f9149 100644
--- a/core/src/main/java/org/apache/cxf/io/CachedConstants.java
+++ b/core/src/main/java/org/apache/cxf/io/CachedConstants.java
@@ -71,6 +71,14 @@ public final class CachedConstants {
public static final String CIPHER_TRANSFORMATION_BUS_PROP =
"bus.io.CachedOutputStream.CipherTransformation";
+ /**
+ * The delay (in ms) for cleaning up unclosed {@code CachedOutputStream} instances. 30 minutes
+ * is specified by default. If the value of the delay is set to 0 (or is negative), the cleaner
+ * will be disabled.
+ */
+ public static final String CLEANER_DELAY_BUS_PROP =
+ "bus.io.CachedOutputStreamCleaner.Delay";
+
private CachedConstants() {
// complete
}
diff --git a/core/src/main/java/org/apache/cxf/io/CachedOutputStream.java b/core/src/main/java/org/apache/cxf/io/CachedOutputStream.java
index ea8ce0d625d..3ba937d04b0 100644
--- a/core/src/main/java/org/apache/cxf/io/CachedOutputStream.java
+++ b/core/src/main/java/org/apache/cxf/io/CachedOutputStream.java
@@ -22,6 +22,7 @@
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@@ -93,6 +94,7 @@ public class CachedOutputStream extends OutputStream {
private List callbacks;
private List