View Javadoc

1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * 
4    * Copyright (C) 1999-2006, QOS.ch
5    * 
6    * This library is free software, you can redistribute it and/or modify it under
7    * the terms of the GNU Lesser General Public License as published by the Free
8    * Software Foundation.
9    */
10  
11  package chapter7;
12  
13  import java.rmi.RemoteException;
14  import java.rmi.registry.LocateRegistry;
15  import java.rmi.registry.Registry;
16  import java.rmi.server.UnicastRemoteObject;
17  import java.util.Vector;
18  
19  import org.slf4j.Logger;
20  import org.slf4j.LoggerFactory;
21  import org.slf4j.MDC;
22  
23  import ch.qos.logback.classic.LoggerContext;
24  import ch.qos.logback.classic.joran.JoranConfigurator;
25  import ch.qos.logback.core.joran.spi.JoranException;
26  
27  
28  /**
29   * A simple NumberCruncher implementation that logs its progress when
30   * factoring numbers. The purpose of the whole exercise is to show the
31   * use of mapped diagnostic contexts in order to distinguish the log
32   * output from different client requests.
33   * */
34  public class NumberCruncherServer extends UnicastRemoteObject
35    implements NumberCruncher {
36  
37    private static final long serialVersionUID = 1L;
38  
39    static Logger logger = LoggerFactory.getLogger(NumberCruncherServer.class);
40  
41    public NumberCruncherServer() throws RemoteException {
42    }
43  
44    public int[] factor(int number) throws RemoteException {
45      // The client's host is an important source of information.
46      try {
47        MDC.put("client", NumberCruncherServer.getClientHost());
48      } catch (java.rmi.server.ServerNotActiveException e) {
49        logger.warn("Caught unexpected ServerNotActiveException.", e);
50      }
51  
52      // The information contained within the request is another source
53      // of distinctive information. It might reveal the users name,
54      // date of request, request ID etc. In servlet type environments,
55      // useful information is contained in the HttpRequest or in the  
56      // HttpSession.
57      MDC.put("number", String.valueOf(number));
58  
59      logger.info("Beginning to factor.");
60  
61      if (number <= 0) {
62        throw new IllegalArgumentException(number +
63          " is not a positive integer.");
64      } else if (number == 1) {
65        return new int[] { 1 };
66      }
67  
68      Vector<Integer> factors = new Vector<Integer>();
69      int n = number;
70  
71      for (int i = 2; (i <= n) && ((i * i) <= number); i++) {
72        // It is bad practice to place log requests within tight loops.
73        // It is done here to show interleaved log output from
74        // different requests. 
75        logger.debug("Trying " + i + " as a factor.");
76  
77        if ((n % i) == 0) {
78          logger.info("Found factor " + i);
79          factors.addElement(new Integer(i));
80  
81          do {
82            n /= i;
83          } while ((n % i) == 0);
84        }
85  
86        // Placing artificial delays in tight-loops will also lead to
87        // sub-optimal resuts. :-)
88        delay(100);
89      }
90  
91      if (n != 1) {
92        logger.info("Found factor " + n);
93        factors.addElement(new Integer(n));
94      }
95  
96      int len = factors.size();
97  
98      int[] result = new int[len];
99  
100     for (int i = 0; i < len; i++) {
101       result[i] = ((Integer) factors.elementAt(i)).intValue();
102     }
103 
104     // clean up
105     MDC.remove("client");
106     MDC.remove("number");
107 
108     return result;
109   }
110 
111   static void usage(String msg) {
112     System.err.println(msg);
113     System.err.println("Usage: java chapter7.NumberCruncherServer configFile\n" +
114       "   where configFile is a logback configuration file.");
115     System.exit(1);
116   }
117 
118   public static void delay(int millis) {
119     try {
120       Thread.sleep(millis);
121     } catch (InterruptedException e) {
122     }
123   }
124 
125   public static void main(String[] args) {
126     if (args.length != 1) {
127       usage("Wrong number of arguments.");
128     }
129 
130     String configFile = args[0];
131 
132     if (configFile.endsWith(".xml")) {
133       try {
134         LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
135         JoranConfigurator configurator = new JoranConfigurator();
136         configurator.setContext(lc);
137         lc.shutdownAndReset();
138         configurator.doConfigure(args[0]);
139       } catch (JoranException je) {
140         je.printStackTrace();
141       }
142     }
143 
144     NumberCruncherServer ncs;
145 
146     try {
147       ncs = new NumberCruncherServer();
148       logger.info("Creating registry.");
149 
150       Registry registry = LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
151       registry.rebind("Factor", ncs);
152       logger.info("NumberCruncherServer bound and ready.");
153     } catch (Exception e) {
154       logger.error("Could not bind NumberCruncherServer.", e);
155 
156       return;
157     }
158   }
159 }