You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by jg...@apache.org on 2019/05/28 09:46:55 UTC

svn commit: r1860225 [16/16] - in /tomee/deps/branches/commons-daemon: ./ src/ src/assembly/ src/changes/ src/docs/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/commons/ src/main/java/org/apache/commons...

Added: tomee/deps/branches/commons-daemon/src/test/java/org/apache/commons/daemon/SimpleDaemon.java
URL: http://svn.apache.org/viewvc/tomee/deps/branches/commons-daemon/src/test/java/org/apache/commons/daemon/SimpleDaemon.java?rev=1860225&view=auto
==============================================================================
--- tomee/deps/branches/commons-daemon/src/test/java/org/apache/commons/daemon/SimpleDaemon.java (added)
+++ tomee/deps/branches/commons-daemon/src/test/java/org/apache/commons/daemon/SimpleDaemon.java Tue May 28 09:46:53 2019
@@ -0,0 +1,344 @@
+/*
+ *  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.apache.commons.daemon;
+
+import java.io.*;
+import java.net.*;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Vector;
+import org.apache.commons.daemon.Daemon;
+import org.apache.commons.daemon.DaemonController;
+import org.apache.commons.daemon.DaemonContext;
+
+/**
+ */
+public class SimpleDaemon implements Daemon, Runnable, DaemonUserSignal {
+
+    private ServerSocket server=null;
+    private Thread thread=null;
+    private DaemonController controller=null;
+    private volatile boolean stopping=false;
+    private String directory=null;
+    private Vector<Handler> handlers=null;
+    private boolean softReloadSignalled;
+
+    public SimpleDaemon() {
+        super();
+        System.err.println("SimpleDaemon: instance "+this.hashCode()+
+                           " created");
+        this.handlers=new Vector<Handler>();
+    }
+
+    @Override
+    protected void finalize() {
+        System.err.println("SimpleDaemon: instance "+this.hashCode()+
+                           " garbage collected");
+    }
+
+    /**
+     * init and destroy were added in jakarta-tomcat-daemon.
+     */
+    @Override
+    public void init(final DaemonContext context)
+    throws Exception {
+        System.err.println("SimpleDaemon: instance "+this.hashCode()+
+                           " init");
+
+        int port=1200;
+
+        final String[] a = context.getArguments();
+
+        if (a.length>0) {
+            port=Integer.parseInt(a[0]);
+        }
+        if (a.length>1) {
+            this.directory=a[1];
+        } else {
+            this.directory="/tmp";
+        }
+
+        /* Dump a message */
+        System.err.println("SimpleDaemon: loading on port "+port);
+
+        /* Set up this simple daemon */
+        this.controller=context.getController();
+        this.server=new ServerSocket(port);
+        this.thread=new Thread(this);
+    }
+
+    @Override
+    public void start() {
+        /* Dump a message */
+        System.err.println("SimpleDaemon: starting");
+
+        /* Start */
+        this.thread.start();
+    }
+
+    @Override
+    public void stop()
+    throws IOException, InterruptedException {
+        /* Dump a message */
+        System.err.println("SimpleDaemon: stopping");
+
+        /* Close the ServerSocket. This will make our thread to terminate */
+        this.stopping=true;
+        this.server.close();
+
+        /* Wait for the main thread to exit and dump a message */
+        this.thread.join(5000);
+        System.err.println("SimpleDaemon: stopped");
+    }
+
+    @Override
+    public void destroy() {
+        System.err.println("SimpleDaemon: instance "+this.hashCode()+
+                           " destroy");
+    }
+
+    @Override
+    public void run() {
+        int number=0;
+
+        System.err.println("SimpleDaemon: started acceptor loop");
+        try {
+            while(!this.stopping) {
+                checkForReload();
+                final Socket socket=this.server.accept();
+                checkForReload();
+
+                final Handler handler=new Handler(socket,this,this.controller);
+                handler.setConnectionNumber(number++);
+                handler.setDirectoryName(this.directory);
+                new Thread(handler).start();
+            }
+        } catch (final IOException e) {
+            /* Don't dump any error message if we are stopping. A IOException
+               is generated when the ServerSocket is closed in stop() */
+            if (!this.stopping) {
+                e.printStackTrace(System.err);
+            }
+        }
+
+        /* Terminate all handlers that at this point are still open */
+        final Enumeration<Handler> openhandlers=this.handlers.elements();
+        while (openhandlers.hasMoreElements()) {
+            final Handler handler=openhandlers.nextElement();
+            System.err.println("SimpleDaemon: dropping connection "+
+                               handler.getConnectionNumber());
+            handler.close();
+        }
+
+        System.err.println("SimpleDaemon: exiting acceptor loop");
+    }
+
+    @Override
+    public void signal() {
+        /* In this example we are using soft reload on
+         * custom signal.
+         */
+        this.softReloadSignalled = true;
+    }
+
+    private void checkForReload() {
+      if (this.softReloadSignalled) {
+        System.err.println("SimpleDaemon: picked up reload, waiting for connections to finish...");
+        while (! this.handlers.isEmpty()) {}
+        System.err.println("SimpleDaemon: all connections have finished, pretending to reload");
+        this.softReloadSignalled = false;
+      }
+    }
+
+    protected void addHandler(final Handler handler) {
+        synchronized (handler) {
+            this.handlers.add(handler);
+        }
+    }
+
+    protected void removeHandler(final Handler handler) {
+        synchronized (handler) {
+            this.handlers.remove(handler);
+        }
+    }
+
+    public static class Handler implements Runnable {
+
+        private DaemonController controller=null;
+        private SimpleDaemon parent=null;
+        private String directory=null;
+        private Socket socket=null;
+        private int number=0;
+
+        public Handler(final Socket s, final SimpleDaemon p, final DaemonController c) {
+            super();
+            this.socket=s;
+            this.parent=p;
+            this.controller=c;
+        }
+
+        @Override
+        public void run() {
+            this.parent.addHandler(this);
+            System.err.println("SimpleDaemon: connection "+this.number+
+                               " opened from "+this.socket.getInetAddress());
+            try {
+                final InputStream in=this.socket.getInputStream();
+                final OutputStream out=this.socket.getOutputStream();
+                handle(in,out);
+                this.socket.close();
+            } catch (final IOException e) {
+                e.printStackTrace(System.err);
+            }
+            System.err.println("SimpleDaemon: connection "+this.number+
+                               " closed");
+            this.parent.removeHandler(this);
+        }
+
+        public void close() {
+            try {
+                this.socket.close();
+            } catch (final IOException e) {
+                e.printStackTrace(System.err);
+            }
+        }
+
+        public void setConnectionNumber(final int number) {
+            this.number=number;
+        }
+
+        public int getConnectionNumber() {
+            return(this.number);
+        }
+
+        public void setDirectoryName(final String directory) {
+            this.directory=directory;
+        }
+
+        public String getDirectoryName() {
+            return(this.directory);
+        }
+
+        public void log(final String name)
+        throws IOException {
+            final OutputStream file=new FileOutputStream(name,true);
+            final PrintStream out=new PrintStream(file);
+            final SimpleDateFormat fmt=new SimpleDateFormat();
+
+            out.println(fmt.format(new Date()));
+            out.close();
+            file.close();
+        }
+
+        public void handle(final InputStream in, final OutputStream os) {
+            final PrintStream out=new PrintStream(os);
+
+            while(true) {
+                try {
+                    /* If we don't have data in the System InputStream, we want
+                       to ask to the user for an option. */
+                    if (in.available()==0) {
+                        out.println();
+                        out.println("Please select one of the following:");
+                        out.println("    1) Shutdown");
+                        out.println("    2) Reload");
+                        out.println("    3) Create a file");
+                        out.println("    4) Disconnect");
+                        out.println("    5) Soft reload");
+                        out.print("Your choice: ");
+                    }
+
+                    /* Read an option from the client */
+                    final int x=in.read();
+
+                    switch (x) {
+                        /* If the socket was closed, we simply return */
+                        case -1:
+                            return;
+
+                        /* Attempt to shutdown */
+                        case '1':
+                            out.println("Attempting a shutdown...");
+                            try {
+                                this.controller.shutdown();
+                            } catch (final IllegalStateException e) {
+                                out.println();
+                                out.println("Can't shutdown now");
+                                e.printStackTrace(out);
+                            }
+                            break;
+
+                        /* Attempt to reload */
+                        case '2':
+                            out.println("Attempting a reload...");
+                            try {
+                                this.controller.reload();
+                            } catch (final IllegalStateException e) {
+                                out.println();
+                                out.println("Can't reload now");
+                                e.printStackTrace(out);
+                            }
+                            break;
+
+                        /* Disconnect */
+                        case '3':
+                            final String name=this.getDirectoryName()+
+                                        "/SimpleDaemon."+
+                                        this.getConnectionNumber()+
+                                        ".tmp";
+                            try {
+                                this.log(name);
+                                out.println("File '"+name+"' created");
+                            } catch (final IOException e) {
+                                e.printStackTrace(out);
+                            }
+                            break;
+
+                        /* Disconnect */
+                        case '4':
+                            out.println("Disconnecting...");
+                            return;
+                        case '5':
+                            out.println("Reloading configuration...");
+                            this.parent.signal();
+                            return;
+
+                        /* Discard any carriage return / newline characters */
+                        case '\r':
+                        case '\n':
+                            break;
+
+                        /* We got something that we weren't supposed to get */
+                        default:
+                            out.println("Unknown option '"+(char)x+"'");
+                            break;
+
+                    }
+
+                /* If we get an IOException we return (disconnect) */
+                } catch (final IOException e) {
+                    System.err.println("SimpleDaemon: IOException in "+
+                                       "connection "+
+                                       this.getConnectionNumber());
+                    return;
+                }
+            }
+        }
+    }
+}