001 /**
002 * Jetrix TetriNET Server
003 * Copyright (C) 2001-2004 Emmanuel Bourg
004 *
005 * This program is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU General Public License
007 * as published by the Free Software Foundation; either version 2
008 * of the License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013 * GNU General Public License for more details.
014 *
015 * You should have received a copy of the GNU General Public License
016 * along with this program; if not, write to the Free Software
017 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
018 */
019
020 package net.jetrix;
021
022 import java.io.File;
023 import java.io.FileOutputStream;
024 import java.io.IOException;
025 import java.net.URL;
026 import java.net.URLClassLoader;
027 import java.net.DatagramPacket;
028 import java.net.DatagramSocket;
029 import java.net.InetAddress;
030 import java.util.ArrayList;
031 import java.util.List;
032 import java.util.jar.JarOutputStream;
033 import java.util.jar.Pack200;
034
035 /**
036 * An application launcher executing a specified class and building dynamically
037 * its class path.
038 *
039 * @author Emmanuel Bourg
040 * @version $Revision: 794 $, $Date: 2009-02-17 20:08:39 +0100 (Tue, 17 Feb 2009) $
041 */
042 public class Launcher {
043
044 public static final String MAIN_CLASS = "net.jetrix.Server";
045
046 /**
047 * Server entry point. All classes, jar and zip files in the lib
048 * subdirectory are automatically added to the classpath.
049 *
050 * @param args start parameters
051 */
052 public static void main(String[] args) throws Exception
053 {
054 if (args.length == 1 && "stop".equals(args[0]))
055 {
056 stop();
057 }
058 else
059 {
060 start(args);
061 }
062 }
063
064 private static void start(String[] args) throws Exception
065 {
066 // get the files in the lib directory
067 File repository = new File("lib/");
068
069 // decompress the pack200 files
070 unpack(repository);
071
072 ClassLoader loader = createClassLoader(repository, new File("lang/"));
073
074 Thread.currentThread().setContextClassLoader(loader);
075
076 // run the main method of the specified class
077 Class serverClass = loader.loadClass(MAIN_CLASS);
078 serverClass.getMethod("main", String[].class).invoke(null, new Object[] { args });
079 }
080
081 /**
082 * Unpack the pack200 files in the specified directory
083 *
084 * @param directory the directory containing the files to be unpacked
085 */
086 private static void unpack(File directory) throws IOException
087 {
088 File[] files = directory.listFiles();
089
090 for (File file : files)
091 {
092 String filename = file.getAbsolutePath();
093 if (filename.endsWith(".pack"))
094 {
095 // remove the .pack extension at the end of the unpacked file
096 String unpackedName = filename.substring(0, filename.lastIndexOf(".pack"));
097 JarOutputStream out = new JarOutputStream(new FileOutputStream(unpackedName));
098
099 Pack200.newUnpacker().unpack(file, out);
100
101 out.flush();
102 out.close();
103
104 // delete the packed file
105 file.delete();
106 }
107 }
108 }
109
110 /**
111 * Build a classloader including the jar and zip files in the specified
112 * directories. The directories are also included in the classpath.
113 *
114 * @param directories the directories containing the jars to be mounted in the classpath
115 */
116 private static ClassLoader createClassLoader(File... directories) throws Exception
117 {
118 List<URL> urls = new ArrayList<URL>();
119
120 for (File directory : directories)
121 {
122 // add the jar and zip files in the directory to the classpath
123 File[] files = directory.listFiles();
124
125 for (File file : files)
126 {
127 String filename = file.getAbsolutePath();
128 if (filename.endsWith(".jar") || filename.endsWith(".zip"))
129 {
130 urls.add(file.toURI().toURL());
131 }
132 }
133
134 // add the directory to the classpath
135 urls.add(directory.toURI().toURL());
136 }
137
138 // create the classloader
139 return new URLClassLoader(urls.toArray(new URL[urls.size()]), null);
140 }
141
142 private static void stop() throws Exception
143 {
144 // send the "shutdown" to the UDP port 31457
145 byte[] msg = "shutdown".getBytes("UTF8");
146 DatagramPacket packet = new DatagramPacket(msg, msg.length);
147 packet.setAddress(InetAddress.getLocalHost());
148 packet.setPort(31457);
149
150 DatagramSocket socket = new DatagramSocket();
151 try
152 {
153 socket.send(packet);
154 }
155 finally
156 {
157 socket.close();
158 }
159 }
160
161 }