package org.osgl; /*- * #%L * Java Tool * %% * Copyright (C) 2014 - 2018 OSGL (Open Source General Library) * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% */ import org.osgl.cache.CacheService; import org.osgl.cache.impl.InteralCacheService; import org.osgl.exception.NotAppliedException; import org.osgl.util.*; import org.osgl.util.algo.StringReplace; import org.osgl.util.algo.StringSearch; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.nio.CharBuffer; import java.util.*; import java.util.regex.Pattern; import javax.inject.Singleton; public class OsglConfig { private static CacheService internalCache = new InteralCacheService(); public static final String OSGL_EXTENSION_LIST = "META-INF/osgl/extension.list"; public static void setInternalCache(CacheService cache) { internalCache = $.requireNotNull(cache); } public static CacheService internalCache() { return internalCache; } /** * Default string search logic */ public static StringSearch DEF_STRING_SEARCH = new StringSearch.SimpleStringSearch(); /** * Default string replace logic */ public static StringReplace DEF_STRING_REPLACE = new StringReplace.SimpleStringReplace(); public static $.Function<Class, ?> INSTANCE_FACTORY = new $.Function<Class, Object>() { @Override public Object apply(Class aClass) throws NotAppliedException, Lang.Break { if (List.class == aClass) { return new ArrayList<>(); } else if (Map.class == aClass) { return new HashMap<>(); } else if (Set.class == aClass) { return new HashSet<>(); } else if (SortedSet.class == aClass) { return new TreeSet<>(); } else if (SortedMap.class == aClass) { return new TreeMap<>(); } else if (C.Map.class == aClass) { return C.newMap(); } else if (C.List.class == aClass) { return C.newList(); } return $.newInstance(aClass); } }; public static $.Function<Class, ?> globalInstanceFactory() { return INSTANCE_FACTORY; } private static $.Predicate _singletonChecker = new $.Predicate() { @Override public boolean test(Object o) { Class<?> type = o instanceof Class ? (Class) o : o.getClass(); return null != type.getAnnotation(Singleton.class); } }; public static void setSingletonChecker($.Predicate singletonChecker) { _singletonChecker = $.requireNotNull(singletonChecker); } public static boolean isSingleton(Object o) { return _singletonChecker.test(o); } public static void registerGlobalInstanceFactory($.Function<Class, ?> instanceFactory) { INSTANCE_FACTORY = $.requireNotNull(instanceFactory); } private static final Set<String> immutableClassNames = new HashSet<>(); private static $.Predicate<Class> immutableClassPredicate = $.F.no(); static { immutableClassNames.addAll(IO.read(OsglConfig.class.getResource("immutable-classes.list")).toLines()); } public static void registerImmutableClassNames(Collection<String> immutableClassNames) { OsglConfig.immutableClassNames.addAll(immutableClassNames); } public static void registerImmutableClassPredicate($.Predicate<Class> predicate) { immutableClassPredicate = $.requireNotNull(predicate); } static boolean isImmutable(Class<?> c) { return immutableClassNames.contains(c.getName()) || immutableClassPredicate.test(c); } private static Set<String> mappingDisabledFields = new HashSet<>(); private static List<$.Predicate<String>> mappingDisabledFieldPredicates = new ArrayList<>(); /** * Check if a field name or map key should be ignored by global filter in mapping process. * @param s a field name or map key * @return `true` if the field name or map key should be ignored in mapping process. */ public static boolean globalMappingFilter_shouldIgnore(String s) { if (mappingDisabledFields.contains(s)) { return true; } if (mappingDisabledFieldPredicates.isEmpty()) { return false; } for ($.Predicate<String> tester : mappingDisabledFieldPredicates) { if (tester.test(s)) { return true; } } return false; } /** * Register global mapping filters. * * @param filterSpec * the first filter spec * @param filterSpecs * other filter specs * @see #addGlobalMappingFilter(String) */ public static void addGlobalMappingFilters(String filterSpec, String ... filterSpecs) { addGlobalMappingFilter(filterSpec); for (String s : filterSpecs) { addGlobalMappingFilter(s); } } /** * Register global mapping filters * * @param filterSpecs * A collection of filter specs * @see #addGlobalMappingFilter(String) */ public static void addGlobalMappingFilters(Collection<String> filterSpecs) { for (String filter : filterSpecs) { addGlobalMappingFilter(filter); } } /** * Register a global mapping filter. Unlike normal mapping filter, global mapping filter spec * * * checks only immediate level field name or map key * * it is always a black list filter * * it supports different matching verb: * - `contains:<payload>` - if test string contains `payload` then it shall be ignored * - `starts:<payload>` - if test string starts with `payload` then it shall be ignored * - `ends:<payload>` - if test string ends with `payload` then it shall be ignored * - `reg:<payload>` - if test string matches reg exp pattern `payload` then it shall be ignored * * if the filter spec dose not fall in the above category, then it is added into a set, and * if any test string exactly matches any item in that set, it shall be ignored. * * @param filterSpec * the filter spec. It can contains multiple filter specs separated by `,` */ public static void addGlobalMappingFilter(String filterSpec) { List<String> list = S.fastSplit(filterSpec, ","); for (String s : list) { if (S.blank(s)) { continue; } addSingleGlobalMappingFilter(s.trim()); } } private static void addSingleGlobalMappingFilter(String filterSpec) { E.illegalArgumentIf(S.blank(filterSpec), "Invalid filter: " + filterSpec); if (filterSpec.startsWith("contains:")) { String text = filterSpec.substring(9); E.illegalArgumentIf(S.blank(text), "Invalid filter: " + filterSpec); mappingDisabledFieldPredicates.add(S.F.contains(text)); } else if (filterSpec.startsWith("reg:")) { String text = filterSpec.substring(4); E.illegalArgumentIf(S.blank(text), "Invalid filter: " + filterSpec); final Pattern pattern = Pattern.compile(text); mappingDisabledFieldPredicates.add(new Lang.Predicate<String>() { @Override public boolean test(String s) { return pattern.matcher(s).matches(); } }); } else if (filterSpec.startsWith("starts:")) { String text = filterSpec.substring(7); E.illegalArgumentIf(S.blank(text), "Invalid filter: " + filterSpec); mappingDisabledFieldPredicates.add(S.F.startsWith(text)); } else if (filterSpec.startsWith("ends:")) { String text = filterSpec.substring(5); E.illegalArgumentIf(S.blank(text), "Invalid filter: " + filterSpec); mappingDisabledFieldPredicates.add(S.F.endsWith(text)); } else { mappingDisabledFields.add(filterSpec); } } public static void setThreadLocalBufferLimit(int limit) { UtilConfig.setThreadLocalBufferLimit(limit); } public static void setThreadLocalCharBufferLimit(int limit) { UtilConfig.setThreadLocalCharBufferLimit(limit); } public static int getThreadLocalCharBufferLimit() { return UtilConfig.getThreadLocalCharBufferLimit(); } public static void setThreadLocalCharBufferInitSize(int size) { UtilConfig.setThreadLocalCharBufferInitSize(size); } public static int getThreadLocalCharBufferInitSize() { return UtilConfig.getThreadLocalCharBufferInitSize(); } public static void setThreadLocalByteArrayBufferLimit(int limit) { UtilConfig.setThreadLocalByteArrayBufferLimit(limit); } public static int getThreadLocalByteArrayBufferLimit() { return UtilConfig.getThreadLocalByteArrayBufferLimit(); } public static void setThreadLocalByteArrayBufferInitSize(int size) { UtilConfig.setThreadLocalByteArrayBufferInitSize(size); } public static int getThreadLocalByteArrayBufferInitSize() { return UtilConfig.getThreadLocalByteArrayBufferInitSize(); } public static void registerExtensions() { try { final Enumeration<URL> systemResources = Lang.class.getClassLoader().getResources(OSGL_EXTENSION_LIST); while (systemResources.hasMoreElements()) { InputStream is = systemResources.nextElement().openStream(); List<String> lines = IO.read(is).toLines(); for (String extensionClass : lines) { if (S.blank(extensionClass)) { continue; } extensionClass = extensionClass.trim(); if (extensionClass.startsWith("#")) { continue; } try { $.classForName(extensionClass); } catch (Exception e) { System.out.println("[osgl] Warning: error loading extension class [" + extensionClass + "]"); e.printStackTrace(); } } } } catch (IOException e) { System.out.println("[osgl] Warning: error loading extensions due to IO exception"); e.printStackTrace(); } } public static $.Predicate<Readable> binaryDataProbe() { return binaryDataProbe; } public static void registerBinaryDataProbe($.Predicate<Readable> probe) { binaryDataProbe = $.requireNotNull(probe); } private static $.Predicate<Readable> binaryDataProbe = new $.Predicate<Readable>() { @Override public boolean test(Readable readable) { CharBuffer buf = CharBuffer.allocate(100); try { int n = readable.read(buf); if (n < 0) { return false; } buf.flip(); for (int i = 0; i < n; ++i) { char c = buf.charAt(i); if (Character.isISOControl(c)) { if (c != '\n' && c != '\r') { return true; } } } return false; } catch (IOException e) { throw E.ioException(e); } finally { buf.clear(); } } }; private static String xmlRootTag = "xml"; public static void setXmlRootTag(String tag) { xmlRootTag = S.requireNotBlank(tag); } public static String xmlRootTag() { return xmlRootTag; } private static String xmlListItemTag = "xmlListItem"; public static void setXmlListItemTag(String tag) { xmlListItemTag = tag; } public static String xmlListItemTag() { return xmlListItemTag; } private static int BIGLINE_ITERATOR_BUF_SIZE = 20000; public static void setBiglineIteratorBufSize(int size) { if (size < 1000) { size = 1000; } BIGLINE_ITERATOR_BUF_SIZE = size; } public static int getBiglineIteratorBufSize() { return BIGLINE_ITERATOR_BUF_SIZE; } }