001: package Shared.Logging.Internal;
002:
003: import java.io.*;
004: import java.io.PrintStream;
005: import java.net.Socket;
006:
007: //import java.security.*;
008: //import java.security.spec.*;
009: //import java.security.interfaces.*;
010:
011: import javax.crypto.*;
012: import javax.crypto.spec.*;
013: import javax.crypto.interfaces.*; //import com.sun.crypto.provider.SunJCE;
014:
015: import Shared.Logging.Log;
016:
017: /**
018: * This logger sends the log text over a tcp/ip socket
019: * to the internet.
020: * On the server side, run the SocketLogReceiver, which
021: * saves the received log texts to disk using by passing
022: * it to a file logger.
023: *
024: * Uses a symmetric key for MD5AndDES encryption of the send data.
025: *
026: */
027: public class SocketLogger extends GenericLogger {
028:
029: private int socketTimeout = 4000; // 4 second timeout
030:
031: private Socket socket;
032: private DataOutputStream dataOutputStream = null;
033:
034: private boolean connectionWorks = true; // this is reported on the first log call
035:
036: private Cipher encriptingCipher;
037:
038: public SocketLogger(String logIdentifier, String host, int port) {
039: super (logIdentifier);
040: try {
041: this .encriptingCipher = CypherFactory
042: .CreatePasswordBasedCipher(Cipher.ENCRYPT_MODE);
043: this .socket = new Socket(host, port);
044: this .socket.setSoTimeout(this .socketTimeout);
045: this .socket.setTcpNoDelay(true);
046: OutputStream os = this .socket.getOutputStream();
047: this .dataOutputStream = new DataOutputStream(os);
048: // Now encrypt and send the identification data:
049: this .encryptAndSendData(Log.SocketLoggerIdentification);
050: } catch (Exception e) {
051: this .connectionWorks = false; // deactivate it
052: System.out
053: .println("SocketLogger could not be initialized.");
054: System.out
055: .println("SocketLogger is deactivated therefore. Exception is:");
056: e.printStackTrace(System.out);
057: System.out.flush();
058: }
059: }
060:
061: /**
062: * Writes the log text to System.out.
063: */
064: public synchronized void publish(String levelName, String message) {
065: if (this .connectionWorks) {
066: try {
067: this .encryptAndSendData(super .getLogText(levelName,
068: message));
069: } catch (Exception e) {
070: this .connectionWorks = false; // stop output of this logger
071: // Use other loggers for information:
072: Log
073: .Error("SocketLogger: Unable to send log information. Reason:");
074: Log.Error(e);
075: Log.Error("SocketLogger has been deactivated.");
076: }
077: } // else: nothing as it was reported once on the first detection of a problem
078: }
079:
080: /**
081: * Writes the stacktrace to System.out.
082: */
083: public synchronized void publish(String levelName,
084: Throwable throwable) {
085: if (this .connectionWorks) {
086: try {
087: this .encryptAndSendData(super .getThrowableText(
088: levelName, throwable));
089: } catch (Exception e) {
090: this .connectionWorks = false; // stop further output of this logger
091: // Use other loggers for information:
092: Log
093: .Error("SocketLogger: Unable to send log information. Reason:");
094: Log.Error(e);
095: Log.Error("SocketLogger has been deactivated.");
096: }
097: } // else: nothing as it was reported once on the first detection of a problem
098: }
099:
100: /**
101: * This one just logs the message directly without any formatting.
102: */
103: public void publishDirectly(String message) {
104: if (this .connectionWorks) {
105: try {
106: this .encryptAndSendData(message);
107: } catch (Exception e) {
108: this .connectionWorks = false; // stop output of this logger
109: // Use other loggers for information:
110: Log
111: .Error("SocketLogger: Unable to send log information. Reason:");
112: Log.Error(e);
113: Log.Error("SocketLogger has been deactivated.");
114: }
115: } // else: nothing as it was reported once on the first detection of a problem
116: }
117:
118: /**
119: * Encrypts the passed text and sends it.
120: */
121: private void encryptAndSendData(String text) {
122: try {
123: byte[] clearText = text.getBytes("UTF-8");
124: byte[] cipherText = this .encriptingCipher
125: .doFinal(clearText);
126: // The receiver has to know exactly how many bytes to read,
127: // until the received content can be decrypted, so write the
128: // number of the following bytes first:
129:
130: System.out
131: .println("encryptAndSendData: cipherText.length= "
132: + cipherText.length);
133:
134: this .dataOutputStream.writeInt(cipherText.length);
135: // followed by the bytes:
136: for (int i = 0; i < cipherText.length; i++) {
137: this .dataOutputStream.writeByte(cipherText[i]);
138: }
139: // and flush:
140: this .dataOutputStream.flush();
141: } catch (Exception e) {
142: this .connectionWorks = false; // stop further output of this logger
143: // Use other loggers for information:
144: Log.Error("Unable to send log information. Reason:");
145: Log.Error(e);
146: Log.Error("SocketLogger has been deactivated.");
147: }
148: }
149:
150: /**
151: * This is called by the Logs shutdown hook.
152: * The logger must close any open streams and if required
153: * do further cleanup. The JVM will shutdown short time
154: * after this call.
155: */
156: public void terminate() {
157: // no action required for this logger.
158: }
159:
160: } // SocketLogger
|