private static MethodAnalysisResults analyzeLambda(MetamodelUtil metamodel, ClassLoader alternateClassLoader, boolean isObjectEqualsSafe, boolean isAllEqualsSafe, boolean isCollectionContainsSafe, String className, String methodName, String methodSignature) throws IOException, AnalyzerException { // Open up the corresponding class to analyze PathAnalysisFactory pathAnalysisFactory = new PathAnalysisFactory( metamodel.getMethodChecker(isObjectEqualsSafe, isAllEqualsSafe, isCollectionContainsSafe)); TransformationClassAnalyzer classAnalyzer = new TransformationClassAnalyzer(className, alternateClassLoader); MethodAnalysisResults analysis = classAnalyzer.analyzeLambdaMethod(methodName, methodSignature, pathAnalysisFactory); PathAnalysisSimplifier.cleanAndSimplify(analysis, metamodel.getComparisonMethods(isObjectEqualsSafe), metamodel.getComparisonStaticMethods(isObjectEqualsSafe), isAllEqualsSafe); return analysis; }
public <T, U> U analyzeLambdaMethod(String methodName, String methodSignature, PathAnalysisSupplementalFactory<T, U> pathAnalysisFactory) throws AnalyzerException { MethodNode specificMethod = null; for (MethodNode m: (List<MethodNode>)cl.methods) { if (!m.name.equals(methodName) || !m.desc.equals(methodSignature)) continue; specificMethod = m; } if (specificMethod != null) return analyzeMethod(specificMethod, pathAnalysisFactory); return null; }
boolean hasLoops(CFG cfg, int[]visitStatus, int index) { final int VISITING = 1; final int VISITED = 2; // reached an instruction with no successor (probably a return instruction) if (cfg.succsOf(index) == null) return false; // Check if we've visited the node and finished exploring all sub-branches if (visitStatus[index] == VISITED) return false; // Check if we've looped back to visit a node we haven't finished exploring if (visitStatus[index] == VISITING) return true; // Mark node as being explored visitStatus[index] = VISITING; // Visit successors of this node and see if we loop back for (int succ: cfg.succsOf(index)) if (hasLoops(cfg, visitStatus, succ)) return true; // Mark this node as having been explored successfully visitStatus[index] = VISITED; return false; } }
private static MethodAnalysisResults analyzeLambda(MetamodelUtil metamodel, String className, String methodName, String methodSignature) { try { // Open up the corresponding class to analyze PathAnalysisFactory pathAnalysisFactory = new PathAnalysisFactory( new MethodChecker(metamodel)); TransformationClassAnalyzer classAnalyzer = new TransformationClassAnalyzer(className); MethodAnalysisResults analysis = classAnalyzer.analyzeLambdaMethod(methodName, methodSignature, pathAnalysisFactory); PathAnalysisSimplifier.cleanAndSimplify(analysis, Collections.emptyMap(), Collections.emptyMap(), false); return analysis; } catch (IOException e) { e.printStackTrace(); return null; } catch (AnalyzerException e) { e.printStackTrace(); return null; } }
U analysis = analyzeMethod(specificMethod, pathAnalysisFactory); if (analysis != null)
if (hasLoops(cfg, visitStatus, 0)) return null;
private static MethodAnalysisResults analyzeLambdaClass(Class<?> lambdaClass, MetamodelUtil metamodel, LambdaAsClassAnalysisConfig lambdaAsClass, ClassLoader alternateClassLoader, boolean isObjectEqualsSafe, boolean isAllEqualsSafe, boolean isCollectionContainsSafe) throws IOException, AnalyzerException { // Open up the corresponding class to analyze TransformationClassAnalyzer classAnalyzer = new TransformationClassAnalyzer(lambdaClass.getName(), alternateClassLoader); Method matchingMethod = lambdaAsClass.findLambdaMethod(lambdaClass); if (matchingMethod == null) throw new AnalyzerException(null, "Could not find a lambda method with the expected name in the class"); PathAnalysisFactory pathAnalysisFactory = new PathAnalysisFactory( metamodel.getMethodChecker(isObjectEqualsSafe, isAllEqualsSafe, isCollectionContainsSafe)); MethodAnalysisResults analysis = classAnalyzer.analyzeLambdaMethod(matchingMethod.getName(), Type.getMethodDescriptor(matchingMethod), pathAnalysisFactory); PathAnalysisSimplifier.cleanAndSimplify(analysis, metamodel.getComparisonMethods(isObjectEqualsSafe), metamodel.getComparisonStaticMethods(isObjectEqualsSafe), isAllEqualsSafe); return analysis; }
throw new IllegalArgumentException("Expecting a constructor method for a lambda"); TransformationClassAnalyzer classAnalyzer = new TransformationClassAnalyzer(sig.owner, alternateClassLoader); PathAnalysisFactory pathAnalysisFactory = new PathAnalysisFactory( metamodel.getMethodChecker(isObjectEqualsSafe, isAllEqualsSafe, isCollectionContainsSafe)); MethodAnalysisResults analysis = classAnalyzer.analyzeLambdaMethod(sig.name, sig.desc, pathAnalysisFactory); if (analysis == null) throw new QueryTransformException("Symbolic execution of constructor failed"); if (analysis.paths.size() != 1) throw new QueryTransformException("Symbolic execution of constructor failed");
@Override public void checkLambdaSideEffects(LambdaAnalysis lambda) throws QueryTransformException { for (PathAnalysis path: lambda.symbolicAnalysis.paths) { for (MethodSideEffect effect: path.getSideEffects()) { if (effect instanceof MethodSideEffectCall) { MethodSideEffectCall call = (MethodSideEffectCall)effect; if (!call.m.name.equals("<init>")) throw new QueryTransformException("Lambda has a side-effect that can't be emulated with a database query"); try { TransformationClassAnalyzer classAnalyzer = new TransformationClassAnalyzer(call.m.owner, alternateClassLoader); PathAnalysisFactory pathAnalysisFactory = new PathAnalysisFactory( metamodel.getMethodChecker(isObjectEqualsSafe, isAllEqualsSafe, isCollectionContainsSafe)); MethodAnalysisResults analysis = classAnalyzer.analyzeLambdaMethod(call.m.name, call.m.desc, pathAnalysisFactory); analyzeConstructor(analysis); continue; } catch (AnalyzerException | IOException e) { throw new QueryTransformException("Could not analyze the side-effects of the lambda to check for safety", e); } } throw new QueryTransformException("Lambda has a side-effect that can't be emulated with a database query"); } } } }
private static MethodAnalysisResults analyzeLambda(MetamodelUtil metamodel, String className, String methodName, String methodSignature) { try { // Open up the corresponding class to analyze PathAnalysisFactory pathAnalysisFactory = new PathAnalysisFactory( new MethodChecker(metamodel)); TransformationClassAnalyzer classAnalyzer = new TransformationClassAnalyzer(className); MethodAnalysisResults analysis = classAnalyzer.analyzeLambdaMethod(methodName, methodSignature, pathAnalysisFactory); PathAnalysisSimplifier.cleanAndSimplify(analysis, Collections.emptyMap(), Collections.emptyMap(), false); return analysis; } catch (IOException e) { e.printStackTrace(); return null; } catch (AnalyzerException e) { e.printStackTrace(); return null; } }