Bug? rename library OkHttp.jar to okhttp.jar (about classpath on linux)

icefairy333

Active Member
Licensed User
Longtime User
after compile the project with #MergeLibraries: False ,the ide show
B4X:
The following libraries should be distributed in the libs folder:
 jCore.jar jOkHttpUtils2.jar jServer.jar jfx.jar okhttp.jar jstringutils.jar json.jar okhttp-3.5.0.jar okio-1.11.0.jar jetty_b4j.jar c3p0-0.9.5.2.jar c3p0-oracle-thin-extras-0.9.5.2.jar mchange-commons-java-0.2.11.jar
but the real filename in the library directory is "OkHttp.jar",so with Linux it will cause classNotFound exception,please modify the name to lowercase in the library directory before publish B4J , Thank you.
I use this code to copy the jar auto:
B4X:
'WebPlus Handler自动扫描器
Sub Class_Globals
    Private jr As jarUtils
    Type actionts(ak As String,sth As Boolean)
End Sub

'init and add all handler(which "handler" in names),you should defined a var named "actionkey" in handler else I will use the name before "handler"
'add:public sth as boolean=true 'when you want the handler to be SingleThreadHandler
Public Sub Initialize(ser As Server)
    jr.Initialize
    Dim clsList As List
    Dim srcpath As String=jr.SrcPath
    If srcpath.ToLowerCase.EndsWith(".jar") Then
        'find class from jar
        clsList=jr.GetAllClassesNamesFromJar(jr.pkgName,srcpath)
    Else
        clsList=jr.GetAllClassesNames
    End If
   
    If clsList.IsInitialized And clsList.Size>0 Then
        For Each k As String In clsList
            If k.IndexOf("handler")>-1 And k.IndexOf("$")=-1 Then
                Dim actKey As actionts=GetActionKeyTS(k)
                If actKey.ak.Length<1 Then
                    actKey.ak="/"&k.Replace("handler","")
                    G.mLog("add handler:"&actKey.ak&" with default handler:"&k)
                Else
                    G.mLog("add handler:"&actKey.ak&" with handler:"&k)
                End If
               
                ser.AddHandler(actKey.ak,k,actKey.sth)
            End If
        Next
    Else
        Log("clsList not init or MergeLibraries is set to true,if you want to using this utils you should set MergeLibraries to false")
    End If
'    #if release
    printStartCmdLine
'    #End If
   
End Sub
Private Sub printStartCmdLine
    File.WriteString(File.DirApp,"webplus.pid",jr.GetCurrentPid)
    If File.Exists(File.DirApp,"webplusstarter.bat")=False Then
        '如果启动脚本不存在则进入生成环节
        Dim srcpath As String=jr.SrcPath.ToLowerCase
        Dim sb,sblinux As StringBuilder
        Dim cplst As List
        sb.Initialize
        sblinux.Initialize
        sblinux.Append("echo startingProject").Append(CRLF)
        sb.Append($"@echo off
color 0a
title "webplus Project Starter"
cd /d %~dp0
set curpath=%cd%
echo "enter work dir:%curpath%"
echo "kill java.exe"
for /f "tokens=1" %%i in (webplus.pid) do taskkill /f /pid %%i
"$)
        Dim jarname As String=getJarFilenameFromOBjects
        Log("jarname:"&jarname)
        If srcpath.EndsWith(".jar") Then
            sb.Append("java.exe -jar "&jarname).Append(CRLF)
        Else
            Dim cpstr As String=GetSystemProperty("java.class.path","")
            Dim enc As String=GetSystemProperty("file.encoding","unknow")
            sb.Append("java.exe -Dfile.encoding=").Append(enc).Append(" -cp ")
            Try
                If cpstr.Length>0 Then
                    cplst=Regex.Split(";",cpstr)
                    If cplst.IsInitialized=False Then cplst.Initialize
                    For Each s As String In cplst
                        If s.Length>0 Then
                            sb.Append($""${getFilePathinLibs(getRealFileName(s))}";"$)
                        End If
                    Next
                    sb=sb.Remove(sb.Length-1,sb.Length)
                    sb.Append(" -jar "&getJarFilenameFromOBjects).Append(CRLF)
                   
'                    sb.Append(" "&jr.pkgName&".main").Append(CRLF)
                End If
               
            Catch
                Log(LastException)
            End Try
            Try
                If File.Exists(File.DirApp,"libs")=False Then File.MakeDir(File.DirApp,"libs")
                Dim libsdir As String=File.Combine(File.DirApp,"libs")
                For Each s As String In cplst
                    If File.Exists("",s) And File.IsDirectory("",s)=False And s.ToLowerCase.EndsWith(".jar") Then
                        '如果文件存在且不是目录且是jar文件
                        File.Copy("",s,libsdir,getRealFileName(s))
                    End If
                Next
            Catch
                Log("copy libs error:"&LastException)
            End Try
           
        End If
        sb.Append("echo ""webplus project run completed ok""").Append(CRLF)
        Dim tw As TextWriter
        tw.Initialize2(File.OpenOutput(File.DirApp,"webplusstarter.bat",False),"GBK")
        tw.WriteLine(sb.ToString)
        tw.Flush
        tw.Close
        sblinux.Append("java -jar "&getJarFilenameFromOBjects).Append(" &").Append(CRLF)
        sblinux.Append("echo project started").Append(CRLF)
        tw.Initialize2(File.OpenOutput(File.DirApp,"webplusstarter.sh",False),"UTF-8")
        tw.WriteLine(sblinux.ToString)
        tw.Flush
        tw.Close
        Log("项目启动脚本:"&File.Combine(File.DirApp,"webplusstarter.bat"))
    End If
   
   
   
End Sub
Sub getRealFileName(s As String) As String
    Dim path As String=File.GetFileParent(s)
    Dim fn As String=File.GetName(s)
    If path.Length>0 Then
        Dim lst As List=File.ListFiles(path)
        For Each s As String In lst
            If s.EqualsIgnoreCase(fn) Then
                Return s
            End If
        Next
    End If
    Return ""
End Sub
Private Sub getJarFilenameFromOBjects As String
    Dim lst As List
    #if release
    lst=File.ListFiles(File.DirApp)
    #Else
    lst=File.ListFiles(File.Combine(File.DirApp,"../"))
    #End If
   
    For Each s As String In lst
        #if release
        If s.ToLowerCase.EndsWith(".jar") Then
            Return File.GetName(s)
        End If
        #Else
        If s.ToLowerCase.EndsWith(".b4j") Then
            Return File.GetName(s).Replace(".b4j",".jar")
        End If
        #End If
       
    Next
End Sub
Private Sub getFilePathinLibs(s As String) As String
    If s.Length>0 Then Return File.Combine(File.Combine("%curpath%","libs"),File.GetName(s)) Else Return ""
End Sub
Private Sub GetActionKeyTS(clsName As String) As actionts
    Dim jo As JavaObject
    Dim ret As actionts
    ret.Initialize
    Dim pkg As String=jr.pkgName&"."&clsName
    Try
        jo=jo.InitializeNewInstance(pkg,Null)
        #if release
        jo.RunMethod("_class_globals",Null) 'release mode
        #else
            jo.RunMethod("_class_globals",Array As Object(Null)) 'debug mode
        #End If
       
        ret.ak=jo.GetField("_actionkey")
    Catch
'        Log(LastException)
        ret.ak=""
    End Try
    Try
        ret.sth=jo.GetField("_sth")
    Catch
        ret.sth=False
    End Try
    Return ret
End Sub

file jarUtils
B4X:
'Class module

Sub Class_Globals

    Private jo As JavaObject

End Sub


'Initializes the object. You can add parameters to this method if needed.

Public Sub Initialize

    jo=Me

End Sub

'return a list includes all classname

Public Sub GetAllClassesNames As List

    Dim clsList As List=GetAllClasses(getpkgName)

    For i=0 To clsList.Size-1

        Dim clsName As String=clsList.Get(i)

        clsName=clsName.SubString2(clsName.LastIndexOf(".")+1,clsName.Length)

        clsName=clsName.Replace("class ","")

        clsList.Set(i,clsName)

    Next

    Return clsList

End Sub

Public Sub GetAllClassesNamesFromJar(pkgName As String,jarpath As String) As List

    Dim clsList As List=GetAllClassesFromJar(pkgName,jarpath)

    For i=0 To clsList.Size-1

        Dim clsName As String=clsList.Get(i)

        clsName=clsName.SubString2(clsName.LastIndexOf(".")+1,clsName.Length)

        clsName=clsName.Replace("class ","")

        clsList.Set(i,clsName)

    Next

    Return clsList

End Sub


'map:type,name

Public Sub getClassAllProperties(cls As Object) As List

    Dim lst As List

    jo=Me

    lst=jo.RunMethod("getClassAllProperties",Array As Object(cls))

    Return lst

End Sub

'map:type,name

Public Sub getClassPublicProperties(cls As Object) As List

    Dim lst As List

    jo=Me

    lst=jo.RunMethod("getClassPublicProperties",Array As Object(cls))

    Return lst

End Sub

Public Sub getClassMethods(cls As Object) As List

    Dim lst As List

    jo=Me

    lst=jo.RunMethod("getClassMethods",Array As Object(cls))

    Return lst

End Sub

'you must load at least one class before using this method

Public Sub GetAllClasses(pkgname As String) As List

    Dim lst As List

    jo=Me

    lst=jo.RunMethod("getClasses",Array As Object(pkgname))

    If lst.IsInitialized=False Or lst.Size=0 Then

        lst.Initialize

        Log("class list empty")

    End If

    Return lst

End Sub

Public Sub GetAllClassesFromJar(pkgname As String,path As String) As JavaObject

    Dim lst As List

    jo=Me

    lst=jo.RunMethod("getClassesFromJar",Array As Object(pkgname,path))

    If lst.IsInitialized=False Or lst.Size=0 Then

        lst.Initialize

        Log("class list empty")

    End If

    Return lst

End Sub

Public Sub getThisClass As JavaObject

    jo=Me

    Return jo.RunMethod("getClass",Null)

End Sub

Public Sub getNativeClass(b4xClass As Object) As JavaObject

    jo=b4xClass

    Return jo.RunMethod("getClass",Null)

End Sub

Public Sub getClassByName(fullname As String) As JavaObject

    jo=Me

    Return jo.RunMethod("getClassByName",Array As String(fullname))

End Sub

'return the jar file path when MergeLibraries=true

'return the directory path when MergeLibraries=false or debug mode

'path based on system(AbsolutePath)

Public Sub getSrcPath As String

    jo=Me

    Return jo.RunMethod("getSrcPath",Null)

End Sub

'get package name of this app

Public Sub getpkgName As String

    jo=Me

    Dim pkg As String=jo.RunMethod("getpkgName",Array As Object(getThisClass))

    Return pkg

End Sub

Public Sub GetCurrentPid As Int

    Dim jo As JavaObject

    jo=jo.InitializeStatic("java.lang.management.ManagementFactory").RunMethodJO("getRuntimeMXBean",Null)

    Dim name As String=jo.RunMethod("getName",Null)

    Dim ns() As String=Regex.Split("@",name)

    Return ns(0)

End Sub


#If java

import java.io.File;

import java.lang.reflect.Field; 

import java.lang.reflect.Method;

import java.io.FileFilter;

import java.io.IOException;

import java.net.JarURLConnection;

import java.net.URL;

import java.net.URLDecoder;

import java.util.ArrayList;

import java.util.Enumeration;

import java.util.LinkedHashSet;

import java.util.List;

import java.util.Set;

import java.util.jar.JarEntry;

import java.util.jar.JarFile;



import anywheresoftware.b4a.BA;

import anywheresoftware.b4a.keywords.Common;

import anywheresoftware.b4a.objects.collections.Map;


    public static ArrayList<Map.MyMap> getClassAllProperties(Class clazz) { 

        Field[] fields = clazz.getDeclaredFields(); 

        ArrayList<Map.MyMap> lst=new ArrayList<Map.MyMap>();

        for (int i=0; i<fields.length; i++) { 

            Field field=fields[i];

            lst.add(Common.createMap(new Object[]{(Object)"type",field.getType().getSimpleName(),(Object)"name",field.getName()}).getObject()); 

        } 

        return lst; 

    } 

    public static ArrayList<Map.MyMap> getClassPublicProperties(Class clazz) { 

        Field[] fields = clazz.getFields(); 

        ArrayList<Map.MyMap> lst=new ArrayList<Map.MyMap>();

        for (int i=0; i<fields.length; i++) { 

            Field field=fields[i];

            lst.add(Common.createMap(new Object[]{(Object)"type",field.getType().getSimpleName(),(Object)"name",field.getName()}).getObject()); 

        } 

        return lst; 

    } 

    public String getSrcPath() {

        URL url=getClass().getProtectionDomain().getCodeSource().getLocation();

        String path="";

        try {

            path=URLDecoder.decode(url.getPath(), "utf-8");

            File file=new File(path);

            path=file.getAbsolutePath();

        } catch (Exception e) {

            // TODO: handle exception

        }

        return path;


    }

    public List<Method> getClassMethods(Class c){

        Method m[] = c.getMethods(); // 取得全部的方法

        List <Method> result = new ArrayList<Method>(); 

        if(m!=null){

            for (int i=0;i<m.length;i++){

                result.add(m[i]);

            }

        }

        return result;

    }

    public String getpkgName(Class c){

        return c.getPackage().getName();

    }

    public Class<?> getClassByName(String n){

        try { 

            //添加到classes 

            return Class.forName(n);

        } catch (ClassNotFoundException e) { 

            e.printStackTrace(); 

        } 

        return null;

    }

/**

* 类相关的工具类

*

* @author <a href="mailto:[email protected]">ohergal</a>

*

*/

    /**

     * 取得某个接口下所有实现这个接口的类

     * */

    public List<Class> getAllClassByInterface(Class c) {

            List<Class>  returnClassList = null;


            if(c.isInterface()) {

                // 获取当前的包名

                String packageName = c.getPackage().getName();

                // 获取当前包下以及子包下所以的类

                List<Class<?>> allClass = getClasses(packageName);

                if(allClass != null) {

                    returnClassList = new ArrayList<Class>();

                    for(Class classes : allClass) {

                        // 判断是否是同一个接口

                        if(c.isAssignableFrom(classes)) {

                            // 本身不加入进去

                            if(!c.equals(classes)) {

                                returnClassList.add(classes);       

                            }

                        }

                    }

                }

            }


            return returnClassList;

        }



    /*

     * 取得某一类所在包的所有类名 不含迭代

     */

    public String[] getPackageAllClassName(String classLocation, String packageName){

        //将packageName分解

        String[] packagePathSplit = packageName.split("[.]");

        String realClassLocation = classLocation;

        int packageLength = packagePathSplit.length;

        for(int i = 0; i< packageLength; i++){

            realClassLocation = realClassLocation + File.separator+packagePathSplit[i];

        }

        File packeageDir = new File(realClassLocation);

        if(packeageDir.isDirectory()){

            String[] allClassName = packeageDir.list();

            return allClassName;

        }

        return null;

    }


    /**

     * 从包package中获取所有的Class

     * @param pack

     * @return

     */

    public List<Class<?>> getClasses(String packageName){


        //第一个class类的集合

        List<Class<?>> classes = new ArrayList<Class<?>>();

        //是否循环迭代

        boolean recursive = true;

        //获取包的名字 并进行替换

        String packageDirName = packageName.replace('.', '/');

        //定义一个枚举的集合 并进行循环来处理这个目录下的things

        Enumeration<URL> dirs;

        try {

            dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);

            //循环迭代下去

            while (dirs.hasMoreElements()){

                //获取下一个元素

                URL url = dirs.nextElement();

                //得到协议的名称

                String protocol = url.getProtocol();

                //如果是以文件的形式保存在服务器上

                if ("file".equals(protocol)) {

                    //获取包的物理路径

                    String filePath = URLDecoder.decode(url.getFile(), "UTF-8");

                    //以文件的方式扫描整个包下的文件 并添加到集合中

                    findAndAddClassesInPackageByFile(packageName, filePath, recursive, classes);

                } else if ("jar".equals(protocol)){

                    //如果是jar包文件

                    //定义一个JarFile

                    JarFile jar;

                    try {

                        //获取jar

                        jar = ((JarURLConnection) url.openConnection()).getJarFile();

                        //从此jar包 得到一个枚举类

                        Enumeration<JarEntry> entries = jar.entries();

                        //同样的进行循环迭代

                        while (entries.hasMoreElements()) {

                            //获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件

                            JarEntry entry = entries.nextElement();

                            String name = entry.getName();

                            //如果是以/开头的

                            if (name.charAt(0) == '/') {

                                //获取后面的字符串

                                name = name.substring(1);

                            }

                            //如果前半部分和定义的包名相同

                            if (name.startsWith(packageDirName)) {

                                int idx = name.lastIndexOf('/');

                                //如果以"/"结尾 是一个包

                                if (idx != -1) {

                                    //获取包名 把"/"替换成"."

                                    packageName = name.substring(0, idx).replace('/', '.');

                                }

                                //如果可以迭代下去 并且是一个包

                                if ((idx != -1) || recursive){

                                    //如果是一个.class文件 而且不是目录

                                    if (name.endsWith(".class") && !entry.isDirectory()) {

                                        //去掉后面的".class" 获取真正的类名

                                        String className = name.substring(packageName.length() + 1, name.length() - 6);

                                        try {

                                            //添加到classes

                                            classes.add(Class.forName(packageName + '.' + className));

                                        } catch (ClassNotFoundException e) {

                                            e.printStackTrace();

                                        }

                                      }

                                }

                            }

                        }

                    } catch (IOException e) {

                        e.printStackTrace();

                    }

                }

            }

        } catch (IOException e) {

            e.printStackTrace();

        }


        return classes;

    }

    public List<Class<?>> getClassesFromJar(String packageName,String path){

        //第一个class类的集合

        JarFile jar;

        String packageDirName = packageName.replace('.', '/');

        ArrayList<Class<?>> classes=new ArrayList<>();

        boolean recursive=true;

        try {

            //获取jar

            jar =new JarFile(path);

            //从此jar包 得到一个枚举类

            Enumeration<JarEntry> entries = jar.entries();

            //同样的进行循环迭代

            while (entries.hasMoreElements()) {

                //获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件

                JarEntry entry = entries.nextElement();

                String name = entry.getName();

                //如果是以/开头的

                if (name.charAt(0) == '/') {

                    //获取后面的字符串

                    name = name.substring(1);

                }

                //如果前半部分和定义的包名相同

                if (name.startsWith(packageDirName)) {

                    int idx = name.lastIndexOf('/');

                    //如果以"/"结尾 是一个包

                    if (idx != -1) {

                        //获取包名 把"/"替换成"."

                        packageName = name.substring(0, idx).replace('/', '.');

                    }

                    //如果可以迭代下去 并且是一个包

                    if ((idx != -1) || recursive){

                        //如果是一个.class文件 而且不是目录

                        if (name.endsWith(".class") && !entry.isDirectory()) {

                            //去掉后面的".class" 获取真正的类名

                            String className = name.substring(packageName.length() + 1, name.length() - 6);

                            try {

                                //添加到classes

                                classes.add(Class.forName(packageName + '.' + className));

                            } catch (ClassNotFoundException e) {

                                e.printStackTrace();

                            }

                          }

                    }

                }

            }

        } catch (IOException e) {

            e.printStackTrace();

        }

        return classes;

    }

    /**

     * 以文件的形式来获取包下的所有Class

     * @param packageName

     * @param packagePath

     * @param recursive

     * @param classes

     */

    public void findAndAddClassesInPackageByFile(String packageName, String packagePath, final boolean recursive, List<Class<?>> classes){

        //获取此包的目录 建立一个File

        File dir = new File(packagePath);

        //如果不存在或者 也不是目录就直接返回

        if (!dir.exists() || !dir.isDirectory()) {

            return;

        }

        //如果存在 就获取包下的所有文件 包括目录

        File[] dirfiles = dir.listFiles(new FileFilter() {

        //自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件)

              public boolean accept(File file) {

                return (recursive && file.isDirectory()) || (file.getName().endsWith(".class"));

              }

            });

        //循环所有文件

        for (File file : dirfiles) {

            //如果是目录 则继续扫描

            if (file.isDirectory()) {

                findAndAddClassesInPackageByFile(packageName + "." + file.getName(),

                                      file.getAbsolutePath(),

                                      recursive,

                                      classes);

            }

            else {

                //如果是java类文件 去掉后面的.class 只留下类名

                String className = file.getName().substring(0, file.getName().length() - 6);

                try {

                    //添加到集合中去

                    classes.add(Class.forName(packageName + '.' + className));

                } catch (ClassNotFoundException e) {

                    e.printStackTrace();

                }

            }

        }

    }


#End If
 
Last edited:
Top