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