001/* 002 * BridJ - Dynamic and blazing-fast native interop for Java. 003 * http://bridj.googlecode.com/ 004 * 005 * Copyright (c) 2010-2013, Olivier Chafik (http://ochafik.com/) 006 * All rights reserved. 007 * 008 * Redistribution and use in source and binary forms, with or without 009 * modification, are permitted provided that the following conditions are met: 010 * 011 * * Redistributions of source code must retain the above copyright 012 * notice, this list of conditions and the following disclaimer. 013 * * Redistributions in binary form must reproduce the above copyright 014 * notice, this list of conditions and the following disclaimer in the 015 * documentation and/or other materials provided with the distribution. 016 * * Neither the name of Olivier Chafik nor the 017 * names of its contributors may be used to endorse or promote products 018 * derived from this software without specific prior written permission. 019 * 020 * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY 021 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 022 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 023 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY 024 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 025 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 026 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 027 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 028 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 029 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 030 */ 031package org.bridj.cpp.mfc; 032 033import org.bridj.BridJ; 034import org.bridj.Callback; 035import org.bridj.NativeObject; 036import org.bridj.Pointer; 037import org.bridj.util.Utils; 038import org.bridj.cpp.CPPRuntime; 039 040import java.lang.reflect.Method; 041import java.lang.reflect.Type; 042import java.util.HashSet; 043import java.util.Map; 044import java.util.Set; 045 046/** 047 * 048 * @author Olivier 049 */ 050public class MFCRuntime extends CPPRuntime { 051 052 Method mfcGetMessageMap; 053 String mfcGetMessageMapMangling; 054 Callback mfcGetMessageMapCallback; 055 Set<Class<?>> hasMessageMap = new HashSet<Class<?>>(); 056 057 @Override 058 public <T extends NativeObject> Class<? extends T> getActualInstanceClass(Pointer<T> pInstance, Type officialType) { 059 Class officialTypeClass = Utils.getClass(officialType); 060 // For MFC classes, use GetRuntimeClass() 061 if (CObject.class.isAssignableFrom(officialTypeClass)) { 062 Pointer<CRuntimeClass> pClass = new CObject((Pointer) pInstance, this).GetRuntimeClass(); 063 if (pClass != null) { 064 CRuntimeClass rtc = pClass.get(); 065 try { 066 Class<? extends T> type = (Class) getMFCClass(rtc.m_lpszClassName()); 067 if (officialTypeClass == null || officialTypeClass.isAssignableFrom(type)) { 068 return type; 069 } 070 } catch (ClassNotFoundException ex) { 071 } 072 return officialTypeClass; 073 } 074 } 075 076 // TODO Auto-generated method stub 077 return super.getActualInstanceClass(pInstance, officialType); 078 } 079 080 private Class<?> getMFCClass(Pointer<Byte> mLpszClassName) throws ClassNotFoundException { 081 throw new ClassNotFoundException(mLpszClassName.getCString()); 082 } 083 084 public void getExtraFieldsOfNewClass(Class<?> type, Map<String, Type> out) { 085 //super.getExtraFieldsOfNewClass(type, out); 086 if (!hasMessageMap.contains(type)) { 087 return; 088 } 089 090 out.put("messageMap", Pointer.class); 091 } 092 093 public void getOverriddenVirtualMethods(Map<String, Pointer<?>> out) { 094 //super.getVirtualMethodBindings(out); 095 out.put("mfcGetMessageMap", Pointer.getPointer(mfcGetMessageMapCallback)); 096 } 097 098 @Override 099 public void register(Type type) { 100 super.register(type); 101 Class typeClass = Utils.getClass(type); 102 103 MessageMapBuilder map = new MessageMapBuilder(); 104 for (Method method : typeClass.getMethods()) { 105 106 OnCommand onCommand = method.getAnnotation(OnCommand.class); 107 if (onCommand != null) { 108 map.add(method, onCommand); 109 } 110 111 OnCommandEx onCommandEx = method.getAnnotation(OnCommandEx.class); 112 if (onCommandEx != null) { 113 map.add(method, onCommandEx); 114 } 115 116 OnUpdateCommand onUpdateCommand = method.getAnnotation(OnUpdateCommand.class); 117 if (onUpdateCommand != null) { 118 map.add(method, onUpdateCommand); 119 } 120 121 OnRegisteredMessage onRegisteredMessage = method.getAnnotation(OnRegisteredMessage.class); 122 if (onRegisteredMessage != null) { 123 map.add(method, onRegisteredMessage); 124 } 125 126 OnMessage onMessage = method.getAnnotation(OnMessage.class); 127 if (onMessage != null) { 128 map.add(method, onMessage); 129 } 130 } 131 if (!map.isEmpty()) { 132 map.register(this, typeClass); 133 } 134 135 } 136}