View Javadoc

1   /*
2    * This file is part of AceLogger.
3    * 
4    * AceLogger is free software: you can redistribute it and/or modify it under the terms of the GNU
5    * Lesser General Public License as published by the Free Software Foundation, either version 3 of
6    * the License, or (at your option) any later version.
7    * 
8    * AceLogger is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
9    * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10   * Lesser General Public License for more details.
11   * 
12   * You should have received a copy of the GNU Lesser General Public License along with AceLogger.
13   * If not, see <http://www.gnu.org/licenses/lgpl-3.0.html>.
14   */
15  package net.sourceforge.acelogger.execution;
16  
17  import java.io.PrintWriter;
18  import java.io.StringWriter;
19  import java.text.MessageFormat;
20  import java.util.MissingResourceException;
21  import java.util.ResourceBundle;
22  
23  import net.sourceforge.acelogger.LogEvent;
24  import net.sourceforge.acelogger.Logger;
25  import net.sourceforge.acelogger.constants.FormatterConstants;
26  import net.sourceforge.acelogger.formatter.Formatter;
27  import net.sourceforge.acelogger.level.LogLevel;
28  import net.sourceforge.acelogger.location.LogEventLocation;
29  import net.sourceforge.acelogger.location.gatherer.LocationGatherer;
30  
31  // FIXME: This is such a mess, let's just re-think this.
32  /**
33   * An implementation of {@link Logger} to be used during the startup and shutdown of the framework.
34   * If other classes are used here, they shouldn't use the internal logger to report errors, so it's
35   * safer to use simple variations of these classes.
36   * 
37   * @author Zardi (https://sourceforge.net/users/daniel_zardi)
38   * @version 1.0.0
39   * @since 1.0.0
40   */
41  public class InternalLogger implements Logger {
42  
43  	private static final String IDENTIFIER = "net.sourceforge.acelogger";
44  
45  	private Formatter formatter;
46  
47  	private LocationGatherer gatherer;
48  
49  	private static class InternalFormatter implements Formatter {
50  
51  		private static final String RESOURCE_BUNDLE_NAME =
52  			"net.sourceforge.acelogger.messages.InternalLogging";
53  
54  		private static final String LOG_ENTRY_PATTERN =
55  			"{0,date,yyyy-MM-dd HH:mm:ss,SSS} [{1}] ({2}) - {3}" + FormatterConstants.NEW_LINE;
56  
57  		private ResourceBundle resolver;
58  
59  		public InternalFormatter() {
60  			resolver = ResourceBundle.getBundle(RESOURCE_BUNDLE_NAME);
61  		}
62  
63  		/** {@inheritDoc} */
64  		public String formatLogCall(LogEvent call) {
65  			String resolvedPattern = "";
66  			try {
67  				// FIXME: It hangs Here.. WTF !!!!!!! Can't we use a stream??
68  				resolvedPattern = resolver.getString(call.getMessage());
69  			} catch (NullPointerException e) {
70  				// FIXME: An error inside another one, this is so confusing. What should we do?
71  			} catch (MissingResourceException e) {
72  				// FIXME: An error inside another one, this is so confusing. What should we do?
73  			} catch (ClassCastException e) {
74  				// FIXME: An error inside another one, this is so confusing. What should we do?
75  			} catch (Throwable e) {
76  				e.printStackTrace();
77  			}
78  			String formattedMessage = MessageFormat.format(
79  					resolvedPattern, call.getMessageParameters()
80  				);
81  			StringBuilder formattedLogCall = new StringBuilder();
82  			formattedLogCall.append(MessageFormat.format(LOG_ENTRY_PATTERN, call.getCallTime(),
83  					call.getLevel(), call.getLocation().getStackTraceLikeName(), formattedMessage
84  				));
85  			if (call.getCause() != null) {
86  				StringWriter stackTraceDestination = new StringWriter();
87  				PrintWriter stackTraceWriter = new PrintWriter(stackTraceDestination);
88  				call.getCause().printStackTrace(stackTraceWriter);
89  				stackTraceWriter.flush();
90  				stackTraceWriter.close();
91  				formattedLogCall.append(stackTraceDestination.toString());
92  			}
93  			return formattedLogCall.toString();
94  		}
95  
96  		/** {@inheritDoc} */
97  		public String getIdentifier() {
98  			return IDENTIFIER;
99  		}
100 
101 	}
102 
103 	private static class InternalLocationGatherer implements LocationGatherer {
104 
105 		private static final int FRAME_SHIFT = 3;
106 
107 		/** {@inheritDoc} */
108 		public LogEventLocation getCallLocation() {
109 			return getCallLocation(Thread.currentThread());
110 		}
111 
112 		/** {@inheritDoc} */
113 		public LogEventLocation getCallLocation(Thread currentThread) {
114 			StackTraceElement[] stackTrace = currentThread.getStackTrace();
115 			int userCodeCallIndex = 0;
116 			for (int i = 0; i < stackTrace.length; i++) {
117 				String frameClassName = stackTrace[i].getClassName();
118 				if (!frameClassName.startsWith("java.util.concurrent")
119 						&& !frameClassName.startsWith("java.lang.Thread")
120 						&& !frameClassName.startsWith(InternalLogger.class.getName())
121 						&& !frameClassName.startsWith(UncaughtExceptionLogger.class.getName())) {
122 					userCodeCallIndex = i;
123 					if (i + FRAME_SHIFT < stackTrace.length) {
124 						userCodeCallIndex += FRAME_SHIFT;
125 					}
126 					break;
127 				}
128 			}
129 			StackTraceElement userCodeFrame = stackTrace[userCodeCallIndex];
130 			return new LogEventLocation(
131 					userCodeFrame.getClass().getPackage().getName(),
132 					userCodeFrame.getClassName(),
133 					userCodeFrame.getMethodName(),
134 					userCodeFrame.getFileName(),
135 					userCodeFrame.getLineNumber(),
136 					currentThread.getName()
137 				);
138 		}
139 
140 		/** {@inheritDoc} */
141 		public String getIdentifier() {
142 			return IDENTIFIER;
143 		}
144 
145 	}
146 
147 	/**
148 	 * Constructs a new internal logger.
149 	 * 
150 	 * @since 1.0.0
151 	 */
152 	public InternalLogger() {
153 		formatter = new InternalFormatter();
154 		gatherer = new InternalLocationGatherer();
155 	}
156 
157 	/** {@inheritDoc} */
158 	public void debug(String message, Object... params) {
159 		// REMARK: Intentionally left blank. This Logger does not support debug.
160 	}
161 
162 	/** {@inheritDoc} */
163 	public void debug(String message, Throwable cause, Object... params) {
164 		// REMARK: Intentionally left blank. This Logger does not support debug.
165 	}
166 
167 	/** {@inheritDoc} */
168 	public void error(String message, Object... params) {
169 		LogEvent call = new LogEvent(
170 				message, LogLevel.ERROR, gatherer.getCallLocation(), null, params);
171 		System.out.print(formatter.formatLogCall(call));
172 	}
173 
174 	/** {@inheritDoc} */
175 	public void error(String message, Throwable cause, Object... params) {
176 		LogEvent call = new LogEvent(
177 				message, LogLevel.ERROR, gatherer.getCallLocation(), cause, params);
178 		System.out.print(formatter.formatLogCall(call));
179 	}
180 
181 	/** {@inheritDoc} */
182 	public void fatal(String message, Object... params) {
183 		LogEvent call = new LogEvent(
184 				message, LogLevel.FATAL, gatherer.getCallLocation(), null, params);
185 		System.out.print(formatter.formatLogCall(call));
186 	}
187 
188 	/** {@inheritDoc} */
189 	public void fatal(String message, Throwable cause, Object... params) {
190 		LogEvent call = new LogEvent(
191 				message, LogLevel.FATAL, gatherer.getCallLocation(), cause, params);
192 		System.out.print(formatter.formatLogCall(call));
193 	}
194 
195 	/** {@inheritDoc} */
196 	public void info(String message, Object... params) {
197 		LogEvent call = new LogEvent(
198 				message, LogLevel.INFO, gatherer.getCallLocation(), null, params);
199 		System.out.print(formatter.formatLogCall(call));
200 	}
201 
202 	/** {@inheritDoc} */
203 	public void info(String message, Throwable cause, Object... params) {
204 		LogEvent call = new LogEvent(
205 				message, LogLevel.INFO, gatherer.getCallLocation(), cause, params);
206 		System.out.print(formatter.formatLogCall(call));
207 	}
208 
209 	/** {@inheritDoc} */
210 	public boolean isDebugEnabled() {
211 		return false;
212 	}
213 
214 	/** {@inheritDoc} */
215 	public boolean isErrorEnabled() {
216 		return true;
217 	}
218 
219 	/** {@inheritDoc} */
220 	public boolean isFatalEnabled() {
221 		return true;
222 	}
223 
224 	/** {@inheritDoc} */
225 	public boolean isInfoEnabled() {
226 		return true;
227 	}
228 
229 	/** {@inheritDoc} */
230 	public boolean isTraceEnabled() {
231 		return false;
232 	}
233 
234 	/** {@inheritDoc} */
235 	public boolean isWarnEnabled() {
236 		return true;
237 	}
238 
239 	/** {@inheritDoc} */
240 	public void trace(String message, Object... params) {
241 		// REMARK: Intentionally left blank. This Logger does not support trace.
242 	}
243 
244 	/** {@inheritDoc} */
245 	public void trace(String message, Throwable cause, Object... params) {
246 		// REMARK: Intentionally left blank. This Logger does not support trace.
247 	}
248 
249 	/** {@inheritDoc} */
250 	public void warn(String message, Object... params) {
251 		// TODO Auto-generated method stub
252 
253 	}
254 
255 	/** {@inheritDoc} */
256 	public void warn(String message, Throwable cause, Object... params) {
257 		// TODO Auto-generated method stub
258 
259 	}
260 
261 	/** {@inheritDoc} */
262 	public String getIdentifier() {
263 		return IDENTIFIER;
264 	}
265 
266 }