/**
 * Copyright (C) 2011 Akiban Technologies Inc.
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License, version 3,
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see http://www.gnu.org/licenses.
 */

package com.akiban.server;

import com.akiban.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.akiban.server.manage.ManageMXBean;
import com.akiban.server.manage.ManageMXBeanImpl;
import com.akiban.server.service.DefaultServiceFactory;
import com.akiban.server.service.Service;
import com.akiban.server.service.ServiceManager;
import com.akiban.server.service.ServiceManagerImpl;
import com.akiban.server.service.jmx.JmxManageable;
import com.akiban.util.Tap;

import javax.management.ObjectName;
import java.io.IOException;
import java.lang.management.ManagementFactory;

/**
 * @author peter
 */
public class AkServer implements Service<AkServer>, JmxManageable {
    private static final String VERSION_STRING_FILE = "version/akserver_version";
    public static final String VERSION_STRING = getVersionString();

    private static final Logger LOG = LoggerFactory.getLogger(AkServer.class.getName());
    private static final ShutdownMXBeanImpl shutdown = new ShutdownMXBeanImpl();

    
    /**
     * Name of this akserver. Must match one of the entries in
     * /config/cluster.properties (managed by Admin).
     */
    private static final String AKSERVER_NAME = System.getProperty("akserver.name");

    private final JmxObjectInfo jmxObjectInfo;

    public AkServer() {
        this.jmxObjectInfo = new JmxObjectInfo("AKSERVER", new ManageMXBeanImpl(this), ManageMXBean.class);
    }

    @Override
    public void start() throws Exception {
        LOG.info("Starting AkServer {}", AKSERVER_NAME);
        Tap.registerMXBean();
    }

    @Override
    public void stop() throws Exception
    {
        LOG.info("Stopping AkServer {}", AKSERVER_NAME);
        Tap.unregisterMXBean();
    }

    public ServiceManager getServiceManager()
    {
        return ServiceManagerImpl.get();
    }

    @Override
    public JmxObjectInfo getJmxObjectInfo() {
        return jmxObjectInfo;
    }

    @Override
    public AkServer cast() {
        return this;
    }

    @Override
    public Class<AkServer> castClass() {
        return AkServer.class;
    }

    private static String getVersionString()
    {
        try {
            return Strings.join(Strings.dumpResource(null,
                    VERSION_STRING_FILE));
        } catch (IOException e) {
            LOG.warn("Couldn't read resource file");
            return "Error: " + e;
        }
    }

    
    public interface ShutdownMXBean {
        public void shutdown();
    }

    private static class ShutdownMXBeanImpl implements ShutdownMXBean {
        private static final String BEAN_NAME = "com.akiban:type=SHUTDOWN";

        public ShutdownMXBeanImpl() {
            createHook();
            registerMXBean();
        }

        @Override
        public void shutdown() {
            try {
                ServiceManager sm = ServiceManagerImpl.get();
                if(sm != null) {
                    sm.stopServices();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        private void createHook() {
            Thread hook = new Thread(new Runnable() {
                @Override
                public void run() {
                    shutdown();
                }
            }, "ShutdownHook");
            Runtime.getRuntime().addShutdownHook(hook);
        }

        private void registerMXBean() {
            try {
                ManagementFactory.getPlatformMBeanServer().registerMBean(this, new ObjectName(BEAN_NAME));
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * @param args
     *            the command line arguments
     */
    public static void main(String[] args) throws Exception
    {
        final ServiceManager serviceManager = new ServiceManagerImpl(new DefaultServiceFactory());
        serviceManager.startServices();
    }
}

@@ -1642,16 +1642,20 @@
 shutdown
+Bean
  = new S
@@ -3333,64 +3333,8 @@
 ) %7B%0A
-            createHook();%0A            registerMXBean();%0A
     
@@ -3662,179 +3662,288 @@
   %7D%0A
-%0A        private void createHook() %7B
+    %7D%0A%0A%0A    /**%0A     * @param args the command line arguments
 %0A     
+*/%0A
     
-   Thread hook = new Thread(new Runnable() %7B%0A                @Override%0A                public void run() %7B%0A          
+public static void main(String%5B%5D args) throws Exception %7B%0A        final ServiceManager serviceManager = new ServiceManagerImpl(new DefaultServiceFactory());%0A        serviceManager.startServices();%0A%0A
         
   sh
@@ -3938,17 +3938,22 @@
         
- 
+// JMX
  shutdow
@@ -3953,34 +3953,32 @@
 shutdown
-();%0A      
+ method%0A
         
   %7D%0A    
@@ -3961,35 +3961,37 @@
  method%0A        
-  %7D
+try %7B
 %0A            %7D, 
@@ -3991,157 +3991,72 @@
     
-%7D, %22ShutdownHook%22);%0A            Runtime.getRuntime().addShutdownHook(hook);%0A        %7D%0A%0A        private void registerMXBean() %7B%0A            try %7B%0A    
+ObjectName name = new ObjectName(ShutdownMXBeanImpl.BEAN_NAME);%0A
     
@@ -4124,46 +4124,29 @@
 ean(
-this, new ObjectName(BEAN_NAME));%0A    
+shutdownBean, name);%0A
     
@@ -4184,38 +4184,66 @@
         
-    e.printStackTrace(
+LOG.error(%22Exception registering shutdown bean%22, e
 );%0A     
@@ -4237,37 +4237,34 @@
 n%22, e);%0A        
-  
-  
 %7D
+%0A
 %0A        %7D%0A    %7D
@@ -4260,98 +4260,132 @@
     
-%7D%0A    %7D%0A%0A%0A    /**%0A     * @param args
+// JVM shutdown hook%0A        Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() %7B
 %0A     
-*
        
-     the command line arguments%0A
+@Override%0A   
      
-*/%0A
     
@@ -4395,71 +4395,33 @@
 lic 
-static void main(String%5B%5D args) throws Exception
+void run() %7B
 %0A    
-%7B%0A
         
 fina
@@ -4420,136 +4420,77 @@
     
-final ServiceManager serviceManager = new ServiceManagerImpl(new DefaultServiceFactory());%0A        serviceManager.startServices(
+    shutdownBean.shutdown();%0A            %7D%0A        %7D, %22ShutdownHook%22)
 );%0A 

Move registering of shutdown hook and bean out of ShutdownMXBeanImpl and into the AkServer.main