1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package edu.internet2.middleware.grouper.util;
20
21 import java.beans.PropertyDescriptor;
22 import java.io.BufferedReader;
23 import java.io.Closeable;
24 import java.io.File;
25 import java.io.FileInputStream;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.io.InputStreamReader;
29 import java.io.OutputStream;
30 import java.io.PrintWriter;
31 import java.io.PushbackInputStream;
32 import java.io.Reader;
33 import java.io.StringWriter;
34 import java.io.UnsupportedEncodingException;
35 import java.io.Writer;
36 import java.lang.annotation.Annotation;
37 import java.lang.reflect.Array;
38 import java.lang.reflect.Constructor;
39 import java.lang.reflect.Field;
40 import java.lang.reflect.InvocationTargetException;
41 import java.lang.reflect.Method;
42 import java.lang.reflect.Modifier;
43 import java.math.BigDecimal;
44 import java.net.InetAddress;
45 import java.net.ServerSocket;
46 import java.net.URL;
47 import java.net.URLDecoder;
48 import java.net.URLEncoder;
49 import java.nio.charset.StandardCharsets;
50 import java.security.CodeSource;
51 import java.security.MessageDigest;
52 import java.security.NoSuchAlgorithmException;
53 import java.sql.Connection;
54 import java.sql.ResultSet;
55 import java.sql.SQLException;
56 import java.sql.Statement;
57 import java.sql.Timestamp;
58 import java.text.DateFormat;
59 import java.text.DecimalFormat;
60 import java.text.Normalizer;
61 import java.text.ParseException;
62 import java.text.SimpleDateFormat;
63 import java.util.ArrayList;
64 import java.util.Arrays;
65 import java.util.Calendar;
66 import java.util.Collection;
67 import java.util.Collections;
68 import java.util.Comparator;
69 import java.util.Date;
70 import java.util.Enumeration;
71 import java.util.HashMap;
72 import java.util.HashSet;
73 import java.util.Iterator;
74 import java.util.LinkedHashMap;
75 import java.util.LinkedHashSet;
76 import java.util.List;
77 import java.util.Map;
78 import java.util.Properties;
79 import java.util.Set;
80 import java.util.TimeZone;
81 import java.util.TreeSet;
82 import java.util.concurrent.Callable;
83 import java.util.concurrent.ExecutorService;
84 import java.util.concurrent.Executors;
85 import java.util.concurrent.Future;
86 import java.util.concurrent.ThreadFactory;
87 import java.util.regex.Matcher;
88 import java.util.regex.Pattern;
89
90 import javax.xml.stream.XMLStreamException;
91 import javax.xml.stream.XMLStreamWriter;
92
93 import org.apache.commons.beanutils.PropertyUtils;
94 import org.apache.commons.codec.binary.Base64;
95 import org.apache.commons.io.FileUtils;
96 import org.apache.commons.jexl2.Expression;
97 import org.apache.commons.jexl2.JexlContext;
98 import org.apache.commons.jexl2.JexlEngine;
99 import org.apache.commons.jexl2.JexlException;
100 import org.apache.commons.jexl2.MapContext;
101 import org.apache.commons.jexl2.Script;
102 import org.apache.commons.jexl3.JexlBuilder;
103 import org.apache.commons.jexl3.JxltEngine;
104 import org.apache.commons.jexl3.JxltEngine.Template;
105 import org.apache.commons.lang.StringUtils;
106 import org.apache.commons.lang.exception.ExceptionUtils;
107 import org.apache.commons.lang.exception.Nestable;
108 import org.apache.commons.logging.Log;
109 import org.apache.commons.logging.LogFactory;
110 import org.apache.commons.logging.impl.Log4JLogger;
111 import org.apache.commons.validator.routines.EmailValidator;
112 import org.apache.log4j.Appender;
113 import org.apache.log4j.Category;
114 import org.apache.log4j.ConsoleAppender;
115 import org.apache.log4j.FileAppender;
116 import org.codehaus.groovy.tools.shell.ExitNotification;
117 import org.hibernate.Session;
118 import org.hibernate.Transaction;
119 import org.hibernate.cfg.Configuration;
120 import org.hibernate.resource.transaction.spi.TransactionStatus;
121 import org.ldaptive.io.Hex;
122
123 import com.fasterxml.jackson.databind.JsonNode;
124 import com.fasterxml.jackson.databind.ObjectMapper;
125 import com.fasterxml.jackson.databind.node.ArrayNode;
126 import com.fasterxml.jackson.databind.node.NullNode;
127 import com.fasterxml.jackson.databind.node.ObjectNode;
128 import com.unboundid.ldap.sdk.DN;
129 import com.unboundid.ldap.sdk.LDAPException;
130 import com.unboundid.ldap.sdk.RDN;
131
132 import edu.internet2.middleware.grouper.Group;
133 import edu.internet2.middleware.grouper.GrouperSession;
134 import edu.internet2.middleware.grouper.Stem;
135 import edu.internet2.middleware.grouper.StemFinder;
136 import edu.internet2.middleware.grouper.app.gsh.GrouperGroovyRuntime;
137 import edu.internet2.middleware.grouper.app.gsh.GrouperGroovysh;
138 import edu.internet2.middleware.grouper.app.loader.OtherJobScript;
139 import edu.internet2.middleware.grouper.cache.GrouperCache;
140 import edu.internet2.middleware.grouper.cfg.GrouperConfig;
141 import edu.internet2.middleware.grouper.cfg.GrouperHibernateConfig;
142 import edu.internet2.middleware.grouper.exception.ExpressionLanguageMissingVariableException;
143 import edu.internet2.middleware.grouper.hibernate.HibUtils;
144 import edu.internet2.middleware.grouper.hooks.logic.HookVeto;
145 import edu.internet2.middleware.grouper.misc.GrouperCloneable;
146 import edu.internet2.middleware.grouper.misc.GrouperId;
147 import edu.internet2.middleware.grouper.misc.GrouperStartup;
148 import edu.internet2.middleware.grouper.subj.GrouperSubject;
149 import edu.internet2.middleware.grouperClient.collections.MultiKey;
150 import edu.internet2.middleware.grouperClient.util.ExpirableCache;
151 import edu.internet2.middleware.grouperClient.util.GrouperClientUtils;
152 import edu.internet2.middleware.subject.Source;
153 import edu.internet2.middleware.subject.Subject;
154 import edu.internet2.middleware.subject.provider.SourceManager;
155 import javassist.util.proxy.ProxyObject;
156 import net.sf.json.JSONObject;
157 import net.sf.json.JsonConfig;
158 import net.sf.json.util.PropertyFilter;
159
160
161
162
163
164
165
166
167 public class GrouperUtil {
168
169 public static void main(String[] args) throws Exception {
170
171 GrouperStartup.startup();
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283 GrouperSession.startRootSession();
284 OtherJobScripter/OtherJobScript.html#OtherJobScript">OtherJobScript otherJobScript = new OtherJobScript();
285 otherJobScript.execute("OTHER_JOB_deleteNgssWsProxyCache", null);
286
287 }
288
289
290
291
292
293
294
295
296 public static String gshRunScript(String script) {
297 return gshRunScript(script, false);
298 }
299
300
301
302
303
304
305
306
307
308
309 public static String gshRunScript(String script, boolean lightWeight) {
310 GrouperGroovysh.GrouperGroovyResult grouperGroovyResult = GrouperGroovysh.runScript(script, lightWeight);
311 String output = grouperGroovyResult.fullOutput();
312 return output;
313 }
314
315 public static void setClear(Set<?> set) {
316 if (set != null) {
317 set.clear();
318 }
319 }
320
321
322
323
324
325
326 public static void exceptionFinallyInjectOrThrow(Exception tryException,
327 Exception finallyException) {
328 if (tryException != null) {
329 GrouperUtil.injectInException(tryException, "\n\n####FINALLY EXCEPTION START####\n\n" + GrouperUtil.getFullStackTrace(finallyException) + "\n\n####FINALLY EXCEPTION END####\n\n");
330 } else {
331 tryException = finallyException;
332 }
333 if (tryException instanceof RuntimeException) {
334 throw (RuntimeException)tryException;
335 }
336 throw new RuntimeException(tryException);
337 }
338
339
340
341
342
343
344
345
346
347 public static String normalize(String form, String text) {
348 if (text == null) {
349 return text;
350 }
351 Normalizer.Form formEnum = Normalizer.Form.valueOf(text);
352 return Normalizer.normalize(text, formEnum);
353
354 }
355
356
357
358
359
360 private final static Map<MultiKey, JexlEngine> jexlEngines = new HashMap<MultiKey, JexlEngine>();
361
362
363
364
365 private static boolean jexlEnginesInitialized = false;
366
367
368
369
370 static {
371 {
372 Boolean silent = true;
373 Boolean lenient = true;
374 final JexlEngine jexlEngine = new JexlEngine();
375 jexlEngine.setSilent(silent);
376 jexlEngine.setLenient(lenient);
377 jexlEngines.put(new MultiKey(silent, lenient), jexlEngine);
378 }
379 {
380 Boolean silent = false;
381 Boolean lenient = true;
382 final JexlEngine jexlEngine = new JexlEngine();
383 jexlEngine.setSilent(silent);
384 jexlEngine.setLenient(lenient);
385 jexlEngines.put(new MultiKey(silent, lenient), jexlEngine);
386 }
387 {
388 Boolean silent = true;
389 Boolean lenient = false;
390 final JexlEngine jexlEngine = new JexlEngine();
391 jexlEngine.setSilent(silent);
392 jexlEngine.setLenient(lenient);
393 jexlEngines.put(new MultiKey(silent, lenient), jexlEngine);
394 }
395 {
396 Boolean silent = false;
397 Boolean lenient = false;
398 final JexlEngine jexlEngine = new JexlEngine();
399 jexlEngine.setSilent(silent);
400 jexlEngine.setLenient(lenient);
401 jexlEngines.put(new MultiKey(silent, lenient), jexlEngine);
402 }
403 }
404
405
406 private static ThreadLocal<Map<String, Map<String, String>>> propertiesThreadLocalOverrideMap = new ThreadLocal<Map<String, Map<String, String>>>();
407
408
409
410 private static ThreadLocal<Boolean> inRetriableCode = new InheritableThreadLocal<Boolean>();
411
412
413
414
415 public static boolean isInRetriableCode() {
416 Boolean threadlocalBoolean = inRetriableCode.get();
417 return threadlocalBoolean != null && threadlocalBoolean;
418 }
419
420
421
422
423 public static void threadLocalInRetriableCodeAssign() {
424 inRetriableCode.set(true);
425 }
426
427
428
429
430
431 public static void threadLocalInRetriableCodeClear() {
432 inRetriableCode.remove();
433 }
434
435
436
437
438
439
440 public static String splitTrimEmailAddresses(String emailAddresses) {
441
442 return normalizeEmailAddresses(emailAddresses);
443 }
444
445
446
447
448
449
450 public static String normalizeEmailAddresses(String emailAddresses) {
451 if (emailAddresses == null) {
452 return null;
453 }
454 emailAddresses = StringUtils.replace(emailAddresses, ",", " ");
455 emailAddresses = StringUtils.replace(emailAddresses, ";", " ");
456 emailAddresses = StringUtils.replace(emailAddresses, "\n", " ");
457 emailAddresses = StringUtils.replace(emailAddresses, "\t", " ");
458 emailAddresses = StringUtils.replace(emailAddresses, "\r", " ");
459 emailAddresses = join(splitTrim(emailAddresses, " "), ";");
460 return emailAddresses;
461 }
462
463
464
465
466
467
468 public static boolean validEmail(String email) {
469 return EmailValidator.getInstance(false, true).isValid(email);
470 }
471
472
473
474
475
476
477
478 public static boolean subjectHasAttribute(Subject subject, String attributeName) {
479 if (subject == null) {
480 return false;
481 }
482 String attributeValue = subject.getAttributeValue(attributeName);
483 return !isBlank(attributeValue);
484 }
485
486
487
488
489
490
491
492
493
494 public static boolean matchSqlString(String sqlMatcher, String testText) {
495
496
497 String regexString = StringUtils.replace(sqlMatcher, "\\", "\\\\");
498
499
500 regexString = replace(regexString,
501 new String[]{"$", "^", "*", "(", ")", "+", "[", "{", "]", "}", "|", "\"", ".", "?"},
502 new String[]{"\\$", "\\^", "\\*", "\\(", "\\)", "\\+", "\\[", "\\{", "\\]", "\\}", "\\|", "\"", "\\.", "\\?", });
503
504
505 regexString = StringUtils.replace(regexString, "_", ".");
506 regexString = "^" + StringUtils.replace(regexString, "%", ".*") + "$";
507
508 Pattern pattern = Pattern.compile(regexString, Pattern.DOTALL);
509 Matcher matcher = pattern.matcher(testText);
510 return matcher.matches();
511 }
512
513
514
515
516
517
518
519
520 public static <T> Set<T> setShorten(Set<T> theSet, int maxSize) {
521
522 if (length(theSet) < maxSize) {
523 return theSet;
524 }
525
526
527 Set<T> newList = new LinkedHashSet<T>();
528 int i=0;
529
530
531 for (T t : theSet) {
532
533 if (i>=maxSize) {
534 break;
535 }
536
537 newList.add(t);
538 i++;
539 }
540 return newList;
541 }
542
543
544
545
546
547
548 public static String formatNumberWithCommas(Long number) {
549 if (number == null) {
550 return "null";
551 }
552 DecimalFormat df = new DecimalFormat();
553 return df.format(number);
554 }
555
556
557
558
559
560
561
562 public static int compare(Comparable first, Comparable second) {
563 if (first == second) {
564 return 0;
565 }
566 if (first == null) {
567 return -1;
568 }
569 if (second == null) {
570 return 1;
571 }
572 return first.compareTo(second);
573 }
574
575
576
577
578
579
580 public static Set<Source> convertSources(String sources) {
581 if (StringUtils.isBlank(sources)) {
582 return null;
583 }
584 String[] sourceStrings = splitTrim(sources, ",");
585
586 Set<Source> sourceSet = new HashSet<Source>();
587 for (String source : sourceStrings) {
588 sourceSet.add(SourceManager.getInstance().getSource(source));
589 }
590
591 return sourceSet;
592 }
593
594
595
596
597
598
599
600 public static Set<Source> convertSources(String[] sourceIds) {
601 if (length(sourceIds) == 0) {
602 return null;
603 }
604 Set<Source> sourceSet = new HashSet<Source>();
605 for (String source : sourceIds) {
606 if (!StringUtils.isBlank(source)) {
607 sourceSet.add(SourceManager.getInstance().getSource(source));
608 }
609 }
610
611 return sourceSet;
612 }
613
614
615
616
617
618
619 public static String escapeSingleQuotes(String string) {
620 if (string == null) {
621 return string;
622 }
623 return string.replace("'", "\'");
624 }
625
626
627
628
629
630
631 public static String escapeDoubleQuotes(String string) {
632 if (string == null) {
633 return string;
634 }
635 return string.replace("\"", """);
636 }
637
638
639
640
641
642
643 public static String escapeDoubleQuotesForString(String string) {
644 if (string == null) {
645 return string;
646 }
647 return string.replace("\"", "\\\"");
648 }
649
650
651
652
653
654
655 public static String escapeDoubleQuotesSlashesAndNewlinesForString(String string) {
656
657 string = escapeSlashesForString(string);
658 string = escapeNewlinesForString(string);
659 string = escapeDoubleQuotesForString(string);
660 return string;
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679 }
680
681
682
683
684
685
686 public static String escapeNewlinesForString(String string) {
687 if (string == null) {
688 return string;
689 }
690 return string.replace("\n", "\\n");
691 }
692
693
694
695
696
697
698 public static String escapeSlashesForString(String string) {
699 if (string == null) {
700 return string;
701 }
702 return string.replace("\\", "\\\\");
703 }
704
705
706
707
708
709
710
711 @Deprecated
712 public static String convertSourcesToSqlInString(Set<Source> sources) {
713 return HibUtils.convertSourcesToSqlInString(sources);
714 }
715
716
717
718
719
720
721 public static Map<String, String> toMap(String... strings) {
722 Map<String, String> map = new LinkedHashMap<String, String>();
723 if (strings != null) {
724 if (strings.length % 2 != 0) {
725 throw new RuntimeException("Must pass in an even number of strings: " + strings.length);
726 }
727 for (int i=0;i<strings.length;i+=2) {
728 map.put(strings[i], strings[i+1]);
729 }
730 }
731 return map;
732 }
733
734
735
736
737
738
739
740 public static Map<String, Object> toStringObjectMap(Object... stringObjects) {
741 Map<String, Object> map = new LinkedHashMap<String, Object>();
742 if (stringObjects != null) {
743 if (stringObjects.length % 2 != 0) {
744 throw new RuntimeException("Must pass in an even number of strings: " + stringObjects.length);
745 }
746 for (int i=0;i<stringObjects.length;i+=2) {
747 String key = (String)stringObjects[i];
748 map.put(key, stringObjects[i+1]);
749 }
750 }
751 return map;
752 }
753
754
755
756
757
758
759 public static String convertMillisToFriendlyString(Integer duration) {
760 if (duration == null) {
761 return convertMillisToFriendlyString((Long)null);
762 }
763 return convertMillisToFriendlyString(new Long(duration.intValue()));
764 }
765
766
767
768
769
770
771 public static String convertMillisToFriendlyString(Long duration) {
772
773 if (duration == null) {
774 return "";
775 }
776
777 if (duration < 1000) {
778 return duration + "ms";
779 }
780
781 long ms = duration % 1000;
782 duration = duration / 1000;
783 long s = duration % 60;
784 duration = duration / 60;
785
786 if (duration == 0) {
787 return s + "s, " + ms + "ms";
788 }
789
790 long m = duration % 60;
791 duration = duration / 60;
792
793 if (duration == 0) {
794 return m + "m, " + s + "s, " + ms + "ms";
795 }
796
797 long h = duration % 24;
798 duration = duration / 24;
799
800 if (duration == 0) {
801 return h + "h, " + m + "m, " + s + "s, " + ms + "ms";
802 }
803
804 long d = duration;
805
806 return d + "d, " + h + "h, " + m + "m, " + s + "s, " + ms + "ms";
807 }
808
809
810
811
812
813 public static void deleteFile(File file) {
814
815 if (file.exists()) {
816 if (!file.delete()) {
817 throw new RuntimeException("Couldnt delete file: " + file.toString());
818 }
819 }
820 }
821
822
823
824
825
826
827
828
829
830 public static String argAfter(String[] args, String argBefore) {
831 if (length(args) <= 1) {
832 return null;
833 }
834 int argBeforeIndex = -1;
835 for (int i=0;i<args.length;i++) {
836 if (equals(args[i], argBefore)) {
837 argBeforeIndex = i;
838 break;
839 }
840 }
841 if (argBeforeIndex == -1) {
842 throw new RuntimeException("Cant find arg before");
843 }
844 if (argBeforeIndex < args.length - 1) {
845 return args[argBeforeIndex + 1];
846 }
847 return null;
848 }
849
850
851
852
853
854
855
856 public static void append(StringBuilder result,
857 String separatorIfResultNotEmpty, String stringToAppend) {
858 if (result.length() != 0) {
859 result.append(separatorIfResultNotEmpty);
860 }
861 result.append(stringToAppend);
862 }
863
864
865
866
867 public static final String LOG_ERROR = "Error trying to make parent dirs for logger or logging first statement, check to make " +
868 "sure you have proper file permissions, and that your servlet container is giving " +
869 "your app rights to access the log directory (e.g. for tomcat set TOMCAT5_SECURITY=no), g" +
870 "oogle it for more info";
871
872
873
874
875 public static final long ONE_KB = 1024;
876
877
878
879
880 public static final long ONE_MB = ONE_KB * ONE_KB;
881
882
883
884
885 public static final long ONE_GB = ONE_KB * ONE_MB;
886
887
888
889
890 static String grouperHome;
891
892 static {
893
894 String theGrouperHome = System.getProperty("grouper.home");
895 if (isBlank(theGrouperHome)) {
896 grouperHome = new File("").getAbsolutePath();
897 } else {
898 grouperHome = theGrouperHome;
899 }
900 }
901
902
903
904
905
906
907
908
909
910
911 public static String byteCountToDisplaySize(long size) {
912 String displaySize;
913
914 if (size / ONE_GB > 0) {
915 displaySize = String.valueOf(size / ONE_GB) + " GB";
916 } else if (size / ONE_MB > 0) {
917 displaySize = String.valueOf(size / ONE_MB) + " MB";
918 } else if (size / ONE_KB > 0) {
919 displaySize = String.valueOf(size / ONE_KB) + " KB";
920 } else {
921 displaySize = String.valueOf(size) + " bytes";
922 }
923
924 return displaySize;
925 }
926
927
928
929
930
931 public static Log getLog(Class<?> theClass) {
932 logDirsCreateIfNotDone();
933 return LogFactory.getLog(theClass);
934 }
935
936
937
938
939 private static boolean logDirsCreated = false;
940
941
942 public static void fileCopy(File src, File dest) {
943 try {
944 FileUtils.copyFile(src, dest);
945 } catch (IOException ioe) {
946 throw new RuntimeException("Problem copying: " + (src == null ? null : src.getAbsolutePath()) + " to: " + (dest == null ? null : dest.getAbsolutePath()));
947 }
948 }
949
950
951
952
953
954
955 public static void fileCopyExampleResourceIfNotExist(String exampleResource, String resource) {
956 try {
957
958 if (GrouperUtil.computeUrl(resource, true) != null) {
959 return;
960 }
961 File fileResource = GrouperUtil.fileFromResourceName(resource);
962 if (fileResource == null || !fileResource.exists()) {
963 throw new RuntimeException("File doesnt exist: " + resource);
964 }
965
966 } catch (RuntimeException re) {
967 try {
968
969 File exampleFile = GrouperUtil.fileFromResourceName(exampleResource);
970
971 fileCopy(exampleFile, new File(exampleFile.getParentFile() + File.separator + resource));
972 } catch (RuntimeException re2) {
973
974 throw re;
975 }
976 }
977
978 }
979
980
981
982
983 public static void logDirsCreateIfNotDone() {
984 if (logDirsCreated) {
985 return;
986 }
987 logDirsCreated = true;
988
989 String location = "log4j.properties";
990
991 fileCopyExampleResourceIfNotExist("log4j.example.properties", location);
992 Properties properties = propertiesFromResourceName(location);
993 Set<String> keySet = (Set<String>)(Object)properties.keySet();
994 for (String key : keySet) {
995
996 if (key.endsWith(".File")) {
997 try {
998 String fileName = properties.getProperty(key);
999 if(fileName.startsWith("${grouper.home}")) {
1000 if(grouperHome==null) {
1001 throw new IllegalStateException("The System property grouper.home is referenced in log4j configuration " +
1002 "however, it is not set.");
1003 }
1004 if (!grouperHome.endsWith("/") && !grouperHome.endsWith("\\")) {
1005 fileName = grouperHome + File.separator + fileName.substring(15);
1006 } else {
1007 fileName = grouperHome + fileName.substring(15);
1008 }
1009 }
1010 File file = new File(fileName);
1011 File parent = file.getParentFile();
1012
1013 if (parent != null && !parent.exists()) {
1014
1015 System.out.println("Grouper warning: parent dir of log file doesnt exist: " + fileCanonicalPath(parent));
1016
1017 mkdirs(parent);
1018 System.out.println("Grouper note: auto-created parent dir of log file: " + fileCanonicalPath(parent));
1019
1020 }
1021
1022 } catch (RuntimeException re) {
1023
1024 System.err.println(LOG_ERROR);
1025 re.printStackTrace();
1026 throw new RuntimeException(LOG_ERROR, re);
1027 }
1028 }
1029 }
1030 }
1031
1032
1033
1034
1035
1036
1037
1038 public static void logErrorNextException(Log log, Throwable throwable, int timeToLive) {
1039 if (throwable == null) {
1040 return;
1041 }
1042 if (timeToLive < 0) {
1043 throw new RuntimeException("TimeToLive less than 0", throwable);
1044 }
1045
1046 if (throwable instanceof SQLException) {
1047 SQLException sqlException = (SQLException)throwable;
1048 SQLException nextException = sqlException.getNextException();
1049 if (nextException != null) {
1050 if (isInRetriableCode()) {
1051 log.info("Next exception (note, this will be retried so it might not be an issue)", nextException);
1052 } else {
1053 log.error("Next exception", nextException);
1054 }
1055
1056 logErrorNextException(log, nextException, timeToLive-1);
1057 }
1058 }
1059
1060 Throwable cause = throwable.getCause();
1061 if (cause != null) {
1062 logErrorNextException(log, cause, timeToLive-1);
1063 }
1064
1065 }
1066
1067
1068
1069
1070
1071
1072
1073 public static boolean hasOption(int options, int option) {
1074 return (options & option) > 0;
1075 }
1076
1077
1078 private static Set<MultiKey> dbChangeWhitelist = new HashSet<MultiKey>();
1079
1080
1081
1082
1083 private static Boolean printGrouperLogsToConsole = null;
1084
1085
1086
1087
1088
1089 public static boolean isPrintGrouperLogsToConsole() {
1090 if (printGrouperLogsToConsole == null) {
1091 logDirPrint();
1092 }
1093 return printGrouperLogsToConsole;
1094 }
1095
1096
1097
1098
1099
1100
1101 public static String fileCanonicalPath(File file) {
1102 try {
1103 return file.getCanonicalPath();
1104 } catch (IOException ioe) {
1105 throw new RuntimeException("Problem with file: " + file.getAbsolutePath(), ioe);
1106 }
1107 }
1108
1109
1110
1111
1112 private static String logDirMessage = null;
1113
1114
1115
1116
1117
1118 public static String logDirPrint() {
1119 logDirsCreateIfNotDone();
1120
1121 if (printGrouperLogsToConsole != null) {
1122 return logDirMessage;
1123 }
1124 StringBuilder resultMessage = new StringBuilder();
1125 printGrouperLogsToConsole = false;
1126 Log rootLogger = LogFactory.getLog("edu.internet2.middleware.grouper");
1127 StringBuilder rootLoggerAppender = new StringBuilder();
1128 boolean writesLogs = false;
1129
1130
1131 if (rootLogger instanceof Log4JLogger) {
1132 Category log4jLogger = ((Log4JLogger)rootLogger).getLogger();
1133 int timeToLive = 30;
1134
1135
1136 while (log4jLogger.getLevel() == null) {
1137 Category parent = log4jLogger.getParent();
1138 if (parent == null) {
1139 break;
1140 }
1141 log4jLogger = parent;
1142 if (timeToLive-- < 0) {
1143 break;
1144 }
1145 }
1146
1147 Set<Appender> allAppenders = new LinkedHashSet<Appender>();
1148 Category currentAppenderLogger = log4jLogger;
1149 while (currentAppenderLogger != null) {
1150 Enumeration allAppendersEnumeration = currentAppenderLogger.getAllAppenders();
1151 while (allAppendersEnumeration.hasMoreElements()) {
1152 allAppenders.add((Appender)allAppendersEnumeration.nextElement());
1153 }
1154 currentAppenderLogger = currentAppenderLogger.getParent();
1155 }
1156
1157 for (Appender appender : allAppenders) {
1158 writesLogs = true;
1159 if (appender instanceof ConsoleAppender) {
1160 printGrouperLogsToConsole = true;
1161 rootLoggerAppender.append("console, ");
1162 } else if (appender instanceof FileAppender) {
1163 String path = ((FileAppender)appender).getFile();
1164 if (isBlank(path)) {
1165 resultMessage.append("Grouper error, file appender path is empty, maybe dir doesnt exist\n");
1166 } else {
1167 File logFile = new File(path);
1168 if (logFile.getParentFile() != null && !logFile.getParentFile().exists()) {
1169 resultMessage.append("Grouper warning: parent dir of log file doesnt exist: " + logFile.getAbsolutePath() + "\n");
1170 mkdirs(logFile.getParentFile());
1171 resultMessage.append("Grouper note: auto-created parent dir of log file: " + logFile.getAbsolutePath() + "\n");
1172 }
1173 rootLoggerAppender.append(logFile.getAbsolutePath()).append(", ");
1174 }
1175 } else {
1176 rootLoggerAppender.append("appender type: " + appender.getClass().getSimpleName()).append(", ");
1177 }
1178 }
1179 if (!writesLogs || !rootLogger.isErrorEnabled()) {
1180 resultMessage.append("Grouper warning, it is detected that you are not logging errors for " +
1181 "package edu.internet2.middleware.grouper, you should enable logging at " +
1182 "least at the WARN level in log4j.properties\n");
1183 } else {
1184 if (rootLogger.isErrorEnabled() && !rootLogger.isWarnEnabled()) {
1185 resultMessage.append("Grouper warning, it is detected that you are logging " +
1186 "edu.internet2.middleware.grouper as ERROR and not WARN level. It is " +
1187 "recommended to log at at least WARN level in log4j.properties\n");
1188 }
1189 String logLevel = null;
1190 if (rootLogger.isTraceEnabled()) {
1191 logLevel = "TRACE";
1192 } else if (rootLogger.isDebugEnabled()) {
1193 logLevel = "DEBUG";
1194 } else if (rootLogger.isInfoEnabled()) {
1195 logLevel = "INFO";
1196 } else if (rootLogger.isWarnEnabled()) {
1197 logLevel = "WARN";
1198 } else if (rootLogger.isErrorEnabled()) {
1199 logLevel = "ERROR";
1200 } else if (rootLogger.isFatalEnabled()) {
1201 logLevel = "FATAL";
1202 }
1203 resultMessage.append("Grouper is logging to file: " + rootLoggerAppender + "at min level "
1204 + logLevel + " for package: edu.internet2.middleware.grouper, based on log4j.properties\n");
1205 }
1206 } else {
1207 resultMessage.append("Grouper logs are not using log4j: " + (rootLogger == null ? null : rootLogger.getClass()) + "\n");
1208 }
1209 logDirMessage = resultMessage.toString();
1210 return logDirMessage;
1211 }
1212
1213
1214
1215
1216
1217
1218
1219 public static String suffixAfterChar(String input, char theChar) {
1220 if (input == null) {
1221 return null;
1222 }
1223
1224 int lastIndex = input.lastIndexOf(theChar);
1225 if (lastIndex > -1) {
1226 input = input.substring(lastIndex + 1, input.length());
1227 }
1228 return input;
1229 }
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239 public static String oracleStandardNameFromJava(String javaName) {
1240
1241 StringBuilder result = new StringBuilder();
1242
1243 if ((javaName == null) || (0 == "".compareTo(javaName))) {
1244 return javaName;
1245 }
1246
1247
1248 javaName = suffixAfterChar(javaName, '.');
1249
1250
1251 result.append(javaName.charAt(0));
1252
1253 char currChar;
1254
1255 boolean previousCap = false;
1256
1257
1258 for (int i = 1; i < javaName.length(); i++) {
1259 currChar = javaName.charAt(i);
1260
1261
1262 if (!previousCap && (currChar >= 'A') && (currChar <= 'Z')) {
1263 result.append("_");
1264 }
1265
1266 result.append(currChar);
1267 if ((currChar >= 'A') && (currChar <= 'Z')) {
1268 previousCap = true;
1269 } else {
1270 previousCap = false;
1271 }
1272 }
1273
1274
1275 return result.toString().toUpperCase();
1276 }
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288 public static <K,V> boolean mapEquals(Map<K,V> first, Map<K,V> second) {
1289 Set<K> keysMismatch = new HashSet<K>();
1290 mapDifferences(first, second, keysMismatch, null);
1291
1292 return keysMismatch.size() == 0;
1293
1294 }
1295
1296
1297
1298
1299 private static final Map EMPTY_MAP = Collections.unmodifiableMap(new HashMap());
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311 public static <K,V> void mapDifferences(Map<K,V> first, Map<K,V> second, Set<K> differences, String prefix) {
1312 if (first == second) {
1313 return;
1314 }
1315
1316 if (first == null) {
1317 first = EMPTY_MAP;
1318 }
1319 if (second == null) {
1320 second = EMPTY_MAP;
1321 } else {
1322
1323 second = new LinkedHashMap<K,V>(second);
1324 }
1325 int firstSize = first == null ? 0 : first.size();
1326 int secondSize = second == null ? 0 : second.size();
1327
1328 if (firstSize == 0 && secondSize == 0) {
1329 return;
1330 }
1331
1332 for (K key : first.keySet()) {
1333
1334 if (second.containsKey(key)) {
1335 V firstValue = first.get(key);
1336 V secondValue = second.get(key);
1337
1338 second.remove(key);
1339 if (equals(firstValue, secondValue)) {
1340 continue;
1341 }
1342 }
1343 differences.add(isNotBlank(prefix) ? (K)(prefix + key) : key);
1344 }
1345
1346 for (K key : second.keySet()) {
1347 differences.add(isNotBlank(prefix) ? (K)(prefix + key) : key);
1348 }
1349 }
1350
1351
1352
1353
1354
1355 public static void sleep(long millis) {
1356 if (millis == 0) {
1357 return;
1358 }
1359 try {
1360 Thread.sleep(millis);
1361 } catch (InterruptedException ie) {
1362 throw new RuntimeException(ie);
1363 }
1364 }
1365
1366
1367
1368
1369
1370 public static void sleepWithStdoutCountdown(int seconds) {
1371 for (int i=seconds;i>0;i--) {
1372 System.out.println("Sleeping: " + i);
1373 sleep(1000);
1374 }
1375 }
1376
1377
1378
1379
1380
1381
1382 public synchronized static String encryptSha(String plaintext) {
1383 MessageDigest md = null;
1384 try {
1385 md = MessageDigest.getInstance("SHA");
1386 } catch (NoSuchAlgorithmException e) {
1387 throw new RuntimeException(e);
1388 }
1389 try {
1390 md.update(plaintext.getBytes("UTF-8"));
1391 } catch (UnsupportedEncodingException e) {
1392 throw new RuntimeException(e);
1393 }
1394 byte raw[] = md.digest();
1395 byte[] encoded = Base64.encodeBase64(raw);
1396 String hash = new String(encoded);
1397
1398 return hash;
1399 }
1400
1401
1402
1403
1404
1405
1406
1407 public static boolean injectInException(Throwable t, String message) {
1408
1409 String throwableFieldName = GrouperConfig.retrieveConfig().propertyValueString("throwable.data.field.name");
1410
1411 if (isBlank(throwableFieldName)) {
1412
1413 throwableFieldName = "detailMessage";
1414 }
1415 try {
1416 String currentValue = t.getMessage();
1417 if (!isBlank(currentValue)) {
1418 currentValue += ",\n" + message;
1419 } else {
1420 currentValue = message;
1421 }
1422 assignField(t, throwableFieldName, currentValue);
1423 return true;
1424 } catch (Throwable t2) {
1425
1426 return false;
1427 }
1428
1429 }
1430
1431
1432
1433
1434
1435
1436
1437
1438 public static boolean findGrouperPropertiesDbMatch(boolean whitelist, String user, String url) {
1439
1440
1441 Properties grouperProperties = GrouperConfig.retrieveConfig().properties();
1442
1443
1444
1445
1446
1447
1448
1449 int index = 0;
1450 String typeString = whitelist ? "allow" : "deny";
1451 while (true) {
1452 String currentUser = trim(grouperProperties.getProperty(
1453 "db.change." + typeString + ".user." + index));
1454 String currentUrl = trim(grouperProperties.getProperty(
1455 "db.change." + typeString + ".url." + index));
1456
1457
1458 if (isBlank(currentUser) || isBlank(currentUrl)) {
1459 break;
1460 }
1461 if (equals(currentUser, user) && equals(currentUrl, url)) {
1462 return true;
1463 }
1464 index++;
1465 }
1466 return false;
1467 }
1468
1469
1470 public static String PROMPT_KEY_SCHEMA_EXPORT_ALL_TABLES = "schemaexport all tables";
1471
1472
1473 public static String PROMPT_KEY_RESET_DATA = "delete all grouper data";
1474
1475
1476 public static boolean stopPromptingUser = false;
1477
1478
1479 private static Set<String> stopPromptingUserPrintlns = new HashSet<String>();
1480
1481
1482
1483
1484
1485
1486 public static void promptUserAboutDbChanges(String reason, boolean checkResponse) {
1487
1488 Properties grouperHibernateProperties = GrouperHibernateConfig.retrieveConfig().properties();
1489
1490 String url = trim(grouperHibernateProperties.getProperty("hibernate.connection.url"));
1491 String user = trim(grouperHibernateProperties.getProperty("hibernate.connection.username"));
1492
1493 promptUserAboutChanges(reason, checkResponse, "db", url, user);
1494 }
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507 public static String ldapConvertDnToSubPath(String dn, String baseDn, String searchDn) {
1508
1509
1510 if (StringUtils.isBlank(dn)) {
1511 return dn;
1512 }
1513
1514 if (!StringUtils.isBlank(baseDn)) {
1515 if (dn.endsWith(baseDn)) {
1516 dn = dn.substring(0, dn.length() - (baseDn.length()+1));
1517 }
1518 }
1519 if (!StringUtils.isBlank(searchDn)) {
1520 if (dn.endsWith(searchDn)) {
1521 dn = dn.substring(0, dn.length() - (searchDn.length()+1));
1522 }
1523 }
1524
1525 if (StringUtils.isBlank(dn)) {
1526 return dn;
1527 }
1528
1529 DN theDn = null;
1530 try {
1531 theDn = new DN(dn);
1532 } catch (LDAPException ldapException) {
1533 throw new RuntimeException("Cant parse DN: '" + dn + "'", ldapException);
1534 }
1535
1536 RDN[] rdns = theDn.getRDNs();
1537 StringBuilder path = new StringBuilder();
1538 for (int i=rdns.length-1;i>=0;i--) {
1539 RDN rdn = rdns[i];
1540 path.append(rdn.getAttributeValues()[0]);
1541 if (i != 0) {
1542 path.append(":");
1543 }
1544
1545 }
1546 return path.toString();
1547 }
1548
1549
1550
1551
1552
1553
1554
1555 public static String ldapConvertDnToSpecificValue(String dn) {
1556
1557
1558 if (StringUtils.isBlank(dn)) {
1559 return dn;
1560 }
1561 try {
1562 DN theDn = new DN(dn);
1563 RDN[] rdns = theDn.getRDNs();
1564 RDN firstRdn = rdns[0];
1565 return firstRdn.getAttributeValues()[0];
1566 } catch (LDAPException ldapException) {
1567 throw new RuntimeException("Cant parse DN: '" + dn + "'", ldapException);
1568 }
1569 }
1570
1571
1572
1573
1574
1575
1576
1577 public static String ldapEscapeRdn(String rdnString) {
1578
1579 String rdnAttribute = StringUtils.substringBefore(rdnString, "=");
1580 String rdnValue = StringUtils.substringAfter(rdnString, "=");
1581
1582 if ( StringUtils.isEmpty(rdnValue) || StringUtils.isEmpty(rdnValue) ) {
1583 throw new RuntimeException("Unable to parse and escape rdn: '" + rdnString + "'");
1584 }
1585
1586
1587
1588 RDN rdn = new RDN(rdnAttribute, rdnValue);
1589 return rdn.toMinimallyEncodedString();
1590 }
1591
1592
1593
1594
1595
1596
1597
1598 public static String ldapEscapeRdnValue(String rdnValue) {
1599
1600
1601
1602
1603 RDN rdn = new RDN("cn", rdnValue);
1604 return rdn.toMinimallyEncodedString().substring("cn=".length());
1605 }
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616 public static String ldapBushyDn(String groupName, String rdnAttributeName,
1617 String ouAttributeName,
1618 boolean performRdnEscaping, boolean performFilterEscaping) {
1619 return ldapBushyDn(groupName, rdnAttributeName, null, ouAttributeName, performRdnEscaping, performFilterEscaping);
1620 }
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632 public static String ldapBushyDn(String groupName, String rdnAttributeName,
1633 String rdnAttributeValue, String ouAttributeName,
1634 boolean performRdnEscaping, boolean performFilterEscaping) {
1635
1636 StringBuilder result = new StringBuilder();
1637
1638 List<String> namePieces=Arrays.asList(groupName.split(":"));
1639 Collections.reverse(namePieces);
1640
1641
1642 for (int i=0; i<namePieces.size(); i++) {
1643 if ( result.length() != 0 ) {
1644 result.append(',');
1645 }
1646
1647 RDN rdn;
1648 String piece;
1649
1650 if (i==0 && rdnAttributeValue != null) {
1651 piece = new String(rdnAttributeValue);
1652 } else {
1653 piece = namePieces.get(i);
1654 }
1655
1656
1657 if ( performFilterEscaping ) {
1658 piece = ldapFilterEscape(piece);
1659 }
1660
1661 if (i==0) {
1662 rdn = new RDN(rdnAttributeName, piece);
1663 } else {
1664 rdn = new RDN(ouAttributeName, piece);
1665 }
1666
1667 if ( performRdnEscaping ) {
1668 result.append(rdn.toMinimallyEncodedString());
1669 } else {
1670 result.append(rdn.toString());
1671 }
1672 }
1673
1674 return result.toString();
1675
1676 }
1677
1678 public static String ldapFilterEscape(String s) {
1679
1680 if (s == null) {
1681 return s;
1682 }
1683 final StringBuilder sb = new StringBuilder(s.length());
1684 final byte[] utf8 = s.getBytes(StandardCharsets.UTF_8);
1685
1686
1687 if (s.length() == utf8.length) {
1688 for (byte b : utf8) {
1689 if (b <= 0x1F || b == 0x28 || b == 0x29 || b == 0x2A || b == 0x5C || b == 0x7F) {
1690 sb.append('\\').append(Hex.encode(new byte[] {b}));
1691 } else {
1692 sb.append((char) b);
1693 }
1694 }
1695 } else {
1696 int multiByte = 0;
1697 for (byte b : utf8) {
1698 if (multiByte > 0) {
1699 sb.append('\\').append(Hex.encode(new byte[] {b}));
1700 multiByte--;
1701 } else if ((b & 0x7F) == b) {
1702 if (b <= 0x1F || b == 0x28 || b == 0x29 || b == 0x2A || b == 0x5C || b == 0x7F) {
1703 sb.append('\\').append(Hex.encode(new byte[] {b}));
1704 } else {
1705 sb.append((char) b);
1706 }
1707 } else {
1708
1709 if ((b & 0xE0) == 0xC0) {
1710 multiByte = 1;
1711
1712 } else if ((b & 0xF0) == 0xE0) {
1713 multiByte = 2;
1714
1715 } else if ((b & 0xF8) == 0xF0) {
1716 multiByte = 3;
1717 } else {
1718 throw new IllegalStateException("Could not read UTF-8 string encoding");
1719 }
1720 sb.append('\\').append(Hex.encode(new byte[] {b}));
1721 }
1722 }
1723 }
1724
1725 return sb.toString();
1726 }
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736 public static void promptUserAboutChanges(String reason, boolean checkResponse, String dbType, String url, String user) {
1737
1738 MultiKey cacheKey = stopPromptingUser ? new MultiKey(url, user) : new MultiKey(reason, url, user);
1739
1740
1741 if (dbChangeWhitelist.contains(cacheKey)) {
1742
1743 if (stopPromptingUser) {
1744 String message = dbType + " prompting has been disabled (e.g. due to testing), so this user '"
1745 + user + "' and url '" + url + "' are allowed for: " + reason;
1746 if (!stopPromptingUserPrintlns.contains(message)) {
1747 System.out.println(message);
1748 }
1749 stopPromptingUserPrintlns.add(message);
1750 return;
1751 }
1752 return;
1753 }
1754
1755
1756 String allow = System.getProperty("grouper.allow.db.changes");
1757 if (equals("true", allow)) {
1758 System.out.println("System property grouper.allow.db.changes is true which allows " + dbType + " changes to user '"
1759 + user + "' and url '" + url + "'");
1760
1761 dbChangeWhitelist.add(cacheKey);
1762 return;
1763 }
1764
1765
1766 if (findGrouperPropertiesDbMatch(false, user, url)) {
1767 System.out.println("This " + dbType + " user '" + user + "' and url '" + url + "' are denied to be " +
1768 "changed in the grouper.properties");
1769 System.exit(1);
1770
1771 }
1772
1773
1774 if (findGrouperPropertiesDbMatch(true, user, url)) {
1775 System.out.println("This " + dbType + " user '" + user + "' and url '" + url + "' are allowed to be " +
1776 "changed in the grouper.properties");
1777 if (!checkResponse) {
1778 System.out.println("Unfortunately this is checked from ant so you have to type 'y' anyways...");
1779 }
1780 } else {
1781
1782 BufferedReader stdin = null;
1783 String message = null;
1784
1785 try {
1786 stdin = new BufferedReader(new InputStreamReader(System.in));
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799 System.out.println("(note, might need to type in your response multiple times (Java stdin is flaky))");
1800 System.out.println("(note, you can whitelist or blacklist " + dbType + " urls and users in the grouper.properties)");
1801
1802 String prompt = "Are you sure you want to " + reason + " in " + dbType + " user '" + user + "', " + dbType + " url '" + url + "'? (y|n): ";
1803 System.out.println(prompt);
1804 System.out.flush();
1805 if (!checkResponse) {
1806 return;
1807 }
1808
1809 for (int i=0;i<10;i++) {
1810 message = stdin.readLine();
1811 message = trimToEmpty(message);
1812 if (!isEmpty(message)) {
1813 if (equalsIgnoreCase(message, "y") || equalsIgnoreCase(message, "n")) {
1814 break;
1815 }
1816 System.out.println("Didn't receive 'y' or 'n', received '" + message + "'...");
1817 System.out.println(prompt);
1818 System.out.flush();
1819 }
1820 }
1821 if (!equalsIgnoreCase(message, "y") && !equalsIgnoreCase(message, "n")) {
1822 System.out.println("Sorry you are having trouble, try the whitelist in grouper.properties");
1823 System.exit(1);
1824 }
1825 } catch (Exception e) {
1826 throw new RuntimeException(e);
1827
1828
1829
1830 }
1831 if (!equalsIgnoreCase(message, "y")) {
1832 System.out.println("Didn't receive 'y', received '" + message + "', OK, exiting");
1833 System.exit(1);
1834 }
1835 }
1836
1837 dbChangeWhitelist.add(cacheKey);
1838 System.out.println("Continuing...");
1839 }
1840
1841
1842
1843
1844
1845
1846
1847
1848 public static String uniqueId() {
1849
1850 synchronized (GrouperUtil.class) {
1851 lastId = incrementStringInt(lastId);
1852 }
1853
1854 return String.valueOf(lastId);
1855 }
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865 public static File fileFromResourceName(String resourceName) {
1866
1867 URL url = computeUrl(resourceName, true);
1868
1869 if (url == null) {
1870 return null;
1871 }
1872 try {
1873 String fileName = URLDecoder.decode(url.getFile(), "UTF-8");
1874
1875 File configFile = new File(fileName);
1876
1877 return configFile;
1878 } catch (UnsupportedEncodingException uee) {
1879 throw new RuntimeException(uee);
1880 }
1881 }
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891 public static String getLocationFromResourceName(String resourceName) {
1892
1893 URL url = computeUrl(resourceName, true);
1894
1895 if (url == null) {
1896 return null;
1897 }
1898
1899 if (url.getProtocol() == "file") {
1900 try {
1901 String urlFile = URLDecoder.decode(url.getFile(), "UTF-8");
1902 return fileCanonicalPath(new File(urlFile));
1903 } catch (UnsupportedEncodingException uee) {
1904 throw new RuntimeException(uee);
1905 }
1906 }
1907
1908 try {
1909 String urlPath = URLDecoder.decode(url.toString(), "UTF-8");
1910 return urlPath;
1911 } catch (UnsupportedEncodingException uee) {
1912 throw new RuntimeException(uee);
1913 }
1914 }
1915
1916
1917
1918
1919
1920
1921
1922 public static URL computeUrl(String resourceName, boolean canBeNull) {
1923
1924 ClassLoader cl = classLoader();
1925
1926 URL url = null;
1927
1928 try {
1929
1930 String newResourceName = resourceName.startsWith("/")
1931 ? resourceName.substring(1) : resourceName;
1932 url = cl.getResource(newResourceName);
1933 } catch (NullPointerException npe) {
1934 String error = "computeUrl() Could not find resource file: " + resourceName;
1935 throw new RuntimeException(error, npe);
1936 }
1937
1938 if (!canBeNull && url == null) {
1939 throw new RuntimeException("Cant find resource: " + resourceName);
1940 }
1941
1942 return url;
1943 }
1944
1945
1946
1947
1948
1949
1950 public static ClassLoader classLoader() {
1951 return GrouperUtil.class.getClassLoader();
1952 }
1953
1954
1955
1956
1957
1958
1959
1960
1961 @SuppressWarnings({ "unchecked", "cast" })
1962 public static <T> T[] nonNull(T[] array, Class<?> theClass) {
1963 if (int.class.equals(theClass)) {
1964 return (T[])(Object)new int[0];
1965 }
1966 if (float.class.equals(theClass)) {
1967 return (T[])(Object)new float[0];
1968 }
1969 if (double.class.equals(theClass)) {
1970 return (T[])(Object)new double[0];
1971 }
1972 if (short.class.equals(theClass)) {
1973 return (T[])(Object)new short[0];
1974 }
1975 if (long.class.equals(theClass)) {
1976 return (T[])(Object)new long[0];
1977 }
1978 if (byte.class.equals(theClass)) {
1979 return (T[])(Object)new byte[0];
1980 }
1981 if (boolean.class.equals(theClass)) {
1982 return (T[])(Object)new boolean[0];
1983 }
1984 if (char.class.equals(theClass)) {
1985 return (T[])(Object)new char[0];
1986 }
1987 return array == null ? ((T[])Array.newInstance(theClass, 0)) : array;
1988 }
1989
1990
1991
1992
1993
1994
1995
1996 public static String stripSuffix(String string, String suffix) {
1997 if (string == null || suffix == null) {
1998 return string;
1999 }
2000 if (string.endsWith(suffix)) {
2001 return string.substring(0, string.length() - suffix.length());
2002 }
2003 return string;
2004 }
2005
2006
2007
2008
2009
2010
2011
2012 public static String stripPrefix(String string, String prefix) {
2013 if (string == null || prefix == null) {
2014 return string;
2015 }
2016 if (string.startsWith(prefix)) {
2017 return string.substring(prefix.length(), string.length());
2018 }
2019 return string;
2020 }
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035 public static String prefixOrSuffix(String startString, String separator,
2036 boolean isPrefix) {
2037 String prefixOrSuffix = null;
2038
2039
2040 if (startString == null) {
2041 return startString;
2042 }
2043
2044
2045 int separatorIndex = isPrefix ? startString.indexOf(separator) : startString.lastIndexOf(separator);
2046
2047
2048 if (separatorIndex == -1) {
2049 return startString;
2050 }
2051
2052
2053 int separatorLength = separator.length();
2054
2055 if (isPrefix) {
2056 prefixOrSuffix = startString.substring(0, separatorIndex);
2057 } else {
2058 prefixOrSuffix = startString.substring(separatorIndex + separatorLength,
2059 startString.length());
2060 }
2061
2062 return prefixOrSuffix;
2063 }
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106 public static String indent(String string, boolean failIfTypeNotFound) {
2107 if (string == null) {
2108 return null;
2109 }
2110 string = trim(string);
2111 if (string.startsWith("<")) {
2112
2113 return new XmlIndenter(string).result();
2114 }
2115 if (string.startsWith("{")) {
2116 return new JsonIndenter(string).result();
2117 }
2118 if (!failIfTypeNotFound) {
2119
2120 return string;
2121 }
2122 throw new RuntimeException("Cant find type of string: " + string);
2123 }
2124
2125
2126
2127
2128
2129
2130 public static String jsonConvertTo(Object object) {
2131 return jsonConvertTo(object, true);
2132 }
2133
2134
2135
2136
2137
2138
2139 public static String jsonConvertTo(Object object, boolean includeObjectNameWrapper) {
2140
2141 if (object == null) {
2142 throw new NullPointerException();
2143 }
2144
2145
2146
2147
2148
2149
2150 JsonConfig jsonConfig = new JsonConfig();
2151 jsonConfig.setJsonPropertyFilter( new PropertyFilter(){
2152 public boolean apply( Object source, String name, Object value ) {
2153
2154 if( value != null && value instanceof Map ){
2155 Map map = (Map)value;
2156 if (map.size() > 0 && !(map.keySet().iterator().next() instanceof String)) {
2157 return true;
2158 }
2159 }
2160 return value == null;
2161 }
2162 });
2163 JSONObject jsonObject = JSONObject.fromObject( object, jsonConfig );
2164 String json = jsonObject.toString();
2165
2166 if (!includeObjectNameWrapper) {
2167 return json;
2168 }
2169 return "{\"" + object.getClass().getSimpleName() + "\":" + json + "}";
2170 }
2171
2172
2173
2174
2175
2176
2177
2178
2179 public static String jsonJacksonGetString(JsonNode jsonNode, String fieldName) {
2180 return jsonJacksonGetString(jsonNode, fieldName, null);
2181 }
2182
2183
2184
2185
2186
2187
2188
2189 public static void jsonJacksonAssignString(ObjectNode objectNode, String fieldName, String value) {
2190 if (!StringUtils.isBlank(value)) {
2191 objectNode.put(fieldName, value);
2192 }
2193 }
2194
2195
2196
2197
2198
2199
2200
2201 public static void jsonJacksonAssignBoolean(ObjectNode objectNode, String fieldName, Boolean value) {
2202 if (value != null) {
2203 objectNode.put(fieldName, value);
2204 }
2205 }
2206
2207
2208
2209
2210
2211
2212 public static void jsonJacksonAssignLong(ObjectNode objectNode, String fieldName, Long value) {
2213 if (value != null) {
2214 objectNode.put(fieldName, value);
2215 }
2216 }
2217
2218
2219
2220
2221
2222
2223
2224 public static void jsonJacksonAssignStringArray(ObjectNode objectNode, String fieldName, Collection<String> values) {
2225 if (values != null) {
2226 ObjectMapper objectMapper = new ObjectMapper();
2227 ArrayNode valuesJson = objectMapper.createArrayNode();
2228 for (String value : values) {
2229 valuesJson.add(value);
2230 }
2231 objectNode.set(fieldName, valuesJson);
2232 }
2233 }
2234
2235
2236
2237
2238
2239
2240
2241
2242 public static String jsonJacksonGetString(JsonNode jsonNode, String fieldName, String defaultString) {
2243 if (jsonNode != null) {
2244 JsonNode fieldNode = jsonNode.get(fieldName);
2245 if (fieldNode != null) {
2246 if (!(fieldNode instanceof NullNode)) {
2247 if (defaultString != null) {
2248 return fieldNode.asText(defaultString);
2249 }
2250 return fieldNode.asText();
2251 }
2252 }
2253 }
2254 return defaultString;
2255 }
2256
2257
2258
2259
2260
2261
2262
2263 public static JsonNode jsonJacksonGetNode(JsonNode jsonNode, String fieldName) {
2264
2265 if (jsonNode == null) {
2266 return null;
2267 }
2268
2269 JsonNode fieldNode = jsonNode.get(fieldName);
2270 if (fieldNode == null || fieldNode instanceof NullNode) {
2271 return null;
2272 }
2273 return fieldNode;
2274
2275 }
2276
2277
2278
2279
2280
2281
2282
2283 public static Set<String> jsonJacksonGetStringSet(JsonNode jsonNode, String fieldName) {
2284 Set<String> result = null;
2285 if (jsonNode != null) {
2286 ArrayNode fieldNode = (ArrayNode)jsonNode.get(fieldName);
2287 if (fieldNode != null) {
2288 result = new LinkedHashSet<String>();
2289 for (int i=0;i<fieldNode.size();i++) {
2290 JsonNode textNode = fieldNode.get(i);
2291 String textValue = textNode.asText();
2292 result.add(textValue);
2293 }
2294 }
2295 }
2296 return result;
2297 }
2298
2299
2300
2301
2302
2303
2304
2305 public static Boolean jsonJacksonGetBoolean(JsonNode jsonNode, String fieldName) {
2306 return jsonJacksonGetBoolean(jsonNode, fieldName, null);
2307 }
2308
2309
2310
2311
2312
2313
2314
2315
2316 public static Boolean jsonJacksonGetBoolean(JsonNode jsonNode, String fieldName, Boolean defaultBoolean) {
2317 if (jsonNode != null) {
2318 JsonNode fieldNode = jsonNode.get(fieldName);
2319 if (fieldNode != null) {
2320 if (!(fieldNode instanceof NullNode)) {
2321 if (defaultBoolean != null) {
2322 return fieldNode.asBoolean(defaultBoolean);
2323 }
2324 return fieldNode.asBoolean();
2325 }
2326 }
2327 }
2328 return defaultBoolean;
2329 }
2330
2331
2332
2333
2334
2335
2336
2337 public static Long jsonJacksonGetLong(JsonNode jsonNode, String fieldName) {
2338 return jsonJacksonGetLong(jsonNode, fieldName, null);
2339 }
2340
2341
2342
2343
2344
2345
2346
2347 public static Long jsonJacksonGetLong(JsonNode jsonNode, String fieldName, Long defaultLong) {
2348 if (jsonNode != null) {
2349 JsonNode fieldNode = jsonNode.get(fieldName);
2350 if (fieldNode != null) {
2351 if (!(fieldNode instanceof NullNode)) {
2352 if (defaultLong != null) {
2353 return fieldNode.asLong(defaultLong);
2354 }
2355 return fieldNode.asLong();
2356 }
2357 }
2358 }
2359 return defaultLong;
2360 }
2361
2362
2363
2364
2365
2366
2367
2368 public static Integer jsonJacksonGetInteger(JsonNode jsonNode, String fieldName) {
2369 return jsonJacksonGetInteger(jsonNode, fieldName, null);
2370 }
2371
2372
2373
2374
2375
2376
2377
2378 public static Integer jsonJacksonGetInteger(JsonNode jsonNode, String fieldName, Integer defaultInteger) {
2379 if (jsonNode != null) {
2380 JsonNode fieldNode = jsonNode.get(fieldName);
2381 if (fieldNode != null) {
2382 if (!(fieldNode instanceof NullNode)) {
2383 if (defaultInteger != null) {
2384 return fieldNode.asInt(defaultInteger);
2385 }
2386 return fieldNode.asInt();
2387 }
2388 }
2389 }
2390 return defaultInteger;
2391 }
2392
2393
2394 public static ObjectNode jsonJacksonNode() {
2395 ObjectMapper objectMapper = new ObjectMapper();
2396 ObjectNode objectNode = objectMapper.createObjectNode();
2397 return objectNode;
2398 }
2399
2400 public static ArrayNode jsonJacksonArrayNode() {
2401 ObjectMapper objectMapper = new ObjectMapper();
2402 ArrayNode arrayNode = objectMapper.createArrayNode();
2403 return arrayNode;
2404 }
2405
2406
2407
2408 public static JsonNode jsonJacksonNode(String json) {
2409 try {
2410 ObjectMapper objectMapper = new ObjectMapper();
2411
2412 JsonNode rootNode = objectMapper.readTree(json);
2413 return rootNode;
2414 } catch (Exception e) {
2415 injectInException(e, "Error in json '" + abbreviate(json, 4000) + "'");
2416 if (e instanceof RuntimeException) {
2417 throw (RuntimeException)e;
2418 }
2419 throw new RuntimeException(e);
2420 }
2421 }
2422
2423 public static String jsonJacksonToString(JsonNode jsonNode) {
2424 try {
2425 ObjectMapper objectMapper = new ObjectMapper();
2426 String json = objectMapper.writeValueAsString(jsonNode);
2427 return json;
2428 } catch (Exception e) {
2429 if (e instanceof RuntimeException) {
2430 throw (RuntimeException)e;
2431 }
2432 throw new RuntimeException(e);
2433 }
2434 }
2435
2436
2437
2438
2439
2440
2441
2442
2443 public static String jsonConvertToNoWrap(Object object) {
2444
2445 if (object == null) {
2446 throw new NullPointerException();
2447 }
2448
2449 JsonConfig jsonConfig = new JsonConfig();
2450 jsonConfig.setJsonPropertyFilter( new PropertyFilter(){
2451 public boolean apply( Object source, String name, Object value ) {
2452
2453 if( value != null && value instanceof Map ){
2454 Map map = (Map)value;
2455 if (map.size() > 0 && !(map.keySet().iterator().next() instanceof String)) {
2456 return true;
2457 }
2458 }
2459 if ("source".equals(name) && source instanceof Subject) {
2460 return true;
2461 }
2462 if ("subject".equals(name) && source != null && source.getClass().getName().equals("edu.internet2.middleware.grouper.grouperUi.beans.api.GuiSubject")) {
2463 return true;
2464 }
2465 if ("member".equals(name) && source != null && source.getClass().getName().equals("edu.internet2.middleware.grouper.grouperUi.beans.api.GuiSubject")) {
2466 return true;
2467 }
2468 return value == null;
2469 }
2470 });
2471 JSONObject jsonObject = JSONObject.fromObject( object, jsonConfig );
2472 String json = jsonObject.toString();
2473
2474 return json;
2475 }
2476
2477
2478
2479
2480
2481
2482 public static void jsonConvertTo(Object object, Writer writer) {
2483 String json = jsonConvertTo(object);
2484 try {
2485 writer.write(json);
2486 } catch (IOException ioe) {
2487 throw new RuntimeException(ioe);
2488 }
2489 }
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524 private static Pattern jsonPattern = Pattern.compile("^\\s*\\{\\s*\\\"([^\"]+)\\\"\\s*:\\s*(.*)}\\s*$", Pattern.DOTALL);
2525
2526
2527
2528
2529
2530
2531
2532
2533 public static Object jsonConvertFrom(Map<String, Class<?>> conversionMap, String json) {
2534
2535
2536
2537 Matcher matcher = jsonPattern.matcher(json);
2538
2539 if (!matcher.matches()) {
2540 throw new RuntimeException("Cant match this json, should start with simple class name: " + json);
2541 }
2542
2543 String simpleClassName = matcher.group(1);
2544 String jsonBody = matcher.group(2);
2545
2546 Class<?> theClass = conversionMap.get(simpleClassName);
2547 if (theClass == null) {
2548 throw new RuntimeException("Not allowed to unmarshal json: " + simpleClassName + ", " + json);
2549 }
2550
2551
2552 JSONObject jsonObject = JSONObject.fromObject( jsonBody );
2553 Object object = JSONObject.toBean( jsonObject, theClass );
2554
2555 return object;
2556 }
2557
2558
2559
2560
2561
2562
2563
2564
2565 public static <T> T jsonConvertFrom (String json, Class<T> theClass) {
2566 JSONObject jsonObject = JSONObject.fromObject( json );
2567 Object object = JSONObject.toBean( jsonObject, theClass );
2568 return (T)object;
2569 }
2570
2571
2572
2573
2574
2575
2576 public static String extensionFromName(String name) {
2577 if (isBlank(name)) {
2578 return name;
2579 }
2580 int lastColonIndex = name.lastIndexOf(':');
2581 if (lastColonIndex == -1) {
2582 return name;
2583 }
2584 String extension = name.substring(lastColonIndex+1);
2585 return extension;
2586 }
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598 public static boolean nameInFolderDirect(String name, String folder) {
2599
2600 String parentStem = parentStemNameFromName(name);
2601
2602 return equals(parentStem, folder);
2603 }
2604
2605
2606
2607
2608
2609
2610 public static Class forName(String origClassName) {
2611
2612 try {
2613 return Class.forName(origClassName);
2614 } catch (Throwable t) {
2615 throw new RuntimeException("Problem loading class: " + origClassName, t);
2616 }
2617
2618 }
2619
2620
2621
2622
2623
2624
2625
2626 public static <T> T newInstance(Class<T> theClass) {
2627 try {
2628 return theClass.newInstance();
2629 } catch (Throwable e) {
2630 if (theClass != null && Modifier.isAbstract(theClass.getModifiers())) {
2631 throw new RuntimeException("Problem with class: " + theClass + ", maybe because it is abstract!", e);
2632 }
2633 throw new RuntimeException("Problem with class: " + theClass, e);
2634 }
2635 }
2636
2637
2638
2639
2640
2641
2642
2643
2644 public static String parentStemNameFromName(String name) {
2645 return parentStemNameFromName(name, true);
2646 }
2647
2648
2649
2650
2651
2652
2653
2654
2655 public static String parentStemNameFromName(String name, boolean nullForRoot) {
2656
2657
2658 if (isBlank(name)) {
2659 return name;
2660 }
2661
2662 int lastColonIndex = name.lastIndexOf(':');
2663 if (lastColonIndex == -1) {
2664
2665 if (nullForRoot) {
2666 return null;
2667 }
2668 return ":";
2669 }
2670 String parentStemName = name.substring(0,lastColonIndex);
2671 return parentStemName;
2672
2673 }
2674
2675
2676
2677
2678
2679
2680
2681 public static String defaultIfBlank(String string, String defaultStringIfBlank) {
2682 return isBlank(string) ? defaultStringIfBlank : string;
2683 }
2684
2685
2686
2687
2688
2689
2690
2691
2692 public static <T> T defaultIfNull(T theValue, T defaultIfTheValueIsNull) {
2693 return theValue != null ? theValue : defaultIfTheValueIsNull;
2694 }
2695
2696
2697
2698
2699
2700
2701
2702 public static <T> void addIfNotThere(Collection<T> list, Collection<T> listToAdd) {
2703
2704 if (listToAdd == null) {
2705 return;
2706 }
2707 for (T t : listToAdd) {
2708 if (!list.contains(t)) {
2709 list.add(t);
2710 }
2711 }
2712 }
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723 private static void toStringForLogHelper(Object object, int maxChars, StringBuilder result, boolean newLines) {
2724
2725 try {
2726 if (object == null) {
2727 result.append("null");
2728 } else if (object.getClass().isArray()) {
2729
2730 int length = Array.getLength(object);
2731 if (length == 0) {
2732 result.append("Empty array");
2733 } else {
2734 result.append("Array size: ").append(length).append(": ");
2735 for (int i = 0; i < length; i++) {
2736 result.append("[").append(i).append("]: ").append(
2737 toStringForLog(Array.get(object, i), maxChars)).append(newLines ? "\n" : ", ");
2738 if (maxChars != -1 && result.length() > maxChars) {
2739 return;
2740 }
2741 }
2742 }
2743 } else if (object instanceof Collection) {
2744
2745 Collection<Object> collection = (Collection<Object>) object;
2746 int collectionSize = collection.size();
2747 if (collectionSize == 0) {
2748 result.append("Empty ").append(object.getClass().getSimpleName());
2749 } else {
2750 result.append(object.getClass().getSimpleName()).append(" size: ").append(collectionSize).append(": ");
2751 int i=0;
2752 for (Object collectionObject : collection) {
2753 result.append("[").append(i).append("]: ").append(
2754 toStringForLog(collectionObject, maxChars)).append(newLines ? "\n" : ", ");
2755 if (maxChars != -1 && result.length() > maxChars) {
2756 return;
2757 }
2758 i++;
2759 }
2760 }
2761 } else if (object instanceof Subject) {
2762 result.append(subjectToString((Subject)object));
2763 } else {
2764 result.append(object.toString());
2765 }
2766 } catch (Exception e) {
2767 result.append("<<exception>> ").append(object.getClass()).append(":\n")
2768 .append(getFullStackTrace(e)).append("\n");
2769 }
2770 }
2771
2772
2773
2774
2775
2776
2777
2778 public static String toStringFields(Object object, Set<String> fieldNames) {
2779
2780 if (object == null) {
2781 return null;
2782 }
2783
2784 StringBuilder result = new StringBuilder(object.getClass().getSimpleName() + ": ");
2785
2786
2787 for (String fieldName : nonNull(fieldNames)) {
2788
2789 Object value = fieldValue(object, fieldName);
2790 if (value != null) {
2791 result.append(fieldName).append(": '").append(value).append("', ");
2792 }
2793
2794 }
2795
2796
2797 result.delete(result.length()-2, result.length());
2798 return result.toString();
2799
2800 }
2801
2802
2803
2804
2805
2806
2807 public static String collectionToString(Collection collection) {
2808 if (collection == null) {
2809 return "null";
2810 }
2811 if (collection.size() == 0) {
2812 return "empty";
2813 }
2814 StringBuilder result = new StringBuilder();
2815 boolean first = true;
2816 for (Object object : collection) {
2817 if (!first) {
2818 result.append(", ");
2819 }
2820 first = false;
2821 result.append(object);
2822 }
2823 return result.toString();
2824
2825 }
2826
2827
2828
2829
2830
2831 public static String setToString(Set set) {
2832 return collectionToString(set);
2833 }
2834
2835
2836
2837
2838
2839
2840
2841 @Deprecated
2842 public static String MapToString(Map map) {
2843 return mapToString(map);
2844 }
2845
2846
2847
2848
2849
2850
2851 public static String mapToString(Map map) {
2852 if (map == null) {
2853 return "null";
2854 }
2855 if (map.size() == 0) {
2856 return "empty";
2857 }
2858 StringBuilder result = new StringBuilder();
2859 boolean first = true;
2860 for (Object object : map.keySet()) {
2861 if (!first) {
2862 result.append(", ");
2863 }
2864 first = false;
2865 result.append(object).append(": ").append(map.get(object));
2866 }
2867 return result.toString();
2868 }
2869
2870
2871
2872
2873
2874
2875
2876 public static String toStringForLog(Object object) {
2877 StringBuilder result = new StringBuilder();
2878 toStringForLogHelper(object, -1, result, true);
2879 return result.toString();
2880 }
2881
2882
2883
2884
2885
2886
2887
2888 public static String toStringForLog(Object object, boolean newLines) {
2889 StringBuilder result = new StringBuilder();
2890 toStringForLogHelper(object, -1, result, newLines);
2891 return result.toString();
2892 }
2893
2894
2895
2896
2897
2898
2899
2900
2901 public static String toStringForLog(Object object, int maxChars) {
2902 StringBuilder result = new StringBuilder();
2903 toStringForLogHelper(object, -1, result, true);
2904 String resultString = result.toString();
2905 if (maxChars != -1) {
2906 return abbreviate(resultString, maxChars);
2907 }
2908 return resultString;
2909 }
2910
2911
2912
2913
2914
2915
2916
2917 public static int batchNumberOfBatches(int count, int batchSize) {
2918
2919 if (batchSize == 0) {
2920 return 0;
2921 }
2922 int batches = 1 + ((count - 1) / batchSize);
2923 return batches;
2924
2925 }
2926
2927
2928
2929
2930
2931
2932
2933 public static int batchNumberOfBatches(Collection<?> collection, int batchSize) {
2934 int arrraySize = length(collection);
2935 return batchNumberOfBatches(arrraySize, batchSize);
2936
2937 }
2938
2939
2940
2941
2942
2943
2944
2945
2946 public static Set<String> findParentStemNames(Collection<Group> groups) {
2947 Set<String> result = new LinkedHashSet<String>();
2948 if (groups == null || groups.size() == 0) {
2949 return result;
2950 }
2951 for (Group group : groups) {
2952 String name = group.getName();
2953 result.addAll(findParentStemNames(name));
2954 }
2955 return result;
2956 }
2957
2958
2959
2960
2961
2962
2963
2964
2965 public static Set<String> findParentStemNames(String objectName) {
2966 List<String> result = new ArrayList<String>();
2967 String currentName = objectName;
2968 while(true) {
2969 currentName = parentStemNameFromName(currentName);
2970 if (isEmpty(currentName)) {
2971
2972 result.add(":");
2973 break;
2974 }
2975 result.add(currentName);
2976 }
2977 Collections.reverse(result);
2978 return new LinkedHashSet(result);
2979 }
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992 @SuppressWarnings("unchecked")
2993 public static <T> List<T> batchList(List<T> collection, int batchSize,
2994 int batchIndex) {
2995
2996 int numberOfBatches = batchNumberOfBatches(collection, batchSize);
2997 int arraySize = length(collection);
2998
2999
3000 if (arraySize == 0) {
3001 return new ArrayList<T>();
3002 }
3003
3004 List<T> theBatchObjects = new ArrayList<T>();
3005
3006
3007
3008
3009
3010
3011
3012 if (batchIndex == numberOfBatches - 1) {
3013
3014
3015
3016
3017 int collectionIndex = 0;
3018 for (T t : collection) {
3019 if (collectionIndex++ < batchIndex * batchSize) {
3020 continue;
3021 }
3022
3023
3024
3025
3026
3027 theBatchObjects.add(t);
3028 }
3029
3030 } else {
3031
3032
3033 int collectionIndex = 0;
3034 for (T t : collection) {
3035 if (collectionIndex < batchIndex * batchSize) {
3036 collectionIndex++;
3037 continue;
3038 }
3039
3040 if (collectionIndex >= (batchIndex + 1) * batchSize) {
3041 break;
3042 }
3043 theBatchObjects.add(t);
3044 collectionIndex++;
3045 }
3046 }
3047 return theBatchObjects;
3048 }
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060 public static String[] splitTrim(String input, String separator) {
3061 return splitTrim(input, separator, true);
3062 }
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075 public static List<String> splitTrimToList(String input, String separator) {
3076 if (isBlank(input)) {
3077 return null;
3078 }
3079 String[] array = splitTrim(input, separator);
3080 return toList(array);
3081 }
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094 public static Set<String> splitTrimToSet(String input, String separator) {
3095 if (isBlank(input)) {
3096 return null;
3097 }
3098 String[] array = splitTrim(input, separator);
3099 return toSet(array);
3100 }
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113 public static String[] splitTrim(String input, String separator, boolean treatAdjacentSeparatorsAsOne) {
3114 if (isBlank(input)) {
3115 return null;
3116 }
3117
3118
3119 String[] items = treatAdjacentSeparatorsAsOne ? splitByWholeSeparator(input, separator) :
3120 split(input, separator);
3121
3122
3123 for (int i = 0; (items != null) && (i < items.length); i++) {
3124 items[i] = trim(items[i]);
3125 }
3126
3127
3128 return items;
3129 }
3130
3131
3132
3133
3134
3135
3136 public static String escapeUrlEncode(String string) {
3137 String result = null;
3138 try {
3139 result = URLEncoder.encode(string, "UTF-8");
3140 } catch (UnsupportedEncodingException ex) {
3141 throw new RuntimeException("UTF-8 not supported", ex);
3142 }
3143
3144
3145 result = replace(result, "%3A", ":");
3146 return result;
3147 }
3148
3149
3150
3151
3152
3153
3154 public static String escapeUrlDecode(String string) {
3155 String result = null;
3156 try {
3157 result = URLDecoder.decode(string, "UTF-8");
3158 } catch (UnsupportedEncodingException ex) {
3159 throw new RuntimeException("UTF-8 not supported", ex);
3160 }
3161 return result;
3162 }
3163
3164
3165
3166
3167
3168
3169
3170 public static <T> List<T> nonNull(List<T> list) {
3171 return list == null ? new ArrayList<T>() : list;
3172 }
3173
3174
3175
3176
3177
3178
3179
3180 public static <T> Collection<T> nonNull(Collection<T> list) {
3181 return list == null ? new ArrayList<T>() : list;
3182 }
3183
3184
3185
3186
3187
3188
3189
3190 public static <T> Set<T> nonNull(Set<T> set) {
3191 return set == null ? new HashSet<T>() : set;
3192 }
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202 public static <K,V> Map<K,V> nonNull(Map<K,V> map) {
3203 return map == null ? new HashMap<K,V>() : map;
3204 }
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215 public static <T> List<T> toList(T... objects) {
3216 if (objects == null) {
3217 return null;
3218 }
3219 if (objects.length == 1 && objects[0] instanceof List) {
3220 return (List<T>)objects[0];
3221 }
3222
3223 List<T> result = new ArrayList<T>();
3224 for (T object : objects) {
3225 result.add(object);
3226 }
3227 return result;
3228 }
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238 public static List<Object> toListObject(Object... objects) {
3239 if (objects == null) {
3240 return null;
3241 }
3242 List<Object> result = new ArrayList<Object>();
3243 for (Object object : objects) {
3244 result.add(object);
3245 }
3246 return result;
3247 }
3248
3249
3250
3251
3252
3253
3254
3255 public static List<Class<?>> toListClasses(Class<?>... classes) {
3256 return toList(classes);
3257 }
3258
3259
3260
3261
3262
3263
3264
3265
3266 public static <T> Set<T> toSet(T... objects) {
3267 if (objects == null || objects.length == 0 || (objects.length == 1 && objects[0] == null )) {
3268 return null;
3269 }
3270 Set<T> result = new LinkedHashSet<T>();
3271 for (T object : objects) {
3272 result.add(object);
3273 }
3274 return result;
3275 }
3276
3277
3278
3279
3280
3281
3282
3283
3284 public static <T> Set<Object> toSetObjectType(T... objects) {
3285 if (objects == null || objects.length == 0 || (objects.length == 1 && objects[0] == null )) {
3286 return null;
3287 }
3288 Set<Object> result = new LinkedHashSet<Object>();
3289 for (T object : objects) {
3290 result.add(object);
3291 }
3292 return result;
3293 }
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303 public static <T> Set<T> toSetObject(T object) {
3304 if (object == null) {
3305 return null;
3306 }
3307 Set<T> result = new LinkedHashSet<T>();
3308 result.add(object);
3309 return result;
3310 }
3311
3312
3313
3314
3315 private static final String CACHE_SEPARATOR = "__";
3316
3317
3318
3319
3320
3321
3322 public static String timestampIsoUtcSecondsConvertToString(Timestamp timestamp) {
3323
3324 if (timestamp == null) {
3325 return null;
3326 }
3327
3328 String my8601formattedDate = timestampIsoUtcSeconds.format(timestamp);
3329 return my8601formattedDate;
3330 }
3331
3332
3333
3334
3335
3336
3337 public static Timestamp timestampIsoUtcSecondsConvertFromString(String string) {
3338
3339 if (StringUtils.isBlank(string)) {
3340 return null;
3341 }
3342
3343 try {
3344 Date date = timestampIsoUtcSeconds.parse(string);
3345 return new Timestamp(date.getTime());
3346 } catch (Exception e) {
3347 throw new RuntimeException("Cant parse string: '" + string + "' in format: yyyy-MM-dd'T'HH:mm:ss'Z'");
3348 }
3349 }
3350
3351
3352
3353
3354 public static final DateFormat timestampIsoUtcSeconds = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
3355
3356 static {
3357 timestampIsoUtcSeconds.setTimeZone(TimeZone.getTimeZone("UTC"));
3358 }
3359
3360
3361
3362
3363 public static final String DATE_FORMAT = "yyyyMMdd";
3364
3365
3366
3367
3368 public static final String TIMESTAMP_FILE_FORMAT = "yyyy_MM_dd__HH_mm_ss_SSS";
3369
3370
3371
3372
3373 final static SimpleDateFormat timestampFileFormat = new SimpleDateFormat(TIMESTAMP_FILE_FORMAT);
3374
3375
3376
3377
3378 public static final String DATE_FORMAT2 = "yyyy/MM/dd";
3379
3380
3381
3382
3383 public static final String DATE_MINUTES_SECONDS_FORMAT = "yyyy/MM/dd HH:mm:ss";
3384
3385
3386
3387
3388 public static final String DATE_MINUTES_SECONDS_NO_SLASH_FORMAT = "yyyyMMdd HH:mm:ss";
3389
3390
3391
3392
3393 public static final String TIMESTAMP_FORMAT = "yyyy/MM/dd HH:mm:ss.SSS";
3394
3395
3396
3397
3398 public static final String TIMESTAMP_NO_SLASH_FORMAT = "yyyyMMdd HH:mm:ss.SSS";
3399
3400
3401
3402
3403 final static SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
3404
3405
3406
3407
3408 final static SimpleDateFormat dateFormat2 = new SimpleDateFormat(DATE_FORMAT2);
3409
3410
3411
3412
3413 final static SimpleDateFormat dateMinutesSecondsFormat = new SimpleDateFormat(
3414 DATE_MINUTES_SECONDS_FORMAT);
3415
3416
3417
3418
3419 final static SimpleDateFormat dateMinutesSecondsNoSlashFormat = new SimpleDateFormat(
3420 DATE_MINUTES_SECONDS_NO_SLASH_FORMAT);
3421
3422
3423
3424
3425 final static SimpleDateFormat timestampFormat = new SimpleDateFormat(TIMESTAMP_FORMAT);
3426
3427
3428
3429
3430 final static SimpleDateFormat timestampNoSlashFormat = new SimpleDateFormat(
3431 TIMESTAMP_NO_SLASH_FORMAT);
3432
3433
3434
3435
3436
3437
3438
3439 public static void assertion(boolean isTrue, String reason) {
3440 if (!isTrue) {
3441 throw new RuntimeException(reason);
3442 }
3443
3444 }
3445
3446
3447
3448
3449 private static GrouperCache<String, Set<Field>> fieldSetCache = null;
3450
3451
3452
3453
3454 private static Object fieldSetCacheSemaphore = new Object();
3455
3456
3457
3458
3459
3460 private static GrouperCache<String, Set<Field>> fieldSetCache() {
3461 if (fieldSetCache == null) {
3462 synchronized(fieldSetCacheSemaphore) {
3463 if (fieldSetCache == null) {
3464 fieldSetCache = new GrouperCache<String, Set<Field>>("edu.internet2.middleware.grouper.util.GrouperUtil.fieldSetCache",
3465 2000, false, 60*60*24, 60*60*24, false);
3466 }
3467 }
3468 }
3469 return fieldSetCache;
3470 }
3471
3472
3473
3474
3475
3476 private static GrouperCache<Class, Method[]> declaredMethodsCache = null;
3477
3478
3479
3480
3481 private static Object declaredMethodsCacheSemaphore = new Object();
3482
3483
3484
3485
3486
3487 private static GrouperCache<Class, Method[]> declaredMethodsCache() {
3488 if (declaredMethodsCache == null) {
3489 synchronized(declaredMethodsCacheSemaphore) {
3490 if (declaredMethodsCache == null) {
3491 declaredMethodsCache = new GrouperCache<Class, Method[]>("edu.internet2.middleware.grouper.util.GrouperUtil.declaredMethodsCache",
3492 2000, false, 60*60*24, 60*60*24, false);
3493 }
3494 }
3495 }
3496 return declaredMethodsCache;
3497 }
3498
3499
3500
3501
3502
3503
3504 private static GrouperCache<String, Set<Method>> getterSetCache = null;
3505
3506
3507
3508
3509 private static Object getterSetCacheSemaphore = new Object();
3510
3511
3512
3513
3514
3515 private static GrouperCache<String, Set<Method>> getterSetCache() {
3516 if (getterSetCache == null) {
3517 synchronized(getterSetCacheSemaphore) {
3518 if (getterSetCache == null) {
3519 getterSetCache = new GrouperCache<String, Set<Method>>("edu.internet2.middleware.grouper.util.getterSetCache",
3520 2000, false, 0, 60*60*24, false);
3521 }
3522 }
3523 }
3524 return getterSetCache;
3525 }
3526
3527
3528
3529
3530
3531
3532 private static GrouperCache<String, Set<Method>> setterSetCache = null;
3533
3534
3535
3536
3537 private static Object setterSetCacheSemaphore = new Object();
3538
3539
3540
3541
3542
3543 private static GrouperCache<String, Set<Method>> setterSetCache() {
3544 if (setterSetCache == null) {
3545 synchronized(setterSetCacheSemaphore) {
3546 if (setterSetCache == null) {
3547 setterSetCache = new GrouperCache<String, Set<Method>>("edu.internet2.middleware.grouper.util.setterSetCache",
3548 2000, false, 0, 60*60*24, false);
3549 }
3550 }
3551 }
3552 return setterSetCache;
3553 }
3554
3555
3556
3557
3558
3559 private static char[] lastId = convertLongToStringSmall(new Date().getTime())
3560 .toCharArray();
3561
3562
3563
3564
3565 private static ExpirableCache<String, Properties> resourcePropertiesCache = null;
3566
3567
3568
3569
3570 private static Object resourcePropertiesCacheSemaphore = new Object();
3571
3572
3573
3574
3575
3576 private static ExpirableCache<String, Properties> resourcePropertiesCache() {
3577 if (resourcePropertiesCache == null) {
3578 synchronized(resourcePropertiesCacheSemaphore) {
3579 if (resourcePropertiesCache == null) {
3580
3581
3582
3583 resourcePropertiesCache = new ExpirableCache<String, Properties>(5);
3584
3585 }
3586 }
3587 }
3588 return resourcePropertiesCache;
3589 }
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611 public static void assignField(Class theClass, Object invokeOn,
3612 String fieldName, Object dataToAssign, boolean callOnSupers,
3613 boolean overrideSecurity, boolean typeCast,
3614 Class<? extends Annotation> annotationWithValueOverride) {
3615 if (theClass == null && invokeOn != null) {
3616 theClass = invokeOn.getClass();
3617 }
3618 Field field = field(theClass, fieldName, callOnSupers, true);
3619 assignField(field, invokeOn, dataToAssign, overrideSecurity, typeCast,
3620 annotationWithValueOverride);
3621 }
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638 public static void assignField(Class theClass, Object invokeOn,
3639 String fieldName, Object dataToAssign,
3640 Class<? extends Annotation> annotationWithValueOverride) {
3641 assignField(theClass, invokeOn, fieldName, dataToAssign, true, true,
3642 true, annotationWithValueOverride);
3643 }
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659 public static void assignField(Field field, Object invokeOn,
3660 Object dataToAssign, boolean overrideSecurity, boolean typeCast) {
3661
3662 try {
3663 Class fieldType = field.getType();
3664
3665 if (typeCast) {
3666 dataToAssign =
3667 typeCast(dataToAssign, fieldType,
3668 true, true);
3669 }
3670 if (overrideSecurity) {
3671 field.setAccessible(true);
3672 }
3673 field.set(invokeOn, dataToAssign);
3674 } catch (Exception e) {
3675 throw new RuntimeException("Cant assign reflection field: "
3676 + (field == null ? null : field.getName()) + ", on: "
3677 + className(invokeOn) + ", with args: "
3678 + classNameCollection(dataToAssign), e);
3679 }
3680 }
3681
3682
3683
3684
3685
3686
3687
3688 public static Iterator iterator(Object collection) {
3689 if (collection == null) {
3690 return null;
3691 }
3692
3693 if (collection instanceof Collection
3694 && !(collection instanceof ArrayList)) {
3695 return ((Collection) collection).iterator();
3696 }
3697 return null;
3698 }
3699
3700
3701
3702
3703
3704
3705
3706 public static int length(Object arrayOrCollection) {
3707 if (arrayOrCollection == null) {
3708 return 0;
3709 }
3710 if (arrayOrCollection.getClass().isArray()) {
3711 return Array.getLength(arrayOrCollection);
3712 }
3713 if (arrayOrCollection instanceof Collection) {
3714 return ((Collection) arrayOrCollection).size();
3715 }
3716 if (arrayOrCollection instanceof Map) {
3717 return ((Map) arrayOrCollection).size();
3718 }
3719
3720 return 1;
3721 }
3722
3723
3724
3725
3726
3727
3728
3729 public static boolean isArrayOrCollection(Object arrayOrCollection) {
3730 if (arrayOrCollection == null) {
3731 return false;
3732 }
3733 return (arrayOrCollection.getClass().isArray() || arrayOrCollection instanceof Collection);
3734 }
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745 public static Object next(Object arrayOrCollection, Iterator iterator,
3746 int index) {
3747 if (arrayOrCollection.getClass().isArray()) {
3748 return Array.get(arrayOrCollection, index);
3749 }
3750 if (arrayOrCollection instanceof ArrayList) {
3751 return ((ArrayList) arrayOrCollection).get(index);
3752 }
3753 if (arrayOrCollection instanceof Collection) {
3754 return iterator.next();
3755 }
3756
3757 if (0 == index) {
3758 return arrayOrCollection;
3759 }
3760 throw new RuntimeException("Invalid class type: "
3761 + arrayOrCollection.getClass().getName());
3762 }
3763
3764
3765
3766
3767
3768
3769
3770
3771 public static Object remove(Object arrayOrCollection,
3772 int index) {
3773 return remove(arrayOrCollection, null, index);
3774 }
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784 public static Object remove(Object arrayOrCollection, Iterator iterator,
3785 int index) {
3786
3787
3788 if (iterator != null) {
3789 iterator.remove();
3790 return arrayOrCollection;
3791 }
3792 if (arrayOrCollection.getClass().isArray()) {
3793 int newLength = Array.getLength(arrayOrCollection) - 1;
3794 Object newArray = Array.newInstance(arrayOrCollection.getClass().getComponentType(), newLength);
3795 if (newLength == 0) {
3796 return newArray;
3797 }
3798 if (index > 0) {
3799 System.arraycopy(arrayOrCollection, 0, newArray, 0, index);
3800 }
3801 if (index < newLength) {
3802 System.arraycopy(arrayOrCollection, index+1, newArray, index, newLength - index);
3803 }
3804 return newArray;
3805 }
3806 if (arrayOrCollection instanceof List) {
3807 ((List)arrayOrCollection).remove(index);
3808 return arrayOrCollection;
3809 } else if (arrayOrCollection instanceof Collection) {
3810
3811 ((Collection)arrayOrCollection).remove(get(arrayOrCollection, index));
3812 return arrayOrCollection;
3813 }
3814 throw new RuntimeException("Invalid class type: "
3815 + arrayOrCollection.getClass().getName());
3816 }
3817
3818
3819
3820
3821
3822
3823 public static String classesString(Object object) {
3824 StringBuilder result = new StringBuilder();
3825 if (object.getClass().isArray()) {
3826 int length = Array.getLength(object);
3827 for (int i=0;i<length;i++) {
3828 result.append(((Class)Array.get(object, i)).getSimpleName());
3829 if (i < length-1) {
3830 result.append(", ");
3831 }
3832 }
3833 return result.toString();
3834 }
3835
3836 throw new RuntimeException("Not implemented: " + className(object));
3837 }
3838
3839
3840
3841
3842
3843
3844
3845 public static String classNameCollection(Object object) {
3846 if (object == null) {
3847 return null;
3848 }
3849 StringBuffer result = new StringBuffer();
3850
3851 Iterator iterator = iterator(object);
3852 int length = length(object);
3853 for (int i = 0; i < length && i < 20; i++) {
3854 result.append(className(next(object, iterator, i)));
3855 if (i != length - 1) {
3856 result.append(", ");
3857 }
3858 }
3859 return result.toString();
3860 }
3861
3862
3863
3864
3865
3866
3867
3868 public static String className(Object object) {
3869 return object == null ? null : unenhanceClass(object.getClass())
3870 .getName();
3871 }
3872
3873
3874
3875
3876
3877
3878
3879 public static Class unenhanceClass(Class theClass) {
3880 try {
3881
3882
3883
3884
3885
3886 while (ProxyObject.class.isAssignableFrom(theClass)) {
3887 theClass = theClass.getSuperclass();
3888 }
3889
3890 return theClass;
3891 } catch (Exception e) {
3892 throw new RuntimeException("Problem unenhancing " + theClass, e);
3893 }
3894 }
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912 @SuppressWarnings("unchecked")
3913 public static void assignField(Field field, Object invokeOn,
3914 Object dataToAssign, boolean overrideSecurity, boolean typeCast,
3915 Class<? extends Annotation> annotationWithValueOverride) {
3916
3917 if (annotationWithValueOverride != null) {
3918
3919 Annotation annotation = field
3920 .getAnnotation(annotationWithValueOverride);
3921 if (annotation != null) {
3922
3923
3924
3925
3926
3927
3928
3929 throw new RuntimeException("Not supported");
3930 }
3931 }
3932 assignField(field, invokeOn, dataToAssign, overrideSecurity, typeCast);
3933 }
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946 public static void assignField(Object invokeOn, String fieldName,
3947 Object dataToAssign) {
3948 assignField(null, invokeOn, fieldName, dataToAssign, true, true, true,
3949 null);
3950 }
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964 public static Field field(Class theClass, String fieldName,
3965 boolean callOnSupers, boolean throwExceptionIfNotFound) {
3966 try {
3967 Field field = theClass.getDeclaredField(fieldName);
3968
3969 return field;
3970 } catch (NoSuchFieldException e) {
3971
3972
3973 if (callOnSupers && !theClass.equals(Object.class)) {
3974 return field(theClass.getSuperclass(), fieldName, callOnSupers,
3975 throwExceptionIfNotFound);
3976 }
3977 }
3978
3979 if (throwExceptionIfNotFound) {
3980 throw new RuntimeException("Cant find field: " + fieldName
3981 + ", in: " + theClass + ", callOnSupers: " + callOnSupers);
3982 }
3983 return null;
3984 }
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996 @SuppressWarnings("unchecked")
3997 public static Set<String> fieldNames(Class theClass, Class fieldType,
3998 boolean includeStaticFields) {
3999 return fieldNamesHelper(theClass, theClass, fieldType, true, true,
4000 includeStaticFields, null, true);
4001 }
4002
4003
4004
4005
4006
4007
4008
4009
4010 public static String dbVersionDescribeDifferences(Object theOld, Object theNew, Set<String> differentFieldNames) {
4011
4012 StringBuilder result = new StringBuilder(theOld == null ? "Old state unknown, new state is: " : "Fields changed: ");
4013
4014 int length = length(differentFieldNames);
4015
4016 if (length == 0) {
4017 result.append("none");
4018 return result.toString();
4019 }
4020 int i=0;
4021 for (String fieldName : nonNull(differentFieldNames)) {
4022 result.append(fieldName);
4023 if (i < length-1) {
4024 result.append(", ");
4025 } else {
4026 result.append(".\n");
4027 }
4028 i++;
4029 }
4030
4031 i=0;
4032 for (String fieldName : nonNull(differentFieldNames)) {
4033 String oldString = theOld == null ? "?" : stringValue(fieldValue(theOld, fieldName));
4034 oldString = StringUtils.abbreviate(oldString, 200);
4035 String newString = stringValue(fieldValue(theNew, fieldName));
4036 newString = StringUtils.abbreviate(newString, 200);
4037 result.append(fieldName).append(": FROM: '").append(oldString).append("', TO: '").append(newString).append("'");
4038 if (i < length-1) {
4039 result.append("\n");
4040 }
4041 i++;
4042 }
4043 return result.toString();
4044 }
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063 public static Set<String> fieldNames(Class theClass,
4064 Class superclassToStopAt, Class<?> fieldType,
4065 boolean includeSuperclassToStopAt, boolean includeStaticFields,
4066 boolean includeFinalFields) {
4067 return fieldNamesHelper(theClass, superclassToStopAt, fieldType,
4068 includeSuperclassToStopAt, includeStaticFields,
4069 includeFinalFields, null, true);
4070
4071 }
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094 public static Set<String> fieldNames(Class theClass,
4095 Class superclassToStopAt, Class<?> fieldType,
4096 boolean includeSuperclassToStopAt, boolean includeStaticFields,
4097 boolean includeFinalFields,
4098 Class<? extends Annotation> markerAnnotationToIngore) {
4099 return fieldNamesHelper(theClass, superclassToStopAt, fieldType,
4100 includeSuperclassToStopAt, includeStaticFields,
4101 includeFinalFields, markerAnnotationToIngore, false);
4102
4103 }
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119 public static Set<String> fieldNames(Class theClass,
4120 Class superclassToStopAt,
4121 Class<? extends Annotation> markerAnnotationToIngore) {
4122 return fieldNamesHelper(theClass, superclassToStopAt, null, true,
4123 false, false, markerAnnotationToIngore, false);
4124 }
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149 @SuppressWarnings("unchecked")
4150 static Set<String> fieldNamesHelper(Class theClass,
4151 Class superclassToStopAt, Class<?> fieldType,
4152 boolean includeSuperclassToStopAt, boolean includeStaticFields,
4153 boolean includeFinalFields,
4154 Class<? extends Annotation> markerAnnotation,
4155 boolean includeAnnotation) {
4156 Set<Field> fieldSet = fieldsHelper(theClass, superclassToStopAt,
4157 fieldType, includeSuperclassToStopAt, includeStaticFields,
4158 includeFinalFields, markerAnnotation, includeAnnotation);
4159 Set<String> fieldNameSet = new LinkedHashSet<String>();
4160 for (Field field : fieldSet) {
4161 fieldNameSet.add(field.getName());
4162 }
4163 return fieldNameSet;
4164
4165 }
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190 @SuppressWarnings("unchecked")
4191 public static Set<Field> fields(Class theClass, Class superclassToStopAt,
4192 Class fieldType, boolean includeSuperclassToStopAt,
4193 boolean includeStaticFields, boolean includeFinalFields,
4194 Class<? extends Annotation> markerAnnotation,
4195 boolean includeAnnotation) {
4196 return fieldsHelper(theClass, superclassToStopAt, fieldType,
4197 includeSuperclassToStopAt, includeStaticFields,
4198 includeFinalFields, markerAnnotation, includeAnnotation);
4199 }
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219 @SuppressWarnings("unchecked")
4220 public static Set<Field> fields(Class theClass, Class superclassToStopAt,
4221 Class<? extends Annotation> markerAnnotation,
4222 boolean includeAnnotation) {
4223 return fieldsHelper(theClass, superclassToStopAt, null, true, false,
4224 false, markerAnnotation, includeAnnotation);
4225 }
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250 @SuppressWarnings("unchecked")
4251 static Set<Field> fieldsHelper(Class theClass, Class superclassToStopAt,
4252 Class<?> fieldType, boolean includeSuperclassToStopAt,
4253 boolean includeStaticFields, boolean includeFinalFields,
4254 Class<? extends Annotation> markerAnnotation,
4255 boolean includeAnnotation) {
4256
4257
4258 Set<Field> fieldNameSet = null;
4259 String cacheKey = theClass + CACHE_SEPARATOR + superclassToStopAt
4260 + CACHE_SEPARATOR + fieldType + CACHE_SEPARATOR
4261 + includeSuperclassToStopAt + CACHE_SEPARATOR
4262 + includeStaticFields + CACHE_SEPARATOR + includeFinalFields
4263 + CACHE_SEPARATOR + markerAnnotation + CACHE_SEPARATOR
4264 + includeAnnotation;
4265 fieldNameSet = fieldSetCache().get(cacheKey);
4266 if (fieldNameSet != null) {
4267 return fieldNameSet;
4268 }
4269
4270 fieldNameSet = new LinkedHashSet<Field>();
4271 fieldsHelper(theClass, superclassToStopAt, fieldType,
4272 includeSuperclassToStopAt, includeStaticFields,
4273 includeFinalFields, markerAnnotation, fieldNameSet,
4274 includeAnnotation);
4275
4276
4277 fieldSetCache().put(cacheKey, fieldNameSet);
4278
4279 return fieldNameSet;
4280
4281 }
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293 public static Set<String> compareObjectFields(Object first, Object second,
4294 Set<String> fieldsToCompare, String mapPrefix) {
4295
4296 Set<String> differentFields = new LinkedHashSet<String>();
4297
4298 if (first == second) {
4299 return differentFields;
4300 }
4301
4302
4303 if (first == null || second == null) {
4304 differentFields.addAll(fieldsToCompare);
4305 }
4306
4307 for (String fieldName : fieldsToCompare) {
4308 try {
4309 Object firstValue = fieldValue(first, fieldName);
4310 Object secondValue = fieldValue(second, fieldName);
4311
4312 if (firstValue == secondValue) {
4313 continue;
4314 }
4315 if (firstValue instanceof Map || secondValue instanceof Map) {
4316 mapDifferences((Map)firstValue, (Map)secondValue, differentFields, mapPrefix);
4317 continue;
4318 }
4319
4320
4321 if (firstValue instanceof String || secondValue instanceof String) {
4322 if (!equals(defaultString((String)firstValue),
4323 defaultString((String)secondValue))) {
4324 differentFields.add(fieldName);
4325 }
4326 continue;
4327 }
4328
4329 if (firstValue == null || secondValue == null) {
4330 differentFields.add(fieldName);
4331 continue;
4332 }
4333
4334 if (!firstValue.equals(secondValue)) {
4335 differentFields.add(fieldName);
4336 continue;
4337 }
4338
4339 } catch (RuntimeException re) {
4340 throw new RuntimeException("Problem comparing field " + fieldName
4341 + " on objects: " + className(first) + ", " + className(second));
4342 }
4343
4344
4345 }
4346 return differentFields;
4347 }
4348
4349
4350
4351
4352
4353
4354
4355
4356 public static <T> T clone(T object, Set<String> fieldsToClone) {
4357
4358
4359 T result = (T)newInstance(object.getClass());
4360
4361 cloneFields(object, result, fieldsToClone);
4362
4363 return result;
4364 }
4365
4366
4367
4368
4369
4370
4371
4372
4373 public static <T> void cloneFields(T object, T result,
4374 Set<String> fieldsToClone) {
4375
4376 if (object == result) {
4377 return;
4378 }
4379
4380
4381 if (object == null || result == null) {
4382 throw new RuntimeException("Cant copy from or to null: " + className(object) + ", " + className(result));
4383 }
4384
4385 Class<?> fieldValueClass = null;
4386
4387 for (String fieldName : nonNull(fieldsToClone)) {
4388 try {
4389
4390 Object fieldValue = fieldValue(object, fieldName);
4391 fieldValueClass = fieldValue == null ? null : fieldValue.getClass();
4392
4393 Object fieldValueToAssign = cloneValue(fieldValue);
4394
4395
4396 assignField(result, fieldName, fieldValueToAssign);
4397
4398 } catch (RuntimeException re) {
4399 throw new RuntimeException("Problem cloning field: " + object.getClass()
4400 + ", " + fieldName + ", " + fieldValueClass, re);
4401 }
4402 }
4403 }
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414 public static <T> T cloneValue(T value) {
4415
4416 Object clonedValue = value;
4417
4418 if (value == null || value instanceof String || value instanceof Class<?>
4419 || value instanceof Enum<?>
4420 || value.getClass().isPrimitive() || value instanceof Number
4421 || value instanceof Boolean
4422 || value instanceof Date || value instanceof Configuration
4423 || value instanceof Subject || value.getClass().isEnum()) {
4424
4425
4426
4427 } else if (value instanceof GrouperCloneable) {
4428
4429
4430 clonedValue = ((GrouperCloneable)value).clone();
4431
4432 } else if (value instanceof Map) {
4433 clonedValue = new LinkedHashMap();
4434 Map mapValue = (Map)value;
4435 Map clonedMapValue = (Map)clonedValue;
4436 for (Object key : mapValue.keySet()) {
4437 clonedMapValue.put(cloneValue(key), cloneValue(mapValue.get(key)));
4438 }
4439 } else if (value instanceof Set) {
4440 clonedValue = new LinkedHashSet();
4441 Set setValue = (Set)value;
4442 Set clonedSetValue = (Set)clonedValue;
4443 for (Object each : setValue) {
4444 clonedSetValue.add(cloneValue(each));
4445 }
4446 } else if (value instanceof List) {
4447 clonedValue = new ArrayList();
4448 List listValue = (List)value;
4449 List clonedListValue = (List)clonedValue;
4450 for (Object each : listValue) {
4451 clonedListValue.add(cloneValue(each));
4452 }
4453 } else if (value.getClass().isArray()) {
4454 clonedValue = Array.newInstance(value.getClass().getComponentType(), Array.getLength(value));
4455 for (int i=0;i<Array.getLength(value);i++) {
4456 Array.set(clonedValue, i, cloneValue(Array.get(value, i)));
4457 }
4458
4459 } else {
4460
4461
4462 throw new RuntimeException("Unexpected class in clone method: " + value.getClass());
4463
4464 }
4465 return (T)clonedValue;
4466 }
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476 public static Set<String> methodNames(Class<?> theClass, Class<?> superclassToStopAt,
4477 boolean includeSuperclassToStopAt, boolean includeStaticMethods) {
4478
4479 Set<Method> methods = new LinkedHashSet<Method>();
4480 methodsHelper(theClass, superclassToStopAt, includeSuperclassToStopAt, includeStaticMethods,
4481 null, false, methods);
4482 Set<String> methodNames = new HashSet<String>();
4483 for (Method method : methods) {
4484 methodNames.add(method.getName());
4485 }
4486 return methodNames;
4487 }
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499 public static Method methodByName(Class<?> theClass, String methodName, Class<?> superclassToStopAt,
4500 boolean includeSuperclassToStopAt, boolean includeStaticMethods, boolean exceptionIfNotFound) {
4501
4502 Set<Method> methods = new LinkedHashSet<Method>();
4503 methodsByNameHelper(theClass, methodName, superclassToStopAt,
4504 includeSuperclassToStopAt, includeStaticMethods,
4505 null, false, methods);
4506 if (methods.size() > 1) {
4507 throw new RuntimeException("There are more than one method with name " + methodName + " in class: " + theClass);
4508 }
4509
4510 if (methods.size() == 1) {
4511 return methods.iterator().next();
4512 }
4513
4514 if (exceptionIfNotFound) {
4515 throw new RuntimeException("Could not find method " + methodName + " in class: " + theClass);
4516 }
4517
4518 return null;
4519 }
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531 public static void methodsHelper(Class<?> theClass, Class<?> superclassToStopAt,
4532 boolean includeSuperclassToStopAt,
4533 boolean includeStaticMethods, Class<? extends Annotation> markerAnnotation,
4534 boolean includeAnnotation, Set<Method> methodSet) {
4535 theClass = unenhanceClass(theClass);
4536 Method[] methods = theClass.getDeclaredMethods();
4537 if (length(methods) != 0) {
4538 for (Method method : methods) {
4539
4540 if (!includeStaticMethods
4541 && Modifier.isStatic(method.getModifiers())) {
4542 continue;
4543 }
4544
4545 if (markerAnnotation != null
4546 && (includeAnnotation != method
4547 .isAnnotationPresent(markerAnnotation))) {
4548 continue;
4549 }
4550
4551 methodSet.add(method);
4552 }
4553 }
4554
4555
4556 if (theClass.equals(superclassToStopAt)
4557 || theClass.equals(Object.class)) {
4558 return;
4559 }
4560 Class superclass = theClass.getSuperclass();
4561 if (!includeSuperclassToStopAt && superclass.equals(superclassToStopAt)) {
4562 return;
4563 }
4564
4565 methodsHelper(superclass, superclassToStopAt,
4566 includeSuperclassToStopAt, includeStaticMethods,
4567 markerAnnotation, includeAnnotation, methodSet);
4568
4569 }
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585 public static Method method(Class<?> theClass,
4586 String methodName, Object paramTypesOrArrayOrList,
4587 Class<?> superclassToStopAt,
4588 boolean includeSuperclassToStopAt,
4589 boolean isStaticOrInstance, Class<? extends Annotation> markerAnnotation,
4590 boolean includeAnnotation) {
4591 theClass = unenhanceClass(theClass);
4592
4593 Class[] paramTypesArray = (Class[]) toArray(paramTypesOrArrayOrList);
4594
4595 Method method = null;
4596
4597 try {
4598 method = theClass.getDeclaredMethod(methodName, paramTypesArray);
4599 } catch (NoSuchMethodException nsme) {
4600
4601 } catch (Exception e) {
4602 throw new RuntimeException("Problem retrieving method: " + theClass.getSimpleName() + ", " + methodName, e);
4603 }
4604
4605 if (method != null) {
4606
4607
4608 if (!isStaticOrInstance
4609 && Modifier.isStatic(method.getModifiers())) {
4610 return null;
4611 }
4612
4613 if (markerAnnotation == null
4614 || (includeAnnotation == method
4615 .isAnnotationPresent(markerAnnotation))) {
4616 return method;
4617 }
4618 }
4619
4620
4621 if (theClass.equals(superclassToStopAt)
4622 || theClass.equals(Object.class)) {
4623 return null;
4624 }
4625 Class superclass = theClass.getSuperclass();
4626 if (!includeSuperclassToStopAt && superclass.equals(superclassToStopAt)) {
4627 return null;
4628 }
4629
4630 return method(superclass, methodName, paramTypesArray, superclassToStopAt,
4631 includeSuperclassToStopAt, isStaticOrInstance, markerAnnotation, includeAnnotation);
4632 }
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657 @SuppressWarnings("unchecked")
4658 private static void fieldsHelper(Class theClass, Class superclassToStopAt,
4659 Class<?> fieldType, boolean includeSuperclassToStopAt,
4660 boolean includeStaticFields, boolean includeFinalFields,
4661 Class<? extends Annotation> markerAnnotation, Set<Field> fieldSet,
4662 boolean includeAnnotation) {
4663 theClass = unenhanceClass(theClass);
4664 Field[] fields = theClass.getDeclaredFields();
4665 if (length(fields) != 0) {
4666 for (Field field : fields) {
4667
4668 if (fieldType != null
4669 && !fieldType.isAssignableFrom(field.getType())) {
4670 continue;
4671 }
4672
4673 if (!includeStaticFields
4674 && Modifier.isStatic(field.getModifiers())) {
4675 continue;
4676 }
4677
4678 if (!includeFinalFields
4679 && Modifier.isFinal(field.getModifiers())) {
4680 continue;
4681 }
4682
4683 if (markerAnnotation != null
4684 && (includeAnnotation != field
4685 .isAnnotationPresent(markerAnnotation))) {
4686 continue;
4687 }
4688
4689 fieldSet.add(field);
4690 }
4691 }
4692
4693
4694 if (theClass.equals(superclassToStopAt)
4695 || theClass.equals(Object.class)) {
4696 return;
4697 }
4698 Class superclass = theClass.getSuperclass();
4699 if (!includeSuperclassToStopAt && superclass.equals(superclassToStopAt)) {
4700 return;
4701 }
4702
4703 fieldsHelper(superclass, superclassToStopAt, fieldType,
4704 includeSuperclassToStopAt, includeStaticFields,
4705 includeFinalFields, markerAnnotation, fieldSet,
4706 includeAnnotation);
4707 }
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725 public static Object fieldValue(Class theClass, Object invokeOn,
4726 String fieldName, boolean callOnSupers, boolean overrideSecurity, boolean considerFieldValuable) {
4727
4728
4729 if (considerFieldValuable && (invokeOn instanceof FieldValuable)) {
4730 return ((FieldValuable)invokeOn).fieldValue(fieldName);
4731 }
4732
4733 Field field = null;
4734
4735
4736 try {
4737
4738 if (theClass == null) {
4739 theClass = invokeOn.getClass();
4740 }
4741 field = field(theClass, fieldName, callOnSupers, true);
4742 return fieldValue(field, invokeOn, overrideSecurity);
4743 } catch (Exception e) {
4744 throw new RuntimeException("Cant execute reflection field: "
4745 + fieldName + ", on: " + className(invokeOn), e);
4746 }
4747 }
4748
4749
4750
4751
4752 public static interface FieldValuable {
4753
4754
4755
4756
4757
4758
4759 public Object fieldValue(String fieldName);
4760
4761 }
4762
4763
4764
4765
4766
4767
4768
4769
4770 public static Object fieldValue(Field field, Object invokeOn) {
4771 return fieldValue(field, invokeOn, true);
4772 }
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782 public static Object fieldValue(Field field, Object invokeOn,
4783 boolean overrideSecurity) {
4784
4785 if (overrideSecurity) {
4786 field.setAccessible(true);
4787 }
4788 try {
4789 return field.get(invokeOn);
4790 } catch (Exception e) {
4791 throw new RuntimeException("Cant execute reflection field: "
4792 + field.getName() + ", on: " + className(invokeOn), e);
4793
4794 }
4795
4796 }
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807 public static Object fieldValue(Object invokeOn, String fieldName) {
4808 return fieldValue(null, invokeOn, fieldName, true, true, true);
4809 }
4810
4811
4812
4813
4814
4815
4816
4817 private static Method[] retrieveDeclaredMethods(Class theClass) {
4818 Method[] methods = declaredMethodsCache().get(theClass);
4819
4820 if (methods == null) {
4821 methods = theClass.getDeclaredMethods();
4822 declaredMethodsCache().put(theClass, methods);
4823 }
4824 return methods;
4825 }
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839 public static Object callMethod(Class theClass, Object invokeOn,
4840 String methodName) {
4841 return callMethod(theClass, invokeOn, methodName, null, null);
4842 }
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859 public static Object callMethod(Class theClass, Object invokeOn,
4860 String methodName, Object paramTypesOrArrayOrList,
4861 Object paramsOrListOrArray) {
4862 return callMethod(theClass, invokeOn, methodName,
4863 paramTypesOrArrayOrList, paramsOrListOrArray, true);
4864 }
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883 public static Object callMethod(Class theClass, Object invokeOn,
4884 String methodName, Object paramTypesOrArrayOrList,
4885 Object paramsOrListOrArray, boolean callOnSupers) {
4886 return callMethod(theClass, invokeOn, methodName,
4887 paramTypesOrArrayOrList, paramsOrListOrArray, callOnSupers,
4888 false);
4889 }
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899 public static <T> T construct(Class<T> theClass, Class[] types, Object[] args) {
4900 try {
4901 Constructor<T> constructor = theClass.getConstructor(types);
4902
4903 return constructor.newInstance(args);
4904
4905 } catch (Exception e) {
4906 throw new RuntimeException("Having trouble with constructor for class: " + theClass.getSimpleName()
4907 + " and args: " + classesString(types), e);
4908 }
4909 }
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923 public static <K, V> Map<K, V> listToMap(List<V> list, @SuppressWarnings("unused") final Class<K> keyClass,
4924 @SuppressWarnings("unused") final Class<V> valueClass, String keyPropertyName) {
4925 Map<K,V> result = new LinkedHashMap<K, V>();
4926 for (V value : nonNull(list)) {
4927 K key = (K)propertyValue(value, keyPropertyName);
4928 result.put(key, value);
4929 }
4930 return result;
4931 }
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952 public static Object callMethod(Class theClass, Object invokeOn,
4953 String methodName, Object paramTypesOrArrayOrList,
4954 Object paramsOrListOrArray, boolean callOnSupers,
4955 boolean overrideSecurity) {
4956 try {
4957 Method method = null;
4958
4959 Class[] paramTypesArray = (Class[]) toArray(paramTypesOrArrayOrList);
4960
4961 try {
4962 method = theClass.getDeclaredMethod(methodName, paramTypesArray);
4963 if (overrideSecurity) {
4964 method.setAccessible(true);
4965 }
4966 } catch (Exception e) {
4967
4968 if (e instanceof NoSuchMethodException) {
4969
4970
4971
4972 if (callOnSupers
4973 && !theClass.equals(Object.class)) {
4974 return callMethod(theClass.getSuperclass(), invokeOn,
4975 methodName, paramTypesOrArrayOrList,
4976 paramsOrListOrArray, callOnSupers, overrideSecurity);
4977 }
4978 }
4979 throw new RuntimeException("Problem calling method " + methodName
4980 + " on " + theClass.getName(), e);
4981 }
4982
4983 return invokeMethod(method, invokeOn, paramsOrListOrArray);
4984 } catch (RuntimeException re) {
4985 String message = "Problem calling method " + methodName
4986 + " on " + (theClass == null ? null : theClass.getName());
4987 if (injectInException(re, message)) {
4988 throw re;
4989 }
4990 throw new RuntimeException(message, re);
4991 }
4992 }
4993
4994
4995 private static final Object NO_PARAMS = new Object();
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006 public static Object invokeMethod(Method method, Object invokeOn) {
5007 return invokeMethod(method, invokeOn, NO_PARAMS);
5008 }
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020 public static Object invokeMethod(Method method, Object invokeOn,
5021 Object paramsOrListOrArray) {
5022
5023 Object[] args = paramsOrListOrArray == NO_PARAMS ? null : (Object[]) toArray(paramsOrListOrArray);
5024
5025
5026 method.setAccessible(true);
5027
5028
5029 Object result = null;
5030 Exception e = null;
5031 try {
5032 result = method.invoke(invokeOn, args);
5033 } catch (IllegalAccessException iae) {
5034 e = iae;
5035 } catch (IllegalArgumentException iae) {
5036 e = iae;
5037 } catch (InvocationTargetException ite) {
5038
5039 if (ite.getCause() instanceof RuntimeException) {
5040 throw (RuntimeException)ite.getCause();
5041 }
5042
5043 e = ite;
5044 }
5045 if (e != null) {
5046 throw new RuntimeException("Cant execute reflection method: "
5047 + method.getName() + ", on: " + className(invokeOn)
5048 + ", with args: " + classNameCollection(args), e);
5049 }
5050 return result;
5051 }
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061 public static Object toArray(Object objectOrArrayOrCollection) {
5062
5063
5064 if (objectOrArrayOrCollection != null
5065 && objectOrArrayOrCollection.getClass().isArray()) {
5066 return objectOrArrayOrCollection;
5067 }
5068 int length = length(objectOrArrayOrCollection);
5069 if (length == 0) {
5070 return null;
5071 }
5072
5073 if (objectOrArrayOrCollection instanceof Collection) {
5074 Collection<Object> collection = (Collection<Object>) objectOrArrayOrCollection;
5075 Object first = collection.iterator().next();
5076 Class<Object> theClass = first == null ? (Class)Object.class : (Class)first
5077 .getClass();
5078 return toArray(collection, theClass);
5079 }
5080
5081 Object array = Array.newInstance(objectOrArrayOrCollection.getClass(),
5082 1);
5083 Array.set(array, 0, objectOrArrayOrCollection);
5084 return array;
5085 }
5086
5087
5088
5089
5090
5091
5092
5093
5094 @SuppressWarnings("unchecked")
5095 public static <T> T[] toArray(Collection collection, Class<T> theClass) {
5096 if (collection == null || collection.size() == 0) {
5097 return null;
5098 }
5099
5100 return (T[])collection.toArray((Object[]) Array.newInstance(theClass,
5101 collection.size()));
5102
5103 }
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115 public static Object callMethod(Class theClass, String methodName) {
5116 return callMethod(theClass, null, methodName, null, null);
5117 }
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130 public static Object callMethod(Class theClass, String methodName,
5131 boolean callOnSupers) {
5132 return callMethod(theClass, null, methodName, null, null, callOnSupers);
5133 }
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148 public static Object callMethod(Class theClass, String methodName,
5149 Object paramTypesOrArrayOrList, Object paramsOrListOrArray) {
5150 return callMethod(theClass, null, methodName, paramTypesOrArrayOrList,
5151 paramsOrListOrArray);
5152 }
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164 public static Object callMethod(Object invokeOn, String methodName) {
5165 if (invokeOn == null) {
5166 throw new NullPointerException("invokeOn is null: " + methodName);
5167 }
5168 return callMethod(invokeOn.getClass(), invokeOn, methodName, null,
5169 null, true, true);
5170 }
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184 public static String replace(String text, Object searchFor,
5185 Object replaceWith) {
5186 return replace(null, null, text, searchFor, replaceWith, false, 0,
5187 false);
5188 }
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204 public static String replace(String text, Object searchFor,
5205 Object replaceWith, boolean recurse) {
5206 return replace(null, null, text, searchFor, replaceWith, recurse,
5207 recurse ? length(searchFor) : 0, false);
5208 }
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226 public static String replace(String text, Object searchFor,
5227 Object replaceWith, boolean recurse, boolean removeIfFound) {
5228 return replace(null, null, text, searchFor, replaceWith, recurse,
5229 recurse ? length(searchFor) : 0, removeIfFound);
5230 }
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262 public static String replace(String text, String repl, String with) {
5263 return replace(text, repl, with, -1);
5264 }
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303 public static String replace(String text, String repl, String with, int max) {
5304 if (text == null || isEmpty(repl) || with == null || max == 0) {
5305 return text;
5306 }
5307
5308 StringBuffer buf = new StringBuffer(text.length());
5309 int start = 0, end = 0;
5310 while ((end = text.indexOf(repl, start)) != -1) {
5311 buf.append(text.substring(start, end)).append(with);
5312 start = end + repl.length();
5313
5314 if (--max == 0) {
5315 break;
5316 }
5317 }
5318 buf.append(text.substring(start));
5319 return buf.toString();
5320 }
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344 public static boolean isEmpty(String str) {
5345 return str == null || str.length() == 0;
5346 }
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361 public static void replace(StringBuffer outBuffer, String text,
5362 Object searchFor, Object replaceWith) {
5363 replace(outBuffer, null, text, searchFor, replaceWith, false, 0, false);
5364 }
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381 public static void replace(StringBuffer outBuffer, String text,
5382 Object searchFor, Object replaceWith, boolean recurse) {
5383 replace(outBuffer, null, text, searchFor, replaceWith, recurse,
5384 recurse ? length(searchFor) : 0, false);
5385 }
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416 private static String replace(StringBuffer outBuffer, Writer outWriter,
5417 String text, Object searchFor, Object replaceWith, boolean recurse,
5418 int timeToLive, boolean removeIfFound) {
5419
5420
5421
5422 if (!recurse) {
5423 return replaceHelper(outBuffer, outWriter, text, searchFor,
5424 replaceWith, recurse, timeToLive, removeIfFound);
5425 }
5426
5427 String result = replaceHelper(null, null, text, searchFor, replaceWith,
5428 recurse, timeToLive, removeIfFound);
5429 if (outBuffer != null) {
5430 outBuffer.append(result);
5431 return null;
5432 }
5433
5434 if (outWriter != null) {
5435 try {
5436 outWriter.write(result);
5437 } catch (IOException ioe) {
5438 throw new RuntimeException(ioe);
5439 }
5440 return null;
5441 }
5442
5443 return result;
5444
5445 }
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460 public static void replace(Writer outWriter, String text, Object searchFor,
5461 Object replaceWith) {
5462 replace(null, outWriter, text, searchFor, replaceWith, false, 0, false);
5463 }
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480 public static void replace(Writer outWriter, String text, Object searchFor,
5481 Object replaceWith, boolean recurse) {
5482 replace(null, outWriter, text, searchFor, replaceWith, recurse,
5483 recurse ? length(searchFor) : 0, false);
5484 }
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515 private static String replaceHelper(StringBuffer outBuffer,
5516 Writer outWriter, String text, Object searchFor,
5517 Object replaceWith, boolean recurse, int timeToLive,
5518 boolean removeIfFound) {
5519
5520 try {
5521
5522 if (timeToLive < 0) {
5523 throw new IllegalArgumentException("TimeToLive under 0: "
5524 + timeToLive + ", " + text);
5525 }
5526
5527 int searchForLength = length(searchFor);
5528 boolean done = false;
5529
5530 if (isEmpty(text)) {
5531 return text;
5532 }
5533
5534 if (searchForLength == 0) {
5535 done = true;
5536 }
5537
5538 boolean[] noMoreMatchesForReplIndex = null;
5539 int inputIndex = -1;
5540 int replaceIndex = -1;
5541 long resultPacked = -1;
5542
5543 if (!done) {
5544
5545 if (searchForLength != length(replaceWith)) {
5546 throw new IndexOutOfBoundsException("Lengths dont match: "
5547 + searchForLength + ", " + length(replaceWith));
5548 }
5549
5550
5551 noMoreMatchesForReplIndex = new boolean[searchForLength];
5552
5553
5554
5555
5556
5557 resultPacked = findNextIndexHelper(searchForLength, searchFor,
5558 replaceWith,
5559 noMoreMatchesForReplIndex, text, 0);
5560
5561 inputIndex = unpackInt(resultPacked, true);
5562 replaceIndex = unpackInt(resultPacked, false);
5563 }
5564
5565
5566
5567
5568 boolean writeToWriter = outWriter != null;
5569
5570
5571 if (done || inputIndex == -1) {
5572 if (writeToWriter) {
5573 outWriter.write(text, 0, text.length());
5574 return null;
5575 }
5576 if (outBuffer != null) {
5577 appendSubstring(outBuffer, text, 0, text.length());
5578 return null;
5579 }
5580 return text;
5581 }
5582
5583
5584 StringBuffer bufferToWriteTo = outBuffer != null ? outBuffer
5585 : (writeToWriter ? null : new StringBuffer(text.length()
5586 + replaceStringsBufferIncrease(text, searchFor,
5587 replaceWith)));
5588
5589 String searchString = null;
5590 String replaceString = null;
5591
5592 int start = 0;
5593
5594 while (inputIndex != -1) {
5595
5596 searchString = (String) get(searchFor, replaceIndex);
5597 replaceString = (String) get(replaceWith, replaceIndex);
5598 if (writeToWriter) {
5599 outWriter.write(text, start, inputIndex - start);
5600 outWriter.write(replaceString);
5601 } else {
5602 appendSubstring(bufferToWriteTo, text, start, inputIndex)
5603 .append(replaceString);
5604 }
5605
5606 if (removeIfFound) {
5607
5608 searchFor = remove(searchFor, replaceIndex);
5609 replaceWith = remove(replaceWith, replaceIndex);
5610 noMoreMatchesForReplIndex = (boolean[])remove(noMoreMatchesForReplIndex, replaceIndex);
5611
5612 searchForLength--;
5613 }
5614
5615 start = inputIndex + searchString.length();
5616
5617 resultPacked = findNextIndexHelper(searchForLength, searchFor,
5618 replaceWith,
5619 noMoreMatchesForReplIndex, text, start);
5620 inputIndex = unpackInt(resultPacked, true);
5621 replaceIndex = unpackInt(resultPacked, false);
5622 }
5623 if (writeToWriter) {
5624 outWriter.write(text, start, text.length() - start);
5625
5626 } else {
5627 appendSubstring(bufferToWriteTo, text, start, text.length());
5628 }
5629
5630
5631 if (writeToWriter || outBuffer != null) {
5632 if (recurse) {
5633 throw new IllegalArgumentException(
5634 "Cannot recurse and write to existing buffer or writer!");
5635 }
5636 return null;
5637 }
5638 String resultString = bufferToWriteTo.toString();
5639
5640 if (recurse) {
5641 return replaceHelper(outBuffer, outWriter, resultString,
5642 searchFor, replaceWith, recurse, timeToLive - 1, false);
5643 }
5644
5645 return resultString;
5646 } catch (IOException ioe) {
5647 throw new RuntimeException(ioe);
5648 }
5649 }
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661 static int replaceStringsBufferIncrease(String text, Object repl,
5662 Object with) {
5663
5664 int increase = 0;
5665 Iterator iteratorReplace = iterator(repl);
5666 Iterator iteratorWith = iterator(with);
5667 int replLength = length(repl);
5668 String currentRepl = null;
5669 String currentWith = null;
5670 for (int i = 0; i < replLength; i++) {
5671 currentRepl = (String) next(repl, iteratorReplace, i);
5672 currentWith = (String) next(with, iteratorWith, i);
5673 if (currentRepl == null || currentWith == null) {
5674 throw new NullPointerException("Replace string is null: "
5675 + text + ", " + currentRepl + ", " + currentWith);
5676 }
5677 int greater = currentWith.length() - currentRepl.length();
5678 increase += greater > 0 ? 3 * greater : 0;
5679 }
5680
5681 increase = Math.min(increase, text.length() / 5);
5682 return increase;
5683 }
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697 private static long findNextIndexHelper(int searchForLength,
5698 Object searchFor, Object replaceWith, boolean[] noMoreMatchesForReplIndex,
5699 String input, int start) {
5700
5701 int inputIndex = -1;
5702 int replaceIndex = -1;
5703
5704 Iterator iteratorSearchFor = iterator(searchFor);
5705 Iterator iteratorReplaceWith = iterator(replaceWith);
5706
5707 String currentSearchFor = null;
5708 String currentReplaceWith = null;
5709 int tempIndex = -1;
5710 for (int i = 0; i < searchForLength; i++) {
5711 currentSearchFor = (String) next(searchFor, iteratorSearchFor, i);
5712 currentReplaceWith = (String) next(replaceWith,
5713 iteratorReplaceWith, i);
5714 if (noMoreMatchesForReplIndex[i] || isEmpty(currentSearchFor)
5715 || currentReplaceWith == null) {
5716 continue;
5717 }
5718 tempIndex = input.indexOf(currentSearchFor, start);
5719
5720
5721 noMoreMatchesForReplIndex[i] = tempIndex == -1;
5722
5723 if (tempIndex != -1 && (inputIndex == -1 || tempIndex < inputIndex)) {
5724 inputIndex = tempIndex;
5725 replaceIndex = i;
5726 }
5727
5728 }
5729
5730 long resultPacked = packInts(inputIndex, replaceIndex);
5731 return resultPacked;
5732 }
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744 public static long packInts(int first, int second) {
5745 long result = first;
5746 result <<= 32;
5747 result |= second;
5748 return result;
5749 }
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760 public static int unpackInt(long theLong, boolean isFirst) {
5761
5762 int result = 0;
5763
5764 if (isFirst) {
5765 theLong >>= 32;
5766 }
5767
5768 result = (int) (theLong & 0xffffffff);
5769 return result;
5770 }
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786 private static StringBuffer appendSubstring(StringBuffer buf,
5787 String string, int start, int end) {
5788 for (int i = start; i < end; i++) {
5789 buf.append(string.charAt(i));
5790 }
5791 return buf;
5792 }
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802 public static Object get(Object arrayOrCollection, int index) {
5803
5804 if (arrayOrCollection == null) {
5805 if (index == 0) {
5806 return null;
5807 }
5808 throw new RuntimeException("Trying to access index " + index
5809 + " of null");
5810 }
5811
5812
5813 if (arrayOrCollection instanceof List) {
5814 return ((List) arrayOrCollection).get(index);
5815 }
5816 if (arrayOrCollection instanceof Collection) {
5817 Iterator iterator = iterator(arrayOrCollection);
5818 for (int i = 0; i < index; i++) {
5819 next(arrayOrCollection, iterator, i);
5820 }
5821 return next(arrayOrCollection, iterator, index);
5822 }
5823
5824 if (arrayOrCollection.getClass().isArray()) {
5825 return Array.get(arrayOrCollection, index);
5826 }
5827
5828 if (index == 0) {
5829 return arrayOrCollection;
5830 }
5831
5832 throw new RuntimeException("Trying to access index " + index
5833 + " of and object: " + arrayOrCollection);
5834 }
5835
5836
5837
5838
5839
5840
5841 public static String toString(Collection<Source> sources) {
5842 if (length(sources) == 0) {
5843 return null;
5844 }
5845 StringBuilder result = new StringBuilder();
5846 for (Source source : sources) {
5847 result.append(source.getId()).append(", ");
5848 }
5849 result.delete(result.length()-2, result.length());
5850 return result.toString();
5851 }
5852
5853
5854
5855
5856
5857
5858
5859 public static String toStringSafe(Object object) {
5860 if (object == null) {
5861 return null;
5862 }
5863
5864 try {
5865
5866 if (object instanceof Collection) {
5867 Collection<Object> collection = (Collection<Object>) object;
5868 int collectionSize = collection.size();
5869 if (collectionSize == 0) {
5870 return "Empty " + object.getClass().getSimpleName();
5871 }
5872 Object first = collection.iterator().next();
5873 return object.getClass().getSimpleName() + " of size "
5874 + collectionSize + " with first type: " +
5875 (first == null ? null : first.getClass());
5876 }
5877
5878 return object.toString();
5879 } catch (Exception e) {
5880 return "<<exception>> " + object.getClass() + ":\n" + getFullStackTrace(e) + "\n";
5881 }
5882 }
5883
5884
5885
5886
5887
5888
5889
5890 public static boolean booleanValue(Object object) {
5891
5892 if (nullOrBlank(object)) {
5893 throw new RuntimeException(
5894 "Expecting something which can be converted to boolean, but is null or blank: '"
5895 + object + "'");
5896 }
5897
5898 if (object instanceof Boolean) {
5899 return (Boolean) object;
5900 }
5901 if (object instanceof String) {
5902 String string = (String) object;
5903 if (equalsIgnoreCase(string, "true")
5904 || equalsIgnoreCase(string, "t")
5905 || equalsIgnoreCase(string, "yes")
5906 || equalsIgnoreCase(string, "on")
5907 || equalsIgnoreCase(string, "y")) {
5908 return true;
5909 }
5910 if (equalsIgnoreCase(string, "false")
5911 || equalsIgnoreCase(string, "f")
5912 || equalsIgnoreCase(string, "no")
5913 || equalsIgnoreCase(string, "off")
5914 || equalsIgnoreCase(string, "n")) {
5915 return false;
5916 }
5917 throw new RuntimeException(
5918 "Invalid string to boolean conversion: '" + string
5919 + "' expecting true|false or t|f or yes|no or y|n case insensitive");
5920
5921 }
5922 throw new RuntimeException("Cant convert object to boolean: "
5923 + object.getClass());
5924
5925 }
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935 public static boolean booleanValue(Object object, boolean defaultBoolean) {
5936 if (nullOrBlank(object)) {
5937 return defaultBoolean;
5938 }
5939 return booleanValue(object);
5940 }
5941
5942
5943
5944
5945
5946
5947
5948 public static Boolean booleanObjectValue(Object object) {
5949 if (nullOrBlank(object)) {
5950 return null;
5951 }
5952 return booleanValue(object);
5953 }
5954
5955
5956
5957
5958
5959
5960
5961 public static boolean nullOrBlank(Object object) {
5962
5963 if (object == null) {
5964 return true;
5965 }
5966 if (object instanceof String && isBlank(((String) object))) {
5967 return true;
5968 }
5969 return false;
5970
5971 }
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981 public static Method getter(Class theClass, String fieldName, boolean callOnSupers,
5982 boolean throwExceptionIfNotFound) {
5983 String getterName = getterNameFromPropertyName(theClass, fieldName);
5984 return getterHelper(theClass, fieldName, getterName, callOnSupers, throwExceptionIfNotFound);
5985 }
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996 public static Method getterHelper(Class theClass, String fieldName, String getterName,
5997 boolean callOnSupers, boolean throwExceptionIfNotFound) {
5998 Method[] methods = retrieveDeclaredMethods(theClass);
5999 if (methods != null) {
6000 for (Method method : methods) {
6001 if (equals(getterName, method.getName()) && isGetter(method)) {
6002 return method;
6003 }
6004 }
6005 }
6006
6007
6008 if (callOnSupers && !theClass.equals(Object.class)) {
6009 return getterHelper(theClass.getSuperclass(), fieldName, getterName,
6010 callOnSupers, throwExceptionIfNotFound);
6011 }
6012
6013 if (throwExceptionIfNotFound) {
6014 throw new PropertyDoesNotExistUnchecked("Cant find getter: "
6015 + getterName + ", in: " + theClass
6016 + ", callOnSupers: " + callOnSupers);
6017 }
6018 return null;
6019 }
6020
6021
6022
6023
6024
6025
6026 public static String getterNameFromPropertyName(Class theClass, String propertyName) {
6027
6028 Set<Field> fields = fields(theClass, null, null, false);
6029 for (Field field : nonNull(fields)) {
6030 if (propertyName.equals(field.getName())) {
6031 if (boolean.class.equals(field.getType())) {
6032 return "is" + capitalize(propertyName);
6033 }
6034 break;
6035 }
6036 }
6037 String getterName = "get" + capitalize(propertyName);
6038 String iserName = "is" + capitalize(propertyName);
6039 Set<String> methodNames = methodNames(theClass, null, false, false);
6040 if (methodNames.contains(iserName)) {
6041 return iserName;
6042 }
6043 return getterName;
6044 }
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057 @SuppressWarnings("unchecked")
6058 public static Set<Method> getters(Class theClass, Class superclassToStopAt,
6059 Class<? extends Annotation> markerAnnotation, Boolean includeAnnotation) {
6060 return gettersHelper(theClass, superclassToStopAt, null, true,
6061 markerAnnotation, includeAnnotation);
6062 }
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075 @SuppressWarnings("unchecked")
6076 static Set<Method> gettersHelper(Class theClass, Class superclassToStopAt, Class<?> fieldType,
6077 boolean includeSuperclassToStopAt,
6078 Class<? extends Annotation> markerAnnotation, Boolean includeAnnotation) {
6079
6080
6081 Set<Method> getterSet = null;
6082 String cacheKey = theClass + CACHE_SEPARATOR + superclassToStopAt + CACHE_SEPARATOR + fieldType + CACHE_SEPARATOR
6083 + includeSuperclassToStopAt + CACHE_SEPARATOR + markerAnnotation + CACHE_SEPARATOR + includeAnnotation;
6084 getterSet = getterSetCache().get(cacheKey);
6085 if (getterSet != null) {
6086 return getterSet;
6087 }
6088
6089 getterSet = new LinkedHashSet<Method>();
6090 gettersHelper(theClass, superclassToStopAt, fieldType, includeSuperclassToStopAt,
6091 markerAnnotation, getterSet, includeAnnotation);
6092
6093
6094 getterSetCache().put(cacheKey, getterSet);
6095
6096 return getterSet;
6097
6098 }
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111 @SuppressWarnings("unchecked")
6112 private static void gettersHelper(Class theClass, Class superclassToStopAt, Class<?> propertyType,
6113 boolean includeSuperclassToStopAt,
6114 Class<? extends Annotation> markerAnnotation, Set<Method> getterSet, Boolean includeAnnotation) {
6115 theClass = unenhanceClass(theClass);
6116 Method[] methods = retrieveDeclaredMethods(theClass);
6117 if (length(methods) != 0) {
6118
6119
6120 List<Method> methodsList = new ArrayList<Method>();
6121
6122 for (Method method: methods) {
6123 methodsList.add(method);
6124 }
6125
6126 Collections.sort(methodsList, new Comparator<Method>() {
6127
6128 @Override
6129 public int compare(Method o1, Method o2) {
6130 return o1.getName().compareTo(o2.getName());
6131 }
6132 });
6133
6134 for (Method method: methodsList) {
6135
6136 if (!isGetter(method)) {
6137 continue;
6138 }
6139
6140 if (markerAnnotation != null
6141 && (includeAnnotation != method.isAnnotationPresent(markerAnnotation))) {
6142 continue;
6143 }
6144
6145 if (propertyType != null && !propertyType.isAssignableFrom(method.getReturnType())) {
6146 continue;
6147 }
6148
6149
6150 getterSet.add(method);
6151 }
6152 }
6153
6154 if (theClass.equals(superclassToStopAt) || theClass.equals(Object.class)) {
6155 return;
6156 }
6157 Class superclass = theClass.getSuperclass();
6158 if (!includeSuperclassToStopAt && superclass.equals(superclassToStopAt)) {
6159 return;
6160 }
6161
6162 gettersHelper(superclass, superclassToStopAt, propertyType,
6163 includeSuperclassToStopAt, markerAnnotation, getterSet,
6164 includeAnnotation);
6165 }
6166
6167
6168
6169
6170
6171
6172
6173 public static boolean isGetter(Method method) {
6174
6175
6176 String methodName = method.getName();
6177 if (!methodName.startsWith("get") && !methodName.startsWith("is")) {
6178 return false;
6179 }
6180
6181
6182 if (method.getReturnType() == Void.TYPE) {
6183 return false;
6184 }
6185
6186
6187 if (length(method.getParameterTypes()) != 0) {
6188 return false;
6189 }
6190
6191
6192 if (Modifier.isStatic(method.getModifiers())) {
6193 return false;
6194 }
6195
6196 return true;
6197 }
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208 public static void assignSetter(Object invokeOn,
6209 String fieldName, Object dataToAssign, boolean typeCast) {
6210 Class invokeOnClass = invokeOn.getClass();
6211 try {
6212 Method setter = setter(invokeOnClass, fieldName, true, true);
6213 setter.setAccessible(true);
6214 if (typeCast) {
6215 dataToAssign = typeCast(dataToAssign, setter.getParameterTypes()[0]);
6216 }
6217 setter.invoke(invokeOn, new Object[]{dataToAssign});
6218 } catch (Exception e) {
6219 throw new RuntimeException("Problem assigning setter: " + fieldName
6220 + " on class: " + invokeOnClass + ", type of data is: " + className(dataToAssign), e);
6221 }
6222 }
6223
6224
6225
6226
6227
6228
6229
6230 public static boolean isSetter(Method method) {
6231
6232
6233 if (!method.getName().startsWith("set")) {
6234 return false;
6235 }
6236
6237
6238 if (method.getReturnType() != Void.TYPE) {
6239 return false;
6240 }
6241
6242
6243 if (length(method.getParameterTypes()) != 1) {
6244 return false;
6245 }
6246
6247
6248 if (Modifier.isStatic(method.getModifiers())) {
6249 return false;
6250 }
6251
6252 return true;
6253 }
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263 public static Method setter(Class theClass, String fieldName, boolean callOnSupers,
6264 boolean throwExceptionIfNotFound) {
6265 String setterName = setterNameFromPropertyName(fieldName);
6266 return setterHelper(theClass, fieldName, setterName, callOnSupers, throwExceptionIfNotFound);
6267 }
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278 public static Method setterHelper(Class theClass, String fieldName, String setterName,
6279 boolean callOnSupers, boolean throwExceptionIfNotFound) {
6280 Method[] methods = retrieveDeclaredMethods(theClass);
6281 if (methods != null) {
6282 for (Method method : methods) {
6283 if (equals(setterName, method.getName()) && isSetter(method)) {
6284 return method;
6285 }
6286 }
6287 }
6288
6289
6290 if (callOnSupers && !theClass.equals(Object.class)) {
6291 return setterHelper(theClass.getSuperclass(), fieldName, setterName,
6292 callOnSupers, throwExceptionIfNotFound);
6293 }
6294
6295 if (throwExceptionIfNotFound) {
6296 throw new PropertyDoesNotExistUnchecked("Cant find setter: "
6297 + setterName + ", in: " + theClass
6298 + ", callOnSupers: " + callOnSupers);
6299 }
6300 return null;
6301 }
6302
6303
6304
6305
6306
6307
6308 public static String setterNameFromPropertyName(String propertyName) {
6309 return "set" + capitalize(propertyName);
6310 }
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323 @SuppressWarnings("unchecked")
6324 public static Set<Method> setters(Class theClass, Class superclassToStopAt, Class<?> fieldType,
6325 boolean includeSuperclassToStopAt,
6326 Class<? extends Annotation> markerAnnotation, boolean includeAnnotation) {
6327 return settersHelper(theClass, superclassToStopAt, fieldType,
6328 includeSuperclassToStopAt, markerAnnotation, includeAnnotation);
6329 }
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342 @SuppressWarnings("unchecked")
6343 static Set<Method> settersHelper(Class theClass, Class superclassToStopAt, Class<?> fieldType,
6344 boolean includeSuperclassToStopAt,
6345 Class<? extends Annotation> markerAnnotation, boolean includeAnnotation) {
6346
6347
6348 Set<Method> setterSet = null;
6349 String cacheKey = theClass + CACHE_SEPARATOR + superclassToStopAt + CACHE_SEPARATOR + fieldType + CACHE_SEPARATOR
6350 + includeSuperclassToStopAt + CACHE_SEPARATOR + markerAnnotation + CACHE_SEPARATOR + includeAnnotation;
6351 setterSet = setterSetCache().get(cacheKey);
6352 if (setterSet != null) {
6353 return setterSet;
6354 }
6355
6356 setterSet = new LinkedHashSet<Method>();
6357 settersHelper(theClass, superclassToStopAt, fieldType, includeSuperclassToStopAt,
6358 markerAnnotation, setterSet, includeAnnotation);
6359
6360
6361 setterSetCache().put(cacheKey, setterSet);
6362
6363 return setterSet;
6364
6365 }
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378 @SuppressWarnings("unchecked")
6379 private static void settersHelper(Class theClass, Class superclassToStopAt, Class<?> propertyType,
6380 boolean includeSuperclassToStopAt,
6381 Class<? extends Annotation> markerAnnotation, Set<Method> setterSet, Boolean includeAnnotation) {
6382 theClass = unenhanceClass(theClass);
6383 Method[] methods = retrieveDeclaredMethods(theClass);
6384 if (length(methods) != 0) {
6385 for (Method method: methods) {
6386
6387 if (!isSetter(method)) {
6388 continue;
6389 }
6390
6391 if (markerAnnotation != null
6392 && (includeAnnotation != method.isAnnotationPresent(markerAnnotation))) {
6393 continue;
6394 }
6395
6396 if (propertyType != null && !propertyType.isAssignableFrom(method.getParameterTypes()[0])) {
6397 continue;
6398 }
6399
6400
6401 setterSet.add(method);
6402 }
6403 }
6404
6405 if (theClass.equals(superclassToStopAt) || theClass.equals(Object.class)) {
6406 return;
6407 }
6408 Class superclass = theClass.getSuperclass();
6409 if (!includeSuperclassToStopAt && superclass.equals(superclassToStopAt)) {
6410 return;
6411 }
6412
6413 settersHelper(superclass, superclassToStopAt, propertyType,
6414 includeSuperclassToStopAt, markerAnnotation, setterSet,
6415 includeAnnotation);
6416 }
6417
6418
6419
6420
6421
6422
6423 public static String propertyName(Method method) {
6424 String methodName = method.getName();
6425 boolean isGetter = methodName.startsWith("get");
6426 boolean isSetter = methodName.startsWith("set");
6427 boolean isIsser = methodName.startsWith("is");
6428 int expectedLength = isIsser ? 2 : 3;
6429 int length = methodName.length();
6430 if ((!(isGetter || isSetter || isIsser)) || (length <= expectedLength)) {
6431 throw new RuntimeException("Not a getter or setter: " + methodName);
6432 }
6433 char fourthCharLower = Character.toLowerCase(methodName.charAt(expectedLength));
6434
6435 if (length == expectedLength +1) {
6436 return Character.toString(fourthCharLower);
6437 }
6438
6439 return fourthCharLower + methodName.substring(expectedLength+1, length);
6440 }
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451 public static <T> List<T> propertyList(Collection<?> collection,
6452 String propertyName, @SuppressWarnings("unused") Class<T> fieldType) {
6453
6454 if (collection == null) {
6455 return null;
6456 }
6457
6458 List<T> list = new ArrayList<T>();
6459
6460 for (Object object : collection) {
6461 T value = (T)propertyValue(object, propertyName);
6462 list.add(value);
6463 }
6464
6465 return list;
6466
6467 }
6468
6469
6470
6471
6472
6473
6474
6475
6476 public static Class propertyType(Class theClass, String propertyName) {
6477 theClass = unenhanceClass(theClass);
6478 Method method = getter(theClass, propertyName, true, false);
6479 if (method != null) {
6480 return method.getReturnType();
6481 }
6482
6483 method = setter(theClass, propertyName, true, false);
6484 if (method != null) {
6485 return method.getParameterTypes()[0];
6486 }
6487
6488 Field field = field(theClass, propertyName, true, true);
6489 return field.getType();
6490 }
6491
6492
6493
6494
6495
6496
6497
6498
6499
6500 public static <T> T typeCast(Object value, Class<T> theClass) {
6501
6502 return typeCast(value, theClass, false, false);
6503 }
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516
6517
6518
6519
6520
6521 public static File newFileUniqueName(String parentDirName, String namePrefix, String nameSuffix, boolean createFile) {
6522
6523 String errorMessage = "\n\nError: grouper needs to be able to write files, make sure your directories are owned and writable by 'tomcat.tomcat' perhaps need to set this in Dockerfile if applicable"
6524 + "\nRUN chown -R tomcat:tomcat /opt/grouper/grouperWebapp\n\n";
6525
6526 DateFormat fileNameFormat = new SimpleDateFormat("yyyyMMdd_HH_mm_ss_SSS");
6527 if (!isBlank(parentDirName)) {
6528 parentDirName=fixRelativePath(parentDirName);
6529 if (!parentDirName.endsWith("/") && !parentDirName.endsWith("\\")) {
6530 parentDirName += File.separator;
6531 }
6532
6533
6534 File parentDir = new File(parentDirName);
6535 if (!parentDir.exists()) {
6536 if (!parentDir.mkdirs()) {
6537 throw new RuntimeException("Cant make dir: " + parentDir.getAbsolutePath() + errorMessage);
6538 }
6539 } else {
6540 if (!parentDir.isDirectory()) {
6541 throw new RuntimeException("Parent dir is not a directory: " + parentDir.getAbsolutePath());
6542 }
6543 }
6544
6545 } else {
6546
6547 parentDirName = "";
6548 }
6549
6550 if (!nameSuffix.contains(".")) {
6551 nameSuffix = "." + nameSuffix;
6552 }
6553
6554 String fileName = parentDirName + namePrefix + "_" + fileNameFormat.format(new Date()) + nameSuffix;
6555 int dotLocation = fileName.lastIndexOf('.');
6556 String fileNamePre = fileName.substring(0,dotLocation);
6557 String fileNamePost = fileName.substring(dotLocation);
6558 File theFile = new File(fileName);
6559
6560 int i;
6561
6562 for (i=0;i<1000;i++) {
6563
6564 if (!theFile.exists()) {
6565 break;
6566 }
6567
6568 fileName = fileNamePre + "_" + i + fileNamePost;
6569 theFile = new File(fileName);
6570
6571 }
6572
6573 if (i>=1000) {
6574 throw new RuntimeException("Cant find filename to create: " + fileName);
6575 }
6576
6577 if (createFile) {
6578 try {
6579 if (!theFile.createNewFile()) {
6580 throw new RuntimeException("Cant create file, it returned false. ");
6581 }
6582 } catch (Exception e) {
6583 throw new RuntimeException("Cant create file: " + fileName + ", make sure " +
6584 "permissions and such are ok, or change file location in grouper.properties if applicable. " + errorMessage, e);
6585 }
6586 }
6587 return theFile;
6588 }
6589
6590
6591
6592
6593
6594
6595 public static Long dateLongValue(String date) {
6596 if (isBlank(date)) {
6597 return null;
6598 }
6599 Date dateObject = dateValue(date);
6600 return dateObject.getTime();
6601 }
6602
6603
6604
6605
6606 private static final String TIMESTAMP_XML_FORMAT = "yyyy/MM/dd HH:mm:ss.SSS";
6607
6608
6609
6610
6611
6612
6613 public static String dateStringValue(Date date) {
6614 if (date == null) {
6615 return null;
6616 }
6617 SimpleDateFormat simpleDateFormat = new SimpleDateFormat(TIMESTAMP_XML_FORMAT);
6618 return simpleDateFormat.format(date);
6619 }
6620
6621
6622
6623
6624
6625
6626 public static String dateStringValue(Long theDate) {
6627 if (theDate == null) {
6628 return null;
6629 }
6630 return dateStringValue(new Date(theDate));
6631 }
6632
6633
6634
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644 public static Date dateValue(Object inputObject) {
6645 if (inputObject == null) {
6646 return null;
6647 }
6648
6649 if (inputObject instanceof java.util.Date) {
6650 return (Date)inputObject;
6651 }
6652
6653 if (inputObject instanceof String) {
6654 String input = (String)inputObject;
6655
6656 if (isBlank(input)) {
6657 return null;
6658 }
6659
6660 try {
6661 if (input.length() == 8) {
6662
6663 return dateFormat().parse(input);
6664 }
6665 if (!contains(input, '.')) {
6666 if (contains(input, '/')) {
6667 return dateMinutesSecondsFormat.parse(input);
6668 }
6669
6670 return dateMinutesSecondsNoSlashFormat.parse(input);
6671 }
6672 if (contains(input, '/')) {
6673
6674 int lastDotIndex = input.lastIndexOf('.');
6675 if (lastDotIndex == input.length() - 7) {
6676 String nonNanoInput = input.substring(0,input.length()-3);
6677 Date date = timestampFormat.parse(nonNanoInput);
6678
6679 String lastThree = input.substring(input.length()-3,input.length());
6680 int lastThreeInt = Integer.parseInt(lastThree);
6681 Timestamp timestamp = new Timestamp(date.getTime());
6682 timestamp.setNanos(timestamp.getNanos() + (lastThreeInt * 1000));
6683 return timestamp;
6684 }
6685 return timestampFormat.parse(input);
6686 }
6687
6688 return timestampNoSlashFormat.parse(input);
6689 } catch (ParseException pe) {
6690 throw new RuntimeException(errorStart + toStringForLog(input));
6691 }
6692 }
6693
6694 throw new RuntimeException("Cannot convert Object to date : " + toStringForLog(inputObject));
6695 }
6696
6697
6698
6699
6700 private static Pattern datePattern_yyyy_mm_dd = Pattern.compile("^(\\d{4})[^\\d]+(\\d{1,2})[^\\d]+(\\d{1,2})$");
6701
6702
6703
6704
6705 private static Pattern datePattern_dd_mon_yyyy = Pattern.compile("^(\\d{1,2})[^\\d]+([a-zA-Z]{3,15})[^\\d]+(\\d{4})$");
6706
6707
6708
6709
6710 private static Pattern datePattern_yyyy_mm_dd_hhmmss = Pattern.compile("^(\\d{4})[^\\d]+(\\d{1,2})[^\\d]+(\\d{1,2})[^\\d]+(\\d{1,2})[^\\d]+(\\d{1,2})[^\\d]+(\\d{1,2})$");
6711
6712
6713
6714
6715 private static Pattern datePattern_dd_mon_yyyy_hhmmss = Pattern.compile("^(\\d{1,2})[^\\d]+([a-zA-Z]{3,15})[^\\d]+(\\d{4})[^\\d]+(\\d{1,2})[^\\d]+(\\d{1,2})[^\\d]+(\\d{1,2})$");
6716
6717
6718
6719
6720 private static Pattern datePattern_yyyy_mm_dd_hhmmss_SSS = Pattern.compile("^(\\d{4})[^\\d]+(\\d{1,2})[^\\d]+(\\d{1,2})[^\\d]+(\\d{1,2})[^\\d]+(\\d{1,2})[^\\d]+(\\d{1,2})[^\\d]+(\\d{1,3})$");
6721
6722
6723
6724
6725 private static Pattern datePattern_dd_mon_yyyy_hhmmss_SSS = Pattern.compile("^(\\d{1,2})[^\\d]+([a-zA-Z]{3,15})[^\\d]+(\\d{4})[^\\d]+(\\d{1,2})[^\\d]+(\\d{1,2})[^\\d]+(\\d{1,2})[^\\d]+(\\d{1,3})$");
6726
6727
6728
6729
6730
6731
6732
6733
6734
6735
6736
6737
6738
6739 public static Date stringToDate2(String input) {
6740
6741 if (isBlank(input)) {
6742 return null;
6743 }
6744 input = input.trim();
6745 Matcher matcher = null;
6746
6747 int month = 0;
6748 int day = 0;
6749 int year = 0;
6750 int hour = 0;
6751 int minute = 0;
6752 int second = 0;
6753 int milli = 0;
6754
6755 boolean foundMatch = false;
6756
6757
6758 if (!foundMatch) {
6759 matcher = datePattern_yyyy_mm_dd.matcher(input);
6760 if (matcher.matches()) {
6761 year = intValue(matcher.group(1));
6762 month = intValue(matcher.group(2));
6763 day = intValue(matcher.group(3));
6764 foundMatch = true;
6765 }
6766 }
6767
6768
6769 if (!foundMatch) {
6770 matcher = datePattern_dd_mon_yyyy.matcher(input);
6771 if (matcher.matches()) {
6772 day = intValue(matcher.group(1));
6773 month = monthInt(matcher.group(2));
6774 year = intValue(matcher.group(3));
6775 foundMatch = true;
6776 }
6777 }
6778
6779
6780 if (!foundMatch) {
6781 matcher = datePattern_yyyy_mm_dd_hhmmss.matcher(input);
6782 if (matcher.matches()) {
6783 year = intValue(matcher.group(1));
6784 month = intValue(matcher.group(2));
6785 day = intValue(matcher.group(3));
6786 hour = intValue(matcher.group(4));
6787 minute = intValue(matcher.group(5));
6788 second = intValue(matcher.group(6));
6789 foundMatch = true;
6790 }
6791 }
6792
6793
6794 if (!foundMatch) {
6795 matcher = datePattern_dd_mon_yyyy_hhmmss.matcher(input);
6796 if (matcher.matches()) {
6797 day = intValue(matcher.group(1));
6798 month = monthInt(matcher.group(2));
6799 year = intValue(matcher.group(3));
6800 hour = intValue(matcher.group(4));
6801 minute = intValue(matcher.group(5));
6802 second = intValue(matcher.group(6));
6803 foundMatch = true;
6804 }
6805 }
6806
6807
6808 if (!foundMatch) {
6809 matcher = datePattern_yyyy_mm_dd_hhmmss_SSS.matcher(input);
6810 if (matcher.matches()) {
6811 year = intValue(matcher.group(1));
6812 month = intValue(matcher.group(2));
6813 day = intValue(matcher.group(3));
6814 hour = intValue(matcher.group(4));
6815 minute = intValue(matcher.group(5));
6816 second = intValue(matcher.group(6));
6817 milli = intValue(matcher.group(7));
6818 foundMatch = true;
6819 }
6820 }
6821
6822
6823 if (!foundMatch) {
6824 matcher = datePattern_dd_mon_yyyy_hhmmss_SSS.matcher(input);
6825 if (matcher.matches()) {
6826 day = intValue(matcher.group(1));
6827 month = monthInt(matcher.group(2));
6828 year = intValue(matcher.group(3));
6829 hour = intValue(matcher.group(4));
6830 minute = intValue(matcher.group(5));
6831 second = intValue(matcher.group(6));
6832 milli = intValue(matcher.group(7));
6833 foundMatch = true;
6834 }
6835 }
6836
6837 Calendar calendar = Calendar.getInstance();
6838 calendar.set(Calendar.YEAR, year);
6839 calendar.set(Calendar.MONTH, month-1);
6840 calendar.set(Calendar.DAY_OF_MONTH, day);
6841 calendar.set(Calendar.HOUR_OF_DAY, hour);
6842 calendar.set(Calendar.MINUTE, minute);
6843 calendar.set(Calendar.SECOND, second);
6844 calendar.set(Calendar.MILLISECOND, milli);
6845 return calendar.getTime();
6846 }
6847
6848
6849
6850
6851
6852
6853
6854 public static int monthInt(String mon) {
6855
6856 if (!isBlank(mon)) {
6857 mon = mon.toLowerCase();
6858
6859 if (equals(mon, "jan") || equals(mon, "january")) {
6860 return 1;
6861 }
6862
6863 if (equals(mon, "feb") || equals(mon, "february")) {
6864 return 2;
6865 }
6866
6867 if (equals(mon, "mar") || equals(mon, "march")) {
6868 return 3;
6869 }
6870
6871 if (equals(mon, "apr") || equals(mon, "april")) {
6872 return 4;
6873 }
6874
6875 if (equals(mon, "may")) {
6876 return 5;
6877 }
6878
6879 if (equals(mon, "jun") || equals(mon, "june")) {
6880 return 6;
6881 }
6882
6883 if (equals(mon, "jul") || equals(mon, "july")) {
6884 return 7;
6885 }
6886
6887 if (equals(mon, "aug") || equals(mon, "august")) {
6888 return 8;
6889 }
6890
6891 if (equals(mon, "sep") || equals(mon, "september")) {
6892 return 9;
6893 }
6894
6895 if (equals(mon, "oct") || equals(mon, "october")) {
6896 return 10;
6897 }
6898
6899 if (equals(mon, "nov") || equals(mon, "november")) {
6900 return 11;
6901 }
6902
6903 if (equals(mon, "dec") || equals(mon, "december")) {
6904 return 12;
6905 }
6906
6907 }
6908
6909 throw new RuntimeException("Invalid month: " + mon);
6910 }
6911
6912
6913
6914
6915
6916
6917 public static boolean isBlank(Object input) {
6918 if (null == input) {
6919 return true;
6920 }
6921 return (input instanceof String && isBlank((String)input));
6922 }
6923
6924
6925
6926
6927
6928
6929
6930
6931
6932
6933
6934
6935 @SuppressWarnings("unchecked")
6936 public static <T> T typeCast(Object value, Class<T> theClass,
6937 boolean convertNullToDefaultPrimitive, boolean useNewInstanceHooks) {
6938
6939 if (Object.class.equals(theClass)) {
6940 return (T)value;
6941 }
6942
6943 if (value==null) {
6944 if (convertNullToDefaultPrimitive && theClass.isPrimitive()) {
6945 if ( theClass == boolean.class ) {
6946 return (T)Boolean.FALSE;
6947 }
6948 if ( theClass == char.class ) {
6949 return (T)(Object)0;
6950 }
6951
6952 return typeCast(0, theClass, false, false);
6953 }
6954 return null;
6955 }
6956
6957 if (theClass.isInstance(value)) {
6958 return (T)value;
6959 }
6960
6961
6962 if (theClass.isArray() && theClass.getComponentType() != null) {
6963 theClass = (Class<T>)theClass.getComponentType();
6964 }
6965 Object resultValue = null;
6966
6967 if (theClass.equals(Date.class)) {
6968 resultValue = dateValue(value);
6969 } else if (theClass.equals(String.class)) {
6970 resultValue = stringValue(value);
6971 } else if (theClass.equals(Timestamp.class)) {
6972 resultValue = toTimestamp(value);
6973 } else if (theClass.equals(Boolean.class) || theClass.equals(boolean.class)) {
6974 resultValue = booleanObjectValue(value);
6975 } else if (theClass.equals(Integer.class) || theClass.equals(int.class)) {
6976 resultValue = intObjectValue(value, true);
6977 } else if (theClass.equals(Double.class) || theClass.equals(double.class)) {
6978 resultValue = doubleObjectValue(value, true);
6979 } else if (theClass.equals(Float.class) || theClass.equals(float.class)) {
6980 resultValue = floatObjectValue(value, true);
6981 } else if (theClass.equals(Long.class) || theClass.equals(long.class)) {
6982 resultValue = longObjectValue(value, true);
6983 } else if (theClass.equals(Byte.class) || theClass.equals(byte.class)) {
6984 resultValue = byteObjectValue(value);
6985 } else if (theClass.equals(Character.class) || theClass.equals(char.class)) {
6986 resultValue = charObjectValue(value);
6987 } else if (theClass.equals(Short.class) || theClass.equals(short.class)) {
6988 resultValue = shortObjectValue(value);
6989 } else if ( theClass.isEnum() && (value instanceof String) ) {
6990 resultValue = Enum.valueOf((Class)theClass, (String) value);
6991 } else if ( theClass.equals(Class.class) && (value instanceof String) ) {
6992 resultValue = forName((String)value);
6993 } else if (useNewInstanceHooks && value instanceof String) {
6994 String stringValue = (String)value;
6995 if ( equals("null", stringValue)) {
6996 resultValue = null;
6997 } else if (equals("newInstance", stringValue)) {
6998 resultValue = newInstance(theClass);
6999 } else {
7000
7001 try {
7002 Constructor constructor = theClass.getConstructor(new Class[] {String.class} );
7003 resultValue = constructor.newInstance(new Object[] {stringValue} );
7004 } catch (Exception e) {
7005 throw new RuntimeException("Cant find constructor with string for class: " + theClass);
7006 }
7007 }
7008 } else {
7009 throw new RuntimeException("Cannot convert from type: " + value.getClass() + " to type: " + theClass);
7010 }
7011
7012 return (T)resultValue;
7013 }
7014
7015
7016
7017
7018
7019
7020 public static boolean isScalar(Class<?> type) {
7021
7022 if (type.isArray()) {
7023 return false;
7024 }
7025
7026
7027 if (type.isPrimitive()) {
7028 return true;
7029 }
7030
7031 if (Number.class.isAssignableFrom(type)) {
7032 return true;
7033 }
7034
7035 if (Date.class.isAssignableFrom(type)) {
7036 return true;
7037 }
7038 if (Character.class.equals(type)) {
7039 return true;
7040 }
7041
7042 if (CharSequence.class.equals(type) || CharSequence.class.isAssignableFrom(type)) {
7043 return true;
7044 }
7045 if (Class.class == type || Boolean.class == type || type.isEnum()) {
7046 return true;
7047 }
7048
7049 return false;
7050 }
7051
7052
7053
7054
7055
7056
7057
7058
7059
7060
7061
7062
7063
7064
7065
7066
7067
7068
7069
7070
7071
7072 public static Timestamp toTimestamp(Object input) {
7073
7074 if (null == input) {
7075 return null;
7076 } else if (input instanceof java.sql.Timestamp) {
7077 return (Timestamp) input;
7078 } else if (input instanceof Long) {
7079 return new Timestamp((Long)input);
7080 } else if (input instanceof String) {
7081 return stringToTimestamp((String) input);
7082 } else if (input instanceof Date) {
7083 return new Timestamp(((Date)input).getTime());
7084 } else if (input instanceof java.sql.Date) {
7085 return new Timestamp(((java.sql.Date)input).getTime());
7086 } else {
7087 throw new RuntimeException("Cannot convert Object to timestamp : " + input);
7088 }
7089
7090 }
7091
7092
7093
7094
7095
7096
7097
7098
7099
7100 public static String stringValue(Object input) {
7101
7102 if (input == null || input instanceof String) {
7103 return (String) input;
7104 }
7105
7106 if (input instanceof Timestamp) {
7107
7108 return timestampToString((Timestamp) input);
7109 }
7110
7111 if (input instanceof Date) {
7112
7113 return stringValue((Date) input);
7114 }
7115
7116 if (input instanceof Integer || input instanceof Long) {
7117 return input.toString();
7118 }
7119 if (input instanceof Number) {
7120 DecimalFormat decimalFormat = new DecimalFormat(
7121 "###################.###############");
7122 return decimalFormat.format(((Number) input).doubleValue());
7123
7124 }
7125
7126 return input.toString();
7127 }
7128
7129
7130
7131
7132
7133
7134 public synchronized static String timestampToString(Date timestamp) {
7135 if (timestamp == null) {
7136 return null;
7137 }
7138 return timestampFormat.format(timestamp);
7139 }
7140
7141
7142
7143
7144
7145
7146 public synchronized static String timestampToFileString(Date timestamp) {
7147 if (timestamp == null) {
7148 return null;
7149 }
7150 return timestampFileFormat.format(timestamp);
7151 }
7152
7153
7154
7155
7156
7157
7158 synchronized static SimpleDateFormat dateFormat() {
7159 return dateFormat;
7160 }
7161
7162
7163
7164
7165
7166
7167 synchronized static SimpleDateFormat dateFormat2() {
7168 return dateFormat2;
7169 }
7170
7171
7172
7173
7174
7175
7176 public static String stringValue(java.util.Date date) {
7177 synchronized (GrouperUtil.class) {
7178 if (date == null) {
7179 return null;
7180 }
7181
7182 String theString = dateFormat().format(date);
7183
7184 return theString;
7185 }
7186 }
7187
7188
7189
7190
7191
7192
7193
7194
7195
7196
7197
7198
7199 public static Timestamp stringToTimestamp(String input) {
7200 Date date = stringToTimestampHelper(input);
7201 if (date == null) {
7202 return null;
7203 }
7204
7205 if (date instanceof Timestamp) {
7206 return (Timestamp)date;
7207 }
7208 return new Timestamp(date.getTime());
7209 }
7210
7211
7212
7213
7214
7215
7216
7217
7218
7219
7220
7221
7222
7223 synchronized static Date stringToTimestampHelper(String input) {
7224
7225 if (isBlank(input)) {
7226 return null;
7227 }
7228 input = input.trim();
7229 try {
7230
7231 if (equals("99999999", input)
7232 || equals("999999", input)) {
7233 input = "20991231";
7234 }
7235 if (input.length() == 8) {
7236
7237 return dateFormat().parse(input);
7238 }
7239 if (input.length() == 10) {
7240
7241 return dateFormat2().parse(input);
7242 }
7243 if (!contains(input, '.')) {
7244 if (contains(input, '/')) {
7245 return dateMinutesSecondsFormat.parse(input);
7246 }
7247
7248 return dateMinutesSecondsNoSlashFormat.parse(input);
7249 }
7250 if (contains(input, '/')) {
7251
7252 int lastDotIndex = input.lastIndexOf('.');
7253 if (lastDotIndex == input.length() - 7) {
7254 String nonNanoInput = input.substring(0,input.length()-3);
7255 Date date = timestampFormat.parse(nonNanoInput);
7256
7257 String lastThree = input.substring(input.length()-3,input.length());
7258 int lastThreeInt = Integer.parseInt(lastThree);
7259 Timestamp timestamp = new Timestamp(date.getTime());
7260 timestamp.setNanos(timestamp.getNanos() + (lastThreeInt * 1000));
7261 return timestamp;
7262 }
7263 return timestampFormat.parse(input);
7264 }
7265
7266 return timestampNoSlashFormat.parse(input);
7267 } catch (ParseException pe) {
7268 throw new RuntimeException(errorStart + input);
7269 }
7270 }
7271
7272
7273
7274
7275 private static final String errorStart = "Invalid timestamp, please use any of the formats: "
7276 + DATE_FORMAT + ", " + TIMESTAMP_FORMAT
7277 + ", " + DATE_MINUTES_SECONDS_FORMAT + ": ";
7278
7279
7280
7281
7282
7283
7284 public static BigDecimal bigDecimalObjectValue(Object input) {
7285 if (input instanceof BigDecimal) {
7286 return (BigDecimal)input;
7287 }
7288 if (isBlank(input)) {
7289 return null;
7290 }
7291 return BigDecimal.valueOf(doubleValue(input));
7292 }
7293
7294
7295
7296
7297
7298
7299 public static Byte byteObjectValue(Object input) {
7300 if (input instanceof Byte) {
7301 return (Byte)input;
7302 }
7303 if (isBlank(input)) {
7304 return null;
7305 }
7306 return Byte.valueOf(byteValue(input));
7307 }
7308
7309
7310
7311
7312
7313
7314 public static byte byteValue(Object input) {
7315 if (input instanceof String) {
7316 String string = (String)input;
7317 return Byte.parseByte(string);
7318 }
7319 if (input instanceof Number) {
7320 return ((Number)input).byteValue();
7321 }
7322 throw new RuntimeException("Cannot convert to byte: " + className(input));
7323 }
7324
7325
7326
7327
7328
7329
7330
7331
7332
7333
7334 public static Double doubleObjectValue(Object input, boolean allowNullBlank) {
7335
7336 if (input instanceof Double) {
7337 return (Double) input;
7338 }
7339
7340 if (allowNullBlank && isBlank(input)) {
7341 return null;
7342 }
7343
7344 return Double.valueOf(doubleValue(input));
7345 }
7346
7347
7348
7349
7350
7351
7352
7353
7354
7355 public static double doubleValue(Object input) {
7356 if (input instanceof String) {
7357 String string = (String)input;
7358 return Double.parseDouble(string);
7359 }
7360 if (input instanceof Number) {
7361 return ((Number)input).doubleValue();
7362 }
7363 throw new RuntimeException("Cannot convert to double: " + className(input));
7364 }
7365
7366
7367
7368
7369
7370
7371
7372
7373
7374
7375
7376 public static double doubleValueNoError(Object input) {
7377 if (input == null || (input instanceof String
7378 && isBlank((String)input))) {
7379 return NOT_FOUND;
7380 }
7381
7382 try {
7383 return doubleValue(input);
7384 } catch (Exception e) {
7385
7386 }
7387
7388 return NOT_FOUND;
7389 }
7390
7391
7392
7393
7394
7395
7396
7397
7398
7399
7400 public static Float floatObjectValue(Object input, boolean allowNullBlank) {
7401
7402 if (input instanceof Float) {
7403 return (Float) input;
7404 }
7405
7406 if (allowNullBlank && isBlank(input)) {
7407 return null;
7408 }
7409 return Float.valueOf(floatValue(input));
7410 }
7411
7412
7413
7414
7415
7416
7417
7418
7419
7420 public static float floatValue(Object input) {
7421 if (input instanceof String) {
7422 String string = (String)input;
7423 return Float.parseFloat(string);
7424 }
7425 if (input instanceof Number) {
7426 return ((Number)input).floatValue();
7427 }
7428 throw new RuntimeException("Cannot convert to float: " + className(input));
7429 }
7430
7431
7432
7433
7434
7435
7436
7437
7438
7439
7440 public static float floatValueNoError(Object input) {
7441 if (input == null || (input instanceof String
7442 && isBlank((String)input))) {
7443 return NOT_FOUND;
7444 }
7445 try {
7446 return floatValue(input);
7447 } catch (Exception e) {
7448 LOG.error(e);
7449 }
7450
7451 return NOT_FOUND;
7452 }
7453
7454
7455
7456
7457
7458
7459
7460
7461
7462
7463 public static Integer intObjectValue(Object input, boolean allowNullBlank) {
7464
7465 if (input instanceof Integer) {
7466 return (Integer) input;
7467 }
7468
7469 if (allowNullBlank && isBlank(input)) {
7470 return null;
7471 }
7472
7473 return Integer.valueOf(intValue(input));
7474 }
7475
7476
7477
7478
7479
7480
7481 public static int intValue(Object input) {
7482 if (input instanceof String) {
7483 String string = (String)input;
7484 return Integer.parseInt(string);
7485 }
7486 if (input instanceof Number) {
7487 return ((Number)input).intValue();
7488 }
7489 throw new RuntimeException("Cannot convert to int: " + className(input));
7490 }
7491
7492
7493
7494
7495
7496
7497
7498 public static int intValue(Object input, int valueIfNull) {
7499 if (input == null || "".equals(input)) {
7500 return valueIfNull;
7501 }
7502 return intObjectValue(input, false);
7503 }
7504
7505
7506
7507
7508
7509 public static Set<String> stemCalculateTopLevelStems(Set<String> stems) {
7510
7511 Set<String> topLevelStems = new TreeSet<String>();
7512
7513 if (GrouperUtil.isBlank(stems)) {
7514 return topLevelStems;
7515 }
7516
7517
7518 if (stems.contains(":")) {
7519 topLevelStems.add(":");
7520 return topLevelStems;
7521 }
7522
7523
7524
7525 SYNC_STEMS:
7526 for (String stem : stems) {
7527
7528
7529 CURRENT_STEM_PARENT_STEM:
7530 for (String parentStem : GrouperUtil.findParentStemNames(stem)) {
7531 if (StringUtils.equals(":", parentStem) || StringUtils.isBlank(parentStem)) {
7532 continue CURRENT_STEM_PARENT_STEM;
7533 }
7534
7535 if (topLevelStems.contains(parentStem)) {
7536 continue SYNC_STEMS;
7537 }
7538
7539 }
7540
7541
7542 Iterator<String> iterator = topLevelStems.iterator();
7543
7544 String syncFolderToAddWithColon = stem + ":";
7545
7546 while (iterator.hasNext()) {
7547 String currentTopLevelStemToSync = iterator.next();
7548 if (currentTopLevelStemToSync.startsWith(syncFolderToAddWithColon)) {
7549 iterator.remove();
7550 }
7551 }
7552
7553
7554 topLevelStems.add(stem);
7555
7556 }
7557 return topLevelStems;
7558 }
7559
7560
7561
7562
7563
7564 public static void stemRemoveChildStemsOfTopStem(List<Stem> stems) {
7565
7566 if (stems == null) {
7567 return;
7568 }
7569
7570 int stemSize = stems.size();
7571
7572
7573
7574
7575 int numberOfStems = -1;
7576 int indexOfHighestStem = -1;
7577
7578 for (int i=0;i<stemSize;i++) {
7579
7580 Stem currentStem = stems.get(i);
7581
7582 int currentNumberOfStems = currentStem.isRootStem() ? 0 : (StringUtils.countMatches(currentStem.getName(), ":") + 1);
7583
7584 if (numberOfStems == -1 || currentNumberOfStems < numberOfStems) {
7585 numberOfStems = currentNumberOfStems;
7586 indexOfHighestStem = i;
7587 }
7588 }
7589
7590 Stem highestStem = stems.get(indexOfHighestStem);
7591
7592 String highestStemPrefix = highestStem.isRootStem() ? ":" : (highestStem.getName() + ":");
7593
7594 Iterator<Stem> iterator = stems.iterator();
7595 while (iterator.hasNext()) {
7596 Stem currentStem = iterator.next();
7597
7598 if (currentStem.equals(highestStem)) {
7599 continue;
7600 }
7601
7602 if (highestStem.isRootStem() || currentStem.getName().startsWith(highestStemPrefix)) {
7603 iterator.remove();
7604 }
7605 }
7606 }
7607
7608
7609
7610
7611
7612 public static void stemRemoveAncestorStemsOfChildStem(Collection<String> stemNames) {
7613
7614 if (stemNames == null) {
7615 return;
7616 }
7617
7618 Iterator<String> iterator = stemNames.iterator();
7619 while (iterator.hasNext()) {
7620 String currentStemName = iterator.next();
7621
7622 if (currentStemName.equals(":") && stemNames.size() > 1) {
7623 iterator.remove();
7624 } else {
7625 String stemSub = currentStemName + ":";
7626 for (String stemName: stemNames) {
7627
7628 if (stemName.startsWith(stemSub)) {
7629 iterator.remove();
7630 break;
7631 }
7632
7633 }
7634 }
7635 }
7636 }
7637
7638
7639
7640
7641
7642 public static void stemRemoveChildStemsOfTopStemName(Collection<String> stemNames) {
7643
7644 if (stemNames == null) {
7645 return;
7646 }
7647
7648 Iterator<String> iterator = stemNames.iterator();
7649 while (iterator.hasNext()) {
7650 String currentStemName = iterator.next();
7651
7652 if (currentStemName.equals(":") && stemNames.size() > 1) {
7653 continue;
7654 } else {
7655 for (String stemName: stemNames) {
7656 if (stemName.equals(":")) {
7657 iterator.remove();
7658 break;
7659 } else {
7660 String stemSub = stemName + ":";
7661 if (currentStemName.startsWith(stemSub)) {
7662 iterator.remove();
7663 break;
7664 }
7665 }
7666
7667 }
7668 }
7669 }
7670 }
7671
7672
7673
7674
7675
7676
7677
7678
7679
7680
7681 public static int intValueNoError(Object input) {
7682 if (input == null || (input instanceof String
7683 && isBlank((String)input))) {
7684 return NOT_FOUND;
7685 }
7686 try {
7687 return intValue(input);
7688 } catch (Exception e) {
7689
7690 }
7691
7692 return NOT_FOUND;
7693 }
7694
7695
7696 public static final int NOT_FOUND = -999999999;
7697
7698
7699
7700
7701 private static final Log LOG = getLog(GrouperUtil.class);
7702
7703
7704
7705
7706 public static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
7707
7708
7709
7710
7711
7712
7713
7714
7715
7716
7717 public static Long longObjectValue(Object input, boolean allowNullBlank) {
7718
7719 if (input instanceof Long) {
7720 return (Long) input;
7721 }
7722
7723 if (allowNullBlank && isBlank(input)) {
7724 return null;
7725 }
7726
7727 return Long.valueOf(longValue(input));
7728 }
7729
7730
7731
7732
7733
7734
7735
7736
7737
7738
7739 public static Timestamp timestampObjectValue(Object input, boolean allowNullBlank) {
7740
7741 if (input instanceof Timestamp) {
7742 return (Timestamp) input;
7743 }
7744
7745 if (input instanceof Long) {
7746 return new Timestamp((Long)input);
7747 }
7748
7749 if (input instanceof Date) {
7750 return new Timestamp(((Date)input).getTime());
7751 }
7752
7753 if (input instanceof String) {
7754 try {
7755 Date date = timestampFormat.parse((String)input);
7756 return new Timestamp(date.getTime());
7757 } catch (Exception e) {
7758 throw new RuntimeException("Invalid timestamp '" + input + "', expecting: " + TIMESTAMP_FORMAT);
7759 }
7760 }
7761
7762 if (allowNullBlank && isBlank(input)) {
7763 return null;
7764 }
7765
7766 throw new RuntimeException("Invalid timestamp: '" + input + "'");
7767 }
7768
7769
7770
7771
7772
7773
7774 public static long longValue(Object input) {
7775 if (input instanceof String) {
7776 String string = (String)input;
7777 return Long.parseLong(string);
7778 }
7779 if (input instanceof Number) {
7780 return ((Number)input).longValue();
7781 }
7782 if (input instanceof Timestamp) {
7783 return ((Timestamp)input).getTime();
7784 }
7785 throw new RuntimeException("Cannot convert to long: " + className(input));
7786 }
7787
7788
7789
7790
7791
7792
7793
7794 public static long longValue(Object input, long valueIfNull) {
7795 if (input == null || "".equals(input)) {
7796 return valueIfNull;
7797 }
7798 return longObjectValue(input, false);
7799 }
7800
7801
7802
7803
7804
7805
7806
7807
7808
7809
7810 public static long longValueNoError(Object input) {
7811 if (input == null || (input instanceof String
7812 && isBlank((String)input))) {
7813 return NOT_FOUND;
7814 }
7815 try {
7816 return longValue(input);
7817 } catch (Exception e) {
7818
7819 }
7820
7821 return NOT_FOUND;
7822 }
7823
7824
7825
7826
7827
7828
7829
7830
7831
7832 public static Short shortObjectValue(Object input) {
7833
7834 if (input instanceof Short) {
7835 return (Short) input;
7836 }
7837
7838 if (isBlank(input)) {
7839 return null;
7840 }
7841
7842 return Short.valueOf(shortValue(input));
7843 }
7844
7845
7846
7847
7848
7849
7850 public static short shortValue(Object input) {
7851 if (input instanceof String) {
7852 String string = (String)input;
7853 return Short.parseShort(string);
7854 }
7855 if (input instanceof Number) {
7856 return ((Number)input).shortValue();
7857 }
7858 throw new RuntimeException("Cannot convert to short: " + className(input));
7859 }
7860
7861
7862
7863
7864
7865
7866 public static Character charObjectValue(Object input) {
7867 if (input instanceof Character) {
7868 return (Character) input;
7869 }
7870 if (isBlank(input)) {
7871 return null;
7872 }
7873 return new Character(charValue(input));
7874 }
7875
7876
7877
7878
7879
7880
7881 public static char charValue(Object input) {
7882 if (input instanceof Character) {
7883 return ((Character) input).charValue();
7884 }
7885
7886 if (input instanceof String) {
7887 String inputString = (String) input;
7888 if (inputString.length() == 1) {
7889 return inputString.charAt(0);
7890 }
7891 }
7892 throw new RuntimeException("Cannot convert to char: "
7893 + (input == null ? null : (input.getClass() + ", " + input)));
7894 }
7895
7896
7897
7898
7899
7900 public static void createParentDirectories(File file) {
7901 if (!file.getParentFile().exists()) {
7902 if (!file.getParentFile().mkdirs()) {
7903 throw new RuntimeException("Could not create directory : " + file.getParentFile());
7904 }
7905 }
7906 }
7907
7908
7909
7910
7911
7912
7913
7914
7915
7916 public static void saveStringIntoFile(File file, String contents) {
7917 try {
7918 String encoding = GrouperConfig.retrieveConfig().propertyValueString("grouper.default.fileEncoding", "UTF-8");
7919
7920 writeStringToFile(file, contents, encoding);
7921 } catch (IOException ioe) {
7922 throw new RuntimeException(ioe);
7923 }
7924 }
7925
7926
7927
7928
7929
7930 public static String whitespaceRemove(String input) {
7931 if (input == null) {
7932 return input;
7933 }
7934 return input.replaceAll("\\s","");
7935 }
7936
7937
7938
7939
7940
7941
7942 public static String whitespaceNormalizeNewLines(String input) {
7943 if (StringUtils.isBlank(input)) {
7944 return input;
7945 }
7946 String modifiedInput = input.replaceAll("\r\n", "\n");
7947 modifiedInput = modifiedInput.replaceAll("\r", "\n");
7948 return modifiedInput;
7949 }
7950
7951
7952
7953
7954
7955
7956
7957
7958
7959
7960
7961
7962 public static boolean saveStringIntoFile(File file, String contents,
7963 boolean onlyIfDifferentContents, boolean ignoreWhitespace) {
7964 if (onlyIfDifferentContents && file.exists()) {
7965 String fileContents = readFileIntoString(file);
7966 String compressedContents = contents;
7967 if (ignoreWhitespace) {
7968 compressedContents = replaceWhitespaceWithSpace(compressedContents);
7969 fileContents = replaceWhitespaceWithSpace(fileContents);
7970 }
7971
7972
7973 if (equals(fileContents, compressedContents)) {
7974 return false;
7975 }
7976
7977 }
7978 saveStringIntoFile(file, contents);
7979 return true;
7980 }
7981
7982
7983
7984
7985
7986
7987
7988
7989
7990
7991
7992
7993
7994
7995
7996
7997
7998
7999 public static void writeStringToFile(File file, String data, String encoding)
8000 throws IOException {
8001 OutputStream out = new java.io.FileOutputStream(file);
8002 try {
8003 out.write(data.getBytes(encoding));
8004 } finally {
8005 closeQuietly(out);
8006 }
8007 }
8008
8009
8010
8011
8012
8013
8014
8015 public static String readFileIntoString(File file) {
8016
8017 if (file == null) {
8018 return null;
8019 }
8020 try {
8021 return readFileToString(file, "UTF-8");
8022 } catch (IOException ioe) {
8023 throw new RuntimeException(ioe);
8024 }
8025 }
8026
8027
8028
8029
8030
8031
8032
8033 public static String readResourceIntoString(String resourceName, boolean allowNull) {
8034 if (isBlank(resourceName)) {
8035 if (allowNull) {
8036 return null;
8037 }
8038 throw new RuntimeException("Resource name is blank");
8039 }
8040 URL url = computeUrl(resourceName, allowNull);
8041
8042
8043 if (url == null && allowNull) {
8044 return null;
8045 }
8046
8047 InputStream inputStream = null;
8048 StringWriter stringWriter = new StringWriter();
8049 try {
8050 inputStream = url.openStream();
8051 String encoding = GrouperConfig.retrieveConfig().propertyValueString("grouper.default.fileEncoding", "UTF-8");
8052 copy(inputStream, stringWriter, encoding);
8053 } catch (IOException ioe) {
8054 throw new RuntimeException("Error reading resource: '" + resourceName + "'", ioe);
8055 } finally {
8056 closeQuietly(inputStream);
8057 closeQuietly(stringWriter);
8058 }
8059 return stringWriter.toString();
8060 }
8061
8062
8063
8064
8065
8066
8067
8068
8069
8070
8071
8072
8073
8074
8075
8076
8077 public static String readFileToString(File file, String encoding) throws IOException {
8078 InputStream in = new java.io.FileInputStream(file);
8079 try {
8080 return toString(in, encoding);
8081 } finally {
8082 closeQuietly(in);
8083 }
8084 }
8085
8086
8087
8088
8089
8090
8091 public static String replaceWhitespaceWithSpace(String input) {
8092 if (input == null) {
8093 return input;
8094 }
8095 return input.replaceAll("\\s+", " ");
8096 }
8097
8098
8099
8100
8101
8102
8103 public static void closeQuietly(InputStream input) {
8104 if (input == null) {
8105 return;
8106 }
8107
8108 try {
8109 input.close();
8110 } catch (IOException ioe) {
8111 }
8112 }
8113
8114
8115
8116
8117
8118
8119 public static void closeQuietly(OutputStream output) {
8120 if (output == null) {
8121 return;
8122 }
8123
8124 try {
8125 output.close();
8126 } catch (IOException ioe) {
8127 }
8128 }
8129
8130
8131
8132
8133
8134
8135
8136 public static void closeQuietly(Reader input) {
8137 if (input == null) {
8138 return;
8139 }
8140
8141 try {
8142 input.close();
8143 } catch (IOException ioe) {
8144 }
8145 }
8146
8147
8148
8149
8150
8151 public static void closeQuietly(Writer writer) {
8152 if (writer != null) {
8153 try {
8154 writer.close();
8155 } catch (IOException e) {
8156
8157 }
8158 }
8159 }
8160
8161
8162
8163
8164
8165 public static void closeQuietly(XMLStreamWriter writer) {
8166 if (writer != null) {
8167 try {
8168 writer.close();
8169 } catch (XMLStreamException e) {
8170
8171 }
8172 }
8173 }
8174
8175
8176
8177
8178
8179
8180
8181
8182
8183
8184 public static String toString(InputStream input, String encoding) throws IOException {
8185 StringWriter sw = new StringWriter();
8186 copy(input, sw, encoding);
8187 return sw.toString();
8188 }
8189
8190
8191
8192
8193
8194
8195
8196
8197
8198
8199
8200 public static void copy(InputStream input, Writer output, String encoding)
8201 throws IOException {
8202 InputStreamReader in = new InputStreamReader(input, encoding);
8203 copy(in, output);
8204 }
8205
8206
8207
8208
8209
8210
8211
8212
8213 public static int copy(Reader input, Writer output) throws IOException {
8214 char[] buffer = new char[DEFAULT_BUFFER_SIZE];
8215 int count = 0;
8216 int n = 0;
8217 while (-1 != (n = input.read(buffer))) {
8218 output.write(buffer, 0, n);
8219 count += n;
8220 }
8221 return count;
8222 }
8223
8224
8225
8226
8227
8228 public static void threadJoin(Thread thread) {
8229 if (thread == null) {
8230 return;
8231 }
8232 try {
8233 thread.join();
8234 } catch (InterruptedException ie) {
8235 throw new RuntimeException("Thread interrupted: " + thread.getName(), ie);
8236 }
8237 }
8238
8239
8240
8241
8242
8243
8244 public static void threadJoin(Thread thread, long millis) {
8245 try {
8246 thread.join(millis);
8247 } catch (InterruptedException ie) {
8248 throw new RuntimeException("Thread interrupted: " + thread.getName(), ie);
8249 }
8250 }
8251
8252
8253
8254
8255
8256
8257
8258
8259
8260
8261 public static String convertLongToChar(long theLong) {
8262 if ((theLong < 0) || (theLong >= 62)) {
8263 throw new RuntimeException("convertLongToChar() "
8264 + " invalid input (not >=0 && <62: " + theLong);
8265 } else if (theLong < 26) {
8266 return "" + (char) ('a' + theLong);
8267 } else if (theLong < 52) {
8268 return "" + (char) ('A' + (theLong - 26));
8269 } else {
8270 return "" + (char) ('0' + (theLong - 52));
8271 }
8272 }
8273
8274
8275
8276
8277
8278
8279
8280
8281
8282
8283 public static String convertLongToCharSmall(long theLong) {
8284 if ((theLong < 0) || (theLong >= 36)) {
8285 throw new RuntimeException("convertLongToCharSmall() "
8286 + " invalid input (not >=0 && <36: " + theLong);
8287 } else if (theLong < 26) {
8288 return "" + (char) ('A' + theLong);
8289 } else {
8290 return "" + (char) ('0' + (theLong - 26));
8291 }
8292 }
8293
8294
8295
8296
8297
8298
8299
8300
8301
8302
8303 public static String convertLongToString(long theLong) {
8304 long quotient = theLong / 62;
8305 long remainder = theLong % 62;
8306
8307 if (quotient == 0) {
8308 return convertLongToChar(remainder);
8309 }
8310 StringBuffer result = new StringBuffer();
8311 result.append(convertLongToString(quotient));
8312 result.append(convertLongToChar(remainder));
8313
8314 return result.toString();
8315 }
8316
8317
8318
8319
8320
8321
8322
8323
8324
8325
8326 public static String convertLongToStringSmall(long theLong) {
8327 long quotient = theLong / 36;
8328 long remainder = theLong % 36;
8329
8330 if (quotient == 0) {
8331 return convertLongToCharSmall(remainder);
8332 }
8333 StringBuffer result = new StringBuffer();
8334 result.append(convertLongToStringSmall(quotient));
8335 result.append(convertLongToCharSmall(remainder));
8336
8337 return result.toString();
8338 }
8339
8340
8341
8342
8343
8344
8345
8346
8347 public static char incrementChar(char theChar) {
8348 if (theChar == 'Z') {
8349 return '0';
8350 }
8351
8352 if (theChar == '9') {
8353 return 'A';
8354 }
8355
8356 return ++theChar;
8357 }
8358
8359
8360
8361
8362
8363
8364
8365
8366
8367 public static char[] incrementStringInt(char[] string) {
8368 if (string == null) {
8369 return string;
8370 }
8371
8372
8373 int i = 0;
8374
8375 for (i = string.length - 1; i >= 0; i--) {
8376 char inc = string[i];
8377 inc = incrementChar(inc);
8378 string[i] = inc;
8379
8380 if (inc != 'A') {
8381 break;
8382 }
8383 }
8384
8385
8386 if (i < 0) {
8387 return ("A" + new String(string)).toCharArray();
8388 }
8389
8390 return string;
8391 }
8392
8393
8394
8395
8396
8397
8398 public synchronized static Properties propertiesFromResourceName(String resourceName) {
8399 return propertiesFromResourceName(resourceName, true, true);
8400 }
8401
8402
8403
8404
8405 private static GrouperCache<File, Properties> propertiesFromFileCache = null;
8406
8407
8408
8409
8410 private static Object propertiesFromFileCacheSemaphore = new Object();
8411
8412
8413
8414
8415
8416 private static GrouperCache<File, Properties> propertiesFromFileCache() {
8417 if (propertiesFromFileCache == null) {
8418 synchronized(propertiesFromFileCacheSemaphore) {
8419 if (propertiesFromFileCache == null) {
8420 propertiesFromFileCache = new GrouperCache<File,Properties>(
8421 GrouperUtil.class.getName() + ".propertiesFromFileCache", 200, false, 300, 300, false);
8422 }
8423 }
8424 }
8425 return propertiesFromFileCache;
8426 }
8427
8428
8429
8430
8431 static GrouperCache<String, Properties> propertiesFromUrlCache = null;
8432
8433
8434
8435
8436 private static Object propertiesFromUrlCacheSemaphore = new Object();
8437
8438
8439
8440
8441
8442 private static GrouperCache<String, Properties> propertiesFromUrlCache() {
8443 if (propertiesFromUrlCache == null) {
8444 synchronized(propertiesFromUrlCacheSemaphore) {
8445 if (propertiesFromUrlCache == null) {
8446 propertiesFromUrlCache = new GrouperCache<String,Properties>(
8447 GrouperUtil.class.getName() + ".propertiesFromUrlCache", 200, false, 300, 300, false);
8448 }
8449 }
8450 }
8451 return propertiesFromUrlCache;
8452 }
8453
8454
8455
8456
8457 private static GrouperCache<String, Properties> propertiesFromUrlFailsafeCache = null;
8458
8459
8460
8461
8462 private static Object propertiesFromUrlFailsafeCacheSemaphore = new Object();
8463
8464
8465
8466
8467
8468 private static GrouperCache<String, Properties> propertiesFromUrlFailsafeCache() {
8469 if (propertiesFromUrlFailsafeCache == null) {
8470 synchronized(propertiesFromUrlFailsafeCacheSemaphore) {
8471 if (propertiesFromUrlFailsafeCache == null) {
8472 propertiesFromUrlFailsafeCache = new GrouperCache<String,Properties>(
8473 GrouperUtil.class.getName() + ".propertiesFromUrlFailsafeCache", 200, false, 60*60*24, 60*60*24, false);
8474 }
8475 }
8476 }
8477 return propertiesFromUrlFailsafeCache;
8478 }
8479
8480
8481 static int propertiesFromUrlHttpCount = 0;
8482
8483
8484 static int propertiesFromUrlFailsafeGetCount = 0;
8485
8486
8487 static boolean propertiesFromUrlFailForTest = false;
8488
8489
8490
8491
8492
8493
8494
8495
8496
8497
8498 public static Properties propertiesFromUrl(String urlString, boolean useCache,
8499 boolean useFailSafeCache, GrouperHtmlFilter grouperHtmlFilter) {
8500
8501 Properties properties = null;
8502
8503 if (useCache) {
8504 properties = propertiesFromUrlCache().get(urlString);
8505 if (properties != null) {
8506 if (useFailSafeCache) {
8507
8508 propertiesFromUrlFailsafeCache().put(urlString, properties);
8509 }
8510 return properties;
8511 }
8512 }
8513
8514 InputStream inputStream = null;
8515 try {
8516 if (propertiesFromUrlFailForTest) {
8517
8518 propertiesFromUrlFailForTest=false;
8519 throw new RuntimeException("testing here!!!!");
8520 }
8521 URL url = new URL(urlString);
8522 properties = new Properties();
8523 inputStream = url.openConnection().getInputStream();
8524 properties.load(inputStream);
8525
8526
8527 propertiesFromUrlHttpCount++;
8528
8529 if (grouperHtmlFilter != null) {
8530 for (Object key : properties.keySet()) {
8531 String value = (String)properties.get(key);
8532 String formattedValue = grouperHtmlFilter.filterHtml(value);
8533 properties.put(key, formattedValue);
8534 }
8535 }
8536
8537 } catch (Exception e) {
8538
8539 if (useFailSafeCache) {
8540 properties = propertiesFromUrlFailsafeCache().get(urlString);
8541 }
8542 String error = "Problem with url: " + urlString;
8543
8544 LOG.error(error, e);
8545
8546 error = "Problem with url: " + StringUtils.abbreviate(urlString, 19);
8547
8548 if (!useFailSafeCache || properties == null) {
8549 throw new RuntimeException(error, e);
8550 }
8551
8552 if (useCache) {
8553 propertiesFromUrlCache().put(urlString, properties);
8554 }
8555
8556 propertiesFromUrlFailsafeGetCount++;
8557
8558 return properties;
8559 } finally {
8560 closeQuietly(inputStream);
8561 }
8562
8563
8564 if (useCache) {
8565 propertiesFromUrlCache().put(urlString, properties);
8566 }
8567 if (useFailSafeCache) {
8568
8569 propertiesFromUrlFailsafeCache().put(urlString, properties);
8570 }
8571 return properties;
8572
8573
8574 }
8575
8576
8577
8578
8579
8580
8581
8582 public synchronized static Properties propertiesFromFile(File file, boolean useCache) {
8583 Properties properties = null;
8584 if (useCache) {
8585 properties = propertiesFromFileCache().get(file);
8586 if (properties != null) {
8587 return properties;
8588 }
8589 }
8590
8591 FileInputStream fileInputStream = null;
8592
8593 try {
8594 fileInputStream = new FileInputStream(file);
8595 properties = new Properties();
8596 properties.load(fileInputStream);
8597 } catch (IOException ioe) {
8598 throw new RuntimeException("Problem with file: " + file, ioe);
8599 } finally {
8600
8601 closeQuietly(fileInputStream);
8602
8603 }
8604
8605 if (useCache) {
8606 propertiesFromFileCache().put(file, properties);
8607 }
8608 return properties;
8609 }
8610
8611
8612
8613
8614
8615
8616
8617
8618 public synchronized static Properties propertiesFromResourceName(String resourceName, boolean useCache,
8619 boolean exceptionIfNotExist) {
8620
8621 Properties properties = resourcePropertiesCache() == null ? null : resourcePropertiesCache().get(resourceName);
8622
8623 if (resourcePropertiesCache() == null || !useCache || resourcePropertiesCache().get(resourceName) == null) {
8624
8625 properties = new Properties();
8626
8627 URL url = computeUrl(resourceName, true);
8628 InputStream inputStream = null;
8629 try {
8630 inputStream = url.openStream();
8631 properties.load(inputStream);
8632 } catch (Exception e) {
8633 if (exceptionIfNotExist) {
8634 throw new RuntimeException("Problem with resource: '" + resourceName + "'", e);
8635 }
8636 properties = null;
8637 } finally {
8638 closeQuietly(inputStream);
8639
8640 if (useCache && resourcePropertiesCache() != null) {
8641 resourcePropertiesCache().put(resourceName, properties);
8642 }
8643 }
8644 }
8645
8646 fixHibernateConnectionUrl(properties);
8647
8648 return properties;
8649 }
8650
8651
8652
8653
8654
8655
8656
8657
8658
8659
8660
8661 public static <E extends Enum<?>> E enumValueOfIgnoreCase(Class<E> theEnumClass, String string,
8662 boolean exceptionOnNotFound) throws RuntimeException {
8663 return enumValueOfIgnoreCase(theEnumClass, string, exceptionOnNotFound, true);
8664 }
8665
8666
8667
8668
8669
8670
8671
8672
8673
8674
8675
8676
8677
8678 public static <E extends Enum<?>> E enumValueOfIgnoreCase(Class<E> theEnumClass, String string,
8679 boolean exceptionOnNotFound, boolean exceptionIfInvalid) throws RuntimeException {
8680
8681 if (!exceptionOnNotFound && isBlank(string)) {
8682 return null;
8683 }
8684 for (E e : theEnumClass.getEnumConstants()) {
8685 if (equalsIgnoreCase(string, e.name())) {
8686 return e;
8687 }
8688 }
8689 if (!exceptionIfInvalid) {
8690 return null;
8691 }
8692 StringBuilder error = new StringBuilder(
8693 "Cant find " + theEnumClass.getSimpleName() + " from string: '").append(string);
8694 error.append("', expecting one of: ");
8695 for (E e : theEnumClass.getEnumConstants()) {
8696 error.append(e.name()).append(", ");
8697 }
8698 throw new RuntimeException(error.toString());
8699
8700 }
8701
8702
8703
8704
8705
8706
8707
8708 public static PropertyDescriptor retrievePropertyDescriptor(Object object, String property) {
8709 try {
8710 return PropertyUtils.getPropertyDescriptor(object, property);
8711 } catch (Exception e) {
8712 }
8713 return null;
8714 }
8715
8716
8717
8718
8719
8720
8721
8722 public static Object propertyValue(Object object, String property) {
8723 Method getter = getter(object.getClass(), property, true, true);
8724 Object result = invokeMethod(getter, object);
8725 return result;
8726 }
8727
8728
8729
8730
8731
8732
8733
8734 public static String propertiesValue(Properties properties, String key) {
8735 return propertiesValue(properties, null, key);
8736 }
8737
8738
8739
8740
8741
8742
8743
8744
8745 public static String propertiesValue(Properties properties, Map<String, String> overrideMap, String key) {
8746 return propertiesValue(properties, overrideMap, null, key);
8747 }
8748
8749
8750
8751
8752
8753
8754
8755
8756
8757 public static String propertiesValue(Properties properties, Map<String, String> overrideMap, Map<String, String> overrideMap2, String key) {
8758 String value = overrideMap == null ? null : overrideMap.get(key);
8759 if (isBlank(value)) {
8760 value = overrideMap2 == null ? null : overrideMap2.get(key);
8761 }
8762 if (isBlank(value)) {
8763 value = properties.getProperty(key);
8764 }
8765 return trim(value);
8766 }
8767
8768
8769
8770
8771
8772
8773
8774
8775 public static boolean propertiesValueBoolean(Properties properties,
8776 String propertyName, boolean defaultValue) {
8777 return propertiesValueBoolean(properties, null, propertyName, defaultValue);
8778 }
8779
8780
8781
8782
8783
8784
8785
8786
8787
8788 public static boolean propertiesValueBoolean(Properties properties,
8789 Map<String, String> overrideMap, String propertyName, boolean defaultValue) {
8790 return propertiesValueBoolean(properties, overrideMap, null, propertyName, defaultValue);
8791 }
8792
8793
8794
8795
8796
8797
8798
8799
8800
8801
8802 public static boolean propertiesValueBoolean(Properties properties,
8803 Map<String, String> overrideMap, Map<String, String> overrideMap2, String propertyName, boolean defaultValue) {
8804
8805
8806 String value = propertiesValue(properties, overrideMap, overrideMap2, propertyName);
8807 if (isBlank(value)) {
8808 return defaultValue;
8809 }
8810
8811 if ("true".equalsIgnoreCase(value)) {
8812 return true;
8813 }
8814 if ("false".equalsIgnoreCase(value)) {
8815 return false;
8816 }
8817 if ("t".equalsIgnoreCase(value)) {
8818 return true;
8819 }
8820 if ("f".equalsIgnoreCase(value)) {
8821 return false;
8822 }
8823 throw new RuntimeException("Invalid boolean value: '" + value + "' for property: " + propertyName + " in properties file");
8824
8825 }
8826
8827
8828
8829
8830
8831 public static void closeQuietly(Connection connection) {
8832 if (connection != null) {
8833 try {
8834 connection.close();
8835 } catch (Exception e) {
8836
8837 }
8838 }
8839 }
8840
8841
8842
8843
8844
8845 public static void closeQuietly(Session session) {
8846 if (session != null) {
8847 try {
8848 session.close();
8849 } catch (Exception e) {
8850
8851 }
8852 }
8853 }
8854
8855
8856
8857
8858
8859 public static void closeQuietly(Statement statement) {
8860 if (statement != null) {
8861 try {
8862 statement.close();
8863 } catch (Exception e) {
8864
8865 }
8866 }
8867 }
8868
8869
8870
8871
8872
8873 public static void closeQuietly(ResultSet resultSet) {
8874 if (resultSet != null) {
8875 try {
8876 resultSet.close();
8877 } catch (Exception e) {
8878
8879 }
8880 }
8881 }
8882
8883
8884 private static String hostname = null;
8885
8886
8887
8888
8889
8890 public static String hostname() {
8891
8892 if (isBlank(hostname)) {
8893
8894
8895 hostname = "unknown";
8896 try {
8897 InetAddress addr = InetAddress.getLocalHost();
8898
8899
8900 hostname = addr.getHostName();
8901 } catch (Exception e) {
8902 LOG.error("Cant find servers hostname: ", e);
8903 }
8904 }
8905
8906 return hostname;
8907 }
8908
8909
8910
8911
8912
8913
8914 public static boolean isAscii(char input) {
8915 return input < 128;
8916 }
8917
8918
8919
8920
8921
8922
8923 public static int lengthAscii(String input) {
8924 if (input == null) {
8925 return 0;
8926 }
8927
8928 int utfLength = input.length();
8929
8930 int extras = 0;
8931 for (int i=0;i<utfLength;i++) {
8932
8933 if (!isAscii(input.charAt(i))) {
8934 extras++;
8935 }
8936 }
8937 return utfLength + extras;
8938 }
8939
8940
8941
8942
8943
8944 public static void rollbackQuietly(Transaction transaction) {
8945 if (transaction != null && transaction.getStatus().isOneOf(TransactionStatus.ACTIVE)) {
8946 try {
8947 transaction.rollback();
8948 } catch (Exception e) {
8949
8950 }
8951 }
8952 }
8953
8954
8955
8956
8957
8958 public static void rollbackQuietly(Connection connection) {
8959 if (connection != null) {
8960 try {
8961 connection.rollback();
8962 } catch (Exception e) {
8963
8964 }
8965 }
8966 }
8967
8968
8969
8970
8971
8972
8973 public static int stringLength(String string) {
8974 return string == null ? 0 : string.length();
8975 }
8976
8977
8978
8979
8980
8981 public static void closeQuietly(Closeable closeable) {
8982 if (closeable != null) {
8983 try {
8984 closeable.close();
8985 } catch (IOException e) {
8986
8987 }
8988 }
8989 }
8990
8991
8992
8993
8994
8995
8996 public static boolean fileCreateNewFile(File file) {
8997 if (file.exists() && file.isFile()) {
8998 return false;
8999 }
9000
9001 try {
9002 file.createNewFile();
9003 } catch (IOException ioe) {
9004 throw new RuntimeException("Cant create file: " + file.getAbsolutePath());
9005 }
9006
9007 return true;
9008 }
9009
9010
9011
9012
9013 private static int nonAsciiCharLength = -1;
9014
9015
9016
9017
9018
9019 private static int nonAsciiCharLength() {
9020 if (nonAsciiCharLength == -1) {
9021 nonAsciiCharLength = GrouperConfig.getPropertyInt("grouper.nonAsciiCharDbBytesLength", 3);
9022 }
9023 return nonAsciiCharLength;
9024 }
9025
9026
9027
9028
9029
9030
9031
9032 public static String truncateAscii(String input, int requiredLength) {
9033 if (input == null) {
9034 return input;
9035 }
9036
9037 int utfLength = input.length();
9038
9039
9040 if (utfLength * 2 < requiredLength) {
9041 return input;
9042 }
9043
9044
9045 int asciiLength = 0;
9046 for (int i=0;i<utfLength;i++) {
9047
9048 asciiLength++;
9049
9050
9051 if (!isAscii(input.charAt(i))) {
9052 asciiLength+=(nonAsciiCharLength()-1);
9053 }
9054
9055
9056 if (asciiLength > requiredLength) {
9057
9058 return input.substring(0,i);
9059 }
9060 }
9061
9062 return input;
9063 }
9064
9065
9066
9067
9068
9069
9070 public static String subjectToString(Subject subject) {
9071 if (subject == null) {
9072 return null;
9073 }
9074 try {
9075 if (subject instanceof GrouperSubject) {
9076 return "Subject groupName: " + subject.getName() + ", sourceId: " + subject.getSource().getId();
9077 }
9078 return "Subject id: " + subject.getId() + ", sourceId: " + subject.getSource().getId();
9079 } catch (RuntimeException e) {
9080
9081 return subject.toString();
9082 }
9083 }
9084
9085
9086
9087
9088
9089
9090
9091 public static String readFromFileIfFile(String in, boolean disableExternalFileLookup) {
9092 String theIn = in;
9093
9094 if (File.separatorChar == '/') {
9095 theIn = replace(theIn, "\\", "/");
9096 } else {
9097 theIn = replace(theIn, "/", "\\");
9098 }
9099
9100
9101 if (theIn.indexOf(File.separatorChar) != -1 && disableExternalFileLookup) {
9102
9103 theIn = readFileIntoString(new File(theIn));
9104 return theIn;
9105 }
9106 return in;
9107
9108 }
9109
9110
9111
9112
9113
9114
9115 public static void mkdirs(File dir) {
9116 if (!dir.exists()) {
9117 if (!dir.mkdirs()) {
9118 throw new RuntimeException("Could not create directory : " + dir.getParentFile());
9119 }
9120 return;
9121 }
9122 if (!dir.isDirectory()) {
9123 throw new RuntimeException("Should be a directory but is not: " + dir);
9124 }
9125 }
9126
9127
9128
9129
9130
9131
9132 public static String fixRelativePath(String inPath) {
9133 if(grouperHome==null || inPath.matches("^(/|\\\\|\\w:).*")) {
9134 return inPath;
9135 }
9136 String sep = "";
9137 if(!grouperHome.matches(".*?(\\\\|/)$")) {
9138 sep = File.separator;
9139 }
9140
9141 String outPath=grouperHome + sep + inPath;
9142
9143 return outPath;
9144 }
9145
9146
9147
9148
9149
9150 static void fixHibernateConnectionUrl(Properties props) {
9151 String url = props.getProperty("hibernate.connection.url");
9152 if (isBlank(url)) {
9153 return;
9154 }
9155 if (!url.startsWith("jdbc:hsqldb:")) {
9156 return;
9157 }
9158 if (url.matches("^jdbc:hsqldb:(mem|hsql|res|hsql|hsqls|http|https):.*")) {
9159 return;
9160 }
9161 int spliceAt = 12;
9162 if (url.startsWith("jdbc:hsqldb:file:")) {
9163 spliceAt = 17;
9164 }
9165 String file = url.substring(spliceAt);
9166 String newUrl = url.substring(0, spliceAt) + fixRelativePath(file);
9167 props.setProperty("hibernate.connection.url", newUrl);
9168 }
9169
9170
9171
9172
9173
9174
9175
9176 public static boolean equals(String first, String second) {
9177 if (first == second) {
9178 return true;
9179 }
9180 if (first == null || second == null) {
9181 return false;
9182 }
9183 return first.equals(second);
9184 }
9185
9186
9187
9188
9189
9190
9191
9192
9193
9194
9195
9196
9197
9198
9199
9200
9201 public static boolean isBlank(String str) {
9202 int strLen;
9203 if (str == null || (strLen = str.length()) == 0) {
9204 return true;
9205 }
9206 for (int i = 0; i < strLen; i++) {
9207 if ((Character.isWhitespace(str.charAt(i)) == false)) {
9208 return false;
9209 }
9210 }
9211 return true;
9212 }
9213
9214
9215
9216
9217
9218
9219 public static boolean isNotBlank(String str) {
9220 return !isBlank(str);
9221 }
9222
9223
9224
9225
9226
9227
9228 public static String trim(String str) {
9229 return str == null ? null : str.trim();
9230 }
9231
9232
9233
9234
9235
9236
9237
9238 public static boolean equalsIgnoreCase(String str1, String str2) {
9239 return str1 == null ? str2 == null : str1.equalsIgnoreCase(str2);
9240 }
9241
9242
9243
9244
9245
9246
9247 public static String trimToEmpty(String str) {
9248 return str == null ? "" : str.trim();
9249 }
9250
9251
9252
9253
9254
9255
9256
9257
9258
9259
9260
9261
9262
9263
9264
9265
9266
9267
9268
9269
9270
9271
9272
9273
9274
9275
9276
9277
9278
9279
9280
9281
9282
9283 public static String abbreviate(String str, int maxWidth) {
9284 return abbreviate(str, 0, maxWidth);
9285 }
9286
9287
9288
9289
9290
9291
9292
9293
9294
9295
9296
9297
9298
9299
9300
9301
9302
9303
9304
9305
9306
9307
9308
9309
9310
9311
9312
9313
9314
9315
9316
9317
9318
9319
9320
9321
9322 public static String abbreviate(String str, int offset, int maxWidth) {
9323 if (str == null) {
9324 return null;
9325 }
9326 if (maxWidth < 4) {
9327 throw new IllegalArgumentException("Minimum abbreviation width is 4");
9328 }
9329 if (str.length() <= maxWidth) {
9330 return str;
9331 }
9332 if (offset > str.length()) {
9333 offset = str.length();
9334 }
9335 if ((str.length() - offset) < (maxWidth - 3)) {
9336 offset = str.length() - (maxWidth - 3);
9337 }
9338 if (offset <= 4) {
9339 return str.substring(0, maxWidth - 3) + "...";
9340 }
9341 if (maxWidth < 7) {
9342 throw new IllegalArgumentException("Minimum abbreviation width with offset is 7");
9343 }
9344 if ((offset + (maxWidth - 3)) < str.length()) {
9345 return "..." + abbreviate(str.substring(offset), maxWidth - 3);
9346 }
9347 return "..." + str.substring(str.length() - (maxWidth - 3));
9348 }
9349
9350
9351
9352
9353
9354
9355
9356
9357
9358
9359
9360
9361
9362
9363
9364
9365
9366
9367
9368
9369
9370
9371
9372
9373
9374 public static String[] split(String str) {
9375 return split(str, null, -1);
9376 }
9377
9378
9379
9380
9381
9382
9383
9384
9385
9386
9387
9388
9389
9390
9391
9392
9393
9394
9395
9396
9397
9398
9399
9400
9401
9402
9403
9404 public static String[] split(String str, char separatorChar) {
9405 return splitWorker(str, separatorChar, false);
9406 }
9407
9408
9409
9410
9411
9412
9413
9414
9415
9416
9417
9418
9419
9420
9421
9422
9423
9424
9425
9426
9427
9428
9429
9430
9431
9432
9433 public static String[] split(String str, String separatorChars) {
9434 return splitWorker(str, separatorChars, -1, false);
9435 }
9436
9437
9438
9439
9440
9441
9442
9443
9444
9445
9446
9447
9448
9449
9450
9451
9452
9453
9454
9455
9456
9457
9458
9459
9460
9461
9462
9463
9464
9465
9466
9467 public static String[] split(String str, String separatorChars, int max) {
9468 return splitWorker(str, separatorChars, max, false);
9469 }
9470
9471
9472
9473
9474
9475
9476
9477
9478
9479
9480
9481
9482
9483
9484
9485
9486
9487
9488
9489
9490
9491
9492
9493
9494
9495 public static String[] splitByWholeSeparator(String str, String separator) {
9496 return splitByWholeSeparator(str, separator, -1);
9497 }
9498
9499
9500
9501
9502
9503
9504
9505
9506
9507
9508
9509
9510
9511
9512
9513
9514
9515
9516
9517
9518
9519
9520
9521
9522
9523
9524
9525
9526 public static String[] splitByWholeSeparator(String str, String separator, int max) {
9527 if (str == null) {
9528 return null;
9529 }
9530
9531 int len = str.length();
9532
9533 if (len == 0) {
9534 return EMPTY_STRING_ARRAY;
9535 }
9536
9537 if ((separator == null) || ("".equals(separator))) {
9538
9539 return split(str, null, max);
9540 }
9541
9542 int separatorLength = separator.length();
9543
9544 ArrayList substrings = new ArrayList();
9545 int numberOfSubstrings = 0;
9546 int beg = 0;
9547 int end = 0;
9548 while (end < len) {
9549 end = str.indexOf(separator, beg);
9550
9551 if (end > -1) {
9552 if (end > beg) {
9553 numberOfSubstrings += 1;
9554
9555 if (numberOfSubstrings == max) {
9556 end = len;
9557 substrings.add(str.substring(beg));
9558 } else {
9559
9560
9561 substrings.add(str.substring(beg, end));
9562
9563
9564
9565
9566 beg = end + separatorLength;
9567 }
9568 } else {
9569
9570 beg = end + separatorLength;
9571 }
9572 } else {
9573
9574 substrings.add(str.substring(beg));
9575 end = len;
9576 }
9577 }
9578
9579 return (String[]) substrings.toArray(new String[substrings.size()]);
9580 }
9581
9582
9583
9584
9585
9586
9587
9588
9589
9590
9591
9592
9593
9594
9595
9596
9597
9598
9599
9600
9601
9602
9603
9604
9605
9606
9607 public static String[] splitPreserveAllTokens(String str) {
9608 return splitWorker(str, null, -1, true);
9609 }
9610
9611
9612
9613
9614
9615
9616
9617
9618
9619
9620
9621
9622
9623
9624
9625
9626
9627
9628
9629
9630
9631
9632
9633
9634
9635
9636
9637
9638
9639
9640
9641
9642
9643 public static String[] splitPreserveAllTokens(String str, char separatorChar) {
9644 return splitWorker(str, separatorChar, true);
9645 }
9646
9647
9648
9649
9650
9651
9652
9653
9654
9655
9656
9657
9658
9659 private static String[] splitWorker(String str, char separatorChar,
9660 boolean preserveAllTokens) {
9661
9662
9663 if (str == null) {
9664 return null;
9665 }
9666 int len = str.length();
9667 if (len == 0) {
9668 return EMPTY_STRING_ARRAY;
9669 }
9670 List list = new ArrayList();
9671 int i = 0, start = 0;
9672 boolean match = false;
9673 boolean lastMatch = false;
9674 while (i < len) {
9675 if (str.charAt(i) == separatorChar) {
9676 if (match || preserveAllTokens) {
9677 list.add(str.substring(start, i));
9678 match = false;
9679 lastMatch = true;
9680 }
9681 start = ++i;
9682 continue;
9683 }
9684 lastMatch = false;
9685 match = true;
9686 i++;
9687 }
9688 if (match || (preserveAllTokens && lastMatch)) {
9689 list.add(str.substring(start, i));
9690 }
9691 return (String[]) list.toArray(new String[list.size()]);
9692 }
9693
9694
9695
9696
9697
9698
9699
9700
9701
9702
9703
9704
9705
9706
9707
9708
9709
9710
9711
9712
9713
9714
9715
9716
9717
9718
9719
9720
9721
9722
9723
9724
9725
9726
9727 public static String[] splitPreserveAllTokens(String str, String separatorChars) {
9728 return splitWorker(str, separatorChars, -1, true);
9729 }
9730
9731
9732
9733
9734
9735
9736
9737
9738
9739
9740
9741
9742
9743
9744
9745
9746
9747
9748
9749
9750
9751
9752
9753
9754
9755
9756
9757
9758
9759
9760
9761
9762
9763
9764
9765
9766
9767 public static String[] splitPreserveAllTokens(String str, String separatorChars, int max) {
9768 return splitWorker(str, separatorChars, max, true);
9769 }
9770
9771
9772
9773
9774
9775
9776
9777
9778
9779
9780
9781
9782
9783
9784
9785 private static String[] splitWorker(String str, String separatorChars, int max,
9786 boolean preserveAllTokens) {
9787
9788
9789
9790
9791 if (str == null) {
9792 return null;
9793 }
9794 int len = str.length();
9795 if (len == 0) {
9796 return EMPTY_STRING_ARRAY;
9797 }
9798 List list = new ArrayList();
9799 int sizePlus1 = 1;
9800 int i = 0, start = 0;
9801 boolean match = false;
9802 boolean lastMatch = false;
9803 if (separatorChars == null) {
9804
9805 while (i < len) {
9806 if (Character.isWhitespace(str.charAt(i))) {
9807 if (match || preserveAllTokens) {
9808 lastMatch = true;
9809 if (sizePlus1++ == max) {
9810 i = len;
9811 lastMatch = false;
9812 }
9813 list.add(str.substring(start, i));
9814 match = false;
9815 }
9816 start = ++i;
9817 continue;
9818 }
9819 lastMatch = false;
9820 match = true;
9821 i++;
9822 }
9823 } else if (separatorChars.length() == 1) {
9824
9825 char sep = separatorChars.charAt(0);
9826 while (i < len) {
9827 if (str.charAt(i) == sep) {
9828 if (match || preserveAllTokens) {
9829 lastMatch = true;
9830 if (sizePlus1++ == max) {
9831 i = len;
9832 lastMatch = false;
9833 }
9834 list.add(str.substring(start, i));
9835 match = false;
9836 }
9837 start = ++i;
9838 continue;
9839 }
9840 lastMatch = false;
9841 match = true;
9842 i++;
9843 }
9844 } else {
9845
9846 while (i < len) {
9847 if (separatorChars.indexOf(str.charAt(i)) >= 0) {
9848 if (match || preserveAllTokens) {
9849 lastMatch = true;
9850 if (sizePlus1++ == max) {
9851 i = len;
9852 lastMatch = false;
9853 }
9854 list.add(str.substring(start, i));
9855 match = false;
9856 }
9857 start = ++i;
9858 continue;
9859 }
9860 lastMatch = false;
9861 match = true;
9862 i++;
9863 }
9864 }
9865 if (match || (preserveAllTokens && lastMatch)) {
9866 list.add(str.substring(start, i));
9867 }
9868 return (String[]) list.toArray(new String[list.size()]);
9869 }
9870
9871
9872
9873
9874
9875
9876
9877
9878
9879
9880
9881
9882
9883
9884
9885
9886
9887
9888
9889
9890
9891 public static String join(Object[] array) {
9892 return join(array, null);
9893 }
9894
9895
9896
9897
9898
9899
9900
9901
9902
9903
9904
9905
9906
9907
9908
9909
9910
9911
9912
9913
9914
9915
9916
9917 public static String join(Object[] array, char separator) {
9918 if (array == null) {
9919 return null;
9920 }
9921 int arraySize = array.length;
9922 int bufSize = (arraySize == 0 ? 0 : ((array[0] == null ? 16 : array[0].toString()
9923 .length()) + 1)
9924 * arraySize);
9925 StringBuffer buf = new StringBuffer(bufSize);
9926
9927 for (int i = 0; i < arraySize; i++) {
9928 if (i > 0) {
9929 buf.append(separator);
9930 }
9931 if (array[i] != null) {
9932 buf.append(array[i]);
9933 }
9934 }
9935 return buf.toString();
9936 }
9937
9938
9939
9940
9941
9942
9943
9944
9945
9946
9947
9948
9949
9950
9951
9952
9953
9954
9955
9956
9957
9958
9959
9960
9961 public static String join(Object[] array, String separator) {
9962 if (array == null) {
9963 return null;
9964 }
9965 if (separator == null) {
9966 separator = "";
9967 }
9968 int arraySize = array.length;
9969
9970
9971
9972
9973 int bufSize = ((arraySize == 0) ? 0 : arraySize
9974 * ((array[0] == null ? 16 : array[0].toString().length()) + separator.length()));
9975
9976 StringBuffer buf = new StringBuffer(bufSize);
9977
9978 for (int i = 0; i < arraySize; i++) {
9979 if (i > 0) {
9980 buf.append(separator);
9981 }
9982 if (array[i] != null) {
9983 buf.append(array[i]);
9984 }
9985 }
9986 return buf.toString();
9987 }
9988
9989
9990
9991
9992
9993
9994
9995
9996
9997
9998
9999
10000
10001
10002
10003 public static String join(Iterator iterator, char separator) {
10004 if (iterator == null) {
10005 return null;
10006 }
10007 StringBuffer buf = new StringBuffer(256);
10008 while (iterator.hasNext()) {
10009 Object obj = iterator.next();
10010 if (obj != null) {
10011 buf.append(obj);
10012 }
10013 if (iterator.hasNext()) {
10014 buf.append(separator);
10015 }
10016 }
10017 return buf.toString();
10018 }
10019
10020
10021
10022
10023
10024
10025
10026
10027
10028
10029
10030
10031
10032
10033 public static String join(Iterator iterator, String separator) {
10034 if (iterator == null) {
10035 return null;
10036 }
10037 StringBuffer buf = new StringBuffer(256);
10038 while (iterator.hasNext()) {
10039 Object obj = iterator.next();
10040 if (obj != null) {
10041 buf.append(obj);
10042 }
10043 if ((separator != null) && iterator.hasNext()) {
10044 buf.append(separator);
10045 }
10046 }
10047 return buf.toString();
10048 }
10049
10050
10051
10052
10053
10054
10055
10056
10057
10058
10059
10060
10061
10062
10063
10064
10065 public static String defaultString(String str) {
10066 return str == null ? "" : str;
10067 }
10068
10069
10070
10071
10072
10073
10074
10075
10076
10077
10078
10079
10080
10081
10082
10083
10084
10085 public static String defaultString(String str, String defaultStr) {
10086 return str == null ? defaultStr : str;
10087 }
10088
10089
10090
10091
10092
10093
10094
10095
10096
10097
10098
10099
10100
10101
10102
10103
10104 public static String defaultIfEmpty(String str, String defaultStr) {
10105 return isEmpty(str) ? defaultStr : str;
10106 }
10107
10108
10109
10110
10111
10112
10113
10114
10115
10116
10117
10118
10119
10120
10121
10122
10123
10124
10125 public static String capitalize(String str) {
10126 int strLen;
10127 if (str == null || (strLen = str.length()) == 0) {
10128 return str;
10129 }
10130 return new StringBuffer(strLen).append(Character.toTitleCase(str.charAt(0))).append(
10131 str.substring(1)).toString();
10132 }
10133
10134
10135
10136
10137
10138
10139
10140
10141
10142
10143
10144
10145
10146
10147
10148
10149
10150
10151
10152
10153 public static boolean contains(String str, char searchChar) {
10154 if (isEmpty(str)) {
10155 return false;
10156 }
10157 return str.indexOf(searchChar) >= 0;
10158 }
10159
10160
10161
10162
10163
10164
10165
10166
10167
10168
10169
10170
10171
10172
10173
10174
10175
10176
10177
10178
10179
10180
10181 public static boolean contains(String str, String searchStr) {
10182 if (str == null || searchStr == null) {
10183 return false;
10184 }
10185 return str.indexOf(searchStr) >= 0;
10186 }
10187
10188
10189
10190
10191 public static final String[] EMPTY_STRING_ARRAY = new String[0];
10192
10193
10194
10195
10196
10197
10198
10199
10200
10201
10202
10203
10204
10205
10206
10207
10208
10209
10210
10211
10212 public static boolean equals(Object object1, Object object2) {
10213 if (object1 == object2) {
10214 return true;
10215 }
10216 if ((object1 == null) || (object2 == null)) {
10217 return false;
10218 }
10219 if (object1 instanceof Date && object2 instanceof Date) {
10220 return ((Date)object1).getTime() == ((Date)object2).getTime();
10221 }
10222 return object1.equals(object2);
10223 }
10224
10225
10226
10227
10228
10229
10230
10231 public static boolean equalsSet(Set<?> set1, Set<?> set2) {
10232 if (length(set1) == length(set2) && length(set1) == 0) {
10233 return true;
10234 }
10235 if (set1 == null || set2 == null) {
10236 return false;
10237 }
10238
10239 if (set1.size() != set2.size()) {
10240 return false;
10241 }
10242 Set<?> newSet = new HashSet(set1);
10243 newSet.removeAll(set2);
10244 return newSet.size() == 0;
10245 }
10246
10247
10248
10249
10250
10251
10252
10253 public static boolean equalsList(List<?> list1, List<?> list2) {
10254 if (list1 == list2) {
10255 return true;
10256 }
10257 if (list1 == null || list2 == null) {
10258 return false;
10259 }
10260 if (list1.size() != list2.size()) {
10261 return false;
10262 }
10263 for (int i = 0; i < list1.size(); ++i) {
10264 if (!equals(list1.get(i), list2.get(i))) {
10265 return false;
10266 }
10267 }
10268
10269 return true;
10270 }
10271
10272
10273
10274
10275
10276
10277
10278
10279 public static String getFullStackTrace(Throwable throwable) {
10280 StringWriter sw = new StringWriter();
10281 PrintWriter pw = new PrintWriter(sw, true);
10282 Throwable[] ts = getThrowables(throwable);
10283 for (int i = 0; i < ts.length; i++) {
10284 ts[i].printStackTrace(pw);
10285 if (isNestedThrowable(ts[i])) {
10286 break;
10287 }
10288 }
10289 return sw.getBuffer().toString();
10290 }
10291
10292
10293 private static Map<String, Boolean> jexlKnowsIfClass = new HashMap<String, Boolean>();
10294
10295
10296 private static Map<String, Class<?>> jexlClass = new HashMap<String, Class<?>>();
10297
10298
10299 private static Pattern jexlClassPattern = Pattern.compile("^[a-zA-Z0-9_.]*\\.[A-Z][a-zA-Z0-9_]*$");
10300
10301
10302
10303
10304 private static class GrouperMapContext extends MapContext {
10305
10306
10307
10308
10309
10310
10311 private static Object retrieveClass(String name) {
10312 if (isBlank(name)) {
10313 return null;
10314 }
10315
10316
10317
10318 Boolean knowsIfClass = jexlKnowsIfClass.get(name);
10319
10320
10321 if (knowsIfClass != null) {
10322
10323 return jexlClass.get(name);
10324 }
10325
10326
10327 if (jexlClassPattern.matcher(name).matches()) {
10328
10329 jexlKnowsIfClass.put(name, true);
10330
10331 try {
10332 Class<?> theClass = Class.forName(name);
10333 jexlClass.put(name, theClass);
10334 return theClass;
10335 } catch (Exception e) {
10336 LOG.info("Cant load what looks like class: " + name, e);
10337
10338 }
10339 }
10340 return null;
10341
10342 }
10343
10344
10345
10346
10347 @Override
10348 public Object get(String name) {
10349
10350
10351 Object object = super.get(name);
10352
10353 if (object != null) {
10354 return object;
10355 }
10356 return retrieveClass(name);
10357 }
10358
10359
10360
10361
10362 @Override
10363 public boolean has(String name) {
10364 boolean superHas = super.has(name);
10365 if (superHas) {
10366 return true;
10367 }
10368
10369 return retrieveClass(name) != null;
10370
10371 }
10372
10373 }
10374
10375
10376
10377
10378 private static class GrouperMapContext3 extends org.apache.commons.jexl3.MapContext {
10379
10380
10381
10382
10383
10384
10385 private static Object retrieveClass(String name) {
10386 if (isBlank(name)) {
10387 return null;
10388 }
10389
10390
10391
10392 Boolean knowsIfClass = jexlKnowsIfClass.get(name);
10393
10394
10395 if (knowsIfClass != null) {
10396
10397 return jexlClass.get(name);
10398 }
10399
10400
10401 if (jexlClassPattern.matcher(name).matches()) {
10402
10403 jexlKnowsIfClass.put(name, true);
10404
10405 try {
10406 Class<?> theClass = Class.forName(name);
10407 jexlClass.put(name, theClass);
10408 return theClass;
10409 } catch (Exception e) {
10410 LOG.info("Cant load what looks like class: " + name, e);
10411
10412 }
10413 }
10414 return null;
10415
10416 }
10417
10418
10419
10420
10421 @Override
10422 public Object get(String name) {
10423
10424
10425 Object object = super.get(name);
10426
10427 if (object != null) {
10428 return object;
10429 }
10430 return retrieveClass(name);
10431 }
10432
10433
10434
10435
10436 @Override
10437 public boolean has(String name) {
10438 boolean superHas = super.has(name);
10439 if (superHas) {
10440 return true;
10441 }
10442
10443 return retrieveClass(name) != null;
10444
10445 }
10446
10447
10448
10449
10450 }
10451
10452
10453
10454
10455
10456
10457
10458 @SuppressWarnings("unchecked")
10459 public static String substituteExpressionLanguage(String stringToParse, Map<String, Object> variableMap) {
10460
10461 return substituteExpressionLanguage(stringToParse, variableMap, false, false);
10462
10463 }
10464
10465
10466
10467
10468
10469
10470
10471
10472 @SuppressWarnings("unchecked")
10473 @Deprecated
10474 public static String substituteExpressionLanguage(String stringToParse,
10475 Map<String, Object> variableMap, boolean allowStaticClasses) {
10476 return substituteExpressionLanguage(stringToParse, variableMap, allowStaticClasses, false);
10477 }
10478
10479
10480
10481
10482
10483
10484
10485
10486
10487 @SuppressWarnings("unchecked")
10488 public static String substituteExpressionLanguage(String stringToParse,
10489 Map<String, Object> variableMap, boolean allowStaticClasses, boolean silent) {
10490 return substituteExpressionLanguage(stringToParse, variableMap, allowStaticClasses, silent, false);
10491 }
10492
10493
10494
10495
10496
10497
10498
10499
10500
10501 private static Pattern scriptPattern = Pattern.compile("\\$\\{(.*?)\\}");
10502
10503
10504
10505
10506
10507
10508
10509
10510
10511
10512
10513 @SuppressWarnings("unchecked")
10514 public static String substituteExpressionLanguage(String stringToParse,
10515 Map<String, Object> variableMap, boolean allowStaticClasses, boolean silent, boolean lenient) {
10516 variableMap = nonNull(variableMap);
10517 substituteExpressionInit();
10518
10519 if (isBlank(stringToParse)) {
10520 return stringToParse;
10521 }
10522 String overallResult = null;
10523 Exception exception = null;
10524 try {
10525 JexlContext jc = allowStaticClasses ? new GrouperMapContext() : new MapContext();
10526
10527 int index = 0;
10528
10529 for (String key: variableMap.keySet()) {
10530 jc.set(key, variableMap.get(key));
10531 }
10532
10533
10534 jc.set("grouperUtil", new GrouperUtilElSafe());
10535
10536
10537
10538 Matcher matcher = scriptPattern.matcher(stringToParse);
10539
10540 StringBuilder result = new StringBuilder();
10541
10542
10543 while(matcher.find()) {
10544 result.append(stringToParse.substring(index, matcher.start()));
10545
10546
10547 String script = matcher.group(1);
10548
10549 index = matcher.end();
10550
10551 if (script.contains("{")) {
10552
10553 int scriptStart = matcher.start(1);
10554 int openCurlyCount = 0;
10555 for (int i=scriptStart; i<stringToParse.length();i++) {
10556 char curChar = stringToParse.charAt(i);
10557 if (curChar == '{') {
10558 openCurlyCount++;
10559 }
10560 if (curChar == '}') {
10561 openCurlyCount--;
10562
10563 if (openCurlyCount <= -1) {
10564 script = stringToParse.substring(scriptStart, i);
10565 index = i+1;
10566 break;
10567 }
10568 }
10569 }
10570 }
10571
10572
10573 Object o = null;
10574
10575
10576
10577
10578
10579
10580
10581
10582
10583
10584
10585
10586
10587
10588
10589
10590
10591 Expression e = jexlEngines.get(new MultiKey(silent, lenient)).createExpression(script);
10592
10593 try {
10594 o = e.evaluate(jc);
10595 } catch (JexlException je) {
10596
10597 if (!lenient && StringUtils.trimToEmpty(je.getMessage()).contains("undefined variable")) {
10598
10599
10600 String message = je.getMessage();
10601
10602 Pattern exceptionPattern = Pattern.compile("^.*undefined variable (.*)");
10603 Matcher exceptionMatcher = exceptionPattern.matcher(message);
10604 if (exceptionMatcher.matches()) {
10605
10606 message = "variable '" + exceptionMatcher.group(1) + "' is not defined in script: '" + script + "'";
10607 }
10608 throw new ExpressionLanguageMissingVariableException(message, je);
10609 }
10610 throw je;
10611 }
10612
10613
10614
10615 if (o == null && lenient) {
10616 o = "";
10617 }
10618
10619 if (o == null) {
10620 LOG.warn("expression returned null: " + script + ", in pattern: '" + stringToParse + "', available variables are: "
10621 + toStringForLog(variableMap.keySet()));
10622 }
10623
10624 if (o instanceof RuntimeException) {
10625 throw (RuntimeException)o;
10626 }
10627
10628 result.append(o);
10629
10630 }
10631
10632 result.append(stringToParse.substring(index, stringToParse.length()));
10633 overallResult = result.toString();
10634 return overallResult;
10635
10636 } catch (HookVeto hv) {
10637 exception = hv;
10638 throw hv;
10639 } catch (Exception e) {
10640 exception = e;
10641 if (e instanceof ExpressionLanguageMissingVariableException) {
10642 throw (ExpressionLanguageMissingVariableException)e;
10643 }
10644 throw new RuntimeException("Error substituting string: '" + stringToParse + "'", e);
10645 } finally {
10646 if (LOG.isDebugEnabled()) {
10647 Set<String> keysSet = new LinkedHashSet<String>(nonNull(variableMap).keySet());
10648 keysSet.add("grouperUtil");
10649 StringBuilder logMessage = new StringBuilder();
10650 logMessage.append("Subsituting EL: '").append(stringToParse).append("', and with env vars: ");
10651 String[] keys = keysSet.toArray(new String[]{});
10652 for (int i=0;i<keys.length;i++) {
10653 logMessage.append(keys[i]);
10654 if (i != keys.length-1) {
10655 logMessage.append(", ");
10656 }
10657 }
10658 logMessage.append(" with result: '" + overallResult + "'");
10659 if (exception != null) {
10660 if (exception instanceof HookVeto) {
10661 logMessage.append(", it was vetoed: " + exception);
10662 } else {
10663 logMessage.append(", and exception: " + exception + ", " + ExceptionUtils.getFullStackTrace(exception));
10664 }
10665 }
10666 LOG.debug(logMessage.toString());
10667 }
10668 }
10669 }
10670
10671
10672
10673
10674
10675
10676
10677
10678
10679
10680
10681 @SuppressWarnings("unchecked")
10682 public static Object substituteExpressionLanguageScript(String script,
10683 Map<String, Object> variableMap, boolean allowStaticClasses, boolean silent, boolean lenient) {
10684 variableMap = nonNull(variableMap);
10685 substituteExpressionInit();
10686
10687 if (isBlank(script)) {
10688 return null;
10689 }
10690 String overallResult = null;
10691 Exception exception = null;
10692 try {
10693 JexlContext jc = allowStaticClasses ? new GrouperMapContext() : new MapContext();
10694
10695 int index = 0;
10696
10697 for (String key: variableMap.keySet()) {
10698 jc.set(key, variableMap.get(key));
10699 }
10700
10701
10702 jc.set("grouperUtil", new GrouperUtilElSafe());
10703
10704
10705 script = script.trim();
10706 if (!script.startsWith("${") || !script.endsWith("}")) {
10707 throw new RuntimeException("Script must be ${script}: '" + script + "'");
10708 }
10709
10710 script = script.substring(2, script.length()-1);
10711
10712 Script e = jexlEngines.get(new MultiKey(silent, lenient)).createScript(script);
10713
10714
10715 Object o = null;
10716
10717 try {
10718 o = e.execute(jc);
10719 } catch (JexlException je) {
10720
10721 if (!lenient && StringUtils.trimToEmpty(je.getMessage()).contains("undefined variable")) {
10722
10723
10724 String message = je.getMessage();
10725
10726 Pattern exceptionPattern = Pattern.compile("^.*undefined variable (.*)");
10727 Matcher exceptionMatcher = exceptionPattern.matcher(message);
10728 if (exceptionMatcher.matches()) {
10729
10730 message = "variable '" + exceptionMatcher.group(1) + "' is not defined in script: '" + script + "'";
10731 }
10732 throw new ExpressionLanguageMissingVariableException(message, je);
10733 }
10734 throw je;
10735 }
10736
10737 if (o instanceof RuntimeException) {
10738 throw (RuntimeException)o;
10739 }
10740
10741 return o;
10742 } catch (HookVeto hv) {
10743 exception = hv;
10744 throw hv;
10745 } catch (Exception e) {
10746 exception = e;
10747 if (e instanceof ExpressionLanguageMissingVariableException) {
10748 throw (ExpressionLanguageMissingVariableException)e;
10749 }
10750 throw new RuntimeException("Error substituting string: '" + script + "'", e);
10751 } finally {
10752 if (LOG.isDebugEnabled()) {
10753 Set<String> keysSet = new LinkedHashSet<String>(nonNull(variableMap).keySet());
10754 keysSet.add("grouperUtil");
10755 StringBuilder logMessage = new StringBuilder();
10756 logMessage.append("Subsituting EL: '").append(script).append("', and with env vars: ");
10757 String[] keys = keysSet.toArray(new String[]{});
10758 for (int i=0;i<keys.length;i++) {
10759 logMessage.append(keys[i]);
10760 if (i != keys.length-1) {
10761 logMessage.append(", ");
10762 }
10763 }
10764 logMessage.append(" with result: '" + overallResult + "'");
10765 if (exception != null) {
10766 if (exception instanceof HookVeto) {
10767 logMessage.append(", it was vetoed: " + exception);
10768 } else {
10769 logMessage.append(", and exception: " + exception + ", " + ExceptionUtils.getFullStackTrace(exception));
10770 }
10771 }
10772 LOG.debug(logMessage.toString());
10773 }
10774 }
10775 }
10776
10777
10778
10779
10780
10781
10782
10783
10784
10785
10786
10787
10788
10789
10790 public static Throwable[] getThrowables(Throwable throwable) {
10791 List list = new ArrayList();
10792 while (throwable != null) {
10793 list.add(throwable);
10794 throwable = getCause(throwable);
10795 }
10796 return (Throwable[]) list.toArray(new Throwable[list.size()]);
10797 }
10798
10799
10800
10801
10802 private static String[] CAUSE_METHOD_NAMES = {
10803 "getCause",
10804 "getNextException",
10805 "getTargetException",
10806 "getException",
10807 "getSourceException",
10808 "getRootCause",
10809 "getCausedByException",
10810 "getNested",
10811 "getLinkedException",
10812 "getNestedException",
10813 "getLinkedCause",
10814 "getThrowable",
10815 };
10816
10817
10818
10819
10820
10821
10822
10823
10824
10825
10826 public static boolean isNestedThrowable(Throwable throwable) {
10827 if (throwable == null) {
10828 return false;
10829 }
10830
10831 if (throwable instanceof Nestable) {
10832 return true;
10833 } else if (throwable instanceof SQLException) {
10834 return true;
10835 } else if (throwable instanceof InvocationTargetException) {
10836 return true;
10837 } else if (isThrowableNested()) {
10838 return true;
10839 }
10840
10841 Class cls = throwable.getClass();
10842 for (int i = 0, isize = CAUSE_METHOD_NAMES.length; i < isize; i++) {
10843 try {
10844 Method method = cls.getMethod(CAUSE_METHOD_NAMES[i], (Class[])null);
10845 if (method != null && Throwable.class.isAssignableFrom(method.getReturnType())) {
10846 return true;
10847 }
10848 } catch (NoSuchMethodException ignored) {
10849 } catch (SecurityException ignored) {
10850 }
10851 }
10852
10853 try {
10854 Field field = cls.getField("detail");
10855 if (field != null) {
10856 return true;
10857 }
10858 } catch (NoSuchFieldException ignored) {
10859 } catch (SecurityException ignored) {
10860 }
10861
10862 return false;
10863 }
10864
10865
10866
10867
10868 private static final Method THROWABLE_CAUSE_METHOD;
10869 static {
10870 Method getCauseMethod;
10871 try {
10872 getCauseMethod = Throwable.class.getMethod("getCause", (Class[])null);
10873 } catch (Exception e) {
10874 getCauseMethod = null;
10875 }
10876 THROWABLE_CAUSE_METHOD = getCauseMethod;
10877 }
10878
10879
10880
10881
10882
10883
10884
10885
10886
10887 public static boolean isThrowableNested() {
10888 return THROWABLE_CAUSE_METHOD != null;
10889 }
10890
10891
10892
10893
10894
10895
10896
10897
10898
10899
10900
10901
10902
10903
10904
10905
10906
10907
10908
10909
10910
10911
10912
10913
10914
10915
10916
10917
10918
10919
10920
10921 public static Throwable getCause(Throwable throwable) {
10922 return getCause(throwable, CAUSE_METHOD_NAMES);
10923 }
10924
10925
10926
10927
10928
10929
10930
10931
10932
10933
10934
10935
10936
10937
10938
10939
10940
10941
10942
10943 public static Throwable getCause(Throwable throwable, String[] methodNames) {
10944 if (throwable == null) {
10945 return null;
10946 }
10947 Throwable cause = getCauseUsingWellKnownTypes(throwable);
10948 if (cause == null) {
10949 if (methodNames == null) {
10950 methodNames = CAUSE_METHOD_NAMES;
10951 }
10952 for (int i = 0; i < methodNames.length; i++) {
10953 String methodName = methodNames[i];
10954 if (methodName != null) {
10955 cause = getCauseUsingMethodName(throwable, methodName);
10956 if (cause != null) {
10957 break;
10958 }
10959 }
10960 }
10961
10962 if (cause == null) {
10963 cause = getCauseUsingFieldName(throwable, "detail");
10964 }
10965 }
10966 return cause;
10967 }
10968
10969
10970
10971
10972
10973
10974
10975
10976 private static Throwable getCauseUsingMethodName(Throwable throwable, String methodName) {
10977 Method method = null;
10978 try {
10979 method = throwable.getClass().getMethod(methodName, (Class[])null);
10980 } catch (NoSuchMethodException ignored) {
10981 } catch (SecurityException ignored) {
10982 }
10983
10984 if (method != null && Throwable.class.isAssignableFrom(method.getReturnType())) {
10985 try {
10986 return (Throwable) method.invoke(throwable, EMPTY_OBJECT_ARRAY);
10987 } catch (IllegalAccessException ignored) {
10988 } catch (IllegalArgumentException ignored) {
10989 } catch (InvocationTargetException ignored) {
10990 }
10991 }
10992 return null;
10993 }
10994
10995
10996
10997
10998
10999
11000
11001
11002 private static Throwable getCauseUsingFieldName(Throwable throwable, String fieldName) {
11003 Field field = null;
11004 try {
11005 field = throwable.getClass().getField(fieldName);
11006 } catch (NoSuchFieldException ignored) {
11007 } catch (SecurityException ignored) {
11008 }
11009
11010 if (field != null && Throwable.class.isAssignableFrom(field.getType())) {
11011 try {
11012 return (Throwable) field.get(throwable);
11013 } catch (IllegalAccessException ignored) {
11014 } catch (IllegalArgumentException ignored) {
11015 }
11016 }
11017 return null;
11018 }
11019
11020
11021
11022
11023
11024
11025
11026
11027
11028
11029
11030 private static Throwable getCauseUsingWellKnownTypes(Throwable throwable) {
11031 if (throwable instanceof Nestable) {
11032 return ((Nestable) throwable).getCause();
11033 } else if (throwable instanceof SQLException) {
11034 return ((SQLException) throwable).getNextException();
11035 } else if (throwable instanceof InvocationTargetException) {
11036 return ((InvocationTargetException) throwable).getTargetException();
11037 } else {
11038 return null;
11039 }
11040 }
11041
11042
11043
11044
11045 public static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
11046
11047
11048
11049
11050
11051
11052
11053
11054
11055
11056
11057
11058
11059
11060
11061
11062 public static void copy(InputStream input, Writer output)
11063 throws IOException {
11064 InputStreamReader in = new InputStreamReader(input);
11065 copy(in, output);
11066 }
11067
11068
11069
11070
11071
11072
11073
11074 public static File jarFile(Class sampleClass, boolean printError) {
11075 try {
11076 CodeSource codeSource = sampleClass.getProtectionDomain().getCodeSource();
11077 if (codeSource != null && codeSource.getLocation() != null) {
11078 return new File(codeSource.getLocation().getFile());
11079 }
11080 String resourcePath = sampleClass.getName();
11081 resourcePath = resourcePath.replace('.', '/') + ".class";
11082 URL url = computeUrl(resourcePath, true);
11083 String urlPath = url.toString();
11084
11085 if (urlPath.startsWith("jar:")) {
11086 urlPath = urlPath.substring(4);
11087 }
11088 if (urlPath.startsWith("file:")) {
11089 urlPath = urlPath.substring(5);
11090 }
11091 urlPath = prefixOrSuffix(urlPath, "!", true);
11092
11093 File file = new File(urlPath);
11094 if (urlPath.endsWith(".jar") && file.exists() && file.isFile()) {
11095 return file;
11096 }
11097 } catch (Exception e) {
11098 if (printError) {
11099 e.printStackTrace();
11100 System.err.println("Cant find jar for class: " + sampleClass + ", " + e.getMessage());
11101 }
11102 }
11103 return null;
11104 }
11105
11106
11107
11108
11109
11110
11111
11112
11113 public static String stripLastSlashIfExists(String input) {
11114 if ((input == null) || (input.length() == 0)) {
11115 return input;
11116 }
11117
11118 char lastChar = input.charAt(input.length() - 1);
11119
11120 if ((lastChar == '\\') || (lastChar == '/')) {
11121 return input.substring(0, input.length() - 1);
11122 }
11123
11124 return input;
11125 }
11126
11127
11128
11129
11130
11131
11132
11133
11134 public static String stripFirstSlashIfExists(String input) {
11135 if ((input == null) || (input.length() == 0)) {
11136 return input;
11137 }
11138
11139 char firstChar = input.charAt(0);
11140
11141 if ((firstChar == '\\') || (firstChar == '/')) {
11142 return input.substring(1, input.length());
11143 }
11144
11145 return input;
11146 }
11147
11148
11149
11150
11151
11152
11153
11154 public static String retrievePasswordFromStdin(boolean dontMask, String prompt) {
11155 String passwordString = null;
11156
11157 if (dontMask) {
11158
11159 System.out.print(prompt);
11160
11161 BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
11162
11163
11164
11165 try {
11166 passwordString = br.readLine();
11167 } catch (IOException ioe) {
11168 System.out.println("IO error! " + getFullStackTrace(ioe));
11169 System.exit(1);
11170 }
11171
11172 } else {
11173 char password[] = null;
11174 try {
11175 password = retrievePasswordFromStdin(System.in, prompt);
11176 } catch (IOException ioe) {
11177 ioe.printStackTrace();
11178 }
11179 passwordString = String.valueOf(password);
11180 }
11181 return passwordString;
11182
11183 }
11184
11185
11186
11187
11188
11189
11190
11191 public static final char[] retrievePasswordFromStdin(InputStream in, String prompt) throws IOException {
11192 MaskingThread maskingthread = new MaskingThread(prompt);
11193
11194 Thread thread = new Thread(maskingthread);
11195 thread.start();
11196
11197 char[] lineBuffer;
11198 char[] buf;
11199
11200 buf = lineBuffer = new char[128];
11201
11202 int room = buf.length;
11203 int offset = 0;
11204 int c;
11205
11206 loop: while (true) {
11207 switch (c = in.read()) {
11208 case -1:
11209 case '\n':
11210 break loop;
11211
11212 case '\r':
11213 int c2 = in.read();
11214 if ((c2 != '\n') && (c2 != -1)) {
11215 if (!(in instanceof PushbackInputStream)) {
11216 in = new PushbackInputStream(in);
11217 }
11218 ((PushbackInputStream) in).unread(c2);
11219 } else {
11220 break loop;
11221 }
11222
11223 default:
11224 if (--room < 0) {
11225 buf = new char[offset + 128];
11226 room = buf.length - offset - 1;
11227 System.arraycopy(lineBuffer, 0, buf, 0, offset);
11228 Arrays.fill(lineBuffer, ' ');
11229 lineBuffer = buf;
11230 }
11231 buf[offset++] = (char) c;
11232 break;
11233 }
11234 }
11235 maskingthread.stopMasking();
11236 if (offset == 0) {
11237 return null;
11238 }
11239 char[] ret = new char[offset];
11240 System.arraycopy(buf, 0, ret, 0, offset);
11241 Arrays.fill(buf, ' ');
11242 return ret;
11243 }
11244
11245
11246
11247
11248 static class MaskingThread extends Thread {
11249
11250
11251 private volatile boolean stop;
11252
11253
11254
11255 private char echochar = ' ';
11256
11257
11258
11259
11260 public MaskingThread(String prompt) {
11261 System.out.print(prompt);
11262 }
11263
11264
11265
11266
11267 @Override
11268 public void run() {
11269
11270 int priority = Thread.currentThread().getPriority();
11271 Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
11272
11273 try {
11274 this.stop = true;
11275 while (this.stop) {
11276 System.out.print("\010" + this.echochar);
11277 try {
11278
11279 Thread.sleep(1);
11280 } catch (InterruptedException iex) {
11281 Thread.currentThread().interrupt();
11282 return;
11283 }
11284 }
11285 } finally {
11286 Thread.currentThread().setPriority(priority);
11287 }
11288 }
11289
11290
11291
11292
11293 public void stopMasking() {
11294 this.stop = false;
11295 }
11296 }
11297
11298
11299
11300
11301
11302
11303
11304 private static class DaemonThreadFactory implements ThreadFactory {
11305
11306
11307
11308
11309 private ThreadFactory threadFactory = Executors.defaultThreadFactory();
11310
11311
11312
11313
11314 @Override
11315 public Thread newThread(Runnable r) {
11316 Thread thread = threadFactory.newThread(r);
11317 thread.setDaemon(true);
11318 return thread;
11319 }
11320
11321 }
11322
11323
11324
11325
11326
11327
11328
11329
11330
11331
11332
11333
11334
11335
11336
11337
11338
11339
11340
11341
11342
11343
11344
11345
11346
11347 public static String stripStart(String str, String stripChars) {
11348 int strLen;
11349 if (str == null || (strLen = str.length()) == 0) {
11350 return str;
11351 }
11352 int start = 0;
11353 if (stripChars == null) {
11354 while ((start != strLen) && Character.isWhitespace(str.charAt(start))) {
11355 start++;
11356 }
11357 } else if (stripChars.length() == 0) {
11358 return str;
11359 } else {
11360 while ((start != strLen) && (stripChars.indexOf(str.charAt(start)) != -1)) {
11361 start++;
11362 }
11363 }
11364 return str.substring(start);
11365 }
11366
11367
11368
11369
11370
11371
11372
11373
11374
11375
11376
11377
11378
11379
11380
11381
11382
11383
11384
11385
11386
11387
11388
11389
11390
11391
11392 @Deprecated
11393 public static String stripEnd(String str, String stripChars) {
11394 int end;
11395 if (str == null || (end = str.length()) == 0) {
11396 return str;
11397 }
11398
11399 if (stripChars == null) {
11400 while ((end != 0) && Character.isWhitespace(str.charAt(end - 1))) {
11401 end--;
11402 }
11403 } else if (stripChars.length() == 0) {
11404 return str;
11405 } else {
11406 while ((end != 0) && (stripChars.indexOf(str.charAt(end - 1)) != -1)) {
11407 end--;
11408 }
11409 }
11410 return str.substring(0, end);
11411 }
11412
11413
11414
11415
11416
11417 public static final String EMPTY = "";
11418
11419
11420
11421
11422
11423 public static final int INDEX_NOT_FOUND = -1;
11424
11425
11426
11427
11428 private static final int PAD_LIMIT = 8192;
11429
11430
11431
11432
11433
11434
11435 private static final String[] PADDING = new String[Character.MAX_VALUE];
11436
11437 static {
11438
11439 PADDING[32] = " ";
11440 }
11441
11442
11443
11444
11445
11446
11447
11448
11449
11450
11451
11452
11453
11454
11455
11456
11457
11458
11459
11460 public static String repeat(String str, int repeat) {
11461
11462
11463 if (str == null) {
11464 return null;
11465 }
11466 if (repeat <= 0) {
11467 return EMPTY;
11468 }
11469 int inputLength = str.length();
11470 if (repeat == 1 || inputLength == 0) {
11471 return str;
11472 }
11473 if (inputLength == 1 && repeat <= PAD_LIMIT) {
11474 return padding(repeat, str.charAt(0));
11475 }
11476
11477 int outputLength = inputLength * repeat;
11478 switch (inputLength) {
11479 case 1:
11480 char ch = str.charAt(0);
11481 char[] output1 = new char[outputLength];
11482 for (int i = repeat - 1; i >= 0; i--) {
11483 output1[i] = ch;
11484 }
11485 return new String(output1);
11486 case 2:
11487 char ch0 = str.charAt(0);
11488 char ch1 = str.charAt(1);
11489 char[] output2 = new char[outputLength];
11490 for (int i = repeat * 2 - 2; i >= 0; i--, i--) {
11491 output2[i] = ch0;
11492 output2[i + 1] = ch1;
11493 }
11494 return new String(output2);
11495 default:
11496 StringBuffer buf = new StringBuffer(outputLength);
11497 for (int i = 0; i < repeat; i++) {
11498 buf.append(str);
11499 }
11500 return buf.toString();
11501 }
11502 }
11503
11504
11505
11506
11507
11508
11509
11510
11511
11512
11513
11514
11515
11516
11517
11518
11519 private static String padding(int repeat, char padChar) {
11520
11521
11522 String pad = PADDING[padChar];
11523 if (pad == null) {
11524 pad = String.valueOf(padChar);
11525 }
11526 while (pad.length() < repeat) {
11527 pad = pad.concat(pad);
11528 }
11529 PADDING[padChar] = pad;
11530 return pad.substring(0, repeat);
11531 }
11532
11533
11534
11535
11536
11537
11538
11539
11540
11541
11542
11543
11544
11545
11546
11547
11548
11549
11550
11551
11552 public static String rightPad(String str, int size) {
11553 return rightPad(str, size, ' ');
11554 }
11555
11556
11557
11558
11559
11560
11561
11562
11563
11564
11565
11566
11567
11568
11569
11570
11571
11572
11573
11574
11575
11576
11577 public static String rightPad(String str, int size, char padChar) {
11578 if (str == null) {
11579 return null;
11580 }
11581 int pads = size - str.length();
11582 if (pads <= 0) {
11583 return str;
11584 }
11585 if (pads > PAD_LIMIT) {
11586 return rightPad(str, size, String.valueOf(padChar));
11587 }
11588 return str.concat(padding(pads, padChar));
11589 }
11590
11591
11592
11593
11594
11595
11596
11597
11598
11599
11600
11601
11602
11603
11604
11605
11606
11607
11608
11609
11610
11611
11612
11613
11614 public static String rightPad(String str, int size, String padStr) {
11615 if (str == null) {
11616 return null;
11617 }
11618 if (isEmpty(padStr)) {
11619 padStr = " ";
11620 }
11621 int padLen = padStr.length();
11622 int strLen = str.length();
11623 int pads = size - strLen;
11624 if (pads <= 0) {
11625 return str;
11626 }
11627 if (padLen == 1 && pads <= PAD_LIMIT) {
11628 return rightPad(str, size, padStr.charAt(0));
11629 }
11630
11631 if (pads == padLen) {
11632 return str.concat(padStr);
11633 } else if (pads < padLen) {
11634 return str.concat(padStr.substring(0, pads));
11635 } else {
11636 char[] padding = new char[pads];
11637 char[] padChars = padStr.toCharArray();
11638 for (int i = 0; i < pads; i++) {
11639 padding[i] = padChars[i % padLen];
11640 }
11641 return str.concat(new String(padding));
11642 }
11643 }
11644
11645
11646
11647
11648
11649
11650
11651
11652
11653
11654
11655
11656
11657
11658
11659
11660
11661
11662
11663
11664 public static String leftPad(String str, int size) {
11665 return leftPad(str, size, ' ');
11666 }
11667
11668
11669
11670
11671
11672
11673
11674
11675
11676
11677
11678
11679
11680
11681
11682
11683
11684
11685
11686
11687
11688
11689 public static String leftPad(String str, int size, char padChar) {
11690 if (str == null) {
11691 return null;
11692 }
11693 int pads = size - str.length();
11694 if (pads <= 0) {
11695 return str;
11696 }
11697 if (pads > PAD_LIMIT) {
11698 return leftPad(str, size, String.valueOf(padChar));
11699 }
11700 return padding(pads, padChar).concat(str);
11701 }
11702
11703
11704
11705
11706
11707
11708
11709
11710
11711
11712
11713
11714
11715
11716
11717
11718
11719
11720
11721
11722
11723
11724
11725
11726 public static String leftPad(String str, int size, String padStr) {
11727 if (str == null) {
11728 return null;
11729 }
11730 if (isEmpty(padStr)) {
11731 padStr = " ";
11732 }
11733 int padLen = padStr.length();
11734 int strLen = str.length();
11735 int pads = size - strLen;
11736 if (pads <= 0) {
11737 return str;
11738 }
11739 if (padLen == 1 && pads <= PAD_LIMIT) {
11740 return leftPad(str, size, padStr.charAt(0));
11741 }
11742
11743 if (pads == padLen) {
11744 return padStr.concat(str);
11745 } else if (pads < padLen) {
11746 return padStr.substring(0, pads).concat(str);
11747 } else {
11748 char[] padding = new char[pads];
11749 char[] padChars = padStr.toCharArray();
11750 for (int i = 0; i < pads; i++) {
11751 padding[i] = padChars[i % padLen];
11752 }
11753 return new String(padding).concat(str);
11754 }
11755 }
11756
11757
11758
11759
11760
11761
11762
11763
11764
11765
11766
11767
11768
11769
11770
11771
11772
11773
11774
11775
11776
11777
11778
11779
11780
11781
11782 public static String substringBefore(String str, String separator) {
11783 if (isEmpty(str) || separator == null) {
11784 return str;
11785 }
11786 if (separator.length() == 0) {
11787 return EMPTY;
11788 }
11789 int pos = str.indexOf(separator);
11790 if (pos == -1) {
11791 return str;
11792 }
11793 return str.substring(0, pos);
11794 }
11795
11796
11797
11798
11799
11800
11801
11802
11803
11804
11805
11806
11807
11808
11809
11810
11811
11812
11813
11814
11815
11816
11817
11818
11819
11820
11821
11822 public static String substringAfter(String str, String separator) {
11823 if (isEmpty(str)) {
11824 return str;
11825 }
11826 if (separator == null) {
11827 return EMPTY;
11828 }
11829 int pos = str.indexOf(separator);
11830 if (pos == -1) {
11831 return EMPTY;
11832 }
11833 return str.substring(pos + separator.length());
11834 }
11835
11836
11837
11838
11839
11840
11841
11842
11843
11844
11845
11846
11847
11848
11849
11850
11851
11852
11853
11854
11855
11856
11857
11858
11859
11860
11861 public static String substringBeforeLast(String str, String separator) {
11862 if (isEmpty(str) || isEmpty(separator)) {
11863 return str;
11864 }
11865 int pos = str.lastIndexOf(separator);
11866 if (pos == -1) {
11867 return str;
11868 }
11869 return str.substring(0, pos);
11870 }
11871
11872
11873
11874
11875
11876
11877
11878
11879
11880
11881
11882
11883
11884
11885
11886
11887
11888
11889
11890
11891
11892
11893
11894
11895
11896
11897
11898
11899 public static String substringAfterLast(String str, String separator) {
11900 if (isEmpty(str)) {
11901 return str;
11902 }
11903 if (isEmpty(separator)) {
11904 return EMPTY;
11905 }
11906 int pos = str.lastIndexOf(separator);
11907 if (pos == -1 || pos == (str.length() - separator.length())) {
11908 return EMPTY;
11909 }
11910 return str.substring(pos + separator.length());
11911 }
11912
11913
11914
11915
11916 public static void waitForInput() {
11917 System.out.print("Press enter to continue: ");
11918 BufferedReader stdin = null;
11919
11920 try {
11921 stdin = new BufferedReader(new InputStreamReader(System.in));
11922 stdin.readLine();
11923 } catch (Exception e) {
11924 throw new RuntimeException(e);
11925 }
11926
11927 }
11928
11929
11930
11931
11932
11933
11934
11935
11936
11937 public static <T> T retrieveByProperties(Collection<T> collection,
11938 List<String> propertyNames, List<Object> propertyValues) {
11939 List<T> list = retrieveListByProperties(collection, propertyNames, propertyValues);
11940 return listPopOne(list);
11941 }
11942
11943
11944
11945
11946
11947
11948
11949
11950
11951 public static <T> T retrieveByProperty(Collection<T> collection,
11952 String propertyName, Object propertyValue) {
11953 List<T> list = retrieveListByProperty(collection, propertyName, propertyValue);
11954 return listPopOne(list);
11955 }
11956
11957
11958
11959
11960
11961
11962
11963
11964
11965
11966
11967
11968
11969
11970
11971
11972 public static Stem getFirstParentStemOfName(String name) {
11973 String parent = parentStemNameFromName(name);
11974
11975 if (parent == null || parent.equals(name)) {
11976 return StemFinder.findRootStem(GrouperSession.staticGrouperSession()
11977 .internal_getRootSession());
11978 }
11979
11980 Stem stem = StemFinder.findByName(GrouperSession.staticGrouperSession()
11981 .internal_getRootSession(), parent, false);
11982 if (stem != null) {
11983 return stem;
11984 }
11985
11986 return getFirstParentStemOfName(parent);
11987 }
11988
11989
11990
11991
11992
11993
11994
11995
11996
11997 public static <T> List<T> retrieveListByProperties(Collection<T> collection,
11998 List<String> propertyNames, List<Object> propertyValues) {
11999
12000 int fieldNameLength = propertyNames.size();
12001
12002 List<T> result = new ArrayList<T>();
12003
12004 assertion(fieldNameLength == propertyValues.size(), "Problem: " + fieldNameLength + " != " + propertyValues.size());
12005
12006 OUTER: for (T object : collection) {
12007
12008 for (int i=0;i<fieldNameLength;i++) {
12009 Object propertyValue = propertyValue(object, propertyNames.get(i));
12010 if (!equals(propertyValue, propertyValues.get(i))) {
12011 continue OUTER;
12012 }
12013 }
12014
12015 result.add(object);
12016
12017 }
12018
12019 return result;
12020 }
12021
12022
12023
12024
12025
12026
12027
12028
12029
12030 public static <T> List<T> retrieveListByProperty(Collection<T> collection,
12031 String propertyName, Object propertyValue) {
12032
12033 List<T> result = new ArrayList<T>();
12034
12035 OUTER: for (T object : collection) {
12036 if (object == null) {
12037 continue;
12038 }
12039 Object currentPropertyValue = propertyValue(object, propertyName);
12040 if (!equals(currentPropertyValue, propertyValue)) {
12041 continue OUTER;
12042 }
12043
12044 result.add(object);
12045
12046 }
12047
12048 return result;
12049 }
12050
12051
12052
12053
12054
12055
12056
12057
12058 public static <T> T listPopOne(List<T> list) {
12059 int size = length(list);
12060 if (size == 1) {
12061 return list.get(0);
12062 } else if (size == 0) {
12063 return null;
12064 }
12065 throw new RuntimeException("More than one object of type " + className(list.get(0))
12066 + " was returned when only one was expected. (size:" + size +")" );
12067 }
12068
12069
12070
12071
12072
12073
12074
12075
12076 public static <T> T setPopOne(Set<T> set) {
12077 int size = length(set);
12078 if (size == 1) {
12079 return set.iterator().next();
12080 } else if (size == 0) {
12081 return null;
12082 }
12083 throw new RuntimeException("More than one object of type " + className(set.iterator().next())
12084 + " was returned when only one was expected. (size:" + size +")" );
12085 }
12086
12087
12088
12089
12090
12091
12092
12093
12094
12095 public static <T> T collectionPopOne(Collection<T> collection, boolean exceptionIfMoreThanOne) {
12096 int size = length(collection);
12097 if (size > 1 && exceptionIfMoreThanOne) {
12098 throw new RuntimeException("More than one object of type " + className(get(collection, 0))
12099 + " was returned when only one was expected. (size:" + size +")" );
12100 }
12101 if (size == 0) {
12102 return null;
12103 }
12104 return collection.iterator().next();
12105 }
12106
12107
12108 private static final String[] XML_SEARCH_NO_SINGLE = new String[]{"&","<",">","\""};
12109
12110
12111 private static final String[] XML_REPLACE_NO_SINGLE = new String[]{"&","<",">","""};
12112
12113
12114
12115
12116
12117
12118
12119
12120
12121
12122
12123 public static String xmlEscape(String input) {
12124 return xmlEscape(input, true);
12125 }
12126
12127
12128
12129
12130
12131
12132
12133
12134
12135
12136 public static String xmlEscape(String input, boolean isEscape) {
12137 if (isEscape) {
12138 return replace(input, XML_SEARCH_NO_SINGLE, XML_REPLACE_NO_SINGLE);
12139 }
12140 return replace(input, XML_REPLACE_NO_SINGLE, XML_SEARCH_NO_SINGLE);
12141 }
12142
12143
12144
12145
12146
12147
12148
12149 public static void xmlAttribute(Writer writer, String attributeName, String attributeValue) {
12150 try {
12151 writer.write(" ");
12152 writer.write(attributeName);
12153 writer.write("=\"");
12154 String escapedValue = xmlEscape(attributeValue, true);
12155 writer.write(escapedValue);
12156 writer.write("\"");
12157 } catch (IOException ioe) {
12158 throw new RuntimeException(ioe);
12159 }
12160 }
12161
12162
12163
12164
12165
12166
12167
12168 public static boolean substituteStrings(Map<String, String> stringSubstituteMap,
12169 Object object) {
12170
12171 Set<String> fieldNames = stringFieldNames(object.getClass());
12172
12173 boolean altered = false;
12174
12175
12176 for (String fieldName : fieldNames) {
12177 String value = (String)fieldValue(object, fieldName);
12178
12179
12180 if (!StringUtils.isBlank(value) && stringSubstituteMap.containsKey(value)) {
12181
12182 assignField(object, fieldName, stringSubstituteMap.get(value));
12183 altered = true;
12184 }
12185 }
12186 return altered;
12187 }
12188
12189
12190 public static Map<Class<?>, Set<String>> stringFieldNames = new HashMap<Class<?>, Set<String>>();
12191
12192
12193
12194
12195
12196
12197
12198 public static Set<String> stringFieldNames(Class<?> theClass) {
12199
12200 if (!stringFieldNames.containsKey(theClass)) {
12201 stringFieldNames.put(theClass, fieldNames(theClass, String.class, false));
12202 }
12203 return stringFieldNames.get(theClass);
12204 }
12205
12206
12207
12208
12209
12210
12211
12212
12213 public static boolean appendIfNotBlank(StringBuilder result,
12214 Object theStringOrArrayOrList) {
12215 return appendIfNotBlank(result, null, theStringOrArrayOrList, null);
12216 }
12217
12218
12219
12220
12221
12222
12223
12224
12225
12226
12227 public static String appendIfNotBlankString(String string, String separator, String suffix) {
12228
12229 string = StringUtils.trimToEmpty(string);
12230 suffix = StringUtils.trimToEmpty(suffix);
12231
12232 boolean stringIsBlank = StringUtils.isBlank(string);
12233 boolean suffixIsBlank = StringUtils.isBlank(suffix);
12234
12235 if (stringIsBlank && suffixIsBlank) {
12236 return "";
12237 }
12238
12239 if (stringIsBlank) {
12240 return suffix;
12241 }
12242
12243 if (suffixIsBlank) {
12244 return string;
12245 }
12246
12247 return string + separator + suffix;
12248
12249 }
12250
12251
12252
12253
12254
12255
12256
12257
12258
12259
12260
12261
12262
12263
12264 public static String appendPrefixIfStringNotBlank(String prefix, String separator, String string) {
12265
12266 string = StringUtils.trimToEmpty(string);
12267 prefix = StringUtils.trimToEmpty(prefix);
12268
12269 boolean stringIsBlank = StringUtils.isBlank(string);
12270 boolean prefixIsBlank = StringUtils.isBlank(prefix);
12271
12272 if (stringIsBlank) {
12273 return "";
12274 }
12275
12276 if (prefixIsBlank) {
12277 return string;
12278 }
12279
12280 return prefix + separator + string;
12281
12282 }
12283
12284
12285
12286
12287
12288
12289
12290
12291
12292 public static boolean appendIfNotBlank(StringBuilder result,
12293 String prefix, Object theStringOrArrayOrList) {
12294 return appendIfNotBlank(result, prefix, theStringOrArrayOrList, null);
12295 }
12296
12297
12298
12299
12300
12301
12302
12303
12304
12305
12306 public static boolean appendIfNotBlank(StringBuilder result,
12307 String prefix, Object theStringOrArrayOrList, String suffix) {
12308 return appendIfNotBlank(result, prefix, null, theStringOrArrayOrList, suffix);
12309 }
12310
12311
12312
12313
12314
12315
12316
12317
12318
12319
12320
12321 public static boolean appendIfNotBlank(StringBuilder result,
12322 String prefix, String prefixIfNotBlank, Object theStringOrArrayOrList, String suffix) {
12323 int length = length(theStringOrArrayOrList);
12324 Iterator iterator = iterator(theStringOrArrayOrList);
12325 boolean appendedAnything = false;
12326
12327
12328 boolean hasPrefix = !StringUtils.isEmpty(prefix);
12329 boolean hasPrefixIfNotBlank = !StringUtils.isEmpty(prefixIfNotBlank);
12330 boolean hasSuffix = !StringUtils.isEmpty(suffix);
12331 for (int i=0;i<length;i++) {
12332 String current = (String) next(theStringOrArrayOrList, iterator, i);
12333
12334
12335 if (!StringUtils.isBlank(current)) {
12336
12337
12338 appendedAnything = true;
12339 if (hasPrefix) {
12340 result.append(prefix);
12341 }
12342 if (hasPrefixIfNotBlank && result.length() > 0) {
12343 result.append(prefixIfNotBlank);
12344 }
12345 result.append(current);
12346 if (hasSuffix) {
12347 result.append(suffix);
12348 }
12349 }
12350 }
12351 return appendedAnything;
12352 }
12353
12354
12355
12356
12357
12358
12359
12360
12361 public static boolean appendIfNotEmpty(StringBuilder result,
12362 Object theStringOrArrayOrList) {
12363 return appendIfNotEmpty(result, null, theStringOrArrayOrList, null);
12364 }
12365
12366
12367
12368
12369
12370
12371
12372
12373
12374 public static boolean appendIfNotEmpty(StringBuilder result,
12375 String prefix, Object theStringOrArrayOrList) {
12376 return appendIfNotEmpty(result, prefix, theStringOrArrayOrList, null);
12377 }
12378
12379
12380
12381
12382
12383
12384
12385
12386
12387
12388 public static boolean appendIfNotEmpty(StringBuilder result,
12389 String prefix, Object theStringOrArrayOrList, String suffix) {
12390 return appendIfNotEmpty(result, prefix, null, theStringOrArrayOrList, suffix);
12391 }
12392
12393
12394
12395
12396
12397
12398
12399
12400
12401
12402
12403 public static boolean appendIfNotEmpty(StringBuilder result,
12404 String prefix, String prefixIfNotEmpty, Object theStringOrArrayOrList, String suffix) {
12405 int length = length(theStringOrArrayOrList);
12406 Iterator iterator = iterator(theStringOrArrayOrList);
12407 boolean appendedAnything = false;
12408 boolean hasPrefix = !StringUtils.isEmpty(prefix);
12409 boolean hasPrefixIfNotEmpty = !StringUtils.isEmpty(prefixIfNotEmpty);
12410 boolean hasSuffix = !StringUtils.isEmpty(suffix);
12411 for (int i=0;i<length;i++) {
12412 String current = (String) next(theStringOrArrayOrList, iterator, i);
12413
12414
12415 if (!StringUtils.isEmpty(current)) {
12416
12417
12418 appendedAnything = true;
12419 if (hasPrefix) {
12420 result.append(prefix);
12421 }
12422 if (hasPrefixIfNotEmpty && result.length() > 0) {
12423 result.append(prefixIfNotEmpty);
12424 }
12425 result.append(current);
12426 if (hasSuffix) {
12427 result.append(suffix);
12428 }
12429 }
12430 }
12431 return appendedAnything;
12432 }
12433
12434
12435
12436
12437
12438
12439
12440
12441
12442
12443
12444 public static int indexOf(Object[] array, Object objectToFind) {
12445 return indexOf(array, objectToFind, 0);
12446 }
12447
12448
12449
12450
12451
12452
12453
12454
12455
12456
12457 public static boolean contains(Object[] array, Object objectToFind) {
12458 return indexOf(array, objectToFind) != -1;
12459 }
12460
12461
12462
12463
12464
12465
12466
12467
12468
12469
12470
12471
12472
12473
12474
12475 public static int indexOf(Object[] array, Object objectToFind, int startIndex) {
12476 if (array == null) {
12477 return -1;
12478 }
12479 if (startIndex < 0) {
12480 startIndex = 0;
12481 }
12482 if (objectToFind == null) {
12483 for (int i = startIndex; i < array.length; i++) {
12484 if (array[i] == null) {
12485 return i;
12486 }
12487 }
12488 } else {
12489 for (int i = startIndex; i < array.length; i++) {
12490 if (objectToFind.equals(array[i])) {
12491 return i;
12492 }
12493 }
12494 }
12495 return -1;
12496 }
12497
12498
12499
12500
12501
12502
12503
12504
12505 public static <T> T arrayPopOne(T[] array) {
12506 int size = length(array);
12507 if (size == 1) {
12508 return array[0];
12509 } else if (size == 0) {
12510 return null;
12511 }
12512 throw new RuntimeException("More than one object of type " + className(array[0])
12513 + " was returned when only one was expected. (size:" + size +")" );
12514 }
12515
12516
12517
12518
12519
12520 private static final String WS_DATE_FORMAT = "yyyy/MM/dd HH:mm:ss.SSS";
12521
12522
12523
12524
12525
12526 private static final String WS_DATE_FORMAT2 = "yyyy/MM/dd_HH:mm:ss.SSS";
12527
12528
12529
12530
12531
12532
12533
12534
12535 public static String dateToString(Date date) {
12536 if (date == null) {
12537 return null;
12538 }
12539 SimpleDateFormat simpleDateFormat = new SimpleDateFormat(WS_DATE_FORMAT);
12540 return simpleDateFormat.format(date);
12541 }
12542
12543
12544
12545
12546
12547
12548
12549
12550 public static Date stringToDate(String dateString) {
12551 if (isBlank(dateString)) {
12552 return null;
12553 }
12554 SimpleDateFormat simpleDateFormat = new SimpleDateFormat(WS_DATE_FORMAT);
12555 try {
12556 return simpleDateFormat.parse(dateString);
12557 } catch (ParseException e) {
12558 SimpleDateFormat simpleDateFormat2 = new SimpleDateFormat(WS_DATE_FORMAT2);
12559 try {
12560 return simpleDateFormat2.parse(dateString);
12561 } catch (ParseException e2) {
12562 throw new RuntimeException("Cannot convert '" + dateString
12563 + "' to a date based on format: " + WS_DATE_FORMAT, e);
12564 }
12565 }
12566 }
12567
12568
12569
12570
12571
12572 public static Long getMaxLongValue(Long... values) {
12573 if (values == null || values.length == 0) {
12574 return null;
12575 }
12576
12577 Long maxValue = null;
12578 for (int i = 0; i < values.length; i++) {
12579 if (values[i] != null) {
12580 if (maxValue == null || maxValue.compareTo(values[i]) < 0) {
12581 maxValue = new Long(values[i]);
12582 }
12583 }
12584 }
12585
12586 return maxValue;
12587 }
12588
12589
12590
12591
12592
12593 public static Long getMinLongValue(Long... values) {
12594 if (values == null || values.length == 0) {
12595 return null;
12596 }
12597
12598 Long minValue = null;
12599 for (int i = 0; i < values.length; i++) {
12600 if (values[i] != null) {
12601 if (minValue == null || minValue.compareTo(values[i]) > 0) {
12602 minValue = new Long(values[i]);
12603 }
12604 }
12605 }
12606
12607 return minValue;
12608 }
12609
12610
12611
12612
12613
12614
12615 public static Map<String, String> propertiesThreadLocalOverrideMap(String propertiesFileName) {
12616 Map<String, Map<String, String>> overrideMap = propertiesThreadLocalOverrideMap.get();
12617 if (overrideMap == null) {
12618 overrideMap = new HashMap<String, Map<String, String>>();
12619 propertiesThreadLocalOverrideMap.set(overrideMap);
12620 }
12621 Map<String, String> propertiesOverrideMap = overrideMap.get(propertiesFileName);
12622 if (propertiesOverrideMap == null) {
12623 propertiesOverrideMap = new HashMap<String, String>();
12624 overrideMap.put(propertiesFileName, propertiesOverrideMap);
12625 }
12626 return propertiesOverrideMap;
12627 }
12628
12629
12630
12631
12632
12633 private static Pattern typeCastTypePattern = Pattern.compile("^\\s*\\((.+)\\)\\s*([^\\s]+)\\s*$");
12634
12635
12636
12637
12638
12639
12640
12641
12642
12643
12644
12645 public static Map<String, Object> typeCastStringStringMap(Map<String, Object> limitEnvVars) {
12646
12647 Map<String, Object> result = new LinkedHashMap<String, Object>();
12648
12649 if (length(limitEnvVars) == 0) {
12650 return result;
12651 }
12652
12653 Matcher matcher = null;
12654
12655 for (String key : limitEnvVars.keySet()) {
12656
12657 Object value = limitEnvVars.get(key);
12658 matcher = typeCastTypePattern.matcher(key);
12659 if (value instanceof String && matcher.matches()) {
12660 String type = StringUtils.trimToEmpty(matcher.group(1));
12661 Object valueOriginal = value;
12662 key = StringUtils.trimToEmpty(matcher.group(2));
12663 try {
12664 if (StringUtils.equalsIgnoreCase(type, "int") || StringUtils.equalsIgnoreCase(type, "integer")
12665 || StringUtils.equalsIgnoreCase(type, "long")) {
12666 value = longValue(value);
12667 } else if (StringUtils.equalsIgnoreCase(type, "double") || StringUtils.equalsIgnoreCase(type, "float")
12668 || StringUtils.equalsIgnoreCase(type, "decimal")) {
12669 value = doubleValue(value);
12670 } else if (StringUtils.equalsIgnoreCase(type, "date") || StringUtils.equalsIgnoreCase(type, "timestamp")) {
12671 value = toTimestamp(value);
12672 } else if (StringUtils.equalsIgnoreCase(type, "text") || StringUtils.equalsIgnoreCase(type, "string")) {
12673
12674 } else if (StringUtils.equalsIgnoreCase(type, "boolean")) {
12675 value = booleanValue(value);
12676 } else if (StringUtils.equalsIgnoreCase(type, "null")) {
12677 value = null;
12678 } else if (StringUtils.equalsIgnoreCase(type, "empty") || StringUtils.equalsIgnoreCase(type, "emptyString")) {
12679 value = "";
12680 } else {
12681 throw new RuntimeException("Not expecting type: " + type + ", " + valueOriginal);
12682 }
12683 } catch (RuntimeException re) {
12684 throw new RuntimeException("Cannot convert value to " + key + ", " + type + ", " + valueOriginal, re);
12685 }
12686 }
12687
12688 result.put(key, value);
12689
12690 }
12691 return result;
12692 }
12693
12694
12695
12696
12697
12698
12699
12700
12701
12702
12703
12704
12705 public static boolean ipOnNetwork(String ipString, String networkIpString, int mask) {
12706
12707
12708 if (mask == 0) {
12709 return true;
12710 }
12711
12712 if (StringUtils.equals(networkIpString, "127.0.0.1") && StringUtils.equals(ipString, "0:0:0:0:0:0:0:1")) {
12713 return true;
12714 }
12715
12716
12717 if (StringUtils.equals(networkIpString, ipString)) {
12718 return true;
12719 }
12720
12721 if (ipString.contains(":") || networkIpString.contains(":")) {
12722 return false;
12723 }
12724
12725 int ip = ipInt(ipString);
12726 int networkIp = ipInt(networkIpString);
12727
12728 ip = ipReadyForAnd(ip, mask);
12729 networkIp = ipReadyForAnd(networkIp, mask);
12730
12731 return ip == networkIp;
12732 }
12733
12734
12735
12736
12737 private static Pattern ipv4regex = Pattern.compile("^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$");
12738
12739
12740
12741
12742
12743
12744
12745
12746
12747
12748 public static boolean ipOnNetworks(String ipString, String networkIpStrings) {
12749
12750 String[] networkIpStringsArray = splitTrim(networkIpStrings, ",");
12751
12752
12753 for (String networkIpString : networkIpStringsArray) {
12754
12755 if (ipv4regex.matcher(networkIpString).matches()) {
12756 networkIpString = networkIpString + "/32";
12757 }
12758
12759 if (!contains(networkIpString, "/")) {
12760 throw new RuntimeException("String must contain slash and CIDR network bits, e.g. 1.2.3.4/14");
12761 }
12762
12763 String network = prefixOrSuffix(networkIpString, "/", true);
12764 network = trim(network);
12765
12766 String mask = prefixOrSuffix(networkIpString, "/", false);
12767 mask = trim(mask);
12768 int maskInt = -1;
12769
12770 maskInt = Integer.parseInt(mask);
12771
12772
12773 if (ipOnNetwork(ipString, network, maskInt)) {
12774 return true;
12775 }
12776
12777
12778 }
12779 return false;
12780 }
12781
12782
12783
12784
12785
12786
12787
12788 public static int ipReadyForAnd(int ip, int maskLength) {
12789 int mask = -1 + (int) Math.pow(2, 32 - maskLength);
12790
12791 return ip | mask;
12792 }
12793
12794
12795
12796
12797
12798
12799 public static int ipInt(String ip) {
12800 int block1;
12801 int block2;
12802 int block3;
12803 int block4;
12804
12805 try {
12806 int periodIndex = ip.indexOf('.');
12807 String blockString = ip.substring(0, periodIndex);
12808 block1 = Integer.parseInt(blockString);
12809
12810
12811 int mathPow = (int) Math.pow(2, 24);
12812 block1 *= mathPow;
12813
12814 int oldPeriodIndex = periodIndex;
12815
12816 periodIndex = ip.indexOf('.', periodIndex + 1);
12817 blockString = ip.substring(oldPeriodIndex + 1, periodIndex);
12818 block2 = Integer.parseInt(blockString);
12819 block2 *= Math.pow(2, 16);
12820 oldPeriodIndex = periodIndex;
12821
12822 periodIndex = ip.indexOf('.', periodIndex + 1);
12823 blockString = ip.substring(oldPeriodIndex + 1, periodIndex);
12824 block3 = Integer.parseInt(blockString);
12825 block3 *= Math.pow(2, 8);
12826
12827 blockString = ip.substring(periodIndex + 1, ip.length());
12828 block4 = Integer.parseInt(blockString);
12829 } catch (NumberFormatException nfe) {
12830 throw new RuntimeException("Could not parse the ipaddress: " + ip);
12831 }
12832
12833 return block1 + block2 + block3 + block4;
12834 }
12835
12836
12837
12838
12839
12840
12841
12842
12843
12844
12845
12846
12847 public static void methodsByNameHelper(Class<?> theClass, String methodName, Class<?> superclassToStopAt,
12848 boolean includeSuperclassToStopAt,
12849 boolean includeStaticMethods, Class<? extends Annotation> markerAnnotation,
12850 boolean includeAnnotation, Set<Method> methodSet) {
12851 theClass = unenhanceClass(theClass);
12852 Method[] methods = theClass.getDeclaredMethods();
12853 if (length(methods) != 0) {
12854 for (Method method : methods) {
12855
12856 if (!includeStaticMethods
12857 && Modifier.isStatic(method.getModifiers())) {
12858 continue;
12859 }
12860
12861 if (markerAnnotation != null
12862 && (includeAnnotation != method
12863 .isAnnotationPresent(markerAnnotation))) {
12864 continue;
12865 }
12866 if (StringUtils.equals(methodName, method.getName())) {
12867
12868 methodSet.add(method);
12869 }
12870 }
12871 }
12872
12873
12874 if (theClass.equals(superclassToStopAt)
12875 || theClass.equals(Object.class)) {
12876 return;
12877 }
12878 Class superclass = theClass.getSuperclass();
12879 if (!includeSuperclassToStopAt && superclass.equals(superclassToStopAt)) {
12880 return;
12881 }
12882
12883 methodsByNameHelper(superclass, methodName, superclassToStopAt,
12884 includeSuperclassToStopAt, includeStaticMethods,
12885 markerAnnotation, includeAnnotation, methodSet);
12886
12887 }
12888
12889
12890
12891
12892
12893
12894
12895
12896
12897 public static Object callMethodWithMoreParams(Object instance, Class<?> theType, String methodName, Object[] params) {
12898 Method method = methodByName(theType, methodName, Object.class, false, instance == null ? true : false, true);
12899
12900 int paramsSize = length(params);
12901
12902 Class<?>[] methodParamTypes = method.getParameterTypes();
12903
12904 int methodParamsSize = length(methodParamTypes);
12905 if (methodParamsSize < paramsSize) {
12906 throw new RuntimeException("Problem marshaling between Grouper versions... why is method params "
12907 + methodParamsSize + " less than args? " + paramsSize + " for method: " + method);
12908 }
12909
12910
12911 for (int i=0;i<paramsSize;i++) {
12912 Class<?> methodParamClass = methodParamTypes[i];
12913
12914
12915 if (methodParamTypes[i].isPrimitive() && params[i] == null) {
12916 throw new RuntimeException("Trying to call method: " + methodName + " on class: " + (instance == null ? null : instance.getClass())
12917 + " and arg index: " + i + " is null: but should be a primitive: " + methodParamTypes[i].getName());
12918 }
12919
12920 if (params[i] != null && !(methodParamTypes[i].isAssignableFrom(params[i].getClass()))) {
12921 throw new RuntimeException("Trying to call method: " + methodName + " on class: " + (instance == null ? null : instance.getClass())
12922 + " and arg index: " + i + " is of type: " + methodParamClass + ", but trying to pass: " + params[i].getClass());
12923 }
12924
12925 }
12926
12927 Object[] methodArgs = new Object[methodParamsSize];
12928
12929
12930 if (paramsSize > 0) {
12931 System.arraycopy(params, 0, methodArgs, 0, params.length);
12932
12933 }
12934
12935
12936 try {
12937 return method.invoke(instance, methodArgs);
12938 } catch (Exception e) {
12939 throw new RuntimeException("Trying to call method: " + methodName + " on class: " + (instance == null ? null : instance.getClass()), e);
12940 }
12941 }
12942
12943
12944
12945
12946
12947
12948
12949 public static Object changeToVersion(Object input, String newPackage) {
12950 return changeToVersionHelper(input, newPackage, 100);
12951 }
12952
12953
12954
12955
12956
12957
12958
12959
12960 public static Object changeToVersionHelper(Object input, String newPackage, int timeToLive) {
12961
12962
12963 if (input == null) {
12964 return null;
12965 }
12966
12967
12968 if (!input.getClass().isArray() && StringUtils.equals("java.lang", input.getClass().getPackage().getName())) {
12969
12970 if (input instanceof StringBuilder) {
12971 return new StringBuilder((StringBuilder)input);
12972 }
12973 return input;
12974 }
12975
12976
12977 Class inputClass = input.getClass();
12978
12979 int interestingLogFields = 0;
12980
12981
12982 int inputArrayLength = inputClass.isArray() ? length(input) : -1;
12983 if (inputClass.isArray() && String.class.equals(inputClass.getComponentType())) {
12984
12985 String[] result = new String[inputArrayLength];
12986 System.arraycopy(input, 0, result, 0, result.length);
12987 return result;
12988 }
12989
12990
12991 if (input.getClass().getName().startsWith("java.lang") && input.getClass().isArray()) {
12992 throw new RuntimeException("Not expecting class: " + input.getClass());
12993 }
12994
12995 StringBuilder logMessage = LOG.isDebugEnabled() ? new StringBuilder() : null;
12996
12997 if (logMessage != null) {
12998 logMessage.append("class: ").append(inputClass.getSimpleName()).append(", ");
12999 }
13000
13001 if (timeToLive-- < 0) {
13002 throw new RuntimeException("Circular reference!");
13003 }
13004
13005
13006 try {
13007
13008 Object result = null;
13009
13010 Class<?> outputClass = null;
13011 String outputClassName = newPackage + "." + (inputClass.isArray() ?
13012 inputClass.getComponentType().getSimpleName() : inputClass.getSimpleName());
13013 try {
13014 outputClass = forName(outputClassName);
13015 } catch (RuntimeException re) {
13016 if (re.getCause() instanceof ClassNotFoundException) {
13017 if (logMessage != null) {
13018 logMessage.append("output classNotFound: ").append(outputClassName);
13019 LOG.debug(logMessage.toString());
13020 }
13021 return null;
13022 }
13023
13024 throw re;
13025 }
13026
13027
13028
13029
13030 if (inputClass.isArray()) {
13031 Object array = Array.newInstance(outputClass, inputArrayLength);
13032 for (int i=0;i<inputArrayLength;i++) {
13033
13034 Object inputElement = Array.get(input, i);
13035 Object outputElement = changeToVersionHelper(inputElement, newPackage, timeToLive);
13036 Array.set(array, i, outputElement);
13037
13038 }
13039 return array;
13040 }
13041
13042
13043
13044 result = newInstance(outputClass);
13045
13046
13047 Set<Field> inputFields = fields(inputClass, Object.class, null, false, false, false, null, false);
13048 Set<Field> outputFields = fields(outputClass, Object.class, null, false, false, false, null, false);
13049
13050 Map<String, Field> inputFieldMap = new HashMap<String, Field>();
13051
13052 for (Field field : nonNull(inputFields)) {
13053 inputFieldMap.put(field.getName(), field);
13054 }
13055
13056
13057 for (Field outputField : nonNull(outputFields)) {
13058
13059 Field inputField = inputFieldMap.get(outputField.getName());
13060
13061 if (inputField == null) {
13062 if (logMessage != null) {
13063 interestingLogFields++;
13064 logMessage.append("field not found input: ").append(outputField.getName()).append(", ");
13065 }
13066 continue;
13067 }
13068
13069 inputFieldMap.remove(inputField.getName());
13070
13071 Object inputFieldObject = fieldValue(inputField, input);
13072
13073
13074 Object outputFieldObject = changeToVersionHelper(inputFieldObject, newPackage, timeToLive);
13075
13076
13077 if (outputFieldObject == null) {
13078 continue;
13079 }
13080
13081 try {
13082 assignField(outputField, result, outputFieldObject, true, false);
13083 } catch (RuntimeException re) {
13084 if (logMessage != null) {
13085 logMessage.append("problem with field: ").append(inputField.getName()).append(", ").append(ExceptionUtils.getFullStackTrace(re));
13086 interestingLogFields++;
13087 }
13088 }
13089 }
13090
13091 if (result instanceof ChangeToVersionCustomizable) {
13092 ((ChangeToVersionCustomizable)result).customizeChangeToVersion(input);
13093 }
13094 if (input instanceof ChangeToVersionCustomizable) {
13095 ((ChangeToVersionCustomizable)input).customizeChangeFromVersion(result);
13096 }
13097
13098 if (logMessage != null) {
13099 for (String inputFieldName : nonNull(inputFieldMap.keySet())) {
13100 logMessage.append("field not found output: ").append(inputFieldName).append(", ");
13101 interestingLogFields++;
13102 }
13103
13104 if (interestingLogFields > 0) {
13105 LOG.debug(logMessage.toString());
13106 }
13107 }
13108
13109 return result;
13110 } catch (RuntimeException re) {
13111 if (logMessage != null) {
13112 logMessage.append("Problem with class: ").append(re.getClass()).append(", ").append(re.getMessage());
13113 LOG.debug(logMessage.toString(), re);
13114 }
13115 throw re;
13116 }
13117
13118 }
13119
13120
13121
13122
13123 public static final String JAVA_IO_TMPDIR = "java.io.tmpdir";
13124
13125
13126 private static final String ORIGINAL_TMP_DIR = System.getProperty(JAVA_IO_TMPDIR);
13127
13128
13129 private static boolean loggedTempDir = false;
13130
13131
13132
13133
13134
13135 public static String tmpDir() {
13136 return tmpDir(false);
13137 }
13138
13139
13140
13141
13142
13143
13144 public static String tmpDir(boolean appendSlashIfNotThere) {
13145
13146 String tmpDir = null;
13147
13148 tmpDir = GrouperConfig.retrieveConfig().propertyValueString("grouper.tmp.dir");
13149 if (isBlank(tmpDir)) {
13150 tmpDir = ORIGINAL_TMP_DIR;
13151 if (isBlank(tmpDir)) {
13152
13153 System.out.println("Error: Cant find tmpDir. You should set grouper.tmp.dir in the grouper.properties!");
13154 LOG.fatal("Error: Cant find tmpDir. You should set grouper.tmp.dir in the grouper.properties!");
13155 }
13156 }
13157 if (!isBlank(tmpDir)) {
13158 if (!loggedTempDir) {
13159 loggedTempDir = true;
13160 LOG.info("Tmp dir is set to: '" + tmpDir + "'");
13161 }
13162 if (appendSlashIfNotThere) {
13163 tmpDir = StringUtils.trimToEmpty(tmpDir);
13164 if (!tmpDir.endsWith("\\") && !tmpDir.endsWith("/")) {
13165 tmpDir += File.separator;
13166 }
13167 }
13168 }
13169 return tmpDir;
13170 }
13171
13172
13173
13174
13175
13176
13177
13178 public static <T> List<T> listFromCollection(Collection<T> collection) {
13179 return collection == null ? null : new ArrayList<T>(collection);
13180 }
13181
13182
13183
13184
13185 private static ExecutorService executorService = Executors.newCachedThreadPool(new DaemonThreadFactory());
13186
13187
13188
13189
13190
13191 public static ExecutorService retrieveExecutorService() {
13192 return executorService;
13193 }
13194
13195
13196
13197
13198
13199
13200
13201 public static <T> GrouperFuture<T> executorServiceSubmit(ExecutorService executorService, Callable<T> callable) {
13202 Future future = executorService.submit(callable);
13203 GrouperFuturerouperFuture.html#GrouperFuture">GrouperFuture grouperFuture = new GrouperFuture(future, callable);
13204 return grouperFuture;
13205 }
13206
13207
13208
13209
13210
13211
13212
13213
13214 public static GrouperFuture executorServiceSubmit(ExecutorService executorService, GrouperCallable callable, boolean willRetry) {
13215 callable.setWillRetry(willRetry);
13216 Future future = executorService.submit(callable);
13217 GrouperFuturerouperFuture.html#GrouperFuture">GrouperFuture grouperFuture = new GrouperFuture(future, callable);
13218 return grouperFuture;
13219 }
13220
13221
13222
13223
13224
13225
13226
13227 public static String concat(String a, String b) {
13228 return a+b;
13229 }
13230
13231
13232
13233
13234
13235
13236
13237
13238 public static String concat(String a, String b, String c) {
13239 return a+b+c;
13240 }
13241
13242
13243
13244
13245
13246
13247
13248
13249
13250 public static String concat(String a, String b, String c, String d) {
13251 return a+b+c+d;
13252 }
13253
13254
13255
13256
13257
13258
13259
13260
13261
13262 public static String concat(String a, String b, String c, String d, String e) {
13263 return a+b+c+d+e;
13264 }
13265
13266
13267
13268
13269
13270 public static String stack() {
13271 Exception exception = new Exception();
13272
13273 String stack = getFullStackTrace(exception);
13274
13275 String[] stackLines = splitTrim(stack, "\n");
13276
13277 StringBuffer result = new StringBuffer();
13278
13279 for (int i=0;i<stackLines.length;i++) {
13280 String current = stackLines[i];
13281 if (current.startsWith("at edu.internet2") && !current.startsWith("at edu.internet2.middleware.grouper.util.GrouperUtil.stack(")) {
13282 if (result.length() > 0) {
13283 result.append(", ");
13284 }
13285 result.append(extractFileLine(current));
13286 }
13287 }
13288 return result.toString();
13289 }
13290
13291
13292
13293
13294
13295
13296
13297
13298
13299
13300
13301
13302
13303
13304 private static Pattern extractFileLinePattern = Pattern.compile("^.*\\.(.+)\\((.+):(\\d+)\\).*$");
13305
13306
13307
13308
13309
13310
13311 private static String extractFileLine(String fullLine) {
13312 Matcher matchResult = extractFileLinePattern.matcher(fullLine);
13313
13314 if (matchResult.find()) {
13315 String method = matchResult.group(1);
13316 String file = matchResult.group(2);
13317 if (file.endsWith(".java")) {
13318 file = file.substring(0, file.length() - ".java".length());
13319 }
13320 String line = matchResult.group(3);
13321 return file + "." + method + "() line " + line;
13322 }
13323 return fullLine;
13324 }
13325
13326
13327
13328
13329
13330
13331
13332
13333 public static <T extends GrouperId> Set<T> sortByIds(Collection<String> ids, Collection<T> grouperObjects) {
13334
13335
13336 if (grouperObjects == null) {
13337 return null;
13338 }
13339 Set<T> result = new LinkedHashSet<T>();
13340
13341
13342 if (grouperObjects.size() > 0) {
13343
13344
13345 Map<String, T> lookupMap = new HashMap<String, T>();
13346
13347 for (T grouperObject : grouperObjects) {
13348 lookupMap.put(grouperObject.getId(), grouperObject);
13349 }
13350
13351
13352
13353 Set<String> idsWeHaveUsed = new HashSet<String>();
13354
13355 for (String id : ids) {
13356 T grouperObject = lookupMap.get(id);
13357 if (grouperObject != null) {
13358 result.add(grouperObject);
13359
13360 idsWeHaveUsed.add(id);
13361
13362 }
13363 }
13364
13365
13366 for (T grouperObject : grouperObjects) {
13367 if (!idsWeHaveUsed.contains(grouperObject.getId())) {
13368 result.add(grouperObject);
13369 }
13370 }
13371
13372 }
13373
13374 return result;
13375 }
13376
13377
13378
13379
13380 public static String getGrouperHome() {
13381 return grouperHome;
13382 }
13383
13384
13385
13386
13387
13388
13389 public static List<String> splitFileLines(String fileContents) {
13390 fileContents = StringUtils.replace(fileContents, "\r\n", "\n");
13391 fileContents = StringUtils.replace(fileContents, "\r", "\n");
13392
13393 String[] resultArray = StringUtils.splitPreserveAllTokens(fileContents, '\n');
13394 List<String> result = GrouperUtil.toList(resultArray);
13395 return result;
13396 }
13397
13398
13399 public static final String[] HTML_REPLACE = new String[]{"&","<",">","'","""};
13400
13401
13402 public static final String[] HTML_REPLACE_NO_SINGLE = new String[]{"&","<",">","""};
13403
13404
13405 private static final String[] HTML_SEARCH = new String[]{"&","<",">","'","\""};
13406
13407
13408 public static final String[] HTML_SEARCH_NO_SINGLE = new String[]{"&","<",">","\""};
13409
13410
13411
13412
13413
13414
13415
13416
13417
13418
13419 public static String escapeHtml(String input, boolean isEscape) {
13420 return escapeHtml(input, isEscape, true);
13421 }
13422
13423
13424
13425
13426
13427
13428
13429
13430
13431
13432
13433 public static String escapeHtml(String input, boolean isEscape, boolean escapeSingleQuotes) {
13434 if (escapeSingleQuotes) {
13435 if (isEscape) {
13436 return GrouperUtil.replace(input, HTML_SEARCH, HTML_REPLACE);
13437 }
13438 return GrouperUtil.replace(input, HTML_REPLACE, HTML_SEARCH);
13439 }
13440 if (isEscape) {
13441 return GrouperUtil.replace(input, HTML_SEARCH_NO_SINGLE, HTML_REPLACE_NO_SINGLE);
13442 }
13443 return GrouperUtil.replace(input, HTML_REPLACE_NO_SINGLE, HTML_SEARCH_NO_SINGLE);
13444
13445 }
13446
13447
13448
13449
13450
13451
13452 public static List<File> fileListRecursive(File parent) {
13453 List<File> results = new ArrayList<File>();
13454 fileListRecursiveHelper(parent, results);
13455 return results;
13456 }
13457
13458
13459
13460
13461
13462
13463 private static void fileListRecursiveHelper(File parent, List<File> fileList) {
13464 if (parent == null || !parent.exists() || !parent.isDirectory()) {
13465 return;
13466 }
13467 List<File> subFiles = nonNull(toList(parent.listFiles()));
13468 for (File subFile : subFiles) {
13469 if (subFile.isFile()) {
13470 fileList.add(subFile);
13471 }
13472 if (subFile.isDirectory()) {
13473 fileListRecursiveHelper(subFile, fileList);
13474 }
13475 }
13476 }
13477
13478
13479
13480
13481
13482
13483 public static List<File> fileListRecursiveDirs(File parent) {
13484 List<File> results = new ArrayList<File>();
13485 fileListRecursiveDirsHelper(parent, results);
13486 return results;
13487 }
13488
13489
13490
13491
13492
13493
13494 private static void fileListRecursiveDirsHelper(File parent, List<File> fileList) {
13495 if (parent == null || !parent.exists() || !parent.isDirectory()) {
13496 return;
13497 }
13498 List<File> subFiles = nonNull(toList(parent.listFiles()));
13499 for (File subFile : subFiles) {
13500 if (subFile.isDirectory()) {
13501 fileList.add(subFile);
13502 fileListRecursiveDirsHelper(subFile, fileList);
13503 }
13504 }
13505 }
13506
13507
13508
13509
13510
13511
13512 public static Set<String> fileDescendantDirsRelativePaths(File parentDir) {
13513 Set<String> result = new LinkedHashSet<String>();
13514 List<File> descendants = fileListRecursiveDirs(parentDir);
13515 for (File file : nonNull(descendants)) {
13516 String descendantPath = file.getAbsolutePath();
13517 String parentPath = parentDir.getAbsolutePath();
13518 if (!descendantPath.startsWith(parentPath)) {
13519 throw new RuntimeException("Why doesnt descendantPath '" + descendantPath + "' start with parent path '" + parentPath + "'?");
13520 }
13521 descendantPath = descendantPath.substring(parentPath.length());
13522 if (descendantPath.startsWith("/") || descendantPath.startsWith("\\")) {
13523 descendantPath = descendantPath.substring(1);
13524 }
13525 result.add(descendantPath);
13526 }
13527 return result;
13528 }
13529
13530
13531
13532
13533
13534
13535 public static Set<String> fileDescendantRelativePaths(File parentDir) {
13536 Set<String> result = new LinkedHashSet<String>();
13537 List<File> descendants = fileListRecursive(parentDir);
13538 for (File file : nonNull(descendants)) {
13539 String descendantPath = file.getAbsolutePath();
13540 String parentPath = parentDir.getAbsolutePath();
13541 if (!descendantPath.startsWith(parentPath)) {
13542 throw new RuntimeException("Why doesnt descendantPath '" + descendantPath + "' start with parent path '" + parentPath + "'?");
13543 }
13544 descendantPath = descendantPath.substring(parentPath.length());
13545 if (descendantPath.startsWith("/") || descendantPath.startsWith("\\")) {
13546 descendantPath = descendantPath.substring(1);
13547 }
13548 result.add(descendantPath);
13549 }
13550 return result;
13551 }
13552
13553
13554
13555
13556
13557
13558
13559 public static void mapAddValue(Map<String, Object> map, String key, long numberToAdd) {
13560 if (map == null) {
13561 return;
13562 }
13563
13564 Object currentValue = map.get(key);
13565
13566 if (currentValue == null) {
13567
13568 currentValue = 0L;
13569 }
13570
13571 long newValue = GrouperUtil.longValue(currentValue) + numberToAdd;
13572
13573 map.put(key, newValue);
13574
13575 }
13576
13577
13578
13579
13580
13581
13582
13583 public static void mapAddValue(Map<String, Object> map, String key, int numberToAdd) {
13584 if (map == null) {
13585 return;
13586 }
13587
13588 Object currentValue = map.get(key);
13589
13590 if (currentValue == null) {
13591
13592 currentValue = 0;
13593 }
13594
13595 int newValue = GrouperUtil.intValue(currentValue) + numberToAdd;
13596
13597 map.put(key, newValue);
13598
13599 }
13600
13601
13602
13603
13604
13605
13606
13607
13608
13609
13610
13611 @SuppressWarnings("unchecked")
13612 public static String substituteExpressionLanguageTemplate(String script,
13613 Map<String, Object> variableMap, boolean allowStaticClasses, boolean silent, boolean lenient) {
13614 variableMap = nonNull(variableMap);
13615 substituteExpressionInit3();
13616
13617 if (isBlank(script)) {
13618 return null;
13619 }
13620
13621
13622
13623
13624
13625
13626
13627
13628
13629
13630
13631
13632
13633 String overallResult = null;
13634 Exception exception = null;
13635 try {
13636 org.apache.commons.jexl3.JexlContext jc = allowStaticClasses ? new GrouperMapContext3() : new org.apache.commons.jexl3.MapContext();
13637
13638 int index = 0;
13639
13640 for (String key: variableMap.keySet()) {
13641 jc.set(key, variableMap.get(key));
13642 }
13643
13644
13645 jc.set("grouperUtil", new GrouperUtilElSafe());
13646
13647
13648 script = script.trim();
13649
13650 org.apache.commons.jexl3.JexlEngine jexl = jexlEngines3.get(new MultiKey(silent, lenient));
13651 JxltEngine jxlt = jexl.createJxltEngine();
13652 Template theTemplate = jxlt.createTemplate(script);
13653
13654 Writer writer = new StringWriter();
13655
13656 String result = null;
13657
13658
13659 try {
13660 theTemplate.evaluate(jc, writer);
13661
13662 result = writer.toString();
13663 } catch (JexlException je) {
13664
13665 if (!lenient && StringUtils.trimToEmpty(je.getMessage()).contains("undefined variable")) {
13666
13667
13668 String message = je.getMessage();
13669
13670 Pattern exceptionPattern = Pattern.compile("^.*undefined variable (.*)");
13671 Matcher exceptionMatcher = exceptionPattern.matcher(message);
13672 if (exceptionMatcher.matches()) {
13673
13674 message = "variable '" + exceptionMatcher.group(1) + "' is not defined in script: '" + script + "'";
13675 }
13676 throw new ExpressionLanguageMissingVariableException(message, je);
13677 }
13678 throw je;
13679 }
13680
13681 return trim(result);
13682 } catch (HookVeto hv) {
13683 exception = hv;
13684 throw hv;
13685 } catch (Exception e) {
13686 exception = e;
13687 if (e instanceof ExpressionLanguageMissingVariableException) {
13688 throw (ExpressionLanguageMissingVariableException)e;
13689 }
13690 throw new RuntimeException("Error substituting string: '" + script + "', substituteVarNames: " + setToString(variableMap.keySet()), e);
13691 } finally {
13692 if (LOG.isDebugEnabled()) {
13693 Set<String> keysSet = new LinkedHashSet<String>(nonNull(variableMap).keySet());
13694 keysSet.add("grouperUtil");
13695 StringBuilder logMessage = new StringBuilder();
13696 logMessage.append("Subsituting EL: '").append(script).append("', and with env vars: ");
13697 String[] keys = keysSet.toArray(new String[]{});
13698 for (int i=0;i<keys.length;i++) {
13699 logMessage.append(keys[i]);
13700 if (i != keys.length-1) {
13701 logMessage.append(", ");
13702 }
13703 }
13704 logMessage.append(" with result: '" + overallResult + "'");
13705 if (exception != null) {
13706 if (exception instanceof HookVeto) {
13707 logMessage.append(", it was vetoed: " + exception);
13708 } else {
13709 logMessage.append(", and exception: " + exception + ", " + ExceptionUtils.getFullStackTrace(exception));
13710 }
13711 }
13712 LOG.debug(logMessage.toString());
13713 }
13714 }
13715 }
13716
13717
13718
13719
13720 private final static Map<MultiKey, org.apache.commons.jexl3.JexlEngine> jexlEngines3 = new HashMap<MultiKey, org.apache.commons.jexl3.JexlEngine>();
13721
13722
13723
13724
13725 private static boolean jexlEnginesInitialized3 = false;
13726
13727 private static void substituteExpressionInit() {
13728 if (!jexlEnginesInitialized) {
13729 synchronized (GrouperUtil.class) {
13730 if (!jexlEnginesInitialized) {
13731
13732 int cacheSize = GrouperConfig.retrieveConfig().propertyValueInt("jexl.cacheSize");
13733 for (JexlEngine jexlEngine : jexlEngines.values()) {
13734 jexlEngine.setCache(cacheSize);
13735 }
13736
13737 jexlEnginesInitialized = true;
13738 }
13739 }
13740 }
13741 }
13742
13743 private static void substituteExpressionInit3() {
13744 if (!jexlEnginesInitialized3) {
13745 synchronized (GrouperUtil.class) {
13746 if (!jexlEnginesInitialized3) {
13747
13748 int cacheSize = GrouperConfig.retrieveConfig().propertyValueInt("jexl.cacheSize");
13749 {
13750 Boolean silent = true;
13751 Boolean lenient = true;
13752 final org.apache.commons.jexl3.JexlEngine jexlEngine = new JexlBuilder().silent(silent).strict(!lenient).cache(cacheSize).create();
13753 jexlEngines3.put(new MultiKey(silent, lenient), jexlEngine);
13754 }
13755 {
13756 Boolean silent = false;
13757 Boolean lenient = true;
13758 final org.apache.commons.jexl3.JexlEngine jexlEngine = new JexlBuilder().silent(silent).strict(!lenient).cache(cacheSize).create();
13759 jexlEngines3.put(new MultiKey(silent, lenient), jexlEngine);
13760 }
13761 {
13762 Boolean silent = true;
13763 Boolean lenient = false;
13764 final org.apache.commons.jexl3.JexlEngine jexlEngine = new JexlBuilder().silent(silent).strict(!lenient).cache(cacheSize).create();
13765 jexlEngines3.put(new MultiKey(silent, lenient), jexlEngine);
13766 }
13767 {
13768 Boolean silent = false;
13769 Boolean lenient = false;
13770 final org.apache.commons.jexl3.JexlEngine jexlEngine = new JexlBuilder().silent(silent).strict(!lenient).cache(cacheSize).create();
13771 jexlEngines3.put(new MultiKey(silent, lenient), jexlEngine);
13772 }
13773
13774 jexlEnginesInitialized3 = true;
13775 }
13776 }
13777 }
13778 }
13779
13780
13781
13782
13783
13784 public static void gshReturn(int returnCode) {
13785 GrouperGroovyRuntime grouperGroovyRuntime = GrouperGroovyRuntime.retrieveGrouperGroovyRuntime();
13786 if (grouperGroovyRuntime == null) {
13787
13788 throw new ExitNotification(returnCode);
13789 }
13790
13791 grouperGroovyRuntime.gshReturn(returnCode);
13792 }
13793
13794
13795
13796
13797 public static void gshReturn() {
13798 gshReturn(0);
13799 }
13800
13801
13802
13803
13804
13805
13806
13807
13808 public static boolean portAvailable(int port, String ipAddress) {
13809
13810 ServerSocket ss = null;
13811 try {
13812
13813 if (isBlank(ipAddress) || "0.0.0.0".equals(ipAddress)) {
13814 ss = new ServerSocket(port);
13815 } else {
13816
13817 Pattern pattern = Pattern.compile("(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)");
13818
13819 Matcher matcher = pattern.matcher(ipAddress);
13820
13821 if (!matcher.matches()) {
13822 throw new RuntimeException("IP address not valid! '" + ipAddress + "'");
13823 }
13824
13825 byte[] b = new byte[4];
13826 for (int i=0;i<4;i++) {
13827 int theInt = intValue(matcher.group(i+1));
13828 if (theInt > 255 || theInt < 0) {
13829 System.out.println("IP address part must be between 0 and 255: '" + theInt + "'");
13830 }
13831 b[i] = (byte)theInt;
13832 }
13833
13834
13835 InetAddress inetAddress = InetAddress.getByAddress(b);
13836
13837 ss = new ServerSocket(port, 50, inetAddress);
13838 }
13839 ss.setReuseAddress(true);
13840 return true;
13841 } catch (IOException e) {
13842 } finally {
13843 if (ss != null) {
13844 try {
13845 ss.close();
13846 } catch (IOException e) {
13847
13848 }
13849 }
13850 }
13851
13852 return false;
13853 }
13854
13855
13856
13857
13858
13859
13860
13861
13862
13863 public static boolean portAvailableWait(int port, String ipAddress, int seconds, boolean expectingListening) {
13864 for (int i=0;i<60;i++) {
13865 GrouperUtil.sleep(1000);
13866
13867 boolean portAvailable = portAvailable(port, ipAddress);
13868 if (!expectingListening) {
13869 if (portAvailable) {
13870 return true;
13871 }
13872 } else {
13873 if (!portAvailable) {
13874 return true;
13875 }
13876 }
13877 }
13878 return false;
13879 }
13880
13881
13882
13883
13884
13885 public static boolean isWindows() {
13886 return GrouperClientUtils.isWindows();
13887 }
13888
13889 }