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.tools;
32
33 import java.io.BufferedReader;
34 import java.io.ByteArrayInputStream;
35 import java.io.ByteArrayOutputStream;
36 import java.io.IOException;
37 import java.io.InputStream;
38 import java.io.InputStreamReader;
39 import java.io.OutputStreamWriter;
40 import java.io.Reader;
41 import java.io.StringReader;
42 import java.lang.ref.Reference;
43 import java.lang.ref.SoftReference;
44 import java.lang.reflect.InvocationTargetException;
45 import java.net.URL;
46 import java.text.DateFormat;
47 import java.text.Format;
48 import java.text.MessageFormat;
49 import java.text.SimpleDateFormat;
50 import java.util.ArrayList;
51 import java.util.Calendar;
52 import java.util.Collections;
53 import java.util.Enumeration;
54 import java.util.HashMap;
55 import java.util.HashSet;
56 import java.util.LinkedList;
57 import java.util.List;
58 import java.util.Locale;
59 import java.util.Map;
60 import java.util.ResourceBundle;
61 import java.util.Set;
62 import java.util.logging.Level;
63 import javax.activation.MimeType;
64 import javax.activation.MimeTypeParseException;
65 import org.apache.commons.io.IOUtils;
66 import org.apache.commons.lang.StringEscapeUtils;
67 import org.apache.commons.lang.StringUtils;
68 import org.apache.velocity.Template;
69 import org.apache.velocity.VelocityContext;
70 import org.apache.velocity.app.VelocityEngine;
71 import org.apache.velocity.exception.ParseErrorException;
72 import org.apache.velocity.exception.ResourceNotFoundException;
73 import org.apache.velocity.exception.VelocityException;
74 import org.apache.velocity.runtime.RuntimeConstants;
75 import org.apache.velocity.runtime.RuntimeServices;
76 import org.apache.velocity.runtime.log.LogChute;
77 import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
78 import org.apache.velocity.runtime.resource.loader.URLResourceLoader;
79 import org.jomc.model.Argument;
80 import org.jomc.model.ArgumentType;
81 import org.jomc.model.Dependency;
82 import org.jomc.model.Implementation;
83 import org.jomc.model.InheritanceModel;
84 import org.jomc.model.Message;
85 import org.jomc.model.ModelObject;
86 import org.jomc.model.Modules;
87 import org.jomc.model.Multiplicity;
88 import org.jomc.model.Properties;
89 import org.jomc.model.Property;
90 import org.jomc.model.Specification;
91 import org.jomc.model.SpecificationReference;
92 import org.jomc.model.Specifications;
93 import org.jomc.model.Text;
94 import org.jomc.model.Texts;
95 import org.jomc.model.modlet.ModelHelper;
96 import org.jomc.modlet.Model;
97
98
99
100
101
102
103
104 public class JomcTool
105 {
106
107
108 public abstract static class Listener
109 {
110
111
112 public Listener()
113 {
114 super();
115 }
116
117
118
119
120
121
122
123
124
125
126 public void onLog( final Level level, final String message, final Throwable throwable )
127 {
128 if ( level == null )
129 {
130 throw new NullPointerException( "level" );
131 }
132 }
133
134 }
135
136
137 private static final byte[] NO_BYTES =
138 {
139 };
140
141
142 private static final String TEMPLATE_PREFIX =
143 JomcTool.class.getPackage().getName().replace( '.', '/' ) + "/templates/";
144
145
146 private static final String DEFAULT_TEMPLATE_PROFILE = "jomc-java";
147
148
149 private static volatile String defaultTemplateProfile;
150
151
152
153
154
155 private static final Level DEFAULT_LOG_LEVEL = Level.WARNING;
156
157
158 private static volatile Level defaultLogLevel;
159
160
161 private Model model;
162
163
164 private VelocityEngine velocityEngine;
165
166
167 private String templateEncoding;
168
169
170
171
172
173 private URL templateLocation;
174
175
176 private String inputEncoding;
177
178
179 private String outputEncoding;
180
181
182
183
184
185 private Map<String, Object> templateParameters;
186
187
188 private String templateProfile;
189
190
191 private String indentation;
192
193
194 private String lineSeparator;
195
196
197 private List<Listener> listeners;
198
199
200 private Level logLevel;
201
202
203
204
205
206 private Locale locale;
207
208
209 private volatile Reference<Map<String, String>> indentationCache;
210
211
212 private volatile Reference<Map<String, String>> templateLocationsCache;
213
214
215 private volatile Reference<Map<String, java.util.Properties>> templateProfilePropertiesCache;
216
217
218 private volatile Reference<Set<String>> javaKeywordsCache;
219
220
221 public JomcTool()
222 {
223 super();
224 }
225
226
227
228
229
230
231
232
233
234 public JomcTool( final JomcTool tool ) throws IOException
235 {
236 this();
237
238 if ( tool == null )
239 {
240 throw new NullPointerException( "tool" );
241 }
242
243 this.indentation = tool.indentation;
244 this.inputEncoding = tool.inputEncoding;
245 this.lineSeparator = tool.lineSeparator;
246 this.listeners = tool.listeners != null ? new LinkedList<Listener>( tool.listeners ) : null;
247 this.logLevel = tool.logLevel;
248 this.model = tool.model != null ? tool.model.clone() : null;
249 this.outputEncoding = tool.outputEncoding;
250 this.templateEncoding = tool.templateEncoding;
251 this.templateProfile = tool.templateProfile;
252 this.velocityEngine = tool.velocityEngine;
253 this.locale = tool.locale;
254 this.templateParameters =
255 tool.templateParameters != null ? new HashMap<String, Object>( tool.templateParameters ) : null;
256
257 this.templateLocation =
258 tool.templateLocation != null ? new URL( tool.templateLocation.toExternalForm() ) : null;
259
260 }
261
262
263
264
265
266
267
268
269
270
271
272 public List<Listener> getListeners()
273 {
274 if ( this.listeners == null )
275 {
276 this.listeners = new LinkedList<Listener>();
277 }
278
279 return this.listeners;
280 }
281
282
283
284
285
286
287
288
289
290
291
292
293 public static Level getDefaultLogLevel()
294 {
295 if ( defaultLogLevel == null )
296 {
297 defaultLogLevel = Level.parse( System.getProperty( "org.jomc.tools.JomcTool.defaultLogLevel",
298 DEFAULT_LOG_LEVEL.getName() ) );
299
300 }
301
302 return defaultLogLevel;
303 }
304
305
306
307
308
309
310
311
312 public static void setDefaultLogLevel( final Level value )
313 {
314 defaultLogLevel = value;
315 }
316
317
318
319
320
321
322
323
324
325
326 public final Level getLogLevel()
327 {
328 if ( this.logLevel == null )
329 {
330 this.logLevel = getDefaultLogLevel();
331
332 if ( this.isLoggable( Level.CONFIG ) )
333 {
334 this.log( Level.CONFIG, getMessage( "defaultLogLevelInfo", this.logLevel.getLocalizedName() ), null );
335 }
336 }
337
338 return this.logLevel;
339 }
340
341
342
343
344
345
346
347
348
349 public final void setLogLevel( final Level value )
350 {
351 this.logLevel = value;
352 }
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368 public boolean isLoggable( final Level level )
369 {
370 if ( level == null )
371 {
372 throw new NullPointerException( "level" );
373 }
374
375 return level.intValue() >= this.getLogLevel().intValue();
376 }
377
378
379
380
381
382
383
384
385
386
387 public String getJavaPackageName( final Specification specification )
388 {
389 if ( specification == null )
390 {
391 throw new NullPointerException( "specification" );
392 }
393
394 return specification.getClazz() != null ? this.getJavaPackageName( specification.getClazz() ) : null;
395 }
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410 public String getJavaTypeName( final Specification specification, final boolean qualified )
411 {
412 if ( specification == null )
413 {
414 throw new NullPointerException( "specification" );
415 }
416
417 if ( specification.getClazz() != null )
418 {
419 final StringBuilder typeName = new StringBuilder( specification.getClazz().length() );
420 final String javaPackageName = this.getJavaPackageName( specification );
421
422 if ( qualified && javaPackageName.length() > 0 )
423 {
424 typeName.append( javaPackageName ).append( '.' );
425 }
426
427 typeName.append( javaPackageName.length() > 0
428 ? specification.getClazz().substring( javaPackageName.length() + 1 )
429 : specification.getClazz() );
430
431 return typeName.toString();
432 }
433
434 return null;
435 }
436
437
438
439
440
441
442
443
444
445
446
447
448 public String getJavaClasspathLocation( final Specification specification )
449 {
450 if ( specification == null )
451 {
452 throw new NullPointerException( "specification" );
453 }
454
455 return specification.getClazz() != null
456 ? ( this.getJavaTypeName( specification, true ) ).replace( '.', '/' )
457 : null;
458
459 }
460
461
462
463
464
465
466
467
468
469
470
471
472 public String getJavaPackageName( final SpecificationReference reference )
473 {
474 if ( reference == null )
475 {
476 throw new NullPointerException( "reference" );
477 }
478
479 final Specification s = this.getModules().getSpecification( reference.getIdentifier() );
480 assert s != null : "Specification '" + reference.getIdentifier() + "' not found.";
481 return s.getClazz() != null ? this.getJavaPackageName( s ) : null;
482 }
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497 public String getJavaTypeName( final SpecificationReference reference, final boolean qualified )
498 {
499 if ( reference == null )
500 {
501 throw new NullPointerException( "reference" );
502 }
503
504 final Specification s = this.getModules().getSpecification( reference.getIdentifier() );
505 assert s != null : "Specification '" + reference.getIdentifier() + "' not found.";
506 return s.getClazz() != null ? this.getJavaTypeName( s, qualified ) : null;
507 }
508
509
510
511
512
513
514
515
516
517
518 public String getJavaPackageName( final Implementation implementation )
519 {
520 if ( implementation == null )
521 {
522 throw new NullPointerException( "implementation" );
523 }
524
525 return implementation.getClazz() != null ? this.getJavaPackageName( implementation.getClazz() ) : null;
526 }
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541 public String getJavaTypeName( final Implementation implementation, final boolean qualified )
542 {
543 if ( implementation == null )
544 {
545 throw new NullPointerException( "implementation" );
546 }
547
548 if ( implementation.getClazz() != null )
549 {
550 final StringBuilder typeName = new StringBuilder( implementation.getClazz().length() );
551 final String javaPackageName = this.getJavaPackageName( implementation );
552
553 if ( qualified && javaPackageName.length() > 0 )
554 {
555 typeName.append( javaPackageName ).append( '.' );
556 }
557
558 typeName.append( javaPackageName.length() > 0
559 ? implementation.getClazz().substring( javaPackageName.length() + 1 )
560 : implementation.getClazz() );
561
562 return typeName.toString();
563 }
564
565 return null;
566 }
567
568
569
570
571
572
573
574
575
576
577 public String getJavaClasspathLocation( final Implementation implementation )
578 {
579 if ( implementation == null )
580 {
581 throw new NullPointerException( "implementation" );
582 }
583
584 return implementation.getClazz() != null
585 ? ( this.getJavaTypeName( implementation, true ) ).replace( '.', '/' )
586 : null;
587
588 }
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604 @Deprecated
605 public List<String> getJavaInterfaceNames( final Implementation implementation, final boolean qualified )
606 {
607 if ( implementation == null )
608 {
609 throw new NullPointerException( "implementation" );
610 }
611
612 return this.getImplementedJavaTypeNames( implementation, qualified );
613 }
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630 public List<String> getImplementedJavaTypeNames( final Implementation implementation, final boolean qualified )
631 {
632 if ( implementation == null )
633 {
634 throw new NullPointerException( "implementation" );
635 }
636
637 final Specifications specs = this.getModules().getSpecifications( implementation.getIdentifier() );
638 final List<String> col = new ArrayList<String>( specs == null ? 0 : specs.getSpecification().size() );
639
640 if ( specs != null )
641 {
642 for ( int i = 0, s0 = specs.getSpecification().size(); i < s0; i++ )
643 {
644 final Specification s = specs.getSpecification().get( i );
645
646 if ( s.getClazz() != null )
647 {
648 final String typeName = this.getJavaTypeName( s, qualified );
649 if ( !col.contains( typeName ) )
650 {
651 col.add( typeName );
652 }
653 }
654 }
655 }
656
657 return Collections.unmodifiableList( col );
658 }
659
660
661
662
663
664
665
666
667
668
669 public String getJavaTypeName( final Argument argument )
670 {
671 if ( argument == null )
672 {
673 throw new NullPointerException( "argument" );
674 }
675
676 String javaTypeName = "java.lang.String";
677
678 if ( argument.getType() == ArgumentType.DATE || argument.getType() == ArgumentType.TIME )
679 {
680 javaTypeName = "java.util.Date";
681 }
682 else if ( argument.getType() == ArgumentType.NUMBER )
683 {
684 javaTypeName = "java.lang.Number";
685 }
686
687 return javaTypeName;
688 }
689
690
691
692
693
694
695
696
697
698
699
700
701 public String getJavaMethodParameterName( final Argument argument )
702 {
703 if ( argument == null )
704 {
705 throw new NullPointerException( "argument" );
706 }
707
708 return this.getJavaMethodParameterName( argument.getName() );
709 }
710
711
712
713
714
715
716
717
718
719
720
721
722 public String getJavaTypeName( final Property property, final boolean boxify )
723 {
724 if ( property == null )
725 {
726 throw new NullPointerException( "property" );
727 }
728
729 if ( property.getType() != null )
730 {
731 final String typeName = property.getType();
732
733 if ( boxify )
734 {
735 if ( Boolean.TYPE.getName().equals( typeName ) )
736 {
737 return Boolean.class.getName();
738 }
739 if ( Byte.TYPE.getName().equals( typeName ) )
740 {
741 return Byte.class.getName();
742 }
743 if ( Character.TYPE.getName().equals( typeName ) )
744 {
745 return Character.class.getName();
746 }
747 if ( Double.TYPE.getName().equals( typeName ) )
748 {
749 return Double.class.getName();
750 }
751 if ( Float.TYPE.getName().equals( typeName ) )
752 {
753 return Float.class.getName();
754 }
755 if ( Integer.TYPE.getName().equals( typeName ) )
756 {
757 return Integer.class.getName();
758 }
759 if ( Long.TYPE.getName().equals( typeName ) )
760 {
761 return Long.class.getName();
762 }
763 if ( Short.TYPE.getName().equals( typeName ) )
764 {
765 return Short.class.getName();
766 }
767 }
768
769 return typeName;
770 }
771
772 return property.getAny() != null ? Object.class.getName() : String.class.getName();
773 }
774
775
776
777
778
779
780
781
782
783
784
785
786 public boolean isJavaPrimitiveType( final Property property )
787 {
788 if ( property == null )
789 {
790 throw new NullPointerException( "property" );
791 }
792
793 return !this.getJavaTypeName( property, false ).equals( this.getJavaTypeName( property, true ) );
794 }
795
796
797
798
799
800
801
802
803
804
805
806
807 public String getJavaGetterMethodName( final Property property )
808 {
809 if ( property == null )
810 {
811 throw new NullPointerException( "property" );
812 }
813
814 String prefix = "get";
815
816 final String javaTypeName = this.getJavaTypeName( property, true );
817 if ( Boolean.class.getName().equals( javaTypeName ) )
818 {
819 prefix = "is";
820 }
821
822 return prefix + this.getJavaIdentifier( property.getName(), true );
823 }
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838 public String getJavaSetterMethodName( final Property property )
839 {
840 if ( property == null )
841 {
842 throw new NullPointerException( "property" );
843 }
844
845 return "set" + this.getJavaIdentifier( property.getName(), true );
846 }
847
848
849
850
851
852
853
854
855
856
857
858
859 public String getJavaMethodParameterName( final Property property )
860 {
861 if ( property == null )
862 {
863 throw new NullPointerException( "property" );
864 }
865
866 return this.getJavaMethodParameterName( property.getName() );
867 }
868
869
870
871
872
873
874
875
876
877
878
879
880 public String getJavaTypeName( final Dependency dependency )
881 {
882 if ( dependency == null )
883 {
884 throw new NullPointerException( "dependency" );
885 }
886
887 final Specification s = this.getModules().getSpecification( dependency.getIdentifier() );
888
889 if ( s != null && s.getClazz() != null )
890 {
891 final StringBuilder typeName = new StringBuilder( s.getClazz().length() );
892 typeName.append( this.getJavaTypeName( s, true ) );
893 if ( s.getMultiplicity() == Multiplicity.MANY && dependency.getImplementationName() == null )
894 {
895 typeName.append( "[]" );
896 }
897
898 return typeName.toString();
899 }
900
901 return null;
902 }
903
904
905
906
907
908
909
910
911
912
913
914
915 public String getJavaGetterMethodName( final Dependency dependency )
916 {
917 if ( dependency == null )
918 {
919 throw new NullPointerException( "dependency" );
920 }
921
922 return "get" + this.getJavaIdentifier( dependency.getName(), true );
923 }
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938 public String getJavaSetterMethodName( final Dependency dependency )
939 {
940 if ( dependency == null )
941 {
942 throw new NullPointerException( "dependency" );
943 }
944
945 return "set" + this.getJavaIdentifier( dependency.getName(), true );
946 }
947
948
949
950
951
952
953
954
955
956
957
958
959 public String getJavaMethodParameterName( final Dependency dependency )
960 {
961 if ( dependency == null )
962 {
963 throw new NullPointerException( "dependency" );
964 }
965
966 return this.getJavaMethodParameterName( dependency.getName() );
967 }
968
969
970
971
972
973
974
975
976
977
978
979
980 public String getJavaGetterMethodName( final Message message )
981 {
982 if ( message == null )
983 {
984 throw new NullPointerException( "message" );
985 }
986
987 return "get" + this.getJavaIdentifier( message.getName(), true );
988 }
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003 public String getJavaSetterMethodName( final Message message )
1004 {
1005 if ( message == null )
1006 {
1007 throw new NullPointerException( "message" );
1008 }
1009
1010 return "set" + this.getJavaIdentifier( message.getName(), true );
1011 }
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024 public String getJavaMethodParameterName( final Message message )
1025 {
1026 if ( message == null )
1027 {
1028 throw new NullPointerException( "message" );
1029 }
1030
1031 return this.getJavaMethodParameterName( message.getName() );
1032 }
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044 public String getJavaModifierName( final Implementation implementation, final Dependency dependency )
1045 {
1046 if ( implementation == null )
1047 {
1048 throw new NullPointerException( "implementation" );
1049 }
1050 if ( dependency == null )
1051 {
1052 throw new NullPointerException( "dependency" );
1053 }
1054
1055 return "private";
1056 }
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068 public String getJavaModifierName( final Implementation implementation, final Message message )
1069 {
1070 if ( implementation == null )
1071 {
1072 throw new NullPointerException( "implementation" );
1073 }
1074 if ( message == null )
1075 {
1076 throw new NullPointerException( "message" );
1077 }
1078
1079 return "private";
1080 }
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092 public String getJavaModifierName( final Implementation implementation, final Property property )
1093 {
1094 if ( implementation == null )
1095 {
1096 throw new NullPointerException( "implementation" );
1097 }
1098 if ( property == null )
1099 {
1100 throw new NullPointerException( "property" );
1101 }
1102
1103 String modifier = "private";
1104 final Properties specified = this.getModules().getSpecifiedProperties( implementation.getIdentifier() );
1105
1106 if ( specified != null && specified.getProperty( property.getName() ) != null )
1107 {
1108 modifier = "public";
1109 }
1110
1111 return modifier;
1112 }
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126 public String getJavadocComment( final Text text, final int indentationLevel, final String linePrefix )
1127 {
1128 if ( text == null )
1129 {
1130 throw new NullPointerException( "text" );
1131 }
1132 if ( linePrefix == null )
1133 {
1134 throw new NullPointerException( "linePrefix" );
1135 }
1136 if ( indentationLevel < 0 )
1137 {
1138 throw new IllegalArgumentException( Integer.toString( indentationLevel ) );
1139 }
1140
1141 BufferedReader reader = null;
1142 boolean suppressExceptionOnClose = true;
1143
1144 try
1145 {
1146 String javadoc = "";
1147
1148 if ( text.getValue() != null )
1149 {
1150 final String indent = this.getIndentation( indentationLevel );
1151 reader = new BufferedReader( new StringReader( text.getValue() ) );
1152 final StringBuilder builder = new StringBuilder( text.getValue().length() );
1153
1154 String line;
1155 while ( ( line = reader.readLine() ) != null )
1156 {
1157 builder.append( this.getLineSeparator() ).append( indent ).append( linePrefix ).
1158 append( line.replaceAll( "\\/\\*\\*", "/*" ).replaceAll( "\\*/", "/" ) );
1159
1160 }
1161
1162 if ( builder.length() > 0 )
1163 {
1164 javadoc =
1165 builder.substring( this.getLineSeparator().length() + indent.length() + linePrefix.length() );
1166
1167 if ( !new MimeType( text.getType() ).match( "text/html" ) )
1168 {
1169 javadoc = StringEscapeUtils.escapeHtml( javadoc );
1170 }
1171 }
1172 }
1173
1174 suppressExceptionOnClose = false;
1175 return javadoc;
1176 }
1177 catch ( final MimeTypeParseException e )
1178 {
1179 throw new AssertionError( e );
1180 }
1181 catch ( final IOException e )
1182 {
1183 throw new AssertionError( e );
1184 }
1185 finally
1186 {
1187 try
1188 {
1189 if ( reader != null )
1190 {
1191 reader.close();
1192 }
1193 }
1194 catch ( final IOException e )
1195 {
1196 if ( suppressExceptionOnClose )
1197 {
1198 this.log( Level.SEVERE, getMessage( e ), e );
1199 }
1200 else
1201 {
1202 throw new AssertionError( e );
1203 }
1204 }
1205 }
1206 }
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225 public String getJavadocComment( final Texts texts, final int indentationLevel, final String linePrefix )
1226 {
1227 if ( texts == null )
1228 {
1229 throw new NullPointerException( "texts" );
1230 }
1231 if ( linePrefix == null )
1232 {
1233 throw new NullPointerException( "linePrefix" );
1234 }
1235 if ( indentationLevel < 0 )
1236 {
1237 throw new IllegalArgumentException( Integer.toString( indentationLevel ) );
1238 }
1239
1240 return this.getJavadocComment( texts.getText( this.getLocale().getLanguage() ), indentationLevel, linePrefix );
1241 }
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252 public String getJavaString( final String str )
1253 {
1254 return StringEscapeUtils.escapeJava( str );
1255 }
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268 public String getJavaIdentifier( final String str, final boolean capitalize )
1269 {
1270 String identifier = null;
1271
1272 if ( str != null )
1273 {
1274 final int len = str.length();
1275 final StringBuilder builder = new StringBuilder( len );
1276 boolean uc = capitalize;
1277
1278 for ( int i = 0; i < len; i++ )
1279 {
1280 final char c = str.charAt( i );
1281 final String charString = Character.toString( c );
1282
1283 if ( builder.length() > 0 )
1284 {
1285 if ( Character.isJavaIdentifierPart( c ) )
1286 {
1287 builder.append( uc ? charString.toUpperCase( this.getLocale() ) : charString );
1288 uc = false;
1289 }
1290 else
1291 {
1292 uc = true;
1293 }
1294 }
1295 else
1296 {
1297 if ( Character.isJavaIdentifierStart( c ) )
1298 {
1299 builder.append( uc ? charString.toUpperCase( this.getLocale() )
1300 : charString.toLowerCase( this.getLocale() ) );
1301
1302 uc = false;
1303 }
1304 else
1305 {
1306 uc = capitalize;
1307 }
1308 }
1309 }
1310
1311 identifier = builder.toString();
1312
1313 if ( identifier.length() <= 0 && this.isLoggable( Level.WARNING ) )
1314 {
1315 this.log( Level.WARNING, getMessage( "invalidJavaIdentifier", str ), null );
1316 }
1317 }
1318
1319 return identifier;
1320 }
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331 private String getJavaMethodParameterName( final String str )
1332 {
1333 String methodParameterName = null;
1334
1335 if ( str != null )
1336 {
1337 final int len = str.length();
1338 final StringBuilder builder = new StringBuilder( len );
1339 boolean uc = false;
1340
1341 for ( int i = 0; i < len; i++ )
1342 {
1343 final char c = str.charAt( i );
1344 final String charString = Character.toString( c );
1345
1346 if ( builder.length() > 0 )
1347 {
1348 if ( Character.isJavaIdentifierPart( c ) )
1349 {
1350 builder.append( uc ? charString.toUpperCase( this.getLocale() ) : charString );
1351 uc = false;
1352 }
1353 else
1354 {
1355 uc = true;
1356 }
1357 }
1358 else if ( Character.isJavaIdentifierStart( c ) )
1359 {
1360 builder.append( charString.toLowerCase( this.getLocale() ) );
1361 }
1362 }
1363
1364 methodParameterName = builder.toString();
1365
1366 if ( methodParameterName.length() <= 0 && this.isLoggable( Level.WARNING ) )
1367 {
1368 this.log( Level.WARNING, getMessage( "invalidJavaMethodParameterName", str ), null );
1369 }
1370
1371 if ( this.getJavaKeywords().contains( methodParameterName ) )
1372 {
1373 methodParameterName = "_" + methodParameterName;
1374 }
1375 }
1376
1377 return methodParameterName;
1378 }
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390 public boolean isJavaDefaultPackage( final Specification specification )
1391 {
1392 if ( specification == null )
1393 {
1394 throw new NullPointerException( "specification" );
1395 }
1396
1397 return specification.getClazz() != null && this.getJavaPackageName( specification ).length() == 0;
1398 }
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410 public boolean isJavaDefaultPackage( final Implementation implementation )
1411 {
1412 if ( implementation == null )
1413 {
1414 throw new NullPointerException( "implementation" );
1415 }
1416
1417 return implementation.getClazz() != null && this.getJavaPackageName( implementation ).length() == 0;
1418 }
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431 public String getHtmlString( final String str )
1432 {
1433 return StringEscapeUtils.escapeHtml( str );
1434 }
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447 public String getXmlString( final String str )
1448 {
1449 return StringEscapeUtils.escapeXml( str );
1450 }
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463 public String getJavaScriptString( final String str )
1464 {
1465 return StringEscapeUtils.escapeJavaScript( str );
1466 }
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479 public String getSqlString( final String str )
1480 {
1481 return StringEscapeUtils.escapeSql( str );
1482 }
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495 public String getCsvString( final String str )
1496 {
1497 return StringEscapeUtils.escapeCsv( str );
1498 }
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511 public String getBooleanString( final Boolean b )
1512 {
1513 final MessageFormat messageFormat = new MessageFormat( ResourceBundle.getBundle(
1514 JomcTool.class.getName().replace( '.', '/' ), this.getLocale() ).
1515 getString( b ? "booleanStringTrue" : "booleanStringFalse" ), this.getLocale() );
1516
1517 return messageFormat.format( null );
1518 }
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529 public String getDisplayLanguage( final String language )
1530 {
1531 if ( language == null )
1532 {
1533 throw new NullPointerException( "language" );
1534 }
1535
1536 final Locale l = new Locale( language );
1537 return l.getDisplayLanguage( l );
1538 }
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551 public String getShortDate( final Calendar calendar )
1552 {
1553 if ( calendar == null )
1554 {
1555 throw new NullPointerException( "calendar" );
1556 }
1557
1558 return DateFormat.getDateInstance( DateFormat.SHORT, this.getLocale() ).format( calendar.getTime() );
1559 }
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574 public String getMediumDate( final Calendar calendar )
1575 {
1576 if ( calendar == null )
1577 {
1578 throw new NullPointerException( "calendar" );
1579 }
1580
1581 return DateFormat.getDateInstance( DateFormat.MEDIUM, this.getLocale() ).format( calendar.getTime() );
1582 }
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595 public String getLongDate( final Calendar calendar )
1596 {
1597 if ( calendar == null )
1598 {
1599 throw new NullPointerException( "calendar" );
1600 }
1601
1602 return DateFormat.getDateInstance( DateFormat.LONG, this.getLocale() ).format( calendar.getTime() );
1603 }
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618 public String getIsoDate( final Calendar calendar )
1619 {
1620 if ( calendar == null )
1621 {
1622 throw new NullPointerException( "calendar" );
1623 }
1624
1625 return new SimpleDateFormat( "yyyy-DDD", this.getLocale() ).format( calendar.getTime() );
1626 }
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639 public String getShortTime( final Calendar calendar )
1640 {
1641 if ( calendar == null )
1642 {
1643 throw new NullPointerException( "calendar" );
1644 }
1645
1646 return DateFormat.getTimeInstance( DateFormat.SHORT, this.getLocale() ).format( calendar.getTime() );
1647 }
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662 public String getMediumTime( final Calendar calendar )
1663 {
1664 if ( calendar == null )
1665 {
1666 throw new NullPointerException( "calendar" );
1667 }
1668
1669 return DateFormat.getTimeInstance( DateFormat.MEDIUM, this.getLocale() ).format( calendar.getTime() );
1670 }
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683 public String getLongTime( final Calendar calendar )
1684 {
1685 if ( calendar == null )
1686 {
1687 throw new NullPointerException( "calendar" );
1688 }
1689
1690 return DateFormat.getTimeInstance( DateFormat.LONG, this.getLocale() ).format( calendar.getTime() );
1691 }
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706 public String getIsoTime( final Calendar calendar )
1707 {
1708 if ( calendar == null )
1709 {
1710 throw new NullPointerException( "calendar" );
1711 }
1712
1713 return new SimpleDateFormat( "HH:mm", this.getLocale() ).format( calendar.getTime() );
1714 }
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727 public String getShortDateTime( final Calendar calendar )
1728 {
1729 if ( calendar == null )
1730 {
1731 throw new NullPointerException( "calendar" );
1732 }
1733
1734 return DateFormat.getDateTimeInstance( DateFormat.SHORT, DateFormat.SHORT, this.getLocale() ).
1735 format( calendar.getTime() );
1736
1737 }
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752 public String getMediumDateTime( final Calendar calendar )
1753 {
1754 if ( calendar == null )
1755 {
1756 throw new NullPointerException( "calendar" );
1757 }
1758
1759 return DateFormat.getDateTimeInstance( DateFormat.MEDIUM, DateFormat.MEDIUM, this.getLocale() ).
1760 format( calendar.getTime() );
1761
1762 }
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775 public String getLongDateTime( final Calendar calendar )
1776 {
1777 if ( calendar == null )
1778 {
1779 throw new NullPointerException( "calendar" );
1780 }
1781
1782 return DateFormat.getDateTimeInstance( DateFormat.LONG, DateFormat.LONG, this.getLocale() ).
1783 format( calendar.getTime() );
1784
1785 }
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800 public String getIsoDateTime( final Calendar calendar )
1801 {
1802 if ( calendar == null )
1803 {
1804 throw new NullPointerException( "calendar" );
1805 }
1806
1807
1808 return new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ssZ", this.getLocale() ).format( calendar.getTime() );
1809 }
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821 public String getYears( final Calendar start, final Calendar end )
1822 {
1823 if ( start == null )
1824 {
1825 throw new NullPointerException( "start" );
1826 }
1827 if ( end == null )
1828 {
1829 throw new NullPointerException( "end" );
1830 }
1831
1832 final Format yearFormat = new SimpleDateFormat( "yyyy", this.getLocale() );
1833 final int s = start.get( Calendar.YEAR );
1834 final int e = end.get( Calendar.YEAR );
1835 final StringBuilder years = new StringBuilder();
1836
1837 if ( s != e )
1838 {
1839 if ( s < e )
1840 {
1841 years.append( yearFormat.format( start.getTime() ) ).append( " - " ).
1842 append( yearFormat.format( end.getTime() ) );
1843
1844 }
1845 else
1846 {
1847 years.append( yearFormat.format( end.getTime() ) ).append( " - " ).
1848 append( yearFormat.format( start.getTime() ) );
1849
1850 }
1851 }
1852 else
1853 {
1854 years.append( yearFormat.format( start.getTime() ) );
1855 }
1856
1857 return years.toString();
1858 }
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868 public final Model getModel()
1869 {
1870 if ( this.model == null )
1871 {
1872 this.model = new Model();
1873 this.model.setIdentifier( ModelObject.MODEL_PUBLIC_ID );
1874 }
1875
1876 return this.model;
1877 }
1878
1879
1880
1881
1882
1883
1884
1885
1886 public final void setModel( final Model value )
1887 {
1888 this.model = value;
1889 }
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902 @Deprecated
1903 public Modules getModules()
1904 {
1905 Modules modules = ModelHelper.getModules( this.getModel() );
1906
1907 if ( modules == null )
1908 {
1909 modules = new Modules();
1910 ModelHelper.setModules( this.getModel(), modules );
1911 }
1912
1913 return modules;
1914 }
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925 public final VelocityEngine getVelocityEngine() throws IOException
1926 {
1927 if ( this.velocityEngine == null )
1928 {
1929
1930 class JomcLogChute implements LogChute
1931 {
1932
1933 JomcLogChute()
1934 {
1935 super();
1936 }
1937
1938 public void init( final RuntimeServices runtimeServices ) throws Exception
1939 {
1940 }
1941
1942 public void log( final int level, final String message )
1943 {
1944 this.log( level, message, null );
1945 }
1946
1947 public void log( final int level, final String message, final Throwable throwable )
1948 {
1949 JomcTool.this.log( Level.FINEST, message, throwable );
1950 }
1951
1952 public boolean isLevelEnabled( final int level )
1953 {
1954 return isLoggable( Level.FINEST );
1955 }
1956
1957 }
1958
1959 final VelocityEngine engine = new VelocityEngine();
1960 engine.setProperty( RuntimeConstants.RUNTIME_REFERENCES_STRICT, Boolean.TRUE.toString() );
1961 engine.setProperty( RuntimeConstants.VM_ARGUMENTS_STRICT, Boolean.TRUE.toString() );
1962 engine.setProperty( RuntimeConstants.STRICT_MATH, Boolean.TRUE.toString() );
1963 engine.setProperty( RuntimeConstants.RUNTIME_LOG_LOGSYSTEM, new JomcLogChute() );
1964
1965 engine.setProperty( RuntimeConstants.RESOURCE_LOADER, "class" );
1966 engine.setProperty( "class.resource.loader.class", ClasspathResourceLoader.class.getName() );
1967 engine.setProperty( "class.resource.loader.cache", Boolean.TRUE.toString() );
1968
1969 if ( this.getTemplateLocation() != null )
1970 {
1971 engine.setProperty( RuntimeConstants.RESOURCE_LOADER, "class,url" );
1972 engine.setProperty( "url.resource.loader.class", URLResourceLoader.class.getName() );
1973 engine.setProperty( "url.resource.loader.cache", Boolean.TRUE.toString() );
1974 engine.setProperty( "url.resource.loader.root", this.getTemplateLocation().toExternalForm() );
1975 engine.setProperty( "url.resource.loader.timeout", Integer.toString( 60000 ) );
1976 }
1977
1978 this.velocityEngine = engine;
1979 }
1980
1981 return this.velocityEngine;
1982 }
1983
1984
1985
1986
1987
1988
1989
1990
1991 public final void setVelocityEngine( final VelocityEngine value )
1992 {
1993 this.velocityEngine = value;
1994 }
1995
1996
1997
1998
1999
2000
2001
2002
2003 public VelocityContext getVelocityContext()
2004 {
2005 final Calendar now = Calendar.getInstance();
2006 final VelocityContext ctx = new VelocityContext( Collections.synchronizedMap(
2007 new HashMap<String, Object>( this.getTemplateParameters() ) ) );
2008
2009 this.mergeTemplateProfileProperties( this.getTemplateProfile(), this.getLocale().getLanguage(), ctx );
2010 this.mergeTemplateProfileProperties( this.getTemplateProfile(), null, ctx );
2011 this.mergeTemplateProfileProperties( getDefaultTemplateProfile(), this.getLocale().getLanguage(), ctx );
2012 this.mergeTemplateProfileProperties( getDefaultTemplateProfile(), null, ctx );
2013
2014 this.getModules();
2015 final Model clonedModel = this.getModel().clone();
2016 final Modules clonedModules = ModelHelper.getModules( clonedModel );
2017 assert clonedModules != null : "Unexpected missing modules for model '" + clonedModel.getIdentifier() + "'.";
2018
2019 ctx.put( "model", clonedModel );
2020 ctx.put( "modules", clonedModules );
2021 ctx.put( "imodel", new InheritanceModel( this.getModules() ) );
2022 ctx.put( "tool", this );
2023 ctx.put( "toolName", this.getClass().getName() );
2024 ctx.put( "toolVersion", getMessage( "projectVersion" ) );
2025 ctx.put( "toolUrl", getMessage( "projectUrl" ) );
2026 ctx.put( "calendar", now.getTime() );
2027
2028
2029 ctx.put( "now",
2030 new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ss.SSSZ", this.getLocale() ).format( now.getTime() ) );
2031
2032 ctx.put( "year", new SimpleDateFormat( "yyyy", this.getLocale() ).format( now.getTime() ) );
2033 ctx.put( "month", new SimpleDateFormat( "MM", this.getLocale() ).format( now.getTime() ) );
2034 ctx.put( "day", new SimpleDateFormat( "dd", this.getLocale() ).format( now.getTime() ) );
2035 ctx.put( "hour", new SimpleDateFormat( "HH", this.getLocale() ).format( now.getTime() ) );
2036 ctx.put( "minute", new SimpleDateFormat( "mm", this.getLocale() ).format( now.getTime() ) );
2037 ctx.put( "second", new SimpleDateFormat( "ss", this.getLocale() ).format( now.getTime() ) );
2038 ctx.put( "timezone", new SimpleDateFormat( "Z", this.getLocale() ).format( now.getTime() ) );
2039 ctx.put( "shortDate", this.getShortDate( now ) );
2040 ctx.put( "mediumDate", this.getMediumDate( now ) );
2041 ctx.put( "longDate", this.getLongDate( now ) );
2042 ctx.put( "isoDate", this.getIsoDate( now ) );
2043 ctx.put( "shortTime", this.getShortTime( now ) );
2044 ctx.put( "mediumTime", this.getMediumTime( now ) );
2045 ctx.put( "longTime", this.getLongTime( now ) );
2046 ctx.put( "isoTime", this.getIsoTime( now ) );
2047 ctx.put( "shortDateTime", this.getShortDateTime( now ) );
2048 ctx.put( "mediumDateTime", this.getMediumDateTime( now ) );
2049 ctx.put( "longDateTime", this.getLongDateTime( now ) );
2050 ctx.put( "isoDateTime", this.getIsoDateTime( now ) );
2051
2052 return ctx;
2053 }
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067 public final Map<String, Object> getTemplateParameters()
2068 {
2069 if ( this.templateParameters == null )
2070 {
2071 this.templateParameters = new HashMap<String, Object>();
2072 }
2073
2074 return this.templateParameters;
2075 }
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086 public final URL getTemplateLocation()
2087 {
2088 return this.templateLocation;
2089 }
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100 public final void setTemplateLocation( final URL value )
2101 {
2102 this.templateLocation = value;
2103 }
2104
2105
2106
2107
2108
2109
2110
2111
2112 public final String getTemplateEncoding()
2113 {
2114 if ( this.templateEncoding == null )
2115 {
2116 this.templateEncoding = getMessage( "buildSourceEncoding" );
2117
2118 if ( this.isLoggable( Level.CONFIG ) )
2119 {
2120 this.log( Level.CONFIG, getMessage( "defaultTemplateEncoding", this.templateEncoding ), null );
2121 }
2122 }
2123
2124 return this.templateEncoding;
2125 }
2126
2127
2128
2129
2130
2131
2132
2133
2134 public final void setTemplateEncoding( final String value )
2135 {
2136 this.templateEncoding = value;
2137 this.velocityEngine = null;
2138 }
2139
2140
2141
2142
2143
2144
2145
2146
2147 public final String getInputEncoding()
2148 {
2149 if ( this.inputEncoding == null )
2150 {
2151 this.inputEncoding = new InputStreamReader( new ByteArrayInputStream( NO_BYTES ) ).getEncoding();
2152
2153 if ( this.isLoggable( Level.CONFIG ) )
2154 {
2155 this.log( Level.CONFIG, getMessage( "defaultInputEncoding", this.inputEncoding ), null );
2156 }
2157 }
2158
2159 return this.inputEncoding;
2160 }
2161
2162
2163
2164
2165
2166
2167
2168
2169 public final void setInputEncoding( final String value )
2170 {
2171 this.inputEncoding = value;
2172 }
2173
2174
2175
2176
2177
2178
2179
2180
2181 public final String getOutputEncoding()
2182 {
2183 if ( this.outputEncoding == null )
2184 {
2185 this.outputEncoding = new OutputStreamWriter( new ByteArrayOutputStream() ).getEncoding();
2186
2187 if ( this.isLoggable( Level.CONFIG ) )
2188 {
2189 this.log( Level.CONFIG, getMessage( "defaultOutputEncoding", this.outputEncoding ), null );
2190 }
2191 }
2192
2193 return this.outputEncoding;
2194 }
2195
2196
2197
2198
2199
2200
2201
2202
2203 public final void setOutputEncoding( final String value )
2204 {
2205 this.outputEncoding = value;
2206 }
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221 @Deprecated
2222 public static String getDefaultTemplateProfile()
2223 {
2224 if ( defaultTemplateProfile == null )
2225 {
2226 defaultTemplateProfile = System.getProperty( "org.jomc.tools.JomcTool.defaultTemplateProfile",
2227 DEFAULT_TEMPLATE_PROFILE );
2228
2229 }
2230
2231 return defaultTemplateProfile;
2232 }
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243 @Deprecated
2244 public static void setDefaultTemplateProfile( final String value )
2245 {
2246 defaultTemplateProfile = value;
2247 }
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257 public final String getTemplateProfile()
2258 {
2259 if ( this.templateProfile == null )
2260 {
2261 this.templateProfile = getDefaultTemplateProfile();
2262
2263 if ( this.isLoggable( Level.CONFIG ) )
2264 {
2265 this.log( Level.CONFIG, getMessage( "defaultTemplateProfile", this.templateProfile ), null );
2266 }
2267 }
2268
2269 return this.templateProfile;
2270 }
2271
2272
2273
2274
2275
2276
2277
2278
2279 public final void setTemplateProfile( final String value )
2280 {
2281 this.templateProfile = value;
2282 }
2283
2284
2285
2286
2287
2288
2289
2290
2291 public final String getIndentation()
2292 {
2293 if ( this.indentation == null )
2294 {
2295 this.indentation = " ";
2296
2297 if ( this.isLoggable( Level.CONFIG ) )
2298 {
2299 this.log( Level.CONFIG, getMessage( "defaultIndentation",
2300 StringEscapeUtils.escapeJava( this.indentation ) ), null );
2301
2302 }
2303 }
2304
2305 return this.indentation;
2306 }
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319 public final String getIndentation( final int level )
2320 {
2321 if ( level < 0 )
2322 {
2323 throw new IllegalArgumentException( Integer.toString( level ) );
2324 }
2325
2326 Map<String, String> map = this.indentationCache == null ? null : this.indentationCache.get();
2327
2328 if ( map == null )
2329 {
2330 map = new HashMap<String, String>();
2331 this.indentationCache = new SoftReference<Map<String, String>>( map );
2332 }
2333
2334 final String key = this.getIndentation() + "|" + level;
2335 String idt = map.get( key );
2336
2337 if ( idt == null )
2338 {
2339 final StringBuilder b = new StringBuilder( this.getIndentation().length() * level );
2340
2341 for ( int i = level; i > 0; i-- )
2342 {
2343 b.append( this.getIndentation() );
2344 }
2345
2346 idt = b.toString();
2347 map.put( key, idt );
2348 }
2349
2350 return idt;
2351 }
2352
2353
2354
2355
2356
2357
2358
2359
2360 public final void setIndentation( final String value )
2361 {
2362 this.indentation = value;
2363 }
2364
2365
2366
2367
2368
2369
2370
2371
2372 public final String getLineSeparator()
2373 {
2374 if ( this.lineSeparator == null )
2375 {
2376 this.lineSeparator = System.getProperty( "line.separator", "\n" );
2377
2378 if ( this.isLoggable( Level.CONFIG ) )
2379 {
2380 this.log( Level.CONFIG, getMessage( "defaultLineSeparator",
2381 StringEscapeUtils.escapeJava( this.lineSeparator ) ), null );
2382
2383 }
2384 }
2385
2386 return this.lineSeparator;
2387 }
2388
2389
2390
2391
2392
2393
2394
2395
2396 public final void setLineSeparator( final String value )
2397 {
2398 this.lineSeparator = value;
2399 }
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410 public final Locale getLocale()
2411 {
2412 if ( this.locale == null )
2413 {
2414 this.locale = Locale.ENGLISH;
2415
2416 if ( this.isLoggable( Level.CONFIG ) )
2417 {
2418 this.log( Level.CONFIG, getMessage( "defaultLocale", this.locale ), null );
2419 }
2420 }
2421
2422 return this.locale;
2423 }
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434 public final void setLocale( final Locale value )
2435 {
2436 this.locale = value;
2437 }
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461 public Template getVelocityTemplate( final String templateName ) throws IOException
2462 {
2463 if ( templateName == null )
2464 {
2465 throw new NullPointerException( "templateName" );
2466 }
2467
2468 String location = null;
2469 Template template = null;
2470 final String key = this.getLocale() + "|" + this.getTemplateProfile() + "|" + getDefaultTemplateProfile()
2471 + "|" + templateName;
2472
2473 Map<String, String> map = this.templateLocationsCache == null ? null : this.templateLocationsCache.get();
2474
2475 if ( map == null )
2476 {
2477 map = new HashMap<String, String>( 32 );
2478 this.templateLocationsCache = new SoftReference<Map<String, String>>( map );
2479 }
2480
2481 location = map.get( key );
2482
2483 if ( location == null && !map.containsKey( key ) )
2484 {
2485 if ( !StringUtils.EMPTY.equals( this.getLocale().getLanguage() ) )
2486 {
2487 location = TEMPLATE_PREFIX + this.getTemplateProfile() + "/" + this.getLocale().getLanguage() + "/"
2488 + templateName;
2489
2490 template = this.findVelocityTemplate( location );
2491 }
2492
2493 if ( template == null )
2494 {
2495 location = TEMPLATE_PREFIX + this.getTemplateProfile() + "/" + templateName;
2496 template = this.findVelocityTemplate( location );
2497 }
2498
2499 if ( template == null && !StringUtils.EMPTY.equals( this.getLocale().getLanguage() ) )
2500 {
2501 location = TEMPLATE_PREFIX + getDefaultTemplateProfile() + "/" + this.getLocale().getLanguage() + "/"
2502 + templateName;
2503
2504 template = this.findVelocityTemplate( location );
2505 }
2506
2507 if ( template == null )
2508 {
2509 location = TEMPLATE_PREFIX + getDefaultTemplateProfile() + "/" + templateName;
2510 template = this.findVelocityTemplate( location );
2511 }
2512
2513 map.put( key, location );
2514 }
2515 else if ( location != null )
2516 {
2517 template = this.findVelocityTemplate( location );
2518 }
2519
2520 if ( template == null )
2521 {
2522 throw new IOException( getMessage( "noSuchTemplate", templateName ) );
2523 }
2524
2525 if ( this.isLoggable( Level.FINER ) )
2526 {
2527 this.log( Level.FINER, getMessage( "templateInfo", templateName, location ), null );
2528 }
2529
2530 return template;
2531 }
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545 public void log( final Level level, final String message, final Throwable throwable )
2546 {
2547 if ( level == null )
2548 {
2549 throw new NullPointerException( "level" );
2550 }
2551
2552 if ( this.isLoggable( level ) )
2553 {
2554 for ( int i = this.getListeners().size() - 1; i >= 0; i-- )
2555 {
2556 this.getListeners().get( i ).onLog( level, message, throwable );
2557 }
2558 }
2559 }
2560
2561 private String getJavaPackageName( final String identifier )
2562 {
2563 if ( identifier == null )
2564 {
2565 throw new NullPointerException( "identifier" );
2566 }
2567
2568 final int idx = identifier.lastIndexOf( '.' );
2569 return idx != -1 ? identifier.substring( 0, idx ) : "";
2570 }
2571
2572 private Template findVelocityTemplate( final String location ) throws IOException
2573 {
2574 try
2575 {
2576 return this.getVelocityEngine().getTemplate( location, this.getTemplateEncoding() );
2577 }
2578 catch ( final ResourceNotFoundException e )
2579 {
2580 if ( this.isLoggable( Level.FINER ) )
2581 {
2582 this.log( Level.FINER, getMessage( "templateNotFound", location ), null );
2583 }
2584
2585 return null;
2586 }
2587 catch ( final ParseErrorException e )
2588 {
2589 String m = getMessage( e );
2590 m = m == null ? "" : " " + m;
2591
2592
2593 throw (IOException) new IOException( getMessage( "invalidTemplate", location, m ) ).initCause( e );
2594 }
2595 catch ( final VelocityException e )
2596 {
2597 String m = getMessage( e );
2598 m = m == null ? "" : " " + m;
2599
2600
2601 throw (IOException) new IOException( getMessage( "velocityException", location, m ) ).initCause( e );
2602 }
2603 }
2604
2605 private java.util.Properties getTemplateProfileProperties( final String profileName, final String language )
2606 {
2607 Map<String, java.util.Properties> map =
2608 this.templateProfilePropertiesCache == null ? null : this.templateProfilePropertiesCache.get();
2609
2610 if ( map == null )
2611 {
2612 map = new HashMap<String, java.util.Properties>();
2613 this.templateProfilePropertiesCache = new SoftReference<Map<String, java.util.Properties>>( map );
2614 }
2615
2616 final String key = profileName + "|" + language;
2617 java.util.Properties profileProperties = map.get( key );
2618
2619 if ( profileProperties == null )
2620 {
2621 InputStream in = null;
2622 profileProperties = new java.util.Properties();
2623 final String resourceName = "/" + TEMPLATE_PREFIX + profileName + ( language == null ? "" : "/" + language )
2624 + "/context.properties";
2625
2626 try
2627 {
2628 in = this.getClass().getResourceAsStream( resourceName );
2629
2630 if ( in != null )
2631 {
2632 if ( this.isLoggable( Level.CONFIG ) )
2633 {
2634 this.log( Level.CONFIG, getMessage( "contextPropertiesFound", resourceName ), null );
2635 }
2636
2637 profileProperties.load( in );
2638 }
2639 else if ( this.isLoggable( Level.CONFIG ) )
2640 {
2641 this.log( Level.CONFIG, getMessage( "contextPropertiesNotFound", resourceName ), null );
2642 }
2643
2644 map.put( key, profileProperties );
2645 }
2646 catch ( final IOException e )
2647 {
2648 this.log( Level.SEVERE, getMessage( e ), e );
2649 }
2650 finally
2651 {
2652 try
2653 {
2654 if ( in != null )
2655 {
2656 in.close();
2657 }
2658 }
2659 catch ( final IOException e )
2660 {
2661 this.log( Level.SEVERE, getMessage( e ), e );
2662 }
2663 }
2664 }
2665
2666 return profileProperties;
2667 }
2668
2669 private void mergeTemplateProfileProperties( final String profileName, final String language,
2670 final VelocityContext velocityContext )
2671 {
2672 final java.util.Properties templateProfileProperties =
2673 this.getTemplateProfileProperties( profileName, language );
2674
2675 for ( final Enumeration<?> e = templateProfileProperties.propertyNames(); e.hasMoreElements(); )
2676 {
2677 final String name = e.nextElement().toString();
2678 final String value = templateProfileProperties.getProperty( name );
2679 final String[] values = value.split( "\\|" );
2680
2681 if ( !velocityContext.containsKey( name ) )
2682 {
2683 try
2684 {
2685 if ( values.length > 1 )
2686 {
2687 final Class<?> valueClass = Class.forName( values[0] );
2688 velocityContext.put( name, valueClass.getConstructor( String.class ).newInstance( values[1] ) );
2689 }
2690 else if ( value.contains( "|" ) )
2691 {
2692 velocityContext.put( name, Class.forName( values[0] ).newInstance() );
2693 }
2694 else
2695 {
2696 velocityContext.put( name, value );
2697 }
2698 }
2699 catch ( final InstantiationException ex )
2700 {
2701 this.log( Level.SEVERE, getMessage( ex ), ex );
2702 }
2703 catch ( final IllegalAccessException ex )
2704 {
2705 this.log( Level.SEVERE, getMessage( ex ), ex );
2706 }
2707 catch ( final InvocationTargetException ex )
2708 {
2709 this.log( Level.SEVERE, getMessage( ex ), ex );
2710 }
2711 catch ( final NoSuchMethodException ex )
2712 {
2713 this.log( Level.SEVERE, getMessage( ex ), ex );
2714 }
2715 catch ( final ClassNotFoundException ex )
2716 {
2717 this.log( Level.SEVERE, getMessage( ex ), ex );
2718 }
2719 }
2720 }
2721 }
2722
2723 private Set<String> getJavaKeywords()
2724 {
2725 Reader in = null;
2726 Set<String> set = this.javaKeywordsCache == null ? null : this.javaKeywordsCache.get();
2727
2728 try
2729 {
2730 if ( set == null )
2731 {
2732 set = new HashSet<String>( 64 );
2733 this.javaKeywordsCache = new SoftReference<Set<String>>( set );
2734 }
2735
2736 in = new InputStreamReader( this.getClass().getResourceAsStream(
2737 "/" + this.getClass().getPackage().getName().replace( ".", "/" ) + "/JavaKeywords.txt" ), "UTF-8" );
2738
2739 set.addAll( IOUtils.readLines( in ) );
2740 }
2741 catch ( final IOException e )
2742 {
2743 throw new IllegalStateException( getMessage( e ), e );
2744 }
2745 finally
2746 {
2747 try
2748 {
2749 if ( in != null )
2750 {
2751 in.close();
2752 }
2753 }
2754 catch ( final IOException e )
2755 {
2756 throw new IllegalStateException( getMessage( e ), e );
2757 }
2758 }
2759
2760 return set;
2761 }
2762
2763 private static String getMessage( final String key, final Object... arguments )
2764 {
2765 return MessageFormat.format( ResourceBundle.getBundle(
2766 JomcTool.class.getName().replace( '.', '/' ) ).getString( key ), arguments );
2767
2768 }
2769
2770 private static String getMessage( final Throwable t )
2771 {
2772 return t != null ? t.getMessage() != null ? t.getMessage() : getMessage( t.getCause() ) : null;
2773 }
2774
2775 }