Beispiel #1
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public ClassFile(BinaryReader reader)
        {
            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }

            magic_number = EndianSwap.SwapUInt32(reader.ReadUInt32());

            if (magic_number != 0xCAFEBABE)
            {
                throw new InvalidOperationException(string.Format("Unexpected magic number. {0} != 0xCAFEBABE", magic_number.ToString("X")));
            }

            minor_version = EndianSwap.SwapUInt16(reader.ReadUInt16());

            major_version = EndianSwap.SwapUInt16(reader.ReadUInt16());

            constant_pool_count = EndianSwap.SwapUInt16(reader.ReadUInt16()); // constant_pool_count item is equal to the number of entries in the constant_pool table plus one.

            constant_pool = new ConstantInfo [constant_pool_count];

            for (ushort i = 1; i < constant_pool_count; ++i)
            {
                ConstantInfo.Tags tag = (ConstantInfo.Tags)Enum.ToObject(typeof(ConstantInfo.Tags), reader.ReadByte());

                switch (tag)
                {
                case ConstantInfo.Tags.CONSTANT_Class: constant_pool [i] = new ConstantClassInfo(); break;

                case ConstantInfo.Tags.CONSTANT_FieldRef: constant_pool [i] = new ConstantFieldRefInfo(); break;

                case ConstantInfo.Tags.CONSTANT_MethodRef: constant_pool [i] = new ConstantMethodRefInfo(); break;

                case ConstantInfo.Tags.CONSTANT_InterfaceMethodRef: constant_pool [i] = new ConstantInterfaceMethodRefInfo(); break;

                case ConstantInfo.Tags.CONSTANT_String: constant_pool [i] = new ConstantStringInfo(); break;

                case ConstantInfo.Tags.CONSTANT_Integer: constant_pool [i] = new ConstantIntegerInfo(); break;

                case ConstantInfo.Tags.CONSTANT_Float: constant_pool [i] = new ConstantFloatInfo(); break;

                case ConstantInfo.Tags.CONSTANT_Long: constant_pool [i] = new ConstantLongInfo(); break;

                case ConstantInfo.Tags.CONSTANT_Double: constant_pool [i] = new ConstantDoubleInfo(); break;

                case ConstantInfo.Tags.CONSTANT_NameAndType: constant_pool [i] = new ConstantNameAndTypeInfo(); break;

                case ConstantInfo.Tags.CONSTANT_Utf8: constant_pool [i] = new ConstantUtf8Info(); break;

                case ConstantInfo.Tags.CONSTANT_MethodHandle: constant_pool [i] = new ConstantMethodHandleInfo(); break;

                case ConstantInfo.Tags.CONSTANT_MethodType: constant_pool [i] = new ConstantMethodTypeInfo(); break;

                case ConstantInfo.Tags.CONSTANT_InvokeDynamic: constant_pool [i] = new ConstantInvokeDynamicInfo(); break;

                default: throw new InvalidOperationException("Unexpected constant tag: " + tag.ToString()); break;
                }

                constant_pool [i].Parse(ref reader);

                switch (tag)
                {
                case ConstantInfo.Tags.CONSTANT_Long:
                case ConstantInfo.Tags.CONSTANT_Double:
                {
                    //
                    // If a CONSTANT_Long_info or CONSTANT_Double_info structure is the item in the constant_pool table at
                    // index n, then the next usable item in the pool is located at index n+2.
                    //

                    ++i;

                    break;
                }
                }
            }

            access_flags = EndianSwap.SwapUInt16(reader.ReadUInt16());

            this_class = EndianSwap.SwapUInt16(reader.ReadUInt16());

            super_class = EndianSwap.SwapUInt16(reader.ReadUInt16());

            interfaces_count = EndianSwap.SwapUInt16(reader.ReadUInt16());

            interfaces = new ushort [interfaces_count];

            for (ushort i = 0; i < interfaces_count; ++i)
            {
                interfaces [i] = EndianSwap.SwapUInt16(reader.ReadUInt16());
            }

            fields_count = EndianSwap.SwapUInt16(reader.ReadUInt16());

            fields = new FieldInfo [fields_count];

            for (ushort i = 0; i < fields_count; ++i)
            {
                fields [i] = new FieldInfo();

                fields [i].Parse(ref reader);
            }

            methods_count = EndianSwap.SwapUInt16(reader.ReadUInt16());

            methods = new MethodInfo [methods_count];

            for (ushort i = 0; i < methods_count; ++i)
            {
                methods [i] = new MethodInfo();

                methods [i].Parse(ref reader);
            }

            attributes_count = EndianSwap.SwapUInt16(reader.ReadUInt16());

            attributes = new AttributeInfo [attributes_count];

            for (ushort i = 0; i < attributes_count; ++i)
            {
                attributes [i] = new AttributeInfo();

                attributes [i].Parse(ref reader);
            }
        }
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    public ClassFile (BinaryReader reader)
    {
      if (reader == null)
      {
        throw new ArgumentNullException ("reader");
      }

      magic_number = EndianSwap.SwapUInt32 (reader.ReadUInt32 ());

      if (magic_number != 0xCAFEBABE)
      {
        throw new InvalidOperationException (string.Format ("Unexpected magic number. {0} != 0xCAFEBABE", magic_number.ToString ("X")));
      }

      minor_version = EndianSwap.SwapUInt16 (reader.ReadUInt16 ());

      major_version = EndianSwap.SwapUInt16 (reader.ReadUInt16 ());

      constant_pool_count = EndianSwap.SwapUInt16 (reader.ReadUInt16 ()); // constant_pool_count item is equal to the number of entries in the constant_pool table plus one.

      constant_pool = new ConstantInfo [constant_pool_count];

      for (ushort i = 1; i < constant_pool_count; ++i)
      {
        ConstantInfo.Tags tag = (ConstantInfo.Tags) Enum.ToObject (typeof (ConstantInfo.Tags), reader.ReadByte ());

        switch (tag)
        {
          case ConstantInfo.Tags.CONSTANT_Class: constant_pool [i] = new ConstantClassInfo (); break;
          case ConstantInfo.Tags.CONSTANT_FieldRef: constant_pool [i] = new ConstantFieldRefInfo (); break;
          case ConstantInfo.Tags.CONSTANT_MethodRef: constant_pool [i] = new ConstantMethodRefInfo (); break;
          case ConstantInfo.Tags.CONSTANT_InterfaceMethodRef: constant_pool [i] = new ConstantInterfaceMethodRefInfo (); break;
          case ConstantInfo.Tags.CONSTANT_String: constant_pool [i] = new ConstantStringInfo (); break;
          case ConstantInfo.Tags.CONSTANT_Integer: constant_pool [i] = new ConstantIntegerInfo (); break;
          case ConstantInfo.Tags.CONSTANT_Float: constant_pool [i] = new ConstantFloatInfo (); break;
          case ConstantInfo.Tags.CONSTANT_Long: constant_pool [i] = new ConstantLongInfo (); break;
          case ConstantInfo.Tags.CONSTANT_Double: constant_pool [i] = new ConstantDoubleInfo (); break;
          case ConstantInfo.Tags.CONSTANT_NameAndType: constant_pool [i] = new ConstantNameAndTypeInfo (); break;
          case ConstantInfo.Tags.CONSTANT_Utf8: constant_pool [i] = new ConstantUtf8Info (); break;
          case ConstantInfo.Tags.CONSTANT_MethodHandle: constant_pool [i] = new ConstantMethodHandleInfo (); break;
          case ConstantInfo.Tags.CONSTANT_MethodType: constant_pool [i] = new ConstantMethodTypeInfo (); break;
          case ConstantInfo.Tags.CONSTANT_InvokeDynamic: constant_pool [i] = new ConstantInvokeDynamicInfo (); break;
          default: throw new InvalidOperationException ("Unexpected constant tag: " + tag.ToString ()); break;
        }

        constant_pool [i].Parse (ref reader);

        switch (tag)
        {
          case ConstantInfo.Tags.CONSTANT_Long:
          case ConstantInfo.Tags.CONSTANT_Double:
          {
            // 
            // If a CONSTANT_Long_info or CONSTANT_Double_info structure is the item in the constant_pool table at 
            // index n, then the next usable item in the pool is located at index n+2.
            // 

            ++i;

            break;
          }
        }
      }

      access_flags = EndianSwap.SwapUInt16 (reader.ReadUInt16 ());

      this_class = EndianSwap.SwapUInt16 (reader.ReadUInt16 ());

      super_class = EndianSwap.SwapUInt16 (reader.ReadUInt16 ());

      interfaces_count = EndianSwap.SwapUInt16 (reader.ReadUInt16 ());

      interfaces = new ushort [interfaces_count];

      for (ushort i = 0; i < interfaces_count; ++i)
      {
        interfaces [i] = EndianSwap.SwapUInt16 (reader.ReadUInt16 ());
      }

      fields_count = EndianSwap.SwapUInt16 (reader.ReadUInt16 ());

      fields = new FieldInfo [fields_count];

      for (ushort i = 0; i < fields_count; ++i)
      {
        fields [i] = new FieldInfo ();

        fields [i].Parse (ref reader);
      }

      methods_count = EndianSwap.SwapUInt16 (reader.ReadUInt16 ());

      methods = new MethodInfo [methods_count];

      for (ushort i = 0; i < methods_count; ++i)
      {
        methods [i] = new MethodInfo ();

        methods [i].Parse (ref reader);
      }

      attributes_count = EndianSwap.SwapUInt16 (reader.ReadUInt16 ());

      attributes = new AttributeInfo [attributes_count];

      for (ushort i = 0; i < attributes_count; ++i)
      {
        attributes [i] = new AttributeInfo ();

        attributes [i].Parse (ref reader);
      }
    }
Beispiel #3
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        static int Main(string [] args)
        {
            int returnCode = 0;

            try
            {
                ProcessArguments(args);

                ValidateArguments();

                string workingDirectory = Path.Combine(Path.GetTempPath(), "app-java-builder", Guid.NewGuid().ToString());

                if (Directory.Exists(workingDirectory))
                {
                    Directory.Delete(workingDirectory);
                }

                Directory.CreateDirectory(workingDirectory);

                //
                // Run the javac tool to compile any specified files (and indirectory those referenced by source paths).
                //

                HashSet <string> compilerFilesRead = new HashSet <string> ();

                HashSet <string> compilerFilesWritten = new HashSet <string> ();

                {
                    int exitCode = -1;

                    string executable = Path.Combine(s_jdkHomePath, "bin", "javac.exe");

                    string arguments = string.Join(" ", s_compilerArguments.ToArray());

#if true
                    string sourcesFile = Path.Combine(workingDirectory, "sources.txt");

                    using (StreamWriter writer = new StreamWriter(sourcesFile, false))
                    {
                        foreach (string file in s_compilerInputJavaFiles)
                        {
                            writer.WriteLine(file);
                        }

                        writer.Close();
                    }

                    string fileArgs = arguments += " @" + sourcesFile;

                    {
#else
                    foreach (string file in s_compilerInputJavaFiles)
                    {
                        string fileArgs = arguments + " " + file;
#endif
                        using (Process process = CreateSynchronousProcess(executable, fileArgs, string.Empty))
                        {
                            process.OutputDataReceived += (sender, e) =>
                            {
                                if (e.Data != null)
                                {
                                    ProcessJavacOutput(e.Data, ref compilerFilesRead, ref compilerFilesWritten);
                                }
                            };

                            process.ErrorDataReceived += (sender, e) =>
                            {
                                if (e.Data != null)
                                {
                                    ProcessJavacOutput(e.Data, ref compilerFilesRead, ref compilerFilesWritten);
                                }
                            };

                            if (process.Start())
                            {
                                process.BeginOutputReadLine();

                                process.BeginErrorReadLine();

                                process.WaitForExit();

                                exitCode = process.ExitCode;
                            }

                            if (exitCode != 0)
                            {
                                throw new InvalidOperationException(process.StartInfo.FileName + " failed with exit code: " + exitCode);
                            }
                        }
                    }

                    //
                    // Export dependency files alongside any exported output.
                    //

                    if (exitCode == 0)
                    {
                        foreach (string file in compilerFilesWritten)
                        {
                            using (StreamWriter writer = new StreamWriter(file + ".d", false, Encoding.Unicode))
                            {
                                writer.WriteLine(string.Format("{0}: \\", ConvertPathWindowsToGccDependency(file)));

                                foreach (string dependency in compilerFilesRead)
                                {
                                    writer.WriteLine(string.Format("  {0} \\", ConvertPathWindowsToGccDependency(dependency)));
                                }

                                writer.Close();
                            }
                        }
                    }

#if true
                    File.Delete(sourcesFile);
#endif
                }

                //
                // Copy exported class files to a temporary directory to ensure packages are handled properly (and old classes are cleaned).
                //

                {
                    long failedParsedClassFiles = 0;

                    foreach (string classFile in compilerFilesWritten) // Parallel.ForEach (compilerFilesWritten, classFile =>
                    {
#if DEBUG
                        Debug.WriteLine("Processing: " + classFile);
#endif

                        try
                        {
                            string classId = string.Empty;

                            using (Stream stream = File.Open(classFile, FileMode.Open))
                            {
                                using (BinaryReader reader = new BinaryReader(stream))
                                {
                                    JavaClassParser.ClassFile processedClassFile = new JavaClassParser.ClassFile(reader);

                                    JavaClassParser.ConstantClassInfo thisClassInfo = (JavaClassParser.ConstantClassInfo)processedClassFile.constant_pool [processedClassFile.this_class];

                                    JavaClassParser.ConstantUtf8Info thisClassId = (JavaClassParser.ConstantUtf8Info)processedClassFile.constant_pool [thisClassInfo.name_index];

                                    classId = Encoding.UTF8.GetString(thisClassId.bytes);

                                    reader.Close();
                                }

                                stream.Close();
                            }

                            if (!string.IsNullOrWhiteSpace(classId))
                            {
                                string classPackage = classId.Substring(0, classId.LastIndexOf('/'));

                                string className = classId.Substring(classId.LastIndexOf('/') + 1);

                                string classPackageAsDir = Path.Combine(workingDirectory, classPackage);

                                Directory.CreateDirectory(classPackageAsDir);

                                string targetPath = string.Format("{0}/{1}.class", classPackageAsDir, className);

                                File.Copy(classFile, targetPath, true);
#if DEBUG
                                Debug.WriteLine(string.Format("Copied: '{0}' to '{1}'", classFile, targetPath));
#endif
                            }
                        }
                        catch (Exception e)
                        {
                            LogException(e);

                            Interlocked.Increment(ref failedParsedClassFiles);
                        }
                    }

                    if (failedParsedClassFiles > 0)
                    {
                        throw new InvalidOperationException(string.Format("Failed to parse {0} files.", failedParsedClassFiles));
                    }
                }

                //
                // Run the jar tool to package any compiled class files.
                //

                HashSet <string> archiverFilesRead = new HashSet <string> ();

                HashSet <string> archiverFilesWritten = new HashSet <string> ();

                if (!string.IsNullOrEmpty(s_archiverOutputPath))
                {
                    //
                    // c    create new archive
                    // u    update an existing archive
                    // f    specify archive file name
                    // m    specify manifest file name
                    // 0    store only; use no ZIP compression
                    //

                    StringBuilder argumentsBuilder = new StringBuilder();

                    StringBuilder argumentsModeBuilder = new StringBuilder();

                    argumentsModeBuilder.Append("c");

                    argumentsModeBuilder.Append("v");

                    argumentsModeBuilder.Append("f");

                    argumentsBuilder.Append(s_archiverOutputPath + " ");

                    if (!string.IsNullOrEmpty(s_archiverManifestPath))
                    {
                        argumentsModeBuilder.Append("m");

                        argumentsBuilder.Append(s_archiverManifestPath + " ");
                    }

                    argumentsModeBuilder.Append("0");

                    argumentsBuilder.Append("-C " + QuotePathIfNeeded(workingDirectory) + " . ");

                    string executable = Path.Combine(s_jdkHomePath, "bin", "jar.exe");

                    string arguments = argumentsModeBuilder.ToString() + " " + argumentsBuilder.ToString();

                    string workingDir = string.Empty;

                    int exitCode = -1;

                    using (Process process = CreateSynchronousProcess(executable, arguments, workingDir))
                    {
                        process.OutputDataReceived += (sender, e) =>
                        {
                            if (e.Data != null)
                            {
                                ProcessJarOutput(e.Data, ref archiverFilesRead, ref archiverFilesWritten);
                            }
                        };

                        process.ErrorDataReceived += (sender, e) =>
                        {
                            if (e.Data != null)
                            {
                                ProcessJarOutput(e.Data, ref archiverFilesRead, ref archiverFilesWritten);
                            }
                        };

                        if (process.Start())
                        {
                            process.BeginOutputReadLine();

                            process.BeginErrorReadLine();

                            process.WaitForExit();

                            exitCode = process.ExitCode;
                        }

                        if (exitCode != 0)
                        {
                            throw new InvalidOperationException(process.StartInfo.FileName + " failed with exit code: " + exitCode);
                        }

                        //
                        // Export dependency files alongside any exported output.
                        //

                        if (exitCode == 0)
                        {
                            foreach (string file in compilerFilesWritten)
                            {
                                using (StreamWriter writer = new StreamWriter(file + ".d", false, Encoding.Unicode))
                                {
                                    writer.WriteLine(string.Format("{0}: \\", ConvertPathWindowsToGccDependency(file)));

                                    foreach (string dependency in compilerFilesRead)
                                    {
                                        writer.WriteLine(string.Format("  {0} \\", ConvertPathWindowsToGccDependency(dependency)));
                                    }

                                    writer.Close();
                                }
                            }
                        }
                    }
                }

                if (Directory.Exists(workingDirectory))
                {
                    Directory.Delete(workingDirectory, true);
                }
            }
            catch (Exception e)
            {
                LogException(e);

                returnCode = -1;
            }

            return(returnCode);
        }