1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 package org.jomc.cli.commands;
32
33 import java.util.List;
34 import java.util.Locale;
35 import java.util.concurrent.CopyOnWriteArrayList;
36 import java.util.concurrent.ExecutorService;
37 import java.util.concurrent.Executors;
38 import java.util.concurrent.ThreadFactory;
39 import java.util.concurrent.atomic.AtomicInteger;
40 import java.util.logging.Level;
41 import org.apache.commons.cli.CommandLine;
42 import org.jomc.cli.Command;
43
44
45
46
47
48
49 public abstract class AbstractCommand implements Command
50 {
51
52
53
54
55 private static volatile Level defaultLogLevel;
56
57
58
59
60 private volatile Level logLevel;
61
62
63
64
65 private volatile List<Listener> listeners = new CopyOnWriteArrayList<Listener>();
66
67
68
69
70
71
72 private volatile ExecutorService executorService;
73
74
75
76
77 public AbstractCommand()
78 {
79 super();
80 }
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95 public static Level getDefaultLogLevel()
96 {
97 if ( defaultLogLevel == null )
98 {
99 defaultLogLevel = Level.parse( System.getProperty(
100 "org.jomc.cli.commands.AbstractCommand.defaultLogLevel", Level.WARNING.getName() ) );
101
102 }
103
104 return defaultLogLevel;
105 }
106
107
108
109
110
111
112
113
114 public static void setDefaultLogLevel( final Level value )
115 {
116 defaultLogLevel = value;
117 }
118
119
120
121
122
123
124
125
126
127
128 public final Level getLogLevel()
129 {
130 if ( this.logLevel == null )
131 {
132 this.logLevel = getDefaultLogLevel();
133
134 if ( this.isLoggable( Level.CONFIG ) )
135 {
136 this.log( Level.CONFIG, Messages.getMessage( "defaultLogLevelInfo", this.logLevel.getLocalizedName() ),
137 null );
138
139 }
140 }
141
142 return this.logLevel;
143 }
144
145
146
147
148
149
150
151
152
153 public final void setLogLevel( final Level value )
154 {
155 this.logLevel = value;
156 }
157
158
159
160
161
162
163
164
165
166
167
168
169
170 public final List<Listener> getListeners()
171 {
172 return this.listeners;
173 }
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188 protected boolean isLoggable( final Level level )
189 {
190 if ( level == null )
191 {
192 throw new NullPointerException( "level" );
193 }
194
195 return level.intValue() >= this.getLogLevel().intValue();
196 }
197
198
199
200
201
202
203
204
205
206
207
208
209
210 protected void log( final Level level, final String message, final Throwable throwable )
211 {
212 if ( level == null )
213 {
214 throw new NullPointerException( "level" );
215 }
216
217 if ( this.isLoggable( level ) )
218 {
219 for ( final Listener l : this.getListeners() )
220 {
221 l.onLog( level, message, throwable );
222 }
223 }
224 }
225
226 @Override
227 public org.apache.commons.cli.Options getOptions()
228 {
229 final org.apache.commons.cli.Options options = new org.apache.commons.cli.Options();
230 options.addOption( Options.THREADS_OPTION );
231 return options;
232 }
233
234
235
236
237
238
239
240
241
242
243 protected final ExecutorService getExecutorService( final CommandLine commandLine )
244 {
245 if ( this.executorService == null )
246 {
247 final String formular =
248 commandLine.hasOption( Options.THREADS_OPTION.getOpt() )
249 ? commandLine.getOptionValue( Options.THREADS_OPTION.getOpt() ).toLowerCase( new Locale( "" ) )
250 : "1.0c";
251
252 final Double parallelism =
253 formular.contains( "c" )
254 ? Double.valueOf( formular.replace( "c", "" ) ) * Runtime.getRuntime().availableProcessors()
255 : Double.valueOf( formular );
256
257 if ( parallelism.intValue() > 1 )
258 {
259 this.executorService = Executors.newFixedThreadPool(
260 parallelism.intValue(), new ThreadFactory()
261 {
262
263 private final ThreadGroup group;
264
265 private final AtomicInteger threadNumber = new AtomicInteger( 1 );
266
267
268 {
269 final SecurityManager s = System.getSecurityManager();
270 this.group = s != null
271 ? s.getThreadGroup()
272 : Thread.currentThread().getThreadGroup();
273
274 }
275
276 @Override
277 public Thread newThread( final Runnable r )
278 {
279 final Thread t =
280 new Thread( this.group, r, "jomc-cli-" + this.threadNumber.getAndIncrement(), 0 );
281
282 if ( t.isDaemon() )
283 {
284 t.setDaemon( false );
285 }
286 if ( t.getPriority() != Thread.NORM_PRIORITY )
287 {
288 t.setPriority( Thread.NORM_PRIORITY );
289 }
290
291 return t;
292 }
293
294 } );
295 }
296 }
297
298 return this.executorService;
299 }
300
301 @Override
302 public final int execute( final CommandLine commandLine )
303 {
304 if ( commandLine == null )
305 {
306 throw new NullPointerException( "commandLine" );
307 }
308
309 int status = STATUS_FAILURE;
310
311 try
312 {
313 if ( this.isLoggable( Level.INFO ) )
314 {
315 this.log( Level.INFO, Messages.getMessage( "separator" ), null );
316 this.log( Level.INFO, Messages.getMessage( "applicationTitle" ), null );
317 this.log( Level.INFO, Messages.getMessage( "separator" ), null );
318 this.log( Level.INFO, Messages.getMessage( "commandInfo", this.getName() ), null );
319 }
320
321 this.preExecuteCommand( commandLine );
322 this.executeCommand( commandLine );
323 status = STATUS_SUCCESS;
324 }
325 catch ( final Throwable t )
326 {
327 this.log( Level.SEVERE, null, t );
328 status = STATUS_FAILURE;
329 }
330 finally
331 {
332 try
333 {
334 this.postExecuteCommand( commandLine );
335 }
336 catch ( final Throwable t )
337 {
338 this.log( Level.SEVERE, null, t );
339 status = STATUS_FAILURE;
340 }
341 finally
342 {
343 if ( this.executorService != null )
344 {
345 this.executorService.shutdown();
346 this.executorService = null;
347 }
348 }
349 }
350
351 if ( this.isLoggable( Level.INFO ) )
352 {
353 if ( status == STATUS_SUCCESS )
354 {
355 this.log( Level.INFO, Messages.getMessage( "commandSuccess", this.getName() ), null );
356 }
357 else if ( status == STATUS_FAILURE )
358 {
359 this.log( Level.INFO, Messages.getMessage( "commandFailure", this.getName() ), null );
360 }
361
362 this.log( Level.INFO, Messages.getMessage( "separator" ), null );
363 }
364
365 return status;
366 }
367
368
369
370
371
372
373
374
375
376
377
378 protected void preExecuteCommand( final CommandLine commandLine ) throws CommandExecutionException
379 {
380 if ( commandLine == null )
381 {
382 throw new NullPointerException( "commandLine" );
383 }
384 }
385
386
387
388
389
390
391
392
393
394
395 protected abstract void executeCommand( final CommandLine commandLine ) throws CommandExecutionException;
396
397
398
399
400
401
402
403
404
405
406
407
408 protected void postExecuteCommand( final CommandLine commandLine ) throws CommandExecutionException
409 {
410 if ( commandLine == null )
411 {
412 throw new NullPointerException( "commandLine" );
413 }
414 }
415
416 }