Using Ja.Net to integrate Java and DotNet(c#): Assemblies in Java Source code

2009-09-29 00:41:00 |

How to use IKVM to integrate Java to DotNet

Using Ja.Net to integrate Java and DotNet(c#): Basic

Using Ja.Net to integrate Java and DotNet(c#): Class and Type

Using Ja.Net to integrate Java and DotNet(c#): More detailed basic issues

Using Ja.Net to integrate Java and DotNet(c#): Encoding and Properties

Using Ja.Net to integrate Java and DotNet(c#): Class implementing and inheriting

Using Ja.Net to integrate Java and DotNet(c#): Assemblies in Java Source code

Using Ja.Net to integrate Java and DotNet(c#): IO in Java and DotNet

In this chapter, I will describe some common issues about how to use System.Reflect.Assemble in Java Source code. This chapter covers the following topic:

  1. How to use Assemblies in Java
  2. Tips & Tricks to use Assemblies
  3. How to access resources embedded in assemblies.
  4. How to embed resources into assemblies which generated by bam.exe

Using assemblies in Java

In Java, we can use DotNet assemblies directly, the same as using some jar files.

But there are some difference between assemblies and jar files:

  1. If using jar files, the dependent jar files can not be used by Ja.Net, because the byte-code format was not match, for example, “a.jar” was using “dom4j.jar” as XML parser, the “dom4j.jar” will never be used by Ja.Net before re-compiled the source code using Ja.Net Javac.
  2. All assemblies can be used in Ja.net, no matter how and when compiled them.
  3. The source folders are quite different between Java and DotNet.
  4. No wrapper classes for java.io and System.IO

Here I wrote a helper class for converting and helping functionalities:

public class JaNetHelper
{
    private JaNetHelper()
    {
    }

    public static String getCurrentDirectory()
    {
        return System.IO.Directory.GetCurrentDirectory();
    }

    public static String getApplicationBaseDirectory()
    {
        return System.AppDomain.get_CurrentDomain().get_BaseDirectory();
    }

    public static String getMainModuleFileName()
    {
        return System.Diagnostics.Process.GetCurrentProcess().get_MainModule().get_FileName();
    }

    private static void log(String s)
    {
        System.out.println(s);
    }

    public static java.io.InputStream getResourceFromAssemble(System.Reflection.Assembly ass,String strResourceName)
        throws java.io.IOException
    {
        if(null == strResourceName)
        {
            return null;
        }
        //log("ASSS:"+ass.get_Location());
        System.IO.Stream stream = null;
        String strNewResouce = strResourceName;
        strNewResouce = strNewResouce.replaceAll("\\\\",".");
        strNewResouce = strNewResouce.replaceAll("\\/",".");
        if(strNewResouce.startsWith("."))
        {
            strNewResouce=strNewResouce.substring(1);
        }
        //log("get resource from " + strNewResouce);
        if(null != ass && null == stream)
        {
            stream = ass.GetManifestResourceStream(strNewResouce);
        }
        if(null == stream) //Who excuting me?
        {
            System.Reflection.Assembly assTest = System.Reflection.Assembly.GetExecutingAssembly();
            if(null != assTest)
            {
//                log("GetExecutingAssembly:" + assTest.get_Location() + ">>" + strNewResouce);
                stream = assTest.GetManifestResourceStream(strNewResouce);
            }
        }
        if(null == stream) //Who calling me?
        {
            System.Reflection.Assembly assTest = System.Reflection.Assembly.GetCallingAssembly();
            if(null != assTest)
            {
//                log("GetCallingAssembly:" + assTest.get_Location() + ">>" + strNewResouce);
                stream = assTest.GetManifestResourceStream(strNewResouce);
            }
        }
        if(null == stream) //Who running the main()
        {
            System.Reflection.Assembly assTest = System.Reflection.Assembly.GetEntryAssembly();
            if(null != assTest)
            {
//                log("GetEntryAssembly:" + assTest.get_Location() + ">>" + strNewResouce);
                stream = assTest.GetManifestResourceStream(strNewResouce);
            }
        }
        return dumpToStream(stream);
    }

    public static java.io.InputStream getResourceFromAssemble(Class cls,String strResourceName)
        throws java.io.IOException
    {
        if(null == strResourceName || strResourceName.trim().length() < 1)
        {
            return null;
        }
        strResourceName = strResourceName.trim();
        java.io.InputStream stream = getResourceFromAssemble(getAssembly(cls),strResourceName);
        if(null == stream && null != cls)
        {
            stream = getResourceFromAssemble(getAssembly(cls),cls.getPackage().getName()+"/" + strResourceName);
        }
        return stream;
    }

    public static java.io.InputStream getResourceFromAssemble(System.Type cls,String strResourceName)
        throws java.io.IOException
    {
        if(null == strResourceName || strResourceName.trim().length() < 1)
        {
            return null;
        }
        strResourceName = strResourceName.trim();
        java.io.InputStream stream = getResourceFromAssemble(getAssembly(cls),strResourceName);
        if(null == stream && null != cls)
        {
            stream = getResourceFromAssemble(getAssembly(cls),cls.get_Namespace()+"/" + strResourceName);
        }
        return stream;
    }

    public static System.Reflection.Assembly getAssembly(Class cls)
    {
        if(null == cls)
        {
            cls = JaNetHelper.class;
        }
        return System.Reflection.Assembly.GetAssembly(cls.toType());
    }

    public static System.Reflection.Assembly getAssembly(System.Type cls)
    {
        System.Reflection.Assembly ass = System.Reflection.Assembly.GetAssembly(null == cls ? (JaNetHelper.class.toType()) : cls);
        if(null == ass)
        {
            ass = System.Reflection.Assembly.GetExecutingAssembly();
        }
        if(null == ass)
        {
            ass = System.Reflection.Assembly.GetCallingAssembly();
        }
        if(null == ass)
        {
            ass = System.Reflection.Assembly.GetEntryAssembly();
        }
        return ass;
    }

    public static String getAssemblyLocation(System.Type cls)
    {
        System.Reflection.Assembly ass = getAssembly(cls);
        return null == ass ? null : ass.get_Location();
    }

    public static String getAssemblyLocation(Class cls)
    {
        System.Reflection.Assembly ass = getAssembly(cls);
        return null == ass ? null : ass.get_Location();
    }

    public static String getFileName(String strFolder,String strFileName)
    {
        return System.IO.Path.Combine(strFolder,strFileName);
    }

    public static String getFolderOfFile(String strFileName)
    {
        if(null == strFileName)
        {
            return strFileName;
        }
        System.IO.FileInfo f = new System.IO.FileInfo(strFileName);
        if(f.get_Exists())
        {
            return f.get_Directory().get_FullName();
        }
        else
        {
            return strFileName;
        }
    }

    public static String getApplicationExecutablePath()
    {
        String str = getMainModuleFileName();
        System.IO.FileInfo f = new System.IO.FileInfo(str);
        if(f.get_Exists())
        {
            return f.get_Directory().get_FullName();
        }
        else
        {
            return getApplicationBaseDirectory();
        }

    }

    public static Class classFromType(System.Type type)
        throws ClassNotFoundException
    {
        if(null == type)
        {
            return null;
        }
        else
        {
            return Class.forName(type.get_FullName());
        }
    }

    public static byte[] ConvertToByteArray(System.Byte[] bts)
    {
        if(null == bts)
        {
            return null;
        }
        else
        {
            byte[] ret = new byte[bts.length];
            for(int n = 0;n < bts.length;n++)
            {
                ret[n] = (byte) bts[n];
            }
            return ret;
        }
    }

    public static byte[] ConvertToByteArray(System.Byte[] bts,int nStart,int nLength)
    {
        if(null == bts)
        {
            return null;
        }
        else
        {
            byte[] ret = new byte[bts.length];
            int nLastIndex = nLength < 0 ? bts.length : Math.max(0,nStart) + nLength;
            for(int n = Math.max(0,nStart);n < nLastIndex;n++)
            {
                ret[n] = (byte) bts[n];
            }
            return ret;
        }
    }

    public static java.io.InputStream dumpToStream(System.IO.Stream stream)
        throws java.io.IOException
    {
        if(null == stream)
        {
            return null;
        }
        if(stream.get_CanRead() == false)
        {
            throw new java.io.IOException("The source stream can not be read");
        }
        int nLength = (int) stream.get_Length();
        byte[] bufDest = new byte[nLength];
        System.Byte[] buf = new System.Byte[1024];
        int nReadedLength = 0;
        int nr = 0;
        while((nr = stream.Read(buf,0,buf.length)) > 0)
        {
            for(int n = 0;n < nr && nReadedLength + n < bufDest.length;n++)
            {
                bufDest[nReadedLength + n] = (byte) buf[n];
            }
            nReadedLength += nr;
        }
        buf = null;
        return new java.io.ByteArrayInputStream(bufDest);
    }

    public static void writeToStream(System.IO.Stream stream
                                     ,java.io.OutputStream destination)
        throws java.io.IOException
    {
        writeToStream(stream,destination,0, -1);
    }

    public static void writeToStream(System.IO.Stream stream
                                     ,java.io.OutputStream destination
                                     ,int nStart,long nLength)
        throws java.io.IOException
    {
        if(null == stream || destination == null)
        {
            return;
        }
        if(stream.get_CanRead() == false)
        {
            throw new java.io.IOException("The source stream can not be read");
        }
        nStart = Math.max(0,nStart);
        if(nLength < 0)
        {
            nLength = Long.MAX_VALUE;
        }
        //Seek
        System.Byte[] buf = new System.Byte[1024];
        long nReadedLength = 0;
        int nr = 0;
        if(nStart > 0)
        {
            if(stream.get_CanSeek())
            {
                stream.Seek(nStart,System.IO.SeekOrigin.Begin);
            }
            else
                while(nReadedLength < nStart)
                {
                    long nNeed2Read = Math.max(0,Math.min(nStart - nReadedLength,buf.length));
                    nr = stream.Read(buf,0,(int) nNeed2Read);
                    if(nr <= 0)
                    {
                        break;
                    }
                    nReadedLength += nr;
                }
        }
        //Read
        nReadedLength = 0;
        while(nReadedLength < nLength)
        {
            long nNeed2Read = Math.max(0,Math.min(nLength - nReadedLength,buf.length));
            nr = stream.Read(buf,0,(int) nNeed2Read);
            if(nr <= 0)
            {
                break;
            }
            nReadedLength += nr;
            byte[] a = ConvertToByteArray(buf,0,nr);
            destination.write(a,0,nr);
        }
        destination.flush();
    }
}

Resources

Both Java and DotNet can package some resource files into the release package (Jars or assemblies), but unfortunately, Ja.Net could not package resource automatically, we have to package it by ourselves.

If we want to use the Java resource files and DotNet resource files in the same way, we should check what them have done first, here is a example:

  • Root folder of the source code is “d:\source”
  • Resource file is “d:\source\res\a.txt”
  • In Java, it will be packaged into a jar file keep the same folder “/res/a.txt”, and it could be access by name “/res/a.txt”.
  • In DotNet, it will be packaged into DLL file keep the same folder “/res/a.txt”, but the access string must be “[Default Namespace of current solution].res.a.txt”. Let’s assume the default namespace is “jeasonzhao”, the resource name is “jeasonzhao.res.a.txt”.

we are not going to discuss how to use “pure java” to access resources generated by DotNet, if we want to access resources from assemblies, the best way is using DotNet classes to handle it as the preceding source code shown.

Notes that Ja.Net would not handle any resource file when calling “javac” to compile source code, only “bam.exe” generates resource from the source folder.

As I mentioned, the default behavior of Ja.Net compiler package the resources with a “full path name”, it is not portable, we have to do some modification on bam.exe, I have wrote a separated article taking about it:

Using Ja.Net to integrate Java and DotNet(c#)- Bam.exe bugs fixed


Jeason Zhao (沈胜衣,斛律光) ------雪饮再现,一个人的江湖
我知道我是谁,我是沈胜衣,默默的活着,就像空气。

Add comment




biuquote
  • Comment
  • Preview
Loading