1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 package uk.ac.rdg.resc.jstyx.server;
30
31 import java.net.InetSocketAddress;
32 import java.io.IOException;
33
34 import org.apache.mina.common.TransportType;
35 import org.apache.mina.registry.Service;
36 import org.apache.mina.registry.ServiceRegistry;
37 import org.apache.mina.registry.SimpleServiceRegistry;
38 import org.apache.mina.io.IoAcceptor;
39 import org.apache.mina.io.filter.SSLFilter;
40 import org.apache.mina.protocol.ProtocolProvider;
41
42 import org.apache.log4j.Logger;
43
44 import uk.ac.rdg.resc.jstyx.StyxException;
45 import uk.ac.rdg.resc.jstyx.StyxUtils;
46 import uk.ac.rdg.resc.jstyx.ssl.JonSSLContextFactory;
47
48 /***
49 * A Styx server.
50 *
51 * @author Jon Blower
52 * $Revision: 604 $
53 * $Date: 2006-03-21 14:58:42 +0000 (Tue, 21 Mar 2006) $
54 * $Log$
55 * Revision 1.10 2006/03/21 14:58:42 jonblower
56 * Implemented clear-text password-based authentication and did some simple tests
57 *
58 * Revision 1.9 2006/03/21 09:06:15 jonblower
59 * Still implementing authentication
60 *
61 * Revision 1.8 2006/03/20 17:51:50 jonblower
62 * Adding authentication to base JStyx system
63 *
64 * Revision 1.7 2005/08/30 16:28:23 jonblower
65 * Subsumed TestServer program into StyxServer class
66 *
67 * Revision 1.6 2005/05/05 16:57:38 jonblower
68 * Updated MINA library to revision 168337 and changed code accordingly
69 *
70 * Revision 1.5 2005/03/24 07:57:41 jonblower
71 * Improved code for reading SSL info from SGSconfig file and included parameter information for the Grid Services in the config file
72 *
73 * Revision 1.4 2005/03/14 16:40:02 jonblower
74 * Modifications for using SSL
75 *
76 * Revision 1.3 2005/03/11 14:02:16 jonblower
77 * Merged MINA-Test_20059309 into main line of development
78 *
79 * Revision 1.2.2.6 2005/03/11 08:30:30 jonblower
80 * Moved to log4j logging system (from apache commons logging)
81 *
82 * Revision 1.2.2.5 2005/03/10 18:32:18 jonblower
83 * Minor change to layout
84 *
85 * Revision 1.2.2.3 and 1.2.2.4 2005/03/10 14:38:10 jonblower
86 * Modified for MINA framework
87 *
88 * Revision 1.2.2.1 2005/03/09 19:44:18 jonblower
89 * Changes concerned with migration to MINA
90 *
91 * Revision 1.1.1.1 2005/02/16 18:58:33 jonblower
92 * Initial import
93 *
94 */
95 public class StyxServer
96 {
97
98 private static final Logger log = Logger.getLogger(StyxServer.class);
99
100 private ProtocolProvider provider;
101 private int port;
102
103 private StyxSecurityContext securityContext;
104
105
106 /***
107 * Creates a Styx server that exposes the given directory under the given
108 * port. No security information is used: server will allow anonymous access
109 * and no traffic will be encrypted.
110 * @throws IllegalArgumentException if the port number is invalid or the
111 * root is null.
112 * @throws StyxSecurityException if there was an error setting up the
113 * security context (should never happen since this will be an unsecured
114 * server).
115 */
116 public StyxServer(int port, StyxDirectory root) throws StyxSecurityException
117 {
118 this(port, root, null);
119 }
120
121 /***
122 * Creates a Styx server that listens on the given port and uses the
123 * given protocol provider (This is used by the Styx interloper class)
124 * Connections are anonymous and unsecured.
125 * @throws IllegalArgumentException if the port number is invalid or the
126 * provider is null.
127 */
128 public StyxServer(int port, ProtocolProvider provider)
129 {
130 if (provider == null)
131 {
132 throw new IllegalArgumentException("ProtocolProvider cannot be null");
133 }
134 setPortNumber(port);
135 this.provider = provider;
136 this.securityContext = new StyxSecurityContext();
137 }
138
139 /***
140 * Creates a Styx server.
141 * @param port The port number on which the server will listen
142 * @param root The root of the Styx filesystem to serve
143 * @param securityConfigFile The file containing security information
144 * (user details, SSL setup etc). If this is null, the server will allow
145 * anonymous access and no traffic will be encrypted.
146 * @throws IllegalArgumentException if the port number is invalid or
147 * root == null.
148 * @throws StyxSecurityException if there was an error reading security
149 * configuration from <code>securityConfigFile</code>.
150 */
151 public StyxServer(int port, StyxDirectory root, String securityConfigFile)
152 throws StyxSecurityException
153 {
154 if (root == null)
155 {
156 throw new IllegalArgumentException("root cannot be null");
157 }
158
159 setPortNumber(port);
160 if (securityConfigFile == null)
161 {
162 this.securityContext = new StyxSecurityContext();
163 }
164 else
165 {
166 this.securityContext = new StyxSecurityContext(securityConfigFile);
167 }
168 this.provider = new StyxServerProtocolProvider(root, this.securityContext);
169 }
170
171 /***
172 * Checks to see if the given port number is valid, throwing an
173 * IllegalArgumentException if it isn't. If it is valid, sets it
174 */
175 private void setPortNumber(int port)
176 {
177
178 if (port < 0 || port > StyxUtils.MAXUSHORT)
179 {
180 throw new IllegalArgumentException("Invalid port number");
181 }
182 this.port = port;
183 }
184
185 /***
186 * Starts the Styx server.
187 * @throws IOException if an error occurred
188 */
189 public void start() throws IOException
190 {
191 ServiceRegistry registry = new SimpleServiceRegistry();
192
193
194
195
196 if( this.securityContext.getSSLContext() != null )
197 {
198 SSLFilter sslFilter = new SSLFilter( this.securityContext.getSSLContext() );
199 IoAcceptor acceptor = registry.getIoAcceptor( TransportType.SOCKET );
200 acceptor.getFilterChain().addLast( "sslFilter", sslFilter );
201 }
202
203
204 Service service = new Service( "styx", TransportType.SOCKET, this.port );
205 registry.bind( service, this.provider );
206
207 log.info( "Listening on port " + this.port + ", SSL " +
208 (this.securityContext.getSSLContext() == null ? "disabled" : "enabled"));
209 }
210
211 /***
212 * Simple test Styx server that exposes the contents of a local directory.
213 * The TestServer takes two arguments, both optional. The first is the
214 * port number under which the server will listen (defaults to 8080 if
215 * not set). The second is the directory in the host filesystem which
216 * will be at the root of the Styx server. This defaults to the user's
217 * home directory (i.e. the output of System.getProperty("user.home"))
218 * if not set.
219 */
220 public static void main(String[] args) throws Throwable
221 {
222
223 int port = 8080;
224
225 String home = System.getProperty("user.home");
226 String securityFile = null;
227
228 if (args.length > 0)
229 {
230 try
231 {
232 port = Integer.parseInt(args[0]);
233 }
234 catch (NumberFormatException nfe)
235 {
236 System.err.println(args[0] + " is not a valid port number");
237 return;
238 }
239 }
240 if (args.length > 1)
241 {
242 home = args[1];
243 }
244 if (args.length > 2)
245 {
246 securityFile = args[2];
247 }
248 if (args.length > 3)
249 {
250 System.err.println("Usage: TestServer [port] [root directory] [security file]");
251 return;
252 }
253
254
255 System.out.println("Building directory tree (this can take some time)");
256 StyxDirectory root = new DirectoryOnDisk(home);
257
258
259 root.addChild(new StyxDirectory("jdbandusers", "jdb", StyxUtils.DEFAULT_GROUP, 0755));
260 root.addChild(new StyxDirectory("jdbonly", "jdb", StyxUtils.DEFAULT_GROUP, 0700));
261 root.addChild(new StyxDirectory("adminsonly", "jim", "admins", 0750));
262
263
264 StyxServer server = new StyxServer(port, root, securityFile);
265 server.start();
266 }
267 }