/* * 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 registeredPackages = new ArrayList(); @SuppressWarnings("unchecked") Class getClassForNativeClassName(final String className) { for (final String pkg : registeredPackages) { try { final Class clazz = Class.forName(pkg + "." + className); if (clazz != null) return (Class)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 clazz, Class clazzClazz) { return subclassing.registerUserClass(clazz, clazzClazz); } }