package io.collap.bryg.environment;

import io.collap.bryg.Template;

import java.util.HashMap;
import java.util.Map;

public class StandardEnvironment implements Environment {

    private Map<String, Template> templateMap = new HashMap<> ();
    private ClassLoader templateClassLoader;

    public StandardEnvironment (ClassLoader templateClassLoader) {
        this.templateClassLoader = templateClassLoader;
    }

    @Override
    public Template getTemplate (String name) {
        Template template = templateMap.get (name);

        if (template == null) {
            template = loadTemplate (name);
        }

        return template;
    }

    /**
     * Also adds the loaded template to the cache.
     */
    private synchronized Template loadTemplate (String name) {
        Template template = null;
        try {
            System.out.println ();
            System.out.println ("Template: " + name);
            long start = System.nanoTime ();
            Class<? extends Template> cl = (Class<? extends Template>) templateClassLoader.loadClass (name);
            template = cl.newInstance ();
            templateMap.put (name, template);
            System.out.println ("Loading took " + ((System.nanoTime () - start) / 1.0e9) + "s.");
            System.out.println ();
        } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
            e.printStackTrace ();
        }

        return template;
    }

}

@@ -63,16 +63,46 @@
 plate;%0A%0A
+import java.util.Collections;%0A
 import j
@@ -119,16 +119,16 @@
 ashMap;%0A
-
 import j
@@ -253,24 +253,70 @@
 p = 
-new HashMap%3C
+Collections.synchronizedMap (new HashMap%3CString, Template
 %3E ()
+)
 ;%0A  
@@ -885,14 +885,605 @@
 e = 
-null;%0A
+templateMap.get (name);%0A%0A        /* There could be a case where getTemplate is called with the same name two or more times,%0A           which would result in the following scenario:%0A             1. The first call reaches loadTemplate and calls it. loadTemplate is then locked on this object.%0A             2. The second call reaches loadTemplate and calls it.%0A             3. The first call finishes.%0A             4. The second call can now enter loadTemplate and *loads the template again*.%0A           The check ensures that the template is not loaded again. */%0A        if (template == null) %7B%0A    
     
@@ -1492,16 +1492,20 @@
   try %7B%0A
+    
         
@@ -1535,32 +1535,36 @@
 ();%0A            
+    
 System.out.print
@@ -1601,16 +1601,20 @@
         
+    
 long sta
@@ -1650,16 +1650,20 @@
         
+  
+  
 Class%3C? 
@@ -1755,32 +1755,36 @@
 e);%0A            
+    
 template = cl.ne
@@ -1793,24 +1793,28 @@
 nstance ();%0A
+    
             
@@ -1851,32 +1851,36 @@
 e);%0A            
+    
 System.out.print
@@ -1953,32 +1953,36 @@
 %22);%0A            
+    
 System.out.print
@@ -1996,16 +1996,20 @@
         
+  
+  
 %7D catch 
@@ -2099,16 +2099,20 @@
         
+    
 e.printS
@@ -2121,24 +2121,38 @@
 ckTrace ();%0A
+            %7D%0A
         %7D%0A%0A 

Improve thread safety with additional checks and a synchronized map.