/** Immediately refreshes all globals using the backing database. */ public synchronized void refreshGlobals() { bootstrapOnce.ensure(); Database database = getDatabase(); LOGGER.info("Loading globals from [{}]", database.getName()); Query<Object> globalsQuery = Query.from(Object.class).where("_id = ?", GLOBALS_ID).using(database).noCache(); State newGlobals = State.getInstance(globalsQuery.first()); if (newGlobals == null) { newGlobals = State.getInstance(globalsQuery.master().first()); } if (newGlobals == null) { newGlobals = new State(); newGlobals.setDatabase(database); newGlobals.setId(GLOBALS_ID); newGlobals.save(); } globals = newGlobals; lastGlobalsUpdate = new Date(); fieldsCache.reset(); metricFieldsCache.reset(); indexesCache.reset(); }
public static void getExtraPutExtraPairs() { Map<String, CompilationUnit> asts = State.getInstance().astMap(); for (Map.Entry<String, CompilationUnit> entry : asts.entrySet()) { KeysVisitor kv = new KeysVisitor(); kv.visit(entry.getValue(), null); State.getInstance().pgMap().put(entry.getKey(), kv.getPGs()); } }
@Override public int compare(Object x, Object y) { State xState = State.getInstance(x); State yState = State.getInstance(y); Object xValue = xState != null ? filter(xState.getByPath(field)) : null; Object yValue = yState != null ? filter(yState.getByPath(field)) : null; return ObjectUtils.compare(xValue, yValue, isNullGreatest); }
/** Creates an object represented by the given {@code typeId} and {@code id}. */ public Object createObject(UUID typeId, UUID id) { bootstrapOnce.ensure(); Class<?> objectClass = null; ObjectType type = null; if (typeId != null && !GLOBALS_ID.equals(id)) { if (typeId.equals(id)) { objectClass = ObjectType.class; } else { type = getTypeById(typeId); if (type != null) { objectClass = type.isAbstract() ? Record.class : type.getObjectClass(); } } } boolean hasClass = true; if (objectClass == null) { objectClass = Record.class; hasClass = false; } Object object = SubstitutionUtils.newInstance(objectClass); State state; try { state = State.getInstance(object); } catch (IllegalArgumentException error) { object = TypeDefinition.getInstance(Record.class).newInstance(); state = State.getInstance(object); hasClass = false; } state.setDatabase(getDatabase()); state.setId(id); state.setTypeId(typeId); if (type != null) { if (!hasClass) { for (ObjectField field : type.getFields()) { Object defaultValue = field.getDefaultValue(); if (defaultValue != null) { state.put(field.getInternalName(), defaultValue); } } } } return object; }
public static void getICCLinkResults() { Map<String, CompilationUnit> asts = State.getInstance().astMap(); ICCLinkFindingResults results = new ICCLinkFindingResults(); State.getInstance().setICCResults(results); for (Map.Entry<String, CompilationUnit> entry : asts.entrySet()) { CFPVisitor cfpVisitor = new CFPVisitor(results); cfpVisitor.visit(entry.getValue(), null); } results.propagate(); for (Map.Entry<String, CompilationUnit> entry : asts.entrySet()) { ICCLinkFinder.findICCLinks(entry.getValue(), results); } }
@Override public Object clone() { Object clone = TypeDefinition.getInstance(getClass()).newInstance(); State cloneState = State.getInstance(clone); cloneState.setDatabase(state.getDatabase()); cloneState.setStatus(state.getStatus()); cloneState.setValues(state.getSimpleValues()); return clone; }
// create dependency graph public static DirectedGraph<String, DefaultEdge> createDependencyGraph() { DirectedGraph<String, DefaultEdge> g = new DefaultDirectedGraph<String, DefaultEdge>(DefaultEdge.class); // add vertices for (String key : State.getInstance().pgMap().keySet()) { g.addVertex(key); } // add edges for (Map.Entry<String, PutsAndGets> entry1 : State.getInstance().pgMap().entrySet()) { PutsAndGets pg1 = entry1.getValue(); for (Map.Entry<String, PutsAndGets> entry2 : State.getInstance().pgMap().entrySet()) { PutsAndGets pg2 = entry2.getValue(); if (pg2.isDep(pg1)) { g.addEdge(entry2.getKey(), entry1.getKey()); } } } return g; }
@Override public boolean equals(Object object) { if (this == object) { return true; } else if (object != null) { try { return getState().equals(State.getInstance(object)); } catch (IllegalArgumentException error) { return false; } } else { return false; } }
public void deselect() { State st = State.getInstance(); if (st.getSelectedTile().equals(this)) { st.setSelectedTile(null); st.setTileState(TileUnSelected); selected = false; if (hasCity()) { st.setSelectedCity(null); st.setCityState(CityUnSelected); } if (hasUnit()) { st.setSelectedUnit(null); st.setUnitState(UnitUnSelected); } view.repaint(); } }
public void select() { State st = State.getInstance(); if (st.getTileState() == TileSelected) { State.getSelectedTile().deselect(); } st.setSelectedTile(this); st.setTileState(TileSelected); if (hasCity()) { st.setSelectedCity(city); st.setCityState(CitySelected); } if (hasUnit()) { st.setSelectedUnit(unit); st.setUnitState(UnitSelected); } selected = true; view.repaint(); }
@Override public final boolean evaluate(PredicateParser parser, Object object, Predicate predicate) { State state = State.getInstance(object); ComparisonPredicate comparison = (ComparisonPredicate) predicate; Object keyValue = state.getByPath(comparison.getKey()); List<Object> values = comparison.resolveValues(state.getDatabase()); if (keyValue == null) { keyValue = Query.MISSING_VALUE; return compare(state, keyValue, values); } else if (keyValue instanceof Iterable) { for (Object item : (Iterable<?>) keyValue) { if (evaluateOne(state, item, values)) { return true; } } return false; } else { return evaluateOne(state, keyValue, values); } }
/** Immediately refreshes all types using the backing database. */ public synchronized void refreshTypes() { bootstrapOnce.ensure(); Database database = getDatabase(); try { TypesCache temporaryTypes = temporaryTypesLocal.get(); if (temporaryTypes == null) { temporaryTypes = new TypesCache(); temporaryTypesLocal.set(temporaryTypes); } List<ObjectType> types = Query.from(ObjectType.class).using(database).selectAll(); int typesSize = types.size(); LOGGER.info("Loading [{}] types from [{}]", typesSize, database.getName()); // Load all types from the database first. for (ObjectType type : types) { type.getFields().size(); // Pre-fetch. temporaryTypes.add(type); } if (initializeClasses) { // Make sure that the root type exists. ObjectType rootType = getRootType(); State rootTypeState; if (rootType != null) { rootTypeState = rootType.getState(); } else { rootType = new ObjectType(); rootTypeState = rootType.getState(); rootTypeState.setDatabase(database); } Map<String, Object> rootTypeOriginals = rootTypeState.getSimpleValues(); UUID rootTypeId = rootTypeState.getId(); rootTypeState.setTypeId(rootTypeId); rootTypeState.clear(); rootType.setObjectClassName(ObjectType.class.getName()); rootType.initialize(); temporaryTypes.add(rootType); try { database.beginWrites(); // Make the new root type available to other types. temporaryTypes.add(rootType); if (rootTypeState.isNew()) { State globals = getGlobals(); globals.put(ROOT_TYPE_FIELD, rootType); globals.save(); } else if (!rootTypeState.getSimpleValues().equals(rootTypeOriginals)) { temporaryTypes.changed.add(rootTypeId); } Set<Class<? extends Recordable>> objectClasses = ClassFinder.findClasses(Recordable.class); for (Iterator<Class<? extends Recordable>> i = objectClasses.iterator(); i.hasNext(); ) { Class<? extends Recordable> objectClass = i.next(); try { if (objectClass.isAnonymousClass() || Substitution.class.isAssignableFrom(objectClass)) { i.remove(); } } catch (IncompatibleClassChangeError error) { i.remove(); } } Set<Class<?>> globalModifications = new HashSet<Class<?>>(); Map<ObjectType, List<Class<?>>> typeModifications = new HashMap<ObjectType, List<Class<?>>>(); // Make sure all types are accessible to the rest of the // system as soon as possible, so that references can be // resolved properly later. for (Class<?> objectClass : objectClasses) { ObjectType type = getTypeByClass(objectClass); if (type == null) { type = new ObjectType(); type.getState().setDatabase(database); } else { type.getState().clear(); } type.setObjectClassName(objectClass.getName()); typeModifications.put(type, new ArrayList<Class<?>>()); temporaryTypes.add(type); } // Separate out all modifications from regular types. for (Class<?> objectClass : objectClasses) { if (!Modification.class.isAssignableFrom(objectClass)) { continue; } @SuppressWarnings("unchecked") Set<Class<?>> modifiedClasses = Modification.Static.getModifiedClasses( (Class<? extends Modification<?>>) objectClass); if (modifiedClasses.contains(Object.class)) { globalModifications.add(objectClass); continue; } for (Class<?> modifiedClass : modifiedClasses) { List<Class<?>> assignableClasses = new ArrayList<Class<?>>(); for (Class<?> c : objectClasses) { if (modifiedClass.isAssignableFrom(c)) { assignableClasses.add(c); } } for (Class<?> assignableClass : assignableClasses) { ObjectType type = getTypeByClass(assignableClass); if (type != null) { List<Class<?>> modifications = typeModifications.get(type); if (modifications == null) { modifications = new ArrayList<Class<?>>(); typeModifications.put(type, modifications); } modifications.add(objectClass); } } } } // Apply global modifications. for (Class<?> modification : globalModifications) { ObjectType.modifyAll(database, modification); } // Initialize all types. List<Class<?>> rootTypeModifications = typeModifications.remove(rootType); initializeAndModify(temporaryTypes, rootType, rootTypeModifications); if (rootTypeModifications != null) { for (Class<?> modification : rootTypeModifications) { ObjectType t = getTypeByClass(modification); initializeAndModify(temporaryTypes, t, typeModifications.remove(t)); } } ObjectType fieldType = getTypeByClass(ObjectField.class); List<Class<?>> fieldModifications = typeModifications.remove(fieldType); initializeAndModify(temporaryTypes, fieldType, fieldModifications); if (fieldModifications != null) { for (Class<?> modification : fieldModifications) { ObjectType t = getTypeByClass(modification); initializeAndModify(temporaryTypes, t, typeModifications.remove(t)); } } for (Map.Entry<ObjectType, List<Class<?>>> entry : typeModifications.entrySet()) { initializeAndModify(temporaryTypes, entry.getKey(), entry.getValue()); } database.commitWrites(); } finally { database.endWrites(); } } // Merge temporary types into new permanent types. TypesCache newPermanentTypes = new TypesCache(); for (ObjectType type : permanentTypes.byId.values()) { newPermanentTypes.add(type); } for (ObjectType type : temporaryTypes.byId.values()) { newPermanentTypes.add(type); } newPermanentTypes.changed.addAll(temporaryTypes.changed); newPermanentTypes.changed.addAll(permanentTypes.changed); // If any types changed, clear all types' extras. if (!temporaryTypes.changed.isEmpty()) { for (ObjectType type : newPermanentTypes.byId.values()) { type.getState().getExtras().clear(); } } permanentTypes = newPermanentTypes; lastTypesUpdate = new Date(); } finally { temporaryTypesLocal.remove(); } ObjectType singletonType = getTypeByClass(Singleton.class); if (singletonType != null) { for (ObjectType type : singletonType.findConcreteTypes()) { if (!Query.fromType(type).where("_type = ?", type).master().noCache().hasMoreThan(0)) { try { State.getInstance(type.createObject(null)).saveImmediately(); } catch (Exception error) { LOGGER.warn(String.format("Can't save [%s] singleton!", type.getLabel()), error); } } } } for (ObjectType type : getTypes()) { Class<?> objectClass = type.getObjectClass(); if (objectClass != null) { TypePostProcessorClasses tppcAnnotation = objectClass.getAnnotation(TypePostProcessorClasses.class); if (tppcAnnotation != null) { for (Class<? extends ObjectType.PostProcessor> processorClass : tppcAnnotation.value()) { ObjectType.PostProcessor processor = (ObjectType.PostProcessor) TYPE_POST_PROCESSORS.getUnchecked(processorClass); processor.process(type); } } } } }
public static void main(String[] args) throws Exception { init(args[0], args[1]); getICCLinkResults(); DirectedGraph<String, DefaultEdge> g = createDependencyGraph(); StringBuilder results = new StringBuilder(); if (ICC_SHOW_INTENT_FILTERS) { // TODO we do not need to load manifest if we are not looking at intent filters State.getInstance().setManifestParser(new AndroidManifestParser(args[2])); StringBuilder localResults = new StringBuilder(); for (String component : State.getInstance().getManifestParser().intentFilters.keySet()) { localResults.append("###\n"); localResults.append("Component: " + component + "\n"); localResults.append("Filters:\n"); for (IntentFilter filter : State.getInstance().getManifestParser().intentFilters.get(component)) { localResults.append("---\n"); localResults.append(filter + "\n"); } } String toPrint = localResults.toString(); System.out.println(toPrint); results.append(toPrint); } if (DEBUG_KEYS) { StringBuilder localResults = new StringBuilder(); localResults.append("INTENT KEYS\n"); for (Map.Entry<String, PutsAndGets> entry : State.getInstance().pgMap().entrySet()) { localResults.append( String.format( "COMP:%s, KEYS:%s\n", entry.getKey().toString(), entry.getValue().toString())); } String toPrint = localResults.toString(); System.out.println(toPrint); results.append(toPrint); } IntentStats appIntentStats = new IntentStats(); ICCLinkFindingResults iccResults = State.getInstance().iccResults(); if (iccResults.intentsST.getMap().size() > 0) { StringBuilder localResults = new StringBuilder(); // printing the intents Map<String, IntentInfo> intents = iccResults.intentsST.getMap(); IntentInfo info = null; for (Map.Entry<String, IntentInfo> intentEntry : intents.entrySet()) { info = intentEntry.getValue(); if ((info.isExplicit() && ICC_SHOW_EXPLICIT_INTENTS) || (!info.isExplicit() && ICC_SHOW_IMPLICIT_INTENTS)) { localResults.append( String.format("%s:\n%s\n----------\n", intentEntry.getKey(), intentEntry.getValue())); } } // printing the vars if (ICC_SHOW_VARS) { Map<String, VarInfo> vars = iccResults.varsST.getMap(); for (Map.Entry<String, VarInfo> varEntry : vars.entrySet()) { String name = varEntry.getKey(); VarInfo varInfo = varEntry.getValue(); localResults.append(String.format("%s %s = %s\n", info.type, name, varInfo.value)); } } // printing the links if (ICC_SHOW_LINKS) { List<ICCLinkInfo<IntentInfo>> links = iccResults.iccLinks; for (ICCLinkInfo<IntentInfo> link : links) { localResults.append(link + "\n"); } } IntentStats stats = iccResults.stats; appIntentStats.add(stats); if (ICC_SHOW_STATS_PER_FILE) { localResults.append(iccResults.stats + "\n"); } String toPrint = localResults.toString(); System.out.println(toPrint); results.append(toPrint); } if (ICC_SHOW_FINAL_STATS) { StringBuilder localResults = new StringBuilder(); localResults.append("### App Intent Stats\n"); localResults.append(appIntentStats + "\n"); localResults.append(appIntentStats.getExtendedAnalysis() + "\n"); String toPrint = localResults.toString(); System.out.println(toPrint); results.append(toPrint); } // saving ICC link results information if (ICC_SAVE_RESULTS) { String toSave = results.toString(); String name = fileListFile.split("-")[0] + "-icc-results.txt"; // component dependency graph BufferedWriter bw = new BufferedWriter(new FileWriter(name)); bw.write(toSave); bw.flush(); bw.close(); } // saving ICC link results information in JSON format if (ICC_SAVE_JSON) { String name = fileListFile.split("-")[0] + ".json"; BufferedWriter bw = new BufferedWriter(new FileWriter(name)); bw.write(iccResults.toJSON()); bw.flush(); bw.close(); } if (PRINT_DOT) { String dot = toDot(g); String name = fileListFile.split("-")[0] + "-cdg.dot"; // component dependency graph BufferedWriter bw = new BufferedWriter(new FileWriter(name)); bw.write(dot); bw.flush(); bw.close(); } if (PRINT_TOPO_ORDER) { System.out.println("TOPO ORDER: "); String topoOrder = getTopoOrder(g); System.out.println(topoOrder); String name = fileListFile.split("-")[0] + "-graph-summary.txt"; // component dependency graph BufferedWriter bw = new BufferedWriter(new FileWriter(name)); bw.write(topoOrder); bw.flush(); bw.close(); } }