Browse files

CMake build system, big pile of libs: bspatch, quazip, java, the laun…

…cher
  • Loading branch information...
1 parent d6d5c86 commit b1d00fce8da901b31fa52ea59b4bc3c8edb9d9cc @peterix peterix committed Jan 11, 2013
Showing with 16,978 additions and 27 deletions.
  1. +5 −0 .gitignore
  2. +132 −0 CMakeLists.txt
  3. +17 −0 config.h.in
  4. +83 −0 java/annotations.cpp
  5. +252 −0 java/annotations.h
  6. +153 −0 java/classfile.h
  7. +208 −0 java/constants.h
  8. +62 −0 java/endian.h
  9. +6 −0 java/errors.h
  10. +69 −0 java/javautils.cpp
  11. +9 −0 java/javautils.h
  12. +64 −0 java/membuffer.h
  13. +35 −0 java/test.cpp
  14. +23 −0 launcher/CMakeLists.txt
  15. +123 −0 launcher/MCFrame.java
  16. +331 −0 launcher/MultiMCLauncher.java
  17. +881 −0 launcher/UseJava.cmake
  18. +52 −0 launcher/UseJavaClassFilelist.cmake
  19. +32 −0 launcher/UseJavaSymlinks.cmake
  20. +154 −0 launcher/net/minecraft/Launcher.java
  21. +176 −0 launcher/org/simplericity/macify/eawt/Application.java
  22. +48 −0 launcher/org/simplericity/macify/eawt/ApplicationAdapter.java
  23. +25 −0 launcher/org/simplericity/macify/eawt/ApplicationEvent.java
  24. +27 −0 launcher/org/simplericity/macify/eawt/ApplicationListener.java
  25. +418 −0 launcher/org/simplericity/macify/eawt/DefaultApplication.java
  26. +30 −27 multimc.qrc
  27. +49 −0 multimc_pragma.h
  28. +14 −0 patchlib/CMakeLists.txt
  29. +42 −0 patchlib/LICENSE-bzip2
  30. +1,095 −0 patchlib/blocksort.c
  31. +303 −0 patchlib/bspatch.c
  32. +27 −0 patchlib/bspatch.h
  33. +1,579 −0 patchlib/bzlib.c
  34. +283 −0 patchlib/bzlib.h
  35. +510 −0 patchlib/bzlib_private.h
  36. +672 −0 patchlib/compress.c
  37. +104 −0 patchlib/crctable.c
  38. +646 −0 patchlib/decompress.c
  39. +205 −0 patchlib/huffman.c
  40. +84 −0 patchlib/randtable.c
  41. +26 −0 quazip/CMakeLists.txt
  42. +469 −0 quazip/JlCompress.cpp
  43. +114 −0 quazip/JlCompress.h
  44. +135 −0 quazip/crypt.h
  45. +77 −0 quazip/ioapi.h
  46. +146 −0 quazip/qioapi.cpp
  47. +28 −0 quazip/quaadler32.cpp
  48. +29 −0 quazip/quaadler32.h
  49. +54 −0 quazip/quachecksum32.h
  50. +28 −0 quazip/quacrc32.cpp
  51. +26 −0 quazip/quacrc32.h
  52. +141 −0 quazip/quagzipfile.cpp
  53. +35 −0 quazip/quagzipfile.h
  54. +283 −0 quazip/quaziodevice.cpp
  55. +27 −0 quazip/quaziodevice.h
  56. +554 −0 quazip/quazip.cpp
  57. +411 −0 quazip/quazip.h
  58. +55 −0 quazip/quazip_global.h
  59. +507 −0 quazip/quazipdir.cpp
  60. +171 −0 quazip/quazipdir.h
  61. +488 −0 quazip/quazipfile.cpp
  62. +442 −0 quazip/quazipfile.h
  63. +66 −0 quazip/quazipfileinfo.h
  64. +51 −0 quazip/quazipnewinfo.cpp
  65. +102 −0 quazip/quazipnewinfo.h
  66. +1,603 −0 quazip/unzip.c
  67. +356 −0 quazip/unzip.h
  68. +1,281 −0 quazip/zip.c
  69. +245 −0 quazip/zip.h
View
5 .gitignore
@@ -1 +1,6 @@
Thumbs.db
+.kdev4
+MultiMC5.kdev4
+build
+resources/CMakeFiles
+resources/MultiMCLauncher.jar
View
132 CMakeLists.txt
@@ -0,0 +1,132 @@
+cmake_minimum_required(VERSION 2.8.9)
+project(multimc5)
+
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+
+#### Check for machine endianness ####
+INCLUDE(TestBigEndian)
+TEST_BIG_ENDIAN(BIGENDIAN)
+IF(${BIGENDIAN})
+ ADD_DEFINITIONS(-DMULTIMC_BIG_ENDIAN)
+ENDIF(${BIGENDIAN})
+
+
+#### Find the required Qt parts ####
+find_package(Qt5Widgets)
+#find_package(Qt5Declarative)
+
+include_directories(${Qt5Widgets_INCLUDE_DIRS})
+
+# find ZLIB for quazip
+find_package(ZLIB REQUIRED)
+
+# Find boost.
+set(Boost_USE_STATIC_LIBS ON)
+MESSAGE(STATUS "** Finding Boost...")
+find_package(Boost 1.46.0 REQUIRED)
+MESSAGE(STATUS "** Boost Include: ${Boost_INCLUDE_DIR}")
+MESSAGE(STATUS "** Boost Libraries: ${Boost_LIBRARY_DIRS}")
+
+# Include boost.
+include_directories("${Boost_INCLUDE_DIRS}")
+
+# Add quazip
+add_subdirectory(quazip)
+
+# Add bspatch
+add_subdirectory(patchlib)
+include_directories(patchlib)
+
+# add the java launcher
+add_subdirectory(launcher)
+
+IF(UNIX)
+ # assume GCC, add C++0x/C++11 stuff
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
+ELSEIF(MINGW)
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++0x")
+ENDIF()
+
+# Set the path where CMake will look for modules.
+set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}")
+
+
+set(MultiMC_VERSION_MAJOR 5)
+set(MultiMC_VERSION_MINOR 0)
+set(MultiMC_VERSION_REV 0)
+
+SET(MultiMC_VERSION_BUILD 0 CACHE STRING "Build number.")
+message(STATUS "MultiMC build #${MultiMC_VERSION_BUILD}")
+
+IF (DEFINED MultiMC_BUILD_TAG)
+ message(STATUS "Build tag: ${MultiMC_BUILD_TAG}")
+ELSE ()
+ message(STATUS "No build tag specified.")
+ENDIF ()
+
+if( CMAKE_SIZEOF_VOID_P EQUAL 8 )
+ set (MultiMC_ARCH "x64"
+ CACHE STRING "Architecture we're building for.")
+else()
+ set (MultiMC_ARCH "x86"
+ CACHE STRING "Architecture we're building for.")
+endif()
+message (STATUS "Architecture is ${MultiMC_ARCH}")
+
+SET(MultiMC_Extra_Label "")
+
+IF (WIN32)
+ SET(MultiMC_JOB_NAME "MultiMC4Windows" CACHE STRING "Jenkins job name.")
+ELSEIF(UNIX AND APPLE)
+ SET(MultiMC_JOB_NAME "MultiMC4OSX" CACHE STRING "Jenkins job name.")
+ # This is here because the scheme doesn't exactly apply to every kind of build...
+ SET(MultiMC_Extra_Label ",label=osx")
+ELSE()
+ SET(MultiMC_JOB_NAME "MultiMC4Linux" CACHE STRING "Jenkins job name.")
+ENDIF()
+
+SET(MultiMC_JOB_URL "http://ci.forkk.net/job/${MultiMC_JOB_NAME}/arch=${MultiMC_ARCH}${MultiMC_Extra_Label}/"
+ CACHE STRING "URL of the jenkins job to pull updates from.")
+message(STATUS "Job URL: ${MultiMC_JOB_URL}")
+
+configure_file("${PROJECT_SOURCE_DIR}/config.h.in"
+ "${PROJECT_BINARY_DIR}/config.h")
+
+
+SET(MULTIMC_SOURCES
+main.cpp
+gui/mainwindow.cpp
+data/instancebase.cpp
+util/pathutils.cpp
+
+java/javautils.cpp
+java/annotations.cpp
+)
+
+SET(MULTIMC_HEADERS
+gui/mainwindow.h
+data/instancebase.h
+util/pathutils.h
+multimc_pragma.h
+
+java/annotations.h
+java/classfile.h
+java/constants.h
+java/endian.h
+java/errors.h
+java/javautils.h
+java/membuffer.h
+)
+
+SET_SOURCE_FILES_PROPERTIES(resources/MultiMCLauncher.jar GENERATED)
+
+QT5_WRAP_UI(MULTIMC_UI gui/mainwindow.ui)
+QT5_ADD_RESOURCES(MULTIMC_QRC multimc.qrc)
+
+add_executable(multimc5 ${MULTIMC_SOURCES} ${MULTIMC_HEADERS} ${MULTIMC_UI} ${MULTIMC_QRC})
+qt5_use_modules(multimc5 Widgets)
+link_libraries(multimc5 quazip patchlib)
+add_dependencies(multimc5 MultiMCLauncher)
+install(TARGETS multimc5 RUNTIME DESTINATION bin)
View
17 config.h.in
@@ -0,0 +1,17 @@
+#define VERSION_MAJOR @MultiMC_VERSION_MAJOR@
+#define VERSION_MINOR @MultiMC_VERSION_MINOR@
+#define VERSION_REVISION @MultiMC_VERSION_REV@
+#define VERSION_BUILD @MultiMC_VERSION_BUILD@
+
+#define VERSION_STR "@MultiMC_VERSION_MAJOR@.@MultiMC_VERSION_MINOR@.@MultiMC_VERSION_REV@.@MultiMC_VERSION_BUILD@"
+
+#define x86 1
+#define x64 2
+
+#define ARCH @MultiMC_ARCH@
+
+#define JENKINS_BUILD_TAG "@MultiMC_BUILD_TAG@"
+
+#define JENKINS_JOB_URL "@MultiMC_JOB_URL@"
+
+#define USE_HTTPS @MultiMC_USE_HTTPS@
View
83 java/annotations.cpp
@@ -0,0 +1,83 @@
+#include "classfile.h"
+#include "annotations.h"
+#include <sstream>
+
+namespace java
+{
+ std::string annotation::toString()
+ {
+ std::ostringstream ss;
+ ss << "Annotation type : " << type_index << " - " << pool[type_index].str_data << std::endl;
+ ss << "Contains " << name_val_pairs.size() << " pairs:" << std::endl;
+ for(unsigned i = 0; i < name_val_pairs.size(); i++)
+ {
+ std::pair<uint16_t, element_value *> &val = name_val_pairs[i];
+ auto name_idx = val.first;
+ ss << pool[name_idx].str_data << "(" << name_idx << ")" << " = " << val.second->toString() << std::endl;
+ }
+ return ss.str();
+ }
+
+ annotation * annotation::read (util::membuffer& input, constant_pool& pool)
+ {
+ uint16_t type_index = 0;
+ input.read_be(type_index);
+ annotation * ann = new annotation(type_index,pool);
+
+ uint16_t num_pairs = 0;
+ input.read_be(num_pairs);
+ while(num_pairs)
+ {
+ uint16_t name_idx = 0;
+ // read name index
+ input.read_be(name_idx);
+ auto elem = element_value::readElementValue(input,pool);
+ // read value
+ ann->add_pair(name_idx, elem);
+ num_pairs --;
+ }
+ return ann;
+ }
+
+ element_value* element_value::readElementValue ( util::membuffer& input, java::constant_pool& pool )
+ {
+ element_value_type type = INVALID;
+ input.read(type);
+ uint16_t index = 0;
+ uint16_t index2 = 0;
+ std::vector <element_value *> vals;
+ switch (type)
+ {
+ case PRIMITIVE_BYTE:
+ case PRIMITIVE_CHAR:
+ case PRIMITIVE_DOUBLE:
+ case PRIMITIVE_FLOAT:
+ case PRIMITIVE_INT:
+ case PRIMITIVE_LONG:
+ case PRIMITIVE_SHORT:
+ case PRIMITIVE_BOOLEAN:
+ case STRING:
+ input.read_be(index);
+ return new element_value_simple(type, index, pool);
+ case ENUM_CONSTANT:
+ input.read_be(index);
+ input.read_be(index2);
+ return new element_value_enum(type, index, index2, pool);
+ case CLASS: // Class
+ input.read_be(index);
+ return new element_value_class(type, index, pool);
+ case ANNOTATION: // Annotation
+ // FIXME: runtime visibility info needs to be passed from parent
+ return new element_value_annotation(ANNOTATION, annotation::read(input, pool), pool);
+ case ARRAY: // Array
+ input.read_be(index);
+ for (int i = 0; i < index; i++)
+ {
+ vals.push_back(element_value::readElementValue(input, pool));
+ }
+ return new element_value_array(ARRAY, vals, pool);
+ default:
+ throw new java::classfile_exception();
+ }
+ }
+}
View
252 java/annotations.h
@@ -0,0 +1,252 @@
+#pragma once
+#include "classfile.h"
+#include <map>
+#include <vector>
+
+namespace java
+{
+ enum element_value_type : uint8_t
+ {
+ INVALID = 0,
+ STRING = 's',
+ ENUM_CONSTANT = 'e',
+ CLASS = 'c',
+ ANNOTATION = '@',
+ ARRAY = '[', // one array dimension
+ PRIMITIVE_INT = 'I', // integer
+ PRIMITIVE_BYTE = 'B', // signed byte
+ PRIMITIVE_CHAR = 'C', // Unicode character code point in the Basic Multilingual Plane, encoded with UTF-16
+ PRIMITIVE_DOUBLE = 'D', // double-precision floating-point value
+ PRIMITIVE_FLOAT = 'F', // single-precision floating-point value
+ PRIMITIVE_LONG = 'J', // long integer
+ PRIMITIVE_SHORT = 'S', // signed short
+ PRIMITIVE_BOOLEAN = 'Z' // true or false
+ };
+ /**
+ * The element_value structure is a discriminated union representing the value of an element-value pair.
+ * It is used to represent element values in all attributes that describe annotations
+ * - RuntimeVisibleAnnotations
+ * - RuntimeInvisibleAnnotations
+ * - RuntimeVisibleParameterAnnotations
+ * - RuntimeInvisibleParameterAnnotations).
+ *
+ * The element_value structure has the following format:
+ */
+ class element_value
+ {
+ protected:
+ element_value_type type;
+ constant_pool & pool;
+
+ public:
+ element_value(element_value_type type, constant_pool & pool): type(type), pool(pool) {};
+
+ element_value_type getElementValueType()
+ {
+ return type;
+ }
+
+ virtual std::string toString() = 0;
+
+ static element_value * readElementValue(util::membuffer & input, constant_pool & pool);
+ };
+
+ /**
+ * Each value of the annotations table represents a single runtime-visible annotation on a program element.
+ * The annotation structure has the following format:
+ */
+ class annotation
+ {
+ public:
+ typedef std::vector< std::pair<uint16_t, element_value * > > value_list;
+ protected:
+ /**
+ * The value of the type_index item must be a valid index into the constant_pool table.
+ * The constant_pool entry at that index must be a CONSTANT_Utf8_info (§4.4.7) structure
+ * representing a field descriptor representing the annotation type corresponding
+ * to the annotation represented by this annotation structure.
+ */
+ uint16_t type_index;
+ /**
+ * map between element_name_index and value.
+ *
+ * The value of the element_name_index item must be a valid index into the constant_pool table.
+ * The constant_pool entry at that index must be a CONSTANT_Utf8_info (§4.4.7) structure representing
+ * a valid field descriptor (§4.3.2) that denotes the name of the annotation type element represented
+ * by this element_value_pairs entry.
+ */
+ value_list name_val_pairs;
+ /**
+ * Reference to the parent constant pool
+ */
+ constant_pool & pool;
+ public:
+ annotation(uint16_t type_index, constant_pool& pool):type_index(type_index), pool(pool) {};
+ ~annotation()
+ {
+ for(unsigned i = 0 ; i < name_val_pairs.size(); i++)
+ {
+ delete name_val_pairs[i].second;
+ }
+ }
+ void add_pair(uint16_t key, element_value * value)
+ {
+ name_val_pairs.push_back(std::make_pair(key, value));
+ };
+ value_list::const_iterator begin()
+ {
+ return name_val_pairs.cbegin();
+ }
+ value_list::const_iterator end()
+ {
+ return name_val_pairs.cend();
+ }
+ std::string toString();
+ static annotation * read(util::membuffer & input, constant_pool & pool);
+ };
+ typedef std::vector<annotation *> annotation_table;
+
+
+ /// type for simple value annotation elements
+ class element_value_simple : public element_value
+ {
+ protected:
+ /// index of the constant in the constant pool
+ uint16_t index;
+ public:
+ element_value_simple(element_value_type type, uint16_t index , constant_pool& pool):
+ element_value(type, pool), index(index)
+ {
+ // TODO: verify consistency
+ };
+ uint16_t getIndex()
+ {
+ return index;
+ }
+ virtual std::string toString()
+ {
+ return pool[index].toString();
+ };
+ };
+ /// The enum_const_value item is used if the tag item is 'e'.
+ class element_value_enum : public element_value
+ {
+ protected:
+ /**
+ * The value of the type_name_index item must be a valid index into the constant_pool table.
+ * The constant_pool entry at that index must be a CONSTANT_Utf8_info (§4.4.7) structure
+ * representing a valid field descriptor (§4.3.2) that denotes the internal form of the binary
+ * name (§4.2.1) of the type of the enum constant represented by this element_value structure.
+ */
+ uint16_t typeIndex;
+ /**
+ * The value of the const_name_index item must be a valid index into the constant_pool table.
+ * The constant_pool entry at that index must be a CONSTANT_Utf8_info (§4.4.7) structure
+ * representing the simple name of the enum constant represented by this element_value structure.
+ */
+ uint16_t valueIndex;
+ public:
+ element_value_enum(element_value_type type, uint16_t typeIndex, uint16_t valueIndex, constant_pool& pool):
+ element_value(type, pool), typeIndex(typeIndex), valueIndex(valueIndex)
+ {
+ // TODO: verify consistency
+ }
+ uint16_t getValueIndex()
+ {
+ return valueIndex;
+ }
+ uint16_t getTypeIndex()
+ {
+ return typeIndex;
+ }
+ virtual std::string toString()
+ {
+ return "enum value";
+ };
+ };
+
+ class element_value_class : public element_value
+ {
+ protected:
+ /**
+ * The class_info_index item must be a valid index into the constant_pool table.
+ * The constant_pool entry at that index must be a CONSTANT_Utf8_info (§4.4.7) structure
+ * representing the return descriptor (§4.3.3) of the type that is reified by the class
+ * represented by this element_value structure.
+ *
+ * For example, 'V' for Void.class, 'Ljava/lang/Object;' for Object, etc.
+ *
+ * Or in plain english, you can store type information in annotations. Yay.
+ */
+ uint16_t classIndex;
+ public:
+ element_value_class(element_value_type type, uint16_t classIndex, constant_pool& pool):
+ element_value(type, pool), classIndex(classIndex)
+ {
+ // TODO: verify consistency
+ }
+ uint16_t getIndex()
+ {
+ return classIndex;
+ }
+ virtual std::string toString()
+ {
+ return "class";
+ };
+ };
+
+ /// nested annotations... yay
+ class element_value_annotation : public element_value
+ {
+ private:
+ annotation * nestedAnnotation;
+ public:
+ element_value_annotation(element_value_type type, annotation * nestedAnnotation, constant_pool& pool):
+ element_value(type, pool), nestedAnnotation(nestedAnnotation)
+ {};
+ ~element_value_annotation()
+ {
+ if(nestedAnnotation)
+ {
+ delete nestedAnnotation;
+ nestedAnnotation = nullptr;
+ }
+ }
+ virtual std::string toString()
+ {
+ return "nested annotation";
+ };
+ };
+
+ /// and arrays!
+ class element_value_array : public element_value
+ {
+ public:
+ typedef std::vector <element_value *> elem_vec;
+ protected:
+ elem_vec values;
+ public:
+ element_value_array ( element_value_type type, std::vector <element_value *>& values, constant_pool& pool ):
+ element_value(type, pool), values(values)
+ {};
+ ~element_value_array ()
+ {
+ for(unsigned i = 0; i < values.size();i++)
+ {
+ delete values[i];
+ }
+ };
+ elem_vec::const_iterator begin()
+ {
+ return values.cbegin();
+ }
+ elem_vec::const_iterator end()
+ {
+ return values.cend();
+ }
+ virtual std::string toString()
+ {
+ return "array";
+ };
+ };
+}
View
153 java/classfile.h
@@ -0,0 +1,153 @@
+#pragma once
+#include "membuffer.h"
+#include "constants.h"
+#include "annotations.h"
+#include <map>
+namespace java
+{
+ /**
+ * Class representing a Java .class file
+ */
+ class classfile : public util::membuffer
+ {
+ public:
+ classfile(char * data, std::size_t size) : membuffer(data, size)
+ {
+ valid = false;
+ is_synthetic = false;
+ read_be(magic);
+ if(magic != 0xCAFEBABE)
+ throw new classfile_exception();
+ read_be(minor_version);
+ read_be(major_version);
+ constants.load(*this);
+ read_be(access_flags);
+ read_be(this_class);
+ read_be(super_class);
+
+ // Interfaces
+ uint16_t iface_count = 0;
+ read_be(iface_count);
+ while (iface_count)
+ {
+ uint16_t iface;
+ read_be(iface);
+ interfaces.push_back(iface);
+ iface_count --;
+ }
+
+ // Fields
+ // read fields (and attributes from inside fields) (and possible inner classes. yay for recursion!)
+ // for now though, we will ignore all attributes
+ /*
+ * field_info
+ * {
+ * u2 access_flags;
+ * u2 name_index;
+ * u2 descriptor_index;
+ * u2 attributes_count;
+ * attribute_info attributes[attributes_count];
+ * }
+ */
+ uint16_t field_count = 0;
+ read_be(field_count);
+ while (field_count)
+ {
+ // skip field stuff
+ skip(6);
+ // and skip field attributes
+ uint16_t attr_count = 0;
+ read_be(attr_count);
+ while(attr_count)
+ {
+ skip(2);
+ uint32_t attr_length = 0;
+ read_be(attr_length);
+ skip(attr_length);
+ attr_count --;
+ }
+ field_count --;
+ }
+
+ // class methods
+ /*
+ * method_info
+ * {
+ * u2 access_flags;
+ * u2 name_index;
+ * u2 descriptor_index;
+ * u2 attributes_count;
+ * attribute_info attributes[attributes_count];
+ * }
+ */
+ uint16_t method_count = 0;
+ read_be(method_count);
+ while( method_count )
+ {
+ skip(6);
+ // and skip method attributes
+ uint16_t attr_count = 0;
+ read_be(attr_count);
+ while(attr_count)
+ {
+ skip(2);
+ uint32_t attr_length = 0;
+ read_be(attr_length);
+ skip(attr_length);
+ attr_count --;
+ }
+ method_count --;
+ }
+
+ // class attributes
+ // there are many kinds of attributes. this is just the generic wrapper structure.
+ // type is decided by attribute name. extensions to the standard are *possible*
+ // class annotations are one kind of a attribute (one per class)
+ /*
+ * attribute_info
+ * {
+ * u2 attribute_name_index;
+ * u4 attribute_length;
+ * u1 info[attribute_length];
+ * }
+ */
+ uint16_t class_attr_count = 0;
+ read_be(class_attr_count);
+ while(class_attr_count)
+ {
+ uint16_t name_idx = 0;
+ read_be(name_idx);
+ uint32_t attr_length = 0;
+ read_be(attr_length);
+
+ auto name = constants[name_idx];
+ if(name.str_data == "RuntimeVisibleAnnotations")
+ {
+ uint16_t num_annotations = 0;
+ read_be(num_annotations);
+ while (num_annotations)
+ {
+ visible_class_annotations.push_back(annotation::read(*this, constants));
+ num_annotations --;
+ }
+ }
+ else skip(attr_length);
+ class_attr_count --;
+ }
+ valid = true;
+ };
+ bool valid;
+ bool is_synthetic;
+ uint32_t magic;
+ uint16_t minor_version;
+ uint16_t major_version;
+ constant_pool constants;
+ uint16_t access_flags;
+ uint16_t this_class;
+ uint16_t super_class;
+ // interfaces this class implements ? must be. investigate.
+ std::vector<uint16_t> interfaces;
+ // FIXME: doesn't free up memory on delete
+ java::annotation_table visible_class_annotations;
+ };
+}
View
208 java/constants.h
@@ -0,0 +1,208 @@
+#pragma once
+#include "errors.h"
+#include <sstream>
+
+namespace java
+{
+ class constant
+ {
+ public:
+ enum type_t:uint8_t
+ {
+ j_hole = 0, // HACK: this is a hole in the array, because java is crazy
+ j_string_data = 1,
+ j_int = 3,
+ j_float = 4,
+ j_long = 5,
+ j_double = 6,
+ j_class = 7,
+ j_string = 8,
+ j_fieldref = 9,
+ j_methodref = 10,
+ j_interface_methodref = 11,
+ j_nameandtype = 12
+ } type;
+ constant(util::membuffer & buf )
+ {
+ buf.read(type);
+ // invalid constant type!
+ if(type > j_nameandtype || type == (type_t)0 || type == (type_t)2)
+ throw new classfile_exception();
+
+ // load data depending on type
+ switch(type)
+ {
+ case j_float:
+ case j_int:
+ buf.read_be(int_data); // same as float data really
+ break;
+ case j_double:
+ case j_long:
+ buf.read_be(long_data); // same as double
+ break;
+ case j_class:
+ buf.read_be(ref_type.class_idx);
+ break;
+ case j_fieldref:
+ case j_methodref:
+ case j_interface_methodref:
+ buf.read_be(ref_type.class_idx);
+ buf.read_be(ref_type.name_and_type_idx);
+ break;
+ case j_string:
+ buf.read_be(index);
+ break;
+ case j_string_data:
+ // HACK HACK: for now, we call these UTF-8 and do no further processing.
+ // Later, we should do some decoding. It's really modified UTF-8
+ // * U+0000 is represented as 0xC0,0x80 invalid character
+ // * any single zero byte ends the string
+ // * characters above U+10000 are encoded like in CESU-8
+ buf.read_jstr(str_data);
+ break;
+ case j_nameandtype:
+ buf.read_be(name_and_type.name_index);
+ buf.read_be(name_and_type.descriptor_index);
+ break;
+ }
+ }
+ constant(int fake)
+ {
+ type = j_hole;
+ }
+ std::string toString()
+ {
+ std::ostringstream ss;
+ switch(type)
+ {
+ case j_hole:
+ ss << "Fake legacy entry";
+ break;
+ case j_float:
+ ss << "Float: " << float_data;
+ break;
+ case j_double:
+ ss << "Double: " << double_data;
+ break;
+ case j_int:
+ ss << "Int: " << int_data;
+ break;
+ case j_long:
+ ss << "Long: " << long_data;
+ break;
+ case j_string_data:
+ ss << "StrData: " << str_data;
+ break;
+ case j_string:
+ ss << "Str: " << index;
+ break;
+ case j_fieldref:
+ ss << "FieldRef: " << ref_type.class_idx << " " << ref_type.name_and_type_idx;
+ break;
+ case j_methodref:
+ ss << "MethodRef: " << ref_type.class_idx << " " << ref_type.name_and_type_idx;
+ break;
+ case j_interface_methodref:
+ ss << "IfMethodRef: " << ref_type.class_idx << " " << ref_type.name_and_type_idx;
+ break;
+ case j_class:
+ ss << "Class: " << ref_type.class_idx;
+ break;
+ case j_nameandtype:
+ ss << "NameAndType: " << name_and_type.name_index << " " << name_and_type.descriptor_index;
+ break;
+ }
+ return ss.str();
+ }
+
+ std::string str_data; /** String data in 'modified utf-8'.*/
+ // store everything here.
+ union
+ {
+ int32_t int_data;
+ int64_t long_data;
+ float float_data;
+ double double_data;
+ uint16_t index;
+ struct
+ {
+ /**
+ * Class reference:
+ * an index within the constant pool to a UTF-8 string containing
+ * the fully qualified class name (in internal format)
+ * Used for j_class, j_fieldref, j_methodref and j_interface_methodref
+ */
+ uint16_t class_idx;
+ // used for j_fieldref, j_methodref and j_interface_methodref
+ uint16_t name_and_type_idx;
+ } ref_type;
+ struct
+ {
+ uint16_t name_index;
+ uint16_t descriptor_index;
+ } name_and_type;
+ };
+ };
+ /**
+ * A helper class that represents the custom container used in Java class file for storage of constants
+ */
+ class constant_pool
+ {
+ public:
+ /**
+ * Create a pool of constants
+ */
+ constant_pool(){}
+ /**
+ * Load a java constant pool
+ */
+ void load(util::membuffer & buf)
+ {
+ uint16_t length = 0;
+ buf.read_be(length);
+ length --;
+ uint16_t index = 1;
+ const constant * last_constant = nullptr;
+ while(length)
+ {
+ const constant & cnst = constant(buf);
+ constants.push_back(cnst);
+ last_constant = &constants[constants.size() - 1];
+ if(last_constant->type == constant::j_double || last_constant->type == constant::j_long)
+ {
+ // push in a fake constant to preserve indexing
+ constants.push_back(constant(0));
+ length-=2;
+ index+=2;
+ }
+ else
+ {
+ length--;
+ index++;
+ }
+ }
+ };
+ typedef std::vector<java::constant> container_type;
+ /**
+ * Access constants based on jar file index numbers (index of the first element is 1)
+ */
+ java::constant & operator[](std::size_t constant_index)
+ {
+ if(constant_index == 0 || constant_index > constants.size())
+ {
+ throw new classfile_exception();
+ }
+ return constants[constant_index - 1];
+ };
+ container_type::const_iterator begin() const
+ {
+ return constants.begin();
+ };
+ container_type::const_iterator end() const
+ {
+ return constants.end();
+ }
+ private:
+ container_type constants;
+ };
+}
View
62 java/endian.h
@@ -0,0 +1,62 @@
+#pragma once
+#include <stdint.h>
+
+/**
+ * Swap bytes between big endian and local number representation
+ */
+namespace util
+{
+#ifdef MULTIMC_BIG_ENDIAN
+inline uint64_t bigswap(uint64_t x)
+{
+ return x;
+};
+inline uint32_t bigswap(uint32_t x)
+{
+ return x;
+};
+inline uint16_t bigswap(uint16_t x)
+{
+ return x;
+};
+inline int64_t bigswap(int64_t x)
+{
+ return x;
+};
+inline int32_t bigswap(int32_t x)
+{
+ return x;
+};
+inline int16_t bigswap(int16_t x)
+{
+ return x;
+};
+#else
+inline uint64_t bigswap(uint64_t x)
+{
+ return (x>>56) | ((x<<40) & 0x00FF000000000000) | ((x<<24) & 0x0000FF0000000000) | ((x<<8) & 0x000000FF00000000) |
+ ((x>>8) & 0x00000000FF000000) | ((x>>24) & 0x0000000000FF0000) | ((x>>40) & 0x000000000000FF00) | (x<<56);
+};
+inline uint32_t bigswap(uint32_t x)
+{
+ return (x>>24) | ((x<<8) & 0x00FF0000) | ((x>>8) & 0x0000FF00) | (x<<24);
+};
+inline uint16_t bigswap(uint16_t x)
+{
+ return (x>>8) | (x<<8);
+};
+inline int64_t bigswap(int64_t x)
+{
+ return (x>>56) | ((x<<40) & 0x00FF000000000000) | ((x<<24) & 0x0000FF0000000000) | ((x<<8) & 0x000000FF00000000) |
+ ((x>>8) & 0x00000000FF000000) | ((x>>24) & 0x0000000000FF0000) | ((x>>40) & 0x000000000000FF00) | (x<<56);
+};
+inline int32_t bigswap(int32_t x)
+{
+ return (x>>24) | ((x<<8) & 0x00FF0000) | ((x>>8) & 0x0000FF00) | (x<<24);
+};
+inline int16_t bigswap(int16_t x)
+{
+ return (x>>8) | (x<<8);
+};
+#endif
+}
View
6 java/errors.h
@@ -0,0 +1,6 @@
+#pragma once
+#include <exception>
+namespace java
+{
+ class classfile_exception : public std::exception {};
+}
View
69 java/javautils.cpp
@@ -0,0 +1,69 @@
+#include "multimc_pragma.h"
+#include "classfile.h"
+#include "javautils.h"
+//#include <wx/zipstrm.h>
+#include <memory>
+//#include <wx/wfstream.h>
+//#include "mcversionlist.h"
+
+namespace javautils
+{
+QString GetMinecraftJarVersion(QString jar)
+{
+ return "Unknown";
+ /*
+ wxString fullpath = jar.GetFullPath();
+ wxString version = MCVer_Unknown;
+ if(!jar.FileExists())
+ return version;
+ std::auto_ptr<wxZipEntry> entry;
+ // convert the local name we are looking for into the internal format
+ wxString name = wxZipEntry::GetInternalName("net/minecraft/client/Minecraft.class",wxPATH_UNIX);
+
+ // open the zip
+ wxFFileInputStream inStream(jar.GetFullPath());
+ wxZipInputStream zipIn(inStream);
+
+ // call GetNextEntry() until the required internal name is found
+ do
+ {
+ entry.reset(zipIn.GetNextEntry());
+ }
+ while (entry.get() != NULL && entry->GetInternalName() != name);
+ auto myentry = entry.get();
+ if (myentry == NULL)
+ return version;
+
+ // we got the entry, read the data
+ std::size_t size = myentry->GetSize();
+ char *classdata = new char[size];
+ zipIn.Read(classdata,size);
+ try
+ {
+ char * temp = classdata;
+ java::classfile Minecraft_jar(temp,size);
+ auto cnst = Minecraft_jar.constants;
+ auto iter = cnst.begin();
+ while (iter != cnst.end())
+ {
+ const java::constant & constant = *iter;
+ if(constant.type != java::constant::j_string_data)
+ {
+ iter++;
+ continue;
+ }
+ auto & str = constant.str_data;
+ const char * lookfor = "Minecraft Minecraft "; // length = 20
+ if(str.compare(0,20,lookfor) == 0)
+ {
+ version = str.substr(20).data();
+ break;
+ }
+ iter++;
+ }
+ } catch(java::classfile_exception &){}
+ delete[] classdata;
+ return version;
+ */
+}
+}
View
9 java/javautils.h
@@ -0,0 +1,9 @@
+#pragma once
+#include <QString>
+namespace javautils
+{
+ /*
+ * Get the version from a minecraft.jar by parsing its class files. Expensive!
+ */
+ QString GetMinecraftJarVersion(QString jar);
+}
View
64 java/membuffer.h
@@ -0,0 +1,64 @@
+#pragma once
+#include <stdint.h>
+#include <string>
+#include <vector>
+#include <exception>
+#include "endian.h"
+
+namespace util
+{
+ class membuffer
+ {
+ public:
+ membuffer(char * buffer, std::size_t size)
+ {
+ current = start = buffer;
+ end = start + size;
+ }
+ ~membuffer()
+ {
+ // maybe? possibly? left out to avoid confusion. for now.
+ //delete start;
+ }
+ /**
+ * Read some value. That's all ;)
+ */
+ template <class T>
+ void read(T& val)
+ {
+ val = *(T *)current;
+ current += sizeof(T);
+ }
+ /**
+ * Read a big-endian number
+ * valid for 2-byte, 4-byte and 8-byte variables
+ */
+ template <class T>
+ void read_be(T& val)
+ {
+ val = util::bigswap(*(T *)current);
+ current += sizeof(T);
+ }
+ /**
+ * Read a string in the format:
+ * 2B length (big endian, unsigned)
+ * length bytes data
+ */
+ void read_jstr(std::string & str)
+ {
+ uint16_t length = 0;
+ read_be(length);
+ str.append(current,length);
+ current += length;
+ }
+ /**
+ * Skip N bytes
+ */
+ void skip (std::size_t N)
+ {
+ current += N;
+ }
+ private:
+ char * start, *end, *current;
+ };
+}
View
35 java/test.cpp
@@ -0,0 +1,35 @@
+
+#include "classfile.h"
+#include "annotations.h"
+#include <fstream>
+#include <iostream>
+
+int main(int argc, char* argv[])
+{
+ if(argc > 1)
+ {
+ std::ifstream file_in(argv[1]);
+ if(file_in.is_open())
+ {
+ file_in.seekg(0, std::_S_end);
+ auto length = file_in.tellg();
+ char * data = new char[length];
+ file_in.seekg(0);
+ file_in.read(data,length);
+ java::classfile cf (data, length);
+ java::annotation_table atable = cf.visible_class_annotations;
+ for(int i = 0; i < atable.size(); i++)
+ {
+ std::cout << atable[i]->toString() << std::endl;
+ }
+ return 0;
+ }
+ else
+ {
+ std::cerr << "Failed to open file : " << argv[1] << std::endl;
+ return 1;
+ }
+ }
+ std::cerr << "No file to open :(" << std::endl;
+ return 1;
+}
View
23 launcher/CMakeLists.txt
@@ -0,0 +1,23 @@
+cmake_minimum_required(VERSION 2.8.6)
+project(launcher Java)
+set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}")
+find_package(Java 1.6 REQUIRED COMPONENTS Development)
+
+
+include(UseJava)
+set(CMAKE_JAVA_JAR_ENTRY_POINT MultiMCLauncher)
+set(CMAKE_JAVA_COMPILE_FLAGS -target 1.6 -source 1.6 -Xlint:deprecation -Xlint:unchecked)
+set(CMAKE_JAVA_TARGET_OUTPUT_DIR "${PROJECT_SOURCE_DIR}/../resources")
+
+set(SRC
+ MultiMCLauncher.java
+ org/simplericity/macify/eawt/Application.java
+ org/simplericity/macify/eawt/ApplicationAdapter.java
+ org/simplericity/macify/eawt/ApplicationEvent.java
+ org/simplericity/macify/eawt/ApplicationListener.java
+ org/simplericity/macify/eawt/DefaultApplication.java
+ net/minecraft/Launcher.java
+ MCFrame.java
+)
+
+add_jar(MultiMCLauncher ${SRC})
View
123 launcher/MCFrame.java
@@ -0,0 +1,123 @@
+//
+// Copyright 2012 MultiMC Contributors
+//
+// 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.
+//
+
+import net.minecraft.Launcher;
+import java.applet.Applet;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.Toolkit;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowListener;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.io.IOException;
+import java.io.File;
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+
+public class MCFrame extends Frame implements WindowListener
+{
+ private Launcher appletWrap = null;
+ public MCFrame(String title)
+ {
+ super(title);
+ BufferedImage image = null;
+ try
+ {
+ image = ImageIO.read(new File("icon.png"));
+ setIconImage(image);
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+ this.addWindowListener(this);
+ }
+
+ public void start(Applet mcApplet, String user, String session, Dimension winSize, boolean maximize)
+ {
+ try
+ {
+ appletWrap = new Launcher(mcApplet, new URL("http://www.minecraft.net/game"));
+ }
+ catch (MalformedURLException ignored){}
+
+ appletWrap.setParameter("username", user);
+ appletWrap.setParameter("sessionid", session);
+ appletWrap.setParameter("stand-alone", "true"); // Show the quit button.
+ mcApplet.setStub(appletWrap);
+
+ this.add(appletWrap);
+ appletWrap.setPreferredSize(winSize);
+ this.pack();
+ this.setLocationRelativeTo(null);
+ this.setResizable(true);
+ if (maximize)
+ this.setExtendedState(MAXIMIZED_BOTH);
+
+ validate();
+ appletWrap.init();
+ appletWrap.start();
+ setVisible(true);
+ }
+
+ @Override
+ public void windowActivated(WindowEvent e) {}
+
+ @Override
+ public void windowClosed(WindowEvent e) {}
+
+ @Override
+ public void windowClosing(WindowEvent e)
+ {
+ new Thread()
+ {
+ public void run()
+ {
+ try
+ {
+ Thread.sleep(30000L);
+ } catch (InterruptedException localInterruptedException)
+ {
+ localInterruptedException.printStackTrace();
+ }
+ System.out.println("FORCING EXIT!");
+ System.exit(0);
+ }
+ }
+ .start();
+
+ if (appletWrap != null)
+ {
+ appletWrap.stop();
+ appletWrap.destroy();
+ }
+ // old minecraft versions can hang without this >_<
+ System.exit(0);
+ }
+
+ @Override
+ public void windowDeactivated(WindowEvent e) {}
+
+ @Override
+ public void windowDeiconified(WindowEvent e) {}
+
+ @Override
+ public void windowIconified(WindowEvent e) {}
+
+ @Override
+ public void windowOpened(WindowEvent e) {}
+}
View
331 launcher/MultiMCLauncher.java
@@ -0,0 +1,331 @@
+//
+// Copyright 2012 MultiMC Contributors
+//
+// 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.
+//
+
+import java.applet.Applet;
+import java.awt.Dimension;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipException;
+import java.util.zip.ZipFile;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import org.simplericity.macify.eawt.Application;
+import org.simplericity.macify.eawt.DefaultApplication;
+
+public class MultiMCLauncher
+{
+ /**
+ * @param args
+ * The arguments you want to launch Minecraft with. New path,
+ * Username, Session ID.
+ */
+ public static void main(String[] args)
+ {
+ if (args.length < 3)
+ {
+ System.out.println("Not enough arguments.");
+ System.exit(-1);
+ }
+
+ // Set the OSX application icon first, if we are on OSX.
+ Application application = new DefaultApplication();
+ if(application.isMac())
+ {
+ try
+ {
+ BufferedImage image = ImageIO.read(new File("icon.png"));
+ application.setApplicationIconImage(image);
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ String userName = args[0];
+ String sessionId = args[1];
+ String windowtitle = args[2];
+ String windowParams = args[3];
+ String lwjgl = args[4];
+ String cwd = System.getProperty("user.dir");
+
+ Dimension winSize = new Dimension(854, 480);
+ boolean maximize = false;
+ boolean compatMode = false;
+
+
+ String[] dimStrings = windowParams.split("x");
+
+ if (windowParams.equalsIgnoreCase("compatmode"))
+ {
+ compatMode = true;
+ }
+ else if (windowParams.equalsIgnoreCase("max"))
+ {
+ maximize = true;
+ }
+ else if (dimStrings.length == 2)
+ {
+ try
+ {
+ winSize = new Dimension(Integer.parseInt(dimStrings[0]),
+ Integer.parseInt(dimStrings[1]));
+ }
+ catch (NumberFormatException e)
+ {
+ System.out.println("Invalid Window size argument, " +
+ "using default.");
+ }
+ }
+ else
+ {
+ System.out.println("Invalid Window size argument, " +
+ "using default.");
+ }
+
+ try
+ {
+ File binDir = new File(cwd, "bin");
+ File lwjglDir;
+ if(lwjgl.equalsIgnoreCase("Mojang"))
+ lwjglDir = binDir;
+ else
+ lwjglDir = new File(lwjgl);
+
+ System.out.println("Loading jars...");
+ String[] lwjglJars = new String[] {
+ "lwjgl.jar", "lwjgl_util.jar", "jinput.jar"
+ };
+
+ URL[] urls = new URL[4];
+ try
+ {
+ File f = new File(binDir, "minecraft.jar");
+ urls[0] = f.toURI().toURL();
+ System.out.println("Loading URL: " + urls[0].toString());
+
+ for (int i = 1; i < urls.length; i++)
+ {
+ File jar = new File(lwjglDir, lwjglJars[i-1]);
+ urls[i] = jar.toURI().toURL();
+ System.out.println("Loading URL: " + urls[i].toString());
+ }
+ }
+ catch (MalformedURLException e)
+ {
+ System.err.println("MalformedURLException, " + e.toString());
+ System.exit(5);
+ }
+
+ System.out.println("Loading natives...");
+ String nativesDir = new File(lwjglDir, "natives").toString();
+
+ System.setProperty("org.lwjgl.librarypath", nativesDir);
+ System.setProperty("net.java.games.input.librarypath", nativesDir);
+
+ URLClassLoader cl =
+ new URLClassLoader(urls, MultiMCLauncher.class.getClassLoader());
+
+ // Get the Minecraft Class.
+ Class<?> mc = null;
+ try
+ {
+ mc = cl.loadClass("net.minecraft.client.Minecraft");
+
+ Field f = getMCPathField(mc);
+
+ if (f == null)
+ {
+ System.err.println("Could not find Minecraft path field. Launch failed.");
+ System.exit(-1);
+ }
+
+ f.setAccessible(true);
+ f.set(null, new File(cwd));
+ // And set it.
+ System.out.println("Fixed Minecraft Path: Field was " + f.toString());
+ }
+ catch (ClassNotFoundException e)
+ {
+ System.err.println("Can't find main class. Searching...");
+
+ // Look for any class that looks like the main class.
+ File mcJar = new File(new File(cwd, "bin"), "minecraft.jar");
+ ZipFile zip = null;
+ try
+ {
+ zip = new ZipFile(mcJar);
+ } catch (ZipException e1)
+ {
+ e1.printStackTrace();
+ System.err.println("Search failed.");
+ System.exit(-1);
+ } catch (IOException e1)
+ {
+ e1.printStackTrace();
+ System.err.println("Search failed.");
+ System.exit(-1);
+ }
+
+ Enumeration<? extends ZipEntry> entries = zip.entries();
+ ArrayList<String> classes = new ArrayList<String>();
+
+ while (entries.hasMoreElements())
+ {
+ ZipEntry entry = entries.nextElement();
+ if (entry.getName().endsWith(".class"))
+ {
+ String entryName = entry.getName().substring(0, entry.getName().lastIndexOf('.'));
+ entryName = entryName.replace('/', '.');
+ System.out.println("Found class: " + entryName);
+ classes.add(entryName);
+ }
+ }
+
+ for (String clsName : classes)
+ {
+ try
+ {
+ Class<?> cls = cl.loadClass(clsName);
+ if (!Runnable.class.isAssignableFrom(cls))
+ {
+ continue;
+ }
+ else
+ {
+ System.out.println("Found class implementing runnable: " +
+ cls.getName());
+ }
+
+ if (getMCPathField(cls) == null)
+ {
+ continue;
+ }
+ else
+ {
+ System.out.println("Found class implementing runnable " +
+ "with mcpath field: " + cls.getName());
+ }
+
+ mc = cls;
+ break;
+ }
+ catch (ClassNotFoundException e1)
+ {
+ // Ignore
+ continue;
+ }
+ }
+
+ if (mc == null)
+ {
+ System.err.println("Failed to find Minecraft main class.");
+ System.exit(-1);
+ }
+ else
+ {
+ System.out.println("Found main class: " + mc.getName());
+ }
+ }
+
+ System.setProperty("minecraft.applet.TargetDirectory", cwd);
+
+ String[] mcArgs = new String[2];
+ mcArgs[0] = userName;
+ mcArgs[1] = sessionId;
+
+ if (compatMode)
+ {
+ System.out.println("Launching in compatibility mode...");
+ mc.getMethod("main", String[].class).invoke(null, (Object) mcArgs);
+ }
+ else
+ {
+ System.out.println("Launching with applet wrapper...");
+ try
+ {
+ Class<?> MCAppletClass = cl.loadClass(
+ "net.minecraft.client.MinecraftApplet");
+ Applet mcappl = (Applet) MCAppletClass.newInstance();
+ MCFrame mcWindow = new MCFrame(windowtitle);
+ mcWindow.start(mcappl, userName, sessionId, winSize, maximize);
+ } catch (InstantiationException e)
+ {
+ System.out.println("Applet wrapper failed! Falling back " +
+ "to compatibility mode.");
+ mc.getMethod("main", String[].class).invoke(null, (Object) mcArgs);
+ }
+ }
+ } catch (ClassNotFoundException e)
+ {
+ e.printStackTrace();
+ System.exit(1);
+ } catch (IllegalArgumentException e)
+ {
+ e.printStackTrace();
+ System.exit(2);
+ } catch (IllegalAccessException e)
+ {
+ e.printStackTrace();
+ System.exit(2);
+ } catch (InvocationTargetException e)
+ {
+ e.printStackTrace();
+ System.exit(3);
+ } catch (NoSuchMethodException e)
+ {
+ e.printStackTrace();
+ System.exit(3);
+ } catch (SecurityException e)
+ {
+ e.printStackTrace();
+ System.exit(4);
+ }
+ }
+
+ public static Field getMCPathField(Class<?> mc)
+ {
+ Field[] fields = mc.getDeclaredFields();
+
+ for (int i = 0; i < fields.length; i++)
+ {
+ Field f = fields[i];
+ if (f.getType() != File.class)
+ {
+ // Has to be File
+ continue;
+ }
+ if (f.getModifiers() != (Modifier.PRIVATE + Modifier.STATIC))
+ {
+ // And Private Static.
+ continue;
+ }
+ return f;
+ }
+ return null;
+ }
+}
View
881 launcher/UseJava.cmake
@@ -0,0 +1,881 @@
+# - Use Module for Java
+# This file provides functions for Java. It is assumed that FindJava.cmake
+# has already been loaded. See FindJava.cmake for information on how to
+# load Java into your CMake project.
+#
+# add_jar(TARGET_NAME SRC1 SRC2 .. SRCN RCS1 RCS2 .. RCSN)
+#
+# This command creates a <TARGET_NAME>.jar. It compiles the given source
+# files (SRC) and adds the given resource files (RCS) to the jar file.
+# If only resource files are given then just a jar file is created.
+#
+# Additional instructions:
+# To add compile flags to the target you can set these flags with
+# the following variable:
+#
+# set(CMAKE_JAVA_COMPILE_FLAGS -nowarn)
+#
+# To add a path or a jar file to the class path you can do this
+# with the CMAKE_JAVA_INCLUDE_PATH variable.
+#
+# set(CMAKE_JAVA_INCLUDE_PATH /usr/share/java/shibboleet.jar)
+#
+# To use a different output name for the target you can set it with:
+#
+# set(CMAKE_JAVA_TARGET_OUTPUT_NAME shibboleet.jar)
+# add_jar(foobar foobar.java)
+#
+# To use a different output directory than CMAKE_CURRENT_BINARY_DIR
+# you can set it with:
+#
+# set(CMAKE_JAVA_TARGET_OUTPUT_DIR ${PROJECT_BINARY_DIR}/bin)
+#
+# To define an entry point in your jar you can set it with:
+#
+# set(CMAKE_JAVA_JAR_ENTRY_POINT com/examples/MyProject/Main)
+#
+# To add a VERSION to the target output name you can set it using
+# CMAKE_JAVA_TARGET_VERSION. This will create a jar file with the name
+# shibboleet-1.0.0.jar and will create a symlink shibboleet.jar
+# pointing to the jar with the version information.
+#
+# set(CMAKE_JAVA_TARGET_VERSION 1.2.0)
+# add_jar(shibboleet shibbotleet.java)
+#
+# If the target is a JNI library, utilize the following commands to
+# create a JNI symbolic link:
+#
+# set(CMAKE_JNI_TARGET TRUE)
+# set(CMAKE_JAVA_TARGET_VERSION 1.2.0)
+# add_jar(shibboleet shibbotleet.java)
+# install_jar(shibboleet ${LIB_INSTALL_DIR}/shibboleet)
+# install_jni_symlink(shibboleet ${JAVA_LIB_INSTALL_DIR})
+#
+# If a single target needs to produce more than one jar from its
+# java source code, to prevent the accumulation of duplicate class
+# files in subsequent jars, set/reset CMAKE_JAR_CLASSES_PREFIX prior
+# to calling the add_jar() function:
+#
+# set(CMAKE_JAR_CLASSES_PREFIX com/redhat/foo)
+# add_jar(foo foo.java)
+#
+# set(CMAKE_JAR_CLASSES_PREFIX com/redhat/bar)
+# add_jar(bar bar.java)
+#
+# Target Properties:
+# The add_jar() functions sets some target properties. You can get these
+# properties with the
+# get_property(TARGET <target_name> PROPERTY <propery_name>)
+# command.
+#
+# INSTALL_FILES The files which should be installed. This is used by
+# install_jar().
+# JNI_SYMLINK The JNI symlink which should be installed.
+# This is used by install_jni_symlink().
+# JAR_FILE The location of the jar file so that you can include
+# it.
+# CLASS_DIR The directory where the class files can be found. For
+# example to use them with javah.
+#
+# find_jar(<VAR>
+# name | NAMES name1 [name2 ...]
+# [PATHS path1 [path2 ... ENV var]]
+# [VERSIONS version1 [version2]]
+# [DOC "cache documentation string"]
+# )
+#
+# This command is used to find a full path to the named jar. A cache
+# entry named by <VAR> is created to stor the result of this command. If
+# the full path to a jar is found the result is stored in the variable
+# and the search will not repeated unless the variable is cleared. If
+# nothing is found, the result will be <VAR>-NOTFOUND, and the search
+# will be attempted again next time find_jar is invoked with the same
+# variable.
+# The name of the full path to a file that is searched for is specified
+# by the names listed after NAMES argument. Additional search locations
+# can be specified after the PATHS argument. If you require special a
+# version of a jar file you can specify it with the VERSIONS argument.
+# The argument after DOC will be used for the documentation string in
+# the cache.
+#
+# install_jar(TARGET_NAME DESTINATION)
+#
+# This command installs the TARGET_NAME files to the given DESTINATION.
+# It should be called in the same scope as add_jar() or it will fail.
+#
+# install_jni_symlink(TARGET_NAME DESTINATION)
+#
+# This command installs the TARGET_NAME JNI symlinks to the given
+# DESTINATION. It should be called in the same scope as add_jar()
+# or it will fail.
+#
+# create_javadoc(<VAR>
+# PACKAGES pkg1 [pkg2 ...]
+# [SOURCEPATH <sourcepath>]
+# [CLASSPATH <classpath>]
+# [INSTALLPATH <install path>]
+# [DOCTITLE "the documentation title"]
+# [WINDOWTITLE "the title of the document"]
+# [AUTHOR TRUE|FALSE]
+# [USE TRUE|FALSE]
+# [VERSION TRUE|FALSE]
+# )
+#
+# Create java documentation based on files or packages. For more
+# details please read the javadoc manpage.
+#
+# There are two main signatures for create_javadoc. The first
+# signature works with package names on a path with source files:
+#
+# Example:
+# create_javadoc(my_example_doc
+# PACKAGES com.exmaple.foo com.example.bar
+# SOURCEPATH "${CMAKE_CURRENT_SOURCE_DIR}"
+# CLASSPATH ${CMAKE_JAVA_INCLUDE_PATH}
+# WINDOWTITLE "My example"
+# DOCTITLE "<h1>My example</h1>"
+# AUTHOR TRUE
+# USE TRUE
+# VERSION TRUE
+# )
+#
+# The second signature for create_javadoc works on a given list of
+# files.
+#
+# create_javadoc(<VAR>
+# FILES file1 [file2 ...]
+# [CLASSPATH <classpath>]
+# [INSTALLPATH <install path>]
+# [DOCTITLE "the documentation title"]
+# [WINDOWTITLE "the title of the document"]
+# [AUTHOR TRUE|FALSE]
+# [USE TRUE|FALSE]
+# [VERSION TRUE|FALSE]
+# )
+#
+# Example:
+# create_javadoc(my_example_doc
+# FILES ${example_SRCS}
+# CLASSPATH ${CMAKE_JAVA_INCLUDE_PATH}
+# WINDOWTITLE "My example"
+# DOCTITLE "<h1>My example</h1>"
+# AUTHOR TRUE
+# USE TRUE
+# VERSION TRUE
+# )
+#
+# Both signatures share most of the options. These options are the
+# same as what you can find in the javadoc manpage. Please look at
+# the manpage for CLASSPATH, DOCTITLE, WINDOWTITLE, AUTHOR, USE and
+# VERSION.
+#
+# The documentation will be by default installed to
+#
+# ${CMAKE_INSTALL_PREFIX}/share/javadoc/<VAR>
+#
+# if you don't set the INSTALLPATH.
+#
+
+#=============================================================================
+# Copyright 2010-2011 Andreas schneider <asn@redhat.com>
+# Copyright 2010 Ben Boeckel <ben.boeckel@kitware.com>
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+# License text for the above reference.)
+
+function (__java_copy_file src dest comment)
+ add_custom_command(
+ OUTPUT ${dest}
+ COMMAND cmake -E copy_if_different
+ ARGS ${src}
+ ${dest}
+ DEPENDS ${src}
+ COMMENT ${comment})
+endfunction (__java_copy_file src dest comment)
+
+# define helper scripts
+set(_JAVA_CLASS_FILELIST_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/UseJavaClassFilelist.cmake)
+set(_JAVA_SYMLINK_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/UseJavaSymlinks.cmake)
+
+function(add_jar _TARGET_NAME)
+ set(_JAVA_SOURCE_FILES ${ARGN})
+
+ if (NOT DEFINED CMAKE_JAVA_TARGET_OUTPUT_DIR)
+ set(CMAKE_JAVA_TARGET_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR})
+ endif(NOT DEFINED CMAKE_JAVA_TARGET_OUTPUT_DIR)
+
+ if (CMAKE_JAVA_JAR_ENTRY_POINT)
+ set(_ENTRY_POINT_OPTION e)
+ set(_ENTRY_POINT_VALUE ${CMAKE_JAVA_JAR_ENTRY_POINT})
+ endif (CMAKE_JAVA_JAR_ENTRY_POINT)
+
+ if (LIBRARY_OUTPUT_PATH)
+ set(CMAKE_JAVA_LIBRARY_OUTPUT_PATH ${LIBRARY_OUTPUT_PATH})
+ else (LIBRARY_OUTPUT_PATH)
+ set(CMAKE_JAVA_LIBRARY_OUTPUT_PATH ${CMAKE_JAVA_TARGET_OUTPUT_DIR})
+ endif (LIBRARY_OUTPUT_PATH)
+
+ set(CMAKE_JAVA_INCLUDE_PATH
+ ${CMAKE_JAVA_INCLUDE_PATH}
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_JAVA_OBJECT_OUTPUT_PATH}
+ ${CMAKE_JAVA_LIBRARY_OUTPUT_PATH}
+ )
+
+ if (WIN32 AND NOT CYGWIN AND NOT CMAKE_CROSSCOMPILING)
+ set(CMAKE_JAVA_INCLUDE_FLAG_SEP ";")
+ else ()
+ set(CMAKE_JAVA_INCLUDE_FLAG_SEP ":")
+ endif()
+
+ foreach (JAVA_INCLUDE_DIR ${CMAKE_JAVA_INCLUDE_PATH})
+ set(CMAKE_JAVA_INCLUDE_PATH_FINAL "${CMAKE_JAVA_INCLUDE_PATH_FINAL}${CMAKE_JAVA_INCLUDE_FLAG_SEP}${JAVA_INCLUDE_DIR}")
+ endforeach(JAVA_INCLUDE_DIR)
+
+ set(CMAKE_JAVA_CLASS_OUTPUT_PATH "${CMAKE_JAVA_TARGET_OUTPUT_DIR}${CMAKE_FILES_DIRECTORY}/${_TARGET_NAME}.dir")
+
+ set(_JAVA_TARGET_OUTPUT_NAME "${_TARGET_NAME}.jar")
+ if (CMAKE_JAVA_TARGET_OUTPUT_NAME AND CMAKE_JAVA_TARGET_VERSION)
+ set(_JAVA_TARGET_OUTPUT_NAME "${CMAKE_JAVA_TARGET_OUTPUT_NAME}-${CMAKE_JAVA_TARGET_VERSION}.jar")
+ set(_JAVA_TARGET_OUTPUT_LINK "${CMAKE_JAVA_TARGET_OUTPUT_NAME}.jar")
+ elseif (CMAKE_JAVA_TARGET_VERSION)
+ set(_JAVA_TARGET_OUTPUT_NAME "${_TARGET_NAME}-${CMAKE_JAVA_TARGET_VERSION}.jar")
+ set(_JAVA_TARGET_OUTPUT_LINK "${_TARGET_NAME}.jar")
+ elseif (CMAKE_JAVA_TARGET_OUTPUT_NAME)
+ set(_JAVA_TARGET_OUTPUT_NAME "${CMAKE_JAVA_TARGET_OUTPUT_NAME}.jar")
+ endif (CMAKE_JAVA_TARGET_OUTPUT_NAME AND CMAKE_JAVA_TARGET_VERSION)
+ # reset
+ set(CMAKE_JAVA_TARGET_OUTPUT_NAME)
+
+ set(_JAVA_CLASS_FILES)
+ set(_JAVA_COMPILE_FILES)
+ set(_JAVA_DEPENDS)
+ set(_JAVA_RESOURCE_FILES)
+ foreach(_JAVA_SOURCE_FILE ${_JAVA_SOURCE_FILES})
+ get_filename_component(_JAVA_EXT ${_JAVA_SOURCE_FILE} EXT)
+ get_filename_component(_JAVA_FILE ${_JAVA_SOURCE_FILE} NAME_WE)
+ get_filename_component(_JAVA_PATH ${_JAVA_SOURCE_FILE} PATH)
+ get_filename_component(_JAVA_FULL ${_JAVA_SOURCE_FILE} ABSOLUTE)
+
+ file(RELATIVE_PATH _JAVA_REL_BINARY_PATH ${CMAKE_JAVA_TARGET_OUTPUT_DIR} ${_JAVA_FULL})
+ file(RELATIVE_PATH _JAVA_REL_SOURCE_PATH ${CMAKE_CURRENT_SOURCE_DIR} ${_JAVA_FULL})
+ string(LENGTH ${_JAVA_REL_BINARY_PATH} _BIN_LEN)
+ string(LENGTH ${_JAVA_REL_SOURCE_PATH} _SRC_LEN)
+ if (${_BIN_LEN} LESS ${_SRC_LEN})
+ set(_JAVA_REL_PATH ${_JAVA_REL_BINARY_PATH})
+ else (${_BIN_LEN} LESS ${_SRC_LEN})
+ set(_JAVA_REL_PATH ${_JAVA_REL_SOURCE_PATH})
+ endif (${_BIN_LEN} LESS ${_SRC_LEN})
+ get_filename_component(_JAVA_REL_PATH ${_JAVA_REL_PATH} PATH)
+
+ if (_JAVA_EXT MATCHES ".java")
+ list(APPEND _JAVA_COMPILE_FILES ${_JAVA_SOURCE_FILE})
+ set(_JAVA_CLASS_FILE "${CMAKE_JAVA_CLASS_OUTPUT_PATH}/${_JAVA_REL_PATH}/${_JAVA_FILE}.class")
+ set(_JAVA_CLASS_FILES ${_JAVA_CLASS_FILES} ${_JAVA_CLASS_FILE})
+
+ elseif (_JAVA_EXT MATCHES ".jar"
+ OR _JAVA_EXT MATCHES ".war"
+ OR _JAVA_EXT MATCHES ".ear"
+ OR _JAVA_EXT MATCHES ".sar")
+ list(APPEND CMAKE_JAVA_INCLUDE_PATH ${_JAVA_SOURCE_FILE})
+
+ elseif (_JAVA_EXT STREQUAL "")
+ list(APPEND CMAKE_JAVA_INCLUDE_PATH ${JAVA_JAR_TARGET_${_JAVA_SOURCE_FILE}} ${JAVA_JAR_TARGET_${_JAVA_SOURCE_FILE}_CLASSPATH})
+ list(APPEND _JAVA_DEPENDS ${JAVA_JAR_TARGET_${_JAVA_SOURCE_FILE}})
+
+ else (_JAVA_EXT MATCHES ".java")
+ __java_copy_file(${CMAKE_CURRENT_SOURCE_DIR}/${_JAVA_SOURCE_FILE}
+ ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/${_JAVA_SOURCE_FILE}
+ "Copying ${_JAVA_SOURCE_FILE} to the build directory")
+ list(APPEND _JAVA_RESOURCE_FILES ${_JAVA_SOURCE_FILE})
+ endif (_JAVA_EXT MATCHES ".java")
+ endforeach(_JAVA_SOURCE_FILE)
+
+ # create an empty java_class_filelist
+ if (NOT EXISTS ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_class_filelist)
+ file(WRITE ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_class_filelist "")
+ endif()
+
+ if (_JAVA_COMPILE_FILES)
+ # Compile the java files and create a list of class files
+ add_custom_command(
+ # NOTE: this command generates an artificial dependency file
+ OUTPUT ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_compiled_${_TARGET_NAME}
+ COMMAND ${Java_JAVAC_EXECUTABLE}
+ ${CMAKE_JAVA_COMPILE_FLAGS}
+ -classpath "${CMAKE_JAVA_INCLUDE_PATH_FINAL}"
+ -d ${CMAKE_JAVA_CLASS_OUTPUT_PATH}
+ ${_JAVA_COMPILE_FILES}
+ COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_compiled_${_TARGET_NAME}
+ DEPENDS ${_JAVA_COMPILE_FILES}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+ COMMENT "Building Java objects for ${_TARGET_NAME}.jar"
+ )
+ add_custom_command(
+ OUTPUT ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_class_filelist
+ COMMAND ${CMAKE_COMMAND}
+ -DCMAKE_JAVA_CLASS_OUTPUT_PATH=${CMAKE_JAVA_CLASS_OUTPUT_PATH}
+ -DCMAKE_JAR_CLASSES_PREFIX="${CMAKE_JAR_CLASSES_PREFIX}"
+ -P ${_JAVA_CLASS_FILELIST_SCRIPT}
+ DEPENDS ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_compiled_${_TARGET_NAME}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+ )
+ endif (_JAVA_COMPILE_FILES)
+
+ # create the jar file
+ set(_JAVA_JAR_OUTPUT_PATH
+ ${CMAKE_JAVA_TARGET_OUTPUT_DIR}/${_JAVA_TARGET_OUTPUT_NAME})
+ if (CMAKE_JNI_TARGET)
+ add_custom_command(
+ OUTPUT ${_JAVA_JAR_OUTPUT_PATH}
+ COMMAND ${Java_JAR_EXECUTABLE}
+ -cf${_ENTRY_POINT_OPTION} ${_JAVA_JAR_OUTPUT_PATH} ${_ENTRY_POINT_VALUE}
+ ${_JAVA_RESOURCE_FILES} @java_class_filelist
+ COMMAND ${CMAKE_COMMAND}
+ -D_JAVA_TARGET_DIR=${CMAKE_JAVA_TARGET_OUTPUT_DIR}
+ -D_JAVA_TARGET_OUTPUT_NAME=${_JAVA_TARGET_OUTPUT_NAME}
+ -D_JAVA_TARGET_OUTPUT_LINK=${_JAVA_TARGET_OUTPUT_LINK}
+ -P ${_JAVA_SYMLINK_SCRIPT}
+ COMMAND ${CMAKE_COMMAND}
+ -D_JAVA_TARGET_DIR=${CMAKE_JAVA_TARGET_OUTPUT_DIR}
+ -D_JAVA_TARGET_OUTPUT_NAME=${_JAVA_JAR_OUTPUT_PATH}
+ -D_JAVA_TARGET_OUTPUT_LINK=${_JAVA_TARGET_OUTPUT_LINK}
+ -P ${_JAVA_SYMLINK_SCRIPT}
+ DEPENDS ${_JAVA_RESOURCE_FILES} ${_JAVA_DEPENDS} ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_class_filelist
+ WORKING_DIRECTORY ${CMAKE_JAVA_CLASS_OUTPUT_PATH}
+ COMMENT "Creating Java archive ${_JAVA_TARGET_OUTPUT_NAME}"
+ )
+ else ()
+ add_custom_command(
+ OUTPUT ${_JAVA_JAR_OUTPUT_PATH}
+ COMMAND ${Java_JAR_EXECUTABLE}
+ -cf${_ENTRY_POINT_OPTION} ${_JAVA_JAR_OUTPUT_PATH} ${_ENTRY_POINT_VALUE}
+ ${_JAVA_RESOURCE_FILES} @java_class_filelist
+ COMMAND ${CMAKE_COMMAND}
+ -D_JAVA_TARGET_DIR=${CMAKE_JAVA_TARGET_OUTPUT_DIR}
+ -D_JAVA_TARGET_OUTPUT_NAME=${_JAVA_TARGET_OUTPUT_NAME}
+ -D_JAVA_TARGET_OUTPUT_LINK=${_JAVA_TARGET_OUTPUT_LINK}
+ -P ${_JAVA_SYMLINK_SCRIPT}
+ WORKING_DIRECTORY ${CMAKE_JAVA_CLASS_OUTPUT_PATH}
+ DEPENDS ${_JAVA_RESOURCE_FILES} ${_JAVA_DEPENDS} ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_class_filelist
+ COMMENT "Creating Java archive ${_JAVA_TARGET_OUTPUT_NAME}"
+ )
+ endif (CMAKE_JNI_TARGET)
+
+ # Add the target and make sure we have the latest resource files.
+ add_custom_target(${_TARGET_NAME} ALL DEPENDS ${_JAVA_JAR_OUTPUT_PATH})
+
+ set_property(
+ TARGET
+ ${_TARGET_NAME}
+ PROPERTY
+ INSTALL_FILES
+ ${_JAVA_JAR_OUTPUT_PATH}
+ )
+
+ if (_JAVA_TARGET_OUTPUT_LINK)
+ set_property(
+ TARGET
+ ${_TARGET_NAME}
+ PROPERTY
+ INSTALL_FILES
+ ${_JAVA_JAR_OUTPUT_PATH}
+ ${CMAKE_JAVA_TARGET_OUTPUT_DIR}/${_JAVA_TARGET_OUTPUT_LINK}
+ )
+
+ if (CMAKE_JNI_TARGET)
+ set_property(
+ TARGET
+ ${_TARGET_NAME}
+ PROPERTY
+ JNI_SYMLINK
+ ${CMAKE_JAVA_TARGET_OUTPUT_DIR}/${_JAVA_TARGET_OUTPUT_LINK}
+ )
+ endif (CMAKE_JNI_TARGET)
+ endif (_JAVA_TARGET_OUTPUT_LINK)
+
+ set_property(
+ TARGET
+ ${_TARGET_NAME}
+ PROPERTY
+ JAR_FILE
+ ${_JAVA_JAR_OUTPUT_PATH}
+ )
+
+ set_property(
+ TARGET
+ ${_TARGET_NAME}
+ PROPERTY
+ CLASSDIR
+ ${CMAKE_JAVA_CLASS_OUTPUT_PATH}
+ )
+
+endfunction(add_jar)
+
+function(INSTALL_JAR _TARGET_NAME _DESTINATION)
+ get_property(__FILES
+ TARGET
+ ${_TARGET_NAME}
+ PROPERTY
+ INSTALL_FILES
+ )
+
+ if (__FILES)
+ install(
+ FILES
+ ${__FILES}
+ DESTINATION
+ ${_DESTINATION}
+ )
+ else (__FILES)
+ message(SEND_ERROR "The target ${_TARGET_NAME} is not known in this scope.")
+ endif (__FILES)
+endfunction(INSTALL_JAR _TARGET_NAME _DESTINATION)
+
+function(INSTALL_JNI_SYMLINK _TARGET_NAME _DESTINATION)
+ get_property(__SYMLINK
+ TARGET
+ ${_TARGET_NAME}
+ PROPERTY
+ JNI_SYMLINK
+ )
+
+ if (__SYMLINK)
+ install(
+ FILES
+ ${__SYMLINK}
+ DESTINATION
+ ${_DESTINATION}
+ )
+ else (__SYMLINK)
+ message(SEND_ERROR "The target ${_TARGET_NAME} is not known in this scope.")
+ endif (__SYMLINK)
+endfunction(INSTALL_JNI_SYMLINK _TARGET_NAME _DESTINATION)
+
+function (find_jar VARIABLE)
+ set(_jar_names)
+ set(_jar_files)
+ set(_jar_versions)
+ set(_jar_paths
+ /usr/share/java/
+ /usr/local/share/java/
+ ${Java_JAR_PATHS})
+ set(_jar_doc "NOTSET")
+
+ set(_state "name")
+
+ foreach (arg ${ARGN})
+ if (${_state} STREQUAL "name")
+ if (${arg} STREQUAL "VERSIONS")
+ set(_state "versions")
+ elseif (${arg} STREQUAL "NAMES")
+ set(_state "names")
+ elseif (${arg} STREQUAL "PATHS")
+ set(_state "paths")
+ elseif (${arg} STREQUAL "DOC")
+ set(_state "doc")
+ else (${arg} STREQUAL "NAMES")
+ set(_jar_names ${arg})
+ if (_jar_doc STREQUAL "NOTSET")
+ set(_jar_doc "Finding ${arg} jar")
+ endif (_jar_doc STREQUAL "NOTSET")
+ endif (${arg} STREQUAL "VERSIONS")
+ elseif (${_state} STREQUAL "versions")
+ if (${arg} STREQUAL "NAMES")
+ set(_state "names")
+ elseif (${arg} STREQUAL "PATHS")
+ set(_state "paths")
+ elseif (${arg} STREQUAL "DOC")
+ set(_state "doc")
+ else (${arg} STREQUAL "NAMES")
+ set(_jar_versions ${_jar_versions} ${arg})
+ endif (${arg} STREQUAL "NAMES")
+ elseif (${_state} STREQUAL "names")
+ if (${arg} STREQUAL "VERSIONS")
+ set(_state "versions")
+ elseif (${arg} STREQUAL "PATHS")
+ set(_state "paths")
+ elseif (${arg} STREQUAL "DOC")
+ set(_state "doc")
+ else (${arg} STREQUAL "VERSIONS")
+ set(_jar_names ${_jar_names} ${arg})
+ if (_jar_doc STREQUAL "NOTSET")
+ set(_jar_doc "Finding ${arg} jar")
+ endif (_jar_doc STREQUAL "NOTSET")
+ endif (${arg} STREQUAL "VERSIONS")
+ elseif (${_state} STREQUAL "paths")
+ if (${arg} STREQUAL "VERSIONS")
+ set(_state "versions")
+ elseif (${arg} STREQUAL "NAMES")
+ set(_state "names")
+ elseif (${arg} STREQUAL "DOC")
+ set(_state "doc")
+ else (${arg} STREQUAL "VERSIONS")
+ set(_jar_paths ${_jar_paths} ${arg})
+ endif (${arg} STREQUAL "VERSIONS")
+ elseif (${_state} STREQUAL "doc")
+ if (${arg} STREQUAL "VERSIONS")
+ set(_state "versions")
+ elseif (${arg} STREQUAL "NAMES")
+ set(_state "names")
+ elseif (${arg} STREQUAL "PATHS")
+ set(_state "paths")
+ else (${arg} STREQUAL "VERSIONS")
+ set(_jar_doc ${arg})
+ endif (${arg} STREQUAL "VERSIONS")
+ endif (${_state} STREQUAL "name")
+ endforeach (arg ${ARGN})
+
+ if (NOT _jar_names)
+ message(FATAL_ERROR "find_jar: No name to search for given")
+ endif (NOT _jar_names)
+
+ foreach (jar_name ${_jar_names})
+ foreach (version ${_jar_versions})
+ set(_jar_files ${_jar_files} ${jar_name}-${version}.jar)
+ endforeach (version ${_jar_versions})
+ set(_jar_files ${_jar_files} ${jar_name}.jar)
+ endforeach (jar_name ${_jar_names})
+
+ find_file(${VARIABLE}
+ NAMES ${_jar_files}
+ PATHS ${_jar_paths}
+ DOC ${_jar_doc}
+ NO_DEFAULT_PATH)
+endfunction (find_jar VARIABLE)
+
+function(create_javadoc _target)
+ set(_javadoc_packages)
+ set(_javadoc_files)
+ set(_javadoc_sourcepath)
+ set(_javadoc_classpath)
+ set(_javadoc_installpath "${CMAKE_INSTALL_PREFIX}/share/javadoc")
+ set(_javadoc_doctitle)
+ set(_javadoc_windowtitle)
+ set(_javadoc_author FALSE)
+ set(_javadoc_version FALSE)
+ set(_javadoc_use FALSE)
+
+ set(_state "package")
+
+ foreach (arg ${ARGN})
+ if (${_state} STREQUAL "package")
+ if (${arg} STREQUAL "PACKAGES")
+ set(_state "packages")
+ elseif (${arg} STREQUAL "FILES")
+ set(_state "files")
+ elseif (${arg} STREQUAL "SOURCEPATH")
+ set(_state "sourcepath")
+ elseif (${arg} STREQUAL "CLASSPATH")
+ set(_state "classpath")
+ elseif (${arg} STREQUAL "INSTALLPATH")
+ set(_state "installpath")
+ elseif (${arg} STREQUAL "DOCTITLE")
+ set(_state "doctitle")
+ elseif (${arg} STREQUAL "WINDOWTITLE")
+ set(_state "windowtitle")
+ elseif (${arg} STREQUAL "AUTHOR")
+ set(_state "author")
+ elseif (${arg} STREQUAL "USE")
+ set(_state "use")
+ elseif (${arg} STREQUAL "VERSION")
+ set(_state "version")
+ else ()
+ set(_javadoc_packages ${arg})
+ set(_state "packages")
+ endif ()
+ elseif (${_state} STREQUAL "packages")
+ if (${arg} STREQUAL "FILES")
+ set(_state "files")
+ elseif (${arg} STREQUAL "SOURCEPATH")
+ set(_state "sourcepath")
+ elseif (${arg} STREQUAL "CLASSPATH")
+ set(_state "classpath")
+ elseif (${arg} STREQUAL "INSTALLPATH")
+ set(_state "installpath")
+ elseif (${arg} STREQUAL "DOCTITLE")
+ set(_state "doctitle")
+ elseif (${arg} STREQUAL "WINDOWTITLE")
+ set(_state "windowtitle")
+ elseif (${arg} STREQUAL "AUTHOR")
+ set(_state "author")
+ elseif (${arg} STREQUAL "USE")
+ set(_state "use")
+ elseif (${arg} STREQUAL "VERSION")
+ set(_state "version")
+ else ()
+ list(APPEND _javadoc_packages ${arg})
+ endif ()
+ elseif (${_state} STREQUAL "files")
+ if (${arg} STREQUAL "PACKAGES")
+ set(_state "packages")
+ elseif (${arg} STREQUAL "SOURCEPATH")
+ set(_state "sourcepath")
+ elseif (${arg} STREQUAL "CLASSPATH")
+ set(_state "classpath")
+ elseif (${arg} STREQUAL "INSTALLPATH")
+ set(_state "installpath")
+ elseif (${arg} STREQUAL "DOCTITLE")
+ set(_state "doctitle")
+ elseif (${arg} STREQUAL "WINDOWTITLE")
+ set(_state "windowtitle")
+ elseif (${arg} STREQUAL "AUTHOR")
+ set(_state "author")
+ elseif (${arg} STREQUAL "USE")
+ set(_state "use")
+ elseif (${arg} STREQUAL "VERSION")
+ set(_state "version")
+ else ()
+ list(APPEND _javadoc_files ${arg})
+ endif ()
+ elseif (${_state} STREQUAL "sourcepath")
+ if (${arg} STREQUAL "PACKAGES")
+ set(_state "packages")
+ elseif (${arg} STREQUAL "FILES")
+ set(_state "files")
+ elseif (${arg} STREQUAL "CLASSPATH")
+ set(_state "classpath")
+ elseif (${arg} STREQUAL "INSTALLPATH")
+ set(_state "installpath")
+ elseif (${arg} STREQUAL "DOCTITLE")
+ set(_state "doctitle")
+ elseif (${arg} STREQUAL "WINDOWTITLE")
+ set(_state "windowtitle")
+ elseif (${arg} STREQUAL "AUTHOR")
+ set(_state "author")
+ elseif (${arg} STREQUAL "USE")
+ set(_state "use")
+ elseif (${arg} STREQUAL "VERSION")
+ set(_state "version")
+ else ()
+ list(APPEND _javadoc_sourcepath ${arg})
+ endif ()
+ elseif (${_state} STREQUAL "classpath")
+ if (${arg} STREQUAL "PACKAGES")
+ set(_state "packages")
+ elseif (${arg} STREQUAL "FILES")
+ set(_state "files")
+ elseif (${arg} STREQUAL "SOURCEPATH")
+ set(_state "sourcepath")
+ elseif (${arg} STREQUAL "INSTALLPATH")
+ set(_state "installpath")
+ elseif (${arg} STREQUAL "DOCTITLE")
+ set(_state "doctitle")
+ elseif (${arg} STREQUAL "WINDOWTITLE")
+ set(_state "windowtitle")
+ elseif (${arg} STREQUAL "AUTHOR")
+ set(_state "author")
+ elseif (${arg} STREQUAL "USE")
+ set(_state "use")
+ elseif (${arg} STREQUAL "VERSION")
+ set(_state "version")
+ else ()
+ list(APPEND _javadoc_classpath ${arg})
+ endif ()
+ elseif (${_state} STREQUAL "installpath")
+ if (${arg} STREQUAL "PACKAGES")
+ set(_state "packages")
+ elseif (${arg} STREQUAL "FILES")
+ set(_state "files")
+ elseif (${arg} STREQUAL "SOURCEPATH")
+ set(_state "sourcepath")
+ elseif (${arg} STREQUAL "DOCTITLE")
+ set(_state "doctitle")
+ elseif (${arg} STREQUAL "WINDOWTITLE")
+ set(_state "windowtitle")
+ elseif (${arg} STREQUAL "AUTHOR")
+ set(_state "author")
+ elseif (${arg} STREQUAL "USE")
+ set(_state "use")
+ elseif (${arg} STREQUAL "VERSION")
+ set(_state "version")
+ else ()
+ set(_javadoc_installpath ${arg})
+ endif ()
+ elseif (${_state} STREQUAL "doctitle")
+ if (${arg} STREQUAL "PACKAGES")
+ set(_state "packages")
+ elseif (${arg} STREQUAL "FILES")
+ set(_state "files")
+ elseif (${arg} STREQUAL "SOURCEPATH")
+ set(_state "sourcepath")
+ elseif (${arg} STREQUAL "INSTALLPATH")
+ set(_state "installpath")
+ elseif (${arg} STREQUAL "CLASSPATH")
+ set(_state "classpath")
+ elseif (${arg} STREQUAL "WINDOWTITLE")
+ set(_state "windowtitle")
+ elseif (${arg} STREQUAL "AUTHOR")
+ set(_state "author")
+ elseif (${arg} STREQUAL "USE")
+ set(_state "use")
+ elseif (${arg} STREQUAL "VERSION")
+ set(_state "version")
+ else ()
+ set(_javadoc_doctitle ${arg})
+ endif ()
+ elseif (${_state} STREQUAL "windowtitle")
+ if (${arg} STREQUAL "PACKAGES")
+ set(_state "packages")
+ elseif (${arg} STREQUAL "FILES")
+ set(_state "files")
+ elseif (${arg} STREQUAL "SOURCEPATH")
+ set(_state "sourcepath")
+ elseif (${arg} STREQUAL "CLASSPATH")
+ set(_state "classpath")
+ elseif (${arg} STREQUAL "INSTALLPATH")
+ set(_state "installpath")
+ elseif (${arg} STREQUAL "DOCTITLE")
+ set(_state "doctitle")
+ elseif (${arg} STREQUAL "AUTHOR")
+ set(_state "author")
+ elseif (${arg} STREQUAL "USE")
+ set(_state "use")
+ elseif (${arg} STREQUAL "VERSION")
+ set(_state "version")
+ else ()
+ set(_javadoc_windowtitle ${arg})
+ endif ()
+ elseif (${_state} STREQUAL "author")
+ if (${arg} STREQUAL "PACKAGES")
+ set(_state "packages")
+ elseif (${arg} STREQUAL "FILES")
+ set(_state "files")
+ elseif (${arg} STREQUAL "SOURCEPATH")
+ set(_state "sourcepath")