View Javadoc

1   /****************************************************************
2    * Licensed to the Apache Software Foundation (ASF) under one   *
3    * or more contributor license agreements.  See the NOTICE file *
4    * distributed with this work for additional information        *
5    * regarding copyright ownership.  The ASF licenses this file   *
6    * to you under the Apache License, Version 2.0 (the            *
7    * "License"); you may not use this file except in compliance   *
8    * with the License.  You may obtain a copy of the License at   *
9    *                                                              *
10   *   http://www.apache.org/licenses/LICENSE-2.0                 *
11   *                                                              *
12   * Unless required by applicable law or agreed to in writing,   *
13   * software distributed under the License is distributed on an  *
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
15   * KIND, either express or implied.  See the License for the    *
16   * specific language governing permissions and limitations      *
17   * under the License.                                           *
18   ****************************************************************/
19  
20  package org.apache.james.jspf.tester;
21  
22  import org.apache.commons.cli.CommandLine;
23  import org.apache.commons.cli.CommandLineParser;
24  import org.apache.commons.cli.HelpFormatter;
25  import org.apache.commons.cli.OptionBuilder;
26  import org.apache.commons.cli.Options;
27  import org.apache.commons.cli.ParseException;
28  import org.apache.commons.cli.PosixParser;
29  import org.jvyaml.Constructor;
30  import org.jvyaml.DefaultYAMLFactory;
31  import org.jvyaml.YAMLFactory;
32  import org.xbill.DNS.TextParseException;
33  
34  import java.io.BufferedReader;
35  import java.io.FileInputStream;
36  import java.io.IOException;
37  import java.io.InputStream;
38  import java.io.InputStreamReader;
39  import java.io.Reader;
40  import java.util.HashMap;
41  import java.util.Iterator;
42  import java.util.Locale;
43  import java.util.Set;
44  
45  /**
46   * Run a fake dnsserver listening both TCP and UDP ports.
47   * 
48   * Mandatory parameters are -f (yaml zone definition) and -t (test name).
49   * if testname is "ALL" then all of the zones in the file are merged in a single
50   * zone and loaded.
51   * 
52   * e.g: DNSTestingServerLauncher -f rfc4408-tests.yml -t ALL
53   * 
54   * by default listen to port 53 of every interface, but ip and port can be updated.
55   */
56  public class DNSTestingServerLauncher {
57  
58      private static final char CHAR_TESTNAME = 't';
59  
60      private static final char CHAR_FILE = 'f';
61  
62      private static final char CHAR_PORT = 'p';
63  
64      private static final char CHAR_IP = 'i';
65  
66      private final static String CMD_IP = "ip";
67  
68      private final static String CMD_PORT = "port";
69  
70      private final static String CMD_FILE = "file";
71  
72      private final static String CMD_TESTNAME = "test";
73  
74      /**
75       * @param args
76       */
77      public static void main(String[] args) {
78          String ip = null;
79          String port = null;
80          String file = null;
81          String test = null;
82          
83          Options options = generateOptions();
84          CommandLineParser parser = new PosixParser();
85  
86          try {
87              CommandLine line = parser.parse(options, args);
88              
89              ip = line.getOptionValue(CHAR_IP);
90              port = line.getOptionValue(CHAR_PORT);
91              file = line.getOptionValue(CHAR_FILE);
92              test = line.getOptionValue(CHAR_TESTNAME);
93              
94              if (ip == null) ip = "0.0.0.0";
95              if (port == null) port = "53";
96              
97              if (file != null && test != null) {
98                  
99                  InputStream is = new FileInputStream(file);
100                 
101                 if (is != null) {
102                     Reader br = new BufferedReader(new InputStreamReader(is));
103                     YAMLFactory fact = new DefaultYAMLFactory();
104                     
105                     Constructor ctor = fact.createConstructor(fact.createComposer(fact.createParser(fact.createScanner(br)),fact.createResolver()));
106                     boolean found = false;
107                     HashMap zonedata = new HashMap();
108                     HashMap testMap = null;
109                     while(ctor.checkData() && !found) {
110                         Object o = ctor.getData();
111                         if (o instanceof HashMap) {
112                           testMap = (HashMap) o;
113                           if (test.equals(testMap.get("description")) || "ALL".equalsIgnoreCase(test)) {
114                               found = true;
115                               loadZoneData(testMap, zonedata);
116                           }
117                         }
118                     }
119                     if (found) {
120                         DNSTestingServer testingServer = new DNSTestingServer(ip, port);
121                         testingServer.setData(zonedata);
122                         
123                         System.out.println("Listening on "+ip+":"+port);
124                         
125                         while (true) {
126                             try {
127                                 Thread.sleep(1000);
128                             } catch (InterruptedException e) {
129                                 // TODO Auto-generated catch block
130                             }
131                         }
132                         
133                     } else {
134                         throw new RuntimeException("Unable to find a <"+test+"> section in the passed file.");
135                     }
136                 } else {
137                     throw new RuntimeException("Unable to load the file: "+file);
138                 }
139 
140                 
141             } else {
142                 System.out.println("Missing required parameter.");
143                 usage();
144             }
145         } catch (ParseException e) {
146             usage();
147         } catch (RuntimeException e) {
148             System.out.println("Error: "+e.getMessage());
149             e.printStackTrace();
150             usage();
151         } catch (TextParseException e) {
152             System.out.println("Parsing Error: "+e.getMessage());
153             e.printStackTrace();
154             usage();
155         } catch (IOException e) {
156             System.out.println("IO Error: "+e.getMessage());
157             e.printStackTrace();
158             usage();
159         }
160 
161     }
162 
163     private static void loadZoneData(HashMap testMap, HashMap zonedata) {
164         HashMap loadedZoneData = (HashMap) testMap.get("zonedata");
165         Set keys = loadedZoneData.keySet();
166         for (Iterator i = keys.iterator(); i.hasNext(); ) {
167             String hostname = (String) i.next();
168             String lowercase = hostname.toLowerCase(Locale.US);
169             if (zonedata.containsKey(lowercase)) {
170                 System.err.println("Replace zone entry for "+lowercase+" to "+loadedZoneData.get(hostname));
171             }
172             zonedata.put(lowercase, loadedZoneData.get(hostname));
173         }
174     }
175 
176     /**
177      * Print out the usage
178      */
179     private static void usage() {
180         HelpFormatter hf = new HelpFormatter();
181         hf.printHelp("DNSTestingServerLauncher", generateOptions(), true);
182         System.exit(255);
183     }
184 
185     /**
186      * Return the generated Options
187      * 
188      * @return options
189      */
190     private static Options generateOptions() {
191         Options options = new Options();
192         options.addOption(OptionBuilder
193                 .withLongOpt(CMD_IP)
194                 .withValueSeparator('=')
195                 .hasArg()
196                 .withArgName("ip")
197                 .withDescription("Listening IP (default: 0.0.0.0 for every IP)")
198                 .create(CHAR_IP));
199         options.addOption(OptionBuilder
200                 .withLongOpt(CMD_PORT)
201                 .withValueSeparator('=')
202                 .hasArg()
203                 .withArgName("port")
204                 .withDescription("Listening port (default: 53)")
205                 .create(CHAR_PORT));
206         options.addOption(OptionBuilder
207                 .withLongOpt(CMD_FILE)
208                 .withValueSeparator('=')
209                 .withDescription("YML file name")
210                 .withArgName("file")
211                 .isRequired()
212                 .hasArg()
213                 .create(CHAR_FILE));
214         options.addOption(OptionBuilder
215                 .withLongOpt(CMD_TESTNAME)
216                 .withValueSeparator('=')
217                 .hasArg()
218                 .withDescription("Test name")
219                 .withArgName("test")
220                 .isRequired()
221                 .create(CHAR_TESTNAME));
222         return options;
223     }
224 
225 }