1 /* 2 * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package com.apple.jobjc; 26 27 import java.lang.ref.WeakReference; 28 import java.lang.reflect.Constructor; 29 30 import javax.tools.annotation.GenerateNativeHeader; 31 32 /* No native methods here, but the constants are needed in the supporting JNI code */ 33 @GenerateNativeHeader 34 public class NSClass<T extends ID> extends ID { 35 /* No native methods here, but the constants are needed in the supporting JNI code */ 36 @GenerateNativeHeader 37 public static class NSClassNotFoundException extends RuntimeException{ 38 public NSClassNotFoundException(String m){ super(m); } 39 public NSClassNotFoundException(String m, Throwable cause){ super(m, cause); } 40 } 41 42 static native long getNativeClassByName(String name); 43 static native long getSuperClassOfClass(long classPtr); 44 static native String getClassNameOfClass(long classPtr); 45 static native long getClass(long objPtr); 46 47 public NSClass(final long ptr, final JObjCRuntime runtime) { 48 super(ptr, runtime); 49 } 50 51 public NSClass(final String name, final JObjCRuntime runtime) { 52 this(getNativeClassByName(name), runtime); 53 if(ptr == 0) throw new NSClassNotFoundException("NSClass pointer is 0. Found no class named " + name); 54 } 55 56 protected NSClass(final JObjCRuntime runtime){ 57 super(0, runtime); 58 final String sn = getClass().getSimpleName(); 59 final String name = sn.substring(0, sn.lastIndexOf("Class")); 60 ptr = getNativeClassByName(name); 61 if(ptr == 0) throw new NSClassNotFoundException("NSClass pointer is 0. Found no class named " + name); 62 } 63 64 NSClass<? super T> getSuperClass() { 65 return new NSClass<T>(getSuperClassOfClass(ptr), runtime); 66 } 67 68 String getClassName() { return getClassNameOfClass(ptr); } 69 70 @Override protected NativeObjectLifecycleManager getNativeObjectLifecycleManager() { 71 return NativeObjectLifecycleManager.Nothing.INST; 72 } 73 74 @Override public boolean equals(Object o){ 75 return (o instanceof NSClass) && (this.ptr == ((NSClass) o).ptr); 76 } 77 78 // 79 80 static <T extends NSClass> T getObjCClassFor(final JObjCRuntime runtime, final long clsPtr){ 81 if (clsPtr == 0) return null; 82 83 final WeakReference cachedObj = objectCache.get().get(clsPtr); 84 if(cachedObj != null && cachedObj.get() != null) return (T) cachedObj.get(); 85 86 final T newObj = (T) createNewObjCClassFor(runtime, clsPtr); 87 objectCache.get().put(clsPtr, new WeakReference(newObj)); 88 return newObj; 89 } 90 91 static <T extends NSClass> T createNewObjCClassFor(final JObjCRuntime runtime, final long clsPtr) { 92 final Constructor<T> ctor = getNSClassConstructorForClassPtr(runtime, clsPtr); 93 return (T) createNewObjCObjectForConstructor(ctor, clsPtr, runtime); 94 } 95 96 @SuppressWarnings("unchecked") 97 static <T extends NSClass> Constructor<T> getNSClassConstructorForClassPtr(final JObjCRuntime runtime, final long clazzPtr){ 98 final Class<T> clazz = getNSClassForClassPtr(runtime, clazzPtr); 99 Constructor<T> ctor; 100 try { 101 ctor = clazz.getDeclaredConstructor(CTOR_ARGS); 102 } catch (SecurityException e) { 103 throw new RuntimeException(e); 104 } catch (NoSuchMethodException e) { 105 throw new RuntimeException(e); 106 } 107 ctor.setAccessible(true); 108 return ctor; 109 } 110 111 @SuppressWarnings("unchecked") 112 static <T extends ID> Class<T> getNSClassForClassPtr(final JObjCRuntime runtime, final long clazzPtr){ 113 final String className = NSClass.getClassNameOfClass(clazzPtr); 114 final Class<T> clazz = (Class<T>) runtime.getClassForNativeClassName(className + "Class"); 115 if(clazz == null){ 116 final long superClazzPtr = NSClass.getSuperClassOfClass(clazzPtr); 117 if(superClazzPtr != 0) 118 return getNSClassForClassPtr(runtime, superClazzPtr); 119 } 120 return clazz; 121 } 122 }