1/*
2 * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/*
25 */
26
27import java.io.*;
28import java.net.*;
29import java.rmi.*;
30import java.rmi.server.*;
31import java.util.zip.*;
32
33
34public class MultiSocketFactory  {
35
36    private static RMISocketFactory def =
37        RMISocketFactory.getDefaultSocketFactory();
38
39
40    public static class ServerFactory
41        implements RMIServerSocketFactory, Serializable
42    {
43
44        private String protocol;
45        private byte[] data;
46
47        public ServerFactory(String protocol, byte[] data) {
48            this.protocol = protocol;
49            this.data = data;
50        }
51
52        public ServerSocket createServerSocket(int port) throws IOException
53        {
54            if (protocol.equals("compress")) {
55                return new CompressServerSocket(port);
56
57            } else if (protocol.equals("xor")) {
58                if (data == null || data.length != 1)
59                    throw new IOException("invalid argument for XOR protocol");
60                return new XorServerSocket(port, data[0]);
61
62            }
63
64            return def.createServerSocket(port);
65        }
66    }
67
68    public static class ClientFactory
69        implements RMIClientSocketFactory, Serializable
70    {
71
72        private String protocol;
73        private byte[] data;
74
75        public ClientFactory(String protocol, byte[] data) {
76            this.protocol = protocol;
77            this.data = data;
78        }
79
80        public Socket createSocket(String host, int port)
81            throws IOException
82        {
83            if (protocol.equals("compress")) {
84                return new CompressSocket(host, port);
85
86            } else if (protocol.equals("xor")) {
87                if (data == null || data.length != 1)
88                    throw new IOException("invalid argument for XOR protocol");
89                return new XorSocket(host, port, data[0]);
90
91            }
92
93            return def.createSocket(host, port);
94        }
95    }
96
97    static class CompressSocket extends Socket {
98        private InputStream in;
99        private OutputStream out;
100        public CompressSocket() { super(); }
101        public CompressSocket(String host, int port) throws IOException {
102            super(host, port);
103        }
104        public InputStream getInputStream() throws IOException {
105            if (in == null) {
106                in = new CompressInputStream(super.getInputStream());
107            }
108            return in;
109        }
110        public OutputStream getOutputStream() throws IOException {
111            if (out == null) {
112                out = new CompressOutputStream(super.getOutputStream());
113            }
114            return out;
115        }
116    }
117
118    static class CompressServerSocket extends ServerSocket {
119        public CompressServerSocket(int port) throws IOException {
120            super(port);
121        }
122        public Socket accept() throws IOException {
123            Socket s = new CompressSocket();
124            implAccept(s);
125            return s;
126        }
127    }
128
129    static class XorSocket extends Socket {
130        private byte pattern;
131        private InputStream in;
132        private OutputStream out;
133        public XorSocket(byte pattern) { super(); this.pattern = pattern; }
134        public XorSocket(String host, int port, byte pattern)
135            throws IOException
136        {
137            super(host, port);
138            this.pattern = pattern;
139        }
140        public InputStream getInputStream() throws IOException {
141            if (in == null) {
142                in = new XorInputStream(super.getInputStream(), pattern);
143            }
144            return in;
145        }
146        public OutputStream getOutputStream() throws IOException {
147            if (out == null) {
148                out = new XorOutputStream(super.getOutputStream(), pattern);
149            }
150            return out;
151        }
152    }
153
154    static class XorServerSocket extends ServerSocket {
155        private byte pattern;
156        public XorServerSocket(int port, byte pattern) throws IOException {
157            super(port);
158            this.pattern = pattern;
159        }
160        public Socket accept() throws IOException {
161            Socket s = new XorSocket(pattern);
162            implAccept(s);
163            return s;
164        }
165    }
166
167    static class XorOutputStream extends FilterOutputStream {
168        private byte pattern;
169        public XorOutputStream(OutputStream out, byte pattern) {
170            super(out);
171            this.pattern = pattern;
172        }
173        public void write(int b) throws IOException {
174            out.write(b ^ pattern);
175            out.flush();
176        }
177        public void write(byte b[], int off, int len) throws IOException {
178            for (int i = 0; i < len; i++)
179                write(b[off + i]);
180        }
181    }
182
183    static class XorInputStream extends FilterInputStream {
184        private byte pattern;
185        public XorInputStream(InputStream in, byte pattern) {
186            super(in);
187            this.pattern = pattern;
188        }
189        public int read() throws IOException {
190            int b = in.read();
191//          System.out.print("BEFORE: " + Integer.toHexString(b));
192            if (b != -1)
193                b = (b ^ pattern) & 0xFF;
194//          System.out.println("\tAFTER: " + Integer.toHexString(b));
195            return b;
196        }
197        public int read(byte b[], int off, int len) throws IOException {
198            if (len <= 0) {
199                return 0;
200            }
201
202            int c = read();
203            if (c == -1) {
204                return -1;
205            }
206            b[off] = (byte)c;
207
208            int i = 1;
209/*****
210            try {
211                for (; i < len ; i++) {
212                    c = read();
213                    if (c == -1) {
214                        break;
215                    }
216                    if (b != null) {
217                        b[off + i] = (byte)c;
218                    }
219                }
220            } catch (IOException ee) {
221            }
222*****/
223            return i;
224        }
225    }
226}
227