This commit is contained in:
Lana Steuck 2014-07-09 10:42:37 -07:00
commit 83fc52870b
1119 changed files with 39264 additions and 25708 deletions

View File

@ -373,7 +373,14 @@ ifeq ($(OPENJDK_TARGET_OS), windows)
POLICY_SRC_LIST += $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS)/lib/security/java.policy
endif
ifndef OPENJDK
ifneq (, $(filter $(OPENJDK_TARGET_OS), windows solaris))
ifeq ($(OPENJDK_TARGET_OS), windows)
ifeq ($(OPENJDK_TARGET_CPU_BITS), 32)
POLICY_SRC_LIST += $(JDK_TOPDIR)/src/closed/$(OPENJDK_TARGET_OS)/lib/security/java.policy-win32
else
POLICY_SRC_LIST += $(JDK_TOPDIR)/src/closed/$(OPENJDK_TARGET_OS)/lib/security/java.policy-win64
endif
endif
ifeq ($(OPENJDK_TARGET_OS), solaris)
POLICY_SRC_LIST += $(JDK_TOPDIR)/src/closed/$(OPENJDK_TARGET_OS)/lib/security/java.policy
endif
endif

View File

@ -62,7 +62,7 @@ GENDATA += $(GENDATA_UNINAME)
##########################################################################################
GENDATA_CURDATA := $(JDK_OUTPUTDIR)/lib/currency.data
GENDATA_CURDATA := $(JDK_OUTPUTDIR)/classes/java/util/currency.data
$(GENDATA_CURDATA): $(JDK_TOPDIR)/make/data/currency/CurrencyData.properties $(BUILD_TOOLS)
$(MKDIR) -p $(@D)

View File

@ -27,7 +27,7 @@ DISABLE_WARNINGS := -Xlint:all,-deprecation,-unchecked,-rawtypes,-cast,-serial,-
# To build with all warnings enabled, do the following:
# make JAVAC_WARNINGS="-Xlint:all -Xmaxwarns 10000"
JAVAC_WARNINGS := -Xlint:-unchecked,-deprecation,-overrides,auxiliaryclass,cast,classfile,dep-ann,divzero,empty,fallthrough,overloads,serial,static,try,varargs -Werror
JAVAC_WARNINGS := -Xlint:all,-deprecation,-rawtypes,-unchecked -Werror
# Any java code executed during a JDK build to build other parts of the JDK must be
# executed by the bootstrap JDK (probably with -Xbootclasspath/p: ) and for this

View File

@ -319,7 +319,6 @@ endif
ifeq ($(OPENJDK_TARGET_OS), macosx)
LIBAWT_FILES += awt_LoadLibrary.c
LIBAWT_CFLAGS += -F/System/Library/Frameworks/JavaVM.framework/Frameworks
endif
ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH), solaris-sparc)
@ -484,7 +483,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBAWT, \
LDFLAGS_SUFFIX_macosx := -lmlib_image -ljvm $(LIBM) \
-framework Cocoa \
-framework OpenGL \
-F/System/Library/Frameworks/JavaVM.framework/Frameworks \
-framework JavaNativeFoundation \
-framework JavaRuntimeSupport \
-framework ApplicationServices \
@ -709,21 +707,24 @@ $(BUILD_LIBLCMS): $(BUILD_LIBAWT)
##########################################################################################
BUILD_LIBJAVAJPEG_DIR := $(JDK_TOPDIR)/src/share/native/sun/awt/image/jpeg
ifdef OPENJDK
BUILD_LIBJPEG_MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libjpeg/mapfile-vers
BUILD_LIBJAVAJPEG_MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libjpeg/mapfile-vers
else
BUILD_LIBJPEG_MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libjpeg/mapfile-vers-closed
BUILD_LIBJPEG_CLOSED_SRC := $(JDK_TOPDIR)/src/closed/share/native/sun/awt/image/jpeg
BUILD_LIBJPEG_CLOSED_INCLUDES := -I$(BUILD_LIBJPEG_CLOSED_SRC)
BUILD_LIBJAVAJPEG_MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libjpeg/mapfile-vers-closed
BUILD_LIBJAVAJPEG_CLOSED_SRC := $(JDK_TOPDIR)/src/closed/share/native/sun/awt/image/jpeg
BUILD_LIBJAVAJPEG_CLOSED_INCLUDES := -I$(BUILD_LIBJAVAJPEG_CLOSED_SRC)
endif
BUILD_LIBJPEG_REORDER :=
BUILD_LIBJAVAJPEG_REORDER :=
ifeq ($(OPENJDK_TARGET_OS), solaris)
ifneq ($(OPENJDK_TARGET_CPU), x86_64)
BUILD_LIBJPEG_REORDER := $(JDK_TOPDIR)/make/mapfiles/libjpeg/reorder-$(OPENJDK_TARGET_CPU)
BUILD_LIBJAVAJPEG_REORDER := $(JDK_TOPDIR)/make/mapfiles/libjpeg/reorder-$(OPENJDK_TARGET_CPU)
endif
endif
# Suppress gcc warnings like "variable might be clobbered by 'longjmp'
# or 'vfork'": this warning indicates that some variable is placed to
# a register by optimized compiler and it's value might be lost on longjmp().
@ -735,37 +736,50 @@ endif
# $(shell $(EXPR) $(CC_MAJORVER) \> 4 \| \
# \( $(CC_MAJORVER) = 4 \& $(CC_MINORVER) \>= 3 \) )
# ifeq ($(CC_43_OR_NEWER), 1)
# BUILD_LIBJPEG_CFLAGS_linux += -Wno-clobbered
# BUILD_LIBJAVAJPEG_CFLAGS_linux += -Wno-clobbered
# endif
#endif
$(eval $(call SetupNativeCompilation,BUILD_LIBJPEG, \
LIBRARY := jpeg, \
ifeq ($(USE_EXTERNAL_LIBJPEG), true)
LIBJPEG_LIBS := -ljpeg
BUILD_LIBJAVAJPEG_INCLUDE_FILES := \
imageIOJPEG.c \
jpegdecoder.c
BUILD_LIBJAVAJPEG_HEADERS :=
else
LIBJPEG_LIBS :=
BUILD_LIBJAVAJPEG_INCLUDE_FILES :=
BUILD_LIBJAVAJPEG_HEADERS := -I$(BUILD_LIBJAVAJPEG_DIR)
endif
$(eval $(call SetupNativeCompilation,BUILD_LIBJAVAJPEG, \
LIBRARY := javajpeg, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(BUILD_LIBJPEG_CLOSED_SRC) \
$(JDK_TOPDIR)/src/share/native/sun/awt/image/jpeg, \
SRC := $(BUILD_LIBJAVAJPEG_CLOSED_SRC) \
$(BUILD_LIBJAVAJPEG_DIR), \
INCLUDE_FILES := $(BUILD_LIBJAVAJPEG_INCLUDE_FILES), \
LANG := C, \
OPTIMIZATION := HIGHEST, \
CFLAGS := $(CFLAGS_JDKLIB) \
$(BUILD_LIBJPEG_CLOSED_INCLUDES) \
-I$(JDK_TOPDIR)/src/share/native/sun/awt/image/jpeg, \
MAPFILE := $(BUILD_LIBJPEG_MAPFILE), \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(BUILD_LIBJAVAJPEG_CLOSED_INCLUDES) \
$(BUILD_LIBJAVAJPEG_HEADERS), \
MAPFILE := $(BUILD_LIBJAVAJPEG_MAPFILE), \
LDFLAGS := $(LDFLAGS_JDKLIB) $(LIBJPEG_LIBS) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
LDFLAGS_windows := $(WIN_JAVA_LIB) jvm.lib, \
LDFLAGS_SUFFIX := $(LDFLAGS_JDKLIB_SUFFIX), \
VERSIONINFO_RESOURCE := $(JDK_TOPDIR)/src/windows/resource/version.rc, \
RC_FLAGS := $(RC_FLAGS) \
-D "JDK_FNAME=jpeg.dll" \
-D "JDK_INTERNAL_NAME=jpeg" \
-D "JDK_FNAME=javajpeg.dll" \
-D "JDK_INTERNAL_NAME=javajpeg" \
-D "JDK_FTYPE=0x2L", \
REORDER := $(BUILD_LIBJPEG_REORDER), \
REORDER := $(BUILD_LIBJAVAJPEG_REORDER), \
OBJECT_DIR := $(JDK_OUTPUTDIR)/objs/libjpeg, \
DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES)))
$(BUILD_LIBJPEG): $(BUILD_LIBJAVA)
$(BUILD_LIBJAVAJPEG): $(BUILD_LIBJAVA)
BUILD_LIBRARIES += $(BUILD_LIBJPEG)
BUILD_LIBRARIES += $(BUILD_LIBJAVAJPEG)
##########################################################################################
@ -1130,12 +1144,6 @@ ifeq ($(BUILD_HEADLESS), true)
-I$(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/jdga \
$(foreach dir, $(LIBAWT_HEADLESS_DIRS), -I$(dir))
ifeq ($(OPENJDK_TARGET_OS), macosx)
LIBAWT_HEADLESS_CFLAGS += \
-F/System/Library/Frameworks/JavaVM.framework/Frameworks \
-F/System/Library/Frameworks/ApplicationServices.framework/Frameworks
endif
LIBAWT_HEADLESS_FILES := \
awt_Font.c \
HeadlessToolkit.c \
@ -1213,6 +1221,13 @@ ifndef BUILD_HEADLESS_ONLY
GIFLIB_CFLAGS := -I$(JDK_TOPDIR)/src/share/native/sun/awt/giflib
endif
ifeq ($(USE_EXTERNAL_LIBJPEG), true)
LIBJPEG_LDFLAGS := -ljpeg
else
LIBSPLASHSCREEN_DIRS += $(JDK_TOPDIR)/src/share/native/sun/awt/image/jpeg
LIBJPEG_CFLAGS := -I$(JDK_TOPDIR)/src/share/native/sun/awt/image/jpeg
endif
ifeq ($(USE_EXTERNAL_LIBPNG), false)
LIBSPLASHSCREEN_DIRS += $(JDK_TOPDIR)/src/share/native/sun/awt/libpng
LIBPNG_CFLAGS := -I$(JDK_TOPDIR)/src/share/native/sun/awt/libpng
@ -1229,8 +1244,7 @@ ifndef BUILD_HEADLESS_ONLY
ifeq ($(OPENJDK_TARGET_OS), macosx)
LIBSPLASHSCREEN_CFLAGS := -I$(JDK_TOPDIR)/src/macosx/native/sun/awt/splashscreen \
$(LIBSPLASHSCREEN_CFLAGS) \
-F/System/Library/Frameworks/JavaVM.framework/Frameworks
$(LIBSPLASHSCREEN_CFLAGS)
LIBSPLASHSCREEN_CFLAGS += -DWITH_MACOSX
LIBSPLASHSCREEN_CFLAGS += -I$(JDK_TOPDIR)/src/macosx/native/sun/osxapp
@ -1260,7 +1274,6 @@ ifndef BUILD_HEADLESS_ONLY
-framework ApplicationServices \
-framework Foundation \
-framework Cocoa \
-F/System/Library/Frameworks/JavaVM.framework/Frameworks \
-framework JavaNativeFoundation
else ifeq ($(OPENJDK_TARGET_OS), windows)
LIBSPLASHSCREEN_LDFLAGS_SUFFIX += kernel32.lib user32.lib gdi32.lib delayimp.lib -DELAYLOAD:user32.dll
@ -1276,12 +1289,12 @@ ifndef BUILD_HEADLESS_ONLY
LANG := C, \
OPTIMIZATION := LOW, \
CFLAGS := $(LIBSPLASHSCREEN_CFLAGS) $(CFLAGS_JDKLIB) \
$(GIFLIB_CFLAGS) $(PNG_CFLAGS), \
$(GIFLIB_CFLAGS) $(LIBJPEG_CFLAGS) $(PNG_CFLAGS), \
MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libsplashscreen/mapfile-vers, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
LDFLAGS_SUFFIX := $(LIBSPLASHSCREEN_LDFLAGS_SUFFIX) $(LIBZ) \
$(GIFLIB_LDFLAGS) $(PNG_LIBS), \
$(GIFLIB_LDFLAGS) $(LIBJPEG_LDFLAGS) $(PNG_LIBS), \
LDFLAGS_SUFFIX_solaris := -lc, \
VERSIONINFO_RESOURCE := $(JDK_TOPDIR)/src/windows/resource/version.rc, \
RC_FLAGS := $(RC_FLAGS) \
@ -1445,9 +1458,7 @@ ifeq ($(OPENJDK_TARGET_OS), macosx)
-I$(JDK_TOPDIR)/src/share/native/sun/awt/image/cvutils \
-I$(JDK_TOPDIR)/src/share/native/sun/java2d/loops \
-I$(JDK_TOPDIR)/src/share/native/sun/java2d/pipe \
-I$(JDK_TOPDIR)/src/share/native/sun/awt/debug \
-F/System/Library/Frameworks/JavaVM.framework/Frameworks \
-F/System/Library/Frameworks/ApplicationServices.framework/Frameworks, \
-I$(JDK_TOPDIR)/src/share/native/sun/awt/debug, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
LDFLAGS_SUFFIX_macosx := -lawt -lmlib_image -losxapp -ljvm $(LIBM) \
@ -1458,7 +1469,6 @@ ifeq ($(OPENJDK_TARGET_OS), macosx)
-framework Cocoa \
-framework Security \
-framework ExceptionHandling \
-F/System/Library/Frameworks/JavaVM.framework/Frameworks \
-framework JavaNativeFoundation \
-framework JavaRuntimeSupport \
-framework OpenGL \
@ -1491,8 +1501,7 @@ ifeq ($(OPENJDK_TARGET_OS), macosx)
CFLAGS := $(CFLAGS_JDKLIB) \
-I$(JDK_TOPDIR)/src/macosx/native/com/apple/laf \
-I$(JDK_TOPDIR)/src/macosx/native/sun/osxapp \
-I$(JDK_TOPDIR)/src/macosx/native/sun/awt \
-F/System/Library/Frameworks/JavaVM.framework/Frameworks, \
-I$(JDK_TOPDIR)/src/macosx/native/sun/awt, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN) \
-Xlinker -rpath -Xlinker @loader_path, \
@ -1500,7 +1509,6 @@ ifeq ($(OPENJDK_TARGET_OS), macosx)
-framework Cocoa \
-framework Carbon \
-framework ApplicationServices \
-F/System/Library/Frameworks/JavaVM.framework/Frameworks \
-framework JavaNativeFoundation \
-framework JavaRuntimeSupport \
-ljava -ljvm, \

View File

@ -306,7 +306,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBPREFS, \
LDFLAGS_SUFFIX_solaris := -ljvm -ljava -lc, \
LDFLAGS_SUFFIX_aix := -ljvm -ljava, \
LDFLAGS_SUFFIX_windows := advapi32.lib jvm.lib $(WIN_JAVA_LIB), \
LDFLAGS_SUFFIX_macosx := -ljvm -framework CoreFoundation, \
LDFLAGS_SUFFIX_macosx := -ljvm -framework CoreFoundation -framework Foundation, \
VERSIONINFO_RESOURCE := $(JDK_TOPDIR)/src/windows/resource/version.rc, \
RC_FLAGS := $(RC_FLAGS) \
-D "JDK_FNAME=prefs.dll" \

View File

@ -32,14 +32,11 @@ ifeq ($(OPENJDK_TARGET_OS), macosx)
LANG := C, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) \
-I$(JDK_TOPDIR)/src/macosx/native/apple/applescript \
-F/System/Library/Frameworks/JavaVM.framework/Frameworks \
-F/System/Library/Frameworks/ApplicationServices.framework/Frameworks, \
-I$(JDK_TOPDIR)/src/macosx/native/apple/applescript, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
LDFLAGS_SUFFIX := -framework Cocoa \
-framework Carbon \
-F/System/Library/Frameworks/JavaVM.framework/Frameworks \
-framework JavaNativeFoundation \
$(LDFLAGS_JDKLIB_SUFFIX), \
OBJECT_DIR := $(JDK_OUTPUTDIR)/objs/libAppleScriptEngine, \
@ -63,9 +60,7 @@ ifeq ($(OPENJDK_TARGET_OS), macosx)
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) \
-I$(JDK_TOPDIR)/src/macosx/native/sun/osxapp \
-I$(JDK_OUTPUTDIR)/gensrc_headers_icons \
-F/System/Library/Frameworks/JavaVM.framework/Frameworks \
-F/System/Library/Frameworks/ApplicationServices.framework/Frameworks, \
-I$(JDK_OUTPUTDIR)/gensrc_headers_icons, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
LDFLAGS_SUFFIX_macosx := \
@ -76,7 +71,6 @@ ifeq ($(OPENJDK_TARGET_OS), macosx)
-framework Cocoa \
-framework Security \
-framework ExceptionHandling \
-F/System/Library/Frameworks/JavaVM.framework/Frameworks \
-framework JavaNativeFoundation \
-framework JavaRuntimeSupport \
-framework OpenGL \
@ -107,16 +101,13 @@ ifeq ($(OPENJDK_TARGET_OS), macosx)
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) \
$(foreach dir, $(LIBOSX_DIRS), -I$(dir)) \
-I$(JDK_TOPDIR)/src/macosx/native/sun/osxapp \
-F/System/Library/Frameworks/JavaVM.framework/Frameworks \
-F/System/Library/Frameworks/ApplicationServices.framework/Frameworks, \
-I$(JDK_TOPDIR)/src/macosx/native/sun/osxapp, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
LDFLAGS_SUFFIX_macosx := \
-losxapp \
-framework Cocoa \
-framework ApplicationServices \
-F/System/Library/Frameworks/JavaVM.framework/Frameworks \
-framework JavaNativeFoundation \
-framework JavaRuntimeSupport \
-framework Security \

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@ -130,7 +130,7 @@ ifneq ($(BUILD_CRYPTO), no)
BUILD_LIBKRB5_NAME := osxkrb5
BUILD_LIBKRB5_SRC := $(JDK_TOPDIR)/src/share/native/sun/security/krb5 \
$(JDK_TOPDIR)/src/macosx/native/sun/security/krb5
BUILD_LIBKRB5_LIBS := -F/System/Library/Frameworks/JavaVM.framework/Frameworks \
BUILD_LIBKRB5_LIBS := \
-framework JavaNativeFoundation \
-framework Cocoa \
-framework SystemConfiguration \
@ -147,7 +147,6 @@ ifneq ($(BUILD_CRYPTO), no)
CFLAGS := $(CFLAGS_JDKLIB) \
-I$(JDK_TOPDIR)/src/share/native/sun/security/krb5, \
CFLAGS_windows := -I$(JDK_TOPDIR)/src/windows/native/sun/security/krb5, \
CFLAGS_macosx := -F/System/Library/Frameworks/JavaVM.framework/Frameworks, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
LDFLAGS_SUFFIX := $(BUILD_LIBKRB5_LIBS), \

View File

@ -155,6 +155,7 @@ SUNWprivate_1.1 {
g_CMpDataID;
colorValueID;
mul8table;
div8table;
jvm;
# ProcessPath entry points and data

View File

@ -56,7 +56,6 @@ PROFILE_1_JRE_LIB_FILES := \
$(OPENJDK_TARGET_CPU_LEGACY_LIB)/server/Xusage.txt \
calendars.properties \
classlist \
currency.data \
ext/localedata.jar \
ext/meta-index \
ext/sunec.jar \

View File

@ -57,6 +57,9 @@ import java.util.Map;
* @author Jasper Potts
*/
public class PainterGenerator {
private static final boolean debug = false;
//a handful of counters, incremented whenever the associated object type is encounted.
//These counters form the basis of the field and method suffixes.
//These are all 1 based, because I felt like it :-)
@ -384,16 +387,24 @@ public class PainterGenerator {
}
if (Float.isNaN(r)) {
System.err.println("[Error] Encountered NaN: encode(" + x + ", " + a + ", " + b + ", " + w + ")");
if (debug) {
System.err.println("[Error] Encountered NaN: encode(" + x + ", " + a + ", " + b + ", " + w + ")");
}
return 0;
} else if (Float.isInfinite(r)) {
System.err.println("[Error] Encountered Infinity: encode(" + x + ", " + a + ", " + b + ", " + w + ")");
if (debug) {
System.err.println("[Error] Encountered Infinity: encode(" + x + ", " + a + ", " + b + ", " + w + ")");
}
return 0;
} else if (r < 0) {
System.err.println("[Error] encoded value was less than 0: encode(" + x + ", " + a + ", " + b + ", " + w + ")");
if (debug) {
System.err.println("[Error] encoded value was less than 0: encode(" + x + ", " + a + ", " + b + ", " + w + ")");
}
return 0;
} else if (r > 3) {
System.err.println("[Error] encoded value was greater than 3: encode(" + x + ", " + a + ", " + b + ", " + w + ")");
if (debug) {
System.err.println("[Error] encoded value was greater than 3: encode(" + x + ", " + a + ", " + b + ", " + w + ")");
}
return 3;
} else {
return r;

View File

@ -1,180 +0,0 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* Copyright (c) 2012, Stephen Colebourne & Michael Nascimento Santos
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of JSR-310 nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package build.tools.tzdb;
/**
* A standard set of date/time fields.
*
* @since 1.8
*/
enum ChronoField {
/**
* The second-of-minute.
* <p>
* This counts the second within the minute, from 0 to 59.
* This field has the same meaning for all calendar systems.
*/
SECOND_OF_MINUTE("SecondOfMinute", 0, 59),
/**
* The second-of-day.
* <p>
* This counts the second within the day, from 0 to (24 * 60 * 60) - 1.
* This field has the same meaning for all calendar systems.
*/
SECOND_OF_DAY("SecondOfDay", 0, 86400 - 1),
/**
* The minute-of-hour.
* <p>
* This counts the minute within the hour, from 0 to 59.
* This field has the same meaning for all calendar systems.
*/
MINUTE_OF_HOUR("MinuteOfHour", 0, 59),
/**
* The hour-of-day.
* <p>
* This counts the hour within the day, from 0 to 23.
* This is the hour that would be observed on a standard 24-hour digital clock.
* This field has the same meaning for all calendar systems.
*/
HOUR_OF_DAY("HourOfDay", 0, 23),
/**
* The day-of-month.
* <p>
* This represents the concept of the day within the month.
* In the default ISO calendar system, this has values from 1 to 31 in most months.
* April, June, September, November have days from 1 to 30, while February has days
* from 1 to 28, or 29 in a leap year.
* <p>
* Non-ISO calendar systems should implement this field using the most recognized
* day-of-month values for users of the calendar system.
* Normally, this is a count of days from 1 to the length of the month.
*/
DAY_OF_MONTH("DayOfMonth", 1, 31),
/**
* The month-of-year, such as March.
* <p>
* This represents the concept of the month within the year.
* In the default ISO calendar system, this has values from January (1) to December (12).
* <p>
* Non-ISO calendar systems should implement this field using the most recognized
* month-of-year values for users of the calendar system.
* Normally, this is a count of months starting from 1.
*/
MONTH_OF_YEAR("MonthOfYear", 1, 12),
/**
* The proleptic year, such as 2012.
* <p>
* This represents the concept of the year, counting sequentially and using negative numbers.
* The proleptic year is not interpreted in terms of the era.
* See {@link #YEAR_OF_ERA} for an example showing the mapping from proleptic year to year-of-era.
* <p>
* The standard mental model for a date is based on three concepts - year, month and day.
* These map onto the {@code YEAR}, {@code MONTH_OF_YEAR} and {@code DAY_OF_MONTH} fields.
* Note that there is no reference to eras.
* The full model for a date requires four concepts - era, year, month and day. These map onto
* the {@code ERA}, {@code YEAR_OF_ERA}, {@code MONTH_OF_YEAR} and {@code DAY_OF_MONTH} fields.
* Whether this field or {@code YEAR_OF_ERA} is used depends on which mental model is being used.
* See {@link ChronoLocalDate} for more discussion on this topic.
* <p>
* Non-ISO calendar systems should implement this field as follows.
* If the calendar system has only two eras, before and after a fixed date, then the
* proleptic-year value must be the same as the year-of-era value for the later era,
* and increasingly negative for the earlier era.
* If the calendar system has more than two eras, then the proleptic-year value may be
* defined with any appropriate value, although defining it to be the same as ISO may be
* the best option.
*/
YEAR("Year", -999_999_999, 999_999_999);
private final String name;
private final int min;
private final int max;
private ChronoField(String name, int min, int max) {
this.name = name;
this.min= min;
this.max= max;
}
/**
* Checks that the specified value is valid for this field.
* <p>
*
* @param value the value to check
* @return the value that was passed in
*/
public int checkValidValue(int value) {
if (value >= min && value <= max) {
return value;
}
throw new DateTimeException("Invalid value for " + name + " value: " + value);
}
public String toString() {
return name;
}
}

View File

@ -1,98 +0,0 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* Copyright (c) 2008-2012, Stephen Colebourne & Michael Nascimento Santos
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of JSR-310 nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package build.tools.tzdb;
/**
* Exception used to indicate a problem while calculating a date-time.
* <p>
* This exception is used to indicate problems with creating, querying
* and manipulating date-time objects.
*
* @since 1.8
*/
class DateTimeException extends RuntimeException {
/**
* Serialization version.
*/
private static final long serialVersionUID = -1632418723876261839L;
/**
* Constructs a new date-time exception with the specified message.
*
* @param message the message to use for this exception, may be null
*/
public DateTimeException(String message) {
super(message);
}
/**
* Constructs a new date-time exception with the specified message and cause.
*
* @param message the message to use for this exception, may be null
* @param cause the cause of the exception, may be null
*/
public DateTimeException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -1,363 +0,0 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* Copyright (c) 2007-2012, Stephen Colebourne & Michael Nascimento Santos
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of JSR-310 nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package build.tools.tzdb;
import static build.tools.tzdb.Utils.*;
import static build.tools.tzdb.LocalTime.SECONDS_PER_DAY;
import static build.tools.tzdb.ChronoField.DAY_OF_MONTH;
import static build.tools.tzdb.ChronoField.MONTH_OF_YEAR;
import static build.tools.tzdb.ChronoField.YEAR;
import java.util.Objects;
/**
* A date without a time-zone in the ISO-8601 calendar system,
* such as {@code 2007-12-03}.
*
* @since 1.8
*/
final class LocalDate {
/**
* The minimum supported {@code LocalDate}, '-999999999-01-01'.
* This could be used by an application as a "far past" date.
*/
public static final LocalDate MIN = new LocalDate(YEAR_MIN_VALUE, 1, 1);
/**
* The maximum supported {@code LocalDate}, '+999999999-12-31'.
* This could be used by an application as a "far future" date.
*/
public static final LocalDate MAX = new LocalDate(YEAR_MAX_VALUE, 12, 31);
/**
* The number of days in a 400 year cycle.
*/
private static final int DAYS_PER_CYCLE = 146097;
/**
* The number of days from year zero to year 1970.
* There are five 400 year cycles from year zero to 2000.
* There are 7 leap years from 1970 to 2000.
*/
static final long DAYS_0000_TO_1970 = (DAYS_PER_CYCLE * 5L) - (30L * 365L + 7L);
/**
* The year.
*/
private final int year;
/**
* The month-of-year.
*/
private final short month;
/**
* The day-of-month.
*/
private final short day;
/**
* Obtains an instance of {@code LocalDate} from a year, month and day.
* <p>
* The day must be valid for the year and month, otherwise an exception will be thrown.
*
* @param year the year to represent, from MIN_YEAR to MAX_YEAR
* @param month the month-of-year to represent, from 1 (January) to 12 (December)
* @param dayOfMonth the day-of-month to represent, from 1 to 31
* @return the local date, not null
* @throws DateTimeException if the value of any field is out of range
* @throws DateTimeException if the day-of-month is invalid for the month-year
*/
public static LocalDate of(int year, int month, int dayOfMonth) {
YEAR.checkValidValue(year);
MONTH_OF_YEAR.checkValidValue(month);
DAY_OF_MONTH.checkValidValue(dayOfMonth);
if (dayOfMonth > 28 && dayOfMonth > lengthOfMonth(month, isLeapYear(year))) {
if (dayOfMonth == 29) {
throw new DateTimeException("Invalid date 'February 29' as '" + year + "' is not a leap year");
} else {
throw new DateTimeException("Invalid date '" + month + " " + dayOfMonth + "'");
}
}
return new LocalDate(year, month, dayOfMonth);
}
/**
* Constructor, previously validated.
*
* @param year the year to represent, from MIN_YEAR to MAX_YEAR
* @param month the month-of-year to represent, not null
* @param dayOfMonth the day-of-month to represent, valid for year-month, from 1 to 31
*/
private LocalDate(int year, int month, int dayOfMonth) {
this.year = year;
this.month = (short) month;
this.day = (short) dayOfMonth;
}
/**
* Gets the year field.
* <p>
* This method returns the primitive {@code int} value for the year.
* <p>
* The year returned by this method is proleptic as per {@code get(YEAR)}.
* To obtain the year-of-era, use {@code get(YEAR_OF_ERA}.
*
* @return the year, from MIN_YEAR to MAX_YEAR
*/
public int getYear() {
return year;
}
/**
* Gets the month-of-year field as an int from 1 to 12.
*
* @return the month-of-year
*/
public int getMonth() {
return month;
}
/**
* Gets the day-of-month field.
* <p>
* This method returns the primitive {@code int} value for the day-of-month.
*
* @return the day-of-month, from 1 to 31
*/
public int getDayOfMonth() {
return day;
}
/**
* Gets the day-of-week field, which is an int from 1 to 7.
*
* @return the day-of-week
*/
public int getDayOfWeek() {
return (int)floorMod(toEpochDay() + 3, 7) + 1;
}
/**
* Returns a copy of this {@code LocalDate} with the specified number of days added.
* <p>
* This method adds the specified amount to the days field incrementing the
* month and year fields as necessary to ensure the result remains valid.
* The result is only invalid if the maximum/minimum year is exceeded.
* <p>
* For example, 2008-12-31 plus one day would result in 2009-01-01.
* <p>
* This instance is immutable and unaffected by this method call.
*
* @param daysToAdd the days to add, may be negative
* @return a {@code LocalDate} based on this date with the days added, not null
* @throws DateTimeException if the result exceeds the supported date range
*/
public LocalDate plusDays(long daysToAdd) {
if (daysToAdd == 0) {
return this;
}
long mjDay = addExact(toEpochDay(), daysToAdd);
return LocalDate.ofEpochDay(mjDay);
}
/**
* Returns a copy of this {@code LocalDate} with the specified number of days subtracted.
* <p>
* This method subtracts the specified amount from the days field decrementing the
* month and year fields as necessary to ensure the result remains valid.
* The result is only invalid if the maximum/minimum year is exceeded.
* <p>
* For example, 2009-01-01 minus one day would result in 2008-12-31.
* <p>
* This instance is immutable and unaffected by this method call.
*
* @param daysToSubtract the days to subtract, may be negative
* @return a {@code LocalDate} based on this date with the days subtracted, not null
* @throws DateTimeException if the result exceeds the supported date range
*/
public LocalDate minusDays(long daysToSubtract) {
return (daysToSubtract == Long.MIN_VALUE ? plusDays(Long.MAX_VALUE).plusDays(1) : plusDays(-daysToSubtract));
}
/**
* Obtains an instance of {@code LocalDate} from the epoch day count.
* <p>
* The Epoch Day count is a simple incrementing count of days
* where day 0 is 1970-01-01. Negative numbers represent earlier days.
*
* @param epochDay the Epoch Day to convert, based on the epoch 1970-01-01
* @return the local date, not null
* @throws DateTimeException if the epoch days exceeds the supported date range
*/
public static LocalDate ofEpochDay(long epochDay) {
long zeroDay = epochDay + DAYS_0000_TO_1970;
// find the march-based year
zeroDay -= 60; // adjust to 0000-03-01 so leap day is at end of four year cycle
long adjust = 0;
if (zeroDay < 0) {
// adjust negative years to positive for calculation
long adjustCycles = (zeroDay + 1) / DAYS_PER_CYCLE - 1;
adjust = adjustCycles * 400;
zeroDay += -adjustCycles * DAYS_PER_CYCLE;
}
long yearEst = (400 * zeroDay + 591) / DAYS_PER_CYCLE;
long doyEst = zeroDay - (365 * yearEst + yearEst / 4 - yearEst / 100 + yearEst / 400);
if (doyEst < 0) {
// fix estimate
yearEst--;
doyEst = zeroDay - (365 * yearEst + yearEst / 4 - yearEst / 100 + yearEst / 400);
}
yearEst += adjust; // reset any negative year
int marchDoy0 = (int) doyEst;
// convert march-based values back to january-based
int marchMonth0 = (marchDoy0 * 5 + 2) / 153;
int month = (marchMonth0 + 2) % 12 + 1;
int dom = marchDoy0 - (marchMonth0 * 306 + 5) / 10 + 1;
yearEst += marchMonth0 / 10;
// check year now we are certain it is correct
int year = YEAR.checkValidValue((int)yearEst);
return new LocalDate(year, month, dom);
}
public long toEpochDay() {
long y = year;
long m = month;
long total = 0;
total += 365 * y;
if (y >= 0) {
total += (y + 3) / 4 - (y + 99) / 100 + (y + 399) / 400;
} else {
total -= y / -4 - y / -100 + y / -400;
}
total += ((367 * m - 362) / 12);
total += day - 1;
if (m > 2) {
total--;
if (isLeapYear(year) == false) {
total--;
}
}
return total - DAYS_0000_TO_1970;
}
/**
* Compares this date to another date.
* <p>
* The comparison is primarily based on the date, from earliest to latest.
* It is "consistent with equals", as defined by {@link Comparable}.
* <p>
* If all the dates being compared are instances of {@code LocalDate},
* then the comparison will be entirely based on the date.
* If some dates being compared are in different chronologies, then the
* chronology is also considered, see {@link java.time.temporal.ChronoLocalDate#compareTo}.
*
* @param other the other date to compare to, not null
* @return the comparator value, negative if less, positive if greater
*/
public int compareTo(LocalDate otherDate) {
int cmp = (year - otherDate.year);
if (cmp == 0) {
cmp = (month - otherDate.month);
if (cmp == 0) {
cmp = (day - otherDate.day);
}
}
return cmp;
}
/**
* Checks if this date is equal to another date.
* <p>
* Compares this {@code LocalDate} with another ensuring that the date is the same.
* <p>
* Only objects of type {@code LocalDate} are compared, other types return false.
* To compare the dates of two {@code TemporalAccessor} instances, including dates
* in two different chronologies, use {@link ChronoField#EPOCH_DAY} as a comparator.
*
* @param obj the object to check, null returns false
* @return true if this is equal to the other date
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof LocalDate) {
return compareTo((LocalDate) obj) == 0;
}
return false;
}
/**
* A hash code for this date.
*
* @return a suitable hash code
*/
@Override
public int hashCode() {
int yearValue = year;
int monthValue = month;
int dayValue = day;
return (yearValue & 0xFFFFF800) ^ ((yearValue << 11) + (monthValue << 6) + (dayValue));
}
}

View File

@ -1,427 +0,0 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* Copyright (c) 2007-2012, Stephen Colebourne & Michael Nascimento Santos
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of JSR-310 nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package build.tools.tzdb;
import static build.tools.tzdb.Utils.*;
import static build.tools.tzdb.LocalTime.HOURS_PER_DAY;
import static build.tools.tzdb.LocalTime.MICROS_PER_DAY;
import static build.tools.tzdb.LocalTime.MILLIS_PER_DAY;
import static build.tools.tzdb.LocalTime.MINUTES_PER_DAY;
import static build.tools.tzdb.LocalTime.SECONDS_PER_DAY;
import static build.tools.tzdb.LocalTime.SECONDS_PER_MINUTE;
import static build.tools.tzdb.LocalTime.SECONDS_PER_HOUR;
import java.util.Objects;
/**
* A date-time without a time-zone in the ISO-8601 calendar system,
* such as {@code 2007-12-03T10:15:30}.
*
* @since 1.8
*/
final class LocalDateTime {
/**
* The minimum supported {@code LocalDateTime}, '-999999999-01-01T00:00:00'.
* This is the local date-time of midnight at the start of the minimum date.
* This combines {@link LocalDate#MIN} and {@link LocalTime#MIN}.
* This could be used by an application as a "far past" date-time.
*/
public static final LocalDateTime MIN = LocalDateTime.of(LocalDate.MIN, LocalTime.MIN);
/**
* The maximum supported {@code LocalDateTime}, '+999999999-12-31T23:59:59.999999999'.
* This is the local date-time just before midnight at the end of the maximum date.
* This combines {@link LocalDate#MAX} and {@link LocalTime#MAX}.
* This could be used by an application as a "far future" date-time.
*/
public static final LocalDateTime MAX = LocalDateTime.of(LocalDate.MAX, LocalTime.MAX);
/**
* The date part.
*/
private final LocalDate date;
/**
* The time part.
*/
private final LocalTime time;
/**
* Obtains an instance of {@code LocalDateTime} from year, month,
* day, hour and minute, setting the second and nanosecond to zero.
* <p>
* The day must be valid for the year and month, otherwise an exception will be thrown.
* The second and nanosecond fields will be set to zero.
*
* @param year the year to represent, from MIN_YEAR to MAX_YEAR
* @param month the month-of-year to represent, from 1 (January) to 12 (December)
* @param dayOfMonth the day-of-month to represent, from 1 to 31
* @param hour the hour-of-day to represent, from 0 to 23
* @param minute the minute-of-hour to represent, from 0 to 59
* @return the local date-time, not null
* @throws DateTimeException if the value of any field is out of range
* @throws DateTimeException if the day-of-month is invalid for the month-year
*/
public static LocalDateTime of(int year, int month, int dayOfMonth, int hour, int minute) {
LocalDate date = LocalDate.of(year, month, dayOfMonth);
LocalTime time = LocalTime.of(hour, minute);
return new LocalDateTime(date, time);
}
/**
* Obtains an instance of {@code LocalDateTime} from a date and time.
*
* @param date the local date, not null
* @param time the local time, not null
* @return the local date-time, not null
*/
public static LocalDateTime of(LocalDate date, LocalTime time) {
Objects.requireNonNull(date, "date");
Objects.requireNonNull(time, "time");
return new LocalDateTime(date, time);
}
/**
* Obtains an instance of {@code LocalDateTime} using seconds from the
* epoch of 1970-01-01T00:00:00Z.
* <p>
* This allows the {@link ChronoField#INSTANT_SECONDS epoch-second} field
* to be converted to a local date-time. This is primarily intended for
* low-level conversions rather than general application usage.
*
* @param epochSecond the number of seconds from the epoch of 1970-01-01T00:00:00Z
* @param nanoOfSecond the nanosecond within the second, from 0 to 999,999,999
* @param offset the zone offset, not null
* @return the local date-time, not null
* @throws DateTimeException if the result exceeds the supported range
*/
public static LocalDateTime ofEpochSecond(long epochSecond, int nanoOfSecond, ZoneOffset offset) {
Objects.requireNonNull(offset, "offset");
long localSecond = epochSecond + offset.getTotalSeconds(); // overflow caught later
long localEpochDay = floorDiv(localSecond, SECONDS_PER_DAY);
int secsOfDay = (int)floorMod(localSecond, SECONDS_PER_DAY);
LocalDate date = LocalDate.ofEpochDay(localEpochDay);
LocalTime time = LocalTime.ofSecondOfDay(secsOfDay); // ignore nano
return new LocalDateTime(date, time);
}
/**
* Constructor.
*
* @param date the date part of the date-time, validated not null
* @param time the time part of the date-time, validated not null
*/
private LocalDateTime(LocalDate date, LocalTime time) {
this.date = date;
this.time = time;
}
/**
* Returns a copy of this date-time with the new date and time, checking
* to see if a new object is in fact required.
*
* @param newDate the date of the new date-time, not null
* @param newTime the time of the new date-time, not null
* @return the date-time, not null
*/
private LocalDateTime with(LocalDate newDate, LocalTime newTime) {
if (date == newDate && time == newTime) {
return this;
}
return new LocalDateTime(newDate, newTime);
}
/**
* Gets the {@code LocalDate} part of this date-time.
* <p>
* This returns a {@code LocalDate} with the same year, month and day
* as this date-time.
*
* @return the date part of this date-time, not null
*/
public LocalDate getDate() {
return date;
}
/**
* Gets the year field.
* <p>
* This method returns the primitive {@code int} value for the year.
* <p>
* The year returned by this method is proleptic as per {@code get(YEAR)}.
* To obtain the year-of-era, use {@code get(YEAR_OF_ERA}.
*
* @return the year, from MIN_YEAR to MAX_YEAR
*/
public int getYear() {
return date.getYear();
}
/**
* Gets the month-of-year field as an int from 1 to 12.
*
* @return the month-of-year
*/
public int getMonth() {
return date.getMonth();
}
/**
* Gets the day-of-month field.
* <p>
* This method returns the primitive {@code int} value for the day-of-month.
*
* @return the day-of-month, from 1 to 31
*/
public int getDayOfMonth() {
return date.getDayOfMonth();
}
/**
* Gets the day-of-week field, which is an integer from 1 to 7.
*
* @return the day-of-week, from 1 to 7
*/
public int getDayOfWeek() {
return date.getDayOfWeek();
}
/**
* Gets the {@code LocalTime} part of this date-time.
* <p>
* This returns a {@code LocalTime} with the same hour, minute, second and
* nanosecond as this date-time.
*
* @return the time part of this date-time, not null
*/
public LocalTime getTime() {
return time;
}
/**
* Gets the hour-of-day field.
*
* @return the hour-of-day, from 0 to 23
*/
public int getHour() {
return time.getHour();
}
/**
* Gets the minute-of-hour field.
*
* @return the minute-of-hour, from 0 to 59
*/
public int getMinute() {
return time.getMinute();
}
/**
* Gets the second-of-minute field.
*
* @return the second-of-minute, from 0 to 59
*/
public int getSecond() {
return time.getSecond();
}
/**
* Converts this date-time to the number of seconds from the epoch
* of 1970-01-01T00:00:00Z.
* <p>
* This combines this local date-time and the specified offset to calculate the
* epoch-second value, which is the number of elapsed seconds from 1970-01-01T00:00:00Z.
* Instants on the time-line after the epoch are positive, earlier are negative.
* <p>
* This default implementation calculates from the epoch-day of the date and the
* second-of-day of the time.
*
* @param offset the offset to use for the conversion, not null
* @return the number of seconds from the epoch of 1970-01-01T00:00:00Z
*/
public long toEpochSecond(ZoneOffset offset) {
Objects.requireNonNull(offset, "offset");
long epochDay = getDate().toEpochDay();
long secs = epochDay * 86400 + getTime().toSecondOfDay();
secs -= offset.getTotalSeconds();
return secs;
}
/**
* Returns a copy of this {@code LocalDateTime} with the specified period in days added.
* <p>
* This method adds the specified amount to the days field incrementing the
* month and year fields as necessary to ensure the result remains valid.
* The result is only invalid if the maximum/minimum year is exceeded.
* <p>
* For example, 2008-12-31 plus one day would result in 2009-01-01.
* <p>
* This instance is immutable and unaffected by this method call.
*
* @param days the days to add, may be negative
* @return a {@code LocalDateTime} based on this date-time with the days added, not null
* @throws DateTimeException if the result exceeds the supported date range
*/
public LocalDateTime plusDays(long days) {
LocalDate newDate = date.plusDays(days);
return with(newDate, time);
}
/**
* Returns a copy of this {@code LocalDateTime} with the specified period in seconds added.
* <p>
* This instance is immutable and unaffected by this method call.
*
* @param seconds the seconds to add, may be negative
* @return a {@code LocalDateTime} based on this date-time with the seconds added, not null
* @throws DateTimeException if the result exceeds the supported date range
*/
public LocalDateTime plusSeconds(long seconds) {
return plusWithOverflow(date, 0, 0, seconds, 1);
}
/**
* Returns a copy of this {@code LocalDateTime} with the specified period added.
* <p>
* This instance is immutable and unaffected by this method call.
*
* @param newDate the new date to base the calculation on, not null
* @param hours the hours to add, may be negative
* @param minutes the minutes to add, may be negative
* @param seconds the seconds to add, may be negative
* @param nanos the nanos to add, may be negative
* @param sign the sign to determine add or subtract
* @return the combined result, not null
*/
private LocalDateTime plusWithOverflow(LocalDate newDate, long hours, long minutes, long seconds, int sign) {
if ((hours | minutes | seconds) == 0) {
return with(newDate, time);
}
long totDays = seconds / SECONDS_PER_DAY + // max/24*60*60
minutes / MINUTES_PER_DAY + // max/24*60
hours / HOURS_PER_DAY; // max/24
totDays *= sign; // total max*0.4237...
long totSecs = (seconds % SECONDS_PER_DAY) +
(minutes % MINUTES_PER_DAY) * SECONDS_PER_MINUTE +
(hours % HOURS_PER_DAY) * SECONDS_PER_HOUR;
long curSoD = time.toSecondOfDay();
totSecs = totSecs * sign + curSoD; // total 432000000000000
totDays += floorDiv(totSecs, SECONDS_PER_DAY);
int newSoD = (int)floorMod(totSecs, SECONDS_PER_DAY);
LocalTime newTime = (newSoD == curSoD ? time : LocalTime.ofSecondOfDay(newSoD));
return with(newDate.plusDays(totDays), newTime);
}
/**
* Compares this date-time to another date-time.
* <p>
* The comparison is primarily based on the date-time, from earliest to latest.
* It is "consistent with equals", as defined by {@link Comparable}.
* <p>
* If all the date-times being compared are instances of {@code LocalDateTime},
* then the comparison will be entirely based on the date-time.
* If some dates being compared are in different chronologies, then the
* chronology is also considered, see {@link ChronoLocalDateTime#compareTo}.
*
* @param other the other date-time to compare to, not null
* @return the comparator value, negative if less, positive if greater
*/
public int compareTo(LocalDateTime other) {
int cmp = date.compareTo(other.getDate());
if (cmp == 0) {
cmp = time.compareTo(other.getTime());
}
return cmp;
}
/**
* Checks if this date-time is equal to another date-time.
* <p>
* Compares this {@code LocalDateTime} with another ensuring that the date-time is the same.
* Only objects of type {@code LocalDateTime} are compared, other types return false.
*
* @param obj the object to check, null returns false
* @return true if this is equal to the other date-time
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof LocalDateTime) {
LocalDateTime other = (LocalDateTime) obj;
return date.equals(other.date) && time.equals(other.time);
}
return false;
}
/**
* A hash code for this date-time.
*
* @return a suitable hash code
*/
@Override
public int hashCode() {
return date.hashCode() ^ time.hashCode();
}
}

View File

@ -1,388 +0,0 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* Copyright (c) 2007-2012, Stephen Colebourne & Michael Nascimento Santos
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of JSR-310 nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package build.tools.tzdb;
import static build.tools.tzdb.ChronoField.HOUR_OF_DAY;
import static build.tools.tzdb.ChronoField.MINUTE_OF_HOUR;
import static build.tools.tzdb.ChronoField.SECOND_OF_MINUTE;
import static build.tools.tzdb.ChronoField.SECOND_OF_DAY;
import java.util.Objects;
/**
* A time without time-zone in the ISO-8601 calendar system,
* such as {@code 10:15:30}.
*
*/
final class LocalTime {
/**
* The minimum supported {@code LocalTime}, '00:00'.
* This is the time of midnight at the start of the day.
*/
public static final LocalTime MIN;
/**
* The minimum supported {@code LocalTime}, '23:59:59.999999999'.
* This is the time just before midnight at the end of the day.
*/
public static final LocalTime MAX;
/**
* The time of midnight at the start of the day, '00:00'.
*/
public static final LocalTime MIDNIGHT;
/**
* The time of noon in the middle of the day, '12:00'.
*/
public static final LocalTime NOON;
/**
* Constants for the local time of each hour.
*/
private static final LocalTime[] HOURS = new LocalTime[24];
static {
for (int i = 0; i < HOURS.length; i++) {
HOURS[i] = new LocalTime(i, 0, 0);
}
MIDNIGHT = HOURS[0];
NOON = HOURS[12];
MIN = HOURS[0];
MAX = new LocalTime(23, 59, 59);
}
/**
* Hours per day.
*/
static final int HOURS_PER_DAY = 24;
/**
* Minutes per hour.
*/
static final int MINUTES_PER_HOUR = 60;
/**
* Minutes per day.
*/
static final int MINUTES_PER_DAY = MINUTES_PER_HOUR * HOURS_PER_DAY;
/**
* Seconds per minute.
*/
static final int SECONDS_PER_MINUTE = 60;
/**
* Seconds per hour.
*/
static final int SECONDS_PER_HOUR = SECONDS_PER_MINUTE * MINUTES_PER_HOUR;
/**
* Seconds per day.
*/
static final int SECONDS_PER_DAY = SECONDS_PER_HOUR * HOURS_PER_DAY;
/**
* Milliseconds per day.
*/
static final long MILLIS_PER_DAY = SECONDS_PER_DAY * 1000L;
/**
* Microseconds per day.
*/
static final long MICROS_PER_DAY = SECONDS_PER_DAY * 1000_000L;
/**
* The hour.
*/
private final byte hour;
/**
* The minute.
*/
private final byte minute;
/**
* The second.
*/
private final byte second;
/**
* Obtains an instance of {@code LocalTime} from an hour and minute.
* <p>
* The second and nanosecond fields will be set to zero by this factory method.
* <p>
* This factory may return a cached value, but applications must not rely on this.
*
* @param hour the hour-of-day to represent, from 0 to 23
* @param minute the minute-of-hour to represent, from 0 to 59
* @return the local time, not null
* @throws DateTimeException if the value of any field is out of range
*/
public static LocalTime of(int hour, int minute) {
HOUR_OF_DAY.checkValidValue(hour);
if (minute == 0) {
return HOURS[hour]; // for performance
}
MINUTE_OF_HOUR.checkValidValue(minute);
return new LocalTime(hour, minute, 0);
}
/**
* Obtains an instance of {@code LocalTime} from an hour, minute and second.
* <p>
* The nanosecond field will be set to zero by this factory method.
* <p>
* This factory may return a cached value, but applications must not rely on this.
*
* @param hour the hour-of-day to represent, from 0 to 23
* @param minute the minute-of-hour to represent, from 0 to 59
* @param second the second-of-minute to represent, from 0 to 59
* @return the local time, not null
* @throws DateTimeException if the value of any field is out of range
*/
public static LocalTime of(int hour, int minute, int second) {
HOUR_OF_DAY.checkValidValue(hour);
if ((minute | second) == 0) {
return HOURS[hour]; // for performance
}
MINUTE_OF_HOUR.checkValidValue(minute);
SECOND_OF_MINUTE.checkValidValue(second);
return new LocalTime(hour, minute, second);
}
/**
* Obtains an instance of {@code LocalTime} from a second-of-day value.
* <p>
* This factory may return a cached value, but applications must not rely on this.
*
* @param secondOfDay the second-of-day, from {@code 0} to {@code 24 * 60 * 60 - 1}
* @return the local time, not null
* @throws DateTimeException if the second-of-day value is invalid
*/
public static LocalTime ofSecondOfDay(int secondOfDay) {
SECOND_OF_DAY.checkValidValue(secondOfDay);
int hours = secondOfDay / SECONDS_PER_HOUR;
secondOfDay -= hours * SECONDS_PER_HOUR;
int minutes = secondOfDay / SECONDS_PER_MINUTE;
secondOfDay -= minutes * SECONDS_PER_MINUTE;
return create(hours, minutes, secondOfDay);
}
/**
* Creates a local time from the hour, minute, second and nanosecond fields.
* <p>
* This factory may return a cached value, but applications must not rely on this.
*
* @param hour the hour-of-day to represent, validated from 0 to 23
* @param minute the minute-of-hour to represent, validated from 0 to 59
* @param second the second-of-minute to represent, validated from 0 to 59
* @return the local time, not null
*/
private static LocalTime create(int hour, int minute, int second) {
if ((minute | second) == 0) {
return HOURS[hour];
}
return new LocalTime(hour, minute, second);
}
/**
* Constructor, previously validated.
*
* @param hour the hour-of-day to represent, validated from 0 to 23
* @param minute the minute-of-hour to represent, validated from 0 to 59
* @param second the second-of-minute to represent, validated from 0 to 59
*/
private LocalTime(int hour, int minute, int second) {
this.hour = (byte) hour;
this.minute = (byte) minute;
this.second = (byte) second;
}
/**
* Gets the hour-of-day field.
*
* @return the hour-of-day, from 0 to 23
*/
public int getHour() {
return hour;
}
/**
* Gets the minute-of-hour field.
*
* @return the minute-of-hour, from 0 to 59
*/
public int getMinute() {
return minute;
}
/**
* Gets the second-of-minute field.
*
* @return the second-of-minute, from 0 to 59
*/
public int getSecond() {
return second;
}
/**
* Returns a copy of this {@code LocalTime} with the specified period in seconds added.
* <p>
* This adds the specified number of seconds to this time, returning a new time.
* The calculation wraps around midnight.
* <p>
* This instance is immutable and unaffected by this method call.
*
* @param secondstoAdd the seconds to add, may be negative
* @return a {@code LocalTime} based on this time with the seconds added, not null
*/
public LocalTime plusSeconds(long secondstoAdd) {
if (secondstoAdd == 0) {
return this;
}
int sofd = hour * SECONDS_PER_HOUR +
minute * SECONDS_PER_MINUTE + second;
int newSofd = ((int) (secondstoAdd % SECONDS_PER_DAY) + sofd + SECONDS_PER_DAY) % SECONDS_PER_DAY;
if (sofd == newSofd) {
return this;
}
int newHour = newSofd / SECONDS_PER_HOUR;
int newMinute = (newSofd / SECONDS_PER_MINUTE) % MINUTES_PER_HOUR;
int newSecond = newSofd % SECONDS_PER_MINUTE;
return create(newHour, newMinute, newSecond);
}
/**
* Returns a copy of this {@code LocalTime} with the specified period in seconds subtracted.
* <p>
* This subtracts the specified number of seconds from this time, returning a new time.
* The calculation wraps around midnight.
* <p>
* This instance is immutable and unaffected by this method call.
*
* @param secondsToSubtract the seconds to subtract, may be negative
* @return a {@code LocalTime} based on this time with the seconds subtracted, not null
*/
public LocalTime minusSeconds(long secondsToSubtract) {
return plusSeconds(-(secondsToSubtract % SECONDS_PER_DAY));
}
/**
* Extracts the time as seconds of day,
* from {@code 0} to {@code 24 * 60 * 60 - 1}.
*
* @return the second-of-day equivalent to this time
*/
public int toSecondOfDay() {
int total = hour * SECONDS_PER_HOUR;
total += minute * SECONDS_PER_MINUTE;
total += second;
return total;
}
/**
* Compares this {@code LocalTime} to another time.
* <p>
* The comparison is based on the time-line position of the local times within a day.
* It is "consistent with equals", as defined by {@link Comparable}.
*
* @param other the other time to compare to, not null
* @return the comparator value, negative if less, positive if greater
* @throws NullPointerException if {@code other} is null
*/
public int compareTo(LocalTime other) {
int cmp = Integer.compare(hour, other.hour);
if (cmp == 0) {
cmp = Integer.compare(minute, other.minute);
if (cmp == 0) {
cmp = Integer.compare(second, other.second);
}
}
return cmp;
}
/**
* Checks if this time is equal to another time.
* <p>
* The comparison is based on the time-line position of the time within a day.
* <p>
* Only objects of type {@code LocalTime} are compared, other types return false.
* To compare the date of two {@code TemporalAccessor} instances, use
* {@link ChronoField#NANO_OF_DAY} as a comparator.
*
* @param obj the object to check, null returns false
* @return true if this is equal to the other time
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof LocalTime) {
LocalTime other = (LocalTime) obj;
return hour == other.hour && minute == other.minute &&
second == other.second;
}
return false;
}
/**
* A hash code for this time.
*
* @return a suitable hash code
*/
@Override
public int hashCode() {
long sod = toSecondOfDay();
return (int) (sod ^ (sod >>> 32));
}
}

View File

@ -1,117 +0,0 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* Copyright (c) 2009-2012, Stephen Colebourne & Michael Nascimento Santos
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of JSR-310 nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package build.tools.tzdb;
import java.util.Objects;
/**
* A definition of the way a local time can be converted to the actual
* transition date-time.
* <p>
* Time zone rules are expressed in one of three ways:
* <p><ul>
* <li>Relative to UTC</li>
* <li>Relative to the standard offset in force</li>
* <li>Relative to the wall offset (what you would see on a clock on the wall)</li>
* </ul><p>
*/
public enum TimeDefinition {
/** The local date-time is expressed in terms of the UTC offset. */
UTC,
/** The local date-time is expressed in terms of the wall offset. */
WALL,
/** The local date-time is expressed in terms of the standard offset. */
STANDARD;
/**
* Converts the specified local date-time to the local date-time actually
* seen on a wall clock.
* <p>
* This method converts using the type of this enum.
* The output is defined relative to the 'before' offset of the transition.
* <p>
* The UTC type uses the UTC offset.
* The STANDARD type uses the standard offset.
* The WALL type returns the input date-time.
* The result is intended for use with the wall-offset.
*
* @param dateTime the local date-time, not null
* @param standardOffset the standard offset, not null
* @param wallOffset the wall offset, not null
* @return the date-time relative to the wall/before offset, not null
*/
public LocalDateTime createDateTime(LocalDateTime dateTime, ZoneOffset standardOffset, ZoneOffset wallOffset) {
switch (this) {
case UTC: {
int difference = wallOffset.getTotalSeconds() - ZoneOffset.UTC.getTotalSeconds();
return dateTime.plusSeconds(difference);
}
case STANDARD: {
int difference = wallOffset.getTotalSeconds() - standardOffset.getTotalSeconds();
return dateTime.plusSeconds(difference);
}
default: // WALL
return dateTime;
}
}
}

View File

@ -56,8 +56,6 @@
*/
package build.tools.tzdb;
import static build.tools.tzdb.Utils.*;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.nio.charset.StandardCharsets;
@ -179,15 +177,41 @@ public final class TzdbZoneRulesCompiler {
System.exit(1);
System.err.println("Source directory does not contain file: VERSION");
}
// load source files
printVerbose("Compiling TZDB version " + version);
// parse source files
for (Path file : srcFiles) {
printVerbose("Parsing file: " + file);
parseFile(file);
}
TzdbZoneRulesProvider provider = new TzdbZoneRulesProvider(srcFiles);
// build zone rules
printVerbose("Building rules");
buildZoneRules();
// Build the rules, zones and links into real zones.
SortedMap<String, ZoneRules> builtZones = new TreeMap<>();
// build zones
for (String zoneId : provider.getZoneIds()) {
printVerbose("Building zone " + zoneId);
builtZones.put(zoneId, provider.getZoneRules(zoneId));
}
// build aliases
Map<String, String> links = provider.getAliasMap();
for (String aliasId : links.keySet()) {
String realId = links.get(aliasId);
printVerbose("Linking alias " + aliasId + " to " + realId);
ZoneRules realRules = builtZones.get(realId);
if (realRules == null) {
realId = links.get(realId); // try again (handle alias liked to alias)
printVerbose("Relinking alias " + aliasId + " to " + realId);
realRules = builtZones.get(realId);
if (realRules == null) {
throw new IllegalArgumentException("Alias '" + aliasId + "' links to invalid zone '" + realId);
}
links.put(aliasId, realId);
}
builtZones.put(aliasId, realRules);
}
// output to file
printVerbose("Outputting tzdb file: " + dstFile);
outputFile(dstFile, version, builtZones, links);
@ -269,361 +293,13 @@ public final class TzdbZoneRulesCompiler {
}
}
private static final Pattern YEAR = Pattern.compile("(?i)(?<min>min)|(?<max>max)|(?<only>only)|(?<year>[0-9]+)");
private static final Pattern MONTH = Pattern.compile("(?i)(jan)|(feb)|(mar)|(apr)|(may)|(jun)|(jul)|(aug)|(sep)|(oct)|(nov)|(dec)");
private static final Matcher DOW = Pattern.compile("(?i)(mon)|(tue)|(wed)|(thu)|(fri)|(sat)|(sun)").matcher("");
private static final Matcher TIME = Pattern.compile("(?<neg>-)?+(?<hour>[0-9]{1,2})(:(?<minute>[0-5][0-9]))?+(:(?<second>[0-5][0-9]))?+").matcher("");
/** The TZDB rules. */
private final Map<String, List<TZDBRule>> rules = new HashMap<>();
/** The TZDB zones. */
private final Map<String, List<TZDBZone>> zones = new HashMap<>();
/** The TZDB links. */
private final Map<String, String> links = new HashMap<>();
/** The built zones. */
private final SortedMap<String, ZoneRules> builtZones = new TreeMap<>();
/** Whether to output verbose messages. */
private boolean verbose;
/**
* private contructor
*/
private TzdbZoneRulesCompiler() {
}
/**
* Parses a source file.
*
* @param file the file being read, not null
* @throws Exception if an error occurs
*/
private void parseFile(Path file) throws Exception {
int lineNumber = 1;
String line = null;
try {
List<String> lines = Files.readAllLines(file, StandardCharsets.ISO_8859_1);
List<TZDBZone> openZone = null;
for (; lineNumber < lines.size(); lineNumber++) {
line = lines.get(lineNumber);
int index = line.indexOf('#'); // remove comments (doesn't handle # in quotes)
if (index >= 0) {
line = line.substring(0, index);
}
if (line.trim().length() == 0) { // ignore blank lines
continue;
}
Scanner s = new Scanner(line);
if (openZone != null && Character.isWhitespace(line.charAt(0)) && s.hasNext()) {
if (parseZoneLine(s, openZone)) {
openZone = null;
}
} else {
if (s.hasNext()) {
String first = s.next();
if (first.equals("Zone")) {
openZone = new ArrayList<>();
try {
zones.put(s.next(), openZone);
if (parseZoneLine(s, openZone)) {
openZone = null;
}
} catch (NoSuchElementException x) {
printVerbose("Invalid Zone line in file: " + file + ", line: " + line);
throw new IllegalArgumentException("Invalid Zone line");
}
} else {
openZone = null;
if (first.equals("Rule")) {
try {
parseRuleLine(s);
} catch (NoSuchElementException x) {
printVerbose("Invalid Rule line in file: " + file + ", line: " + line);
throw new IllegalArgumentException("Invalid Rule line");
}
} else if (first.equals("Link")) {
try {
String realId = s.next();
String aliasId = s.next();
links.put(aliasId, realId);
} catch (NoSuchElementException x) {
printVerbose("Invalid Link line in file: " + file + ", line: " + line);
throw new IllegalArgumentException("Invalid Link line");
}
} else {
throw new IllegalArgumentException("Unknown line");
}
}
}
}
}
} catch (Exception ex) {
throw new Exception("Failed while parsing file '" + file + "' on line " + lineNumber + " '" + line + "'", ex);
}
}
/**
* Parses a Rule line.
*
* @param s the line scanner, not null
*/
private void parseRuleLine(Scanner s) {
TZDBRule rule = new TZDBRule();
String name = s.next();
if (rules.containsKey(name) == false) {
rules.put(name, new ArrayList<TZDBRule>());
}
rules.get(name).add(rule);
rule.startYear = parseYear(s, 0);
rule.endYear = parseYear(s, rule.startYear);
if (rule.startYear > rule.endYear) {
throw new IllegalArgumentException("Year order invalid: " + rule.startYear + " > " + rule.endYear);
}
parseOptional(s.next()); // type is unused
parseMonthDayTime(s, rule);
rule.savingsAmount = parsePeriod(s.next());
rule.text = parseOptional(s.next());
}
/**
* Parses a Zone line.
*
* @param s the line scanner, not null
* @return true if the zone is complete
*/
private boolean parseZoneLine(Scanner s, List<TZDBZone> zoneList) {
TZDBZone zone = new TZDBZone();
zoneList.add(zone);
zone.standardOffset = parseOffset(s.next());
String savingsRule = parseOptional(s.next());
if (savingsRule == null) {
zone.fixedSavingsSecs = 0;
zone.savingsRule = null;
} else {
try {
zone.fixedSavingsSecs = parsePeriod(savingsRule);
zone.savingsRule = null;
} catch (Exception ex) {
zone.fixedSavingsSecs = null;
zone.savingsRule = savingsRule;
}
}
zone.text = s.next();
if (s.hasNext()) {
zone.year = Integer.parseInt(s.next());
if (s.hasNext()) {
parseMonthDayTime(s, zone);
}
return false;
} else {
return true;
}
}
/**
* Parses a Rule line.
*
* @param s the line scanner, not null
* @param mdt the object to parse into, not null
*/
private void parseMonthDayTime(Scanner s, TZDBMonthDayTime mdt) {
mdt.month = parseMonth(s);
if (s.hasNext()) {
String dayRule = s.next();
if (dayRule.startsWith("last")) {
mdt.dayOfMonth = -1;
mdt.dayOfWeek = parseDayOfWeek(dayRule.substring(4));
mdt.adjustForwards = false;
} else {
int index = dayRule.indexOf(">=");
if (index > 0) {
mdt.dayOfWeek = parseDayOfWeek(dayRule.substring(0, index));
dayRule = dayRule.substring(index + 2);
} else {
index = dayRule.indexOf("<=");
if (index > 0) {
mdt.dayOfWeek = parseDayOfWeek(dayRule.substring(0, index));
mdt.adjustForwards = false;
dayRule = dayRule.substring(index + 2);
}
}
mdt.dayOfMonth = Integer.parseInt(dayRule);
}
if (s.hasNext()) {
String timeStr = s.next();
int secsOfDay = parseSecs(timeStr);
if (secsOfDay == 86400) {
mdt.endOfDay = true;
secsOfDay = 0;
}
LocalTime time = LocalTime.ofSecondOfDay(secsOfDay);
mdt.time = time;
mdt.timeDefinition = parseTimeDefinition(timeStr.charAt(timeStr.length() - 1));
}
}
}
private int parseYear(Scanner s, int defaultYear) {
if (s.hasNext(YEAR)) {
s.next(YEAR);
MatchResult mr = s.match();
if (mr.group(1) != null) {
return 1900; // systemv has min
} else if (mr.group(2) != null) {
return YEAR_MAX_VALUE;
} else if (mr.group(3) != null) {
return defaultYear;
}
return Integer.parseInt(mr.group(4));
/*
if (mr.group("min") != null) {
//return YEAR_MIN_VALUE;
return 1900; // systemv has min
} else if (mr.group("max") != null) {
return YEAR_MAX_VALUE;
} else if (mr.group("only") != null) {
return defaultYear;
}
return Integer.parseInt(mr.group("year"));
*/
}
throw new IllegalArgumentException("Unknown year: " + s.next());
}
private int parseMonth(Scanner s) {
if (s.hasNext(MONTH)) {
s.next(MONTH);
for (int moy = 1; moy < 13; moy++) {
if (s.match().group(moy) != null) {
return moy;
}
}
}
throw new IllegalArgumentException("Unknown month: " + s.next());
}
private int parseDayOfWeek(String str) {
if (DOW.reset(str).matches()) {
for (int dow = 1; dow < 8; dow++) {
if (DOW.group(dow) != null) {
return dow;
}
}
}
throw new IllegalArgumentException("Unknown day-of-week: " + str);
}
private String parseOptional(String str) {
return str.equals("-") ? null : str;
}
private int parseSecs(String str) {
if (str.equals("-")) {
return 0;
}
try {
if (TIME.reset(str).find()) {
int secs = Integer.parseInt(TIME.group("hour")) * 60 * 60;
if (TIME.group("minute") != null) {
secs += Integer.parseInt(TIME.group("minute")) * 60;
}
if (TIME.group("second") != null) {
secs += Integer.parseInt(TIME.group("second"));
}
if (TIME.group("neg") != null) {
secs = -secs;
}
return secs;
}
} catch (NumberFormatException x) {}
throw new IllegalArgumentException(str);
}
private ZoneOffset parseOffset(String str) {
int secs = parseSecs(str);
return ZoneOffset.ofTotalSeconds(secs);
}
private int parsePeriod(String str) {
return parseSecs(str);
}
private TimeDefinition parseTimeDefinition(char c) {
switch (c) {
case 's':
case 'S':
// standard time
return TimeDefinition.STANDARD;
case 'u':
case 'U':
case 'g':
case 'G':
case 'z':
case 'Z':
// UTC
return TimeDefinition.UTC;
case 'w':
case 'W':
default:
// wall time
return TimeDefinition.WALL;
}
}
/**
* Build the rules, zones and links into real zones.
*
* @throws Exception if an error occurs
*/
private void buildZoneRules() throws Exception {
// build zones
for (String zoneId : zones.keySet()) {
printVerbose("Building zone " + zoneId);
List<TZDBZone> tzdbZones = zones.get(zoneId);
ZoneRulesBuilder bld = new ZoneRulesBuilder();
for (TZDBZone tzdbZone : tzdbZones) {
bld = tzdbZone.addToBuilder(bld, rules);
}
builtZones.put(zoneId, bld.toRules(zoneId));
}
// build aliases
for (String aliasId : links.keySet()) {
String realId = links.get(aliasId);
printVerbose("Linking alias " + aliasId + " to " + realId);
ZoneRules realRules = builtZones.get(realId);
if (realRules == null) {
realId = links.get(realId); // try again (handle alias liked to alias)
printVerbose("Relinking alias " + aliasId + " to " + realId);
realRules = builtZones.get(realId);
if (realRules == null) {
throw new IllegalArgumentException("Alias '" + aliasId + "' links to invalid zone '" + realId);
}
links.put(aliasId, realId);
}
builtZones.put(aliasId, realRules);
}
// remove UTC and GMT
// builtZones.remove("UTC");
// builtZones.remove("GMT");
// builtZones.remove("GMT0");
builtZones.remove("GMT+0");
builtZones.remove("GMT-0");
links.remove("GMT+0");
links.remove("GMT-0");
// remove ROC, which is not supported in j.u.tz
builtZones.remove("ROC");
links.remove("ROC");
// remove EST, HST and MST. They are supported via
// the short-id mapping
builtZones.remove("EST");
builtZones.remove("HST");
builtZones.remove("MST");
}
private TzdbZoneRulesCompiler() {}
/**
* Prints a verbose message.
@ -635,109 +311,4 @@ public final class TzdbZoneRulesCompiler {
System.out.println(message);
}
}
/**
* Class representing a month-day-time in the TZDB file.
*/
abstract class TZDBMonthDayTime {
/** The month of the cutover. */
int month = 1;
/** The day-of-month of the cutover. */
int dayOfMonth = 1;
/** Whether to adjust forwards. */
boolean adjustForwards = true;
/** The day-of-week of the cutover. */
int dayOfWeek = -1;
/** The time of the cutover. */
LocalTime time = LocalTime.MIDNIGHT;
/** Whether this is midnight end of day. */
boolean endOfDay;
/** The time of the cutover. */
TimeDefinition timeDefinition = TimeDefinition.WALL;
void adjustToFowards(int year) {
if (adjustForwards == false && dayOfMonth > 0) {
LocalDate adjustedDate = LocalDate.of(year, month, dayOfMonth).minusDays(6);
dayOfMonth = adjustedDate.getDayOfMonth();
month = adjustedDate.getMonth();
adjustForwards = true;
}
}
}
/**
* Class representing a rule line in the TZDB file.
*/
final class TZDBRule extends TZDBMonthDayTime {
/** The start year. */
int startYear;
/** The end year. */
int endYear;
/** The amount of savings. */
int savingsAmount;
/** The text name of the zone. */
String text;
void addToBuilder(ZoneRulesBuilder bld) {
adjustToFowards(2004); // irrelevant, treat as leap year
bld.addRuleToWindow(startYear, endYear, month, dayOfMonth, dayOfWeek, time, endOfDay, timeDefinition, savingsAmount);
}
}
/**
* Class representing a linked set of zone lines in the TZDB file.
*/
final class TZDBZone extends TZDBMonthDayTime {
/** The standard offset. */
ZoneOffset standardOffset;
/** The fixed savings amount. */
Integer fixedSavingsSecs;
/** The savings rule. */
String savingsRule;
/** The text name of the zone. */
String text;
/** The year of the cutover. */
int year = YEAR_MAX_VALUE;
ZoneRulesBuilder addToBuilder(ZoneRulesBuilder bld, Map<String, List<TZDBRule>> rules) {
if (year != YEAR_MAX_VALUE) {
bld.addWindow(standardOffset, toDateTime(year), timeDefinition);
} else {
bld.addWindowForever(standardOffset);
}
if (fixedSavingsSecs != null) {
bld.setFixedSavingsToWindow(fixedSavingsSecs);
} else {
List<TZDBRule> tzdbRules = rules.get(savingsRule);
if (tzdbRules == null) {
throw new IllegalArgumentException("Rule not found: " + savingsRule);
}
for (TZDBRule tzdbRule : tzdbRules) {
tzdbRule.addToBuilder(bld);
}
}
return bld;
}
private LocalDateTime toDateTime(int year) {
adjustToFowards(year);
LocalDate date;
if (dayOfMonth == -1) {
dayOfMonth = lengthOfMonth(month, isLeapYear(year));
date = LocalDate.of(year, month, dayOfMonth);
if (dayOfWeek != -1) {
date = previousOrSame(date, dayOfWeek);
}
} else {
date = LocalDate.of(year, month, dayOfMonth);
if (dayOfWeek != -1) {
date = nextOrSame(date, dayOfWeek);
}
}
LocalDateTime ldt = LocalDateTime.of(date, time);
if (endOfDay) {
ldt = ldt.plusDays(1);
}
return ldt;
}
}
}

View File

@ -0,0 +1,843 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package build.tools.tzdb;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NavigableMap;
import java.util.Objects;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.time.*;
import java.time.Year;
import java.time.chrono.IsoChronology;
import java.time.temporal.TemporalAdjusters;
import java.time.zone.ZoneOffsetTransition;
import java.time.zone.ZoneOffsetTransitionRule;
import java.time.zone.ZoneOffsetTransitionRule.TimeDefinition;
import java.time.zone.ZoneRulesException;
/**
* Compile and build time-zone rules from IANA timezone data
*
* @author Xueming Shen
* @author Stephen Colebourne
* @author Michael Nascimento Santos
*
* @since 1.9
*/
class TzdbZoneRulesProvider {
/**
* Creates an instance.
*
* @throws ZoneRulesException if unable to load
*/
public TzdbZoneRulesProvider(List<Path> files) {
try {
load(files);
} catch (Exception ex) {
throw new ZoneRulesException("Unable to load TZDB time-zone rules", ex);
}
}
public Set<String> getZoneIds() {
return new TreeSet(regionIds);
}
public Map<String, String> getAliasMap() {
return links;
}
public ZoneRules getZoneRules(String zoneId) {
Object obj = zones.get(zoneId);
if (obj == null) {
String zoneId0 = zoneId;
if (links.containsKey(zoneId)) {
zoneId = links.get(zoneId);
obj = zones.get(zoneId);
}
if (obj == null) {
throw new ZoneRulesException("Unknown time-zone ID: " + zoneId0);
}
}
if (obj instanceof ZoneRules) {
return (ZoneRules)obj;
}
try {
ZoneRules zrules = buildRules(zoneId, (List<ZoneLine>)obj);
zones.put(zoneId, zrules);
return zrules;
} catch (Exception ex) {
throw new ZoneRulesException(
"Invalid binary time-zone data: TZDB:" + zoneId, ex);
}
}
//////////////////////////////////////////////////////////////////////
/**
* All the regions that are available.
*/
private List<String> regionIds = new ArrayList<>(600);
/**
* Zone region to rules mapping
*/
private final Map<String, Object> zones = new ConcurrentHashMap<>();
/**
* compatibility list
*/
private static HashSet<String> excludedZones;
static {
// (1) exclude EST, HST and MST. They are supported
// via the short-id mapping
// (2) remove UTC and GMT
// (3) remove ROC, which is not supported in j.u.tz
excludedZones = new HashSet<>(10);
excludedZones.add("EST");
excludedZones.add("HST");
excludedZones.add("MST");
excludedZones.add("GMT+0");
excludedZones.add("GMT-0");
excludedZones.add("ROC");
}
private Map<String, String> links = new HashMap<>(150);
private Map<String, List<RuleLine>> rules = new HashMap<>(500);
private void load(List<Path> files) throws IOException {
for (Path file : files) {
List<ZoneLine> openZone = null;
try {
for (String line : Files.readAllLines(file, StandardCharsets.ISO_8859_1)) {
if (line.length() == 0 || line.charAt(0) == '#') {
continue;
}
//StringIterator itr = new StringIterator(line);
String[] tokens = split(line);
if (openZone != null && // continuing zone line
Character.isWhitespace(line.charAt(0)) &&
tokens.length > 0) {
ZoneLine zLine = new ZoneLine();
openZone.add(zLine);
if (zLine.parse(tokens, 0)) {
openZone = null;
}
continue;
}
if (line.startsWith("Zone")) { // parse Zone line
String name = tokens[1];
if (excludedZones.contains(name)){
continue;
}
if (zones.containsKey(name)) {
throw new IllegalArgumentException(
"Duplicated zone name in file: " + name +
", line: [" + line + "]");
}
openZone = new ArrayList<>(10);
zones.put(name, openZone);
regionIds.add(name);
ZoneLine zLine = new ZoneLine();
openZone.add(zLine);
if (zLine.parse(tokens, 2)) {
openZone = null;
}
} else if (line.startsWith("Rule")) { // parse Rule line
String name = tokens[1];
if (!rules.containsKey(name)) {
rules.put(name, new ArrayList<RuleLine>(10));
}
rules.get(name).add(new RuleLine().parse(tokens));
} else if (line.startsWith("Link")) { // parse link line
if (tokens.length >= 3) {
String realId = tokens[1];
String aliasId = tokens[2];
if (excludedZones.contains(aliasId)){
continue;
}
links.put(aliasId, realId);
regionIds.add(aliasId);
} else {
throw new IllegalArgumentException(
"Invalid Link line in file" +
file + ", line: [" + line + "]");
}
} else {
// skip unknown line
}
}
} catch (Exception ex) {
throw new RuntimeException("Failed while processing file [" + file +
"]", ex);
}
}
}
private String[] split(String str) {
int off = 0;
int end = str.length();
ArrayList<String> list = new ArrayList<>(10);
while (off < end) {
char c = str.charAt(off);
if (c == '\t' || c == ' ') {
off++;
continue;
}
if (c == '#') { // comment
break;
}
int start = off;
while (off < end) {
c = str.charAt(off);
if (c == ' ' || c == '\t') {
break;
}
off++;
}
if (start != off) {
list.add(str.substring(start, off));
}
}
return list.toArray(new String[list.size()]);
}
/**
* Class representing a month-day-time in the TZDB file.
*/
private static abstract class MonthDayTime {
/** The month of the cutover. */
Month month = Month.JANUARY;
/** The day-of-month of the cutover. */
int dayOfMonth = 1;
/** Whether to adjust forwards. */
boolean adjustForwards = true;
/** The day-of-week of the cutover. */
DayOfWeek dayOfWeek;
/** The time of the cutover, in second of day */
int secsOfDay = 0;
/** Whether this is midnight end of day. */
boolean endOfDay;
/** The time of the cutover. */
TimeDefinition timeDefinition = TimeDefinition.WALL;
void adjustToForwards(int year) {
if (adjustForwards == false && dayOfMonth > 0) {
// weekDay<=monthDay case, don't have it in tzdb data for now
LocalDate adjustedDate = LocalDate.of(year, month, dayOfMonth).minusDays(6);
dayOfMonth = adjustedDate.getDayOfMonth();
month = adjustedDate.getMonth();
adjustForwards = true;
}
}
LocalDateTime toDateTime(int year) {
LocalDate date;
if (dayOfMonth < 0) {
int monthLen = month.length(IsoChronology.INSTANCE.isLeapYear(year));
date = LocalDate.of(year, month, monthLen + 1 + dayOfMonth);
if (dayOfWeek != null) {
date = date.with(TemporalAdjusters.previousOrSame(dayOfWeek));
}
} else {
date = LocalDate.of(year, month, dayOfMonth);
if (dayOfWeek != null) {
date = date.with(TemporalAdjusters.nextOrSame(dayOfWeek));
}
}
if (endOfDay) {
date = date.plusDays(1);
}
return LocalDateTime.of(date, LocalTime.ofSecondOfDay(secsOfDay));
}
/**
* Parses the MonthDaytime segment of a tzdb line.
*/
private void parse(String[] tokens, int off) {
month = parseMonth(tokens[off++]);
if (off < tokens.length) {
String dayRule = tokens[off++];
if (dayRule.startsWith("last")) {
dayOfMonth = -1;
dayOfWeek = parseDayOfWeek(dayRule.substring(4));
adjustForwards = false;
} else {
int index = dayRule.indexOf(">=");
if (index > 0) {
dayOfWeek = parseDayOfWeek(dayRule.substring(0, index));
dayRule = dayRule.substring(index + 2);
} else {
index = dayRule.indexOf("<=");
if (index > 0) {
dayOfWeek = parseDayOfWeek(dayRule.substring(0, index));
adjustForwards = false;
dayRule = dayRule.substring(index + 2);
}
}
dayOfMonth = Integer.parseInt(dayRule);
if (dayOfMonth < -28 || dayOfMonth > 31 || dayOfMonth == 0) {
throw new IllegalArgumentException(
"Day of month indicator must be between -28 and 31 inclusive excluding zero");
}
}
if (off < tokens.length) {
String timeStr = tokens[off++];
secsOfDay = parseSecs(timeStr);
if (secsOfDay == 86400) {
// time must be midnight when end of day flag is true
endOfDay = true;
secsOfDay = 0;
}
timeDefinition = parseTimeDefinition(timeStr.charAt(timeStr.length() - 1));
}
}
}
int parseYear(String year, int defaultYear) {
switch (year.toLowerCase()) {
case "min": return 1900;
case "max": return Year.MAX_VALUE;
case "only": return defaultYear;
}
return Integer.parseInt(year);
}
Month parseMonth(String mon) {
switch (mon) {
case "Jan": return Month.JANUARY;
case "Feb": return Month.FEBRUARY;
case "Mar": return Month.MARCH;
case "Apr": return Month.APRIL;
case "May": return Month.MAY;
case "Jun": return Month.JUNE;
case "Jul": return Month.JULY;
case "Aug": return Month.AUGUST;
case "Sep": return Month.SEPTEMBER;
case "Oct": return Month.OCTOBER;
case "Nov": return Month.NOVEMBER;
case "Dec": return Month.DECEMBER;
}
throw new IllegalArgumentException("Unknown month: " + mon);
}
DayOfWeek parseDayOfWeek(String dow) {
switch (dow) {
case "Mon": return DayOfWeek.MONDAY;
case "Tue": return DayOfWeek.TUESDAY;
case "Wed": return DayOfWeek.WEDNESDAY;
case "Thu": return DayOfWeek.THURSDAY;
case "Fri": return DayOfWeek.FRIDAY;
case "Sat": return DayOfWeek.SATURDAY;
case "Sun": return DayOfWeek.SUNDAY;
}
throw new IllegalArgumentException("Unknown day-of-week: " + dow);
}
String parseOptional(String str) {
return str.equals("-") ? null : str;
}
static final boolean isDigit(char c) {
return c >= '0' && c <= '9';
}
private int parseSecs(String time) {
if (time.equals("-")) {
return 0;
}
// faster hack
int secs = 0;
int sign = 1;
int off = 0;
int len = time.length();
if (off < len && time.charAt(off) == '-') {
sign = -1;
off++;
}
char c0, c1;
if (off < len && isDigit(c0 = time.charAt(off++))) {
int hour = c0 - '0';
if (off < len && isDigit(c1 = time.charAt(off))) {
hour = hour * 10 + c1 - '0';
off++;
}
secs = hour * 60 * 60;
if (off < len && time.charAt(off++) == ':') {
if (off + 1 < len &&
isDigit(c0 = time.charAt(off++)) &&
isDigit(c1 = time.charAt(off++))) {
// minutes
secs += ((c0 - '0') * 10 + c1 - '0') * 60;
if (off < len && time.charAt(off++) == ':') {
if (off + 1 < len &&
isDigit(c0 = time.charAt(off++)) &&
isDigit(c1 = time.charAt(off++))) {
// seconds
secs += ((c0 - '0') * 10 + c1 - '0');
}
}
}
}
return secs * sign;
}
throw new IllegalArgumentException("[" + time + "]");
}
int parseOffset(String str) {
int secs = parseSecs(str);
if (Math.abs(secs) > 18 * 60 * 60) {
throw new IllegalArgumentException(
"Zone offset not in valid range: -18:00 to +18:00");
}
return secs;
}
int parsePeriod(String str) {
return parseSecs(str);
}
TimeDefinition parseTimeDefinition(char c) {
switch (c) {
case 's':
case 'S':
// standard time
return TimeDefinition.STANDARD;
case 'u':
case 'U':
case 'g':
case 'G':
case 'z':
case 'Z':
// UTC
return TimeDefinition.UTC;
case 'w':
case 'W':
default:
// wall time
return TimeDefinition.WALL;
}
}
}
/**
* Class representing a rule line in the TZDB file.
*/
private static class RuleLine extends MonthDayTime {
/** The start year. */
int startYear;
/** The end year. */
int endYear;
/** The amount of savings, in seconds. */
int savingsAmount;
/** The text name of the zone. */
String text;
/**
* Converts this to a transition rule.
*
* @param standardOffset the active standard offset, not null
* @param savingsBeforeSecs the active savings before the transition in seconds
* @return the transition, not null
*/
ZoneOffsetTransitionRule toTransitionRule(ZoneOffset stdOffset, int savingsBefore) {
// rule shared by different zones, so don't change it
Month month = this.month;
int dayOfMonth = this.dayOfMonth;
DayOfWeek dayOfWeek = this.dayOfWeek;
boolean endOfDay = this.endOfDay;
// optimize stored format
if (dayOfMonth < 0) {
if (month != Month.FEBRUARY) { // not Month.FEBRUARY
dayOfMonth = month.maxLength() - 6;
}
}
if (endOfDay && dayOfMonth > 0 &&
(dayOfMonth == 28 && month == Month.FEBRUARY) == false) {
LocalDate date = LocalDate.of(2004, month, dayOfMonth).plusDays(1); // leap-year
month = date.getMonth();
dayOfMonth = date.getDayOfMonth();
if (dayOfWeek != null) {
dayOfWeek = dayOfWeek.plus(1);
}
endOfDay = false;
}
// build rule
return ZoneOffsetTransitionRule.of(
//month, dayOfMonth, dayOfWeek, time, endOfDay, timeDefinition,
month, dayOfMonth, dayOfWeek,
LocalTime.ofSecondOfDay(secsOfDay), endOfDay, timeDefinition,
stdOffset,
ZoneOffset.ofTotalSeconds(stdOffset.getTotalSeconds() + savingsBefore),
ZoneOffset.ofTotalSeconds(stdOffset.getTotalSeconds() + savingsAmount));
}
RuleLine parse(String[] tokens) {
startYear = parseYear(tokens[2], 0);
endYear = parseYear(tokens[3], startYear);
if (startYear > endYear) {
throw new IllegalArgumentException(
"Invalid <Rule> line/Year order invalid:" + startYear + " > " + endYear);
}
//parseOptional(s.next()); // type is unused
super.parse(tokens, 5); // monthdaytime parsing
savingsAmount = parsePeriod(tokens[8]);
//rule.text = parseOptional(s.next());
return this;
}
}
/**
* Class representing a linked set of zone lines in the TZDB file.
*/
private static class ZoneLine extends MonthDayTime {
/** The standard offset. */
int stdOffsetSecs;
/** The fixed savings amount. */
int fixedSavingsSecs = 0;
/** The savings rule. */
String savingsRule;
/** The text name of the zone. */
String text;
/** The cutover year */
int year = Year.MAX_VALUE;
/** The cutover date time */
LocalDateTime ldt;
/** The cutover date/time in epoch seconds/UTC */
long ldtSecs = Long.MIN_VALUE;
LocalDateTime toDateTime() {
if (ldt == null) {
ldt = toDateTime(year);
}
return ldt;
}
/**
* Creates the date-time epoch second in the wall offset for the local
* date-time at the end of the window.
*
* @param savingsSecs the amount of savings in use in seconds
* @return the created date-time epoch second in the wall offset, not null
*/
long toDateTimeEpochSecond(int savingsSecs) {
if (ldtSecs == Long.MIN_VALUE) {
ldtSecs = toDateTime().toEpochSecond(ZoneOffset.UTC);
}
switch(timeDefinition) {
case UTC: return ldtSecs;
case STANDARD: return ldtSecs - stdOffsetSecs;
default: return ldtSecs - (stdOffsetSecs + savingsSecs); // WALL
}
}
boolean parse(String[] tokens, int off) {
stdOffsetSecs = parseOffset(tokens[off++]);
savingsRule = parseOptional(tokens[off++]);
if (savingsRule != null && savingsRule.length() > 0 &&
(savingsRule.charAt(0) == '-' || isDigit(savingsRule.charAt(0)))) {
try {
fixedSavingsSecs = parsePeriod(savingsRule);
savingsRule = null;
} catch (Exception ex) {
fixedSavingsSecs = 0;
}
}
text = tokens[off++];
if (off < tokens.length) {
year = Integer.parseInt(tokens[off++]);
if (off < tokens.length) {
super.parse(tokens, off); // MonthDayTime
}
return false;
} else {
return true;
}
}
}
/**
* Class representing a rule line in the TZDB file for a particular year.
*/
private static class TransRule implements Comparable<TransRule>
{
private int year;
private RuleLine rule;
/** The trans date/time */
private LocalDateTime ldt;
/** The trans date/time in epoch seconds (assume UTC) */
long ldtSecs;
TransRule(int year, RuleLine rule) {
this.year = year;
this.rule = rule;
this.ldt = rule.toDateTime(year);
this.ldtSecs = ldt.toEpochSecond(ZoneOffset.UTC);
}
ZoneOffsetTransition toTransition(ZoneOffset standardOffset, int savingsBeforeSecs) {
// copy of code in ZoneOffsetTransitionRule to avoid infinite loop
ZoneOffset wallOffset = ZoneOffset.ofTotalSeconds(
standardOffset.getTotalSeconds() + savingsBeforeSecs);
ZoneOffset offsetAfter = ZoneOffset.ofTotalSeconds(
standardOffset.getTotalSeconds() + rule.savingsAmount);
LocalDateTime dt = rule.timeDefinition
.createDateTime(ldt, standardOffset, wallOffset);
return ZoneOffsetTransition.of(dt, wallOffset, offsetAfter);
}
long toEpochSecond(ZoneOffset stdOffset, int savingsBeforeSecs) {
switch(rule.timeDefinition) {
case UTC: return ldtSecs;
case STANDARD: return ldtSecs - stdOffset.getTotalSeconds();
default: return ldtSecs - (stdOffset.getTotalSeconds() + savingsBeforeSecs); // WALL
}
}
/**
* Tests if this a real transition with the active savings in seconds
*
* @param savingsBefore the active savings in seconds
* @return true, if savings changes
*/
boolean isTransition(int savingsBefore) {
return rule.savingsAmount != savingsBefore;
}
public int compareTo(TransRule other) {
return (ldtSecs < other.ldtSecs)? -1 : ((ldtSecs == other.ldtSecs) ? 0 : 1);
}
}
private ZoneRules buildRules(String zoneId, List<ZoneLine> zones) {
if (zones.isEmpty()) {
throw new IllegalStateException("No available zone window");
}
final List<ZoneOffsetTransition> standardTransitionList = new ArrayList<>(4);
final List<ZoneOffsetTransition> transitionList = new ArrayList<>(256);
final List<ZoneOffsetTransitionRule> lastTransitionRuleList = new ArrayList<>(2);
final ZoneLine zone0 = zones.get(0);
// initialize the standard offset, wallOffset and savings for loop
//ZoneOffset stdOffset = zone0.standardOffset;
ZoneOffset stdOffset = ZoneOffset.ofTotalSeconds(zone0.stdOffsetSecs);
int savings = zone0.fixedSavingsSecs;
ZoneOffset wallOffset = ZoneOffset.ofTotalSeconds(stdOffset.getTotalSeconds() + savings);
// start ldt of each zone window
LocalDateTime zoneStart = LocalDateTime.MIN;
// first stanard offset
ZoneOffset firstStdOffset = stdOffset;
// first wall offset
ZoneOffset firstWallOffset = wallOffset;
for (ZoneLine zone : zones) {
// check if standard offset changed, update it if yes
ZoneOffset stdOffsetPrev = stdOffset; // for effectiveSavings check
if (zone.stdOffsetSecs != stdOffset.getTotalSeconds()) {
ZoneOffset stdOffsetNew = ZoneOffset.ofTotalSeconds(zone.stdOffsetSecs);
standardTransitionList.add(
ZoneOffsetTransition.of(
LocalDateTime.ofEpochSecond(zoneStart.toEpochSecond(wallOffset),
0,
stdOffset),
stdOffset,
stdOffsetNew));
stdOffset = stdOffsetNew;
}
LocalDateTime zoneEnd;
if (zone.year == Year.MAX_VALUE) {
zoneEnd = LocalDateTime.MAX;
} else {
zoneEnd = zone.toDateTime();
}
if (zoneEnd.compareTo(zoneStart) < 0) {
throw new IllegalStateException("Windows must be in date-time order: " +
zoneEnd + " < " + zoneStart);
}
// calculate effective savings at the start of the window
List<TransRule> trules = null;
List<TransRule> lastRules = null;
int effectiveSavings = zone.fixedSavingsSecs;
if (zone.savingsRule != null) {
List<RuleLine> tzdbRules = rules.get(zone.savingsRule);
if (tzdbRules == null) {
throw new IllegalArgumentException("<Rule> not found: " +
zone.savingsRule);
}
trules = new ArrayList<>(256);
lastRules = new ArrayList<>(2);
int lastRulesStartYear = Year.MIN_VALUE;
// merge the rules to transitions
for (RuleLine rule : tzdbRules) {
if (rule.startYear > zoneEnd.getYear()) {
// rules will not be used for this zone entry
continue;
}
rule.adjustToForwards(2004); // irrelevant, treat as leap year
int startYear = rule.startYear;
int endYear = rule.endYear;
if (zoneEnd.equals(LocalDateTime.MAX)) {
if (endYear == Year.MAX_VALUE) {
endYear = startYear;
lastRules.add(new TransRule(endYear, rule));
lastRulesStartYear = Math.max(startYear, lastRulesStartYear);
}
} else {
if (endYear == Year.MAX_VALUE) {
//endYear = zoneEnd.getYear();
endYear = zone.year;
}
}
int year = startYear;
while (year <= endYear) {
trules.add(new TransRule(year, rule));
year++;
}
}
// last rules, fill the gap years between different last rules
if (zoneEnd.equals(LocalDateTime.MAX)) {
lastRulesStartYear = Math.max(lastRulesStartYear, zoneStart.getYear()) + 1;
for (TransRule rule : lastRules) {
if (rule.year <= lastRulesStartYear) {
int year = rule.year;
while (year <= lastRulesStartYear) {
trules.add(new TransRule(year, rule.rule));
year++;
}
rule.year = lastRulesStartYear;
rule.ldt = rule.rule.toDateTime(year);
rule.ldtSecs = rule.ldt.toEpochSecond(ZoneOffset.UTC);
}
}
Collections.sort(lastRules);
}
// sort the merged rules
Collections.sort(trules);
effectiveSavings = 0;
for (TransRule rule : trules) {
if (rule.toEpochSecond(stdOffsetPrev, savings) >
zoneStart.toEpochSecond(wallOffset)) {
// previous savings amount found, which could be the
// savings amount at the instant that the window starts
// (hence isAfter)
break;
}
effectiveSavings = rule.rule.savingsAmount;
}
}
// check if the start of the window represents a transition
ZoneOffset effectiveWallOffset =
ZoneOffset.ofTotalSeconds(stdOffset.getTotalSeconds() + effectiveSavings);
if (!wallOffset.equals(effectiveWallOffset)) {
transitionList.add(ZoneOffsetTransition.of(zoneStart,
wallOffset,
effectiveWallOffset));
}
savings = effectiveSavings;
// apply rules within the window
if (trules != null) {
long zoneStartEpochSecs = zoneStart.toEpochSecond(wallOffset);
for (TransRule trule : trules) {
if (trule.isTransition(savings)) {
long epochSecs = trule.toEpochSecond(stdOffset, savings);
if (epochSecs < zoneStartEpochSecs ||
epochSecs >= zone.toDateTimeEpochSecond(savings)) {
continue;
}
transitionList.add(trule.toTransition(stdOffset, savings));
savings = trule.rule.savingsAmount;
}
}
}
if (lastRules != null) {
for (TransRule trule : lastRules) {
lastTransitionRuleList.add(trule.rule.toTransitionRule(stdOffset, savings));
savings = trule.rule.savingsAmount;
}
}
// finally we can calculate the true end of the window, passing it to the next window
wallOffset = ZoneOffset.ofTotalSeconds(stdOffset.getTotalSeconds() + savings);
zoneStart = LocalDateTime.ofEpochSecond(zone.toDateTimeEpochSecond(savings),
0,
wallOffset);
}
return new ZoneRules(firstStdOffset,
firstWallOffset,
standardTransitionList,
transitionList,
lastTransitionRuleList);
}
}

View File

@ -1,176 +0,0 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* Copyright (c) 2009-2012, Stephen Colebourne & Michael Nascimento Santos
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of JSR-310 nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package build.tools.tzdb;
import java.util.Objects;
class Utils {
// Returns the largest (closest to positive infinity)
public static long floorDiv(long x, long y) {
long r = x / y;
// if the signs are different and modulo not zero, round down
if ((x ^ y) < 0 && (r * y != x)) {
r--;
}
return r;
}
// Returns the floor modulus of the {@code long} arguments.
public static long floorMod(long x, long y) {
return x - floorDiv(x, y) * y;
}
// Returns the sum of its arguments,
public static long addExact(long x, long y) {
long r = x + y;
// HD 2-12 Overflow iff both arguments have the opposite sign of the result
if (((x ^ r) & (y ^ r)) < 0) {
throw new ArithmeticException("long overflow");
}
return r;
}
// Year
// Returns true if the specified year is a leap year.
public static boolean isLeapYear(int year) {
return ((year & 3) == 0) && ((year % 100) != 0 || (year % 400) == 0);
}
// The minimum supported year, '-999,999,999'.
public static final int YEAR_MIN_VALUE = -999_999_999;
// The maximum supported year, '+999,999,999'.
public static final int YEAR_MAX_VALUE = 999_999_999;
// Gets the length of the specified month in days.
public static int lengthOfMonth(int month, boolean leapYear) {
switch (month) {
case 2: //FEBRUARY:
return (leapYear ? 29 : 28);
case 4: //APRIL:
case 6: //JUNE:
case 9: //SEPTEMBER:
case 11: //NOVEMBER:
return 30;
default:
return 31;
}
}
// Gets the maximum length of the specified month in days.
public static int maxLengthOfMonth(int month) {
switch (month) {
case 2: //FEBRUARY:
return 29;
case 4: //APRIL:
case 6: //JUNE:
case 9: //SEPTEMBER:
case 11: //NOVEMBER:
return 30;
default:
return 31;
}
}
// DayOfWeek
// Returns the day-of-week that is the specified number of days after
// this one, from 1 to 7 for Monday to Sunday.
public static int plusDayOfWeek(int dow, long days) {
int amount = (int) (days % 7);
return (dow - 1 + (amount + 7)) % 7 + 1;
}
// Returns the day-of-week that is the specified number of days before
// this one, from 1 to 7 for Monday to Sunday.
public static int minusDayOfWeek(int dow, long days) {
return plusDayOfWeek(dow, -(days % 7));
}
// Adjusts the date to the first occurrence of the specified day-of-week
// before the date being adjusted unless it is already on that day in
// which case the same object is returned.
public static LocalDate previousOrSame(LocalDate date, int dayOfWeek) {
return adjust(date, dayOfWeek, 1);
}
// Adjusts the date to the first occurrence of the specified day-of-week
// after the date being adjusted unless it is already on that day in
// which case the same object is returned.
public static LocalDate nextOrSame(LocalDate date, int dayOfWeek) {
return adjust(date, dayOfWeek, 0);
}
// Implementation of next, previous or current day-of-week.
// @param relative whether the current date is a valid answer
private static final LocalDate adjust(LocalDate date, int dow, int relative) {
int calDow = date.getDayOfWeek();
if (relative < 2 && calDow == dow) {
return date;
}
if ((relative & 1) == 0) {
int daysDiff = calDow - dow;
return date.plusDays(daysDiff >= 0 ? 7 - daysDiff : -daysDiff);
} else {
int daysDiff = dow - calDow;
return date.minusDays(daysDiff >= 0 ? 7 - daysDiff : -daysDiff);
}
}
}

View File

@ -1,474 +0,0 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* Copyright (c) 2007-2012, Stephen Colebourne & Michael Nascimento Santos
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of JSR-310 nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package build.tools.tzdb;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* A time-zone offset from Greenwich/UTC, such as {@code +02:00}.
* <p>
* A time-zone offset is the period of time that a time-zone differs from Greenwich/UTC.
* This is usually a fixed number of hours and minutes.
*
* @since 1.8
*/
final class ZoneOffset implements Comparable<ZoneOffset> {
/** Cache of time-zone offset by offset in seconds. */
private static final ConcurrentMap<Integer, ZoneOffset> SECONDS_CACHE = new ConcurrentHashMap<>(16, 0.75f, 4);
/** Cache of time-zone offset by ID. */
private static final ConcurrentMap<String, ZoneOffset> ID_CACHE = new ConcurrentHashMap<>(16, 0.75f, 4);
/**
* The number of seconds per hour.
*/
private static final int SECONDS_PER_HOUR = 60 * 60;
/**
* The number of seconds per minute.
*/
private static final int SECONDS_PER_MINUTE = 60;
/**
* The number of minutes per hour.
*/
private static final int MINUTES_PER_HOUR = 60;
/**
* The abs maximum seconds.
*/
private static final int MAX_SECONDS = 18 * SECONDS_PER_HOUR;
/**
* Serialization version.
*/
private static final long serialVersionUID = 2357656521762053153L;
/**
* The time-zone offset for UTC, with an ID of 'Z'.
*/
public static final ZoneOffset UTC = ZoneOffset.ofTotalSeconds(0);
/**
* Constant for the maximum supported offset.
*/
public static final ZoneOffset MIN = ZoneOffset.ofTotalSeconds(-MAX_SECONDS);
/**
* Constant for the maximum supported offset.
*/
public static final ZoneOffset MAX = ZoneOffset.ofTotalSeconds(MAX_SECONDS);
/**
* The total offset in seconds.
*/
private final int totalSeconds;
/**
* The string form of the time-zone offset.
*/
private final transient String id;
//-----------------------------------------------------------------------
/**
* Obtains an instance of {@code ZoneOffset} using the ID.
* <p>
* This method parses the string ID of a {@code ZoneOffset} to
* return an instance. The parsing accepts all the formats generated by
* {@link #getId()}, plus some additional formats:
* <p><ul>
* <li>{@code Z} - for UTC
* <li>{@code +h}
* <li>{@code +hh}
* <li>{@code +hh:mm}
* <li>{@code -hh:mm}
* <li>{@code +hhmm}
* <li>{@code -hhmm}
* <li>{@code +hh:mm:ss}
* <li>{@code -hh:mm:ss}
* <li>{@code +hhmmss}
* <li>{@code -hhmmss}
* </ul><p>
* Note that &plusmn; means either the plus or minus symbol.
* <p>
* The ID of the returned offset will be normalized to one of the formats
* described by {@link #getId()}.
* <p>
* The maximum supported range is from +18:00 to -18:00 inclusive.
*
* @param offsetId the offset ID, not null
* @return the zone-offset, not null
* @throws DateTimeException if the offset ID is invalid
*/
@SuppressWarnings("fallthrough")
public static ZoneOffset of(String offsetId) {
Objects.requireNonNull(offsetId, "offsetId");
// "Z" is always in the cache
ZoneOffset offset = ID_CACHE.get(offsetId);
if (offset != null) {
return offset;
}
// parse - +h, +hh, +hhmm, +hh:mm, +hhmmss, +hh:mm:ss
final int hours, minutes, seconds;
switch (offsetId.length()) {
case 2:
offsetId = offsetId.charAt(0) + "0" + offsetId.charAt(1); // fallthru
case 3:
hours = parseNumber(offsetId, 1, false);
minutes = 0;
seconds = 0;
break;
case 5:
hours = parseNumber(offsetId, 1, false);
minutes = parseNumber(offsetId, 3, false);
seconds = 0;
break;
case 6:
hours = parseNumber(offsetId, 1, false);
minutes = parseNumber(offsetId, 4, true);
seconds = 0;
break;
case 7:
hours = parseNumber(offsetId, 1, false);
minutes = parseNumber(offsetId, 3, false);
seconds = parseNumber(offsetId, 5, false);
break;
case 9:
hours = parseNumber(offsetId, 1, false);
minutes = parseNumber(offsetId, 4, true);
seconds = parseNumber(offsetId, 7, true);
break;
default:
throw new DateTimeException("Zone offset ID '" + offsetId + "' is invalid");
}
char first = offsetId.charAt(0);
if (first != '+' && first != '-') {
throw new DateTimeException("Zone offset ID '" + offsetId + "' is invalid: Plus/minus not found when expected");
}
if (first == '-') {
return ofHoursMinutesSeconds(-hours, -minutes, -seconds);
} else {
return ofHoursMinutesSeconds(hours, minutes, seconds);
}
}
/**
* Parse a two digit zero-prefixed number.
*
* @param offsetId the offset ID, not null
* @param pos the position to parse, valid
* @param precededByColon should this number be prefixed by a precededByColon
* @return the parsed number, from 0 to 99
*/
private static int parseNumber(CharSequence offsetId, int pos, boolean precededByColon) {
if (precededByColon && offsetId.charAt(pos - 1) != ':') {
throw new DateTimeException("Zone offset ID '" + offsetId + "' is invalid: Colon not found when expected");
}
char ch1 = offsetId.charAt(pos);
char ch2 = offsetId.charAt(pos + 1);
if (ch1 < '0' || ch1 > '9' || ch2 < '0' || ch2 > '9') {
throw new DateTimeException("Zone offset ID '" + offsetId + "' is invalid: Non numeric characters found");
}
return (ch1 - 48) * 10 + (ch2 - 48);
}
//-----------------------------------------------------------------------
/**
* Obtains an instance of {@code ZoneOffset} using an offset in hours.
*
* @param hours the time-zone offset in hours, from -18 to +18
* @return the zone-offset, not null
* @throws DateTimeException if the offset is not in the required range
*/
public static ZoneOffset ofHours(int hours) {
return ofHoursMinutesSeconds(hours, 0, 0);
}
/**
* Obtains an instance of {@code ZoneOffset} using an offset in
* hours and minutes.
* <p>
* The sign of the hours and minutes components must match.
* Thus, if the hours is negative, the minutes must be negative or zero.
* If the hours is zero, the minutes may be positive, negative or zero.
*
* @param hours the time-zone offset in hours, from -18 to +18
* @param minutes the time-zone offset in minutes, from 0 to &plusmn;59, sign matches hours
* @return the zone-offset, not null
* @throws DateTimeException if the offset is not in the required range
*/
public static ZoneOffset ofHoursMinutes(int hours, int minutes) {
return ofHoursMinutesSeconds(hours, minutes, 0);
}
/**
* Obtains an instance of {@code ZoneOffset} using an offset in
* hours, minutes and seconds.
* <p>
* The sign of the hours, minutes and seconds components must match.
* Thus, if the hours is negative, the minutes and seconds must be negative or zero.
*
* @param hours the time-zone offset in hours, from -18 to +18
* @param minutes the time-zone offset in minutes, from 0 to &plusmn;59, sign matches hours and seconds
* @param seconds the time-zone offset in seconds, from 0 to &plusmn;59, sign matches hours and minutes
* @return the zone-offset, not null
* @throws DateTimeException if the offset is not in the required range
*/
public static ZoneOffset ofHoursMinutesSeconds(int hours, int minutes, int seconds) {
validate(hours, minutes, seconds);
int totalSeconds = totalSeconds(hours, minutes, seconds);
return ofTotalSeconds(totalSeconds);
}
/**
* Validates the offset fields.
*
* @param hours the time-zone offset in hours, from -18 to +18
* @param minutes the time-zone offset in minutes, from 0 to &plusmn;59
* @param seconds the time-zone offset in seconds, from 0 to &plusmn;59
* @throws DateTimeException if the offset is not in the required range
*/
private static void validate(int hours, int minutes, int seconds) {
if (hours < -18 || hours > 18) {
throw new DateTimeException("Zone offset hours not in valid range: value " + hours +
" is not in the range -18 to 18");
}
if (hours > 0) {
if (minutes < 0 || seconds < 0) {
throw new DateTimeException("Zone offset minutes and seconds must be positive because hours is positive");
}
} else if (hours < 0) {
if (minutes > 0 || seconds > 0) {
throw new DateTimeException("Zone offset minutes and seconds must be negative because hours is negative");
}
} else if ((minutes > 0 && seconds < 0) || (minutes < 0 && seconds > 0)) {
throw new DateTimeException("Zone offset minutes and seconds must have the same sign");
}
if (Math.abs(minutes) > 59) {
throw new DateTimeException("Zone offset minutes not in valid range: abs(value) " +
Math.abs(minutes) + " is not in the range 0 to 59");
}
if (Math.abs(seconds) > 59) {
throw new DateTimeException("Zone offset seconds not in valid range: abs(value) " +
Math.abs(seconds) + " is not in the range 0 to 59");
}
if (Math.abs(hours) == 18 && (Math.abs(minutes) > 0 || Math.abs(seconds) > 0)) {
throw new DateTimeException("Zone offset not in valid range: -18:00 to +18:00");
}
}
/**
* Calculates the total offset in seconds.
*
* @param hours the time-zone offset in hours, from -18 to +18
* @param minutes the time-zone offset in minutes, from 0 to &plusmn;59, sign matches hours and seconds
* @param seconds the time-zone offset in seconds, from 0 to &plusmn;59, sign matches hours and minutes
* @return the total in seconds
*/
private static int totalSeconds(int hours, int minutes, int seconds) {
return hours * SECONDS_PER_HOUR + minutes * SECONDS_PER_MINUTE + seconds;
}
//-----------------------------------------------------------------------
/**
* Obtains an instance of {@code ZoneOffset} specifying the total offset in seconds
* <p>
* The offset must be in the range {@code -18:00} to {@code +18:00}, which corresponds to -64800 to +64800.
*
* @param totalSeconds the total time-zone offset in seconds, from -64800 to +64800
* @return the ZoneOffset, not null
* @throws DateTimeException if the offset is not in the required range
*/
public static ZoneOffset ofTotalSeconds(int totalSeconds) {
if (Math.abs(totalSeconds) > MAX_SECONDS) {
throw new DateTimeException("Zone offset not in valid range: -18:00 to +18:00");
}
if (totalSeconds % (15 * SECONDS_PER_MINUTE) == 0) {
Integer totalSecs = totalSeconds;
ZoneOffset result = SECONDS_CACHE.get(totalSecs);
if (result == null) {
result = new ZoneOffset(totalSeconds);
SECONDS_CACHE.putIfAbsent(totalSecs, result);
result = SECONDS_CACHE.get(totalSecs);
ID_CACHE.putIfAbsent(result.getId(), result);
}
return result;
} else {
return new ZoneOffset(totalSeconds);
}
}
/**
* Constructor.
*
* @param totalSeconds the total time-zone offset in seconds, from -64800 to +64800
*/
private ZoneOffset(int totalSeconds) {
super();
this.totalSeconds = totalSeconds;
id = buildId(totalSeconds);
}
private static String buildId(int totalSeconds) {
if (totalSeconds == 0) {
return "Z";
} else {
int absTotalSeconds = Math.abs(totalSeconds);
StringBuilder buf = new StringBuilder();
int absHours = absTotalSeconds / SECONDS_PER_HOUR;
int absMinutes = (absTotalSeconds / SECONDS_PER_MINUTE) % MINUTES_PER_HOUR;
buf.append(totalSeconds < 0 ? "-" : "+")
.append(absHours < 10 ? "0" : "").append(absHours)
.append(absMinutes < 10 ? ":0" : ":").append(absMinutes);
int absSeconds = absTotalSeconds % SECONDS_PER_MINUTE;
if (absSeconds != 0) {
buf.append(absSeconds < 10 ? ":0" : ":").append(absSeconds);
}
return buf.toString();
}
}
/**
* Gets the total zone offset in seconds.
* <p>
* This is the primary way to access the offset amount.
* It returns the total of the hours, minutes and seconds fields as a
* single offset that can be added to a time.
*
* @return the total zone offset amount in seconds
*/
public int getTotalSeconds() {
return totalSeconds;
}
/**
* Gets the normalized zone offset ID.
* <p>
* The ID is minor variation to the standard ISO-8601 formatted string
* for the offset. There are three formats:
* <p><ul>
* <li>{@code Z} - for UTC (ISO-8601)
* <li>{@code +hh:mm} or {@code -hh:mm} - if the seconds are zero (ISO-8601)
* <li>{@code +hh:mm:ss} or {@code -hh:mm:ss} - if the seconds are non-zero (not ISO-8601)
* </ul><p>
*
* @return the zone offset ID, not null
*/
public String getId() {
return id;
}
/**
* Compares this offset to another offset in descending order.
* <p>
* The offsets are compared in the order that they occur for the same time
* of day around the world. Thus, an offset of {@code +10:00} comes before an
* offset of {@code +09:00} and so on down to {@code -18:00}.
* <p>
* The comparison is "consistent with equals", as defined by {@link Comparable}.
*
* @param other the other date to compare to, not null
* @return the comparator value, negative if less, postive if greater
* @throws NullPointerException if {@code other} is null
*/
@Override
public int compareTo(ZoneOffset other) {
return other.totalSeconds - totalSeconds;
}
/**
* Checks if this offset is equal to another offset.
* <p>
* The comparison is based on the amount of the offset in seconds.
* This is equivalent to a comparison by ID.
*
* @param obj the object to check, null returns false
* @return true if this is equal to the other offset
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof ZoneOffset) {
return totalSeconds == ((ZoneOffset) obj).totalSeconds;
}
return false;
}
/**
* A hash code for this offset.
*
* @return a suitable hash code
*/
@Override
public int hashCode() {
return totalSeconds;
}
/**
* Outputs this offset as a {@code String}, using the normalized ID.
*
* @return a string representation of this offset, not null
*/
@Override
public String toString() {
return id;
}
}

View File

@ -1,290 +0,0 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* Copyright (c) 2009-2012, Stephen Colebourne & Michael Nascimento Santos
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of JSR-310 nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package build.tools.tzdb;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
/**
* A transition between two offsets caused by a discontinuity in the local time-line.
*
* @since 1.8
*/
final class ZoneOffsetTransition implements Comparable<ZoneOffsetTransition> {
/**
* The local transition date-time at the transition.
*/
private final LocalDateTime transition;
/**
* The offset before transition.
*/
private final ZoneOffset offsetBefore;
/**
* The offset after transition.
*/
private final ZoneOffset offsetAfter;
/**
* Creates an instance defining a transition between two offsets.
*
* @param transition the transition date-time with the offset before the transition, not null
* @param offsetBefore the offset before the transition, not null
* @param offsetAfter the offset at and after the transition, not null
*/
ZoneOffsetTransition(LocalDateTime transition, ZoneOffset offsetBefore, ZoneOffset offsetAfter) {
Objects.requireNonNull(transition, "transition");
Objects.requireNonNull(offsetBefore, "offsetBefore");
Objects.requireNonNull(offsetAfter, "offsetAfter");
if (offsetBefore.equals(offsetAfter)) {
throw new IllegalArgumentException("Offsets must not be equal");
}
this.transition = transition;
this.offsetBefore = offsetBefore;
this.offsetAfter = offsetAfter;
}
/**
* Creates an instance from epoch-second and offsets.
*
* @param epochSecond the transition epoch-second
* @param offsetBefore the offset before the transition, not null
* @param offsetAfter the offset at and after the transition, not null
*/
ZoneOffsetTransition(long epochSecond, ZoneOffset offsetBefore, ZoneOffset offsetAfter) {
this.transition = LocalDateTime.ofEpochSecond(epochSecond, 0, offsetBefore);
this.offsetBefore = offsetBefore;
this.offsetAfter = offsetAfter;
}
/**
* Gets the transition instant as an epoch second.
*
* @return the transition epoch second
*/
public long toEpochSecond() {
return transition.toEpochSecond(offsetBefore);
}
/**
* Gets the local transition date-time, as would be expressed with the 'before' offset.
* <p>
* This is the date-time where the discontinuity begins expressed with the 'before' offset.
* At this instant, the 'after' offset is actually used, therefore the combination of this
* date-time and the 'before' offset will never occur.
* <p>
* The combination of the 'before' date-time and offset represents the same instant
* as the 'after' date-time and offset.
*
* @return the transition date-time expressed with the before offset, not null
*/
public LocalDateTime getDateTimeBefore() {
return transition;
}
/**
* Gets the local transition date-time, as would be expressed with the 'after' offset.
* <p>
* This is the first date-time after the discontinuity, when the new offset applies.
* <p>
* The combination of the 'before' date-time and offset represents the same instant
* as the 'after' date-time and offset.
*
* @return the transition date-time expressed with the after offset, not null
*/
public LocalDateTime getDateTimeAfter() {
return transition.plusSeconds(getDurationSeconds());
}
/**
* Gets the offset before the transition.
* <p>
* This is the offset in use before the instant of the transition.
*
* @return the offset before the transition, not null
*/
public ZoneOffset getOffsetBefore() {
return offsetBefore;
}
/**
* Gets the offset after the transition.
* <p>
* This is the offset in use on and after the instant of the transition.
*
* @return the offset after the transition, not null
*/
public ZoneOffset getOffsetAfter() {
return offsetAfter;
}
/**
* Gets the duration of the transition in seconds.
*
* @return the duration in seconds
*/
private int getDurationSeconds() {
return getOffsetAfter().getTotalSeconds() - getOffsetBefore().getTotalSeconds();
}
/**
* Does this transition represent a gap in the local time-line.
* <p>
* Gaps occur where there are local date-times that simply do not not exist.
* An example would be when the offset changes from {@code +01:00} to {@code +02:00}.
* This might be described as 'the clocks will move forward one hour tonight at 1am'.
*
* @return true if this transition is a gap, false if it is an overlap
*/
public boolean isGap() {
return getOffsetAfter().getTotalSeconds() > getOffsetBefore().getTotalSeconds();
}
/**
* Does this transition represent a gap in the local time-line.
* <p>
* Overlaps occur where there are local date-times that exist twice.
* An example would be when the offset changes from {@code +02:00} to {@code +01:00}.
* This might be described as 'the clocks will move back one hour tonight at 2am'.
*
* @return true if this transition is an overlap, false if it is a gap
*/
public boolean isOverlap() {
return getOffsetAfter().getTotalSeconds() < getOffsetBefore().getTotalSeconds();
}
/**
* Checks if the specified offset is valid during this transition.
* <p>
* This checks to see if the given offset will be valid at some point in the transition.
* A gap will always return false.
* An overlap will return true if the offset is either the before or after offset.
*
* @param offset the offset to check, null returns false
* @return true if the offset is valid during the transition
*/
public boolean isValidOffset(ZoneOffset offset) {
return isGap() ? false : (getOffsetBefore().equals(offset) || getOffsetAfter().equals(offset));
}
/**
* Gets the valid offsets during this transition.
* <p>
* A gap will return an empty list, while an overlap will return both offsets.
*
* @return the list of valid offsets
*/
List<ZoneOffset> getValidOffsets() {
if (isGap()) {
return Collections.emptyList();
}
return Arrays.asList(getOffsetBefore(), getOffsetAfter());
}
/**
* Compares this transition to another based on the transition instant.
* <p>
* This compares the instants of each transition.
* The offsets are ignored, making this order inconsistent with equals.
*
* @param transition the transition to compare to, not null
* @return the comparator value, negative if less, positive if greater
*/
@Override
public int compareTo(ZoneOffsetTransition transition) {
return Long.compare(this.toEpochSecond(), transition.toEpochSecond());
}
/**
* Checks if this object equals another.
* <p>
* The entire state of the object is compared.
*
* @param other the other object to compare to, null returns false
* @return true if equal
*/
@Override
public boolean equals(Object other) {
if (other == this) {
return true;
}
if (other instanceof ZoneOffsetTransition) {
ZoneOffsetTransition d = (ZoneOffsetTransition) other;
return transition.equals(d.transition) &&
offsetBefore.equals(d.offsetBefore) && offsetAfter.equals(d.offsetAfter);
}
return false;
}
/**
* Returns a suitable hash code.
*
* @return the hash code
*/
@Override
public int hashCode() {
return transition.hashCode() ^ offsetBefore.hashCode() ^ Integer.rotateLeft(offsetAfter.hashCode(), 16);
}
}

View File

@ -1,223 +0,0 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* Copyright (c) 2009-2012, Stephen Colebourne & Michael Nascimento Santos
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of JSR-310 nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package build.tools.tzdb;
import static build.tools.tzdb.Utils.*;
import java.util.Objects;
/**
* A rule expressing how to create a transition.
* <p>
* This class allows rules for identifying future transitions to be expressed.
* A rule might be written in many forms:
* <p><ul>
* <li>the 16th March
* <li>the Sunday on or after the 16th March
* <li>the Sunday on or before the 16th March
* <li>the last Sunday in February
* </ul><p>
* These different rule types can be expressed and queried.
*
* <h3>Specification for implementors</h3>
* This class is immutable and thread-safe.
*
* @since 1.8
*/
final class ZoneOffsetTransitionRule {
/**
* The month of the month-day of the first day of the cutover week.
* The actual date will be adjusted by the dowChange field.
*/
final int month;
/**
* The day-of-month of the month-day of the cutover week.
* If positive, it is the start of the week where the cutover can occur.
* If negative, it represents the end of the week where cutover can occur.
* The value is the number of days from the end of the month, such that
* {@code -1} is the last day of the month, {@code -2} is the second
* to last day, and so on.
*/
final byte dom;
/**
* The cutover day-of-week, -1 to retain the day-of-month.
*/
final int dow;
/**
* The cutover time in the 'before' offset.
*/
final LocalTime time;
/**
* Whether the cutover time is midnight at the end of day.
*/
final boolean timeEndOfDay;
/**
* The definition of how the local time should be interpreted.
*/
final TimeDefinition timeDefinition;
/**
* The standard offset at the cutover.
*/
final ZoneOffset standardOffset;
/**
* The offset before the cutover.
*/
final ZoneOffset offsetBefore;
/**
* The offset after the cutover.
*/
final ZoneOffset offsetAfter;
/**
* Creates an instance defining the yearly rule to create transitions between two offsets.
*
* @param month the month of the month-day of the first day of the cutover week, from 1 to 12
* @param dayOfMonthIndicator the day of the month-day of the cutover week, positive if the week is that
* day or later, negative if the week is that day or earlier, counting from the last day of the month,
* from -28 to 31 excluding 0
* @param dayOfWeek the required day-of-week, -1 if the month-day should not be changed
* @param time the cutover time in the 'before' offset, not null
* @param timeEndOfDay whether the time is midnight at the end of day
* @param timeDefnition how to interpret the cutover
* @param standardOffset the standard offset in force at the cutover, not null
* @param offsetBefore the offset before the cutover, not null
* @param offsetAfter the offset after the cutover, not null
* @throws IllegalArgumentException if the day of month indicator is invalid
* @throws IllegalArgumentException if the end of day flag is true when the time is not midnight
*/
ZoneOffsetTransitionRule(
int month,
int dayOfMonthIndicator,
int dayOfWeek,
LocalTime time,
boolean timeEndOfDay,
TimeDefinition timeDefnition,
ZoneOffset standardOffset,
ZoneOffset offsetBefore,
ZoneOffset offsetAfter) {
Objects.requireNonNull(time, "time");
Objects.requireNonNull(timeDefnition, "timeDefnition");
Objects.requireNonNull(standardOffset, "standardOffset");
Objects.requireNonNull(offsetBefore, "offsetBefore");
Objects.requireNonNull(offsetAfter, "offsetAfter");
if (month < 1 || month > 12) {
throw new IllegalArgumentException("month must be between 1 and 12");
}
if (dayOfMonthIndicator < -28 || dayOfMonthIndicator > 31 || dayOfMonthIndicator == 0) {
throw new IllegalArgumentException("Day of month indicator must be between -28 and 31 inclusive excluding zero");
}
if (timeEndOfDay && time.equals(LocalTime.MIDNIGHT) == false) {
throw new IllegalArgumentException("Time must be midnight when end of day flag is true");
}
this.month = month;
this.dom = (byte) dayOfMonthIndicator;
this.dow = dayOfWeek;
this.time = time;
this.timeEndOfDay = timeEndOfDay;
this.timeDefinition = timeDefnition;
this.standardOffset = standardOffset;
this.offsetBefore = offsetBefore;
this.offsetAfter = offsetAfter;
}
//-----------------------------------------------------------------------
/**
* Checks if this object equals another.
* <p>
* The entire state of the object is compared.
*
* @param otherRule the other object to compare to, null returns false
* @return true if equal
*/
@Override
public boolean equals(Object otherRule) {
if (otherRule == this) {
return true;
}
if (otherRule instanceof ZoneOffsetTransitionRule) {
ZoneOffsetTransitionRule other = (ZoneOffsetTransitionRule) otherRule;
return month == other.month && dom == other.dom && dow == other.dow &&
timeDefinition == other.timeDefinition &&
time.equals(other.time) &&
timeEndOfDay == other.timeEndOfDay &&
standardOffset.equals(other.standardOffset) &&
offsetBefore.equals(other.offsetBefore) &&
offsetAfter.equals(other.offsetAfter);
}
return false;
}
/**
* Returns a suitable hash code.
*
* @return the hash code
*/
@Override
public int hashCode() {
int hash = ((time.toSecondOfDay() + (timeEndOfDay ? 1 : 0)) << 15) +
(month << 11) + ((dom + 32) << 5) +
((dow == -1 ? 8 : dow) << 2) + (timeDefinition.ordinal());
return hash ^ standardOffset.hashCode() ^
offsetBefore.hashCode() ^ offsetAfter.hashCode();
}
}

View File

@ -64,6 +64,12 @@ package build.tools.tzdb;
import java.io.DataOutput;
import java.io.IOException;
import java.io.ObjectOutput;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.time.zone.ZoneOffsetTransition;
import java.time.zone.ZoneOffsetTransitionRule;
import java.time.zone.ZoneOffsetTransitionRule.TimeDefinition;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
@ -224,15 +230,15 @@ final class ZoneRules {
* @throws IOException if an error occurs
*/
static void writeRule(ZoneOffsetTransitionRule rule, DataOutput out) throws IOException {
int month = rule.month;
byte dom = rule.dom;
int dow = rule.dow;
LocalTime time = rule.time;
boolean timeEndOfDay = rule.timeEndOfDay;
TimeDefinition timeDefinition = rule.timeDefinition;
ZoneOffset standardOffset = rule.standardOffset;
ZoneOffset offsetBefore = rule.offsetBefore;
ZoneOffset offsetAfter = rule.offsetAfter;
int month = rule.getMonth().getValue();
byte dom = (byte)rule.getDayOfMonthIndicator();
int dow = rule.getDayOfWeek().getValue();
LocalTime time = rule.getLocalTime();
boolean timeEndOfDay = rule.isMidnightEndOfDay();
TimeDefinition timeDefinition = rule.getTimeDefinition();
ZoneOffset standardOffset = rule.getStandardOffset();
ZoneOffset offsetBefore = rule.getOffsetBefore();
ZoneOffset offsetAfter = rule.getOffsetAfter();
int timeSecs = (timeEndOfDay ? 86400 : time.toSecondOfDay());
int stdOffset = standardOffset.getTotalSeconds();

View File

@ -1,743 +0,0 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* Copyright (c) 2009-2012, Stephen Colebourne & Michael Nascimento Santos
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of JSR-310 nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package build.tools.tzdb;
import static build.tools.tzdb.Utils.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* A mutable builder used to create all the rules for a historic time-zone.
* <p>
* The rules of a time-zone describe how the offset changes over time.
* The rules are created by building windows on the time-line within which
* the different rules apply. The rules may be one of two kinds:
* <p><ul>
* <li>Fixed savings - A single fixed amount of savings from the standard offset will apply.</li>
* <li>Rules - A set of one or more rules describe how daylight savings changes during the window.</li>
* </ul><p>
*
* <h4>Implementation notes</h4>
* This class is a mutable builder used to create zone instances.
* It must only be used from a single thread.
* The created instances are immutable and thread-safe.
*
* @since 1.8
*/
public class ZoneRulesBuilder {
/**
* The list of windows.
*/
private List<TZWindow> windowList = new ArrayList<>();
//-----------------------------------------------------------------------
/**
* Constructs an instance of the builder that can be used to create zone rules.
* <p>
* The builder is used by adding one or more windows representing portions
* of the time-line. The standard offset from UTC/Greenwich will be constant
* within a window, although two adjacent windows can have the same standard offset.
* <p>
* Within each window, there can either be a
* {@link #setFixedSavingsToWindow fixed savings amount} or a
* {@link #addRuleToWindow list of rules}.
*/
public ZoneRulesBuilder() {
}
//-----------------------------------------------------------------------
/**
* Adds a window to the builder that can be used to filter a set of rules.
* <p>
* This method defines and adds a window to the zone where the standard offset is specified.
* The window limits the effect of subsequent additions of transition rules
* or fixed savings. If neither rules or fixed savings are added to the window
* then the window will default to no savings.
* <p>
* Each window must be added sequentially, as the start instant of the window
* is derived from the until instant of the previous window.
*
* @param standardOffset the standard offset, not null
* @param until the date-time that the offset applies until, not null
* @param untilDefinition the time type for the until date-time, not null
* @return this, for chaining
* @throws IllegalStateException if the window order is invalid
*/
public ZoneRulesBuilder addWindow(
ZoneOffset standardOffset,
LocalDateTime until,
TimeDefinition untilDefinition) {
Objects.requireNonNull(standardOffset, "standardOffset");
Objects.requireNonNull(until, "until");
Objects.requireNonNull(untilDefinition, "untilDefinition");
TZWindow window = new TZWindow(standardOffset, until, untilDefinition);
if (windowList.size() > 0) {
TZWindow previous = windowList.get(windowList.size() - 1);
window.validateWindowOrder(previous);
}
windowList.add(window);
return this;
}
/**
* Adds a window that applies until the end of time to the builder that can be
* used to filter a set of rules.
* <p>
* This method defines and adds a window to the zone where the standard offset is specified.
* The window limits the effect of subsequent additions of transition rules
* or fixed savings. If neither rules or fixed savings are added to the window
* then the window will default to no savings.
* <p>
* This must be added after all other windows.
* No more windows can be added after this one.
*
* @param standardOffset the standard offset, not null
* @return this, for chaining
* @throws IllegalStateException if a forever window has already been added
*/
public ZoneRulesBuilder addWindowForever(ZoneOffset standardOffset) {
return addWindow(standardOffset, LocalDateTime.MAX, TimeDefinition.WALL);
}
//-----------------------------------------------------------------------
/**
* Sets the previously added window to have fixed savings.
* <p>
* Setting a window to have fixed savings simply means that a single daylight
* savings amount applies throughout the window. The window could be small,
* such as a single summer, or large, such as a multi-year daylight savings.
* <p>
* A window can either have fixed savings or rules but not both.
*
* @param fixedSavingAmountSecs the amount of saving to use for the whole window, not null
* @return this, for chaining
* @throws IllegalStateException if no window has yet been added
* @throws IllegalStateException if the window already has rules
*/
public ZoneRulesBuilder setFixedSavingsToWindow(int fixedSavingAmountSecs) {
if (windowList.isEmpty()) {
throw new IllegalStateException("Must add a window before setting the fixed savings");
}
TZWindow window = windowList.get(windowList.size() - 1);
window.setFixedSavings(fixedSavingAmountSecs);
return this;
}
//-----------------------------------------------------------------------
/**
* Adds a single transition rule to the current window.
* <p>
* This adds a rule such that the offset, expressed as a daylight savings amount,
* changes at the specified date-time.
*
* @param transitionDateTime the date-time that the transition occurs as defined by timeDefintion, not null
* @param timeDefinition the definition of how to convert local to actual time, not null
* @param savingAmountSecs the amount of saving from the standard offset after the transition in seconds
* @return this, for chaining
* @throws IllegalStateException if no window has yet been added
* @throws IllegalStateException if the window already has fixed savings
* @throws IllegalStateException if the window has reached the maximum capacity of 2000 rules
*/
public ZoneRulesBuilder addRuleToWindow(
LocalDateTime transitionDateTime,
TimeDefinition timeDefinition,
int savingAmountSecs) {
Objects.requireNonNull(transitionDateTime, "transitionDateTime");
return addRuleToWindow(
transitionDateTime.getYear(), transitionDateTime.getYear(),
transitionDateTime.getMonth(), transitionDateTime.getDayOfMonth(),
-1, transitionDateTime.getTime(), false, timeDefinition, savingAmountSecs);
}
/**
* Adds a single transition rule to the current window.
* <p>
* This adds a rule such that the offset, expressed as a daylight savings amount,
* changes at the specified date-time.
*
* @param year the year of the transition, from MIN_YEAR to MAX_YEAR
* @param month the month of the transition, not null
* @param dayOfMonthIndicator the day-of-month of the transition, adjusted by dayOfWeek,
* from 1 to 31 adjusted later, or -1 to -28 adjusted earlier from the last day of the month
* @param time the time that the transition occurs as defined by timeDefintion, not null
* @param timeEndOfDay whether midnight is at the end of day
* @param timeDefinition the definition of how to convert local to actual time, not null
* @param savingAmountSecs the amount of saving from the standard offset after the transition in seconds
* @return this, for chaining
* @throws DateTimeException if a date-time field is out of range
* @throws IllegalStateException if no window has yet been added
* @throws IllegalStateException if the window already has fixed savings
* @throws IllegalStateException if the window has reached the maximum capacity of 2000 rules
*/
public ZoneRulesBuilder addRuleToWindow(
int year,
int month,
int dayOfMonthIndicator,
LocalTime time,
boolean timeEndOfDay,
TimeDefinition timeDefinition,
int savingAmountSecs) {
return addRuleToWindow(year, year, month, dayOfMonthIndicator, -1, time, timeEndOfDay, timeDefinition, savingAmountSecs);
}
/**
* Adds a multi-year transition rule to the current window.
* <p>
* This adds a rule such that the offset, expressed as a daylight savings amount,
* changes at the specified date-time for each year in the range.
*
* @param startYear the start year of the rule, from MIN_YEAR to MAX_YEAR
* @param endYear the end year of the rule, from MIN_YEAR to MAX_YEAR
* @param month the month of the transition, from 1 to 12
* @param dayOfMonthIndicator the day-of-month of the transition, adjusted by dayOfWeek,
* from 1 to 31 adjusted later, or -1 to -28 adjusted earlier from the last day of the month
* @param dayOfWeek the day-of-week to adjust to, -1 if day-of-month should not be adjusted
* @param time the time that the transition occurs as defined by timeDefintion, not null
* @param timeEndOfDay whether midnight is at the end of day
* @param timeDefinition the definition of how to convert local to actual time, not null
* @param savingAmountSecs the amount of saving from the standard offset after the transition in seconds
* @return this, for chaining
* @throws DateTimeException if a date-time field is out of range
* @throws IllegalArgumentException if the day of month indicator is invalid
* @throws IllegalArgumentException if the end of day midnight flag does not match the time
* @throws IllegalStateException if no window has yet been added
* @throws IllegalStateException if the window already has fixed savings
* @throws IllegalStateException if the window has reached the maximum capacity of 2000 rules
*/
public ZoneRulesBuilder addRuleToWindow(
int startYear,
int endYear,
int month,
int dayOfMonthIndicator,
int dayOfWeek,
LocalTime time,
boolean timeEndOfDay,
TimeDefinition timeDefinition,
int savingAmountSecs) {
Objects.requireNonNull(time, "time");
Objects.requireNonNull(timeDefinition, "timeDefinition");
if (dayOfMonthIndicator < -28 || dayOfMonthIndicator > 31 || dayOfMonthIndicator == 0) {
throw new IllegalArgumentException("Day of month indicator must be between -28 and 31 inclusive excluding zero");
}
if (timeEndOfDay && time.equals(LocalTime.MIDNIGHT) == false) {
throw new IllegalArgumentException("Time must be midnight when end of day flag is true");
}
if (windowList.isEmpty()) {
throw new IllegalStateException("Must add a window before adding a rule");
}
TZWindow window = windowList.get(windowList.size() - 1);
window.addRule(startYear, endYear, month, dayOfMonthIndicator, dayOfWeek, time, timeEndOfDay, timeDefinition, savingAmountSecs);
return this;
}
//-----------------------------------------------------------------------
/**
* Completes the build converting the builder to a set of time-zone rules.
* <p>
* Calling this method alters the state of the builder.
* Further rules should not be added to this builder once this method is called.
*
* @param zoneId the time-zone ID, not null
* @return the zone rules, not null
* @throws IllegalStateException if no windows have been added
* @throws IllegalStateException if there is only one rule defined as being forever for any given window
*/
public ZoneRules toRules(String zoneId) {
Objects.requireNonNull(zoneId, "zoneId");
if (windowList.isEmpty()) {
throw new IllegalStateException("No windows have been added to the builder");
}
final List<ZoneOffsetTransition> standardTransitionList = new ArrayList<>(4);
final List<ZoneOffsetTransition> transitionList = new ArrayList<>(256);
final List<ZoneOffsetTransitionRule> lastTransitionRuleList = new ArrayList<>(2);
// initialize the standard offset calculation
final TZWindow firstWindow = windowList.get(0);
ZoneOffset loopStandardOffset = firstWindow.standardOffset;
int loopSavings = 0;
if (firstWindow.fixedSavingAmountSecs != null) {
loopSavings = firstWindow.fixedSavingAmountSecs;
}
final ZoneOffset firstWallOffset = ZoneOffset.ofTotalSeconds(loopStandardOffset.getTotalSeconds() + loopSavings);
LocalDateTime loopWindowStart = LocalDateTime.of(YEAR_MIN_VALUE, 1, 1, 0, 0);
ZoneOffset loopWindowOffset = firstWallOffset;
// build the windows and rules to interesting data
for (TZWindow window : windowList) {
// tidy the state
window.tidy(loopWindowStart.getYear());
// calculate effective savings at the start of the window
Integer effectiveSavings = window.fixedSavingAmountSecs;
if (effectiveSavings == null) {
// apply rules from this window together with the standard offset and
// savings from the last window to find the savings amount applicable
// at start of this window
effectiveSavings = 0;
for (TZRule rule : window.ruleList) {
if (rule.toEpochSecond(loopStandardOffset, loopSavings) > loopWindowStart.toEpochSecond(loopWindowOffset)) {
// previous savings amount found, which could be the savings amount at
// the instant that the window starts (hence isAfter)
break;
}
effectiveSavings = rule.savingAmountSecs;
}
}
// check if standard offset changed, and update it
if (loopStandardOffset.equals(window.standardOffset) == false) {
standardTransitionList.add(
new ZoneOffsetTransition(
LocalDateTime.ofEpochSecond(loopWindowStart.toEpochSecond(loopWindowOffset), 0, loopStandardOffset),
loopStandardOffset, window.standardOffset));
loopStandardOffset = window.standardOffset;
}
// check if the start of the window represents a transition
ZoneOffset effectiveWallOffset = ZoneOffset.ofTotalSeconds(loopStandardOffset.getTotalSeconds() + effectiveSavings);
if (loopWindowOffset.equals(effectiveWallOffset) == false) {
transitionList.add(new ZoneOffsetTransition(loopWindowStart, loopWindowOffset, effectiveWallOffset));
}
loopSavings = effectiveSavings;
// apply rules within the window
for (TZRule rule : window.ruleList) {
if (rule.isTransition(loopSavings)) {
ZoneOffsetTransition trans = rule.toTransition(loopStandardOffset, loopSavings);
if (trans.toEpochSecond() < loopWindowStart.toEpochSecond(loopWindowOffset) == false &&
trans.toEpochSecond() < window.createDateTimeEpochSecond(loopSavings)) {
transitionList.add(trans);
loopSavings = rule.savingAmountSecs;
}
}
}
// calculate last rules
for (TZRule lastRule : window.lastRuleList) {
lastTransitionRuleList.add(lastRule.toTransitionRule(loopStandardOffset, loopSavings));
loopSavings = lastRule.savingAmountSecs;
}
// finally we can calculate the true end of the window, passing it to the next window
loopWindowOffset = window.createWallOffset(loopSavings);
loopWindowStart = LocalDateTime.ofEpochSecond(
window.createDateTimeEpochSecond(loopSavings), 0, loopWindowOffset);
}
return new ZoneRules(
firstWindow.standardOffset, firstWallOffset, standardTransitionList,
transitionList, lastTransitionRuleList);
}
//-----------------------------------------------------------------------
/**
* A definition of a window in the time-line.
* The window will have one standard offset and will either have a
* fixed DST savings or a set of rules.
*/
class TZWindow {
/** The standard offset during the window, not null. */
private final ZoneOffset standardOffset;
/** The end local time, not null. */
private final LocalDateTime windowEnd;
/** The type of the end time, not null. */
private final TimeDefinition timeDefinition;
/** The fixed amount of the saving to be applied during this window. */
private Integer fixedSavingAmountSecs;
/** The rules for the current window. */
private List<TZRule> ruleList = new ArrayList<>();
/** The latest year that the last year starts at. */
private int maxLastRuleStartYear = YEAR_MIN_VALUE;
/** The last rules. */
private List<TZRule> lastRuleList = new ArrayList<>();
/**
* Constructor.
*
* @param standardOffset the standard offset applicable during the window, not null
* @param windowEnd the end of the window, relative to the time definition, null if forever
* @param timeDefinition the time definition for calculating the true end, not null
*/
TZWindow(
ZoneOffset standardOffset,
LocalDateTime windowEnd,
TimeDefinition timeDefinition) {
super();
this.windowEnd = windowEnd;
this.timeDefinition = timeDefinition;
this.standardOffset = standardOffset;
}
/**
* Sets the fixed savings amount for the window.
*
* @param fixedSavingAmount the amount of daylight saving to apply throughout the window, may be null
* @throws IllegalStateException if the window already has rules
*/
void setFixedSavings(int fixedSavingAmount) {
if (ruleList.size() > 0 || lastRuleList.size() > 0) {
throw new IllegalStateException("Window has DST rules, so cannot have fixed savings");
}
this.fixedSavingAmountSecs = fixedSavingAmount;
}
/**
* Adds a rule to the current window.
*
* @param startYear the start year of the rule, from MIN_YEAR to MAX_YEAR
* @param endYear the end year of the rule, from MIN_YEAR to MAX_YEAR
* @param month the month of the transition, not null
* @param dayOfMonthIndicator the day-of-month of the transition, adjusted by dayOfWeek,
* from 1 to 31 adjusted later, or -1 to -28 adjusted earlier from the last day of the month
* @param dayOfWeek the day-of-week to adjust to, null if day-of-month should not be adjusted
* @param time the time that the transition occurs as defined by timeDefintion, not null
* @param timeEndOfDay whether midnight is at the end of day
* @param timeDefinition the definition of how to convert local to actual time, not null
* @param savingAmountSecs the amount of saving from the standard offset in seconds
* @throws IllegalStateException if the window already has fixed savings
* @throws IllegalStateException if the window has reached the maximum capacity of 2000 rules
*/
void addRule(
int startYear,
int endYear,
int month,
int dayOfMonthIndicator,
int dayOfWeek,
LocalTime time,
boolean timeEndOfDay,
TimeDefinition timeDefinition,
int savingAmountSecs) {
if (fixedSavingAmountSecs != null) {
throw new IllegalStateException("Window has a fixed DST saving, so cannot have DST rules");
}
if (ruleList.size() >= 2000) {
throw new IllegalStateException("Window has reached the maximum number of allowed rules");
}
boolean lastRule = false;
if (endYear == YEAR_MAX_VALUE) {
lastRule = true;
endYear = startYear;
}
int year = startYear;
while (year <= endYear) {
TZRule rule = new TZRule(year, month, dayOfMonthIndicator, dayOfWeek, time, timeEndOfDay, timeDefinition, savingAmountSecs);
if (lastRule) {
lastRuleList.add(rule);
maxLastRuleStartYear = Math.max(startYear, maxLastRuleStartYear);
} else {
ruleList.add(rule);
}
year++;
}
}
/**
* Validates that this window is after the previous one.
*
* @param previous the previous window, not null
* @throws IllegalStateException if the window order is invalid
*/
void validateWindowOrder(TZWindow previous) {
if (windowEnd.compareTo(previous.windowEnd) < 0) {
throw new IllegalStateException("Windows must be added in date-time order: " +
windowEnd + " < " + previous.windowEnd);
}
}
/**
* Adds rules to make the last rules all start from the same year.
* Also add one more year to avoid weird case where penultimate year has odd offset.
*
* @param windowStartYear the window start year
* @throws IllegalStateException if there is only one rule defined as being forever
*/
void tidy(int windowStartYear) {
if (lastRuleList.size() == 1) {
throw new IllegalStateException("Cannot have only one rule defined as being forever");
}
// handle last rules
if (windowEnd.equals(LocalDateTime.MAX)) {
// setup at least one real rule, which closes off other windows nicely
maxLastRuleStartYear = Math.max(maxLastRuleStartYear, windowStartYear) + 1;
for (TZRule lastRule : lastRuleList) {
addRule(lastRule.year, maxLastRuleStartYear, lastRule.month, lastRule.dayOfMonthIndicator,
lastRule.dayOfWeek, lastRule.time, lastRule.timeEndOfDay, lastRule.timeDefinition, lastRule.savingAmountSecs);
lastRule.year = maxLastRuleStartYear + 1;
}
if (maxLastRuleStartYear == YEAR_MAX_VALUE) {
lastRuleList.clear();
} else {
maxLastRuleStartYear++;
}
} else {
// convert all within the endYear limit
int endYear = windowEnd.getYear();
for (TZRule lastRule : lastRuleList) {
addRule(lastRule.year, endYear + 1, lastRule.month, lastRule.dayOfMonthIndicator,
lastRule.dayOfWeek, lastRule.time, lastRule.timeEndOfDay, lastRule.timeDefinition, lastRule.savingAmountSecs);
}
lastRuleList.clear();
maxLastRuleStartYear = YEAR_MAX_VALUE;
}
// ensure lists are sorted
Collections.sort(ruleList);
Collections.sort(lastRuleList);
// default fixed savings to zero
if (ruleList.size() == 0 && fixedSavingAmountSecs == null) {
fixedSavingAmountSecs = 0;
}
}
/**
* Checks if the window is empty.
*
* @return true if the window is only a standard offset
*/
boolean isSingleWindowStandardOffset() {
return windowEnd.equals(LocalDateTime.MAX) && timeDefinition == TimeDefinition.WALL &&
fixedSavingAmountSecs == null && lastRuleList.isEmpty() && ruleList.isEmpty();
}
/**
* Creates the wall offset for the local date-time at the end of the window.
*
* @param savingsSecs the amount of savings in use in seconds
* @return the created date-time epoch second in the wall offset, not null
*/
ZoneOffset createWallOffset(int savingsSecs) {
return ZoneOffset.ofTotalSeconds(standardOffset.getTotalSeconds() + savingsSecs);
}
/**
* Creates the offset date-time for the local date-time at the end of the window.
*
* @param savingsSecs the amount of savings in use in seconds
* @return the created date-time epoch second in the wall offset, not null
*/
long createDateTimeEpochSecond(int savingsSecs) {
ZoneOffset wallOffset = createWallOffset(savingsSecs);
LocalDateTime ldt = timeDefinition.createDateTime(windowEnd, standardOffset, wallOffset);
return ldt.toEpochSecond(wallOffset);
}
}
//-----------------------------------------------------------------------
/**
* A definition of the way a local time can be converted to an offset time.
*/
class TZRule implements Comparable<TZRule> {
private int year;
private int month;
private int dayOfMonthIndicator;
private int dayOfWeek;
private LocalTime time;
private boolean timeEndOfDay; // Whether the local time is end of day.
private TimeDefinition timeDefinition; // The type of the time.
private int savingAmountSecs; // The amount of the saving to be applied after this point.
/**
* Constructor.
*
* @param year the year
* @param month the month, value from 1 to 12
* @param dayOfMonthIndicator the day-of-month of the transition, adjusted by dayOfWeek,
* from 1 to 31 adjusted later, or -1 to -28 adjusted earlier from the last day of the month
* @param dayOfWeek the day-of-week, -1 if day-of-month is exact
* @param time the time, not null
* @param timeEndOfDay whether midnight is at the end of day
* @param timeDefinition the time definition, not null
* @param savingAfterSecs the savings amount in seconds
*/
TZRule(int year, int month, int dayOfMonthIndicator,
int dayOfWeek, LocalTime time, boolean timeEndOfDay,
TimeDefinition timeDefinition, int savingAfterSecs) {
this.year = year;
this.month = month;
this.dayOfMonthIndicator = dayOfMonthIndicator;
this.dayOfWeek = dayOfWeek;
this.time = time;
this.timeEndOfDay = timeEndOfDay;
this.timeDefinition = timeDefinition;
this.savingAmountSecs = savingAfterSecs;
}
/**
* Converts this to a transition.
*
* @param standardOffset the active standard offset, not null
* @param savingsBeforeSecs the active savings in seconds
* @return the transition, not null
*/
ZoneOffsetTransition toTransition(ZoneOffset standardOffset, int savingsBeforeSecs) {
// copy of code in ZoneOffsetTransitionRule to avoid infinite loop
LocalDate date = toLocalDate();
LocalDateTime ldt = LocalDateTime.of(date, time);
ZoneOffset wallOffset = ZoneOffset.ofTotalSeconds(standardOffset.getTotalSeconds() + savingsBeforeSecs);
LocalDateTime dt = timeDefinition.createDateTime(ldt, standardOffset, wallOffset);
ZoneOffset offsetAfter = ZoneOffset.ofTotalSeconds(standardOffset.getTotalSeconds() + savingAmountSecs);
return new ZoneOffsetTransition(dt, wallOffset, offsetAfter);
}
/**
* Returns the apoch second of this rules with the specified
* active standard offset and active savings
*
* @param standardOffset the active standard offset, not null
* @param savingsBeforeSecs the active savings in seconds
* @return the transition epoch second
*/
long toEpochSecond(ZoneOffset standardOffset, int savingsBeforeSecs) {
LocalDateTime ldt = LocalDateTime.of(toLocalDate(), time);
ZoneOffset wallOffset = ZoneOffset.ofTotalSeconds(standardOffset.getTotalSeconds() + savingsBeforeSecs);
return timeDefinition.createDateTime(ldt, standardOffset, wallOffset)
.toEpochSecond(wallOffset);
}
/**
* Tests if this a real transition with the active savings in seconds
*
* @param savingsBeforeSecs the active savings in seconds
* @return true, if savings in seconds changes
*/
boolean isTransition(int savingsBeforeSecs) {
return savingAmountSecs != savingsBeforeSecs;
}
/**
* Converts this to a transition rule.
*
* @param standardOffset the active standard offset, not null
* @param savingsBeforeSecs the active savings before the transition in seconds
* @return the transition, not null
*/
ZoneOffsetTransitionRule toTransitionRule(ZoneOffset standardOffset, int savingsBeforeSecs) {
// optimize stored format
if (dayOfMonthIndicator < 0) {
if (month != 2) { // not Month.FEBRUARY
dayOfMonthIndicator = maxLengthOfMonth(month) - 6;
}
}
if (timeEndOfDay && dayOfMonthIndicator > 0 &&
(dayOfMonthIndicator == 28 && month == 2) == false) {
LocalDate date = LocalDate.of(2004, month, dayOfMonthIndicator).plusDays(1); // leap-year
month = date.getMonth();
dayOfMonthIndicator = date.getDayOfMonth();
if (dayOfWeek != -1) {
dayOfWeek = plusDayOfWeek(dayOfWeek, 1);
}
timeEndOfDay = false;
}
// build rule
return new ZoneOffsetTransitionRule(
month, dayOfMonthIndicator, dayOfWeek, time, timeEndOfDay, timeDefinition,
standardOffset,
ZoneOffset.ofTotalSeconds(standardOffset.getTotalSeconds() + savingsBeforeSecs),
ZoneOffset.ofTotalSeconds(standardOffset.getTotalSeconds() + savingAmountSecs));
}
public int compareTo(TZRule other) {
int cmp = year - other.year;
cmp = (cmp == 0 ? month - other.month : cmp);
if (cmp == 0) {
// convert to date to handle dow/domIndicator/timeEndOfDay
LocalDate thisDate = toLocalDate();
LocalDate otherDate = other.toLocalDate();
cmp = thisDate.compareTo(otherDate);
}
cmp = (cmp == 0 ? time.compareTo(other.time) : cmp);
return cmp;
}
private LocalDate toLocalDate() {
LocalDate date;
if (dayOfMonthIndicator < 0) {
int monthLen = lengthOfMonth(month, isLeapYear(year));
date = LocalDate.of(year, month, monthLen + 1 + dayOfMonthIndicator);
if (dayOfWeek != -1) {
date = previousOrSame(date, dayOfWeek);
}
} else {
date = LocalDate.of(year, month, dayOfMonthIndicator);
if (dayOfWeek != -1) {
date = nextOrSame(date, dayOfWeek);
}
}
if (timeEndOfDay) {
date = date.plusDays(1);
}
return date;
}
}
}

View File

@ -110,6 +110,7 @@ int main(int argc, const char* argv[]) {
emit_inet("StandardSocketOptions.IP_MULTICAST_LOOP", IPPROTO_IP, IP_MULTICAST_LOOP);
#ifdef AF_INET6
emit_inet6("StandardSocketOptions.IP_TOS", IPPROTO_IPV6, IPV6_TCLASS);
emit_inet6("StandardSocketOptions.IP_MULTICAST_IF", IPPROTO_IPV6, IPV6_MULTICAST_IF);
emit_inet6("StandardSocketOptions.IP_MULTICAST_TTL", IPPROTO_IPV6, IPV6_MULTICAST_HOPS);
emit_inet6("StandardSocketOptions.IP_MULTICAST_LOOP", IPPROTO_IPV6, IPV6_MULTICAST_LOOP);

View File

@ -522,15 +522,17 @@ public class AquaComboBoxUI extends BasicComboBoxUI implements Sizeable {
};
@SuppressWarnings("serial") // anonymous class
private static Action hideAction = new AbstractAction() {
private final Action hideAction = new AbstractAction() {
@Override
public void actionPerformed(final ActionEvent e) {
final JComboBox comboBox = (JComboBox)e.getSource();
comboBox.firePopupMenuCanceled();
comboBox.setPopupVisible(false);
}
if (comboBox.isPopupVisible()) {
comboBox.firePopupMenuCanceled();
comboBox.setPopupVisible(false);
}
@Override
public boolean isEnabled() {
return comboBox.isPopupVisible() && super.isEnabled();
}
};

View File

@ -366,6 +366,11 @@ class AquaFileSystemModel extends AbstractTableModel implements PropertyChangeLi
final SortableFile otherFile = (SortableFile)other;
return otherFile.fFile.equals(fFile);
}
@Override
public int hashCode() {
return Objects.hashCode(fFile);
}
}
class LoadFilesThread extends Thread {

View File

@ -29,18 +29,9 @@ import java.awt.*;
import javax.swing.*;
import sun.lwawt.macosx.CPlatformWindow;
import sun.swing.SwingAccessor;
class ScreenPopupFactory extends PopupFactory {
static {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Void>() {
public Void run() {
System.loadLibrary("osxui");
return null;
}
});
}
static final Float TRANSLUCENT = new Float(248f/255f);
static final Float OPAQUE = new Float(1.0f);
@ -59,19 +50,13 @@ class ScreenPopupFactory extends PopupFactory {
return (Window)w;
}
/*
* Since we can't change the signature of PopupFactory, we have to call the
* private method getPopup(Component, Component, int, int, int) through JNI
* (see AquaLookAndFeel.m)
*/
native Popup _getHeavyWeightPopup(Component comp, Component invoker, int x, int y);
public Popup getPopup(final Component comp, final Component invoker, final int x, final int y) {
if (invoker == null) throw new IllegalArgumentException("Popup.getPopup must be passed non-null contents");
final Popup popup;
if (fIsActive) {
popup = _getHeavyWeightPopup(comp, invoker, x, y);
popup = SwingAccessor.getPopupFactoryAccessor()
.getHeavyWeightPopup(this, comp, invoker, x, y);
} else {
popup = super.getPopup(comp, invoker, x, y);
}

View File

@ -415,7 +415,7 @@ public final class CStrike extends FontStrike {
generalCache = new HashMap<Integer, Long>();
}
generalCache.put(new Integer(index), new Long(value));
generalCache.put(new Integer(index), Long.valueOf(value));
}
public synchronized void dispose() {

View File

@ -317,6 +317,8 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent>
* subclasses to initialize specific peers properties.
*/
void initializeImpl() {
// note that these methods can be overridden by the user and
// can return some strange values like null.
setBackground(target.getBackground());
setForeground(target.getForeground());
setFont(target.getFont());

View File

@ -443,6 +443,12 @@ public class LWWindowPeer
getPlatformWindow().updateIconImages();
}
@Override
public void setBackground(final Color c) {
super.setBackground(c);
updateOpaque();
}
@Override
public void setOpacity(float opacity) {
getPlatformWindow().setOpacity(opacity);

View File

@ -97,7 +97,8 @@ public class CEmbeddedFrame extends EmbeddedFrame {
public void handleKeyEvent(int eventType, int modifierFlags, String characters,
String charsIgnoringMods, boolean isRepeat, short keyCode,
boolean needsKeyTyped) {
responder.handleKeyEvent(eventType, modifierFlags, charsIgnoringMods, keyCode, needsKeyTyped, isRepeat);
responder.handleKeyEvent(eventType, modifierFlags, characters, charsIgnoringMods,
keyCode, needsKeyTyped, isRepeat);
}
public void handleInputEvent(String text) {

View File

@ -29,12 +29,18 @@ import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Insets;
import java.awt.MenuBar;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Window;
import sun.awt.CGraphicsDevice;
import sun.awt.CGraphicsEnvironment;
import sun.awt.CausedFocusEvent;
import sun.awt.LightweightFrame;
import sun.java2d.SurfaceData;
import sun.lwawt.LWLightweightFramePeer;
import sun.lwawt.LWWindowPeer;
import sun.lwawt.PlatformWindow;
@ -72,11 +78,6 @@ public class CPlatformLWWindow extends CPlatformWindow {
return null;
}
@Override
public GraphicsDevice getGraphicsDevice() {
return null;
}
@Override
public SurfaceData getScreenSurface() {
return null;
@ -199,4 +200,24 @@ public class CPlatformLWWindow extends CPlatformWindow {
public long getLayerPtr() {
return 0;
}
@Override
public GraphicsDevice getGraphicsDevice() {
CGraphicsEnvironment ge = (CGraphicsEnvironment)GraphicsEnvironment.
getLocalGraphicsEnvironment();
LWLightweightFramePeer peer = (LWLightweightFramePeer)getPeer();
int scale = ((LightweightFrame)peer.getTarget()).getScaleFactor();
Rectangle bounds = ((LightweightFrame)peer.getTarget()).getHostBounds();
for (GraphicsDevice d : ge.getScreenDevices()) {
if (d.getDefaultConfiguration().getBounds().intersects(bounds) &&
((CGraphicsDevice)d).getScaleFactor() == scale)
{
return d;
}
}
// We shouldn't be here...
return ge.getDefaultScreenDevice();
}
}

View File

@ -125,7 +125,7 @@ final class CPlatformResponder {
/**
* Handles key events.
*/
void handleKeyEvent(int eventType, int modifierFlags, String chars,
void handleKeyEvent(int eventType, int modifierFlags, String chars, String charsIgnoringModifiers,
short keyCode, boolean needsKeyTyped, boolean needsKeyReleased) {
boolean isFlagsChangedEvent =
isNpapiCallback ? (eventType == CocoaConstants.NPCocoaEventFlagsChanged) :
@ -153,7 +153,10 @@ final class CPlatformResponder {
testChar = chars.charAt(0);
}
int[] in = new int[] {testChar, isDeadChar ? 1 : 0, modifierFlags, keyCode};
char testCharIgnoringModifiers = charsIgnoringModifiers != null && charsIgnoringModifiers.length() > 0 ?
charsIgnoringModifiers.charAt(0) : KeyEvent.CHAR_UNDEFINED;
int[] in = new int[] {testCharIgnoringModifiers, isDeadChar ? 1 : 0, modifierFlags, keyCode};
int[] out = new int[3]; // [jkeyCode, jkeyLocation, deadChar]
postsTyped = NSEvent.nsToJavaKeyInfo(in, out);

View File

@ -200,7 +200,7 @@ public class CPlatformView extends CFRetainedResource {
}
private void deliverKeyEvent(NSEvent event) {
responder.handleKeyEvent(event.getType(), event.getModifierFlags(),
responder.handleKeyEvent(event.getType(), event.getModifierFlags(), event.getCharacters(),
event.getCharactersIgnoringModifiers(), event.getKeyCode(), true, false);
}

View File

@ -119,6 +119,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
static final int NONACTIVATING = 1 << 24;
static final int IS_DIALOG = 1 << 25;
static final int IS_MODAL = 1 << 26;
static final int IS_POPUP = 1 << 27;
static final int _STYLE_PROP_BITMASK = DECORATED | TEXTURED | UNIFIED | UTILITY | HUD | SHEET | CLOSEABLE | MINIMIZABLE | RESIZABLE;
@ -318,6 +319,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
styleBits = SET(styleBits, TEXTURED, false);
// Popups in applets don't activate applet's process
styleBits = SET(styleBits, NONACTIVATING, true);
styleBits = SET(styleBits, IS_POPUP, true);
}
if (Window.Type.UTILITY.equals(target.getType())) {
@ -744,20 +746,22 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
@Override
public void setOpaque(boolean isOpaque) {
CWrapper.NSWindow.setOpaque(getNSWindowPtr(), isOpaque);
boolean isTextured = (peer == null)? false : peer.isTextured();
if (!isOpaque && !isTextured) {
long clearColor = CWrapper.NSColor.clearColor();
CWrapper.NSWindow.setBackgroundColor(getNSWindowPtr(), clearColor);
boolean isTextured = (peer == null) ? false : peer.isTextured();
if (!isTextured) {
if (!isOpaque) {
CWrapper.NSWindow.setBackgroundColor(getNSWindowPtr(), 0);
} else if (peer != null) {
Color color = peer.getBackground();
if (color != null) {
int rgb = color.getRGB();
CWrapper.NSWindow.setBackgroundColor(getNSWindowPtr(), rgb);
}
}
}
//This is a temporary workaround. Looks like after 7124236 will be fixed
//the correct place for invalidateShadow() is CGLayer.drawInCGLContext.
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
invalidateShadow();
}
});
SwingUtilities.invokeLater(this::invalidateShadow);
}
@Override

View File

@ -61,7 +61,14 @@ final class CWrapper {
static native void setAlphaValue(long window, float alpha);
static native void setOpaque(long window, boolean opaque);
static native void setBackgroundColor(long window, long color);
/**
* Sets background color of the NSWindow.
*
* @param window the pointer of the NSWindow
* @param color the color in argb format
*/
static native void setBackgroundColor(long window, int color);
static native void miniaturize(long window);
static native void deminiaturize(long window);
@ -82,8 +89,4 @@ final class CWrapper {
static native void setToolTip(long view, String msg);
}
static final class NSColor {
static native long clearColor();
}
}

View File

@ -47,13 +47,15 @@ final class NSEvent {
// Key event information
private short keyCode;
private String characters;
private String charactersIgnoringModifiers;
// Called from native
NSEvent(int type, int modifierFlags, short keyCode, String charactersIgnoringModifiers) {
NSEvent(int type, int modifierFlags, short keyCode, String characters, String charactersIgnoringModifiers) {
this.type = type;
this.modifierFlags = modifierFlags;
this.keyCode = keyCode;
this.characters = characters;
this.charactersIgnoringModifiers = charactersIgnoringModifiers;
}
@ -121,12 +123,16 @@ final class NSEvent {
return charactersIgnoringModifiers;
}
String getCharacters() {
return characters;
}
@Override
public String toString() {
return "NSEvent[" + getType() + " ," + getModifierFlags() + " ,"
+ getClickCount() + " ," + getButtonNumber() + " ," + getX() + " ,"
+ getY() + " ," + getAbsX() + " ," + getAbsY()+ " ," + getKeyCode() + " ,"
+ getCharactersIgnoringModifiers() + "]";
+ getCharacters() + " ," + getCharactersIgnoringModifiers() + "]";
}
/*

View File

@ -1,44 +0,0 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#import "com_apple_laf_ScreenPopupFactory.h"
#import <JavaNativeFoundation/JavaNativeFoundation.h>
static JNF_CLASS_CACHE(sjc_PopupFactory, "javax/swing/PopupFactory");
static JNF_MEMBER_CACHE(jm_getPopup, sjc_PopupFactory, "getPopup", "(Ljava/awt/Component;Ljava/awt/Component;III)Ljavax/swing/Popup;");
/*
* Class: com_apple_laf_ScreenPopupFactory
* Method: _getHeavyWeightPopup
* Signature: (Ljava/awt/Component;Ljava/awt/Component;II)Ljavax/swing/Popup;
*/
JNIEXPORT jobject /* javax.swing.Popup */ JNICALL Java_com_apple_laf_ScreenPopupFactory__1getHeavyWeightPopup
(JNIEnv *env, jobject screenPopupFactory, jobject comp, jobject invoker, jint x, jint y) {
jobject popup;
JNF_COCOA_ENTER(env);
popup = JNFCallObjectMethod(env, screenPopupFactory, jm_getPopup, comp, invoker, x, y, 2);
JNF_COCOA_EXIT(env);
return popup;
}

View File

@ -1,207 +0,0 @@
// !$*UTF8*$!
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
{
00E6828EFEC88D1A11DB9C8B /* Project object */ = {
activeBuildConfigurationName = Release;
activeExecutable = 6A9FA6570246BA6C0CC91562 /* JObjC */;
activeTarget = EB9FD8610AEECCF5008E157E /* JObjC */;
addToTargets = (
4CEBA78E08679EF10015D03E /* JNILib */,
);
breakpointsGroup = 0AB3651F0B2F67B300788B6C /* XCBreakpointsBucket */;
codeSenseManager = 0AB364DB0B2F66FD00788B6C /* Code sense */;
executables = (
6A9FA6570246BA6C0CC91562 /* JObjC */,
);
perUserDictionary = {
PBXConfiguration.PBXFileTableDataSource3.PBXExecutablesDataSource = {
PBXFileTableDataSourceColumnSortingDirectionKey = "-1";
PBXFileTableDataSourceColumnSortingKey = PBXExecutablesDataSource_NameID;
PBXFileTableDataSourceColumnWidthsKey = (
22,
300,
131,
);
PBXFileTableDataSourceColumnsKey = (
PBXExecutablesDataSource_ActiveFlagID,
PBXExecutablesDataSource_NameID,
PBXExecutablesDataSource_CommentsID,
);
};
PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = {
PBXFileTableDataSourceColumnSortingDirectionKey = "-1";
PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID;
PBXFileTableDataSourceColumnWidthsKey = (
20,
245,
20,
48,
43,
43,
20,
);
PBXFileTableDataSourceColumnsKey = (
PBXFileDataSource_FiletypeID,
PBXFileDataSource_Filename_ColumnID,
PBXFileDataSource_Built_ColumnID,
PBXFileDataSource_ObjectSize_ColumnID,
PBXFileDataSource_Errors_ColumnID,
PBXFileDataSource_Warnings_ColumnID,
PBXFileDataSource_Target_ColumnID,
);
};
PBXConfiguration.PBXTargetDataSource.PBXTargetDataSource = {
PBXFileTableDataSourceColumnSortingDirectionKey = "-1";
PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID;
PBXFileTableDataSourceColumnWidthsKey = (
20,
200,
65,
20,
48,
43,
43,
);
PBXFileTableDataSourceColumnsKey = (
PBXFileDataSource_FiletypeID,
PBXFileDataSource_Filename_ColumnID,
PBXTargetDataSource_PrimaryAttribute,
PBXFileDataSource_Built_ColumnID,
PBXFileDataSource_ObjectSize_ColumnID,
PBXFileDataSource_Errors_ColumnID,
PBXFileDataSource_Warnings_ColumnID,
);
};
};
sourceControlManager = 0AB364DA0B2F66FD00788B6C /* Source Control */;
userBuildSettings = {
};
};
0AB364DA0B2F66FD00788B6C /* Source Control */ = {
isa = PBXSourceControlManager;
fallbackIsa = XCSourceControlManager;
isSCMEnabled = 0;
scmConfiguration = {
};
scmType = "";
};
0AB364DB0B2F66FD00788B6C /* Code sense */ = {
isa = PBXCodeSenseManager;
indexTemplatePath = "";
};
0AB3651F0B2F67B300788B6C /* XCBreakpointsBucket */ = {
isa = XCBreakpointsBucket;
name = "Project Breakpoints";
objects = (
);
};
0AB365570B2F6ABB00788B6C /* JObjCdylib.c */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {847, 783}}";
sepNavSelRange = "{0, 0}";
sepNavVisRect = "{{0, 0}, {847, 783}}";
sepNavWindowFrame = "{{84, 198}, {886, 912}}";
};
};
0A3CC35E0B94BB8800F6BA26 /* java */ = {
isa = PBXFileReference;
explicitFileType = "compiled.mach-o.executable";
name = java;
path = /usr/bin/java;
sourceTree = "<absolute>";
};
363028F90383184400C91562 /* Manifest */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {847, 783}}";
sepNavSelRange = "{0, 0}";
sepNavVisRect = "{{0, 0}, {847, 783}}";
sepNavWindowFrame = "{{38, 240}, {886, 912}}";
};
};
4CEBA78E08679EF10015D03E /* Dylib */ = {
activeExec = 0;
};
6A9FA6570246BA6C0CC91562 /* JObjC */ = {
isa = PBXExecutable;
activeArgIndex = 0;
activeArgIndices = (
YES,
);
argumentStrings = (
"-cp JObjC.jar JObjC",
);
autoAttachOnCrash = 1;
configStateDict = {
"PBXLSLaunchAction-0" = {
PBXLSLaunchAction = 0;
PBXLSLaunchStartAction = 1;
PBXLSLaunchStdioStyle = 2;
PBXLSLaunchStyle = 0;
class = PBXLSRunLaunchConfig;
displayName = "Executable Runner";
identifier = com.apple.Xcode.launch.runConfig;
remoteHostInfo = "";
startActionInfo = "";
};
"PBXLSLaunchAction-1" = {
PBXLSLaunchAction = 1;
PBXLSLaunchStartAction = 1;
PBXLSLaunchStdioStyle = 2;
PBXLSLaunchStyle = 0;
class = PBXJavaDebuggingNativeLaunchConfig;
displayName = "Java Debugger";
identifier = com.apple.Xcode.launch.JavaDebugNativeConfig;
remoteHostInfo = "";
startActionInfo = "";
};
};
customDataFormattersEnabled = 1;
debuggerPlugin = GDBDebugging;
disassemblyDisplayState = 0;
dylibVariantSuffix = "";
enableDebugStr = 1;
environmentEntries = (
);
executableSystemSymbolLevel = 0;
executableUserSymbolLevel = 0;
launchableReference = 0A3CC35E0B94BB8800F6BA26 /* java */;
libgmallocEnabled = 0;
name = JObjC;
sourceDirectories = (
);
startupPath = "dist";
};
EB9FD8610AEECCF5008E157E /* JObjC */ = {
activeExec = 0;
};
EB9FD8720AEECD83008E157E /* build.xml */ = {
uiCtxt = {
sepNavIntBoundsRect = "{{0, 0}, {847, 1260}}";
sepNavSelRange = "{1260, 0}";
sepNavVisRect = "{{0, 8}, {847, 783}}";
sepNavWindowFrame = "{{752, 266}, {886, 912}}";
};
};
}

File diff suppressed because it is too large Load Diff

View File

@ -1,132 +0,0 @@
#title JObjC
#
# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation. Oracle designates this
# particular file as subject to the "Classpath" exception as provided
# by Oracle in the LICENSE file that accompanied this code.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
JObjC core provides a pure Java interface for calling C functions and
sending ObjC messages. Given some information, it can marshal types
automatically.
It also parses BridgeSupport to generate Java wrappers around
Framework bundles. These wrappers rely on the core to provide access
to the C constants, enums, structs, functions, ObjC classes, etc of a
framework.
* How to build it
Your best option is `ant all`. There's an Xcode "B&I" target that
works for buildit.
You'll need a recent JavaNativeFoundation, and perhaps some other
things. Everything is usually there on SnowLeopard (or Leopard after
the common ~javabuild/bin/update runs).
The build process is quite involved. Xcode takes care of the native
parts, ant takes care of the Java parts, and there's an unholy mix of
external targets and hidden dependencies that keep Xcode and ant (and
buildit on top of that) from stepping on each other. So a warning: the
ant and Xcode targets don't have proper dependencies set up because of
this. They have some dependencies configured, but not the entire
chain. This is because of the jumping back and forth between
externals. If you run the aggregate targets (Xcode B&I, ant all, ant
test, ant bench), everything's is good. But if you manually invoke
individual targets, chances are you'll miss something. Let's go over
it all step by step:
** ant gen-pcoder
The PrimitiveCoder subclasses have a lot of boiler plate which
simplifies the generated MixedPrimitiveCoder classes. So instead of
maintaining it, I maintain a tiny Haskell script that spits out the
Java code. This ant target runs that script if Haskell is available on
the system. If it isn't available, this will silently fail. That's
okay, because chances are the PrimitiveCoder.java that you got from
svn is current and does not need to be updated.
** ant build-core / Xcode build-core-java
Build core simply builds the JObjC core java classes, and also
generates headers for the JNI for Xcode.
** ant build-core-native / Xcode build-core-native
Xcode builds the native core, using the headers from the Java core. It
generates libJObjC.dylib.
** ant build-generator / Xcode build-generator-java
ant builds the generator.
** ant run-generator / Xcode run-generator
ant runs the generator, using the core Java and native classes.
What is rungen? And what's run-generator-old? run-generator-old is the
preferred way to run the generator from ant, but there's a strange bug
when running from buildit that causes run-generator-old to
freeze. Pratik was helping me debug it, inspecting the stack and
snooping dtrace probes, but we never found the reason for the
block. So I figured that maybe if I just add a layer of indirection
maybe it'll work around that. And it did. Sad but true.
** ant build-generated / Xcode build-generated-java
Build the generator output.
** ant build-additions / Xcode build-additions-java
Builds java additions.
** ant build-additions-native / Xcode build-additions-native
This builds a new version of libJObjC.dylib. It will rebuild
everything from the core, and include everything from additions.
** ant assemble-product / Xcode assemble-product-java
Create a jar, copy products to destination, etc.
* How to test it
The test cases also contain a Java component and a native component,
and are built similarly to the above. The benchmarks are built
together with the tests. So "ant build-test" and "ant
build-test-native" will build both the benchmarks and the test. "ant
test" will run the test. "ant bench" will run benchmarks. If you only
want to run a specific benchmark, you can pass a regexp in the
environment variable BENCH_MATCH.
<src>
ant test
ant bench
BENCH_MATCH=Foo ant bench
</src>
Test and bench reports will end up in
build/JObjC.build/Debug/test-reports/
* How to use it
Include the jar in your classpath and set your java.library.path to
the directory that contains the dylib. Same thing for app bundles.

View File

@ -1,27 +0,0 @@
#!/bin/bash
#
# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation. Oracle designates this
# particular file as subject to the "Classpath" exception as provided
# by Oracle in the LICENSE file that accompanied this code.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
#
egrep "(TODO|FIXME|XXX|HACK)" -r src

View File

@ -1,54 +0,0 @@
#
# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation. Oracle designates this
# particular file as subject to the "Classpath" exception as provided
# by Oracle in the LICENSE file that accompanied this code.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
# makefile for generating a stable set of bridgesupport files that change timestamp
# only when the bridgesupport data actually changes
FRAMEWORKS_DIR = /System/Library/Frameworks
GBM = /usr/bin/gen_bridge_metadata
GEN_HEADERS = $(addsuffix .headers,$(FRAMEWORKS))
GEN_BRIDGESUPPORT = $(addsuffix .bridgesupport,$(FRAMEWORKS))
%.bridgesupport : %.headers $(FRAMEWORKS_DIR)/%.framework/Headers/*.h
@echo "generating bridge support for" $<
if [ -f $(FRAMEWORKS_DIR)/$(<:.headers=.framework)/Resources/BridgeSupport/$(<:.headers=Full.bridgesupport) ] ; \
then cp $(FRAMEWORKS_DIR)/$(<:.headers=.framework)/Resources/BridgeSupport/$(<:.headers=Full.bridgesupport) $@ ; \
else $(GBM) -F complete --framework $(<:.headers=.framework) -o $@ ; \
fi
if cmp -s $@ $(STABLE_GEN_DIR)/$(@:.bridgesupport=Full.bridgesupport) ; \
then : ; \
else cp $@ $(STABLE_GEN_DIR)/$(@:.bridgesupport=Full.bridgesupport) ; \
fi
%.headers : $(FRAMEWORKS_DIR)/%.framework/Headers
@echo linking $<
ln -s $< $@
$(STABLE_GEN_DIR):
mkdir -p $(STABLE_GEN_DIR)
$(GEN_BRIDGESUPPORT): $(GEN_HEADERS) $(STABLE_GEN_DIR)
all: $(GEN_BRIDGESUPPORT)

View File

@ -1,520 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
#
# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation. Oracle designates this
# particular file as subject to the "Classpath" exception as provided
# by Oracle in the LICENSE file that accompanied this code.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
#
-->
<project name="JObjC" default="install" basedir=".">
<property environment="env"/>
<echoproperties/>
<target name="installhdrs">
<echo>Nothing to do for install-headers build phase</echo>
</target>
<target name="installsrc">
<echo>Nothing to do for install-source build phase</echo>
</target>
<property name="redirection-target-defined" value="${env.PRODUCT_NAME}"/>
<target name="install" description="Redirects to the target specified in $PRODUCT_NAME">
<fail unless="env.PRODUCT_NAME" status="-1">
This Ant build file depends on the native Xcode project to invoke
targets by defining $PRODUCT_NAME to specify the target.
</fail>
<echo>--- Redirecting to target "${env.PRODUCT_NAME}"</echo>
<antcall target="${env.PRODUCT_NAME}"/>
</target>
<property name="compile.debug" value="true"/>
<!-- building from the command line / xcode b&i -->
<condition property="src" value="." else="${env.SRCROOT}">
<not><isset property="env.SRCROOT"/></not>
</condition>
<condition property="cfg" value="Debug" else="${env.CONFIGURATION}">
<not><isset property="env.CONFIGURATION"/></not>
</condition>
<condition property="obj" value="build/JObjC.build/${cfg}" else="${env.OBJROOT}">
<not><isset property="env.OBJROOT"/></not>
</condition>
<condition property="dst" value="build/${cfg}" else="${env.DSTROOT}/${cfg}">
<not><isset property="env.DSTROOT"/></not>
</condition>
<condition property="ARCHS" value="ppc i386 x86_64" else="${env.RC_ARCHS}">
<not><isset property="env.RC_ARCHS"/></not>
</condition>
<!-- -/- -->
<property name="bin" location="${obj}/bin"/>
<property name="gendoc" location="${obj}/doc"/>
<condition property="nativelib.dir" value="${dst}">
<not><isset property="env.CONFIGURATION_BUILD_DIR"/></not>
</condition>
<condition property="nativelib.dir" value="${env.CONFIGURATION_BUILD_DIR}">
<isset property="env.CONFIGURATION_BUILD_DIR"/>
</condition>
<property name="nativelib.file" location="${nativelib.dir}/libJObjC.dylib" />
<property name="jniheaders" location="${obj}/src/jni_headers"/>
<property name="core.src" location="${src}/src/core/java"/>
<property name="core.bin" location="${bin}/core"/>
<property name="core.jniheaders" location="${jniheaders}/core"/>
<property name="core.nativelib.dir" location="${nativelib.dir}"/>
<property name="generator.src" location="${src}/src/generator/java"/>
<property name="generator.bin" location="${bin}/generator"/>
<property name="generated.src" location="${obj}/src/jobjc"/>
<property name="generated.bin" location="${bin}/generated"/>
<property name="additions.src" location="${src}/src/runtime-additions"/>
<property name="additions.bin" location="${bin}/additions"/>
<property name="additions.jniheaders" location="${jniheaders}/additions"/>
<property name="additions.nativelib.dir" location="${nativelib.dir}"/>
<property name="test.src" location="${src}/src/tests/java"/>
<property name="test.bin" location="${bin}/test"/>
<property name="test.jniheaders" location="${jniheaders}/test"/>
<property name="test.reports" location="${obj}/test-reports"/>
<condition property="product.target_path"
value="/System/Library/Java/Extensions"
else="${env.INSTALL_PATH}">
<not><isset property="env.INSTALL_PATH"/></not>
</condition>
<echo message="(Settings :src '${src}' :cfg '${cfg}' :obj '${obj}' :dst '${dst}')"/>
<path id="test.lib.path.id">
<fileset dir="/usr/share/java">
<include name="**/*.jar"/>
</fileset>
</path>
<property name="product.jarfile.dir" location="${obj}"/>
<property name="product.jarfile.name" value="JObjC.jar"/>
<property name="product.jarfile" location="${product.jarfile.dir}/${product.jarfile.name}"/>
<target name="gen-pcoder" description="Generate PrimitiveCoder.java">
<exec executable="ruby" failonerror="true">
<arg value="${src}/run-and-write-if-okay"/>
<arg value="${src}/src/core/PrimitiveCoder.hs"/>
<arg value="${src}/src/core/java/com/apple/jobjc/PrimitiveCoder.java"/>
</exec>
</target>
<target name="build-core" depends="gen-pcoder" description="Compile the core runtime classes">
<mkdir dir="${core.bin}" />
<!-- Compile PrimitiveCoder first to work around javac bug. -->
<javac srcdir="${core.src}" destdir="${core.bin}" source="1.5" target="1.5" debug="${compile.debug}"
includes="**/PrimitiveCoder.java"
includeantruntime="false">
<classpath>
<path location="${obj}/../langtools/dist/lib/classes.jar"/>
</classpath>
</javac>
<javac srcdir="${core.src}" destdir="${core.bin}" source="1.5" target="1.5" debug="${compile.debug}" includeantruntime="false">
<classpath>
<path location="${obj}/../langtools/dist/lib/classes.jar"/>
</classpath>
</javac>
<exec executable="/usr/bin/perl" outputproperty="core.classes" failonerror="true">
<arg value="${src}/extract_classes.pl"/>
<arg path="${core.bin}"/>
</exec>
<mkdir dir="${core.jniheaders}" />
<javah destdir="${core.jniheaders}" class="${core.classes}">
<classpath path="${core.bin}"/>
</javah>
</target>
<target name="build-core-native" depends="build-core">
<exec executable="xcodebuild" failonerror="true">
<env key="CC" value=""/>
<env key="CXX" value=""/>
<arg value="-configuration"/>
<arg value="${cfg}"/>
<arg value="-target"/>
<arg value="build-core-native"/>
<arg value="SRCROOT=${src}"/>
<arg value="OBJROOT=${obj}"/>
<arg value="DSTROOT=${dst}"/>
<arg value="TARGET_TEMP_DIR=${env.DSTROOT}"/>
<arg value="PROJECT_TEMP_DIR=${env.DSTROOT}"/>
<arg value="BUILD_DIR=${env.DSTROOT}"/>
</exec>
</target>
<!-- macosx jdk 7 puts jobjc core classes on the bootclasspath by default -->
<target name="build-generator" description="Compile and assemble the generator">
<mkdir dir="${generator.bin}"/>
<javac srcdir="${generator.src}" destdir="${generator.bin}" source="1.5" target="1.5" debug="${compile.debug}" includeantruntime="false">
<compilerarg value="-version"/>
<compilerarg value="-Xbootclasspath/p:${core.bin}"/>
</javac>
</target>
<!-- Use this indirection hack to work around buildit lockup when
running the generator. -->
<target name="run-generator" depends="build-generator" description="Invoke the assembled generator">
<mkdir dir="${generated.src}"/>
<exec executable="ruby" failonerror="true">
<arg value="${src}/rungen"/>
<arg value="install"/>
<arg value="${product.jarfile.name}"/>
<arg value="${nativelib.dir}"/>
<arg value="${obj}"/>
<arg value="${ARCHS}"/>
<arg value="${env.STABLE_GEN_DIR}"/>
</exec>
</target>
<target name="run-generator-old" depends="build-generator" description="Invoke the assembled generator">
<mkdir dir="${generated.src}"/>
<java classname="com.apple.internal.jobjc.generator.Generator" fork="true" failonerror="true">
<jvmarg value="-Xms128m" />
<jvmarg value="-Xmx512m" />
<assertions><enable/></assertions>
<classpath>
<path location="${core.bin}"/>
<path location="${generator.bin}"/>
</classpath>
<sysproperty key="java.library.path" value="${core.nativelib.dir}"/>
<arg value="dst=${generated.src}"/>
</java>
</target>
<target name="build-generated" description="Build and assemble the JObjC core and all generated frameworks">
<mkdir dir="${generated.bin}"/>
<javac srcdir="${generated.src}" destdir="${generated.bin}" source="1.5" target="1.5" fork="yes" memoryMaximumSize="512m" debug="${compile.debug}" includeantruntime="false">
<classpath>
<path location="${core.bin}"/>
</classpath>
<compilerarg value="-version"/>
</javac>
</target>
<target name="build-additions" depends="build-generated">
<mkdir dir="${additions.bin}"/>
<javac srcdir="${additions.src}" destdir="${additions.bin}" source="1.5" target="1.5" debug="${compile.debug}" includeantruntime="false">
<classpath>
<path location="${core.bin}"/>
<path location="${generated.bin}"/>
</classpath>
<compilerarg value="-version"/>
</javac>
<exec executable="/usr/bin/perl" outputproperty="additions.classes" failonerror="true">
<arg value="${src}/extract_classes.pl"/>
<arg path="${additions.bin}"/>
</exec>
<mkdir dir="${additions.jniheaders}"/>
<javah destdir="${additions.jniheaders}" class="${additions.classes}">
<classpath>
<path location="${core.bin}"/>
<path location="${generated.bin}"/>
<path location="${additions.bin}"/>
</classpath>
</javah>
</target>
<target name="build-additions-native">
<exec executable="xcodebuild" failonerror="true">
<env key="CC" value=""/>
<env key="CXX" value=""/>
<arg value="-configuration"/>
<arg value="${cfg}"/>
<arg value="-target"/>
<arg value="build-additions-native"/>
<arg value="SRCROOT=${src}"/>
<arg value="OBJROOT=${obj}"/>
<arg value="DSTROOT=${dst}"/>
<arg value="TARGET_TEMP_DIR=${env.DSTROOT}"/>
<arg value="PROJECT_TEMP_DIR=${env.DSTROOT}"/>
<arg value="BUILD_DIR=${env.DSTROOT}"/>
</exec>
</target>
<target name="assemble-product">
<mkdir dir="${product.jarfile.dir}"/>
<jar jarfile="${product.jarfile}" level="9" index="true">
<fileset dir="${core.bin}"/>
<fileset dir="${generated.bin}"/>
<fileset dir="${additions.bin}"/>
</jar>
<mkdir dir="${dst}/${product.target_path}"/>
<copy file="${product.jarfile}" toDir="${dst}/${product.target_path}" failonerror="true" verbose="true"/>
<copy file="${nativelib.file}" toDir="${dst}/${product.target_path}" failonerror="true" verbose="true"/>
</target>
<target name="doc-core">
<mkdir dir="${gendoc}"/>
<javadoc destdir="${gendoc}" access="protected">
<fileset dir="${src}/src" includes="**/*.java"/>
</javadoc>
</target>
<target name="build-test" description="compile unit tests">
<mkdir dir="${test.bin}"/>
<javac srcdir="${test.src}" destdir="${test.bin}" debug="false" includeantruntime="false">
<classpath>
<pathelement location="${core.bin}"/>
<pathelement location="${generator.bin}"/>
<pathelement location="${generated.bin}"/>
<pathelement location="${additions.bin}"/>
</classpath>
<classpath refid="test.lib.path.id"/>
<compilerarg value="-version"/>
</javac>
<exec executable="/usr/bin/perl" outputproperty="test.classes" failonerror="true">
<arg value="${src}/extract_classes.pl"/>
<arg path="${test.bin}"/>
</exec>
<mkdir dir="${test.jniheaders}"/>
<javah destdir="${test.jniheaders}" class="${test.classes}">
<classpath>
<path location="${core.bin}"/>
<path location="${generated.bin}"/>
<path location="${additions.bin}"/>
<path location="${test.bin}"/>
</classpath>
<classpath refid="test.lib.path.id"/>
</javah>
</target>
<target name="build-test-installed" description="compile unit tests">
<mkdir dir="${test.bin}"/>
<javac srcdir="${test.src}" destdir="${test.bin}" debug="false" includeantruntime="false">
<compilerarg value="-verbose"/>
<classpath>
<pathelement location="${generator.bin}"/>
<pathelement location="${generated.bin}"/>
<pathelement location="${additions.bin}"/>
</classpath>
<classpath refid="test.lib.path.id"/>
<compilerarg value="-version"/>
</javac>
<exec executable="/usr/bin/perl" outputproperty="test.classes" failonerror="true">
<arg value="${src}/extract_classes.pl"/>
<arg path="${test.bin}"/>
</exec>
<mkdir dir="${test.jniheaders}"/>
<javah destdir="${test.jniheaders}" class="${test.classes}">
<classpath>
<path location="${generated.bin}"/>
<path location="${additions.bin}"/>
<path location="${test.bin}"/>
</classpath>
<classpath refid="test.lib.path.id"/>
</javah>
</target>
<target name="build-test-native" depends="build-test">
<exec executable="xcodebuild" failonerror="true">
<env key="CC" value=""/>
<env key="CXX" value=""/>
<arg value="-configuration"/>
<arg value="${cfg}"/>
<arg value="-target"/>
<arg value="build-test-native"/>
<arg value="SRCROOT=${src}"/>
<arg value="OBJROOT=${obj}"/>
<arg value="DSTROOT=${dst}"/>
<arg value="TARGET_TEMP_DIR=${env.DSTROOT}"/>
<arg value="PROJECT_TEMP_DIR=${env.DSTROOT}"/>
<arg value="BUILD_DIR=${env.DSTROOT}"/>
</exec>
</target>
<target name="build-test-native-installed" depends="build-test-installed">
<exec executable="xcodebuild" failonerror="true">
<env key="CC" value=""/>
<env key="CXX" value=""/>
<arg value="-configuration"/>
<arg value="${cfg}"/>
<arg value="-target"/>
<arg value="build-test-native"/>
<arg value="SRCROOT=${src}"/>
<arg value="OBJROOT=${obj}"/>
<arg value="DSTROOT=${dst}"/>
<arg value="TARGET_TEMP_DIR=${env.DSTROOT}"/>
<arg value="PROJECT_TEMP_DIR=${env.DSTROOT}"/>
<arg value="BUILD_DIR=${env.DSTROOT}"/>
</exec>
</target>
<target name="test" depends="build-test-native" description="run unit tests">
<mkdir dir="${test.reports}"/>
<junit fork="yes" printsummary="yes">
<assertions>
<enable/>
</assertions>
<jvmarg value="-server" />
<sysproperty key="java.library.path" value="${nativelib.dir}" />
<classpath>
<pathelement location="${core.bin}"/>
<pathelement location="${generator.bin}"/>
<pathelement location="${generated.bin}"/>
<pathelement location="${additions.bin}"/>
<pathelement location="${test.bin}"/>
</classpath>
<classpath refid="test.lib.path.id"/>
<formatter type="plain"/>
<batchtest fork="yes" todir="${test.reports}">
<fileset dir="${test.src}">
<include name="**/*Test.java"/>
<exclude name="**/AllTests.java"/>
</fileset>
</batchtest>
</junit>
</target>
<target name="test-installed" depends="build-test-native-installed" description="run unit tests">
<mkdir dir="${test.reports}"/>
<junit fork="yes" printsummary="yes">
<assertions>
<enable/>
</assertions>
<jvmarg value="-server" />
<sysproperty key="java.library.path" value="${nativelib.dir}" />
<classpath>
<pathelement location="${generator.bin}"/>
<pathelement location="${generated.bin}"/>
<pathelement location="${additions.bin}"/>
<pathelement location="${test.bin}"/>
</classpath>
<classpath refid="test.lib.path.id"/>
<formatter type="plain"/>
<batchtest fork="yes" todir="${test.reports}">
<fileset dir="${test.src}">
<include name="**/*Test.java"/>
<exclude name="**/AllTests.java"/>
</fileset>
</batchtest>
</junit>
</target>
<condition property="bench_match" value="*" else="${env.BENCH_MATCH}">
<not><isset property="env.BENCH_MATCH"/></not>
</condition>
<target name="bench" depends="build-test-native" description="run benchmarks">
<mkdir dir="${test.reports}"/>
<junit fork="yes" printsummary="yes">
<sysproperty key="java.library.path" value="${nativelib.dir}" />
<classpath>
<pathelement location="${core.bin}"/>
<pathelement location="${generator.bin}"/>
<pathelement location="${generated.bin}"/>
<pathelement location="${additions.bin}"/>
<pathelement location="${test.bin}"/>
</classpath>
<classpath refid="test.lib.path.id"/>
<jvmarg value="-Xms256m" />
<jvmarg value="-Xmx1024m" />
<jvmarg value="-server" />
<formatter type="plain"/>
<batchtest fork="yes" todir="${test.reports}">
<fileset dir="${test.src}">
<include name="**/Bench*${bench_match}*.java"/>
</fileset>
</batchtest>
</junit>
</target>
<target name="bench-installed" depends="build-test-native-installed" description="run benchmarks">
<mkdir dir="${test.reports}"/>
<junit fork="yes" printsummary="yes">
<sysproperty key="java.library.path" value="${nativelib.dir}" />
<classpath>
<pathelement location="${generator.bin}"/>
<pathelement location="${generated.bin}"/>
<pathelement location="${additions.bin}"/>
<pathelement location="${test.bin}"/>
</classpath>
<classpath refid="test.lib.path.id"/>
<jvmarg value="-Xms256m" />
<jvmarg value="-Xmx1024m" />
<jvmarg value="-server" />
<formatter type="plain"/>
<batchtest fork="yes" todir="${test.reports}">
<fileset dir="${test.src}">
<include name="**/Bench*${bench_match}*.java"/>
</fileset>
</batchtest>
</junit>
</target>
<target name="clean">
<delete dir="build"/>
<delete dir="${obj}"/>
<delete dir="${dst}"/>
<delete dir="${gendoc}"/>
<delete dir="${test.reports}"/>
</target>
<target name="clean-all" depends="clean,build-core,build-core-native,build-generator,run-generator,build-generated,build-additions,build-additions-native,assemble-product">
</target>
<target name="all" depends="build-core,build-core-native,build-generator,run-generator,build-generated,build-additions,build-additions-native,assemble-product">
</target>
<target name="all-test" depends="build-core,build-core-native,build-generator,run-generator,build-generated,build-additions,build-additions-native,assemble-product,test-installed">
</target>
<target name="clean-all-test" depends="clean,build-core,build-core-native,build-generator,run-generator,build-generated,build-additions,build-additions-native,assemble-product,test-installed">
</target>
<target name="all-but-gen" depends="clean,build-core,build-core-native,build-generator,build-generated,build-additions,build-additions-native,assemble-product">
</target>
</project>

View File

@ -1,39 +0,0 @@
#!/usr/bin/perl
#
# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation. Oracle designates this
# particular file as subject to the "Classpath" exception as provided
# by Oracle in the LICENSE file that accompanied this code.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
##
$file_dir = $ARGV[0];
@file_list = qx("/usr/bin/find" "$file_dir");
foreach $file (@file_list) {
if ($file =~ s/\.class//) {
if ($file !~ s/\$[0-9]//) {
$file =~ s/$file_dir\///g;
$file =~ s/\//\./g;
chomp($file);
print "$file,";
}
}
}

View File

@ -1,48 +0,0 @@
#!/usr/bin/env ruby
#
# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation. Oracle designates this
# particular file as subject to the "Classpath" exception as provided
# by Oracle in the LICENSE file that accompanied this code.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
#
if ARGV.length < 2
puts <<EOF
Expects two args: EXEC and OUTPATH. First, it runs and prints
`EXEC 2>&1`. If it returns successfully, it writes the output to OUTPATH.
This script will return successfully unless writing the output fails.
EOF
exit
end
EXECPATH = ARGV[0]
OUTPATH = ARGV[1]
output = `#{EXECPATH}`
puts output
if $?.to_i == 0
puts "Writing output of #{EXECPATH} to #{OUTPATH}"
File.open(OUTPATH, 'w') {|f| f.write(output) }
else
puts "#{EXECPATH} failed to run trial. Ignoring."
end

View File

@ -1,67 +0,0 @@
#!/usr/bin/env ruby
#
# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation. Oracle designates this
# particular file as subject to the "Classpath" exception as provided
# by Oracle in the LICENSE file that accompanied this code.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
#
xcodeAction = ARGV[0]
exit unless xcodeAction == "install"
JOBJC_JAR = ARGV[1]
LIBPATH = ARGV[2]
OBJROOT = ARGV[3]
ARCHS = ARGV[4]
STABLE_GEN_DIR = ARGV[5]
ourJavaHome = ENV['JAVA_HOME']
ourJavaVersion = `java -fullversion 2>&1`
$stderr.puts "ENV['JAVA_HOME'] = #{ourJavaHome}"
$stderr.puts "java -fullversion = #{ourJavaVersion}"
$stderr.puts "jobjc_jar = #{JOBJC_JAR}"
$stderr.puts "libpath = #{LIBPATH}"
$stderr.puts "objroot = #{OBJROOT}"
$stderr.puts "ARCHS = #{ARCHS}"
$stderr.puts "STABLE_GEN_DIR = #{STABLE_GEN_DIR}"
jarch = if ARCHS =~ /x86_64/ then "-d64" else "-d32" end
# compute the boot class path, but remove the JObjC jar file that may have been installed in the boot jdk
bootclasspathcmd = "java -classpath #{OBJROOT}/bin/core:#{OBJROOT}/bin/generator com.apple.internal.jobjc.generator.BootClassPathMinus #{JOBJC_JAR}"
$stderr.puts bootclasspathcmd
bootclasspath = `#{bootclasspathcmd}`
$stderr.puts "bootclasspath is: "
$stderr.puts bootclasspath
# we run the generator with our newly created JObjC. The installed version (if available) has been removed from
# the boot class path, so we are building with everything newly created.
cmd = "java #{jarch} -Xms128m -Xmx512m -Djava.library.path=#{LIBPATH} -Xbootclasspath:#{bootclasspath.chomp} -classpath #{OBJROOT}/bin/core:#{OBJROOT}/bin/generator -ea com.apple.internal.jobjc.generator.Generator dst=#{OBJROOT}/src/jobjc frameworks=#{STABLE_GEN_DIR}"
$stderr.puts cmd
puts `#{cmd} 2>&1`
raise $?.to_i if $?.to_i != 0

View File

@ -1,27 +0,0 @@
#!/bin/bash
#
# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation. Oracle designates this
# particular file as subject to the "Classpath" exception as provided
# by Oracle in the LICENSE file that accompanied this code.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
#
java -ea -classpath "lib/junit-4.4.jar:build/JObjC.build/Debug/bin/core:build/JObjC.build/Debug/bin/generator:build/JObjC.build/Debug/bin/additions:build/JObjC.build/Debug/bin/test:build/JObjC.build/Debug/bin/generated" -Djava.library.path=build/Debug $@

View File

@ -1,275 +0,0 @@
#!/usr/bin/env runhaskell
{-
/*
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-}
{-
The simplest way to get Haskell is through MacPorts: sudo port install ghc
Otherwise, see http://www.haskell.org/ghc/
-}
import Data.List
import Data.Maybe
import Data.Char
data Width = W32 | W64
deriving (Show, Eq, Bounded, Enum)
data NType = NBOOL | Nschar | Nuchar | Nsshort | Nushort | Nsint | Nuint
| Nslong | Nulong | Nslonglong | Nulonglong | Nfloat | Ndouble
deriving (Show, Eq, Bounded, Enum)
data JPrim = Jboolean | Jbyte | Jchar | Jshort | Jint | Jlong | Jfloat | Jdouble
deriving (Show, Eq, Bounded, Enum)
data JClass = JBoolean | JByte | JCharacter | JShort | JInteger | JLong
| JFloat | JDouble
deriving (Show, Eq, Bounded, Enum)
data FFIType = SINT8 | UINT8 | SINT16 | UINT16 | SINT32 | UINT32
| SINT64 | UINT64 | FLOAT | DOUBLE
deriving (Show, Eq, Bounded, Enum)
widths = [minBound..maxBound] :: [Width]
ntypes = [minBound..maxBound] :: [NType]
jprims = [minBound..maxBound] :: [JPrim]
jclasses = [minBound..maxBound] :: [JClass]
ffitypes = [minBound..maxBound] :: [FFIType]
-- What's the FFIType for a given Width and NType? For example: W32 NBOOL -> SINT8
ffitype :: Width -> NType -> FFIType
ffitype _ NBOOL = SINT8
ffitype _ Nschar = SINT8
ffitype _ Nuchar = UINT8
ffitype _ Nsshort = SINT16
ffitype _ Nushort = UINT16
ffitype _ Nsint = SINT32
ffitype _ Nuint = UINT32
ffitype W32 Nslong = SINT32
ffitype W64 Nslong = SINT64
ffitype W32 Nulong = UINT32
ffitype W64 Nulong = UINT64
ffitype _ Nslonglong = SINT64
ffitype _ Nulonglong = UINT64
ffitype _ Nfloat = FLOAT
ffitype _ Ndouble = DOUBLE
sizeof :: FFIType -> Int
sizeof SINT8 = 1
sizeof UINT8 = 1
sizeof SINT16 = 2
sizeof UINT16 = 2
sizeof SINT32 = 4
sizeof UINT32 = 4
sizeof SINT64 = 8
sizeof UINT64 = 8
sizeof FLOAT = 4
sizeof DOUBLE = 8
-- What's the Obj-C encoding for a given NType? For example: unsigned char -> 'C'
encoding nt = fromJust $ lookup nt $
[(NBOOL, 'B'), (Nschar, 'c'), (Nuchar, 'C'), (Nsshort, 's'),
(Nushort, 'S'), (Nsint, 'i'), (Nuint, 'I'), (Nslong, 'l'),
(Nulong, 'L'), (Nslonglong, 'q'), (Nulonglong, 'Q'),
(Nfloat, 'f'), (Ndouble, 'd')]
-- What's the JPrim for a given NType? For example: native signed long long -> java long
ntype2jprim nt = fromJust $ lookup nt $
[(NBOOL, Jboolean), (Nschar, Jbyte), (Nuchar, Jbyte),
(Nsshort, Jshort), (Nushort, Jshort), (Nsint, Jint), (Nuint, Jint),
(Nslong, Jlong), (Nulong, Jlong),
(Nslonglong, Jlong), (Nulonglong, Jlong),
(Nfloat, Jfloat), (Ndouble, Jdouble)]
-- What's the JClass for a given JPrim? For example: int -> Integer
jprim2jclass jp = fromJust $ lookup jp $
[(Jboolean, JBoolean), (Jbyte, JByte), (Jchar, JCharacter),
(Jshort, JShort), (Jint, JInteger), (Jlong, JLong),
(Jfloat, JFloat), (Jdouble, JDouble)]
-- Convert a type to something suitable for Java code. For example: Jboolean -> boolean
ntype2js nt = tail $ show nt
jclass2js t = tail $ show t
jprim2js p = tail $ show p
ffitype2js f = "FFI_" ++ (show f)
-- Capitalize the first letter of a String
capitalize [] = []
capitalize s = [toUpper $ head s] ++ tail s
-- Given an Width and NType, return the Java code for reading said NType from memory.
popAddr :: Width -> NType -> String
popAddr _ NBOOL = "rt.unsafe.getByte(addr) != 0"
popAddr _ Nschar = "rt.unsafe.getByte(addr)"
popAddr _ Nuchar = "rt.unsafe.getByte(addr)"
popAddr W32 Nslong = "rt.unsafe.getInt(addr)"
popAddr W32 Nulong = "rt.unsafe.getInt(addr)"
popAddr _ ntype = "rt.unsafe.get" ++ (capitalize.jprim2js.ntype2jprim $ ntype) ++ "(addr)"
-- Given an Width and NType, return the Java code for writing said NType to memory.
pushAddr :: Width -> NType -> String
pushAddr _ NBOOL = "rt.unsafe.putByte(addr, (byte) (x ? 1 : 0));"
pushAddr _ Nschar = "rt.unsafe.putByte(addr, x);"
pushAddr _ Nuchar = "rt.unsafe.putByte(addr, x);"
pushAddr W32 Nslong = "rt.unsafe.putInt(addr, (int) x);"
pushAddr W32 Nulong = "rt.unsafe.putInt(addr, (int) x);"
pushAddr _ ntype = "rt.unsafe.put" ++ (capitalize jprimS) ++ "(addr, (" ++ jprimS ++ ") x);"
where jprimS = jprim2js.ntype2jprim $ ntype
-- Helpers for generating Java ternarnies and conditionals.
archExpr x32 x64 = if x32 /= x64 then retdiff else x32
where retdiff = "(JObjCRuntime.IS64 ? (" ++ x64 ++ ") : (" ++ x32 ++ "))"
archStmt x32 x64 = if x32 /= x64 then retdiff else x32
where retdiff = "if(JObjCRuntime.IS64){ " ++ x64 ++ " }else{ " ++ x32 ++ " }"
-- Get a Java expression for the correct FFIType at runtime. For example: (JObjCRuntime.IS64 ? FFI_SINT64 : FFI_SINT32)
ffitypeVal nt = archExpr (ffitype2js $ ffitype W32 nt)
(ffitype2js $ ffitype W64 nt)
-- Similar to ffiTypeVal. Get the correct pop expression and push statement.
popAddrVal nt = archExpr (popAddr W32 nt) (popAddr W64 nt)
pushAddrVal nt = archStmt (pushAddr W32 nt) (pushAddr W64 nt)
-- What's the Coder class name we're using for a given NType?
coderName nt = aux nt ++ "Coder"
where
aux NBOOL = "Bool"
aux Nschar = "SChar"
aux Nuchar = "UChar"
aux Nsshort = "SShort"
aux Nushort = "UShort"
aux Nsint = "SInt"
aux Nuint = "UInt"
aux Nslong = "SLong"
aux Nulong = "ULong"
aux Nslonglong = "SLongLong"
aux Nulonglong = "ULongLong"
aux Nfloat = "Float"
aux Ndouble = "Double"
-- Operation for converting between primitives. Usually it just casts, but booleans are special.
jconvertPrims sym Jboolean Jboolean = sym
jconvertPrims sym Jboolean b = "((" ++ jprim2js b ++ ")(" ++ sym ++ " ? 1 : 0))"
jconvertPrims sym a Jboolean = "(" ++ sym ++ " != 0)"
jconvertPrims sym a b = if a == b then sym else "((" ++ jprim2js b ++ ")" ++ sym ++ ")"
sizeofRet nt =
let ffitypes = map (\w -> ffitype w nt) widths
sizes = map sizeof ffitypes in
if (length $ nub sizes) == 1
then "\t\treturn " ++ (show.head $ sizes) ++ ";"
else unlines [
"\t\tswitch(w){",
(unlines $ map casestmt widths),
"\t\tdefault: return -1;",
"\t\t}"]
where
casestmt w = "\t\t\tcase " ++ (show w) ++ ": return " ++
(show.sizeof $ ffitype w nt) ++ ";"
-- Generate a coder class for a given NType.
c2java ntype =
unlines [
"// native " ++ ntypeS ++ " -> java " ++ jprimS,
"public static final class " ++ className ++ " extends PrimitiveCoder<" ++ jclassS ++ ">{",
"\tpublic static final " ++ className ++ " INST = new " ++ className ++ "();",
"\tpublic " ++ className ++ "(){ super("++ffitypeVal ntype++", \"" ++ [encoding ntype] ++ "\", "++jclassS++".class, "++jprimS++".class); }",
"\t// compile time",
"\t@Override public void push(JObjCRuntime rt, long addr, " ++ jprimS ++ " x){",
"\t\t" ++ pushAddrVal ntype,
"\t}",
"\t@Override public " ++ jprimS ++ " pop" ++ capitalize jprimS ++ "(JObjCRuntime rt, long addr){",
"\t\treturn " ++ popAddrVal ntype ++ ";",
"\t}",
"\t// for runtime coding",
"\t@Override public int sizeof(Width w){",
sizeofRet ntype,
"\t}",
"\t@Override public void push(JObjCRuntime rt, long addr, " ++ jclassS ++ " x){ " ++
"push(rt, addr, (" ++ jprimS ++ ") x); }",
"\t@Override public " ++ jclassS ++ " pop(JObjCRuntime rt, long addr){ " ++
"return pop" ++ capitalize jprimS ++ "(rt, addr); }",
"\t// proxies for mixed encoding",
makeProxyMethods ntype,
"}"
]
where
jprim = ntype2jprim ntype
jclass = jprim2jclass jprim
jprimS = jprim2js jprim
jclassS = jclass2js jclass
ntypeS = ntype2js ntype
className = coderName ntype
-- Generate push and pop methods that convert and proxy to actual implementation.
makeProxyMethods nt = unlines $ map aux jprims
where
targetJPrim = ntype2jprim nt
targetJPrimS = jprim2js targetJPrim
aux jprim = if targetJPrim == jprim then "" else unlines [
"\t@Override public void push(JObjCRuntime rt, long addr, " ++ jprimS ++ " x){ " ++
"push(rt, addr, " ++ pushConversion "x" ++ "); }",
"\t@Override public " ++ jprimS ++ " pop" ++ capitalize jprimS ++ "(JObjCRuntime rt, long addr){ " ++
"return " ++ (popConversion ("pop" ++ capitalize targetJPrimS ++ "(rt, addr)")) ++ "; }"
]
where
jprimS = jprim2js jprim
pushConversion sym = jconvertPrims sym jprim targetJPrim
popConversion sym = jconvertPrims sym targetJPrim jprim
main = do
putStrLn "package com.apple.jobjc;"
putStrLn "import com.apple.jobjc.JObjCRuntime.Width;"
putStrLn "// Auto generated by PrimitiveCoder.hs"
putStrLn "// Do not edit by hand."
putStrLn "public abstract class PrimitiveCoder<T> extends Coder<T>{"
putStrLn "\tpublic PrimitiveCoder(int ffiTypeCode, String objCEncoding, Class jclass, Class jprim){"
putStrLn "\t\tsuper(ffiTypeCode, objCEncoding, jclass, jprim);"
putStrLn "\t}"
mapM_ (\p -> putStrLn $ unlines [makePopI p, makePushI p]) jprims
mapM_ (putStrLn . c2java) ntypes
putStrLn "}"
where
makePopI jprim = unlines ["\tpublic final " ++ jprim2js jprim ++ " pop" ++ (capitalize.jprim2js $ jprim)
++ "(NativeArgumentBuffer args){\n"
++ "\t\treturn pop" ++ (capitalize.jprim2js $ jprim) ++ "(args.runtime, args.retValPtr);\n"
++ "\t}",
"\tpublic abstract " ++ jprim2js jprim ++ " pop" ++ (capitalize.jprim2js $ jprim) ++ "(JObjCRuntime runtime, long addr);"]
makePushI jprim = unlines ["\tpublic final void push"
++ "(NativeArgumentBuffer args, " ++ jprim2js jprim ++ " x){\n"
++ "\t\tpush(args.runtime, args.argValuesPtr, x);\n"
++ "\t\targs.didPutArgValue(sizeof());\n"
++ "\t}",
"\tpublic abstract void push(JObjCRuntime runtime, long addr, " ++ jprim2js jprim ++ " x);"]

View File

@ -1,63 +0,0 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.jobjc;
import com.apple.jobjc.Coder.PrimitivePointerCoder;
class CIF {
private static native int getSizeofCIF();
private static final int SIZEOF = getSizeofCIF();
private static native boolean prepCIF(long cifPtr, int nargs, long retFFITypePtr, long argsPtr);
public static CIF createCIFFor(final NativeArgumentBuffer args, final Coder returnCoder, final Coder ... argCoders) {
NativeBuffer cifBuf = new NativeBuffer(SIZEOF + (argCoders.length * JObjCRuntime.PTR_LEN));
final long argsPtr = cifBuf.bufferPtr + SIZEOF;
{
long argsIterPtr = argsPtr;
for(final Coder coder : argCoders){
PrimitivePointerCoder.INST.push(args.runtime, argsIterPtr, coder.getFFITypePtr());
argsIterPtr += JObjCRuntime.PTR_LEN;
}
}
boolean ok = prepCIF(cifBuf.bufferPtr, argCoders.length, returnCoder.getFFITypePtr(), argsPtr);
if(!ok)
throw new RuntimeException("ffi_prep_cif failed.");
return new CIF(cifBuf, returnCoder, argCoders);
}
final NativeBuffer cif;
// CIF needs to keep refs to the Coders, so they don't get finalized and their FFITypes freed.
final Coder returnCoder;
final Coder[] argCoders;
private CIF(final NativeBuffer cif, Coder returnCoder, Coder... argCoders) {
this.cif = cif;
this.returnCoder = returnCoder;
this.argCoders = argCoders;
}
}

View File

@ -1,289 +0,0 @@
/*
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.jobjc;
import java.io.StringWriter;
import java.lang.reflect.Method;
import com.apple.jobjc.JObjCRuntime.Width;
import com.apple.jobjc.PrimitiveCoder.BoolCoder;
import com.apple.jobjc.PrimitiveCoder.DoubleCoder;
import com.apple.jobjc.PrimitiveCoder.FloatCoder;
import com.apple.jobjc.PrimitiveCoder.SCharCoder;
import com.apple.jobjc.PrimitiveCoder.SIntCoder;
import com.apple.jobjc.PrimitiveCoder.SLongLongCoder;
import com.apple.jobjc.PrimitiveCoder.SShortCoder;
public abstract class Coder<T> {
private static native long getNativeFFITypePtrForCode(final int code);
static final int FFI_VOID = 0;
static final int FFI_PTR = FFI_VOID+1;
static final int FFI_SINT8 = FFI_PTR+1;
static final int FFI_UINT8 = FFI_SINT8+1;
static final int FFI_SINT16 = FFI_UINT8+1;
static final int FFI_UINT16 = FFI_SINT16+1;
static final int FFI_SINT32 = FFI_UINT16+1;
static final int FFI_UINT32 = FFI_SINT32+1;
static final int FFI_SINT64 = FFI_UINT32+1;
static final int FFI_UINT64 = FFI_SINT64+1;
static final int FFI_FLOAT = FFI_UINT64+1;
static final int FFI_DOUBLE = FFI_FLOAT+1;
static final int FFI_LONGDOUBLE = FFI_DOUBLE+1;
private static long[] ffiCodesToFFITypePtrs;
static{
System.loadLibrary("JObjC");
ffiCodesToFFITypePtrs = new long[FFI_LONGDOUBLE + 1];
for (int i = 0; i < FFI_LONGDOUBLE + 1; i++) ffiCodesToFFITypePtrs[i] = getNativeFFITypePtrForCode(i);
}
long getFFITypePtr() {
return ffiCodesToFFITypePtrs[getTypeCode()];
}
// runtime coding
public abstract void push(final JObjCRuntime runtime, final long addr, final T x);
public abstract T pop(final JObjCRuntime runtime, final long addr);
public void push(final NativeArgumentBuffer args, final T x){
push(args.runtime, args.argValuesPtr, x);
args.didPutArgValue(sizeof());
}
public T pop(final NativeArgumentBuffer args){
return pop(args.runtime, args.retValPtr);
}
public abstract int sizeof(Width w);
final public int sizeof(){ return sizeof(JObjCRuntime.WIDTH); }
//
public Coder(int ffiTypeCode, String objCEncoding, Class jclass, Class jprim) {
this.ffiTypeCode = ffiTypeCode;
this.objCEncoding = objCEncoding;
this.jclass = jclass;
this.jprim = jprim;
}
public Coder(int ffiTypeCode, String objCEncoding, Class jclass) {
this(ffiTypeCode, objCEncoding, jclass, null);
}
private final int ffiTypeCode;
private final String objCEncoding;
private final Class jclass;
private final Class jprim;
final int getTypeCode() { return ffiTypeCode; }
final String getObjCEncoding(){ return objCEncoding; }
public final Class getJavaClass() { return jclass; }
public final Class getJavaPrimitive() { return jprim; }
// runtime coding
private static Coder[] runtimeCoders;
static public Coder getCoderAtRuntimeForType(Class cls){
if(runtimeCoders == null) runtimeCoders = new Coder[]{
NSClassCoder.INST, IDCoder.INST, PointerCoder.INST,
DoubleCoder.INST, FloatCoder.INST, SLongLongCoder.INST,
SIntCoder.INST, SShortCoder.INST, SCharCoder.INST, BoolCoder.INST,
VoidCoder.INST
};
for(Coder c : runtimeCoders)
if((c.getJavaClass() != null && c.getJavaClass().isAssignableFrom(cls)) ||
(c.getJavaPrimitive() != null && c.getJavaPrimitive().isAssignableFrom(cls)))
return c;
if(Struct.class.isAssignableFrom(cls)){
try {
Method m = cls.getDeclaredMethod("getStructCoder");
m.setAccessible(true);
return (Coder) m.invoke(null);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
throw new RuntimeException("Could not find suitable coder for " + cls);
}
static public Coder getCoderAtRuntime(Object inst){
if(inst == null) return PointerCoder.INST;
if(inst instanceof Struct) return ((Struct) inst).getCoder();
return getCoderAtRuntimeForType(inst.getClass());
}
//
public static final class VoidCoder extends Coder<Object>{
public static final VoidCoder INST = new VoidCoder();
public VoidCoder(){ super(FFI_VOID, "v", Void.class, void.class); }
@Override public int sizeof(Width w) { return -1; }
@Override public Object pop(JObjCRuntime runtime, long addr) { throw new RuntimeException("Trying to pop a Void."); }
@Override public void push(JObjCRuntime runtime, long addr, Object x) { throw new RuntimeException("Trying to push a Void."); }
}
public static final class UnknownCoder extends Coder<Object> {
public static final UnknownCoder INST = new UnknownCoder();
public UnknownCoder(){ super(-1, "?", null, null); }
@Override public int sizeof(Width w) { return -1; }
@Override public void push(JObjCRuntime runtime, long addr, Object x) { throw new RuntimeException("Coder not implemented");}
@Override public Object pop(JObjCRuntime runtime, long addr) { throw new RuntimeException("Coder not implemented"); }
}
public static final class PrimitivePointerCoder extends Coder<Long> {
public static final PrimitivePointerCoder INST = new PrimitivePointerCoder();
public PrimitivePointerCoder(){ super(Coder.FFI_PTR, "^?", Long.class, long.class); }
@Override public int sizeof(Width w) { return JObjCRuntime.PTR_LEN; }
public void push(JObjCRuntime runtime, long addr, long x) {
if(JObjCRuntime.IS64)
runtime.unsafe.putLong(addr, x);
else
runtime.unsafe.putInt(addr, (int) x);
}
public void push(final JObjCRuntime runtime, final NativeArgumentBuffer argBuf, final long ptr) {
push(runtime, argBuf.argValuesPtr, ptr);
argBuf.didPutArgValue(sizeof());
}
public long popPtr(final JObjCRuntime runtime, final long addr) {
return JObjCRuntime.IS64 ? runtime.unsafe.getLong(addr) : runtime.unsafe.getInt(addr);
}
public long popPtr(final JObjCRuntime runtime, final NativeArgumentBuffer argBuf) {
return popPtr(runtime, argBuf.retValPtr);
}
@Override public Long pop(JObjCRuntime runtime, long addr) { return popPtr(runtime, addr); }
@Override public void push(JObjCRuntime runtime, long addr, Long x) { push(runtime, addr, (long) x); }
}
public static final class PointerCoder extends Coder<Pointer> {
public static final PointerCoder INST = new PointerCoder();
public PointerCoder(){ super(FFI_PTR, "^?", Pointer.class); }
@Override public int sizeof(Width w) { return PrimitivePointerCoder.INST.sizeof(w); }
@Override public Pointer pop(JObjCRuntime runtime, long addr) {
return new Pointer(PrimitivePointerCoder.INST.popPtr(runtime, addr));
}
@Override public void push(JObjCRuntime runtime, long addr, Pointer x) {
PrimitivePointerCoder.INST.push(runtime, addr, x == null ? 0 : x.ptr);
}
}
public static final class SELCoder extends Coder<SEL> {
public static final SELCoder INST = new SELCoder();
public SELCoder(){ super(FFI_PTR, ":", SEL.class); }
@Override public int sizeof(Width w) { return PrimitivePointerCoder.INST.sizeof(w); }
@Override public void push(JObjCRuntime runtime, long addr, SEL x) {
PrimitivePointerCoder.INST.push(runtime, addr, x == null ? 0 : x.selPtr);
}
@Override public SEL pop(JObjCRuntime runtime, long addr) {
return new SEL(PrimitivePointerCoder.INST.popPtr(runtime, addr));
}
}
public static abstract class StructCoder extends Coder<Struct> {
private final FFIType ffiType;
final int sizeof;
public StructCoder(final int sizeof, final Coder... elementCoders){
super(-1, objCEncoding(elementCoders), null);
this.ffiType = new FFIType(elementCoders);
this.sizeof = sizeof;
}
@Override public int sizeof(Width w) { return sizeof; }
private static String objCEncoding(final Coder[] elementCoders) {
StringWriter str = new StringWriter();
str.append("{?=");
for(Coder c : elementCoders)
str.append(c.getObjCEncoding());
str.append("}");
return str.toString();
}
@Override long getFFITypePtr() { return ffiType.getPtr(); }
@Override public void push(NativeArgumentBuffer argBuf, Struct x) {
// Just point to the instance on the heap instead of copying it onto the arg buf.
argBuf.doPutArgPtr(x.raw.bufferPtr);
}
@Override public void push(JObjCRuntime rt, long addr, Struct x) {
rt.unsafe.copyMemory(x.raw.bufferPtr, addr, sizeof);
}
protected abstract Struct newInstance(JObjCRuntime runtime);
@Override public Struct pop(final JObjCRuntime runtime, final long addr) {
Struct s = newInstance(runtime);
runtime.unsafe.copyMemory(addr, s.raw.bufferPtr, sizeof);
return s;
}
}
public static final class IDCoder extends Coder<ID>{
public static final IDCoder INST = new IDCoder();
public IDCoder(){ super(FFI_PTR, "@", ID.class); }
@Override public int sizeof(Width w) { return PrimitivePointerCoder.INST.sizeof(w); }
public <T extends ID> T newID(final JObjCRuntime runtime, final long objPtr) {
return (T) ID.getObjCObjectFor(runtime, objPtr);
}
@Override public ID pop(final JObjCRuntime runtime, final long addr) {
return newID(runtime, PrimitivePointerCoder.INST.popPtr(runtime, addr));
}
@Override public void push(final JObjCRuntime runtime, final long addr, final ID x) {
PointerCoder.INST.push(runtime, addr, x);
}
}
public static final class NSClassCoder extends Coder<NSClass>{
public static final NSClassCoder INST = new NSClassCoder();
public NSClassCoder(){ super(FFI_PTR, "#", NSClass.class); }
@Override public int sizeof(Width w) { return PrimitivePointerCoder.INST.sizeof(w); }
@Override public NSClass pop(JObjCRuntime runtime, long addr) {
final long clsPtr = PrimitivePointerCoder.INST.popPtr(runtime, addr);
if (clsPtr == 0) return null;
return NSClass.getObjCClassFor(runtime, clsPtr);
}
@Override public void push(JObjCRuntime runtime, long addr, NSClass x) {
PointerCoder.INST.push(runtime, addr, x);
}
}
}

View File

@ -1,57 +0,0 @@
/*
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.jobjc;
import com.apple.jobjc.Coder.PrimitivePointerCoder;
class FFIType{
private static native void makeFFIType(long ffi_type_buf, long elements_buf);
private static native int getFFITypeSizeof();
private static int FFI_TYPE_SIZEOF = getFFITypeSizeof();
final NativeBuffer ffi_type;
final NativeBuffer elements;
final Coder[] elementCoders;
public FFIType(final Coder... elementCoders){
final JObjCRuntime runtime = JObjCRuntime.inst();
this.elementCoders = elementCoders;
this.ffi_type = new NativeBuffer(FFI_TYPE_SIZEOF);
this.elements = new NativeBuffer(JObjCRuntime.PTR_LEN * (elementCoders.length + 1));
long elIterPtr = elements.bufferPtr;
for(Coder c : elementCoders){
PrimitivePointerCoder.INST.push(runtime, elIterPtr, c.getFFITypePtr());
elIterPtr += PrimitivePointerCoder.INST.sizeof();
}
PrimitivePointerCoder.INST.push(runtime, elIterPtr, 0);
makeFFIType(ffi_type.bufferPtr, elements.bufferPtr);
}
public long getPtr(){
return ffi_type.bufferPtr;
}
}

View File

@ -1,60 +0,0 @@
/*
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.jobjc;
public class Function {
private static native long getFxnPtrForFunctionName(final String functionName);
private static native long getFxnPtrForFunctionNameAndLib(final long libPtr, final String functionName);
final long fxnPtr;
Function(final long fxnPtr) {
this.fxnPtr = fxnPtr;
}
public Function(final String name) {
this(getFxnPtr(name));
}
public Function(final MacOSXFramework framework, final String name) {
this(getFxnPtr(name, framework));
}
static long getFxnPtr(final String name){
long fxnPtr = getFxnPtrForFunctionName(name);
if(fxnPtr == 0) throw new RuntimeException("Function pointer for " + name + " not found in runtime.");
return fxnPtr;
}
static long getFxnPtr(final String name, final MacOSXFramework framework){
long fxnPtr = 0;
for(int i = 0; fxnPtr == 0 && i < framework.nativeLibPtrs.length; i++){
fxnPtr = getFxnPtrForFunctionNameAndLib(framework.nativeLibPtrs[i], name);
if(fxnPtr != 0) return fxnPtr;
}
throw new RuntimeException("Function pointer for " + name + " not found in framework " + framework + ".");
}
}

View File

@ -1,163 +0,0 @@
/*
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.jobjc;
import java.lang.ref.WeakReference;
import java.lang.reflect.Constructor;
import java.util.LinkedHashMap;
import java.util.Map;
public class ID extends Pointer<Void>{
static native String getNativeDescription(final long objPtr);
final JObjCRuntime runtime;
static final Class[] CTOR_ARGS = { long.class, JObjCRuntime.class };
protected ID(final long objPtr, final JObjCRuntime runtime) {
super(objPtr);
runtime.assertOK();
this.runtime = runtime;
}
protected ID(final ID obj, final JObjCRuntime runtime) {
this(obj.ptr, runtime);
}
@Override protected NativeObjectLifecycleManager getNativeObjectLifecycleManager() {
return NativeObjectLifecycleManager.CFRetainRelease.INST;
}
protected final JObjCRuntime getRuntime() { return runtime; }
@Override public String toString(){
String s = super.toString();
return s + " (ObjC: " + ptr + " / " + Long.toHexString(ptr) + ")";
}
//
public static <T extends ID> T getInstance(final long ptr, final JObjCRuntime runtime){
return (T) getObjCObjectFor(runtime, ptr);
}
static <T extends ID> T getObjCObjectFor(final JObjCRuntime runtime, final long objPtr){
if (objPtr == 0) return null;
final WeakReference cachedObj = objectCache.get().get(objPtr);
if(cachedObj != null && cachedObj.get() != null) return (T) cachedObj.get();
final long clsPtr = NSClass.getClass(objPtr);
final T newObj = (T) (runtime.subclassing.isUserClass(clsPtr) ?
Subclassing.getJObjectFromIVar(objPtr)
: createNewObjCObjectFor(runtime, objPtr, clsPtr));
objectCache.get().put(objPtr, new WeakReference(newObj));
return newObj;
}
static <T extends ID> T createNewObjCObjectFor(final JObjCRuntime runtime, final long objPtr, final long clsPtr) {
final Constructor<T> ctor = getConstructorForClassPtr(runtime, clsPtr);
return (T) createNewObjCObjectForConstructor(ctor, objPtr, runtime);
}
@SuppressWarnings("unchecked")
static <T extends ID> Constructor<T> getConstructorForClassPtr(final JObjCRuntime runtime, final long clazzPtr){
final Constructor<T> cachedCtor = (Constructor<T>) constructorCache.get().get(clazzPtr);
if(cachedCtor != null) return cachedCtor;
final Class<T> clazz = getClassForClassPtr(runtime, clazzPtr);
Constructor<T> ctor;
try {
ctor = clazz.getDeclaredConstructor(CTOR_ARGS);
} catch (SecurityException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
ctor.setAccessible(true);
constructorCache.get().put(clazzPtr, (Constructor<ID>) ctor);
return ctor;
}
@SuppressWarnings("unchecked")
static <T extends ID> Class<T> getClassForClassPtr(final JObjCRuntime runtime, final long clazzPtr){
final String className = NSClass.getClassNameOfClass(clazzPtr);
final Class<T> clazz = (Class<T>) runtime.getClassForNativeClassName(className);
if(clazz == null){
final long superClazzPtr = NSClass.getSuperClassOfClass(clazzPtr);
if(superClazzPtr != 0)
return getClassForClassPtr(runtime, superClazzPtr);
}
return clazz;
}
static <T extends ID> T createNewObjCObjectForConstructor(final Constructor ctor, final long objPtr, final JObjCRuntime runtime) {
try {
final T newInstance = (T) ctor.newInstance(new Object[] { Long.valueOf(objPtr), runtime });
objectCache.get().put(objPtr, new WeakReference(newInstance));
return newInstance;
} catch (final Exception e) {
throw new RuntimeException(e);
}
}
static <T extends ID> T createNewObjCObjectForClass(final Class<T> clazz, final long objPtr, final JObjCRuntime runtime) {
try {
final Constructor<T> constructor = clazz.getDeclaredConstructor(CTOR_ARGS);
constructor.setAccessible(true);
return (T) createNewObjCObjectForConstructor(constructor, objPtr, runtime);
} catch (final Exception e) {
throw new RuntimeException(e);
}
}
//
static final ThreadLocal<LinkedHashMap<Long, Constructor>> constructorCache = new ThreadLocal<LinkedHashMap<Long, Constructor>>(){
@Override protected LinkedHashMap<Long, Constructor> initialValue(){
final int MAX_ENTRIES = 1000;
final float LOAD_FACTOR = 0.75f;
return new LinkedHashMap<Long, Constructor>((int) (MAX_ENTRIES/LOAD_FACTOR), LOAD_FACTOR, true) {
@Override protected boolean removeEldestEntry(Map.Entry<Long, Constructor> eldest) {
return size() > MAX_ENTRIES;
}
};
}
};
static final ThreadLocal<LinkedHashMap<Long, WeakReference>> objectCache = new ThreadLocal<LinkedHashMap<Long, WeakReference>>(){
@Override protected LinkedHashMap<Long, WeakReference> initialValue(){
final int MAX_ENTRIES = 1000;
final float LOAD_FACTOR = 0.75f;
return new LinkedHashMap<Long, WeakReference>((int) (MAX_ENTRIES/LOAD_FACTOR), LOAD_FACTOR, true) {
@Override protected boolean removeEldestEntry(Map.Entry<Long, WeakReference> eldest) {
return size() > MAX_ENTRIES || eldest.getValue().get() == null;
}
};
}
};
}

View File

@ -1,224 +0,0 @@
/*
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.jobjc;
import com.apple.jobjc.Coder.IDCoder;
import com.apple.jobjc.Coder.NSClassCoder;
import com.apple.jobjc.Coder.PrimitivePointerCoder;
import com.apple.jobjc.Coder.SELCoder;
import com.apple.jobjc.Coder.StructCoder;
public abstract class Invoke {
public abstract void invoke(NativeArgumentBuffer argBuf);
public abstract void invoke(NativeArgumentBuffer buffer, Struct retvalStruct);
//
public static final class FunCall extends Invoke{
static native void invoke(long cifPtr, long fxnPtr, long retValPtr, long argsPtr);
final long fxnPtr;
final CIF cif;
FunCall(long fxnPtr, CIF cif) {
this.fxnPtr = fxnPtr;
this.cif = cif;
}
public FunCall(final JObjCRuntime runtime, final String name, final Coder returnCoder, final Coder ... argCoders) {
this(Function.getFxnPtr(name), CIF.createCIFFor(runtime.getThreadLocalState(), returnCoder, argCoders));
}
public FunCall(final MacOSXFramework framework, final String name, final Coder returnCoder, final Coder ... argCoders) {
this(Function.getFxnPtr(name, framework), CIF.createCIFFor(framework.getRuntime().getThreadLocalState(), returnCoder, argCoders));
}
public void init(final NativeArgumentBuffer argBuf) {
argBuf.reset();
}
@Override public void invoke(final NativeArgumentBuffer argBuf) {
invoke(argBuf, argBuf.retValPtr);
}
@Override public void invoke(final NativeArgumentBuffer buffer, final Struct retvalStruct) {
invoke(buffer, retvalStruct.raw.bufferPtr);
}
void invoke(final NativeArgumentBuffer argBuf, final long retValPtr) {
invoke(cif.cif.bufferPtr, fxnPtr, retValPtr, argBuf.buffer.bufferPtr);
}
}
public static final class MsgSend extends Invoke{
static{ System.load("/usr/lib/libobjc.dylib"); }
private static final long OBJC_MSG_SEND_FXN_PTR = new Function("objc_msgSend").fxnPtr;
private static final long OBJC_MSG_SEND_FPRET_FXN_PTR = new Function("objc_msgSend_fpret").fxnPtr;
private static final long OBJC_MSG_SEND_STRET_FXN_PTR = new Function("objc_msgSend_stret").fxnPtr;
final FunCall funCall;
final long selPtr;
public MsgSend(final JObjCRuntime runtime, final String name, final Coder returnCoder, final Coder ... argCoders) {
this.funCall = new FunCall(getMsgSendFxnPtr(returnCoder),
CIF.createCIFFor(runtime.getThreadLocalState(), returnCoder, getSelCoders(argCoders)));
this.selPtr = SEL.getSelectorPtr(name);
}
public void init(final NativeArgumentBuffer nativeBuffer, final ID obj) {
funCall.init(nativeBuffer);
IDCoder.INST.push(nativeBuffer, obj);
PrimitivePointerCoder.INST.push(nativeBuffer.runtime, nativeBuffer, selPtr);
}
@Override public void invoke(final NativeArgumentBuffer argBuf) {
funCall.invoke(argBuf);
}
@Override public void invoke(final NativeArgumentBuffer buffer, final Struct retvalStruct) {
funCall.invoke(buffer, retvalStruct);
}
// support
static Coder[] getSelCoders(final Coder[] argCoders) {
final Coder[] selArgCoders = new Coder[argCoders.length + 2];
selArgCoders[0] = IDCoder.INST;
selArgCoders[1] = SELCoder.INST;
for (int i = 0; i < argCoders.length; i++)
selArgCoders[i + 2] = argCoders[i];
return selArgCoders;
}
static long getMsgSendFxnPtr(final Coder returnCoder) {
if(returnCoder instanceof StructCoder){
StructCoder scoder = (StructCoder) returnCoder;
switch(JObjCRuntime.ARCH){
case ppc:
return OBJC_MSG_SEND_STRET_FXN_PTR;
case i386:
switch(scoder.sizeof){
case 1: case 2: case 4: case 8:
return OBJC_MSG_SEND_FXN_PTR;
}
return OBJC_MSG_SEND_STRET_FXN_PTR;
case x86_64:
if(scoder.sizeof > 16)
return OBJC_MSG_SEND_STRET_FXN_PTR;
else
return OBJC_MSG_SEND_FXN_PTR;
default:
throw new RuntimeException();
}
}
final int typeCode = returnCoder.getTypeCode();
switch(JObjCRuntime.ARCH){
case ppc:
return OBJC_MSG_SEND_FXN_PTR;
case i386:
switch(typeCode) {
case Coder.FFI_FLOAT: case Coder.FFI_DOUBLE: case Coder.FFI_LONGDOUBLE:
return OBJC_MSG_SEND_FPRET_FXN_PTR;
}
return OBJC_MSG_SEND_FXN_PTR;
case x86_64:
if(typeCode == Coder.FFI_LONGDOUBLE)
return OBJC_MSG_SEND_FPRET_FXN_PTR;
return OBJC_MSG_SEND_FXN_PTR;
default:
throw new RuntimeException();
}
}
}
public static final class MsgSendSuper extends Invoke{
static{ System.load("/usr/lib/libobjc.dylib"); }
private static final long OBJC_MSG_SEND_SUPER_FXN_PTR = new Function("objc_msgSendSuper").fxnPtr;
private static final long OBJC_MSG_SEND_SUPER_STRET_FXN_PTR = new Function("objc_msgSendSuper_stret").fxnPtr;
final FunCall funCall;
final long selPtr;
public MsgSendSuper(final JObjCRuntime runtime, final String name, final Coder returnCoder, final Coder ... argCoders) {
this.funCall = new FunCall(getMsgSendSuperFxnPtr(returnCoder),
CIF.createCIFFor(runtime.getThreadLocalState(), returnCoder, getSuperSelCoders(argCoders)));
this.selPtr = SEL.getSelectorPtr(name);
}
public void init(final NativeArgumentBuffer argBuf, final ID obj, final NSClass cls) {
funCall.init(argBuf);
// Instead of mallocing a struct, or keeping another thread local,
// let's write objc_super out to the argbuf, and then point an argument
// to the data.
final long valPtr = argBuf.argValuesPtr;
final int ptrLen = JObjCRuntime.PTR_LEN;
IDCoder .INST.push(argBuf.runtime, valPtr, obj);
NSClassCoder.INST.push(argBuf.runtime, valPtr + ptrLen, cls);
argBuf.argValuesPtr += ptrLen + ptrLen;
PrimitivePointerCoder.INST.push(argBuf.runtime, argBuf, valPtr);
PrimitivePointerCoder.INST.push(argBuf.runtime, argBuf, selPtr);
}
@Override public void invoke(final NativeArgumentBuffer argBuf) {
funCall.invoke(argBuf);
}
@Override public void invoke(final NativeArgumentBuffer buffer, final Struct retvalStruct) {
funCall.invoke(buffer, retvalStruct);
}
//
private final static StructCoder objc_super_coder = new StructCoder(JObjCRuntime.PTR_LEN*2, IDCoder.INST, NSClassCoder.INST){
@Override protected Struct newInstance(JObjCRuntime runtime) { return null; }};
static Coder[] getSuperSelCoders(final Coder[] argCoders) {
final Coder[] selArgCoders = new Coder[argCoders.length + 2];
selArgCoders[0] = objc_super_coder;
selArgCoders[1] = SELCoder.INST;
for (int i = 0; i < argCoders.length; i++)
selArgCoders[i + 2] = argCoders[i];
return selArgCoders;
}
static long getMsgSendSuperFxnPtr(final Coder returnCoder){
long normal = MsgSend.getMsgSendFxnPtr(returnCoder);
if(normal == MsgSend.OBJC_MSG_SEND_STRET_FXN_PTR)
return OBJC_MSG_SEND_SUPER_STRET_FXN_PTR;
else
return OBJC_MSG_SEND_SUPER_FXN_PTR;
}
}
}

View File

@ -1,139 +0,0 @@
/*
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.jobjc;
import java.lang.reflect.Field;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.List;
import sun.misc.Unsafe;
public final class JObjCRuntime {
static { System.loadLibrary("JObjC"); }
public static enum Arch{ ppc, i386, x86_64 };
public static enum Width{ W32, W64 };
public static final Arch ARCH = getArch();
public static final Width WIDTH = getWidth();
private static Arch getArch(){
String arch = System.getProperty("os.arch");
if("ppc".equals(arch)) return Arch.ppc;
if("i386".equals(arch)) return Arch.i386;
if("x86_64".equals(arch)) return Arch.x86_64;
if("amd64".equals(arch)) return Arch.x86_64;
if("universal".equals(arch)) return Arch.x86_64;
throw new RuntimeException("Did not recognize os.arch system property: '" + arch + "'");
}
private static Width getWidth(){
String width = System.getProperty("sun.arch.data.model");
if("32".equals(width)) return Width.W32;
if("64".equals(width)) return Width.W64;
throw new RuntimeException("Did not recognize sun.arch.data.model system property: '" + width + "'");
}
public static final boolean IS32 = System.getProperty("sun.arch.data.model").equals("32");
public static final boolean IS64 = System.getProperty("sun.arch.data.model").equals("64");
public static final int PTR_LEN = IS64 ? 8 : 4;
public static final boolean IS_BIG_ENDIAN = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
static final boolean DEBUG = Boolean.parseBoolean(System.getProperty("JObjC.debug"));
static void checkPermission(){
final SecurityManager security = System.getSecurityManager();
if (security != null) security.checkPermission(new RuntimePermission("canProcessApplicationEvents"));
}
public final void assertOK(){
if(this != instance)
throw new SecurityException("runtime");
}
private JObjCRuntime(){}
private static JObjCRuntime instance;
static JObjCRuntime inst() {
if (instance == null) instance = new JObjCRuntime();
return instance;
}
public static JObjCRuntime getInstance() {
checkPermission();
return inst();
}
public final NativeArgumentBuffer getThreadLocalState() {
return NativeArgumentBuffer.getThreadLocalBuffer(this);
}
final Unsafe unsafe = getUnsafe();
final Subclassing subclassing = new Subclassing(this);
final List<String> registeredPackages = new ArrayList<String>();
@SuppressWarnings("unchecked")
Class<? extends ID> getClassForNativeClassName(final String className) {
for (final String pkg : registeredPackages) {
try {
final Class<?> clazz = Class.forName(pkg + "." + className);
if (clazz != null) return (Class<? extends ID>)clazz;
} catch (final ClassNotFoundException e) { }
}
return null;
}
private final static Unsafe getUnsafe() {
Unsafe inst = null;
try {
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
inst = (Unsafe) f.get(null);
if(inst == null) throw new NullPointerException("Unsafe.theUnsafe == null");
} catch (Exception e) {
throw new RuntimeException("Unable to get instance of Unsafe.", e);
}
return inst;
}
public void registerPackage(final String pkg) {
registeredPackages.add(pkg);
}
/**
* Register a subclass of NSObject to allow the native side to send
* messages which in turn call java methods declared on the class.
* If a native class by the same name already exists, registerClass
* will simply return without doing anything.
*
* For a usage example, see the SubclassingTest.
*/
public boolean registerUserClass(Class<? extends ID> clazz, Class<? extends NSClass> clazzClazz) {
return subclassing.registerUserClass(clazz, clazzClazz);
}
}

View File

@ -1,74 +0,0 @@
/*
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.jobjc;
public class MacOSXFramework {
private static native long retainFramework(final String frameworkName);
private static native void releaseFramework(final long frameworkPtr);
private static native void getConstant(final long frameworkPtr, String symbol, final long bufferPtr, final int size);
private final JObjCRuntime runtime;
protected final long[] nativeLibPtrs;
final long getFrameworkPtr() { return nativeLibPtrs.length > 0 ? nativeLibPtrs[0] : 0; }
private static long[] createFrameworkPtrsFromPaths(final String[] frameworkLibPaths) {
final long[] libPtrs = new long[frameworkLibPaths.length];
for(int i = 0; i < libPtrs.length; i++){
libPtrs[i] = retainFramework(frameworkLibPaths[i]);
if(libPtrs[i] == 0) throw new RuntimeException("Could not open library at " + frameworkLibPaths[i]);
}
return libPtrs;
}
protected MacOSXFramework(final JObjCRuntime runtime, final String[] nativeLibPaths) {
runtime.assertOK();
this.runtime = runtime;
this.nativeLibPtrs = createFrameworkPtrsFromPaths(nativeLibPaths);
}
@Override protected final synchronized void finalize() throws Throwable {
for(long lib : nativeLibPtrs)
if(lib != 0) releaseFramework(lib);
}
protected final JObjCRuntime getRuntime(){ return runtime; }
protected void getConstant(final String symbol, final long retValPtr, final int size){
assert size >= 0;
assert retValPtr != 0;
getConstant(getFrameworkPtr(), symbol, retValPtr, size);
}
protected void getConstant(final String symbol, final NativeArgumentBuffer out, final int size){
getConstant(symbol, out.retValPtr, size);
}
protected void getConstant(final String symbol, final Struct out, final int size){
getConstant(symbol, out.raw.bufferPtr, size);
}
}

View File

@ -1,117 +0,0 @@
/*
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.jobjc;
import java.lang.ref.WeakReference;
import java.lang.reflect.Constructor;
public class NSClass<T extends ID> extends ID {
public static class NSClassNotFoundException extends RuntimeException{
public NSClassNotFoundException(String m){ super(m); }
public NSClassNotFoundException(String m, Throwable cause){ super(m, cause); }
}
static native long getNativeClassByName(String name);
static native long getSuperClassOfClass(long classPtr);
static native String getClassNameOfClass(long classPtr);
static native long getClass(long objPtr);
public NSClass(final long ptr, final JObjCRuntime runtime) {
super(ptr, runtime);
}
public NSClass(final String name, final JObjCRuntime runtime) {
this(getNativeClassByName(name), runtime);
if(ptr == 0) throw new NSClassNotFoundException("NSClass pointer is 0. Found no class named " + name);
}
protected NSClass(final JObjCRuntime runtime){
super(0, runtime);
final String sn = getClass().getSimpleName();
final String name = sn.substring(0, sn.lastIndexOf("Class"));
ptr = getNativeClassByName(name);
if(ptr == 0) throw new NSClassNotFoundException("NSClass pointer is 0. Found no class named " + name);
}
NSClass<? super T> getSuperClass() {
return new NSClass<T>(getSuperClassOfClass(ptr), runtime);
}
String getClassName() { return getClassNameOfClass(ptr); }
@Override protected NativeObjectLifecycleManager getNativeObjectLifecycleManager() {
return NativeObjectLifecycleManager.Nothing.INST;
}
@Override public boolean equals(Object o){
return (o instanceof NSClass) && (this.ptr == ((NSClass) o).ptr);
}
//
static <T extends NSClass> T getObjCClassFor(final JObjCRuntime runtime, final long clsPtr){
if (clsPtr == 0) return null;
final WeakReference cachedObj = objectCache.get().get(clsPtr);
if(cachedObj != null && cachedObj.get() != null) return (T) cachedObj.get();
final T newObj = (T) createNewObjCClassFor(runtime, clsPtr);
objectCache.get().put(clsPtr, new WeakReference(newObj));
return newObj;
}
static <T extends NSClass> T createNewObjCClassFor(final JObjCRuntime runtime, final long clsPtr) {
final Constructor<T> ctor = getNSClassConstructorForClassPtr(runtime, clsPtr);
return (T) createNewObjCObjectForConstructor(ctor, clsPtr, runtime);
}
@SuppressWarnings("unchecked")
static <T extends NSClass> Constructor<T> getNSClassConstructorForClassPtr(final JObjCRuntime runtime, final long clazzPtr){
final Class<T> clazz = getNSClassForClassPtr(runtime, clazzPtr);
Constructor<T> ctor;
try {
ctor = clazz.getDeclaredConstructor(CTOR_ARGS);
} catch (SecurityException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
ctor.setAccessible(true);
return ctor;
}
@SuppressWarnings("unchecked")
static <T extends ID> Class<T> getNSClassForClassPtr(final JObjCRuntime runtime, final long clazzPtr){
final String className = NSClass.getClassNameOfClass(clazzPtr);
final Class<T> clazz = (Class<T>) runtime.getClassForNativeClassName(className + "Class");
if(clazz == null){
final long superClazzPtr = NSClass.getSuperClassOfClass(clazzPtr);
if(superClazzPtr != 0)
return getNSClassForClassPtr(runtime, superClazzPtr);
}
return clazz;
}
}

View File

@ -1,112 +0,0 @@
/*
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.jobjc;
import java.nio.ByteOrder;
import com.apple.jobjc.Coder.PrimitivePointerCoder;
public final class NativeArgumentBuffer{
private static final ThreadLocal<NativeArgumentBuffer> threadLocal = new ThreadLocal<NativeArgumentBuffer>();
static NativeArgumentBuffer getThreadLocalBuffer(final JObjCRuntime runtime) {
runtime.assertOK();
final NativeArgumentBuffer alreadyCreated = threadLocal.get();
if (alreadyCreated != null) return alreadyCreated;
final NativeArgumentBuffer newThreadLocalState = new NativeArgumentBuffer(runtime);
threadLocal.set(newThreadLocalState);
return newThreadLocalState;
}
final JObjCRuntime runtime;
final NativeBuffer buffer;
long argPtrsPtr;
long argValuesPtr;
final long retValPtr;
private static final int MAX_ARGS = 512;
private static final int BUF_SIZE = MAX_ARGS * 8 * 2;
private static final int ARG_VALS_OFFSET = BUF_SIZE/2;
private NativeArgumentBuffer(final JObjCRuntime runtime) {
runtime.assertOK();
this.runtime = runtime;
this.buffer = new NativeBuffer(BUF_SIZE);
this.buffer.buffer.order(ByteOrder.nativeOrder());
reset();
this.retValPtr = buffer.bufferPtr;
}
// Call before each new call
public void reset() {
argPtrsPtr = buffer.bufferPtr;
argValuesPtr = buffer.bufferPtr + ARG_VALS_OFFSET;
assert buffer.ptrInBounds(argValuesPtr);
}
// Push a pointer to a block of memory
public void doPutArgPtr(long ptr) {
assert buffer.ptrInBounds(argPtrsPtr);
PrimitivePointerCoder.INST.push(runtime, argPtrsPtr, ptr);
argPtrsPtr += JObjCRuntime.PTR_LEN;
}
// Call this after having written a value of size `sizeof` to `argValuesPtr`.
public void didPutArgValue(int sizeof) {
assert buffer.ptrInBounds(argValuesPtr);
doPutArgPtr(argValuesPtr);
argValuesPtr += sizeof;
}
@Override public String toString() {
final StringBuilder builder = new StringBuilder();
final long bptr = buffer.bufferPtr;
for(long i = bptr; i < bptr + ARG_VALS_OFFSET; i += JObjCRuntime.PTR_LEN){
if(argPtrsPtr == i)
builder.append("*");
builder.append(PrimitivePointerCoder.INST.popPtr(JObjCRuntime.inst(), i));
builder.append(" ");
}
builder.append("\n");
for(long i = bptr + ARG_VALS_OFFSET; i < bptr + BUF_SIZE; i += JObjCRuntime.PTR_LEN){
if(argValuesPtr == i)
builder.append("*");
builder.append(PrimitivePointerCoder.INST.popPtr(JObjCRuntime.inst(), i));
builder.append(" ");
}
return builder.toString();
}
}

View File

@ -1,109 +0,0 @@
/*
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.jobjc;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
* A wrapper around a direct ByteBuffer and its native pointer. For documentation, @see java.nio.ByteBuffer
*/
public class NativeBuffer {
static native long getPtrOfBuffer(final ByteBuffer byteBuffer);
public final ByteBuffer buffer;
public final long bufferPtr;
public NativeBuffer(final int capacity){
this(ByteBuffer.allocateDirect(capacity));
}
/**
* Wrap a ByteBuffer and set the ByteOrder to nativeOrder.
*/
public NativeBuffer(ByteBuffer buffer){
this.buffer = buffer;
this.bufferPtr = getPtrOfBuffer(buffer);
assert buffer != null;
assert bufferPtr != 0;
this.buffer.order(ByteOrder.nativeOrder());
}
public byte get() { return buffer.get(); }
public char getChar() { return buffer.getChar(); }
public double getDouble() { return buffer.getDouble(); }
public float getFloat() { return buffer.getFloat(); }
public int getInt() { return buffer.getInt(); }
public long getLong() { return buffer.getLong(); }
public short getShort() { return buffer.getShort(); }
public NativeBuffer put(byte b) { buffer.put(b); return this; }
public NativeBuffer put(NativeBuffer src) { buffer.put(src.buffer); return this; }
public NativeBuffer putChar(char c) { buffer.putChar(c); return this; }
public NativeBuffer putDouble(double d) { buffer.putDouble(d); return this; }
public NativeBuffer putFloat(float f) { buffer.putFloat(f); return this; }
public NativeBuffer putInt(int i) { buffer.putInt(i); return this; }
public NativeBuffer putLong(long l) { buffer.putLong(l); return this; }
public NativeBuffer putShort(short s) { buffer.putShort(s); return this; }
public int capacity() { return buffer.capacity(); }
public int position() { return buffer.position(); }
public NativeBuffer position(int newPosition) { buffer.position(newPosition); return this; }
public NativeBuffer rewind(){ buffer.rewind(); return this; }
public int limit() { return buffer.limit(); }
public NativeBuffer limit(final int sizeof) { buffer.limit(sizeof); return this; }
public int remaining() { return buffer.remaining(); }
public NativeBuffer slice(){ return new NativeBuffer(buffer.slice()); }
@Override public String toString() {
final StringBuilder builder = new StringBuilder();
for(int i = 0; i < limit(); i += JObjCRuntime.PTR_LEN){
if(position() == i)
builder.append("*");
if(JObjCRuntime.IS32)
builder.append(buffer.getInt(i));
else
builder.append(buffer.getLong(i));
builder.append(" ");
}
return builder.toString();
}
public long positionPtr() {
return bufferPtr + position();
}
/**
* bufferPtr <= ptr && ptr < bufferPtr + capacity();
*/
public boolean ptrInBounds(final long ptr){
return bufferPtr <= ptr && ptr < bufferPtr + capacity();
}
}

View File

@ -1,55 +0,0 @@
/*
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.jobjc;
public abstract class NativeObjectLifecycleManager {
private static native void retainNativeObject(final long ptr);
private static native void releaseNativeObject(final long ptr);
private static native void freeNativeObject(final long ptr);
abstract void begin(final long ptr);
abstract void end(final long ptr);
boolean shouldPreRetain() { return false; }
public static class CFRetainRelease extends NativeObjectLifecycleManager {
public static final NativeObjectLifecycleManager INST = new CFRetainRelease();
@Override void begin(final long ptr) { retainNativeObject(ptr); }
@Override void end(final long ptr) { releaseNativeObject(ptr); }
@Override boolean shouldPreRetain() { return true; }
}
public static class Free extends NativeObjectLifecycleManager {
public static final NativeObjectLifecycleManager INST = new Free();
@Override void begin(final long ptr) { }
@Override void end(final long ptr) { freeNativeObject(ptr); }
}
public static class Nothing extends NativeObjectLifecycleManager {
public static final NativeObjectLifecycleManager INST = new Nothing();
@Override void begin(final long ptr) { }
@Override void end(final long ptr) { }
}
}

View File

@ -1,57 +0,0 @@
/*
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.jobjc;
public class Pointer <T> implements Comparable<Pointer<T>>{
long ptr;
protected Pointer(final long ptr) {
this.ptr = ptr;
getNativeObjectLifecycleManager().begin(ptr);
}
@Override protected final synchronized void finalize() throws Throwable {
long pptr = ptr;
ptr = 0;
if (pptr != 0) getNativeObjectLifecycleManager().end(pptr);
}
protected NativeObjectLifecycleManager getNativeObjectLifecycleManager() {
return NativeObjectLifecycleManager.Nothing.INST;
}
@Override public boolean equals(Object o) {
return o instanceof Pointer && ptr == ((Pointer) o).ptr;
}
@Override public int hashCode() { return (int)(ptr^(ptr>>>32)); }
public int compareTo(Pointer<T> o) {
if(this==o || ptr==o.ptr) return 0;
if(ptr < o.ptr) return -1;
return 1;
}
}

View File

@ -1,700 +0,0 @@
/*
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.jobjc;
import com.apple.jobjc.JObjCRuntime.Width;
// Auto generated by PrimitiveCoder.hs
// Do not edit by hand.
public abstract class PrimitiveCoder<T> extends Coder<T>{
public PrimitiveCoder(int ffiTypeCode, String objCEncoding, Class jclass, Class jprim){
super(ffiTypeCode, objCEncoding, jclass, jprim);
}
public final boolean popBoolean(NativeArgumentBuffer args){
return popBoolean(args.runtime, args.retValPtr);
}
public abstract boolean popBoolean(JObjCRuntime runtime, long addr);
public final void push(NativeArgumentBuffer args, boolean x){
push(args.runtime, args.argValuesPtr, x);
args.didPutArgValue(sizeof());
}
public abstract void push(JObjCRuntime runtime, long addr, boolean x);
public final byte popByte(NativeArgumentBuffer args){
return popByte(args.runtime, args.retValPtr);
}
public abstract byte popByte(JObjCRuntime runtime, long addr);
public final void push(NativeArgumentBuffer args, byte x){
push(args.runtime, args.argValuesPtr, x);
args.didPutArgValue(sizeof());
}
public abstract void push(JObjCRuntime runtime, long addr, byte x);
public final char popChar(NativeArgumentBuffer args){
return popChar(args.runtime, args.retValPtr);
}
public abstract char popChar(JObjCRuntime runtime, long addr);
public final void push(NativeArgumentBuffer args, char x){
push(args.runtime, args.argValuesPtr, x);
args.didPutArgValue(sizeof());
}
public abstract void push(JObjCRuntime runtime, long addr, char x);
public final short popShort(NativeArgumentBuffer args){
return popShort(args.runtime, args.retValPtr);
}
public abstract short popShort(JObjCRuntime runtime, long addr);
public final void push(NativeArgumentBuffer args, short x){
push(args.runtime, args.argValuesPtr, x);
args.didPutArgValue(sizeof());
}
public abstract void push(JObjCRuntime runtime, long addr, short x);
public final int popInt(NativeArgumentBuffer args){
return popInt(args.runtime, args.retValPtr);
}
public abstract int popInt(JObjCRuntime runtime, long addr);
public final void push(NativeArgumentBuffer args, int x){
push(args.runtime, args.argValuesPtr, x);
args.didPutArgValue(sizeof());
}
public abstract void push(JObjCRuntime runtime, long addr, int x);
public final long popLong(NativeArgumentBuffer args){
return popLong(args.runtime, args.retValPtr);
}
public abstract long popLong(JObjCRuntime runtime, long addr);
public final void push(NativeArgumentBuffer args, long x){
push(args.runtime, args.argValuesPtr, x);
args.didPutArgValue(sizeof());
}
public abstract void push(JObjCRuntime runtime, long addr, long x);
public final float popFloat(NativeArgumentBuffer args){
return popFloat(args.runtime, args.retValPtr);
}
public abstract float popFloat(JObjCRuntime runtime, long addr);
public final void push(NativeArgumentBuffer args, float x){
push(args.runtime, args.argValuesPtr, x);
args.didPutArgValue(sizeof());
}
public abstract void push(JObjCRuntime runtime, long addr, float x);
public final double popDouble(NativeArgumentBuffer args){
return popDouble(args.runtime, args.retValPtr);
}
public abstract double popDouble(JObjCRuntime runtime, long addr);
public final void push(NativeArgumentBuffer args, double x){
push(args.runtime, args.argValuesPtr, x);
args.didPutArgValue(sizeof());
}
public abstract void push(JObjCRuntime runtime, long addr, double x);
// native BOOL -> java boolean
public static final class BoolCoder extends PrimitiveCoder<Boolean>{
public static final BoolCoder INST = new BoolCoder();
public BoolCoder(){ super(FFI_SINT8, "B", Boolean.class, boolean.class); }
// compile time
@Override public void push(JObjCRuntime rt, long addr, boolean x){
rt.unsafe.putByte(addr, (byte) (x ? 1 : 0));
}
@Override public boolean popBoolean(JObjCRuntime rt, long addr){
return rt.unsafe.getByte(addr) != 0;
}
// for runtime coding
@Override public int sizeof(Width w){
return 1;
}
@Override public void push(JObjCRuntime rt, long addr, Boolean x){ push(rt, addr, (boolean) x); }
@Override public Boolean pop(JObjCRuntime rt, long addr){ return popBoolean(rt, addr); }
// proxies for mixed encoding
@Override public void push(JObjCRuntime rt, long addr, byte x){ push(rt, addr, (x != 0)); }
@Override public byte popByte(JObjCRuntime rt, long addr){ return ((byte)(popBoolean(rt, addr) ? 1 : 0)); }
@Override public void push(JObjCRuntime rt, long addr, char x){ push(rt, addr, (x != 0)); }
@Override public char popChar(JObjCRuntime rt, long addr){ return ((char)(popBoolean(rt, addr) ? 1 : 0)); }
@Override public void push(JObjCRuntime rt, long addr, short x){ push(rt, addr, (x != 0)); }
@Override public short popShort(JObjCRuntime rt, long addr){ return ((short)(popBoolean(rt, addr) ? 1 : 0)); }
@Override public void push(JObjCRuntime rt, long addr, int x){ push(rt, addr, (x != 0)); }
@Override public int popInt(JObjCRuntime rt, long addr){ return ((int)(popBoolean(rt, addr) ? 1 : 0)); }
@Override public void push(JObjCRuntime rt, long addr, long x){ push(rt, addr, (x != 0)); }
@Override public long popLong(JObjCRuntime rt, long addr){ return ((long)(popBoolean(rt, addr) ? 1 : 0)); }
@Override public void push(JObjCRuntime rt, long addr, float x){ push(rt, addr, (x != 0)); }
@Override public float popFloat(JObjCRuntime rt, long addr){ return ((float)(popBoolean(rt, addr) ? 1 : 0)); }
@Override public void push(JObjCRuntime rt, long addr, double x){ push(rt, addr, (x != 0)); }
@Override public double popDouble(JObjCRuntime rt, long addr){ return ((double)(popBoolean(rt, addr) ? 1 : 0)); }
}
// native schar -> java byte
public static final class SCharCoder extends PrimitiveCoder<Byte>{
public static final SCharCoder INST = new SCharCoder();
public SCharCoder(){ super(FFI_SINT8, "c", Byte.class, byte.class); }
// compile time
@Override public void push(JObjCRuntime rt, long addr, byte x){
rt.unsafe.putByte(addr, x);
}
@Override public byte popByte(JObjCRuntime rt, long addr){
return rt.unsafe.getByte(addr);
}
// for runtime coding
@Override public int sizeof(Width w){
return 1;
}
@Override public void push(JObjCRuntime rt, long addr, Byte x){ push(rt, addr, (byte) x); }
@Override public Byte pop(JObjCRuntime rt, long addr){ return popByte(rt, addr); }
// proxies for mixed encoding
@Override public void push(JObjCRuntime rt, long addr, boolean x){ push(rt, addr, ((byte)(x ? 1 : 0))); }
@Override public boolean popBoolean(JObjCRuntime rt, long addr){ return (popByte(rt, addr) != 0); }
@Override public void push(JObjCRuntime rt, long addr, char x){ push(rt, addr, ((byte)x)); }
@Override public char popChar(JObjCRuntime rt, long addr){ return ((char)popByte(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, short x){ push(rt, addr, ((byte)x)); }
@Override public short popShort(JObjCRuntime rt, long addr){ return ((short)popByte(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, int x){ push(rt, addr, ((byte)x)); }
@Override public int popInt(JObjCRuntime rt, long addr){ return ((int)popByte(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, long x){ push(rt, addr, ((byte)x)); }
@Override public long popLong(JObjCRuntime rt, long addr){ return ((long)popByte(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, float x){ push(rt, addr, ((byte)x)); }
@Override public float popFloat(JObjCRuntime rt, long addr){ return ((float)popByte(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, double x){ push(rt, addr, ((byte)x)); }
@Override public double popDouble(JObjCRuntime rt, long addr){ return ((double)popByte(rt, addr)); }
}
// native uchar -> java byte
public static final class UCharCoder extends PrimitiveCoder<Byte>{
public static final UCharCoder INST = new UCharCoder();
public UCharCoder(){ super(FFI_UINT8, "C", Byte.class, byte.class); }
// compile time
@Override public void push(JObjCRuntime rt, long addr, byte x){
rt.unsafe.putByte(addr, x);
}
@Override public byte popByte(JObjCRuntime rt, long addr){
return rt.unsafe.getByte(addr);
}
// for runtime coding
@Override public int sizeof(Width w){
return 1;
}
@Override public void push(JObjCRuntime rt, long addr, Byte x){ push(rt, addr, (byte) x); }
@Override public Byte pop(JObjCRuntime rt, long addr){ return popByte(rt, addr); }
// proxies for mixed encoding
@Override public void push(JObjCRuntime rt, long addr, boolean x){ push(rt, addr, ((byte)(x ? 1 : 0))); }
@Override public boolean popBoolean(JObjCRuntime rt, long addr){ return (popByte(rt, addr) != 0); }
@Override public void push(JObjCRuntime rt, long addr, char x){ push(rt, addr, ((byte)x)); }
@Override public char popChar(JObjCRuntime rt, long addr){ return ((char)popByte(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, short x){ push(rt, addr, ((byte)x)); }
@Override public short popShort(JObjCRuntime rt, long addr){ return ((short)popByte(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, int x){ push(rt, addr, ((byte)x)); }
@Override public int popInt(JObjCRuntime rt, long addr){ return ((int)popByte(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, long x){ push(rt, addr, ((byte)x)); }
@Override public long popLong(JObjCRuntime rt, long addr){ return ((long)popByte(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, float x){ push(rt, addr, ((byte)x)); }
@Override public float popFloat(JObjCRuntime rt, long addr){ return ((float)popByte(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, double x){ push(rt, addr, ((byte)x)); }
@Override public double popDouble(JObjCRuntime rt, long addr){ return ((double)popByte(rt, addr)); }
}
// native sshort -> java short
public static final class SShortCoder extends PrimitiveCoder<Short>{
public static final SShortCoder INST = new SShortCoder();
public SShortCoder(){ super(FFI_SINT16, "s", Short.class, short.class); }
// compile time
@Override public void push(JObjCRuntime rt, long addr, short x){
rt.unsafe.putShort(addr, (short) x);
}
@Override public short popShort(JObjCRuntime rt, long addr){
return rt.unsafe.getShort(addr);
}
// for runtime coding
@Override public int sizeof(Width w){
return 2;
}
@Override public void push(JObjCRuntime rt, long addr, Short x){ push(rt, addr, (short) x); }
@Override public Short pop(JObjCRuntime rt, long addr){ return popShort(rt, addr); }
// proxies for mixed encoding
@Override public void push(JObjCRuntime rt, long addr, boolean x){ push(rt, addr, ((short)(x ? 1 : 0))); }
@Override public boolean popBoolean(JObjCRuntime rt, long addr){ return (popShort(rt, addr) != 0); }
@Override public void push(JObjCRuntime rt, long addr, byte x){ push(rt, addr, ((short)x)); }
@Override public byte popByte(JObjCRuntime rt, long addr){ return ((byte)popShort(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, char x){ push(rt, addr, ((short)x)); }
@Override public char popChar(JObjCRuntime rt, long addr){ return ((char)popShort(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, int x){ push(rt, addr, ((short)x)); }
@Override public int popInt(JObjCRuntime rt, long addr){ return ((int)popShort(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, long x){ push(rt, addr, ((short)x)); }
@Override public long popLong(JObjCRuntime rt, long addr){ return ((long)popShort(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, float x){ push(rt, addr, ((short)x)); }
@Override public float popFloat(JObjCRuntime rt, long addr){ return ((float)popShort(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, double x){ push(rt, addr, ((short)x)); }
@Override public double popDouble(JObjCRuntime rt, long addr){ return ((double)popShort(rt, addr)); }
}
// native ushort -> java short
public static final class UShortCoder extends PrimitiveCoder<Short>{
public static final UShortCoder INST = new UShortCoder();
public UShortCoder(){ super(FFI_UINT16, "S", Short.class, short.class); }
// compile time
@Override public void push(JObjCRuntime rt, long addr, short x){
rt.unsafe.putShort(addr, (short) x);
}
@Override public short popShort(JObjCRuntime rt, long addr){
return rt.unsafe.getShort(addr);
}
// for runtime coding
@Override public int sizeof(Width w){
return 2;
}
@Override public void push(JObjCRuntime rt, long addr, Short x){ push(rt, addr, (short) x); }
@Override public Short pop(JObjCRuntime rt, long addr){ return popShort(rt, addr); }
// proxies for mixed encoding
@Override public void push(JObjCRuntime rt, long addr, boolean x){ push(rt, addr, ((short)(x ? 1 : 0))); }
@Override public boolean popBoolean(JObjCRuntime rt, long addr){ return (popShort(rt, addr) != 0); }
@Override public void push(JObjCRuntime rt, long addr, byte x){ push(rt, addr, ((short)x)); }
@Override public byte popByte(JObjCRuntime rt, long addr){ return ((byte)popShort(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, char x){ push(rt, addr, ((short)x)); }
@Override public char popChar(JObjCRuntime rt, long addr){ return ((char)popShort(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, int x){ push(rt, addr, ((short)x)); }
@Override public int popInt(JObjCRuntime rt, long addr){ return ((int)popShort(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, long x){ push(rt, addr, ((short)x)); }
@Override public long popLong(JObjCRuntime rt, long addr){ return ((long)popShort(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, float x){ push(rt, addr, ((short)x)); }
@Override public float popFloat(JObjCRuntime rt, long addr){ return ((float)popShort(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, double x){ push(rt, addr, ((short)x)); }
@Override public double popDouble(JObjCRuntime rt, long addr){ return ((double)popShort(rt, addr)); }
}
// native sint -> java int
public static final class SIntCoder extends PrimitiveCoder<Integer>{
public static final SIntCoder INST = new SIntCoder();
public SIntCoder(){ super(FFI_SINT32, "i", Integer.class, int.class); }
// compile time
@Override public void push(JObjCRuntime rt, long addr, int x){
rt.unsafe.putInt(addr, (int) x);
}
@Override public int popInt(JObjCRuntime rt, long addr){
return rt.unsafe.getInt(addr);
}
// for runtime coding
@Override public int sizeof(Width w){
return 4;
}
@Override public void push(JObjCRuntime rt, long addr, Integer x){ push(rt, addr, (int) x); }
@Override public Integer pop(JObjCRuntime rt, long addr){ return popInt(rt, addr); }
// proxies for mixed encoding
@Override public void push(JObjCRuntime rt, long addr, boolean x){ push(rt, addr, ((int)(x ? 1 : 0))); }
@Override public boolean popBoolean(JObjCRuntime rt, long addr){ return (popInt(rt, addr) != 0); }
@Override public void push(JObjCRuntime rt, long addr, byte x){ push(rt, addr, ((int)x)); }
@Override public byte popByte(JObjCRuntime rt, long addr){ return ((byte)popInt(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, char x){ push(rt, addr, ((int)x)); }
@Override public char popChar(JObjCRuntime rt, long addr){ return ((char)popInt(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, short x){ push(rt, addr, ((int)x)); }
@Override public short popShort(JObjCRuntime rt, long addr){ return ((short)popInt(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, long x){ push(rt, addr, ((int)x)); }
@Override public long popLong(JObjCRuntime rt, long addr){ return ((long)popInt(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, float x){ push(rt, addr, ((int)x)); }
@Override public float popFloat(JObjCRuntime rt, long addr){ return ((float)popInt(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, double x){ push(rt, addr, ((int)x)); }
@Override public double popDouble(JObjCRuntime rt, long addr){ return ((double)popInt(rt, addr)); }
}
// native uint -> java int
public static final class UIntCoder extends PrimitiveCoder<Integer>{
public static final UIntCoder INST = new UIntCoder();
public UIntCoder(){ super(FFI_UINT32, "I", Integer.class, int.class); }
// compile time
@Override public void push(JObjCRuntime rt, long addr, int x){
rt.unsafe.putInt(addr, (int) x);
}
@Override public int popInt(JObjCRuntime rt, long addr){
return rt.unsafe.getInt(addr);
}
// for runtime coding
@Override public int sizeof(Width w){
return 4;
}
@Override public void push(JObjCRuntime rt, long addr, Integer x){ push(rt, addr, (int) x); }
@Override public Integer pop(JObjCRuntime rt, long addr){ return popInt(rt, addr); }
// proxies for mixed encoding
@Override public void push(JObjCRuntime rt, long addr, boolean x){ push(rt, addr, ((int)(x ? 1 : 0))); }
@Override public boolean popBoolean(JObjCRuntime rt, long addr){ return (popInt(rt, addr) != 0); }
@Override public void push(JObjCRuntime rt, long addr, byte x){ push(rt, addr, ((int)x)); }
@Override public byte popByte(JObjCRuntime rt, long addr){ return ((byte)popInt(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, char x){ push(rt, addr, ((int)x)); }
@Override public char popChar(JObjCRuntime rt, long addr){ return ((char)popInt(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, short x){ push(rt, addr, ((int)x)); }
@Override public short popShort(JObjCRuntime rt, long addr){ return ((short)popInt(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, long x){ push(rt, addr, ((int)x)); }
@Override public long popLong(JObjCRuntime rt, long addr){ return ((long)popInt(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, float x){ push(rt, addr, ((int)x)); }
@Override public float popFloat(JObjCRuntime rt, long addr){ return ((float)popInt(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, double x){ push(rt, addr, ((int)x)); }
@Override public double popDouble(JObjCRuntime rt, long addr){ return ((double)popInt(rt, addr)); }
}
// native slong -> java long
public static final class SLongCoder extends PrimitiveCoder<Long>{
public static final SLongCoder INST = new SLongCoder();
public SLongCoder(){ super((JObjCRuntime.IS64 ? (FFI_SINT64) : (FFI_SINT32)), "l", Long.class, long.class); }
// compile time
@Override public void push(JObjCRuntime rt, long addr, long x){
if(JObjCRuntime.IS64){ rt.unsafe.putLong(addr, (long) x); }else{ rt.unsafe.putInt(addr, (int) x); }
}
@Override public long popLong(JObjCRuntime rt, long addr){
return (JObjCRuntime.IS64 ? (rt.unsafe.getLong(addr)) : (rt.unsafe.getInt(addr)));
}
// for runtime coding
@Override public int sizeof(Width w){
switch(w){
case W32: return 4;
case W64: return 8;
default: return -1;
}
}
@Override public void push(JObjCRuntime rt, long addr, Long x){ push(rt, addr, (long) x); }
@Override public Long pop(JObjCRuntime rt, long addr){ return popLong(rt, addr); }
// proxies for mixed encoding
@Override public void push(JObjCRuntime rt, long addr, boolean x){ push(rt, addr, ((long)(x ? 1 : 0))); }
@Override public boolean popBoolean(JObjCRuntime rt, long addr){ return (popLong(rt, addr) != 0); }
@Override public void push(JObjCRuntime rt, long addr, byte x){ push(rt, addr, ((long)x)); }
@Override public byte popByte(JObjCRuntime rt, long addr){ return ((byte)popLong(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, char x){ push(rt, addr, ((long)x)); }
@Override public char popChar(JObjCRuntime rt, long addr){ return ((char)popLong(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, short x){ push(rt, addr, ((long)x)); }
@Override public short popShort(JObjCRuntime rt, long addr){ return ((short)popLong(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, int x){ push(rt, addr, ((long)x)); }
@Override public int popInt(JObjCRuntime rt, long addr){ return ((int)popLong(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, float x){ push(rt, addr, ((long)x)); }
@Override public float popFloat(JObjCRuntime rt, long addr){ return ((float)popLong(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, double x){ push(rt, addr, ((long)x)); }
@Override public double popDouble(JObjCRuntime rt, long addr){ return ((double)popLong(rt, addr)); }
}
// native ulong -> java long
public static final class ULongCoder extends PrimitiveCoder<Long>{
public static final ULongCoder INST = new ULongCoder();
public ULongCoder(){ super((JObjCRuntime.IS64 ? (FFI_UINT64) : (FFI_UINT32)), "L", Long.class, long.class); }
// compile time
@Override public void push(JObjCRuntime rt, long addr, long x){
if(JObjCRuntime.IS64){ rt.unsafe.putLong(addr, (long) x); }else{ rt.unsafe.putInt(addr, (int) x); }
}
@Override public long popLong(JObjCRuntime rt, long addr){
return (JObjCRuntime.IS64 ? (rt.unsafe.getLong(addr)) : (rt.unsafe.getInt(addr)));
}
// for runtime coding
@Override public int sizeof(Width w){
switch(w){
case W32: return 4;
case W64: return 8;
default: return -1;
}
}
@Override public void push(JObjCRuntime rt, long addr, Long x){ push(rt, addr, (long) x); }
@Override public Long pop(JObjCRuntime rt, long addr){ return popLong(rt, addr); }
// proxies for mixed encoding
@Override public void push(JObjCRuntime rt, long addr, boolean x){ push(rt, addr, ((long)(x ? 1 : 0))); }
@Override public boolean popBoolean(JObjCRuntime rt, long addr){ return (popLong(rt, addr) != 0); }
@Override public void push(JObjCRuntime rt, long addr, byte x){ push(rt, addr, ((long)x)); }
@Override public byte popByte(JObjCRuntime rt, long addr){ return ((byte)popLong(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, char x){ push(rt, addr, ((long)x)); }
@Override public char popChar(JObjCRuntime rt, long addr){ return ((char)popLong(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, short x){ push(rt, addr, ((long)x)); }
@Override public short popShort(JObjCRuntime rt, long addr){ return ((short)popLong(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, int x){ push(rt, addr, ((long)x)); }
@Override public int popInt(JObjCRuntime rt, long addr){ return ((int)popLong(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, float x){ push(rt, addr, ((long)x)); }
@Override public float popFloat(JObjCRuntime rt, long addr){ return ((float)popLong(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, double x){ push(rt, addr, ((long)x)); }
@Override public double popDouble(JObjCRuntime rt, long addr){ return ((double)popLong(rt, addr)); }
}
// native slonglong -> java long
public static final class SLongLongCoder extends PrimitiveCoder<Long>{
public static final SLongLongCoder INST = new SLongLongCoder();
public SLongLongCoder(){ super(FFI_SINT64, "q", Long.class, long.class); }
// compile time
@Override public void push(JObjCRuntime rt, long addr, long x){
rt.unsafe.putLong(addr, (long) x);
}
@Override public long popLong(JObjCRuntime rt, long addr){
return rt.unsafe.getLong(addr);
}
// for runtime coding
@Override public int sizeof(Width w){
return 8;
}
@Override public void push(JObjCRuntime rt, long addr, Long x){ push(rt, addr, (long) x); }
@Override public Long pop(JObjCRuntime rt, long addr){ return popLong(rt, addr); }
// proxies for mixed encoding
@Override public void push(JObjCRuntime rt, long addr, boolean x){ push(rt, addr, ((long)(x ? 1 : 0))); }
@Override public boolean popBoolean(JObjCRuntime rt, long addr){ return (popLong(rt, addr) != 0); }
@Override public void push(JObjCRuntime rt, long addr, byte x){ push(rt, addr, ((long)x)); }
@Override public byte popByte(JObjCRuntime rt, long addr){ return ((byte)popLong(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, char x){ push(rt, addr, ((long)x)); }
@Override public char popChar(JObjCRuntime rt, long addr){ return ((char)popLong(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, short x){ push(rt, addr, ((long)x)); }
@Override public short popShort(JObjCRuntime rt, long addr){ return ((short)popLong(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, int x){ push(rt, addr, ((long)x)); }
@Override public int popInt(JObjCRuntime rt, long addr){ return ((int)popLong(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, float x){ push(rt, addr, ((long)x)); }
@Override public float popFloat(JObjCRuntime rt, long addr){ return ((float)popLong(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, double x){ push(rt, addr, ((long)x)); }
@Override public double popDouble(JObjCRuntime rt, long addr){ return ((double)popLong(rt, addr)); }
}
// native ulonglong -> java long
public static final class ULongLongCoder extends PrimitiveCoder<Long>{
public static final ULongLongCoder INST = new ULongLongCoder();
public ULongLongCoder(){ super(FFI_UINT64, "Q", Long.class, long.class); }
// compile time
@Override public void push(JObjCRuntime rt, long addr, long x){
rt.unsafe.putLong(addr, (long) x);
}
@Override public long popLong(JObjCRuntime rt, long addr){
return rt.unsafe.getLong(addr);
}
// for runtime coding
@Override public int sizeof(Width w){
return 8;
}
@Override public void push(JObjCRuntime rt, long addr, Long x){ push(rt, addr, (long) x); }
@Override public Long pop(JObjCRuntime rt, long addr){ return popLong(rt, addr); }
// proxies for mixed encoding
@Override public void push(JObjCRuntime rt, long addr, boolean x){ push(rt, addr, ((long)(x ? 1 : 0))); }
@Override public boolean popBoolean(JObjCRuntime rt, long addr){ return (popLong(rt, addr) != 0); }
@Override public void push(JObjCRuntime rt, long addr, byte x){ push(rt, addr, ((long)x)); }
@Override public byte popByte(JObjCRuntime rt, long addr){ return ((byte)popLong(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, char x){ push(rt, addr, ((long)x)); }
@Override public char popChar(JObjCRuntime rt, long addr){ return ((char)popLong(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, short x){ push(rt, addr, ((long)x)); }
@Override public short popShort(JObjCRuntime rt, long addr){ return ((short)popLong(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, int x){ push(rt, addr, ((long)x)); }
@Override public int popInt(JObjCRuntime rt, long addr){ return ((int)popLong(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, float x){ push(rt, addr, ((long)x)); }
@Override public float popFloat(JObjCRuntime rt, long addr){ return ((float)popLong(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, double x){ push(rt, addr, ((long)x)); }
@Override public double popDouble(JObjCRuntime rt, long addr){ return ((double)popLong(rt, addr)); }
}
// native float -> java float
public static final class FloatCoder extends PrimitiveCoder<Float>{
public static final FloatCoder INST = new FloatCoder();
public FloatCoder(){ super(FFI_FLOAT, "f", Float.class, float.class); }
// compile time
@Override public void push(JObjCRuntime rt, long addr, float x){
rt.unsafe.putFloat(addr, (float) x);
}
@Override public float popFloat(JObjCRuntime rt, long addr){
return rt.unsafe.getFloat(addr);
}
// for runtime coding
@Override public int sizeof(Width w){
return 4;
}
@Override public void push(JObjCRuntime rt, long addr, Float x){ push(rt, addr, (float) x); }
@Override public Float pop(JObjCRuntime rt, long addr){ return popFloat(rt, addr); }
// proxies for mixed encoding
@Override public void push(JObjCRuntime rt, long addr, boolean x){ push(rt, addr, ((float)(x ? 1 : 0))); }
@Override public boolean popBoolean(JObjCRuntime rt, long addr){ return (popFloat(rt, addr) != 0); }
@Override public void push(JObjCRuntime rt, long addr, byte x){ push(rt, addr, ((float)x)); }
@Override public byte popByte(JObjCRuntime rt, long addr){ return ((byte)popFloat(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, char x){ push(rt, addr, ((float)x)); }
@Override public char popChar(JObjCRuntime rt, long addr){ return ((char)popFloat(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, short x){ push(rt, addr, ((float)x)); }
@Override public short popShort(JObjCRuntime rt, long addr){ return ((short)popFloat(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, int x){ push(rt, addr, ((float)x)); }
@Override public int popInt(JObjCRuntime rt, long addr){ return ((int)popFloat(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, long x){ push(rt, addr, ((float)x)); }
@Override public long popLong(JObjCRuntime rt, long addr){ return ((long)popFloat(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, double x){ push(rt, addr, ((float)x)); }
@Override public double popDouble(JObjCRuntime rt, long addr){ return ((double)popFloat(rt, addr)); }
}
// native double -> java double
public static final class DoubleCoder extends PrimitiveCoder<Double>{
public static final DoubleCoder INST = new DoubleCoder();
public DoubleCoder(){ super(FFI_DOUBLE, "d", Double.class, double.class); }
// compile time
@Override public void push(JObjCRuntime rt, long addr, double x){
rt.unsafe.putDouble(addr, (double) x);
}
@Override public double popDouble(JObjCRuntime rt, long addr){
return rt.unsafe.getDouble(addr);
}
// for runtime coding
@Override public int sizeof(Width w){
return 8;
}
@Override public void push(JObjCRuntime rt, long addr, Double x){ push(rt, addr, (double) x); }
@Override public Double pop(JObjCRuntime rt, long addr){ return popDouble(rt, addr); }
// proxies for mixed encoding
@Override public void push(JObjCRuntime rt, long addr, boolean x){ push(rt, addr, ((double)(x ? 1 : 0))); }
@Override public boolean popBoolean(JObjCRuntime rt, long addr){ return (popDouble(rt, addr) != 0); }
@Override public void push(JObjCRuntime rt, long addr, byte x){ push(rt, addr, ((double)x)); }
@Override public byte popByte(JObjCRuntime rt, long addr){ return ((byte)popDouble(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, char x){ push(rt, addr, ((double)x)); }
@Override public char popChar(JObjCRuntime rt, long addr){ return ((char)popDouble(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, short x){ push(rt, addr, ((double)x)); }
@Override public short popShort(JObjCRuntime rt, long addr){ return ((short)popDouble(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, int x){ push(rt, addr, ((double)x)); }
@Override public int popInt(JObjCRuntime rt, long addr){ return ((int)popDouble(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, long x){ push(rt, addr, ((double)x)); }
@Override public long popLong(JObjCRuntime rt, long addr){ return ((long)popDouble(rt, addr)); }
@Override public void push(JObjCRuntime rt, long addr, float x){ push(rt, addr, ((double)x)); }
@Override public float popFloat(JObjCRuntime rt, long addr){ return ((float)popDouble(rt, addr)); }
}
}

View File

@ -1,62 +0,0 @@
/*
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.jobjc;
public class SEL {
static native long getSelectorPtr(String selectorName);
static native String getSelectorName(long ptr);
final long selPtr;
SEL(long ptr) {
this.selPtr = ptr;
}
public SEL(final String name) {
this(getSelectorPtr(name));
}
@Override public String toString(){
return ((int)selPtr) + " / " + selPtr + " : " + getSelectorName(selPtr);
}
/**
* Converts something like "performSelectorOnMainThread_withObject_wait"
* to "performSelectorOnMainThread:withObject:wait:"
*/
public static String selectorName(String jMethodName, boolean hasArgs){
String b = jMethodName.replaceAll("_", ":");
return hasArgs ? b + ":" : b;
}
public static String jMethodName(String selectorName){
return selectorName.replaceAll(":", "_").replaceAll("_$", "");
}
public static boolean validName(String selectorName){
return selectorName.matches("^[a-zA-Z_][a-zA-Z0-9_:]*$");
}
}

View File

@ -1,56 +0,0 @@
/*
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.jobjc;
/**
* A struct is malloced on the C heap and accessed in Java through a ByteBuffer.
*/
public abstract class Struct{
protected final NativeBuffer raw;
private final JObjCRuntime runtime;
protected final JObjCRuntime getRuntime(){ return runtime; }
/**
* Create a brand new struct from nothing.
*/
protected Struct(final JObjCRuntime runtime, final int SIZEOF){
this(runtime, new NativeBuffer(SIZEOF), SIZEOF);
}
/**
* Create a struct by taking ownership of an existing buffer.
* Used for struct fields of type struct. For example, the origin and size fields
* in NSRect would be initialized with this constructor.
*/
protected Struct(final JObjCRuntime runtime, final NativeBuffer buffer, final int SIZEOF){
if(runtime == null) throw new NullPointerException("runtime");
this.runtime = runtime;
this.raw = buffer;
this.raw.limit(SIZEOF);
}
abstract public Coder getCoder();
}

View File

@ -1,167 +0,0 @@
/*
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.jobjc;
import java.io.StringWriter;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;
import com.apple.jobjc.Coder.PrimitivePointerCoder;
import com.apple.jobjc.Coder.VoidCoder;
import com.apple.jobjc.Invoke.MsgSend;
final class Subclassing {
static native long allocateClassPair(long superClass, String name);
static native boolean addIVarForJObj(long clazz);
static native boolean patchAlloc(long classPtr);
static native boolean addMethod(long cls, String name, Method jMethod, CIF cif, long cifPtr, String objCEncodedType);
static native void registerClassPair(long clazz);
static native <T extends ID> T getJObjectFromIVar(long objPtr);
static native void initJObjectToIVar(long objPtr, ID object);
final Set<Long> registeredUserSubclasses = new HashSet<Long>();
final JObjCRuntime runtime;
Subclassing(JObjCRuntime runtime){
this.runtime = runtime;
}
boolean registerUserClass(final Class<? extends ID> clazz, final Class<? extends NSClass> clazzClazz) {
final String nativeClassName = clazz.getSimpleName();
// Is it already registered?
if(0 != NSClass.getNativeClassByName(nativeClassName))
return false;
if(clazz.isAnonymousClass())
throw new RuntimeException("JObjC cannot register anonymous classes.");
// Verify superclass
long superClass = NSClass.getNativeClassByName(clazz.getSuperclass().getSimpleName());
if(0 == superClass)
throw new RuntimeException(clazz.getSuperclass() + ", the superclass of " + clazz + ", must be a registered class.");
runtime.registerPackage(clazz.getPackage().getName());
// Create class
long classPtr = Subclassing.allocateClassPair(superClass, nativeClassName);
if(classPtr == 0) throw new RuntimeException("objc_allocateClassPair returned 0.");
// Add ivar to hold jobject
boolean addedI = Subclassing.addIVarForJObj(classPtr);
if(!addedI) throw new RuntimeException("class_addIvar returned false.");
// Verify constructor
try {
clazz.getConstructor(ID.CTOR_ARGS);
} catch (Exception e) {
throw new RuntimeException("Could not access required constructor: " + ID.CTOR_ARGS, e);
}
// Patch alloc to create corresponding jobject on invoke
patchAlloc(classPtr);
// Add methods
Set<String> takenSelNames = new HashSet<String>();
for(Method method : clazz.getDeclaredMethods()){
// No overloading
String selName = SEL.selectorName(method.getName(), method.getParameterTypes().length > 0);
if(takenSelNames.contains(selName))
throw new RuntimeException("Obj-C does not allow method overloading. The Objective-C selector '"
+ selName + "' appears more than once in class " + clazz.getCanonicalName() + " / " + nativeClassName + ".");
method.setAccessible(true);
// Divine CIF
Coder returnCoder = Coder.getCoderAtRuntimeForType(method.getReturnType());
Class[] paramTypes = method.getParameterTypes();
Coder[] argCoders = new Coder[paramTypes.length];
for(int i = 0; i < paramTypes.length; i++)
argCoders[i] = Coder.getCoderAtRuntimeForType(paramTypes[i]);
CIF cif = new MsgSend(runtime, selName, returnCoder, argCoders).funCall.cif;
// .. and objc encoding
StringWriter encType = new StringWriter();
encType.append(returnCoder.getObjCEncoding());
encType.append("@:");
for(int i = 0; i < argCoders.length; i++)
encType.append(argCoders[i].getObjCEncoding());
// Add it!
boolean addedM = Subclassing.addMethod(classPtr, selName, method, cif, cif.cif.bufferPtr, encType.toString());
if(!addedM) throw new RuntimeException("Failed to add method.");
takenSelNames.add(selName);
}
// Seal it
Subclassing.registerClassPair(classPtr);
registeredUserSubclasses.add(classPtr);
return true;
}
boolean isUserClass(long clsPtr) {
return registeredUserSubclasses.contains(clsPtr);
}
// Called from JNI
private static void initJObject(final long objPtr){
// System.err.println("initJObject " + objPtr + " / " + Long.toHexString(objPtr));
ID newObj = ID.createNewObjCObjectFor(JObjCRuntime.inst(), objPtr, NSClass.getClass(objPtr));
// System.err.println("... " + newObj);
initJObjectToIVar(objPtr, newObj);
}
private static void invokeFromJNI(ID obj, Method method, CIF cif, long result, long args){
assert obj != null;
assert obj.getClass().equals(method.getDeclaringClass()) :
obj.getClass().toString() + " != " + method.getDeclaringClass().toString();
final int argCount = method.getParameterTypes().length;
// The first two args & coders are for objc id and sel. Skip them.
final Object[] argObjects = new Object[argCount];
for(int i = 0; i < argCount; i++){
final long argAddrAddr = args + ((i+2) * JObjCRuntime.PTR_LEN);
final long argAddr = PrimitivePointerCoder.INST.popPtr(obj.runtime, argAddrAddr);
argObjects[i] = cif.argCoders[i + 2].pop(obj.runtime, argAddr);
}
Object retVal;
try {
retVal = method.invoke(obj, argObjects);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
if(!(cif.returnCoder instanceof VoidCoder))
cif.returnCoder.push(obj.runtime, result, retVal);
}
}

View File

@ -1,50 +0,0 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include "com_apple_jobjc_CIF.h"
#define MACOSX
#include <ffi/ffi.h>
#include <JavaNativeFoundation/JavaNativeFoundation.h>
#include "NativeBuffer.h"
JNIEXPORT jint JNICALL Java_com_apple_jobjc_CIF_getSizeofCIF
(JNIEnv *env, jclass clazz)
{
return (jint) sizeof(ffi_cif);
}
JNIEXPORT jboolean JNICALL Java_com_apple_jobjc_CIF_prepCIF
(JNIEnv *env, jclass clazz, jlong jCIFPtr, jint jNargs, jlong jRetTypePtr, jlong jArgsPtr)
{
ffi_cif *cif = jlong_to_ptr(jCIFPtr);
unsigned int nargs = jNargs;
ffi_type *rtype = jlong_to_ptr(jRetTypePtr);
ffi_type **atypes = jlong_to_ptr(jArgsPtr);
// NSLog(@"rtype->(size: %d, alignment: %d, type: %d)", rtype->size, rtype->alignment, rtype->type);
return (jboolean) (FFI_OK == ffi_prep_cif(cif, FFI_DEFAULT_ABI, nargs, rtype, atypes));
}

View File

@ -1,58 +0,0 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include "com_apple_jobjc_Coder.h"
#include <JavaNativeFoundation/JavaNativeFoundation.h>
#define MACOSX
#include <ffi/ffi.h>
#include <AppKit/AppKit.h>
/*
* Class: com_apple_jobjc_Coder
* Method: getNativeFFITypeCodeForCode
* Signature: (I)J
*/
JNIEXPORT jlong JNICALL Java_com_apple_jobjc_Coder_getNativeFFITypePtrForCode
(JNIEnv *env, jclass clazz, jint code)
{
switch ((long)code) {
case com_apple_jobjc_Coder_FFI_VOID: return ptr_to_jlong(&ffi_type_void);
case com_apple_jobjc_Coder_FFI_PTR: return ptr_to_jlong(&ffi_type_pointer);
case com_apple_jobjc_Coder_FFI_SINT8: return ptr_to_jlong(&ffi_type_sint8);
case com_apple_jobjc_Coder_FFI_UINT8: return ptr_to_jlong(&ffi_type_uint8);
case com_apple_jobjc_Coder_FFI_SINT16: return ptr_to_jlong(&ffi_type_sint16);
case com_apple_jobjc_Coder_FFI_UINT16: return ptr_to_jlong(&ffi_type_uint16);
case com_apple_jobjc_Coder_FFI_SINT32: return ptr_to_jlong(&ffi_type_sint32);
case com_apple_jobjc_Coder_FFI_UINT32: return ptr_to_jlong(&ffi_type_uint32);
case com_apple_jobjc_Coder_FFI_SINT64: return ptr_to_jlong(&ffi_type_sint64);
case com_apple_jobjc_Coder_FFI_UINT64: return ptr_to_jlong(&ffi_type_uint64);
case com_apple_jobjc_Coder_FFI_FLOAT: return ptr_to_jlong(&ffi_type_float);
case com_apple_jobjc_Coder_FFI_DOUBLE: return ptr_to_jlong(&ffi_type_double);
case com_apple_jobjc_Coder_FFI_LONGDOUBLE: return ptr_to_jlong(&ffi_type_longdouble);
}
return ptr_to_jlong(NULL);
}

View File

@ -1,43 +0,0 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include <JavaNativeFoundation/JavaNativeFoundation.h>
#include <ffi/ffi.h>
#include "com_apple_jobjc_FFIType.h"
JNIEXPORT void JNICALL Java_com_apple_jobjc_FFIType_makeFFIType
(JNIEnv *env, jclass clazz, jlong ffi_type_jlong, jlong ffi_type_elements_jlong)
{
ffi_type *type = jlong_to_ptr(ffi_type_jlong);
type->elements = jlong_to_ptr(ffi_type_elements_jlong);
type->type = FFI_TYPE_STRUCT;
type->size = type->alignment = 0;
}
JNIEXPORT jint JNICALL Java_com_apple_jobjc_FFIType_getFFITypeSizeof
(JNIEnv *env, jclass clazz)
{
return (jint) sizeof(ffi_type);
}

View File

@ -1,51 +0,0 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include "com_apple_jobjc_Function.h"
#define MACOSX
#include <dlfcn.h>
#include <JavaNativeFoundation/JavaNativeFoundation.h>
JNIEXPORT jlong JNICALL Java_com_apple_jobjc_Function_getFxnPtrForFunctionName
(JNIEnv *env, jclass clazz, jstring fxnName)
{
const char *functionName = (*env)->GetStringUTFChars(env, fxnName, NULL);
void *fxnPtr = dlsym(RTLD_SELF, functionName);
(*env)->ReleaseStringUTFChars(env, fxnName, functionName);
return ptr_to_jlong(fxnPtr);
}
JNIEXPORT jlong JNICALL Java_com_apple_jobjc_Function_getFxnPtrForFunctionNameAndLib
(JNIEnv *env, jclass clazz, jlong frameworkPtr, jstring fxnName)
{
void *frameworkHandle = jlong_to_ptr(frameworkPtr);
const char *functionName = (*env)->GetStringUTFChars(env, fxnName, NULL);
void *fxnPtr = dlsym(frameworkHandle, functionName);
(*env)->ReleaseStringUTFChars(env, fxnName, functionName);
return ptr_to_jlong(fxnPtr);
}

View File

@ -1,40 +0,0 @@
/*
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include "com_apple_jobjc_Invoke_FunCall.h"
#include <ffi/ffi.h>
#include <objc/message.h>
#include <JavaNativeFoundation/JavaNativeFoundation.h>
JNIEXPORT void JNICALL Java_com_apple_jobjc_Invoke_00024FunCall_invoke
(JNIEnv *env, jclass clazz, jlong cifPtr, jlong fxnPtr, jlong retValPtr, jlong argsPtr)
{
ffi_cif *cif = jlong_to_ptr(cifPtr);
void *fxn = jlong_to_ptr(fxnPtr);
void *retVal = jlong_to_ptr(retValPtr);
void **args = jlong_to_ptr(argsPtr);
ffi_call(cif, fxn, retVal, args);
}

View File

@ -1,69 +0,0 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include "com_apple_jobjc_MacOSXFramework.h"
#include <dlfcn.h>
#include <JavaNativeFoundation/JavaNativeFoundation.h>
/*
* Class: com_apple_jobjc_MacOSXFramework
* Method: retainFramework
* Signature: (Ljava/lang/String;)J
*/
JNIEXPORT jlong JNICALL Java_com_apple_jobjc_MacOSXFramework_retainFramework
(JNIEnv *env, jclass clazz, jstring frameworkName)
{
if (frameworkName == NULL) return ptr_to_jlong(NULL);
const char *frameworkNameCStr = (*env)->GetStringUTFChars(env, frameworkName, JNI_FALSE);
const void *library = dlopen(frameworkNameCStr, RTLD_LOCAL);
(*env)->ReleaseStringUTFChars(env, frameworkName, frameworkNameCStr);
return ptr_to_jlong(library);
}
/*
* Class: com_apple_jobjc_MacOSXFramework
* Method: releaseFramework
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_com_apple_jobjc_MacOSXFramework_releaseFramework
(JNIEnv *env, jclass clazz, jlong frameworkPtr)
{
dlclose(jlong_to_ptr(frameworkPtr));
}
JNIEXPORT void JNICALL Java_com_apple_jobjc_MacOSXFramework_getConstant
(JNIEnv *env, jclass clazz, jlong frameworkPtr, jstring constSymbol, jlong retBuffer, jint size)
{
const char *symbol = (*env)->GetStringUTFChars(env, constSymbol, JNI_FALSE);
void *handle = frameworkPtr ? jlong_to_ptr(frameworkPtr) : RTLD_DEFAULT;
void *data = dlsym(handle, symbol);
(*env)->ReleaseStringUTFChars(env, constSymbol, symbol);
if(!data)
(*env)->ThrowNew(env, (*env)->FindClass(env, "java/lang/RuntimeException"), dlerror());
else
memcpy(jlong_to_ptr(retBuffer), data, (size_t) size);
}

View File

@ -1,78 +0,0 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include "com_apple_jobjc_NSClass.h"
#include <objc/runtime.h>
#include <JavaNativeFoundation/JavaNativeFoundation.h>
/*
* Class: com_apple_jobjc_NSClass
* Method: getNativeClassByName
* Signature: (JLjava/lang/String;)J
*/
JNIEXPORT jlong JNICALL Java_com_apple_jobjc_NSClass_getNativeClassByName
(JNIEnv *env, jclass clazz, jstring className)
{
if (className == NULL) return ptr_to_jlong(NULL);
const char *classNameCStr = (*env)->GetStringUTFChars(env, className, JNI_FALSE);
const id obj = objc_getClass(classNameCStr);
(*env)->ReleaseStringUTFChars(env, className, classNameCStr);
if (obj == nil) return ptr_to_jlong(NULL);
return ptr_to_jlong(obj);
}
/*
* Class: com_apple_jobjc_NSClass
* Method: getSuperClass
* Signature: (J)J
*/
JNIEXPORT jlong JNICALL Java_com_apple_jobjc_NSClass_getSuperClassOfClass
(JNIEnv *env, jclass clazz, jlong clazzPtr)
{
if (clazzPtr == 0L) return ptr_to_jlong(NULL);
const Class objClazz = (Class)jlong_to_ptr(clazzPtr);
return ptr_to_jlong(class_getSuperclass(objClazz));
}
/*
* Class: com_apple_jobjc_NSClass
* Method: getClassName
* Signature: (J)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_apple_jobjc_NSClass_getClassNameOfClass
(JNIEnv *env, jclass clazz, jlong clazzPtr)
{
const char *clazzName = (char *)class_getName((Class)jlong_to_ptr(clazzPtr));
return (*env)->NewStringUTF(env, clazzName);
}
JNIEXPORT jlong JNICALL Java_com_apple_jobjc_NSClass_getClass
(JNIEnv *env, jclass clazz, jlong objPtr)
{
id obj = (id)jlong_to_ptr(objPtr);
return ptr_to_jlong(object_getClass(obj));
}

View File

@ -1,40 +0,0 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* NativeBuffer.h
* Copyright 2007 Apple Inc. All rights reserved.
*
*/
#define BUFFER_AT(buffer, offset) (((UInt8 *)buffer) + offset)
#define GET_VALUE(type, buffer, offset) (*((type *)BUFFER_AT(buffer, offset)))
#define PUT_VALUE(type, buffer, offset, value) (*((type *)BUFFER_AT(buffer, offset)) = value)
#define GET_INT_AT(buffer, offset) GET_VALUE(jint, buffer, offset)
#define GET_LONG_AT(buffer, offset) GET_VALUE(jlong, buffer, offset)
#define PUT_INT_AT(buffer, offset, value) PUT_VALUE(jint, buffer, offset, value)
#define PUT_LONG_AT(buffer, offset, value) PUT_VALUE(jlong, buffer, offset, value)

View File

@ -1,37 +0,0 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include "com_apple_jobjc_NativeBuffer.h"
#define MACOSX
#include <ffi/ffi.h>
#include <JavaNativeFoundation/JavaNativeFoundation.h>
JNIEXPORT jlong JNICALL Java_com_apple_jobjc_NativeBuffer_getPtrOfBuffer
(JNIEnv *env, jclass clazz, jobject buffer)
{
if (buffer == NULL) return ptr_to_jlong(0);
return ptr_to_jlong((*env)->GetDirectBufferAddress(env, buffer));
}

View File

@ -1,65 +0,0 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include "com_apple_jobjc_NativeObjectLifecycleManager.h"
#include <JavaNativeFoundation/JavaNativeFoundation.h>
/*
* Class: com_apple_jobjc_NativeObjectLifecycleManager
* Method: retainNativeObject
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_com_apple_jobjc_NativeObjectLifecycleManager_retainNativeObject
(JNIEnv *env, jclass clazz, jlong ptr)
{
if (ptr == 0L) return;
CFRetain(jlong_to_ptr(ptr));
}
/*
* Class: com_apple_jobjc_NativeObjectLifecycleManager
* Method: releaseNativeObject
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_com_apple_jobjc_NativeObjectLifecycleManager_releaseNativeObject
(JNIEnv *env, jclass clazz, jlong ptr)
{
if (ptr == 0L) return;
CFRelease(jlong_to_ptr(ptr));
}
/*
* Class: com_apple_jobjc_NativeObjectLifecycleManager
* Method: freeNativeObject
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_com_apple_jobjc_NativeObjectLifecycleManager_freeNativeObject
(JNIEnv *env, jclass clazz, jlong ptr)
{
if (ptr == 0L) return;
free(jlong_to_ptr(ptr));
}

View File

@ -1,44 +0,0 @@
/*
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include "com_apple_jobjc_SEL.h"
#include <JavaNativeFoundation/JavaNativeFoundation.h>
#include <objc/message.h>
JNIEXPORT jlong JNICALL Java_com_apple_jobjc_SEL_getSelectorPtr
(JNIEnv *env, jclass jclazz, jstring selName)
{
const char *selNameAsChars = (*env)->GetStringUTFChars(env, selName, JNI_FALSE);
const SEL sel = sel_registerName(selNameAsChars);
(*env)->ReleaseStringUTFChars(env, selName, selNameAsChars);
return ptr_to_jlong((void*)sel);
}
JNIEXPORT jstring JNICALL Java_com_apple_jobjc_SEL_getSelectorName
(JNIEnv *env, jclass jclazz, jlong selPtr)
{
return (*env)->NewStringUTF(env, sel_getName(jlong_to_ptr(selPtr)));
}

View File

@ -1,301 +0,0 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include "com_apple_jobjc_Subclassing.h"
#include <math.h>
#include <assert.h>
#include <errno.h>
#include <objc/runtime.h>
#include <objc/message.h>
#include <ffi/ffi.h>
#include <sys/mman.h>
#include <JavaNativeFoundation/JavaNativeFoundation.h>
// Subclassing of Obj-C classes in Java
//
// See:
// - Objective-C Runtime documentation
// - man ffi_prep_closure
// - Subclassing.java
#pragma mark Accessing object in IVar
#define JOBJ_IVAR_NAME "jObjWrapper"
static jobject getJObjectFromIVar(id obj);
jobject getJObjectFromIVar(id obj)
{
JNFJObjectWrapper *wrapper = NULL;
object_getInstanceVariable(obj, JOBJ_IVAR_NAME, (void**) &wrapper);
return wrapper ? [wrapper jObject] : NULL;
}
JNIEXPORT jobject JNICALL Java_com_apple_jobjc_Subclassing_getJObjectFromIVar
(JNIEnv *env, jclass jClass, jlong jPtr)
{
id obj = (id) jlong_to_ptr(jPtr);
if(obj == NULL){
(*env)->ThrowNew(env, (*env)->FindClass(env,
"java/lang/NullPointerException"), "obj");
return NULL;
}
JNFJObjectWrapper *wrapper;
if(!object_getInstanceVariable(obj, JOBJ_IVAR_NAME, (void**) &wrapper)){
NSLog(@"IVar '%s' not found. obj: %@", JOBJ_IVAR_NAME, obj);
(*env)->ThrowNew(env, (*env)->FindClass(env, "java/lang/RuntimeException"),
"Could not find instance variable that holds Java object.");
return NULL;
}
return wrapper ? [wrapper jObject] : NULL;
}
JNIEXPORT void JNICALL Java_com_apple_jobjc_Subclassing_initJObjectToIVar
(JNIEnv *env, jclass jClass, jlong jPtr, jobject jObject)
{
id obj = (id) jlong_to_ptr(jPtr);
JNFJObjectWrapper *wrapper = [[JNFJObjectWrapper alloc]
initWithJObject:jObject withEnv:env];
[wrapper retain];
if(!object_setInstanceVariable(obj, JOBJ_IVAR_NAME, wrapper)){
NSLog(@"IVar '%s' not found. obj: %@", JOBJ_IVAR_NAME, obj);
(*env)->ThrowNew(env, (*env)->FindClass(env, "java/lang/RuntimeException"),
"Could not find instance variable that holds Java object.");
return;
}
}
#pragma mark Registering class
JNIEXPORT jlong JNICALL Java_com_apple_jobjc_Subclassing_allocateClassPair
(JNIEnv *env, jclass clazz, jlong jSuperClass, jstring jName)
{
const Class superClass = (Class)jlong_to_ptr(jSuperClass);
assert(superClass);
const char *name = (*env)->GetStringUTFChars(env, jName, JNI_FALSE);
const Class newClass = objc_allocateClassPair(superClass, name, 0);
(*env)->ReleaseStringUTFChars(env, jName, name);
return ptr_to_jlong(newClass);
}
JNIEXPORT jboolean JNICALL Java_com_apple_jobjc_Subclassing_addIVarForJObj
(JNIEnv *env, jclass clazz, jlong jSynthClass)
{
return class_addIvar(
jlong_to_ptr(jSynthClass),
JOBJ_IVAR_NAME,
sizeof(id),
(uint8_t)log2((double)sizeof(id)),
"@");
}
JNIEXPORT void JNICALL Java_com_apple_jobjc_Subclassing_registerClassPair
(JNIEnv *env, jclass clazz, jlong jClass)
{
Class c = jlong_to_ptr(jClass);
// NSLog(@"Registering class pair %p / %s", c, class_getName(c));
objc_registerClassPair(c);
}
#pragma mark Patching +alloc
static id patchedAllocIMP(id obj, SEL sel);
static void addJavaInstance(id obj);
JNIEXPORT jboolean JNICALL Java_com_apple_jobjc_Subclassing_patchAlloc
(JNIEnv *env, jclass clazz, jlong jNativeClass)
{
Class metaClass = object_getClass(jlong_to_ptr(jNativeClass));
return class_addMethod(metaClass,
sel_registerName("alloc"),
(IMP) patchedAllocIMP,
"@@:");
}
static id patchedAllocIMP(id cls, SEL sel){
id inst = class_createInstance(cls, 0);
addJavaInstance(inst);
return inst;
}
static void addJavaInstance(id obj){
// NSLog(@"addJavaInstance %p", obj);
// NSLog(@"... calling up to Java");
static JNF_CLASS_CACHE(jc_Subclassing, "com/apple/jobjc/Subclassing");
static JNF_STATIC_MEMBER_CACHE(jm_Subclassing_initJObject,
jc_Subclassing,
"initJObject",
"(J)V");
JNFThreadContext threadWasAttached = JNFThreadDetachOnThreadDeath;
JNIEnv *env = JNFObtainEnv(&threadWasAttached);
JNFCallStaticVoidMethod(env, jm_Subclassing_initJObject,
ptr_to_jlong(obj));
JNFReleaseEnv(env, &threadWasAttached);
}
#pragma mark Adding methods
static ffi_closure *make_closure(ffi_cif *cif, void *user_data);
static void sel_closure_call(ffi_cif* cif, void* result, void** args, void* user_data);
typedef struct closure_data_t{
JNFJObjectWrapper *jMethod;
JNFJObjectWrapper *jCIF;
} closure_data_t;
static ffi_closure *make_closure(ffi_cif *cif, void *user_data){
// Allocate a page to hold the closure with read and write permissions.
ffi_closure *closure;
if ((closure = mmap(NULL, sizeof(ffi_closure), PROT_READ | PROT_WRITE,
MAP_ANON | MAP_PRIVATE, -1, (off_t) 0)) == (void*)-1)
{
fprintf(stderr, "mmap failed with errno: %d", errno);
return NULL;
}
// Prepare the ffi_closure structure.
ffi_status status;
if ((status = ffi_prep_closure(closure, cif, sel_closure_call, (void *)user_data)) != FFI_OK)
{
fprintf(stderr, "ffi_prep_closure failed with ffi_status: %d", status);
munmap(closure, sizeof(ffi_closure));
return NULL;
}
// Ensure that the closure will execute on all architectures.
if (mprotect(closure, sizeof(closure), PROT_READ | PROT_EXEC) == -1)
{
fprintf(stderr, "mprotect failed with errno: %d", errno);
munmap(closure, sizeof(ffi_closure));
return NULL;
}
return closure;
}
JNIEXPORT jboolean JNICALL Java_com_apple_jobjc_Subclassing_addMethod
(JNIEnv *env, jclass clazz, jlong jClass, jstring jSelName, jobject jMethod,
jobject jCIF, jlong jCIFPtr, jstring jObjCEncodedType)
{
ffi_cif *cif = jlong_to_ptr(jCIFPtr);
closure_data_t *user_data = malloc(sizeof(closure_data_t));
user_data->jMethod = [[JNFJObjectWrapper alloc] initWithJObject:jMethod withEnv:env];
user_data->jCIF = [[JNFJObjectWrapper alloc] initWithJObject:jCIF withEnv:env];
ffi_closure *closure;;
if(!(closure = make_closure(cif, user_data))){
[user_data->jMethod release];
[user_data->jCIF release];
free(user_data);
return NO;
}
const Class objcClass = (Class)jlong_to_ptr(jClass);
const char *selName = (*env)->GetStringUTFChars(env, jSelName, JNI_FALSE);
const char *objCEncodedType = (*env)->GetStringUTFChars(env, jObjCEncodedType, JNI_FALSE);
// NSLog(@"Adding method '%s' :: '%s' to '%s' / %p",
// selName,
// objCEncodedType,
// class_getName(objcClass),
// objcClass);
BOOL ret = class_addMethod(objcClass, sel_registerName(selName), (IMP) closure, objCEncodedType);
(*env)->ReleaseStringUTFChars(env, jSelName, selName);
(*env)->ReleaseStringUTFChars(env, jObjCEncodedType, objCEncodedType);
if(!ret){
NSLog(@"class_addMethod failed");
munmap(closure, sizeof(ffi_closure));
[user_data->jMethod release];
[user_data->jCIF release];
free(user_data);
return NO;
}
return ret;
}
static void sel_closure_call(ffi_cif* cif, void* result, void** args, void* user_data)
{
id obj = *(id*) args[0];
// SEL sel = *(SEL*) args[1];
// NSLog(@"Subclassing: sel_closure_call: %p %p", obj, sel);
// NSLog(@"Subclassing: sel_closure_call: obj class: %@ sel name: %s", object_getClass(obj), sel_getName(sel));
jobject jObj = getJObjectFromIVar(obj);
if(!jObj){
addJavaInstance(obj);
jObj = getJObjectFromIVar(obj);
}
closure_data_t *jmeta = user_data;
jobject jMethod = [jmeta->jMethod jObject];
jobject jCIF = [jmeta->jCIF jObject];
JNFThreadContext threadWasAttached = JNFThreadDetachOnThreadDeath;
JNIEnv *env = JNFObtainEnv(&threadWasAttached);
if((*env)->ExceptionOccurred(env)) goto bail;
static JNF_CLASS_CACHE(jc, "com/apple/jobjc/Subclassing");
static JNF_STATIC_MEMBER_CACHE(jm_invokeFromJNI, jc, "invokeFromJNI",
"(Lcom/apple/jobjc/ID;Ljava/lang/reflect/Method;Lcom/apple/jobjc/CIF;JJ)V");
JNFCallStaticVoidMethod(env, jm_invokeFromJNI,
jObj,
jMethod,
jCIF,
ptr_to_jlong(result),
ptr_to_jlong(args));
bail:
JNFReleaseEnv(env, &threadWasAttached);
if((*env)->ExceptionOccurred(env)){
NSLog(@"Exception!");
(*env)->ExceptionDescribe(env);
}
JNFReleaseEnv(env, &threadWasAttached);
}

View File

@ -1,51 +0,0 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.internal.jobjc.generator;
public class BootClassPathMinus {
/*
* return the default boot class path with all parts mentioned in arguments removed
*/
public static void main(String[] args) {
String bootClassPath = System.getProperty("sun.boot.class.path");
StringBuffer newPath = new StringBuffer(bootClassPath.length());
String[] bootClassPathParts = bootClassPath.split(java.io.File.pathSeparator, 0);
for (String part : bootClassPathParts) {
boolean found = false;
for (String minus : args) {
if (part.endsWith(minus)) {
found = true;
}
}
if (!found) {
if (newPath.length() > 0) newPath.append(java.io.File.pathSeparatorChar);
newPath.append(part);
}
}
System.out.println(newPath.toString());
}
}

View File

@ -1,112 +0,0 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.internal.jobjc.generator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.apple.internal.jobjc.generator.model.Category;
import com.apple.internal.jobjc.generator.model.Clazz;
import com.apple.internal.jobjc.generator.model.Framework;
public class ClassConsolidator {
private static String[] PREFERRED_FRAMEWORKS = { "Foundation", "AppKit" };
static void consolidateClassesForFrameworks(final List<Framework> frameworks) throws Throwable {
System.out.println("--2-- Resolving duplicate classes:");
final Map<String, List<Clazz>> allClasses = new HashMap<String, List<Clazz>>();
for (final Framework framework : frameworks) {
for (final Clazz clazz : framework.classes) {
final List<Clazz> existingClazzList = allClasses.get(clazz.name);
if(existingClazzList != null)
existingClazzList.add(clazz);
else
allClasses.put(clazz.name, new ArrayList<Clazz>(Arrays.asList(clazz)));
}
}
final Map<String, Clazz> filteredClasses = new HashMap<String, Clazz>();
final List<List<Clazz>> dreggs = new ArrayList<List<Clazz>>();
final Collection<List<Clazz>> clazzLists = allClasses.values();
for (final List<Clazz> clazzList : clazzLists) {
if (clazzList.size() > 1) {
// add to the list for later analysis
dreggs.add(clazzList);
continue;
}
// if there is only one class definition, go with it!
final Clazz clazz = clazzList.get(0);
filteredClasses.put(clazz.name, clazz);
}
// figure out which class is the real class, and convert the rest to categories
for (final List<Clazz> dreg : dreggs)
deriveCategoriesFrom(dreg, filteredClasses);
// patch up the inheritance hierarchy
System.out.println("Determining super classes:");
for (final Framework framework : frameworks)
framework.resolveSuperClasses(filteredClasses);
}
private static void deriveCategoriesFrom(final List<Clazz> clazzes, final Map<String, Clazz> filteredClasses) {
final List<Clazz> clazzesToDerive = new ArrayList<Clazz>(clazzes);
for (final String preferredFrameworkName : PREFERRED_FRAMEWORKS) {
for (final Clazz clazz : clazzesToDerive) {
if (!preferredFrameworkName.equals(clazz.parent.name)) continue;
System.out.print("\t" + clazz.parent.name + " owns \"" + clazz.name + "\", ");
addCategoriesAndPatchClasses(clazzes, clazz);
filteredClasses.put(clazz.name, clazz);
return;
}
}
final List<String> frameworkNameList = new ArrayList<String>(clazzes.size());
for (final Clazz clazz : clazzes) frameworkNameList.add(clazz.parent.name);
throw new RuntimeException("Could not derived a preferred framework for: " + clazzes.get(0).name + ", from (" + Utils.joinWComma(frameworkNameList) + ")");
}
private static void addCategoriesAndPatchClasses(final List<Clazz> clazzes, final Clazz clazz) {
final List<String> fwNames = new ArrayList<String>(clazzes.size());
for (final Clazz cls : clazzes) {
if (cls == clazz) continue;
fwNames.add(cls.parent.name);
cls.parent.classes.remove(cls);
cls.parent.categories.add(new Category(cls, clazz));
}
System.out.println("creating categories in: " + Utils.joinWComma(fwNames));
}
}

View File

@ -1,61 +0,0 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.internal.jobjc.generator;
import java.io.File;
import java.util.*;
import com.apple.internal.jobjc.generator.classes.*;
public class FileCopier {
public static List<OutputFile> addSourceFilesFrom(final String srcPath) {
final List<OutputFile> outputFileList = new ArrayList<OutputFile>();
final List<File> fileList = getFileList(srcPath);
for (final File file : fileList) {
outputFileList.add(new CopiedFile(file, ClassGenerator.JOBJC_PACKAGE, file.getName().replace("\\.java", "")));
}
return outputFileList;
}
private static List<File> getFileList(final String srcPath) {
final File srcRoot = new File(srcPath);
if (!srcRoot.exists()) throw new RuntimeException("Source root " + srcRoot + " does not exist. Nowhere to copy base runtime objects from.");
final File targetDir = new File(srcRoot, ClassGenerator.JOBJC_PACKAGE.replaceAll("\\.", "\\/"));
if (!targetDir.exists() || !targetDir.isDirectory()) throw new RuntimeException("Base runtime object source directory " + targetDir + " does not exist. No runtime class files to copy.");
final List<File> fileList = new ArrayList<File>();
final File[] targetDirFileList = targetDir.listFiles();
for (final File file : targetDirFileList) {
if (!file.isFile()) continue;
if (!file.getName().endsWith(".java")) continue;
fileList.add(file);
}
return fileList;
}
}

View File

@ -1,112 +0,0 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.internal.jobjc.generator;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.apple.internal.jobjc.generator.model.Framework;
import com.apple.internal.jobjc.generator.model.Framework.FrameworkDependency;
import com.apple.internal.jobjc.generator.utils.Fp;
import com.apple.internal.jobjc.generator.utils.StructOffsetResolverBigBang;
import com.apple.jobjc.JObjCRuntime;
public class FrameworkGenerator {
private static final String BRIDGESUPPORT_FILE_EXTENSION = "Full.bridgesupport";
private static final String FRAMEWORK_MATCH = "^.*Full\\.bridgesupport$";
private static final String FRAMEWORK_PRUNE = "^.*(PyObjC|/Versions|\\.lproj|/Headers|/PrivateHeaders).*$";
static List<File> findFrameworkFilesIn(final File file) throws IOException{
final List<File> bridgeSupportFiles = Utils.find(file, FRAMEWORK_MATCH, FRAMEWORK_PRUNE);
System.out.println("found " + bridgeSupportFiles.size() + " frameworks");
return bridgeSupportFiles;
}
static List<Framework> parseFrameworksFrom(final List<File> bridgeSupportFiles) {
final List<Framework> frameworks = new ArrayList<Framework>();
System.out.println("Parsing XML");
for (final File file : bridgeSupportFiles){
Framework f = new Framework(extractFrameworkNameFrom(file), file);
try{
f.load();
frameworks.add(f);
System.out.println("Generator@" + JObjCRuntime.ARCH + " loaded "
+ f.name + " (" + Fp.join(":", f.binaries) + ")");
}
catch(Exception x){
System.out.println("!! Generator@" + JObjCRuntime.ARCH + " failed to load "
+ f.name + " (" + Fp.join(":", f.binaries) + "). SKIPPING");
}
}
System.out.println("Parsing dependencies");
for (final Framework f : frameworks) f.parseDependencies(frameworks);
Set<String> alreadyWarnedDependency = new HashSet<String>();
for(final Framework f : frameworks)
for(final FrameworkDependency dep : f.dependencies)
if(dep.object == null && !alreadyWarnedDependency.contains(dep.name)){
System.out.println(String.format("Warning: unresolved dependency: %1$30s -> %2$s", f.name, dep.name));
alreadyWarnedDependency.add(dep.name);
}
if(alreadyWarnedDependency.size() > 0)
System.out.println("Unresolved dependencies lead to unresolved types.");
Utils.topologicalSort(frameworks);
List<Framework> cycle = Utils.getDependencyCycle(frameworks);
if(cycle != null)
System.out.println("Warning: cycle found in framework dependencies: " + Fp.join(" -> ", cycle));
System.out.println("Parsing types");
for (final Framework f : frameworks){
f.parseCFTypes();
f.parseOpaques();
}
for (final Framework f : frameworks) f.parseStructs();
new StructOffsetResolverBigBang().resolve(frameworks);
System.out.println("Parsing classes");
for (final Framework f : frameworks) f.parseClasses();
System.out.println("Parsing constants");
for (final Framework f : frameworks) f.parseConstants();
System.out.println("Parsing functions");
for (final Framework f : frameworks) f.parseFunctions();
return frameworks;
}
private static String extractFrameworkNameFrom(final File file) {
final String fileName = file.getName();
return fileName.substring(0, fileName.lastIndexOf(BRIDGESUPPORT_FILE_EXTENSION));
}
}

View File

@ -1,178 +0,0 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.internal.jobjc.generator;
import java.io.PrintStream;
import java.io.StringWriter;
import com.apple.internal.jobjc.generator.model.Arg;
import com.apple.internal.jobjc.generator.model.Function;
import com.apple.internal.jobjc.generator.model.Method;
import com.apple.internal.jobjc.generator.model.types.JType;
import com.apple.internal.jobjc.generator.utils.JavaLang.JLCall;
import com.apple.internal.jobjc.generator.utils.JavaLang.JLField;
import com.apple.internal.jobjc.generator.utils.JavaLang.JLMethod;
import com.apple.internal.jobjc.generator.utils.JavaLang.JLTertiary;
import com.apple.jobjc.Coder;
import com.apple.jobjc.Invoke;
import com.apple.jobjc.Invoke.FunCall;
import com.apple.jobjc.Invoke.MsgSend;
public class FunctionGenerator {
private final static String VARARGS_NAME = "varargs";
private static String createFieldCache(final Class<? extends Invoke> type, final Function fxn) {
final String identifier = makeInstanceName(fxn);
JLField field = new JLField("private static", type.getCanonicalName(), identifier);
// It's okay to make it static, because the getter isn't static, so the only way to access it is through an instance.
JLMethod getter = new JLMethod("private final", type.getCanonicalName(), "get_" + identifier);
JLCall createIt = new JLCall("new " + type.getCanonicalName());
createIt.args.add(firstArg(fxn));
createIt.args.add("\"" + fxn.name + "\"");
createIt.args.add(fxn.returnValue.type.getJType().getCoderDescriptor().getCoderInstanceName());
for (final Arg arg : fxn.args)
createIt.args.add(arg.type.getJType().getCoderDescriptor().getCoderInstanceName());
getter.body.add("return " + new JLTertiary(identifier + " != null", identifier, identifier + " = " + createIt) + ";");
return field.toString() + getter.toString();
}
private static String createLocalForward(final Class<? extends Invoke> type, final Function fxn) {
final String identifier = makeInstanceName(fxn);
return new JLField("final", type.getCanonicalName(), identifier, new JLCall("get_" + identifier)).toString();
}
private static String createLocalNew(final Class<? extends Invoke> type, final Function fxn) {
final String identifier = makeInstanceName(fxn);
StringWriter out = new StringWriter();
out.append(String.format("%3$s[] argCoders = new %3$s[%1$d + %2$s.length];\n", fxn.args.size(), VARARGS_NAME, Coder.class.getCanonicalName()));
for(int i = 0; i < fxn.args.size(); i++)
out.append(String.format("argCoders[%1$d] = %2$s;\n", i, fxn.args.get(0).type.getJType().getCoderDescriptor().getCoderInstanceName()));
if(fxn.variadic){
out.append(String.format("for(int i = %1$d; i < (%1$d + %2$s.length); i++)\n", fxn.args.size(), VARARGS_NAME));
out.append(String.format("\targCoders[i] = %1$s.getCoderAtRuntime(%2$s[i - %3$s]);\n", Coder.class.getCanonicalName(), VARARGS_NAME, fxn.args.size()));
}
out.append("final " + type.getCanonicalName() + " " + identifier + " = new " + type.getCanonicalName() + "(" + firstArg(fxn) + ", \"" + fxn.name + "\", "
+ fxn.returnValue.type.getJType().getCoderDescriptor().getCoderInstanceName() + ", argCoders);");
return out.toString();
}
private static final String CONTEXT_NAME = "nativeBuffer";
public static void writeOutFunction(final PrintStream out, final Class<? extends Invoke> type, final Function fxn, final String initWithObj) {
final String instName = makeInstanceName(fxn);
final JType returnJavaType = fxn.returnValue.type.getJType();
if(!fxn.variadic){
out.print(createFieldCache(type, fxn));
out.println();
}
JLMethod meth = new JLMethod("public", returnJavaType.getJavaReturnTypeName(), fxn.getJavaName());
for(Arg arg : fxn.args)
meth.args.add("final " + arg.type.getJType().getTypeNameAsParam() + " " + arg.javaName);
if(fxn.variadic)
meth.args.add("final Object... " + VARARGS_NAME);
if(fxn instanceof Method && ((Method)fxn).ignore){
String suggestion = ((Method)fxn).suggestion == null ? "" : (" Suggested work-around: " + ((Method)fxn).suggestion);
meth.jdoc.add("@deprecated The framework recommends that this method be ignored. (It may be deprecated.)" + suggestion);
meth.attrs.add("@Deprecated");
}
// type mismatch warning
{
{
String retMsg = fxn.returnValue.type.getJType().getCoderDescriptor().mismatchMessage();
if(retMsg != null){
meth.jdoc.add("@deprecated Possible type mismatch: (return value) " + retMsg);
meth.attrs.add("@Deprecated");
}
}
for(int i = 0; i < fxn.args.size(); i++){
final Arg arg = fxn.args.get(i);
String argMsg = arg.type.getJType().getCoderDescriptor().mismatchMessage();
if(argMsg != null){
meth.jdoc.add("@deprecated Possible type mismatch: (arg" + i + ": " + arg.javaName + ") " + argMsg);
meth.attrs.add("@Deprecated");
}
}
}
if(fxn.variadic)
meth.body.add(createLocalNew(coreType(fxn), fxn));
else
meth.body.add(createLocalForward(coreType(fxn), fxn));
meth.body.add(returnJavaType.createDeclareBuffer(CONTEXT_NAME));
meth.body.add(returnJavaType.createInit(CONTEXT_NAME, instName, initWithObj));
for(final Arg arg : fxn.args)
meth.body.add(arg.type.getJType().getCoderDescriptor().getPushStatementFor(CONTEXT_NAME, arg.javaName));
if(fxn.variadic){
meth.body.add(String.format("for(int i = %1$d; i < (%1$d + %2$s.length); i++)", fxn.args.size(), VARARGS_NAME));
meth.body.add(String.format("\targCoders[i].push(%1$s, %2$s[i - %3$d]);", CONTEXT_NAME, VARARGS_NAME, fxn.args.size()));
}
meth.body.add(returnJavaType.createInvoke(CONTEXT_NAME, instName));
meth.body.add(returnJavaType.createPop(CONTEXT_NAME));
meth.body.add(returnJavaType.createReturn());
out.print(meth.toString());
out.println();
}
private static Class<? extends Invoke> coreType(final Function fxn){
return fxn instanceof Method ? MsgSend.class : FunCall.class;
}
private static String firstArg(Function fxn){
return fxn instanceof Method ? "getRuntime()" : "this";
}
private static String makeInstanceName(Function fxn){
String ext;
if(fxn instanceof Method){
if(((Method) fxn).isClassMethod) ext = "CMetInst";
else ext = "IMetInst";
}
else
ext = "FxnInst";
return fxn.getJavaName() + "_" + ext;
}
}

View File

@ -1,94 +0,0 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.internal.jobjc.generator;
import java.io.File;
import java.util.List;
import java.util.Map;
import com.apple.internal.jobjc.generator.classes.MixedPrimitiveCoderClassFile;
import com.apple.internal.jobjc.generator.classes.OutputFile;
import com.apple.internal.jobjc.generator.model.Framework;
import com.apple.internal.jobjc.generator.model.coders.ComplexCoderDescriptor;
import com.apple.internal.jobjc.generator.model.types.Type;
import com.apple.internal.jobjc.generator.model.types.TypeCache;
import com.apple.internal.jobjc.generator.utils.Fp.Pair;
public class Generator {
private static final String DEFAULT_FRAMEWORKS_PATH = "/System/Library/Frameworks";
private static final String DEFAULT_OUTPUT_PATH = "/tmp/JObjC";
public static void main(final String...args) throws Throwable {
final Map<String, String> argMap = Utils.getArgs(args);
final String dst = get(argMap, "dst", DEFAULT_OUTPUT_PATH);
System.out.println("Cleaning up: " + dst);
final File dstLoc = new File(dst);
Utils.recDelete(dstLoc);
dstLoc.mkdirs();
System.out.println("Outputting classes to: " + dst);
final String frameworksPath = get(argMap, "frameworks", DEFAULT_FRAMEWORKS_PATH);
System.out.println("Searching for bridged frameworks in: " + frameworksPath);
final List<File> bridgeSupportFiles = FrameworkGenerator.findFrameworkFilesIn(new File(frameworksPath));
final List<Framework> frameworks = FrameworkGenerator.parseFrameworksFrom(bridgeSupportFiles);
System.out.println("--1-- Generator: consolidateClassesForFrameworks");
ClassConsolidator.consolidateClassesForFrameworks(frameworks);
System.out.println("--1-- Generator: TypeCache load");
TypeCache.inst().load(frameworks);
System.out.println("--1-- Generator: disambiguateMethodNames");
MethodDisambiguator.disambiguateMethodNames();
System.out.println("--1-- Generator: disambiguateFunctionsIn");
MethodDisambiguator.disambiguateFunctionsIn(frameworks);
System.out.println("--1-- Generator: generateClasses");
final List<OutputFile> sourceFiles = ClassGenerator.generateClasses(frameworks);
sourceFiles.add(new MixedPrimitiveCoderClassFile(ComplexCoderDescriptor.getMixedEncoders()));
System.out.println("--1-- Generator: writing " + sourceFiles.size() + " files");
for (final OutputFile sourceFile : sourceFiles) sourceFile.write(dstLoc);
System.out.println("I have " + TypeCache.inst().getUnknownTypes().size() + " unresolved types.");
for (final Type type : TypeCache.inst().getUnknownTypes())
System.out.println("[Warning] unknown type: " + type);
for(Type type : TypeCache.inst().typesByNTypes.values()){
if(!type.type32.getClass().equals(type.type64.getClass())){
System.out.format("Type with differing NTypes: %1$15s: %2$s\n", type.name, new Pair(type.type32, type.type64));
}
}
}
private static String get(final Map<String, String> defaults, final String key, final String defaultValue) {
final String value = defaults.get(key);
if (value != null) return value;
return defaultValue;
}
}

View File

@ -1,66 +0,0 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.internal.jobjc.generator;
import java.util.List;
import com.apple.internal.jobjc.generator.model.Clazz;
import com.apple.internal.jobjc.generator.model.Framework;
import com.apple.internal.jobjc.generator.model.Function;
import com.apple.internal.jobjc.generator.model.types.TypeCache;
public class MethodDisambiguator {
static void disambiguateMethodNames() {
// link all subclassers off their parents
for (final Clazz clazz : TypeCache.inst().getAllClasses()) {
final Clazz superClazz = clazz.superClass;
if (superClazz != null) superClazz.subClassers.add(clazz);
}
// recursively call all subclassers, starting from NSObject on down
disambiguateMethodNamesFor(TypeCache.inst().getClassForName("NSObject"));
// NSProxy does not appear to subclass from NSObject, but it is still a real full class...?
disambiguateMethodNamesFor(TypeCache.inst().getClassForName("NSProxy"));
}
static void disambiguateMethodNamesFor(final Clazz clazz) {
clazz.disambiguateMethods();
for (final Clazz subClazz : clazz.subClassers) {
disambiguateMethodNamesFor(subClazz);
}
}
public static void disambiguateFunctionsIn(final List<Framework> frameworks) {
for (final Framework framework : frameworks) {
disambiguateFunctionsInFramework(framework);
}
}
static void disambiguateFunctionsInFramework(final Framework framework) {
for (final Function fxn : framework.functions)
fxn.disambiguateArgs();
}
}

View File

@ -1,45 +0,0 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.internal.jobjc.generator;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class RestrictedKeywords {
static final String[] JAVA_KEYWORD_CONFLICTS = {
"wait", "null", "class", "new", "toString", "finalize", "boolean", "interface", "final", "static"
};
static final Set<String> originalRestrictedSet = new HashSet<String>(Arrays.asList(JAVA_KEYWORD_CONFLICTS));
public static Set<String> getNewRestrictedSet() {
return new HashSet<String>(originalRestrictedSet);
}
public static boolean isRestricted(String s){
return originalRestrictedSet.contains(s);
}
}

View File

@ -1,186 +0,0 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.internal.jobjc.generator;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Pattern;
import com.apple.internal.jobjc.generator.model.Framework;
import com.apple.internal.jobjc.generator.model.Framework.FrameworkDependency;
import com.apple.internal.jobjc.generator.utils.Fp;
public class Utils {
public static boolean isLeopard = System.getProperty("os.version").startsWith("10.5");
public static boolean isSnowLeopard = System.getProperty("os.version").startsWith("10.6");
@SuppressWarnings("unchecked")
public static <T> List<T> list(final Object...args) {
final ArrayList<Object> list = new ArrayList<Object>(args.length);
for (final Object arg : args) list.add(arg);
return (List<T>)list;
}
/**
* A small implementation of UNIX find.
* @param matchRegex Only collect paths that match this regex.
* @param pruneRegex Don't recurse down a path that matches this regex. May be null.
* @throws IOException if File.getCanonicalPath() fails.
*/
public static List<File> find(final File startpath, final String matchRegex, final String pruneRegex) throws IOException{
final Pattern matchPattern = Pattern.compile(matchRegex, Pattern.CASE_INSENSITIVE);
final Pattern prunePattern = pruneRegex == null ? null : Pattern.compile(pruneRegex, Pattern.CASE_INSENSITIVE);
final Set<String> visited = new HashSet<String>();
final List<File> found = new ArrayList<File>();
class Search{
void search(final File path) throws IOException{
if(prunePattern != null && prunePattern.matcher(path.getAbsolutePath()).matches()) return;
String cpath = path.getCanonicalPath();
if(!visited.add(cpath)) return;
if(matchPattern.matcher(path.getAbsolutePath()).matches())
found.add(path);
if(path.isDirectory())
for(File sub : path.listFiles())
search(sub);
}
}
new Search().search(startpath);
return found;
}
public static String joinWComma(final List<?> list) { return Fp.join(", ", list); }
public static String joinWComma(final Object[] list) { return Fp.join(", ", Arrays.asList(list)); }
public static class Substituter {
String str;
public Substituter(final String str) {
this.str = str.replaceAll("\\#", "\t").replaceAll("\\~", "\n");
}
public void replace(final String key, final String value) {
str = str.replaceAll("\\$" + key, value);
}
/**
* Apply String.format first, and then pass through Substituter.
*/
public static String format(String format, Object... args){
return new Substituter(String.format(format, args)).toString();
}
@Override public String toString() {
return str;
}
}
static Map<String, String> getArgs(final String...args) {
final Map<String, String> argMap = new HashMap<String, String>();
for (final String arg : args) {
final String[] splitArg = arg.split("\\=");
if (splitArg.length != 2) continue;
argMap.put(splitArg[0], splitArg[1]);
}
return argMap;
}
static void recDelete(final File file) {
if (!file.exists()) return;
if (file.isDirectory()) for (final File f : file.listFiles()) recDelete(f);
file.delete();
}
public static String capitalize(String s){
if(s.length() == 0) return s;
return Character.toString(Character.toUpperCase(s.charAt(0))) + s.substring(1);
}
/**
* Sort frameworks by dependencies. If A is a dependency of B,
* then A will come before B in the list.
*/
public static void topologicalSort(final List<Framework> frameworks) {
final Set<Framework> visited = new TreeSet<Framework>();
final List<Framework> sorted = new ArrayList<Framework>(frameworks.size());
class Rec{
void visit(final Framework fw){
if(!visited.add(fw)) return;
for(FrameworkDependency dep : fw.dependencies)
if(dep.object != null)
visit(dep.object);
sorted.add(fw);
}
}
for(Framework fw : frameworks) new Rec().visit(fw);
frameworks.clear();
frameworks.addAll(sorted);
}
/**
* If there is a cycle it is returned. Otherwise null is returned.
*/
public static List<Framework> getDependencyCycle(List<Framework> frameworks) {
@SuppressWarnings("serial")
class FoundCycle extends Throwable{
public final List<Framework> cycle;
public FoundCycle(List<Framework> cycle){
this.cycle = cycle;
}
};
class Rec{
void visit(final Framework fw, List<Framework> visited) throws FoundCycle{
visited = new LinkedList<Framework>(visited);
if(visited.contains(fw)){
visited.add(fw);
throw new FoundCycle(visited);
}
visited.add(fw);
for(FrameworkDependency dep : fw.dependencies)
if(dep.object != null)
visit(dep.object, visited);
}
}
try{ for(Framework fw : frameworks){ new Rec().visit(fw, new LinkedList<Framework>()); }}
catch(FoundCycle x){ return x.cycle; }
return null;
}
public static String getCanonicalPath(File file) throws RuntimeException{
try {
return file.getCanonicalPath();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -1,59 +0,0 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.internal.jobjc.generator.classes;
import java.io.PrintStream;
import com.apple.internal.jobjc.generator.model.CFType;
import com.apple.jobjc.Pointer;
public class CFTypeClassFile extends GeneratedClassFile {
final CFType cftype;
public CFTypeClassFile(final CFType cftype) {
super(cftype.parent.pkg, cftype.type.getJType().getJavaClassName(), com.apple.jobjc.CFType.class.getCanonicalName());
this.cftype = cftype;
}
@Override public void writeBeginning(PrintStream out){
out.println("\tpublic " + className + "(" + Pointer.class.getName() + "<?> ptr){");
out.println("\t\tsuper(ptr);");
out.println("\t}");
out.println("");
out.println("\tpublic " + className + "(long ptr){");
out.println("\t\tsuper(ptr);");
out.println("\t}");
}
@Override public void writeBody(PrintStream out){
if(cftype.getTypeIdFunc != null){
out.println("\tpublic static long getTypeId(){");
out.println("\t\treturn " + RootJObjCClass.runtimeFrameworkInst(cftype.parent.name) + "." + cftype.getTypeIdFunc + "();");
out.println("\t}");
}
else
out.println("\t// getTypeIdFunc not found");
}
}

View File

@ -1,64 +0,0 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.internal.jobjc.generator.classes;
import java.io.PrintStream;
import java.util.HashSet;
import java.util.Set;
import com.apple.internal.jobjc.generator.FunctionGenerator;
import com.apple.internal.jobjc.generator.model.Category;
import com.apple.internal.jobjc.generator.model.Method;
import com.apple.jobjc.JObjCRuntime;
import com.apple.jobjc.Invoke.MsgSend;
public class CategoryClassClassFile extends AbstractObjCClassFile {
final Category category;
public CategoryClassClassFile(final Category category) {
super(category.category, category.category.name + "Class",
category.category.superClass.getFullPath() + "Class");
this.category = category;
}
@Override public void writeBeginning(final PrintStream out) {
out.format(
"\t%1$s(%2$s runtime) {\n" +
"\t\tsuper(\"%3$s\", runtime);\n" +
"\t}\n",
className, JObjCRuntime.class.getCanonicalName(), category.category.superClass.name);
}
@Override public void writeBody(final PrintStream out) {
Set<String> written = new HashSet<String>();
for(final Method method : this.clazz.classMethods)
if(written.add(method.name))
FunctionGenerator.writeOutFunction(out, MsgSend.class, method, "this");
else
System.out.format("Duplicate method: %1$s %2$s -%3$s\n", clazz.parent.name, className, method.name);
}
@Override protected boolean isFinal(){ return true; }
}

View File

@ -1,48 +0,0 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.internal.jobjc.generator.classes;
import java.io.PrintStream;
import com.apple.internal.jobjc.generator.model.Category;
import com.apple.jobjc.JObjCRuntime;
public class CategoryClassFile extends JObjCClassFile {
private final Category category;
public CategoryClassFile(final Category category) {
super(category.category);
this.category = category;
}
@Override public void writeBeginning(final PrintStream out) {
String targetCls = category.category.superClass.getFullPath();
out.format("\tpublic %1$s(final %2$s obj, final %3$s runtime) {\n" +
"\t\tsuper(obj, runtime);\n" +
"\t}\n",
className, targetCls, JObjCRuntime.class.getCanonicalName());
super.writeBeginning(out);
}
}

View File

@ -1,54 +0,0 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.internal.jobjc.generator.classes;
import java.io.*;
public class CopiedFile extends OutputFile {
final File sourceFile;
public CopiedFile(final File sourceFile, final String pkg, final String filename) {
super(pkg, filename);
this.sourceFile = sourceFile;
}
@Override
public void write(final File parentDir) {
try {
final PrintStream out = open(parentDir);
final InputStream in = new FileInputStream(sourceFile);
copy(in, out);
close(out);
} catch (final IOException e) { throw new RuntimeException(e); }
}
private static void copy(final InputStream in, final PrintStream out) throws IOException {
int bit;
while (-1 != (bit = in.read())) {
out.write(bit);
}
}
}

View File

@ -1,160 +0,0 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.internal.jobjc.generator.classes;
import java.io.File;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;
import com.apple.internal.jobjc.generator.FunctionGenerator;
import com.apple.internal.jobjc.generator.Utils;
import com.apple.internal.jobjc.generator.model.Category;
import com.apple.internal.jobjc.generator.model.Clazz;
import com.apple.internal.jobjc.generator.model.Constant;
import com.apple.internal.jobjc.generator.model.Framework;
import com.apple.internal.jobjc.generator.model.Function;
import com.apple.internal.jobjc.generator.model.NativeEnum;
import com.apple.internal.jobjc.generator.model.StringConstant;
import com.apple.internal.jobjc.generator.model.Struct;
import com.apple.internal.jobjc.generator.model.types.JType;
import com.apple.internal.jobjc.generator.model.types.JType.JStruct;
import com.apple.internal.jobjc.generator.utils.Fp;
import com.apple.internal.jobjc.generator.utils.JavaLang;
import com.apple.internal.jobjc.generator.utils.Fp.Map1;
import com.apple.internal.jobjc.generator.utils.JavaLang.JLCall;
import com.apple.internal.jobjc.generator.utils.JavaLang.JLField;
import com.apple.internal.jobjc.generator.utils.JavaLang.JLMethod;
import com.apple.internal.jobjc.generator.utils.JavaLang.JLReturn;
import com.apple.jobjc.JObjCRuntime;
import com.apple.jobjc.MacOSXFramework;
import com.apple.jobjc.Invoke.FunCall;
public class FrameworkClassFile extends GeneratedClassFile {
final Framework framework;
public FrameworkClassFile(final Framework framework) {
super(framework.pkg, framework.name + "Framework", MacOSXFramework.class.getName());
this.framework = framework;
}
@Override public void writeBeginning(final PrintStream out) {
List<String> binPaths = Fp.map(new Map1<File,String>(){
public String apply(File a) { return "\"" + a.getAbsolutePath() + "\""; }},
framework.binaries);
out.println(new Utils.Substituter(
"#public " + className + "(" + JObjCRuntime.class.getName() + " runtime) {~" +
"##super(runtime, new String[]{" + Fp.join(", ", binPaths) + "});~" +
"#}~"
));
}
@Override public void writeBody(final PrintStream out) {
for(final Struct struct : new ArrayList<Struct>(framework.structs)){
out.println("\tpublic " + struct.name + " make" + struct.name + "(){");
out.println("\t\treturn new " + struct.name + "(getRuntime());");
out.println("\t}");
out.println("\tpublic " + struct.name + " make" + struct.name + "(com.apple.jobjc.NativeBuffer base){");
out.println("\t\treturn new " + struct.name + "(getRuntime(), base);");
out.println("\t}");
}
for(final NativeEnum nenum : framework.enums){
if(nenum.ignore){
out.println("\t/**");
out.println("\t * @deprecated Suggestion: " + nenum.suggestion);
out.println("\t */");
out.println("\t@Deprecated");
}
out.println(String.format("\tpublic final %3$s %1$s(){ return %2$s; }",
nenum.name, nenum.valueToString(), nenum.type.getJType().getJavaReturnTypeName()));
}
for(final Constant konst : framework.constants){
String cacheName = "_" + konst.name;
final JType jtype = konst.type.getJType();
final String cast = jtype.getReturnTypeCast() == null ? "" : "(" + jtype.getReturnTypeCast() + ")";
out.println();
out.print(new JLField("private", jtype.getJavaTypeName(), cacheName, jtype.getDefaultReturnValue()));
JLMethod reader = new JLMethod("public final", jtype.getJavaReturnTypeName(), konst.name);
reader.body.add("if(" + cacheName + " != " + jtype.getDefaultReturnValue() + ") return " + cast + cacheName + ";");
String contextName = jtype instanceof JStruct ? "returnValue" : "nativeBuffer";
if(jtype instanceof JStruct)
reader.body.add(((JStruct)jtype).createReturnValue());
else
reader.body.add(jtype.createDeclareBuffer(contextName));
reader.body.add("getConstant(\"" + konst.name + "\", " + contextName + ", " + jtype.getCoderDescriptor().getCoderInstanceName() + ".sizeof());");
reader.body.add(jtype.createPop(contextName));
reader.body.add(cacheName + " = returnValue;");
reader.body.add(jtype.createReturn());
out.print(reader);
}
for(final StringConstant konst : framework.stringConstants){
if(Fp.any(new Map1<Constant,Boolean>(){ public Boolean apply(Constant a) {
return a.name.equals(konst.name);
}}, new ArrayList<Constant>(framework.constants))){
System.out.println("Warning: [" + framework.name + "] String constant " + konst.name + " is already defined in constants. Skipping.");
}
else{
out.println("\tpublic final String " + konst.name + "(){ return \"" + escapeQuotes(konst.value) + "\"; }");
}
}
/**
* Order classes to get stable output
*/
TreeSet<Clazz> sortedClasses = new TreeSet<Clazz>(framework.classes);
for (final Clazz clazz : sortedClasses) {
final String classClassName = clazz.name + "Class";
out.println(JavaLang.makeSingleton("_" + classClassName, clazz.name, classClassName, "getRuntime()"));
}
for (final Category cat : framework.categories) {
final String classClassName = cat.category.name + "Class";
out.println(JavaLang.makeSingleton("_" + classClassName, cat.category.name, classClassName, "getRuntime()"));
JLMethod jlm = new JLMethod("public", cat.category.name, cat.category.name, "final " + cat.category.superClass.getFullPath() + " obj");
jlm.body.add(new JLReturn(new JLCall("new " + cat.category.name, "obj", "getRuntime()")));
out.println(jlm);
}
for (final Function fxn : framework.functions){
FunctionGenerator.writeOutFunction(out, FunCall.class, fxn, null);
}
}
private String escapeQuotes(String s){
return s.replace("\"", "\\\"");
}
}

View File

@ -1,78 +0,0 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.internal.jobjc.generator.classes;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
public class GeneratedClassFile extends OutputFile {
protected final String className;
protected final String genericArgs;
protected final String superClass;
public GeneratedClassFile(final String pkg, final String classname, final String superClass) {
this(pkg, classname, null, superClass);
}
public GeneratedClassFile(final String pkg, final String classname, final String genericArgs, final String superClass) {
super(pkg, classname + ".java");
this.className = classname;
this.genericArgs = genericArgs;
this.superClass = superClass;
}
@Override
public void write(final File parentDir) {
try {
final PrintStream out = open(parentDir);
out.println("package " + pkg + ";");
out.println();
out.print("public " + (isFinal() ? "final" : "") + " class " + className);
if(genericArgs != null) out.print("<" + genericArgs + ">");
if (superClass != null) out.print(" extends " + superClass);
out.println(" {");
writeBeginning(out);
writeBody(out);
writeEnd(out);
out.println("}");
close(out);
} catch (final IOException e) { throw new RuntimeException(e); }
}
public void writeBeginning(final PrintStream out) {
}
public void writeBody(final PrintStream out) {
}
public void writeEnd(final PrintStream out) {
}
protected boolean isFinal(){ return false; }
}

View File

@ -1,69 +0,0 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.internal.jobjc.generator.classes;
import java.io.PrintStream;
import java.util.HashSet;
import java.util.Set;
import com.apple.internal.jobjc.generator.ClassGenerator;
import com.apple.internal.jobjc.generator.FunctionGenerator;
import com.apple.internal.jobjc.generator.model.Clazz;
import com.apple.internal.jobjc.generator.model.Method;
import com.apple.jobjc.JObjCRuntime;
import com.apple.jobjc.Invoke.MsgSend;
public class JObjCClassClassFile extends AbstractObjCClassFile {
public JObjCClassClassFile(final Clazz clazz) {
super(clazz, clazz.name + "Class", clazz.superClass != null ? clazz.superClass.getFullPath() + "Class" : ClassGenerator.JOBJC_PACKAGE + ".NSClass<" + clazz.name + ">");
}
@Override public void writeBeginning(final PrintStream out) {
out.format(
"\tpublic %1$s(%2$s runtime) {\n" +
"\t\tsuper(runtime);\n" +
"\t}\n",
className, JObjCRuntime.class.getCanonicalName());
out.format(
"\tpublic %1$s(String name, %2$s runtime) {\n" +
"\t\tsuper(name, runtime);\n" +
"\t}\n",
className, JObjCRuntime.class.getCanonicalName());
out.format(
"\tpublic %1$s(long ptr, %2$s runtime) {\n" +
"\t\tsuper(ptr, runtime);\n" +
"\t}\n",
className, JObjCRuntime.class.getCanonicalName());
}
@Override public void writeBody(final PrintStream out) {
Set<String> written = new HashSet<String>();
for(final Method method : this.clazz.classMethods)
if(written.add(method.name))
FunctionGenerator.writeOutFunction(out, MsgSend.class, method, "this");
else
System.out.format("Duplicate method: %1$s %2$s -%3$s\n", clazz.parent.name, className, method.name);
}
}

View File

@ -1,81 +0,0 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.internal.jobjc.generator.classes;
import java.io.PrintStream;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import com.apple.internal.jobjc.generator.FunctionGenerator;
import com.apple.internal.jobjc.generator.model.Clazz;
import com.apple.internal.jobjc.generator.model.Method;
import com.apple.jobjc.JObjCRuntime;
import com.apple.jobjc.NativeObjectLifecycleManager;
import com.apple.jobjc.Invoke.MsgSend;
public class JObjCClassFile extends AbstractObjCClassFile {
public JObjCClassFile(final Clazz clazz) {
super(clazz, clazz.name,
clazz.superClass == null ? "com.apple.jobjc.ID"
: clazz.superClass.getFullPath());
}
private static Map<String, NativeObjectLifecycleManager> nolmForClass =
new TreeMap<String, NativeObjectLifecycleManager>();
static{
nolmForClass.put("NSAutoreleasePool", NativeObjectLifecycleManager.Nothing.INST);
}
@Override public void writeBeginning(final PrintStream out) {
out.format("\tpublic %1$s(final long objPtr, final %2$s runtime) {\n" +
"\t\tsuper(objPtr, runtime);\n" +
"\t}\n",
className, JObjCRuntime.class.getCanonicalName());
out.format("\tpublic %1$s(final %1$s obj, final %2$s runtime) {\n" +
"\t\tsuper(obj, runtime);\n" +
"\t}\n",
className, JObjCRuntime.class.getCanonicalName());
NativeObjectLifecycleManager nolm = nolmForClass.get(clazz.name);
if(nolm != null)
out.format("\t@Override\n"+
"\tprotected %1$s getNativeObjectLifecycleManager() {\n" +
"\t\treturn %2$s.INST;\n" +
"\t}\n",
NativeObjectLifecycleManager.class.getCanonicalName(), nolm.getClass().getCanonicalName());
}
@Override public void writeBody(final PrintStream out) {
Set<String> written = new HashSet<String>();
for(final Method method : this.clazz.instanceMethods)
if(written.add(method.name))
FunctionGenerator.writeOutFunction(out, MsgSend.class, method, "this");
else
System.out.format("Duplicate method: %1$s %2$s -%3$s\n", clazz.parent.name, className, method.name);
}
}

View File

@ -1,51 +0,0 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.internal.jobjc.generator.classes;
import java.io.PrintStream;
import java.util.Collection;
import com.apple.internal.jobjc.generator.ClassGenerator;
import com.apple.internal.jobjc.generator.model.coders.ComplexCoderDescriptor.MixedEncodingDescriptor;
import com.apple.jobjc.PrimitiveCoder;
public class MixedPrimitiveCoderClassFile extends GeneratedClassFile {
private static final String MULTI_CODER_CLASSNAME = "MixedPrimitiveCoder";
public static final String FULL_MULTI_CODER_CLASSNAME = ClassGenerator.JOBJC_PACKAGE + "." + MULTI_CODER_CLASSNAME;
final Collection<MixedEncodingDescriptor> coderDescs;
public MixedPrimitiveCoderClassFile(final Collection<MixedEncodingDescriptor> coderDescs) {
super(ClassGenerator.JOBJC_PACKAGE, MULTI_CODER_CLASSNAME, "java.lang.Object");
this.coderDescs = coderDescs;
}
@Override
public void writeBody(final PrintStream out) {
for (final MixedEncodingDescriptor desc : coderDescs) {
out.println("\tpublic static final " + PrimitiveCoder.class.getCanonicalName() + " " + desc.getMixedName() + " = " + desc.getDefinition() + ";");
}
}
}

View File

@ -1,53 +0,0 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.internal.jobjc.generator.classes;
import java.io.PrintStream;
import com.apple.internal.jobjc.generator.model.Opaque;
import com.apple.jobjc.Pointer;
public class OpaqueClassFile extends GeneratedClassFile {
final Opaque opaque;
public OpaqueClassFile(final Opaque opaque) {
super(opaque.parent.pkg, opaque.type.getJType().getJavaClassName(), com.apple.jobjc.Opaque.class.getCanonicalName());
this.opaque = opaque;
}
@Override public void writeBeginning(PrintStream out){
out.println("\t// " + opaque.type);
out.println("\t// " + opaque.type.getJType());
out.println("");
out.println("\tpublic " + className + "(" + Pointer.class.getName() + "<?> ptr){");
out.println("\t\tsuper(ptr);");
out.println("\t}");
out.println("");
out.println("\tpublic " + className + "(long ptr){");
out.println("\t\tsuper(ptr);");
out.println("\t}");
}
}

View File

@ -1,58 +0,0 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.internal.jobjc.generator.classes;
import java.io.*;
public abstract class OutputFile {
final String pkg;
final String fileName;
public OutputFile(final String pkg, final String filename) {
this.pkg = pkg;
this.fileName = filename;
}
public PrintStream open(final File parentDir) throws IOException {
final File pkgDir = new File(parentDir, pkg.replace('.', '/'));
pkgDir.mkdirs();
final File classFile = new File(pkgDir, fileName);
classFile.createNewFile();
return new PrintStream(classFile);
}
public void close(final PrintStream out) {
out.close();
}
public abstract void write(final File parentDir);
public boolean isClass(final Class<?> clazz) {
final String pkgName = clazz.getPackage().getName();
if (!pkgName.equals(pkg)) return false;
return fileName.contains(clazz.getSimpleName());
}
}

View File

@ -1,84 +0,0 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.apple.internal.jobjc.generator.classes;
import java.io.PrintStream;
import java.util.List;
import com.apple.internal.jobjc.generator.ClassGenerator;
import com.apple.internal.jobjc.generator.model.Framework;
import com.apple.internal.jobjc.generator.utils.JavaLang;
import com.apple.internal.jobjc.generator.utils.JavaLang.JLCtor;
import com.apple.internal.jobjc.generator.utils.JavaLang.JLField;
import com.apple.internal.jobjc.generator.utils.JavaLang.JLMethod;
import com.apple.jobjc.JObjCRuntime;
public class RootJObjCClass extends GeneratedClassFile {
private static final String JOBJC_CLASSNAME = "JObjC";
public static final String FULL_JOBJC_CLASSNAME = ClassGenerator.JOBJC_PACKAGE + "." + JOBJC_CLASSNAME;
public static final String JOBJC_RUNTIME_INST = FULL_JOBJC_CLASSNAME + ".getInstance()";
public static final String JOBJC_RUNTIME_INST_R = FULL_JOBJC_CLASSNAME + ".getInstance(getRuntime())";
public static final String runtimeFrameworkInst(String fwname){
return JOBJC_RUNTIME_INST + "." + fwname + "()";
}
public static final String runtimeFrameworkInstR(String fwname){
return JOBJC_RUNTIME_INST_R + "." + fwname + "()";
}
final List<Framework> frameworks;
public RootJObjCClass(final List<Framework> frameworks) {
super(ClassGenerator.JOBJC_PACKAGE, JOBJC_CLASSNAME, "java.lang.Object");
this.frameworks = frameworks;
}
@Override public void writeBeginning(final PrintStream out) {
out.print(new JLField("private static", JOBJC_CLASSNAME, "instance"));
out.print(new JLField("private final", JObjCRuntime.class.getName(), "runtime"));
JLMethod getInstR = new JLMethod("public static", JOBJC_CLASSNAME, "getInstance", "final JObjCRuntime runtime");
getInstR.body.add("if(runtime == null) throw new NullPointerException(\"runtime\");");
getInstR.body.add("if(instance == null) instance = new JObjC(runtime);");
getInstR.body.add("return instance;");
out.print(getInstR);
JLMethod getInst = new JLMethod("public static", JOBJC_CLASSNAME, "getInstance");
getInst.body.add("return getInstance(JObjCRuntime.getInstance());");
out.print(getInst);
JLCtor ctor = new JLCtor("private", JOBJC_CLASSNAME, "final JObjCRuntime runtime");
ctor.body.add("this.runtime = runtime;");
for (final Framework f : frameworks)
ctor.body.add("runtime.registerPackage(\"" + f.pkg + "\");");
out.print(ctor);
}
@Override public void writeBody(final PrintStream out) {
for (final Framework f : frameworks)
out.println(JavaLang.makeSingleton("_" + f.name, f.name, f.pkg + "." + f.name + "Framework", "runtime"));
}
}

Some files were not shown because too many files have changed in this diff Show More