001/*******************************************************************************
002The MIT License (MIT)
003
004Copyright (c) 2024 KILLCODING.COM
005
006Permission is hereby granted, free of charge, to any person obtaining a copy
007of this software and associated documentation files (the "Software"), to deal
008in the Software without restriction, including without limitation the rights
009to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
010copies of the Software, and to permit persons to whom the Software is
011furnished to do so, subject to the following conditions:
012
013The above copyright notice and this permission notice shall be included in
014all copies or substantial portions of the Software.
015
016THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
017IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
018FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
019AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
020LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
021OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
022THE SOFTWARE.
023*****************************************************************************/
024package com.killcoding.tool;
025
026import java.util.List;
027import java.util.Collections;
028import java.util.ArrayList;
029import java.util.Random;
030import java.net.InetAddress;
031import com.killcoding.log.Logger;
032import java.net.URL;
033import java.net.URI;
034import java.net.URISyntaxException;
035import java.io.File;
036import com.killcoding.log.LoggerFactory;
037import java.net.URLClassLoader;
038import java.io.FileFilter;
039import java.net.MalformedURLException;
040import java.security.MessageDigest;
041import com.killcoding.file.BaseFile;
042import java.util.Arrays;
043import java.nio.file.Files;
044import java.util.stream.Collectors;
045import java.nio.file.Paths;
046import java.nio.file.Path;
047import java.io.IOException;
048import java.nio.file.LinkOption;
049
050public final class CommonTools {
051    
052    private static String HOSTNAME = null;
053
054
055        public static URLClassLoader loadJars(String libDirs) throws Exception {
056        return loadJars(libDirs,ClassLoader.getSystemClassLoader());
057        }
058        
059        public static URLClassLoader loadJars(String[] libDirs) throws Exception {
060        return loadJars(libDirs,ClassLoader.getSystemClassLoader());
061        }       
062        
063        public static URLClassLoader loadJars(String[] libDirs,ClassLoader classLoader) throws Exception {
064            return loadJars(String.join(";",libDirs),classLoader);
065        }
066
067        public static URLClassLoader loadJars(String libDirs,ClassLoader classLoader) throws Exception {
068                if (libDirs == null) 
069                        return null;
070        
071                List<URL> urlList = new ArrayList<URL>();
072                List<String> libDirArr = Arrays.asList(libDirs.split(";"));
073                for(String libDir : libDirArr){
074                File jars = new File(libDir);
075                if(!jars.exists())
076                    continue;
077                
078                if(jars.isDirectory()){    
079                        List<String> list = findFiles(jars.getAbsolutePath(),".jar");
080                        for(String jarPath : list){
081                            urlList.add(new File(jarPath).toURL());
082                        }
083                }
084                if(jars.isFile()){
085                   boolean isJar = jars.getName().toLowerCase().endsWith(".jar");
086
087                   if(isJar) urlList.add(jars.toURL());
088                }
089                }
090
091                URL[] urls = urlList.toArray(new URL[]{});
092                
093                URLClassLoader cl = new URLClassLoader(urls,classLoader);
094                return cl;
095        }
096        
097    public static List<String> findFiles(String dir,String ext) throws IOException {
098        
099        if(!new File(dir).exists()) return new ArrayList<String>();
100        
101        List<Path> paths = Files.walk(Paths.get(dir))
102                .filter(Files::isRegularFile)
103                .filter(path -> path.toString().toLowerCase().endsWith(ext))
104                .collect(Collectors.toList());
105                
106        return paths.stream()
107                      .map(path -> path.toAbsolutePath().toString())
108                      .collect(Collectors.toList());
109    }
110    
111    public static List<String> findFiles(String dir) throws IOException {
112        
113        if(!new File(dir).exists()) return new ArrayList<String>();
114        
115        List<Path> paths = Files.walk(Paths.get(dir))
116                .filter(Files::isRegularFile)
117                .collect(Collectors.toList());
118                
119        return paths.stream()
120                      .map(path -> path.toAbsolutePath().toString())
121                      .collect(Collectors.toList());                
122    }    
123    
124    public static List<String> findSubDirs(String dir) throws IOException {
125        
126        if(!new File(dir).exists()) return new ArrayList<String>();
127        
128        List<Path> paths = Files.walk(Paths.get(dir))
129                .filter(Files::isDirectory)
130                .collect(Collectors.toList());
131                
132        return paths.stream()
133                      .map(path -> path.toAbsolutePath().toString())
134                      .collect(Collectors.toList());                
135    }    
136
137        public static String getJarPath(Class clazz) {
138                try {
139                        return new File(clazz.getProtectionDomain().getCodeSource().getLocation().toURI())
140                                        .getParentFile().getPath().replaceAll("\\\\", "/");
141                } catch (Exception e) {
142                        Logger.systemError(CommonTools.class, e);
143                        return null;
144                }
145        }
146        
147        public static boolean isBlank(Object o) {
148                if (o == null)
149                        return true;
150
151                if (o.toString().trim().equals(""))
152                        return true;
153
154                return false;
155        }
156
157        public static File getSystemProperties(Class clazz, String envKey, String propFileName) {
158                try {
159                        File envFile = null;
160
161                        String envFilePath = System.getenv(envKey) == null ? System.getProperty(envKey) : System.getenv(envKey);
162                        if (envFilePath != null) {
163                                envFile = new File(envFilePath);
164                                if(!envFile.exists()){
165                                    Logger.systemDebug(CommonTools.class,"Missing %s",envFilePath);
166                                }
167                        }
168
169                        if (envFile != null && envFile.exists()) {
170                            Logger.systemDebug(CommonTools.class,"Found %s",envFile.getPath());
171                                return envFile;
172                        }
173                        
174                        String jarPath = new File(clazz.getProtectionDomain().getCodeSource().getLocation().toURI()).getParentFile().getPath();
175                        File jarConfigFile = new File(String.format("%s/%s", jarPath, propFileName));
176
177                        if(!jarConfigFile.exists()) {
178                            jarConfigFile = new File(String.format("%s/config/%s", jarPath, propFileName));
179                        }
180                        
181            if (jarConfigFile.exists()) {
182                Logger.systemDebug(CommonTools.class,"Found %s",jarConfigFile.getPath());
183                                return jarConfigFile;
184                        }                       
185                        
186                        String jarParentPath = new File(jarPath).getParentFile()
187                                        .getPath();
188                                        
189                        File jarParentConfigFile = new File(String.format("%s/%s", jarParentPath, propFileName));
190                        
191                        if(!jarParentConfigFile.exists()) {
192                            jarParentConfigFile = new File(String.format("%s/config/%s", jarParentPath, propFileName));
193                        }                       
194                        
195            if (jarParentConfigFile.exists()) {
196                Logger.systemDebug(CommonTools.class,"Found %s",jarParentConfigFile.getPath());
197                                return jarParentConfigFile;
198                        }
199                        
200                        URL classPathFileUrl = clazz.getResource(String.format("/%s", propFileName));
201                        if (classPathFileUrl != null) {
202                            Logger.systemDebug(CommonTools.class,"Found %s",classPathFileUrl.getPath());
203                                return new File(classPathFileUrl.toURI());
204                        }
205                        
206            classPathFileUrl = clazz.getResource(String.format("/config/%s", propFileName));
207                        if (classPathFileUrl != null) {
208                            Logger.systemDebug(CommonTools.class,"Found %s",classPathFileUrl.getPath());
209                                return new File(classPathFileUrl.toURI());
210                        }
211                        try{
212                        classPathFileUrl = clazz.getResource("/");
213                        if (classPathFileUrl != null) {
214                            String classParentPath = new File(classPathFileUrl.toURI()).getParent();
215                            if(classParentPath != null){
216                                    File classParentConfigFile = new File(String.format("%s/%s", classParentPath, propFileName));
217                                    
218                                    if(!classParentConfigFile.exists()) {
219                                        classParentConfigFile = new File(String.format("%s/config/%s", classParentPath, propFileName));
220                                    }
221                                    
222                                    if(!classParentConfigFile.exists()) {
223                                        Logger.systemDebug(CommonTools.class,"Found %s",classParentConfigFile.getPath());
224                                        return classParentConfigFile;
225                                    }
226                            }
227                        }       
228                        }catch(Exception e){
229                            Logger.systemDebug(CommonTools.class,"Missing class path.");
230                            Logger.systemDebug(CommonTools.class, e.getMessage(),e);
231                        }
232                } catch (Exception e) {
233            Logger.systemError(CommonTools.class, e);
234                }
235                Logger.systemDebug(CommonTools.class,"Missing %s",propFileName);
236                return null;
237        }
238
239        public synchronized static String getHostname() {
240            
241            if(HOSTNAME != null) return HOSTNAME;
242            
243            HOSTNAME = System.getenv("HOSTNAME");
244        if(HOSTNAME == null){
245                try {
246                        InetAddress addr = InetAddress.getLocalHost();
247                        HOSTNAME = addr.getHostName();
248                        System.setProperty("HOSTNAME",HOSTNAME);
249                        System.setProperty("hostname",HOSTNAME);
250                } catch (Exception e) {
251                        Logger.systemError(CommonTools.class, e);
252                }
253        }
254                return HOSTNAME;
255        }
256
257        public static String generateId(int len) {
258                final Character[] CHARS = new Character[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c',
259                                'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
260                                'y', 'z' };
261                StringBuffer id = new StringBuffer();
262                for (int i = 0; i < len; i++) {
263                        char c = CHARS[new Random().nextInt(CHARS.length)];
264                        id.append(c);
265                }
266                return id.toString();
267        }
268
269        public static <T> List<List<T>> averageAssign(List<T> source, int limit) {
270                if (null == source || source.isEmpty()) {
271                        return Collections.emptyList();
272                }
273                List<List<T>> result = new ArrayList<>();
274                int listCount = (source.size() - 1) / limit + 1;
275                int remaider = source.size() % listCount;
276                int number = source.size() / listCount;
277                int offset = 0;
278                for (int i = 0; i < listCount; i++) {
279                        List<T> value;
280                        if (remaider > 0) {
281                                value = source.subList(i * number + offset, (i + 1) * number + offset + 1);
282                                remaider--;
283                                offset++;
284                        } else {
285                                value = source.subList(i * number + offset, (i + 1) * number + offset);
286                        }
287                        result.add(value);
288                }
289                return result;
290        }
291        
292        public static String md5(String text) {
293                char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
294                                'A', 'B', 'C', 'D', 'E', 'F' };
295
296                try {
297                        byte[] btInput = text.getBytes(BaseFile.CHARSET);
298                        MessageDigest mdInst = MessageDigest.getInstance("MD5");
299                        mdInst.update(btInput);
300                        byte[] md = mdInst.digest();
301                        int j = md.length;
302                        char str[] = new char[j * 2];
303                        int k = 0;
304                        for (int i = 0; i < j; i++) {
305                                byte byte0 = md[i];
306                                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
307                                str[k++] = hexDigits[byte0 & 0xf];
308                        }
309                        return new String(str);
310                } catch (Exception e) {
311                    LoggerFactory.getLogger(CommonTools.class).error(e.getMessage(),e);
312                        return null;
313                }
314
315        }       
316
317}