/** * This class is part of project that implements Aspectual Components * * Author: Predrag Petkovic, predrag@ccs.neu.edu * Northeastern University * * This class is responsible for translating an internal representation * of deployment file into the map. It checks all restriction that involve mapping. */ package edu.neu.ccs.aspects.map; import java.lang.reflect.*; import java.util.*; public class Mapper { public static Map getMap(ComponentMap componentMap) throws MappingException { MadeMap map = new MadeMap(){}; try { map.componentClass = Class.forName(componentMap.componentName); } catch (Exception e) { throw new MappingException("Can't find component class " + componentMap.componentName); } // Every field of the component represents a participant Field[] componentFields = map.componentClass.getFields(); Class[] participants = new Class[componentFields.length]; Hashtable participantName2participant = new Hashtable(); Hashtable participant2methods = new Hashtable(); // Get all participant classes and their methods for (int i = 0; i < participants.length; i++) { participants[i] = componentFields[i].getType(); participantName2participant.put(componentFields[i].getName(), participants[i]); Method[] methods = participants[i].getMethods(); participant2methods.put(participants[i], methods); } // Examine every participant map for (int i = 0; i < componentMap.participantMaps.size(); i++) { ParticipantMap participantMap = (ParticipantMap)componentMap.participantMaps.elementAt(i); String participantName = participantMap.participantName; // Check if participant in component map is present in the component Class participant = (Class) participantName2participant.get(participantName); if (participant == null) { throw new MappingException("There is no participant with name: " + participantName); } // Hash(expectedMethod, mappedMethod) Hashtable expectedMethods = new Hashtable(); Vector applicationClasses = new Vector(); // Examine every pair: (participant, application class) for (int j = 0; j < participantMap.applicationClassName.size(); j++) { String applicationClassName = (String)participantMap.applicationClassName.elementAt(j); Class applicationClass; // Check if there is application class in the system try { applicationClass = Class.forName(applicationClassName); } catch (Exception e){ throw new MappingException("Can't find application class " + applicationClassName); } // Check if application class is already mapped in some participant if (applicationClasses.contains(applicationClass)) throw new MappingException("Application class " + applicationClassName + "mapped into two participants"); applicationClasses.add(applicationClass); map.application2participant.put(applicationClass, participant); Method[] applMethods = applicationClass.getDeclaredMethods(); // Hash(methodToMap, beforeMethod) Hashtable beforeMethods = new Hashtable(); // Hash(methodToMap, replacingMethod) Hashtable replacingMethods = new Hashtable(); // Hash(methodToMap, afterMethod) Hashtable afterMethods = new Hashtable(); // Examine method maps for (int k = 0; k < participantMap.methodMaps.size(); k++) { MethodMap methodMap = (MethodMap) participantMap.methodMaps.elementAt(k); for (int l = 0; l < methodMap.applicationMethods.size(); l++){ ApplicationMethod applicationMethod = (ApplicationMethod) methodMap.applicationMethods.elementAt(l); Vector beforeMethod = getBeforeMethod(methodMap.participantMethod, applicationMethod, (Method[])participant2methods.get(participant), applMethods); for (int x = 0; x < beforeMethod.size(); x++) { Methods m = (Methods) beforeMethod.elementAt(x); beforeMethods.put(m.applicationMethod, m.participantMethod); } Vector afterMethod = getAfterMethod(methodMap.participantMethod, applicationMethod, (Method[])participant2methods.get(participant), applMethods); for (int x = 0; x < afterMethod.size(); x++) { Methods m = (Methods) afterMethod.elementAt(x); afterMethods.put(m.applicationMethod, m.participantMethod); } Vector replacingMethod = getReplacingMethod(methodMap.participantMethod, applicationMethod, (Method[])participant2methods.get(participant), applMethods); for (int x = 0; x < replacingMethod.size(); x++) { Methods m = (Methods) replacingMethod.elementAt(x); replacingMethods.put(m.applicationMethod, m.participantMethod); } Methods expectedMethod = getExpectedMethod(methodMap.participantMethod, applicationMethod, (Method[])participant2methods.get(participant), applMethods); if (expectedMethod != null) { expectedMethod.applicationMethod.setAccessible(true); expectedMethods.put(expectedMethod.participantMethod, expectedMethod.applicationMethod); } } // end partMethod -> applMethod } // end partMethod -> (applMethod)+ map.beforeMethods.put(applicationClass, beforeMethods); map.replacingMethods.put(applicationClass, replacingMethods); map.afterMethods.put(applicationClass, afterMethods); } // end current part -> appl map.participant2application.put(participant, applicationClasses); map.expectedMethods.put(participant, expectedMethods); Class[] classes = new Class[applicationClasses.size()]; for (int k=0; k (appl)+ return map; } private static class Methods { Method applicationMethod; Method participantMethod; } private static Vector getBeforeMethod(String participantMethod, ApplicationMethod applicationMethod, Method[] participantMethods, Method[] applMethods) throws MappingException { Method beforeMethod = null; for (int i = 0; i < participantMethods.length; i++){ if (participantMethods[i].getName().equals("before_" + participantMethod)) { if (beforeMethod != null) throw new MappingException("Two before methods for participant method: " + participantMethod); beforeMethod = participantMethods[i]; } } Vector methods = new Vector(); if (beforeMethod == null) return methods; for (int i = 0; i < applMethods.length; i++){ if (matchingNames(applicationMethod, applMethods[i].getName()) && compatible(beforeMethod, applMethods[i])) { Methods methodCouple = new Methods(); methodCouple.applicationMethod = applMethods[i]; methodCouple.participantMethod = beforeMethod; methods.add(methodCouple); } } return methods; } private static Vector getAfterMethod(String participantMethod, ApplicationMethod applicationMethod, Method[] participantMethods, Method[] applMethods) throws MappingException { Method afterMethod = null; for (int i = 0; i < participantMethods.length; i++){ if (participantMethods[i].getName().equals("after_" + participantMethod)) { if (afterMethod != null) throw new MappingException("Two after methods for participant method: " + participantMethod); afterMethod = participantMethods[i]; } } Vector methods = new Vector(); if (afterMethod == null) return methods; for (int i = 0; i < applMethods.length; i++){ if (matchingNames(applicationMethod, applMethods[i].getName()) && compatible(afterMethod, applMethods[i])) { Methods methodCouple = new Methods(); methodCouple.applicationMethod = applMethods[i]; methodCouple.participantMethod = afterMethod; methods.add(methodCouple); } } return methods; } private static Vector getReplacingMethod(String participantMethod, ApplicationMethod applicationMethod, Method[] participantMethods, Method[] applMethods) throws MappingException { Method replacingMethod = null; for (int i = 0; i < participantMethods.length; i++){ String participantMethodName = participantMethods[i].getName(); if (participantMethodName.equals("replacing_" + participantMethod)){ if (replacingMethod != null) throw new MappingException("Two replacing methods for participant method: " + participantMethod); replacingMethod = participantMethods[i]; } } Vector methods = new Vector(); if (replacingMethod == null) return methods; for (int i = 0; i < applMethods.length; i++){ if (matchingNames(applicationMethod, applMethods[i].getName()) && compatible(replacingMethod, applMethods[i])) { Methods methodCouple = new Methods(); methodCouple.applicationMethod = applMethods[i]; methodCouple.participantMethod = replacingMethod; methods.add(methodCouple); } } return methods; } private static Methods getExpectedMethod(String participantMethod, ApplicationMethod applicationMethod, Method[] participantMethods, Method[] applMethods) throws MappingException { Method expectedMethod = null; for (int i = 0; i < participantMethods.length; i++){ if (participantMethods[i].getName().equals("expected_" + participantMethod)) { if (expectedMethod != null) throw new MappingException("Two expected methods for participant method: " + participantMethod); expectedMethod = participantMethods[i]; } } if (expectedMethod == null) return null; Methods methodCouple = new Methods(); methodCouple.participantMethod = expectedMethod; for (int i = 0; i < applMethods.length; i++){ if (matchingNames(applicationMethod, applMethods[i].getName()) && compatible(expectedMethod, applMethods[i])) { if (methodCouple.applicationMethod != null) throw new MappingException("Two application methods for " + "expected participant method: " + participantMethod); methodCouple.applicationMethod = applMethods[i]; } } return methodCouple; } private static boolean matchingNames(ApplicationMethod applicationMethod, String name){ if (!name.startsWith("hidden_")) return false; name = name.substring(7); if (applicationMethod.preffix) if (name.startsWith(applicationMethod.name)) return true; if (applicationMethod.suffix) if (name.endsWith(applicationMethod.name)) return true; return (name.equals(applicationMethod.name)); } private static boolean compatible(Method a, Method b){ return true; } private static String shortName(String name){ if (name.indexOf('.') < 0) return name; return name.substring(name.lastIndexOf(".")+1); } private Mapper(){ } }