/**
 * @license
 * Copyright 2017 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

package foam.nanos.boot;

import foam.core.*;
import foam.nanos.*;
import foam.nanos.logger.Logger;
import foam.nanos.pm.PM;

public class NSpecFactory
  implements XFactory
{
  NSpec   spec_;
  ProxyX  x_;
  boolean isCreating_ = false;

  public NSpecFactory(ProxyX x, NSpec spec) {
    x_    = x;
    spec_ = spec;
  }

  public Object create(X x) {
    // Avoid infinite recursions when creating services
    if ( isCreating_ ) {
      if ( ! "logger".equals(spec_.getName()) ) {
        Logger logger = (Logger) x.get("logger");
        if ( logger != null ) logger.warning("Recursive Service Factory", spec_.getName());
      }

      return null;
    }

    isCreating_ = true;

    Object ns     = null;
    PM     pm     = new PM(this.getClass(), spec_ == null ? "-" : spec_.getName());
    Logger logger = (Logger) x.get("logger");

    try {
      if ( logger != null ) logger.info("Creating Service", spec_.getName());
      ns = spec_.createService(x_.getX());
      if ( logger != null ) logger.info("Created Service", spec_.getName());

      if ( ns instanceof ContextAware ) ((ContextAware) ns).setX(x_.getX());
      if ( ns instanceof NanoService  ) ((NanoService)  ns).start();
    } catch (Throwable t) {
      if ( logger != null ) logger.error("Error Creating Service", spec_.getName(), t);
    } finally {
      pm.log(x_.getX());
      isCreating_ = false;
    }

    return ns;
  }
}
@@ -302,17 +302,16 @@
  NSpec  
- 
 spec_;%0A 
@@ -322,42 +322,64 @@
 xyX 
- 
 x_;%0A  
-boolean isCreating_ = false
+Thread creatingThread_ = null;%0A  Object ns_ = null
 ;%0A%0A 
@@ -556,27 +556,57 @@
    if ( 
-isC
+c
 reating
-_
+Thread_ == Thread.currentThread()
  ) %7B%0A   
@@ -837,73 +837,129 @@
     
-isC
+c
 reating
-_ = true;%0A%0A    Object ns     = null;
+Thread_ = Thread.currentThread();%0A%0A    synchronized ( this ) %7B%0A      if ( ns_ != null ) return ns_;%0A
 %0A    
-PM 
   
- 
+PM
  pm 
-    
 = ne
@@ -1020,24 +1020,26 @@
 ame());%0A    
+  
 Logger logge
@@ -1077,14 +1077,18 @@
     
+ 
+ 
 try %7B%0A
+  
     
@@ -1085,33 +1085,32 @@
 y %7B%0A        if (
- 
 logger != null )
@@ -1099,33 +1099,32 @@
  (logger != null
- 
 ) logger.info(%22C
@@ -1165,18 +1165,21 @@
 ;%0A      
+  
 ns
+_
  = spec_
@@ -1197,32 +1197,34 @@
 ice(x_.getX());%0A
+  
       if ( logge
@@ -1209,33 +1209,32 @@
 ));%0A        if (
- 
 logger != null )
@@ -1223,33 +1223,32 @@
  (logger != null
- 
 ) logger.info(%22C
@@ -1285,31 +1285,33 @@
 ());%0A%0A      
+  
 if (
- 
 ns
+_
  instanceof 
@@ -1322,17 +1322,16 @@
 extAware
- 
 ) ((Cont
@@ -1342,16 +1342,17 @@
 ware) ns
+_
 ).setX(x
@@ -1358,24 +1358,26 @@
 x_.getX());%0A
+  
       if ( n
@@ -1374,19 +1374,19 @@
     if (
- 
 ns
+_
  instanc
@@ -1400,18 +1400,16 @@
 oService
-  
 ) ((Nano
@@ -1416,20 +1416,20 @@
 Service)
- 
  ns
+_
 ).start(
@@ -1431,16 +1431,18 @@
 tart();%0A
+  
     %7D ca
@@ -1457,24 +1457,26 @@
 owable t) %7B%0A
+  
       if ( l
@@ -1465,33 +1465,32 @@
 ) %7B%0A        if (
- 
 logger != null )
@@ -1479,33 +1479,32 @@
  (logger != null
- 
 ) logger.error(%22
@@ -1553,16 +1553,18 @@
 t);%0A    
+  
 %7D finall
@@ -1573,16 +1573,18 @@
 %7B%0A      
+ 
+ 
 pm.log(x
@@ -1604,28 +1604,41 @@
     
-isC
+  c
 reating
-_ = false;
+Thread_ = null;%0A      %7D
 %0A   
@@ -1658,11 +1658,13 @@
 n ns
+_
 ;%0A  %7D%0A%7D
+%0A

fix nspecfactory race condition