package XAspectLanguage; import java.util.*; import java.util.jar.JarFile; import java.io.*; import edu.neu.ccs.demeter.aplib.*; import edu.neu.ccs.demeter.dj.ClassGraph; import edu.neu.ccs.demeter.*; public class SemanticChecker { public SemanticChecker() { super(); } public static SemanticChecker parse(java.io.Reader in) throws ParseException { return new Parser(in)._SemanticChecker(); } public static SemanticChecker parse(java.io.InputStream in) throws ParseException { return new Parser(in)._SemanticChecker(); } public static SemanticChecker parse(String s) { try { return parse(new java.io.StringReader(s)); } catch (ParseException e) { throw new RuntimeException(e.toString()); } } // the runtime class graph static ClassGraph runtimeCg; // the class graph defined by the input class dictionary static edu.neu.ccs.demeter.aplib.cd.ClassGraph inputCg; // a pointer to the traversal XAspects component SelectorL ta; // list containing error messages List errors; public void generate(ClassDictionaryL cda, SelectorL travA) { // create the runtime class graph runtimeCg = new ClassGraph(true, false); manuallyCreateClassGraph2(); // create the class graph for the input class dictionary inputCg = ClassGraph.fromString(cda.get_classdict().get_text().toString()); inputCg.normalize(); // assign the pointer to the provided traversal aspect component ta = travA; errors = new LinkedList(); } public List check() { // make some Traversal XAspects specific checks // i.e., make sure that "nodes" and regular expression declarations // utilize other declarations that are defined check_trav_nodesAndRegExp(); // check in all places for undefined classes // i.e., check used classes in class dictionary, strategy expressions, // and class list declarations checkForUndefinedClasses(); // verify that strategies represent legal paths checkTraversalPaths(); return errors; } private void check_trav_nodesAndRegExp() { // check that all used Strategy names in "nodes" node set decls are defined List usedNames = runtimeCg.gather(ta, "from XAspectLanguage.SelectorL via XAspectLanguage.GraphNodes to" + Main.FIdent); List defNames = runtimeCg.gather(ta, "from XAspectLanguage.SelectorL via XAspectLanguage.StrategyDef via XAspectLanguage.StrategyName to" + Main.FIdent); subset_test(usedNames, defNames); // check that regular expressions reference defined node sets List defNodeSetDecls = runtimeCg.gather(ta, "from XAspectLanguage.SelectorL bypassing XAspectLanguage.NodeSubsetExpression via XAspectLanguage.NodeSubsetName to" + Main.FIdent); List usedNodeSetDecls = runtimeCg.gather(ta, "from XAspectLanguage.SelectorL via XAspectLanguage.NodeSubsetExpression via XAspectLanguage.NodeSubsetName to" + Main.FIdent); subset_test(usedNodeSetDecls, defNodeSetDecls); } private void checkForUndefinedClasses() { // get a list of all used classes in input cd, and make sure each used class // is defined by the cd java.util.Collection c = inputCg.getNodes(); checkDefinesClass(c.iterator()); // NOTE: Commented out this check, the Traversal.compute(...) check takes care of this // check that all classes used in strategy expressions are defined //List usedClassNames = runtimeCg.gather(ta, "from SelectorL via StrategyExpression via ClassName to" + Main.FIdent); //checkDefinesClass(usedClassNames.iterator()); // check classes are all defined in class list node sets List usedClasses = runtimeCg.gather(ta, "from XAspectLanguage.SelectorL via XAspectLanguage.ClassNameSet to" + Main.FIdent); checkDefinesClass(usedClasses.iterator()); } private void subset_test(List used, List defined) { ListIterator usedIterator = used.listIterator(); while (usedIterator.hasNext()) { Ident next = (Ident) usedIterator.next(); if (!defined.contains(next)) { //System.out.println(next.toString() + " undefined."); errors.add(new String(next.toString() + " undefined.")); } } } private void checkTraversalPaths() { try { // gather a list of declared strategy expressions List test = runtimeCg.gather(ta, "from XAspectLanguage.SelectorL to XAspectLanguage.Strategy"); // for each strategy, try to compute a traversal given the input cd for (int i = 0; i < test.size(); i++) { Strategy strategy = (Strategy) test.get(i); Traversal.compute(strategy, inputCg); } } catch (TraversalException te) { // bad traversal path //System.out.println("Traversal Error: " + te.getMessage()); errors.add("Traversal Error: " + te.getMessage()); } catch (Exception e) { //System.out.println(e.getMessage()); errors.add(e.getMessage()); } } private void checkDefinesClass(Iterator iter) { while (iter.hasNext()) { Object next = iter.next(); if (!inputCg.definesClass(next.toString())) { //System.out.println(next.toString() + " undefined."); errors.add(next.toString() + " undefined."); } } } // this method has been inserted to manually create the // classgraph, since a .jar file is exported and // dj can't do it itself private void manuallyCreateClassGraph() { String classpath = System.getProperty("java.class.path"); String[] classpaths=classpath.split(File.pathSeparator); int last_slash = classpaths[0].lastIndexOf("\\"); String sg_path = classpaths[0].substring(0,last_slash)+"\\plugins\\XAspects\\XAspects.jar"; try { JarFile jf = new JarFile(new File(sg_path)); Enumeration enu = jf.entries(); while (enu.hasMoreElements()){ String entry = enu.nextElement().toString(); //if (entry.indexOf("sg")!=-1 && entry.indexOf("class")!=-1) { if (entry.indexOf("class") != -1) { entry = entry.replace('/', '.'); int last_dot = entry.lastIndexOf(".class"); entry = entry.substring(0, last_dot); Class cl = Class.forName(entry); runtimeCg.addClass(cl); } } } catch(Exception e) { System.out.println("open error"); } } // alternative method for manual ClassGraph creation private void manuallyCreateClassGraph2() { // list of classes Class[] classes={ASCII_UCodeESC_CharStream.class, AnyClass.class, AnyPart.class, AspectLanguage.class, AspectLanguage_List.class, BCompound.class, BinaryOp.class, Bypassing.class, ClassDict.class, ClassDictionaryL.class, ClassDictionaryName.class, ClassGlob.class, ClassGlobSet.class, ClassGlobSpec.class, ClassGlob_Commalist.class, ClassName.class, ClassNameExact.class, ClassNameGlob.class, ClassNameSet.class, ClassName_BCList.class, CollectVisitor.class, Complement.class, Constraint.class, CopyVisitor.class, DisplayVisitor.class, EdgeGlob.class, EqualVisitor.class, From.class, Glob.class, GlobSet.class, GlobSpec.class, GlobVisitor.class, Glob_Commalist.class, GraphNodeRegExp.class, GraphNodes.class, Intersect.class, Intersection.class, Join.class, Main.class, Merge.class, Name.class, NameBinding.class, NameBinding_Commalist.class, NameMap.class, NegativeConstraint.class, NodeSubsetDef.class, NodeSubsetDef_List.class, NodeSubsetExpression.class, NodeSubsetExpression_PCList.class, NodeSubsetName.class, Nonempty_AspectLanguage_List.class, Nonempty_ClassGlob_Commalist.class, Nonempty_ClassName_BCList.class, Nonempty_Glob_Commalist.class, Nonempty_Name.class, Nonempty_NameBinding_Commalist.class, Nonempty_NodeSubsetDef_List.class, Nonempty_NodeSubsetExpression_PCList.class, Nonempty_PathSegment_List.class, Nonempty_SGEdge_SList.class, Nonempty_StrategyDef_List.class, Nonempty_Strategy_Commalist.class, OneClassGlob.class, OneGlob.class, OnlyThrough.class, Operator.class, ParseException.class, Parser.class, ParserConstants.class, ParserTokenManager.class, PartGlob.class, PartName.class, PartNameExact.class, PartNameGlob.class, PathDirective.class, PathSegment.class, PathSegment_List.class, PositiveConstraint.class, PrintVisitor.class, SGEdge.class, SGEdge_SList.class, SelectorL.class, SelectorName.class, SemanticChecker.class, Simple.class, SimpleStrategy.class, SourceDirective.class, SourceGlob.class, SourceMarker.class, Strategy.class, StrategyCombination.class, StrategyDef.class, StrategyDef_List.class, StrategyExpression.class, StrategyGraph.class, StrategyName.class, StrategyReference.class, Strategy_Commalist.class, SubclassGlob.class, SubgraphVisitor.class, SuperclassGlob.class, SymbolicNameMap.class, SymbolicNameMapI.class, TargetDirective.class, TargetGlob.class, TargetMarker.class, Through.class, To.class, ToStop.class, Token.class, TokenMgrError.class, TraceVisitor.class, TraversalName.class, UCompound.class, UnaryOp.class, Union.class, UniversalVisitor.class, Via.class, WildCard.class, XAspectLanguage2.class, __Subtraversal.class, __V_ClassGlobSpec_addStrings.class, __V_ClassGlobSpec_map.class, __V_ClassGlobSpec_match.class, __V_ClassGlobSpec_toGlobSpec.class, __V_GlobSpec_collectClassGlobs.class, __V_GlobSpec_collectEdgeGlobs.class, __V_GlobSpec_collectGlobs.class, __V_GlobSpec_match.class, __V_GlobSpec_matchEdge.class, __V_NameMap_buildDict.class, __V_PathDirective_toGraph.class, __V_SGEdge_checkConstraint_Edge.class, __V_SGEdge_checkConstraint_Node.class, __V_Strategy_attachEnv.class }; // add each class to classgraph for (int i = 0; i < classes.length; ++i) runtimeCg.addClass(classes[i]); } void universal_trv0_bef(UniversalVisitor _v_) { ((UniversalVisitor) _v_).before(this); } void universal_trv0_aft(UniversalVisitor _v_) { ((UniversalVisitor) _v_).after(this); } void universal_trv0(UniversalVisitor _v_) { universal_trv0_bef(_v_); universal_trv0_aft(_v_); } }