/** * Given an abstract dispatch to an object of type c and a method m, gives a list of possible * receiver methods. */ public List resolveAbstractDispatch(SootClass c, SootMethod m) { c.checkLevel(SootClass.HIERARCHY); m.getDeclaringClass().checkLevel(SootClass.HIERARCHY); checkState(); Iterator<SootClass> classesIt = null; if (c.isInterface()) { classesIt = getImplementersOf(c).iterator(); HashSet<SootClass> classes = new HashSet<SootClass>(); while (classesIt.hasNext()) classes.addAll(getSubclassesOfIncluding(classesIt.next())); classesIt = classes.iterator(); } else classesIt = getSubclassesOfIncluding(c).iterator(); ArraySet s = new ArraySet(); while (classesIt.hasNext()) { SootClass cl = classesIt.next(); if (Modifier.isAbstract(cl.getModifiers())) continue; s.add(resolveConcreteDispatch(cl, m)); } List l = new ArrayList(); l.addAll(s); return Collections.unmodifiableList(l); }
private <T> CachedRuleSource doExtract(final Class<T> source) { final ModelType<T> type = ModelType.of(source); DefaultMethodModelRuleExtractionContext context = new DefaultMethodModelRuleExtractionContext(type, this); // TODO - exceptions thrown here should point to some extensive documentation on the concept of // class rule sources StructSchema<T> schema = getSchema(source, context); if (schema == null) { throw new InvalidModelRuleDeclarationException(context.problems.format()); } // sort for determinism Set<Method> methods = new TreeSet<Method>(Ordering.usingToString()); methods.addAll(Arrays.asList(source.getDeclaredMethods())); ImmutableList.Builder<ModelProperty<?>> implicitInputs = ImmutableList.builder(); ModelProperty<?> target = null; for (ModelProperty<?> property : schema.getProperties()) { if (property.isAnnotationPresent(RuleTarget.class)) { target = property; } else if (property.isAnnotationPresent(RuleInput.class) && !(property.getSchema() instanceof ScalarValueSchema)) { implicitInputs.add(property); } for (WeaklyTypeReferencingMethod<?, ?> method : property.getAccessors()) { methods.remove(method.getMethod()); } } ImmutableList.Builder<ExtractedRuleDetails> rules = ImmutableList.builder(); for (Method method : methods) { MethodRuleDefinition<?, ?> ruleDefinition = DefaultMethodRuleDefinition.create(source, method); ExtractedModelRule rule = getMethodHandler(ruleDefinition, method, context); if (rule != null) { rules.add(new ExtractedRuleDetails(ruleDefinition, rule)); } } if (context.hasProblems()) { throw new InvalidModelRuleDeclarationException(context.problems.format()); } StructBindings<T> bindings = structBindingsStore.getBindings(schema); if (schema.getProperties().isEmpty()) { return new StatelessRuleSource( rules.build(), Modifier.isAbstract(source.getModifiers()) ? new AbstractRuleSourceFactory<T>(schema, bindings, proxyFactory) : new ConcreteRuleSourceFactory<T>(type)); } else { return new ParameterizedRuleSource( rules.build(), target, implicitInputs.build(), schema, bindings, proxyFactory); } }
private void validateRuleMethod( MethodRuleDefinition<?, ?> ruleDefinition, Method ruleMethod, ValidationProblemCollector problems) { if (Modifier.isPrivate(ruleMethod.getModifiers())) { problems.add(ruleMethod, "A rule method cannot be private"); } if (Modifier.isAbstract(ruleMethod.getModifiers())) { problems.add(ruleMethod, "A rule method cannot be abstract"); } if (ruleMethod.getTypeParameters().length > 0) { problems.add(ruleMethod, "Cannot have type variables (i.e. cannot be a generic method)"); } // TODO validations on method: synthetic, bridge methods, varargs, abstract, native ModelType<?> returnType = ModelType.returnType(ruleMethod); if (returnType.isRawClassOfParameterizedType()) { problems.add( ruleMethod, "Raw type " + returnType + " used for return type (all type parameters must be specified of parameterized type)"); } for (int i = 0; i < ruleDefinition.getReferences().size(); i++) { ModelReference<?> reference = ruleDefinition.getReferences().get(i); if (reference.getType().isRawClassOfParameterizedType()) { problems.add( ruleMethod, "Raw type " + reference.getType() + " used for parameter " + (i + 1) + " (all type parameters must be specified of parameterized type)"); } if (reference.getPath() != null) { try { ModelPath.validatePath(reference.getPath().toString()); } catch (Exception e) { problems.add( ruleDefinition, "The declared model element path '" + reference.getPath() + "' used for parameter " + (i + 1) + " is not a valid path", e); } } } }
/** * Checks that a callback method is present and correctly defined. * * <p>Having checked it, you can call it using callback(). * * @param sCallback Name of callback method * @throws OmDeveloperException If the method doesn't exist or is defined incorrectly */ public void checkCallback(String sCallback) throws OmDeveloperException { try { Method m = getClass().getMethod(sCallback, new Class[0]); if (m.getReturnType() != void.class) throw new OmDeveloperException("Callback method " + sCallback + "() must return void"); if (!Modifier.isPublic(m.getModifiers())) throw new OmDeveloperException("Callback method " + sCallback + "() must be public"); if (Modifier.isStatic(m.getModifiers())) throw new OmDeveloperException("Callback method " + sCallback + "() may not be static"); if (Modifier.isAbstract(m.getModifiers())) throw new OmDeveloperException("Callback method " + sCallback + "() may not be abstract"); sCheckedCallbacks.add(sCallback); } catch (NoSuchMethodException e) { throw new OmDeveloperException("Callback method " + sCallback + "() does not exist"); } }
/** * Checks if a class fulfills the JavaBeans contract. * * @param cls the class to check */ public static void checkJavaBean(Class<?> cls) { try { Constructor<?> constructor = cls.getDeclaredConstructor(); int classModifiers = cls.getModifiers(); if (Modifier.isInterface(classModifiers)) throw new RuntimeException(cls.getName() + " is an interface"); if (Modifier.isAbstract(classModifiers)) throw new RuntimeException( cls.getName() + " cannot be instantiated - it is an abstract class"); int modifiers = constructor.getModifiers(); if (!Modifier.isPublic(modifiers)) throw new RuntimeException("No public default constructor in " + cls); } catch (NoSuchMethodException e) { throw new RuntimeException("No default constructor in class " + cls); } catch (SecurityException e) { logger.error( "I am not allowed to check the class by using reflection, " + "so I just can hope the class is alright and go on: ", e); } }
public static void main(String[] args) throws Exception { System.out.println( "Checking that all known MBeans that are " + "NotificationBroadcasters have sane " + "MBeanInfo.getNotifications()"); System.out.println("Checking platform MBeans..."); checkPlatformMBeans(); URL codeBase = ClassLoader.getSystemResource("javax/management/MBeanServer.class"); if (codeBase == null) { throw new Exception("Could not determine codeBase for " + MBeanServer.class); } System.out.println(); System.out.println("Looking for standard MBeans..."); String[] classes = findStandardMBeans(codeBase); System.out.println("Testing standard MBeans..."); for (int i = 0; i < classes.length; i++) { String name = classes[i]; Class<?> c; try { c = Class.forName(name); } catch (Throwable e) { System.out.println(name + ": cannot load (not public?): " + e); continue; } if (!NotificationBroadcaster.class.isAssignableFrom(c)) { System.out.println(name + ": not a NotificationBroadcaster"); continue; } if (Modifier.isAbstract(c.getModifiers())) { System.out.println(name + ": abstract class"); continue; } NotificationBroadcaster mbean; Constructor<?> constr; try { constr = c.getConstructor(); } catch (Exception e) { System.out.println(name + ": no public no-arg constructor: " + e); continue; } try { mbean = (NotificationBroadcaster) constr.newInstance(); } catch (Exception e) { System.out.println(name + ": no-arg constructor failed: " + e); continue; } check(mbean); } System.out.println(); System.out.println("Testing some explicit cases..."); check(new RelationService(false)); /* We can't do this: check(new RequiredModelMBean()); because the Model MBean spec more or less forces us to use the names GENERIC and ATTRIBUTE_CHANGE for its standard notifs. */ checkRMIConnectorServer(); System.out.println(); if (!suspicious.isEmpty()) System.out.println("SUSPICIOUS CLASSES: " + suspicious); if (failed.isEmpty()) System.out.println("TEST PASSED"); else { System.out.println("TEST FAILED: " + failed); System.exit(1); } }
public void printTo(SootClass cl, PrintWriter out) { // add jimple line number tags setJimpleLnNum(1); // Print class name + modifiers { StringTokenizer st = new StringTokenizer(Modifier.toString(cl.getModifiers())); while (st.hasMoreTokens()) { String tok = (String) st.nextToken(); if (cl.isInterface() && tok.equals("abstract")) continue; out.print(tok + " "); } String classPrefix = ""; if (!cl.isInterface()) { classPrefix = classPrefix + " class"; classPrefix = classPrefix.trim(); } out.print(classPrefix + " " + Scene.v().quotedNameOf(cl.getName()) + ""); } // Print extension { if (cl.hasSuperclass()) out.print(" extends " + Scene.v().quotedNameOf(cl.getSuperclass().getName()) + ""); } // Print interfaces { Iterator interfaceIt = cl.getInterfaces().iterator(); if (interfaceIt.hasNext()) { out.print(" implements "); out.print("" + Scene.v().quotedNameOf(((SootClass) interfaceIt.next()).getName()) + ""); while (interfaceIt.hasNext()) { out.print(","); out.print(" " + Scene.v().quotedNameOf(((SootClass) interfaceIt.next()).getName()) + ""); } } } out.println(); incJimpleLnNum(); /* if (!addJimpleLn()) { Iterator clTagsIt = cl.getTags().iterator(); while (clTagsIt.hasNext()) { final Tag t = (Tag)clTagsIt.next(); out.println(t); } }*/ out.println("{"); incJimpleLnNum(); if (Options.v().print_tags_in_output()) { Iterator cTagIterator = cl.getTags().iterator(); while (cTagIterator.hasNext()) { Tag t = (Tag) cTagIterator.next(); out.print("/*"); out.print(t.toString()); out.println("*/"); } } // Print fields { Iterator fieldIt = cl.getFields().iterator(); if (fieldIt.hasNext()) { while (fieldIt.hasNext()) { SootField f = (SootField) fieldIt.next(); if (f.isPhantom()) continue; if (Options.v().print_tags_in_output()) { Iterator fTagIterator = f.getTags().iterator(); while (fTagIterator.hasNext()) { Tag t = (Tag) fTagIterator.next(); out.print("/*"); out.print(t.toString()); out.println("*/"); } } out.println(" " + f.getDeclaration() + ";"); if (addJimpleLn()) { setJimpleLnNum(addJimpleLnTags(getJimpleLnNum(), f)); } // incJimpleLnNum(); } } } // Print methods { Iterator methodIt = cl.methodIterator(); if (methodIt.hasNext()) { if (cl.getMethodCount() != 0) { out.println(); incJimpleLnNum(); } while (methodIt.hasNext()) { SootMethod method = (SootMethod) methodIt.next(); if (method.isPhantom()) continue; if (!Modifier.isAbstract(method.getModifiers()) && !Modifier.isNative(method.getModifiers())) { if (!method.hasActiveBody()) throw new RuntimeException("method " + method.getName() + " has no active body!"); else if (Options.v().print_tags_in_output()) { Iterator mTagIterator = method.getTags().iterator(); while (mTagIterator.hasNext()) { Tag t = (Tag) mTagIterator.next(); out.print("/*"); out.print(t.toString()); out.println("*/"); } } printTo(method.getActiveBody(), out); if (methodIt.hasNext()) { out.println(); incJimpleLnNum(); } } else { if (Options.v().print_tags_in_output()) { Iterator mTagIterator = method.getTags().iterator(); while (mTagIterator.hasNext()) { Tag t = (Tag) mTagIterator.next(); out.print("/*"); out.print(t.toString()); out.println("*/"); } } out.print(" "); out.print(method.getDeclaration()); out.println(";"); incJimpleLnNum(); if (methodIt.hasNext()) { out.println(); incJimpleLnNum(); } } } } } out.println("}"); incJimpleLnNum(); }
protected void loadHttpServlet(final AnyValue conf, final ClassFilter<? extends Servlet> filter) throws Exception { final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null; final String prefix = conf == null ? "" : conf.getValue("path", ""); final String threadName = "[" + Thread.currentThread().getName() + "] "; List<FilterEntry<? extends Servlet>> list = new ArrayList(filter.getFilterEntrys()); list.sort( (FilterEntry<? extends Servlet> o1, FilterEntry<? extends Servlet> o2) -> { // 必须保证WebSocketServlet优先加载, 因为要确保其他的HttpServlet可以注入本地模式的WebSocketNode boolean ws1 = WebSocketServlet.class.isAssignableFrom(o1.getType()); boolean ws2 = WebSocketServlet.class.isAssignableFrom(o2.getType()); if (ws1 == ws2) return o1.getType().getName().compareTo(o2.getType().getName()); return ws1 ? -1 : 1; }); final List<AbstractMap.SimpleEntry<String, String[]>> ss = sb == null ? null : new ArrayList<>(); for (FilterEntry<? extends Servlet> en : list) { Class<HttpServlet> clazz = (Class<HttpServlet>) en.getType(); if (Modifier.isAbstract(clazz.getModifiers())) continue; WebServlet ws = clazz.getAnnotation(WebServlet.class); if (ws == null || ws.value().length == 0) continue; final HttpServlet servlet = clazz.newInstance(); resourceFactory.inject(servlet, this); final String[] mappings = ws.value(); String pref = ws.repair() ? prefix : ""; DefaultAnyValue servletConf = (DefaultAnyValue) en.getProperty(); WebInitParam[] webparams = ws.initParams(); if (webparams.length > 0) { if (servletConf == null) servletConf = new DefaultAnyValue(); for (WebInitParam webparam : webparams) { servletConf.addValue(webparam.name(), webparam.value()); } } this.httpServer.addHttpServlet(servlet, pref, servletConf, mappings); if (ss != null) { for (int i = 0; i < mappings.length; i++) { mappings[i] = pref + mappings[i]; } ss.add(new AbstractMap.SimpleEntry<>(clazz.getName(), mappings)); } } if (ss != null) { Collections.sort( ss, (AbstractMap.SimpleEntry<String, String[]> o1, AbstractMap.SimpleEntry<String, String[]> o2) -> o1.getKey().compareTo(o2.getKey())); int max = 0; for (AbstractMap.SimpleEntry<String, String[]> as : ss) { if (as.getKey().length() > max) max = as.getKey().length(); } for (AbstractMap.SimpleEntry<String, String[]> as : ss) { sb.append(threadName).append(" Loaded ").append(as.getKey()); for (int i = 0; i < max - as.getKey().length(); i++) { sb.append(' '); } sb.append(" mapping to ").append(Arrays.toString(as.getValue())).append(LINE_SEPARATOR); } } if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString()); }
public static byte[] createAdapterCode( ObjToIntMap functionNames, String adapterName, Class<?> superClass, Class<?>[] interfaces, String scriptClassName) { ClassFileWriter cfw = new ClassFileWriter(adapterName, superClass.getName(), "<adapter>"); cfw.addField( "factory", "Laurora/javascript/ContextFactory;", (short) (ClassFileWriter.ACC_PUBLIC | ClassFileWriter.ACC_FINAL)); cfw.addField( "delegee", "Laurora/javascript/Scriptable;", (short) (ClassFileWriter.ACC_PUBLIC | ClassFileWriter.ACC_FINAL)); cfw.addField( "self", "Laurora/javascript/Scriptable;", (short) (ClassFileWriter.ACC_PUBLIC | ClassFileWriter.ACC_FINAL)); int interfacesCount = interfaces == null ? 0 : interfaces.length; for (int i = 0; i < interfacesCount; i++) { if (interfaces[i] != null) cfw.addInterface(interfaces[i].getName()); } String superName = superClass.getName().replace('.', '/'); Constructor<?>[] ctors = superClass.getConstructors(); for (Constructor<?> ctor : ctors) { generateCtor(cfw, adapterName, superName, ctor); } generateSerialCtor(cfw, adapterName, superName); if (scriptClassName != null) { generateEmptyCtor(cfw, adapterName, superName, scriptClassName); } ObjToIntMap generatedOverrides = new ObjToIntMap(); ObjToIntMap generatedMethods = new ObjToIntMap(); // generate methods to satisfy all specified interfaces. for (int i = 0; i < interfacesCount; i++) { Method[] methods = interfaces[i].getMethods(); for (int j = 0; j < methods.length; j++) { Method method = methods[j]; int mods = method.getModifiers(); if (Modifier.isStatic(mods) || Modifier.isFinal(mods)) { continue; } String methodName = method.getName(); Class<?>[] argTypes = method.getParameterTypes(); if (!functionNames.has(methodName)) { try { superClass.getMethod(methodName, argTypes); // The class we're extending implements this method and // the JavaScript object doesn't have an override. See // bug 61226. continue; } catch (NoSuchMethodException e) { // Not implemented by superclass; fall through } } // make sure to generate only one instance of a particular // method/signature. String methodSignature = getMethodSignature(method, argTypes); String methodKey = methodName + methodSignature; if (!generatedOverrides.has(methodKey)) { generateMethod(cfw, adapterName, methodName, argTypes, method.getReturnType(), true); generatedOverrides.put(methodKey, 0); generatedMethods.put(methodName, 0); } } } // Now, go through the superclass's methods, checking for abstract // methods or additional methods to override. // generate any additional overrides that the object might contain. Method[] methods = getOverridableMethods(superClass); for (int j = 0; j < methods.length; j++) { Method method = methods[j]; int mods = method.getModifiers(); // if a method is marked abstract, must implement it or the // resulting class won't be instantiable. otherwise, if the object // has a property of the same name, then an override is intended. boolean isAbstractMethod = Modifier.isAbstract(mods); String methodName = method.getName(); if (isAbstractMethod || functionNames.has(methodName)) { // make sure to generate only one instance of a particular // method/signature. Class<?>[] argTypes = method.getParameterTypes(); String methodSignature = getMethodSignature(method, argTypes); String methodKey = methodName + methodSignature; if (!generatedOverrides.has(methodKey)) { generateMethod(cfw, adapterName, methodName, argTypes, method.getReturnType(), true); generatedOverrides.put(methodKey, 0); generatedMethods.put(methodName, 0); // if a method was overridden, generate a "super$method" // which lets the delegate call the superclass' version. if (!isAbstractMethod) { generateSuper( cfw, adapterName, superName, methodName, methodSignature, argTypes, method.getReturnType()); } } } } // Generate Java methods for remaining properties that are not // overrides. ObjToIntMap.Iterator iter = new ObjToIntMap.Iterator(functionNames); for (iter.start(); !iter.done(); iter.next()) { String functionName = (String) iter.getKey(); if (generatedMethods.has(functionName)) continue; int length = iter.getValue(); Class<?>[] parms = new Class[length]; for (int k = 0; k < length; k++) parms[k] = ScriptRuntime.ObjectClass; generateMethod(cfw, adapterName, functionName, parms, ScriptRuntime.ObjectClass, false); } return cfw.toByteArray(); }