You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by jf...@apache.org on 2002/03/03 20:07:43 UTC
cvs commit: jakarta-commons-sandbox/daemon/src/samples README.txt ServiceDaemon.java ServiceDaemon.sh SimpleDaemon.java SimpleDaemon.sh build.xml
jfclere 02/03/03 11:07:43
Added: daemon/src/samples README.txt ServiceDaemon.java
ServiceDaemon.sh SimpleDaemon.java SimpleDaemon.sh
build.xml
Log:
Add some examples.
Revision Changes Path
1.1 jakarta-commons-sandbox/daemon/src/samples/README.txt
Index: README.txt
===================================================================
The directory contains examples of java daemons.
The examples are compiled using ant (just type ant). Each example creates a
jar file in ../../dist
SimpleDaemon:
SimpleDaemon demonstrates the feature of the daemon ofered by
jakarta-commons-sandbox/daemon.
To run it adapt the SimpleDaemon.sh file and connect to it using:
telnet localhost 1200
Additional information in ../native/unix/INSTALL.txt
ServiceDaemon:
ServiceDaemon allows to start programs using the jakarta daemon.
That could be usefull when using cygwin under win9x because cygwin only offers
services support under win NT/2000/XP.
(See in ../native/nt/README how to install jsvc as a service in win32).
It uses jakarta Commons Collections:
http://jakarta.apache.org/commons/collections.html
To use it you need at least commons-collections-1.0
You have to create a file named startfile that uses a property format:
name = string to start the program
For example:
sshd /usr/sbin/sshd -D
router1 /home/Standard/router/router pop3 pop3.example.net
router2 /home/Standard/router/smtp smtp.example.net
socks5 /usr/local/bin/socks5 -f
To run it adapt the ServiceDaemon.sh file.
1.1 jakarta-commons-sandbox/daemon/src/samples/ServiceDaemon.java
Index: ServiceDaemon.java
===================================================================
/* ========================================================================= *
* *
* The Apache Software License, Version 1.1 *
* *
* Copyright (c) 1999-2001 The Apache Software Foundation. *
* All rights reserved. *
* *
* ========================================================================= *
* *
* Redistribution and use in source and binary forms, with or without modi- *
* fication, are permitted provided that the following conditions are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice *
* notice, this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. The end-user documentation included with the redistribution, if any, *
* must include the following acknowlegement: *
* *
* "This product includes software developed by the Apache Software *
* Foundation <http://www.apache.org/>." *
* *
* Alternately, this acknowlegement may appear in the software itself, if *
* and wherever such third-party acknowlegements normally appear. *
* *
* 4. The names "The Jakarta Project", "WebApp", and "Apache Software *
* Foundation" must not be used to endorse or promote products derived *
* from this software without prior written permission. For written *
* permission, please contact <ap...@apache.org>. *
* *
* 5. Products derived from this software may not be called "Apache" nor may *
* "Apache" appear in their names without prior written permission of the *
* Apache Software Foundation. *
* *
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES *
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY *
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL *
* THE APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY *
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL *
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS *
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) *
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, *
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *
* POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= *
* *
* This software consists of voluntary contributions made by many indivi- *
* duals on behalf of the Apache Software Foundation. For more information *
* on the Apache Software Foundation, please see <http://www.apache.org/>. *
* *
* ========================================================================= */
/* @version $Id: ServiceDaemon.java,v 1.1 2002/03/03 19:07:43 jfclere Exp $ */
import java.io.*;
import java.net.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import org.apache.commons.daemon.Daemon;
import org.apache.commons.daemon.DaemonController;
import org.apache.commons.daemon.DaemonContext;
import org.apache.commons.collections.ExtendedProperties;
import java.io.IOException;
import java.util.Iterator;
public class ServiceDaemon implements Daemon {
private ExtendedProperties prop = null;
private Process proc[] = null;
public ServiceDaemon() {
super();
System.err.println("ServiceDaemon: instance "+this.hashCode()+
" created");
}
protected void finalize() {
System.err.println("ServiceDaemon: instance "+this.hashCode()+
" garbage collected");
}
/**
* init and destroy were added in jakarta-tomcat-daemon.
*/
public void init(DaemonContext context)
throws Exception {
System.err.println("ServiceDaemon: JFC instance "+this.hashCode()+
" init");
/* read the properties file */
prop = new ExtendedProperties("startfile");
/* create an array to store the processes */
int i=0;
for (Iterator e = prop.getKeys(); e.hasNext() ;) {
e.next();
i++;
}
System.err.println("ServiceDaemon: init for " + i + " processes");
proc = new Process[i];
for (i=0;i<proc.length;i++)
proc[i] = null;
System.err.println("ServiceDaemon: init done ");
}
public void start() {
/* Dump a message */
System.err.println("ServiceDaemon: starting");
/* Start */
int i=0;
for (Iterator e = prop.getKeys(); e.hasNext() ;) {
String name = (String) e.next();
System.err.println("ServiceDaemon: starting: " + name);
try {
proc[i] = Runtime.getRuntime().exec(prop.getString(name));
} catch(Exception ex) {
System.err.println("Exception: " + ex);
}
i++;
}
}
public void stop()
throws IOException, InterruptedException {
/* Dump a message */
System.err.println("ServiceDaemon: stopping");
for (int i=0;i<proc.length;i++) {
if ( proc[i]==null)
continue;
proc[i].destroy();
try {
proc[i].waitFor();
} catch(InterruptedException ex) {
System.err.println("ServiceDaemon: exception while stopping:" +
ex);
}
}
System.err.println("ServiceDaemon: stopped");
}
public void destroy() {
System.err.println("ServiceDaemon: instance "+this.hashCode()+
" destroy");
}
}
1.1 jakarta-commons-sandbox/daemon/src/samples/ServiceDaemon.sh
Index: ServiceDaemon.sh
===================================================================
#!/bin/sh
#
# Small shell script to show how to start the sample services.
#
# Adapt the following lines to your configuration
JAVA_HOME=/cygdrive/c/jdk1.3.1_02
HOME=c:\\cygwin\\home\\Standard
DAEMON_HOME=$HOME\\jakarta-commons-sandbox\\daemon
DAEMON_HOME_SH=/home/Standard/jakarta-commons-sandbox/daemon
TOMCAT_USER=jakarta
CLASSPATH=\
$DAEMON_HOME\\dist\\commons-daemon.jar\;\
$HOME\\commons-collections-1.0\\commons-collections.jar\;\
$DAEMON_HOME\\dist\\Service.jar
$DAEMON_HOME_SH/dist/jsvc \
-home $JAVA_HOME \
-cp $CLASSPATH \
ServiceDaemon
#
# To get a verbose JVM
#-verbose \
# To get a debug of jsvc.
#-debug \
# -user $TOMCAT_USER \
1.1 jakarta-commons-sandbox/daemon/src/samples/SimpleDaemon.java
Index: SimpleDaemon.java
===================================================================
/* ========================================================================= *
* *
* The Apache Software License, Version 1.1 *
* *
* Copyright (c) 1999-2001 The Apache Software Foundation. *
* All rights reserved. *
* *
* ========================================================================= *
* *
* Redistribution and use in source and binary forms, with or without modi- *
* fication, are permitted provided that the following conditions are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice *
* notice, this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. The end-user documentation included with the redistribution, if any, *
* must include the following acknowlegement: *
* *
* "This product includes software developed by the Apache Software *
* Foundation <http://www.apache.org/>." *
* *
* Alternately, this acknowlegement may appear in the software itself, if *
* and wherever such third-party acknowlegements normally appear. *
* *
* 4. The names "The Jakarta Project", "WebApp", and "Apache Software *
* Foundation" must not be used to endorse or promote products derived *
* from this software without prior written permission. For written *
* permission, please contact <ap...@apache.org>. *
* *
* 5. Products derived from this software may not be called "Apache" nor may *
* "Apache" appear in their names without prior written permission of the *
* Apache Software Foundation. *
* *
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES *
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY *
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL *
* THE APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY *
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL *
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS *
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) *
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, *
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *
* POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= *
* *
* This software consists of voluntary contributions made by many indivi- *
* duals on behalf of the Apache Software Foundation. For more information *
* on the Apache Software Foundation, please see <http://www.apache.org/>. *
* *
* ========================================================================= */
/* @version $Id: SimpleDaemon.java,v 1.1 2002/03/03 19:07:43 jfclere Exp $ */
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 {
private ServerSocket server=null;
private Thread thread=null;
private DaemonController controller=null;
private boolean stopping=false;
private String directory=null;
private Vector handlers=null;
public SimpleDaemon() {
super();
System.err.println("SimpleDaemon: instance "+this.hashCode()+
" created");
this.handlers=new Vector();
}
protected void finalize() {
System.err.println("SimpleDaemon: instance "+this.hashCode()+
" garbage collected");
}
/**
* init and destroy were added in jakarta-tomcat-daemon.
*/
public void init(DaemonContext context)
throws Exception {
System.err.println("SimpleDaemon: instance "+this.hashCode()+
" init");
int port=1200;
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);
}
public void start() {
/* Dump a message */
System.err.println("SimpleDaemon: starting");
/* Start */
this.thread.start();
}
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");
}
public void destroy() {
System.err.println("SimpleDaemon: instance "+this.hashCode()+
" destroy");
}
public void run() {
int number=0;
System.err.println("SimpleDaemon: started acceptor loop");
try {
while(!this.stopping) {
Socket socket=this.server.accept();
Handler handler=new Handler(socket,this,this.controller);
handler.setConnectionNumber(number++);
handler.setDirectoryName(this.directory);
new Thread(handler).start();
}
} catch (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 */
Enumeration openhandlers=this.handlers.elements();
while (openhandlers.hasMoreElements()) {
Handler handler=(Handler)openhandlers.nextElement();
System.err.println("SimpleDaemon: dropping connection "+
handler.getConnectionNumber());
handler.close();
}
System.err.println("SimpleDaemon: exiting acceptor loop");
}
protected void addHandler(Handler handler) {
synchronized (handler) {
this.handlers.add(handler);
}
}
protected void removeHandler(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(Socket s, SimpleDaemon p, DaemonController c) {
super();
this.socket=s;
this.parent=p;
this.controller=c;
}
public void run() {
this.parent.addHandler(this);
System.err.println("SimpleDaemon: connection "+this.number+
" opened from "+this.socket.getInetAddress());
try {
InputStream in=this.socket.getInputStream();
OutputStream out=this.socket.getOutputStream();
handle(in,out);
this.socket.close();
} catch (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 (IOException e) {
e.printStackTrace(System.err);
}
}
public void setConnectionNumber(int number) {
this.number=number;
}
public int getConnectionNumber() {
return(this.number);
}
public void setDirectoryName(String directory) {
this.directory=directory;
}
public String getDirectoryName() {
return(this.directory);
}
public void log(String name)
throws IOException {
OutputStream file=new FileOutputStream(name,true);
PrintStream out=new PrintStream(file);
SimpleDateFormat fmt=new SimpleDateFormat();
out.println(fmt.format(new Date()));
out.close();
file.close();
}
public void handle(InputStream in, OutputStream os) {
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.print("Your choiche: ");
}
/* Read an option from the client */
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 (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 (IllegalStateException e) {
out.println();
out.println("Can't reload now");
e.printStackTrace(out);
}
break;
/* Disconnect */
case '3':
String name=this.getDirectoryName()+
"/SimpleDaemon."+
this.getConnectionNumber()+
".tmp";
try {
this.log(name);
out.println("File '"+name+"' created");
} catch (IOException e) {
e.printStackTrace(out);
}
break;
/* Disconnect */
case '4':
out.println("Disconnecting...");
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 (IOException e) {
System.err.println("SimpleDaemon: IOException in "+
"connection "+
this.getConnectionNumber());
return;
}
}
}
}
}
1.1 jakarta-commons-sandbox/daemon/src/samples/SimpleDaemon.sh
Index: SimpleDaemon.sh
===================================================================
#!/bin/sh
#
# Small shell script to show how to start the sample services.
#
# Adapt the following lines to your configuration
JAVA_HOME=/usr/java/jdk1.3.1
DAEMON_HOME=/home1/jakarta/jakarta-commons-sandbox/daemon
TOMCAT_USER=jakarta
CLASSPATH=\
$DAEMON_HOME/dist/commons-daemon.jar:\
$DAEMON_HOME/dist/SimpleDaemon.jar
$DAEMON_HOME/dist/jsvc \
-user $TOMCAT_USER \
-home $JAVA_HOME \
-cp $CLASSPATH \
SimpleDaemon
#
# To get a verbose JVM
#-verbose \
# To get a debug of jsvc.
#-debug \
1.1 jakarta-commons-sandbox/daemon/src/samples/build.xml
Index: build.xml
===================================================================
<project name="daemons samples" default="jars" basedir=".">
<!-- ========== Initialize Properties ===================================== -->
<property file="build.properties"/>
<property name="commons-daemon.jar" value="../../dist/commons-daemon.jar"/>
<property name="dist.home" value="../../dist"/>
<property name="build.home" value="./build"/>
<property name="source.home" value="."/>
<property name="commons-collections.jar" value="../../../../commons-collections-1.0/commons-collections.jar"/>
<target name="jars" depends="SimpleDaemon,ServiceDaemon"/>
<target name="SimpleDaemon" depends="compile"
description="Create SimpleDaemon.jar">
<mkdir dir="${dist.home}"/>
<mkdir dir="${build.home}/classes/META-INF"/>
<copy file="../../../LICENSE"
tofile="${build.home}/classes/META-INF/LICENSE.txt"/>
<jar jarfile="${dist.home}/samples.jar">
<fileset dir="${build.home}/classes">
<include name="SimpleDaemon*.class" />
</fileset>
</jar>
</target>
<target name="ServiceDaemon" depends="compile"
description="Create ServiceDaemon.jar">
<mkdir dir="${dist.home}"/>
<mkdir dir="${build.home}/classes/META-INF"/>
<copy file="../../../LICENSE"
tofile="${build.home}/classes/META-INF/LICENSE.txt"/>
<jar jarfile="${dist.home}/service.jar">
<fileset dir="${build.home}/classes">
<include name="ServiceDaemon*.class" />
</fileset>
</jar>
</target>
<target name="compile" depends="prepare"
description="Create class files">
<javac srcdir="${source.home}"
destdir="${build.home}/classes"
debug="${compile.debug}"
deprecation="${compile.deprecation}"
optimize="${compile.optimize}">
<classpath refid="compile.classpath"/>
</javac>
</target>
<target name="prepare">
<mkdir dir="${build.home}"/>
<mkdir dir="${build.home}/classes"/>
</target>
<!-- Construct compile classpath -->
<path id="compile.classpath">
<pathelement location="${commons-daemon.jar}"/>
<pathelement location="${commons-collections.jar}"/>
</path>
</project>
--
To unsubscribe, e-mail: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>