private static Map<String, Long> getMessageSVUID(Type messageType) throws SJIOException, ClassNotFoundException // SJCompilerUtils has a simpler version of this routine. { HashMap<String, Long> ours = new HashMap<String, Long>(); if (messageType instanceof SJSessionType) // Should come before ordinary class cases? (But SJSessionType shouldn't be a // class type). { ours.putAll(getClassSVUIDs((SJSessionType) messageType)); } else if (messageType.isPrimitive()) { // No SVUID needed for primitive types. } else if (messageType.isClass()) // Duplicated from above. { String className = messageType.toClass().fullName(); Class<?> c = Class.forName(className); if (c.isInterface()) { // Interfaces don't have SVUIDs (so what should we do here?). // This encourages use of // abstract classes rather than interfaces for message types? } else { ObjectStreamClass osc = ObjectStreamClass.lookup(c); if (osc == null) { throw new SJIOException("Class not serializable: " + c); } ours.put( className, osc .getSerialVersionUID()); // Not possible to find a different SVUID for the same // (name) class here? // SVUIDs could be recorded in the // session type objects. // Put currently problems working // with these values at compilation time if the class // binary is not available a priori (SVUID value not built // yet?). } } else if (messageType.isArray()) { throw new SJIOException("Array types not done yet: " + messageType); } return ours; }
public boolean callValid(Type thisType, List<Type> argTypes, Context context) { JL5TypeSystem ts = (JL5TypeSystem) typeSystem(); List<Type> l1 = this.formalTypes(); List<Type> l2 = argTypes; if ((l1.size() == 0) && (l2.size() != 0)) return false; Iterator<Type> itCallee = l1.iterator(); Iterator<Type> itCaller = l2.iterator(); // caller can either: // - have one argument less than callee (last argument of // callee is a varargs and caller do not provide a value) // - have same number of args. The last arg being either // - same type as the last arg of callee // - or same type as the last arg of callee which is a varargs array // - or an array of same type as the last arg of callee (which could be a varargs array) // - have more args, then: // - last args of callee must be a varargs array // - all extra args provided by the caller must match // the varargs array type of the callee. while (itCallee.hasNext() && itCaller.hasNext()) { Type t1 = itCallee.next(); Type t2 = itCaller.next(); // Varargs can be used only in the final argument position // When we reach the final argument, we check if it is varargs array. if (!itCallee.hasNext() && t1.isArray() && ((JL5ArrayType) t1).isVarargs()) { JL5ArrayType vartype = (JL5ArrayType) t1; // Every arguments remaining in the second iterator must match the type // of the varargs array if (!itCaller.hasNext()) { // if we also reached the last element of the caller, // check if the type matches or if it is an array return ts.isImplicitCastValid(t2, vartype, context) || ts.isImplicitCastValid(t2, vartype.base(), context); } else { // There are several arguments left, they should all match the callee's varargs array // type. while (itCaller.hasNext()) { // eat up actual args if (!ts.isImplicitCastValid(t2, vartype.base(), context)) { return false; } t2 = itCaller.next(); } } } else { if (!ts.isImplicitCastValid(t2, t1, context)) { return false; } } } // Caller provided less args than the callee has, which is legal // if callee is a variable arity method if (itCallee.hasNext() && isVariableArrity()) { itCallee.next(); } // and we've reached callee's last arg. return !(itCallee.hasNext() || itCaller.hasNext()); }