Repository: fabric8io/docker-maven-plugin
Issue: NPE when logging to file

### Description

When logging to a file and starting a container early in the build, a NullPointerException is thrown:
```
Exception in thread "Thread-1" java.lang.NullPointerException
	at io.fabric8.maven.docker.log.DefaultLogCallback.ps(DefaultLogCallback.java:74)
	at io.fabric8.maven.docker.log.DefaultLogCallback.error(DefaultLogCallback.java:84)
	at io.fabric8.maven.docker.access.log.LogRequestor.run(LogRequestor.java:110)
```


### Info

* d-m-p version: 0.23.0
* Maven version (`mvn -v`):
```
Apache Maven 3.5.2 (138edd61fd100ec658bfa2d307c43b76940a5d7d; 2017-10-18T09:58:13+02:00)
Maven home: /home/hho/.sdkman/candidates/maven/current
Java version: 1.8.0_151, vendor: Oracle Corporation
Java home: /usr/lib/jvm/java-8-oracle/jre
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "4.13.0-19-generic", arch: "amd64", family: "unix"
```
* Docker version: 17.11.0-ce
* If it's a bug, how to reproduce:
  1. Use the POM given below
  2. run `mvn compile`

<details>
<summary>POM to reproduce</summary>

```xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>demo</groupId>
  <artifactId>npedemo</artifactId>
  <version>1.0-SNAPSHOT</version>
  <build>
    <plugins>
      <plugin>
        <groupId>io.fabric8</groupId>
        <artifactId>docker-maven-plugin</artifactId>
        <version>0.23.0</version>
        <configuration>
          <images>
            <image>
              <name>postgres:alpine</name>
              <run>
                <log>
                  <file>${project.build.directory}/postgres.log</file>
                </log>
              </run>
            </image>
          </images>
        </configuration>
        <executions>
          <execution>
            <id>start-db</id>
            <phase>generate-sources</phase>
            <goals><goal>start</goal></goals>
          </execution>
          <execution>
            <id>stop-db</id>
            <phase>generate-resources</phase>
            <goals><goal>stop</goal></goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>
```


</details>


<details>
<summary>Example Build Output</summary>

```
➜ mvn compile
[INFO] Scanning for projects...
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] Building npedemo 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- docker-maven-plugin:0.23.0:start (start-db) @ npedemo ---
[INFO] DOCKER> [postgres:alpine]: Start container 69f9e99da85e
Exception in thread "Thread-1" java.lang.NullPointerException
	at io.fabric8.maven.docker.log.DefaultLogCallback.ps(DefaultLogCallback.java:74)
	at io.fabric8.maven.docker.log.DefaultLogCallback.error(DefaultLogCallback.java:84)
	at io.fabric8.maven.docker.access.log.LogRequestor.run(LogRequestor.java:110)
[INFO] 
[INFO] --- docker-maven-plugin:0.23.0:stop (stop-db) @ npedemo ---
[INFO] DOCKER> [postgres:alpine]: Stop and removed container 69f9e99da85e after 0 ms
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ npedemo ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /tmp/npedemo/src/main/resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ npedemo ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 1 source file to /tmp/npedemo/target/classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 12.681 s
[INFO] Finished at: 2017-12-14T17:28:47+01:00
[INFO] Final Memory: 21M/360M
[INFO] ------------------------------------------------------------------------
```

</details>


Changed files:
src/main/java/io/fabric8/maven/docker/log/DefaultLogCallback.java, src/test/java/io/fabric8/maven/docker/log/DefaultLogCallbackTest.java, src/main/java/io/fabric8/maven/docker/log/SharedPrintStream.java

diff --git a/src/main/java/io/fabric8/maven/docker/log/DefaultLogCallback.java b/src/main/java/io/fabric8/maven/docker/log/DefaultLogCallback.java
index f46c7372..ebcef931 100644
--- a/src/main/java/io/fabric8/maven/docker/log/DefaultLogCallback.java
+++ b/src/main/java/io/fabric8/maven/docker/log/DefaultLogCallback.java
@@ -19,6 +19,7 @@ import java.io.*;
 import java.util.HashMap;
 import java.util.Map;
 
+import com.google.common.io.Files;
 import io.fabric8.maven.docker.access.log.LogCallback;
 import io.fabric8.maven.docker.util.Timestamp;
 
@@ -46,6 +47,7 @@ public class DefaultLogCallback implements LogCallback {
             } else {
                 SharedPrintStream cachedPs = printStreamMap.get(file);
                 if (cachedPs == null) {
+                    Files.createParentDirs(new File(file));
                     PrintStream ps = new PrintStream(new FileOutputStream(file), true);
                     cachedPs = new SharedPrintStream(ps);
                     printStreamMap.put(file, cachedPs);
diff --git a/src/main/java/io/fabric8/maven/docker/log/SharedPrintStream.java b/src/main/java/io/fabric8/maven/docker/log/SharedPrintStream.java
index 5b0bab48..78cf20d0 100644
--- a/src/main/java/io/fabric8/maven/docker/log/SharedPrintStream.java
+++ b/src/main/java/io/fabric8/maven/docker/log/SharedPrintStream.java
@@ -24,7 +24,7 @@ class SharedPrintStream {
     boolean close() {
         int nrUsers = numUsers.decrementAndGet();
         if (nrUsers == 0 && printStream != System.out) {
-            printStream.close();;
+            printStream.close();
             return true;
         } else {
             return false;
diff --git a/src/test/java/io/fabric8/maven/docker/log/DefaultLogCallbackTest.java b/src/test/java/io/fabric8/maven/docker/log/DefaultLogCallbackTest.java
index 9440d914..ed8b273f 100644
--- a/src/test/java/io/fabric8/maven/docker/log/DefaultLogCallbackTest.java
+++ b/src/test/java/io/fabric8/maven/docker/log/DefaultLogCallbackTest.java
@@ -5,6 +5,7 @@ import static org.hamcrest.Matchers.empty;
 import static org.hamcrest.Matchers.is;
 import static org.hamcrest.Matchers.startsWith;
 import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
 
 import java.io.*;
 import java.util.*;
@@ -12,6 +13,7 @@ import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
 
+import com.google.common.io.Files;
 import org.apache.maven.shared.utils.io.FileUtils;
 import org.junit.Before;
 import org.junit.Test;
@@ -147,6 +149,18 @@ public class DefaultLogCallbackTest {
         assertThat(indexes, is(empty()));
     }
 
+    @Test
+    public void shouldCreateParentDirs() throws IOException {
+        File dir = Files.createTempDir();
+        dir.deleteOnExit();
+        file = new File(dir, "non/existing/dirs/file.log");
+        spec = new LogOutputSpec.Builder().prefix("callback-test> ")
+                .file(file.toString()).build();
+        callback = new DefaultLogCallback(spec);
+        callback.open();
+        assertTrue(file.exists());
+    }
+
     private class LoggerTask implements Runnable {
 
         private LogCallback cb;