1
+ /*
2
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
3
+ * The Universal Permissive License (UPL), Version 1.0
4
+ */
5
+ package oracle .weblogic .deploy .logging ;
6
+
7
+ import java .util .ArrayList ;
8
+ import java .util .List ;
9
+ import java .util .Properties ;
10
+ import java .util .logging .ConsoleHandler ;
11
+ import java .util .logging .Formatter ;
12
+ import java .util .logging .Handler ;
13
+ import java .util .logging .Level ;
14
+ import java .util .logging .LogManager ;
15
+ import java .util .logging .LogRecord ;
16
+ import java .util .logging .MemoryHandler ;
17
+
18
+ import oracle .weblogic .deploy .util .WLSDeployContext ;
19
+ import oracle .weblogic .deploy .util .WLSDeployExit ;
20
+
21
+
22
+ /**
23
+ * This class save the log records logged by the tool at Info level or greater. The WLSDeployExit exit method will
24
+ * call this Handler to publish the messages, along with the total of the log records, by Level category.
25
+ *
26
+ * The WLSDeployCustomizeLoggingConfig adds the properties from this class' getHandlerProperties() to the
27
+ * log manager logger properties and adds the handler to the root WLSDEPLOY Logger. See the class for information
28
+ * on how to inject this handler into the wlsdeploy root logger.
29
+ *
30
+ * Before the tool exit, if specified by the caller, an activity summary of the saved logs is displayed to the console.
31
+ * A final total of the records logged by the tool for the Level categories indicated above is displayed to the console.
32
+ *
33
+ * @see WLSDeployCustomizeLoggingConfig
34
+ * @see oracle.weblogic.deploy.util.WLSDeployExit
35
+ */
36
+ public class SummaryHandler extends Handler implements WLSDeployLogEndHandler {
37
+ private static final String CLASS = SummaryHandler .class .getName ();
38
+ private static final String LEVEL_PROPERTY = "level" ;
39
+ private static final String TARGET_PROPERTY = "target" ;
40
+ private static final String FORMATTER_PROPERTY = "formatter" ;
41
+ private static final String SIZE_PROPERTY = "size" ;
42
+ private static final int DEFAULT_SIZE = 3000 ;
43
+
44
+ private PlatformLogger LOGGER = WLSDeployLogFactory .getLogger ("wlsdeploy.exit" );
45
+ private int bufferSize ;
46
+ private WLSDeployContext context ;
47
+
48
+ private Handler topTarget ;
49
+ private List <LevelHandler > handlers = new ArrayList <>();
50
+ private boolean closed = false ;
51
+
52
+ /**
53
+ * This default constructor is populated with the handler properties loaded by the WLSDeployCustomizeLoggingConfig.
54
+ */
55
+ public SummaryHandler () {
56
+ super ();
57
+ configure ();
58
+
59
+ LOGGER .setLevel (Level .INFO );
60
+ addLevelHandler (Level .WARNING );
61
+ addLevelHandler (Level .SEVERE );
62
+ }
63
+
64
+ /**
65
+ * Tally and save the log record if it matches one of the category Level handlers. Once the summary has completed,
66
+ * all further log records will be ignored.
67
+ *
68
+ * @param record to tally and save in handler with matching Level category
69
+ */
70
+ @ Override
71
+ public synchronized void publish (LogRecord record ) {
72
+ // after close, take yourself out of the mix. The stored up log messages are going to go to the
73
+ // console handler anyway
74
+ if (!closed ) {
75
+ for (Handler handler : handlers ) {
76
+ handler .publish (record );
77
+ }
78
+ }
79
+ }
80
+
81
+ @ Override
82
+ public void flush () {
83
+ topTarget .flush ();
84
+ }
85
+
86
+ @ Override
87
+ public void close () throws SecurityException {
88
+ topTarget .close ();
89
+ }
90
+
91
+ /**
92
+ * This method is called by the tool to complete the SummaryHandler, and display the recap and total information
93
+ * to the console. The log records are only displayed to the console if the tool was run in online mode.
94
+ * This compensates for wlst writing spurious blank lines to the console during online mode.
95
+ *
96
+ * @param modelContext contextual information about the tool
97
+ */
98
+ @ Override
99
+ public synchronized void logEnd (WLSDeployContext modelContext ) {
100
+ closed = true ;
101
+ String METHOD = "push" ;
102
+ LOGGER .entering (modelContext , CLASS , METHOD );
103
+ this .context = modelContext ;
104
+ summaryHead (topTarget );
105
+ for (LevelHandler handler : handlers ) {
106
+ handler .push ();
107
+ }
108
+ summaryTail (topTarget );
109
+ LOGGER .exiting (CLASS , METHOD );
110
+ }
111
+
112
+ /**
113
+ * The WLSDeployLoggingConfig will call this method to add to the logging.properties files.
114
+ * If the logging.properties already contains the property, the property in this list will be ignored.
115
+ *
116
+ * @return properties to set in logging.properties
117
+ */
118
+ public static Properties getHandlerProperties () {
119
+ Properties properties = new Properties ();
120
+ properties .setProperty (LEVEL_PROPERTY , Level .INFO .getName ());
121
+ properties .setProperty (TARGET_PROPERTY , WLSDeployLoggingConsoleHandler .class .getName ());
122
+ properties .setProperty (FORMATTER_PROPERTY , WLSDeployLogFormatter .class .getName ());
123
+ return properties ;
124
+ }
125
+
126
+ private void addLevelHandler (Level level ) {
127
+ LevelHandler handler ;
128
+ Handler levelTarget = getConsoleHandler ();
129
+ levelTarget .setFormatter (new SummaryFormatter (level ));
130
+ handler = new LevelHandler (levelTarget , bufferSize , level );
131
+ handler .setLevel (level );
132
+ handler .setFilter (getFilter ());
133
+ handlers .add (handler );
134
+ }
135
+
136
+ void summaryHead (Handler handler ) {
137
+ handler .publish (getLogRecord ("WLSDPLY-21003" , context .getProgramName (),
138
+ context .getVersion (), context .getWlstMode ()));
139
+ }
140
+
141
+ void summaryTail (Handler handler ) {
142
+ StringBuffer buffer = new StringBuffer ();
143
+ java .util .Formatter fmt = new java .util .Formatter (buffer );
144
+ for (LevelHandler levelHandler : handlers ) {
145
+ if (levelHandler .getTotalRecords () >= 0 ) {
146
+ fmt .format (" %1$s : %2$,5d" , levelHandler .getLevel ().getName (), levelHandler .getTotalRecords ());
147
+ }
148
+ }
149
+ handler .publish (getLogRecord ("WLSDPLY-21002" , buffer ));
150
+ }
151
+
152
+ private class TotalFormatter extends Formatter {
153
+
154
+ @ Override
155
+ public synchronized String format (LogRecord record ) {
156
+ return System .lineSeparator () + formatMessage (record ) + System .lineSeparator ();
157
+ }
158
+
159
+ }
160
+
161
+ private class SummaryFormatter extends Formatter {
162
+
163
+ private final String MSG_FORMAT = " %1$5d. %2$s: %3$s" + System .lineSeparator ();
164
+ private final String INTERNAL = System .lineSeparator () + "%s" + System .lineSeparator () + System .lineSeparator ();
165
+ private int sequence = 0 ;
166
+ private Level level ;
167
+
168
+ public SummaryFormatter (Level level ) {
169
+ this .level = level ;
170
+ }
171
+
172
+ @ Override
173
+ public synchronized String format (LogRecord record ) {
174
+ String message = "" ;
175
+ String msgId = record .getMessage ();
176
+ if (msgId .indexOf ('{' ) >= 0 ) {
177
+ msgId = null ;
178
+ }
179
+ String formatted = formatMessage (record );
180
+ if (msgId != null && !msgId .equals (formatted )) {
181
+ // this has a msg id. don't post any that don't have msg id.
182
+ message = String .format (MSG_FORMAT , ++sequence , msgId , formatted );
183
+ }
184
+ return message ;
185
+ }
186
+
187
+ @ Override
188
+ public String getHead (Handler handler ) {
189
+ return String .format (INTERNAL , formatMessage (getLogRecord ("WLSDPLY-21000" , level .getLocalizedName ())));
190
+ }
191
+ }
192
+
193
+ private class LevelHandler extends MemoryHandler {
194
+
195
+ private int totalRecords ;
196
+
197
+ LevelHandler (Handler handler , int size , Level level ) {
198
+ super (handler , size , Level .OFF );
199
+ setLevel (level );
200
+ }
201
+
202
+ @ Override
203
+ public synchronized void publish (LogRecord record ) {
204
+ if (record .getLevel ().intValue () == getLevel ().intValue ()) {
205
+ ++totalRecords ;
206
+ super .publish (record );
207
+ }
208
+ }
209
+
210
+ int getTotalRecords () {
211
+ return totalRecords ;
212
+ }
213
+
214
+ }
215
+
216
+ private void configure () {
217
+ LogManager manager = LogManager .getLogManager ();
218
+ topTarget = getConsoleHandler ();
219
+ topTarget .setFormatter (new TotalFormatter ());
220
+ bufferSize = getSize (manager .getProperty (getClass ().getName () + "." + SIZE_PROPERTY ));
221
+ }
222
+
223
+ private int getSize (String propSize ) {
224
+ Integer handlerSize ;
225
+ try {
226
+ handlerSize = new Integer (propSize );
227
+ } catch (NumberFormatException nfe ) {
228
+ handlerSize = DEFAULT_SIZE ;
229
+ }
230
+ return handlerSize ;
231
+ }
232
+
233
+ private ConsoleHandler getConsoleHandler () {
234
+ ConsoleHandler handler = null ;
235
+ try {
236
+ handler = (ConsoleHandler ) Class .forName (WLSDeployLoggingConfig .getConsoleHandler ()).newInstance ();
237
+ } catch (ClassNotFoundException | IllegalAccessException cne ) {
238
+ System .out .println ("Class not found " + WLSDeployLoggingConfig .getConsoleHandler ());
239
+ } catch (InstantiationException ie ) {
240
+ handler = new ConsoleHandler ();
241
+ }
242
+ return handler ;
243
+ }
244
+
245
+
246
+ private LogRecord getLogRecord (String msg , Object ... params ) {
247
+ LogRecord record = new LogRecord (Level .INFO , msg );
248
+ record .setLoggerName (LOGGER .getName ());
249
+ if (params != null && params .length != 0 ) {
250
+ record .setParameters (params );
251
+ }
252
+ record .setSourceClassName (CLASS );
253
+ record .setSourceMethodName ("" );
254
+ record .setResourceBundle (LOGGER .getUnderlyingLogger ().getResourceBundle ());
255
+ return record ;
256
+ }
257
+
258
+ }
0 commit comments