public MetaClassRegistryImpl(final int loadDefault, final boolean useAccessible) { this.useAccessible = useAccessible; if (loadDefault == LOAD_DEFAULT) { Map<CachedClass, List<MetaMethod>> map = new HashMap<CachedClass, List<MetaMethod>>(); // let's register the default methods registerMethods(null, true, true, map); final Class[] additionals = DefaultGroovyMethods.additionals; for (int i = 0; i != additionals.length; ++i) { createMetaMethodFromClass(map, additionals[i]); } Class[] pluginDGMs = VMPluginFactory.getPlugin().getPluginDefaultGroovyMethods(); for (Class plugin : pluginDGMs) { registerMethods(plugin, false, true, map); } registerMethods(DefaultGroovyStaticMethods.class, false, false, map); Class[] staticPluginDGMs = VMPluginFactory.getPlugin().getPluginStaticGroovyMethods(); for (Class plugin : staticPluginDGMs) { registerMethods(plugin, false, false, map); } for (Map.Entry<CachedClass, List<MetaMethod>> e : map.entrySet()) { CachedClass cls = e.getKey(); cls.setNewMopMethods(e.getValue()); } } installMetaClassCreationHandle(); final MetaClass emcMetaClass = metaClassCreationHandle.create(ExpandoMetaClass.class, this); emcMetaClass.initialize(); ClassInfo.getClassInfo(ExpandoMetaClass.class).setStrongMetaClass(emcMetaClass); addMetaClassRegistryChangeEventListener( new MetaClassRegistryChangeEventListener() { public void updateConstantMetaClass(MetaClassRegistryChangeEvent cmcu) { synchronized (metaClassInfo) { metaClassInfo.add(cmcu.getNewMetaClass()); DefaultMetaClassInfo.getNewConstantMetaClassVersioning(); Class c = cmcu.getClassToUpdate(); DefaultMetaClassInfo.setPrimitiveMeta(c, cmcu.getNewMetaClass() == null); Field sdyn; try { sdyn = c.getDeclaredField(Verifier.STATIC_METACLASS_BOOL); sdyn.setBoolean(null, cmcu.getNewMetaClass() != null); } catch (Throwable e) { // DO NOTHING } } } }); }
public MetaMethodIndex(CachedClass theCachedClass) { init(DEFAULT_CAPACITY); CachedClass last = null; if (!theCachedClass.isInterface()) { for (CachedClass c = theCachedClass; c != null; c = c.getCachedSuperClass()) { final SingleKeyHashMap.Entry e = methodHeaders.getOrPut(c.getTheClass()); e.value = new Header(c.getTheClass(), last == null ? null : last.getTheClass()); last = c; } } else { final SingleKeyHashMap.Entry e = methodHeaders.getOrPut(Object.class); e.value = new Header(Object.class, theCachedClass.getTheClass()); } }
public Object addMethodToList(Object o, MetaMethod method) { if (o == null) { return method; } if (o instanceof MetaMethod) { MetaMethod match = (MetaMethod) o; if (!isMatchingMethod(match, method)) { FastArray list = new FastArray(2); list.add(match); list.add(method); return list; } else { if (match.isPrivate() || (!isNonRealMethod(match) && match.getDeclaringClass().isInterface() && !method.getDeclaringClass().isInterface())) { // do not overwrite interface methods with instance methods // do not overwrite private methods // Note: private methods from parent classes are not shown here, // but when doing the multimethod connection step, we overwrite // methods of the parent class with methods of a subclass and // in that case we want to keep the private methods } else { CachedClass methodC = method.getDeclaringClass(); CachedClass matchC = match.getDeclaringClass(); if (methodC == matchC) { if (isNonRealMethod(method)) { return method; } } else if (!methodC.isAssignableFrom(matchC.getTheClass())) { return method; } } } return o; } if (o instanceof FastArray) { FastArray list = (FastArray) o; int found = findMatchingMethod(list, method); if (found == -1) { list.add(method); } else { MetaMethod match = (MetaMethod) list.get(found); if (match == method) return o; if (match.isPrivate() || (!isNonRealMethod(match) && match.getDeclaringClass().isInterface() && !method.getDeclaringClass().isInterface())) { // do not overwrite interface methods with instance methods // do not overwrite private methods // Note: private methods from parent classes are not shown here, // but when doing the multimethod connection step, we overwrite // methods of the parent class with methods of a subclass and // in that case we want to keep the private methods } else { CachedClass methodC = method.getDeclaringClass(); CachedClass matchC = match.getDeclaringClass(); if (methodC == matchC) { if (isNonRealMethod(method)) { list.set(found, method); } } else if (!methodC.isAssignableFrom(matchC.getTheClass())) { list.set(found, method); } } } } return o; }