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