org.atomspace.pi2c.runtime.Server.java Source code

Java tutorial

Introduction

Here is the source code for org.atomspace.pi2c.runtime.Server.java

Source

/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.atomspace.pi2c.runtime;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import java.net.URL;
import java.net.URLClassLoader;
import java.util.Date;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import sun.misc.Signal;
import sun.misc.SignalHandler;

public class Server implements Runnable {

    //Only a Jar is started by java -jar server.jar, have to extract and update the classpath
    static public final int RUNMODE_JAR = 1;
    //The Jar is complete extracted and Enviroment with CLASSPATH existing
    static public final int RUNMODE_ENV = 2;

    //Server startup
    static public final int STATUS_STARTING = 1;
    //Server running
    static public final int STATUS_RUNNING = 2;
    //Server receive shutdown signal and process the stopping
    static public final int STATUS_STOPING = 3;

    //Value of RUNMODE_
    static private int runmode;
    //Value of STATUS_
    static private int status;

    static private boolean windows;
    static private boolean linux;
    static private boolean sunos;
    static private boolean freebsd;

    private URL location;
    private ClassPathXmlApplicationContext springContext;

    public static void main(String[] args) throws Exception {
        System.err.println("::: ----------------------------------------------------------------------- :::");
        System.err.println("::: ------------------------------  STARTING  ------------------------------:::");
        System.err.println("::: ----------------------------------------------------------------------- :::");
        System.err.println("\n::: SYSTEM-Properties:                                                    :::");
        Set<?> properties = System.getProperties().keySet();
        for (Object object : properties) {
            System.err.println("::: " + object.toString() + " = " + System.getProperty(object.toString()));
        }
        System.err.println("\n::: ENV-Properties:                                                       :::");
        properties = System.getenv().keySet();
        for (Object object : properties) {
            System.err.println("::: " + object.toString() + " = " + System.getenv(object.toString()));
        }

        windows = System.getProperty("os.name").toLowerCase().startsWith("windows");
        linux = System.getProperty("os.name").toLowerCase().startsWith("linux");
        sunos = System.getProperty("os.name").toLowerCase().startsWith("sun");
        freebsd = System.getProperty("os.name").toLowerCase().startsWith("freebsd");

        if (linux || sunos) {
            //USR2-Signal-Handel lookup internal Server STATUS for Linux or SunOS
            System.err.println("::: " + new Date() + "::: run unter Linux or SunOS :::");
            addUnixSignalStatusHandle();
        } else if (freebsd) {
            System.err.println("::: " + new Date() + "::: run unter FreeBSD :::");
        } else if (windows) {
            //Gracefull Shutdown JFrame for Windows, because can not kill -15 <pid> on Window or in Eclipse Console
            System.err.println("::: " + new Date() + " ::: run unter windows :::");
            addWindowsShutdownHandle();
        } else {
            System.err.println("UNKNOWN OS:" + System.getProperty("os.name"));
        }

        status = STATUS_STARTING;

        Server server = new Server();
        Thread serverThread = new Thread(server);
        serverThread.start();

        //Thread can stop by Shutdown-Hook
        while (true) {
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
                break;
            }
        }

    }

    private static void addWindowsShutdownHandle() {
        Runnable guiCreator = new Runnable() {
            public void run() {
                // create a swing window
                JFrame macroWindow = new JFrame("MacroServer");
                macroWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                macroWindow.setSize(250, 70);
                macroWindow.setVisible(true);
                JButton button = new JButton("SHUTDOWN");
                button.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        System.out.println("STOPPING SERVER, PLEASE WAIT...");
                        System.exit(0);
                    }
                });
                macroWindow.getContentPane().add(button);
            }
        };
        SwingUtilities.invokeLater(guiCreator);
    }

    private static void addUnixSignalStatusHandle() {
        Signal.handle(new Signal("USR2"), new SignalHandler() {
            @Override
            public void handle(Signal sig) {
                System.err
                        .print("::: " + new Date() + " ::: RECIVE SIGNAL " + sig + " ::: Internal Server Status: ");
                if (sig != null) {
                    if (status == STATUS_STARTING) {
                        System.err.println("'STATUS_STARTING' :::");
                    } else if (status == STATUS_RUNNING) {
                        System.err.println("'STATUS_RUNNING' :::");
                    } else if (status == STATUS_STOPING) {
                        System.err.println("'STATUS_STOPING' :::");
                    } else {
                        System.err.println("'STATUS_UNKNOWN' :::");
                    }
                }
                System.err.flush();
            }
        });
    }

    /**
     * Run the Server Thread
     */
    @Override
    public void run() {
        location = Server.class.getProtectionDomain().getCodeSource().getLocation();
        System.err.println("::: " + new Date() + " ::: loading from '" + location + "' :::");

        //GET Lookup Enviroment
        if (location.toString().endsWith("jar")) {
            runmode = RUNMODE_JAR;
            System.err.println("::: " + new Date() + " ::: Starting in JAR-MODE :::");
        } else {
            runmode = RUNMODE_ENV;
            System.err.println("::: " + new Date() + " ::: Starting in existing ENVIROMENT-MODE :::");
        }

        // Adding a Shutdownhook for graceful camel context stop
        ServerShutdownHook shutdownHook = new ServerShutdownHook();
        Thread shutdownHookThread = new Thread(shutdownHook);
        Runtime.getRuntime().addShutdownHook(shutdownHookThread);

        // Extract and Loading Jars with Classloader
        try {
            if (runmode == RUNMODE_JAR)
                this.loadingJars();
            this.startSpringContext();
            status = STATUS_RUNNING;
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    /**
     * Starting a Spring-Context with application-context.xml in classpath
     */
    private void startSpringContext() {
        String filename = "application-context.xml";
        springContext = new ClassPathXmlApplicationContext(filename);
        springContext.start();
    }

    /**
     * Loading Jars with the ClassLoader and Unzip the included Jar-Files from libs folder
     * @throws SecurityException
     * @throws NoSuchMethodException
     * @throws IOException
     * @throws IllegalArgumentException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    private void loadingJars() throws SecurityException, NoSuchMethodException, IOException,
            IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        // Prepair Classloader Reflextion
        Method m = URLClassLoader.class.getDeclaredMethod("addURL", new Class[] { URL.class });
        m.setAccessible(true);

        ClassLoader cl = Server.class.getClassLoader();

        // Create Temp Dir
        File appTmp = new File(System.getProperty("java.io.tmpdir") + "/"
                + location.toString().substring(location.toString().lastIndexOf("/")));
        System.err.println("::: use temporary dir path '" + appTmp.getAbsolutePath() + "'");
        if (!appTmp.exists()) {
            appTmp.mkdir();
        }

        ZipInputStream zip = new ZipInputStream(location.openStream());
        ZipEntry entry = zip.getNextEntry();
        while (entry != null) {
            if (entry.getName().startsWith("libs/") && entry.getName().endsWith(".jar")
                    || (entry.getName().endsWith("MANIFEST.MF"))) {
                System.err.println("::: " + new Date() + " ::: Extracting " + entry.getName() + " :::");
                InputStream is = cl.getResourceAsStream(entry.getName());
                File tmpJar = new File(appTmp + "/" + entry.getName().substring(entry.getName().lastIndexOf("/")));
                unzip(is, tmpJar);
                m.invoke(cl, new Object[] { tmpJar.toURI().toURL() });
            } else {
                System.err.println("::: " + new Date() + " ::: ignore " + entry.getName() + " :::");

            }
            entry = zip.getNextEntry();
        }
    }

    /**
     * Unzip a InputStream to a File-Destination 
     * @param src
     * @param destination
     * @throws IOException
     */
    private void unzip(InputStream src, File destination) throws IOException {
        FileOutputStream fos = new FileOutputStream(destination);

        int len = 0;
        byte[] buffer = new byte[16384];

        while ((len = src.read(buffer)) > 0) {
            fos.write(buffer, 0, len);
        }
        fos.flush();
        fos.close();
    }

    /**
     * Shutdown-Hook for Stop the Spring-Context graceful
     */
    private class ServerShutdownHook implements Runnable {

        @Override
        public void run() {
            status = STATUS_STOPING;

            System.err.println("::: " + new Date() + " ::: Shutdown from: " + location + " :::");
            if (springContext == null) {
                System.err.println("::: " + new Date() + " ::: SpringContext not existing only stop :::");
            } else {
                System.err.println("::: " + new Date() + " ::: SpringContext isActive:" + springContext.isActive()
                        + " / SpringContext isRunning:" + springContext.isRunning() + " :::");
                springContext.stop();
                System.err.println("::: " + new Date() + " ::: SpringContext isActive:" + springContext.isActive()
                        + " / SpringContext isRunning:" + springContext.isRunning() + " :::");
                springContext.destroy();
                System.err.println("::: " + new Date() + " ::: SpringContext isActive:" + springContext.isActive()
                        + " / SpringContext isRunning:" + springContext.isRunning() + " :::");
            }
            System.err.println("::: ----------------------------------------------------------------------- :::");
            System.err.println("::: ------------------------------  STOPPED  ------------------------------ :::");
            System.err.println("::: ----------------------------------------------------------------------- :::");
        }
    }

}