Package: Delegate

Delegate

nameinstructionbranchcomplexitylinemethod
Delegate(String, List)
M: 0 C: 21
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 8
100%
M: 0 C: 1
100%
getDelegateMethod(String, Context)
M: 60 C: 167
74%
M: 13 C: 19
59%
M: 11 C: 6
35%
M: 11 C: 47
81%
M: 0 C: 1
100%
getDelegateMethod(String, List)
M: 13 C: 24
65%
M: 1 C: 5
83%
M: 1 C: 3
75%
M: 2 C: 11
85%
M: 0 C: 1
100%
getJavaDelegateMethod(String, List)
M: 28 C: 35
56%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 4 C: 8
67%
M: 0 C: 1
100%
hasDelegate(ITypeCheckerAssistantFactory)
M: 15 C: 52
78%
M: 0 C: 8
100%
M: 0 C: 5
100%
M: 2 C: 13
87%
M: 0 C: 1
100%
invokeDelegate(Object, Context)
M: 108 C: 67
38%
M: 11 C: 7
39%
M: 8 C: 2
20%
M: 19 C: 13
41%
M: 0 C: 1
100%
newInstance()
M: 45 C: 4
8%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 8 C: 1
11%
M: 0 C: 1
100%
toTitle(String, List)
M: 0 C: 13
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
writeObject(ObjectOutputStream)
M: 9 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%

Coverage

1: /*******************************************************************************
2: *
3: *        Copyright (c) 2009 Fujitsu Services Ltd.
4: *
5: *        Author: Nick Battle
6: *
7: *        This file is part of VDMJ.
8: *
9: *        VDMJ is free software: you can redistribute it and/or modify
10: *        it under the terms of the GNU General Public License as published by
11: *        the Free Software Foundation, either version 3 of the License, or
12: *        (at your option) any later version.
13: *
14: *        VDMJ is distributed in the hope that it will be useful,
15: *        but WITHOUT ANY WARRANTY; without even the implied warranty of
16: *        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17: *        GNU General Public License for more details.
18: *
19: *        You should have received a copy of the GNU General Public License
20: *        along with VDMJ. If not, see <http://www.gnu.org/licenses/>.
21: *
22: ******************************************************************************/
23:
24: package org.overture.interpreter.util;
25:
26: import java.io.IOException;
27: import java.io.PrintWriter;
28: import java.io.Serializable;
29: import java.io.StringWriter;
30: import java.lang.reflect.InvocationTargetException;
31: import java.lang.reflect.Method;
32: import java.lang.reflect.Modifier;
33: import java.util.Collections;
34: import java.util.HashMap;
35: import java.util.List;
36: import java.util.Map;
37: import java.util.Vector;
38:
39: import org.overture.ast.definitions.AExplicitFunctionDefinition;
40: import org.overture.ast.definitions.AExplicitOperationDefinition;
41: import org.overture.ast.definitions.AImplicitFunctionDefinition;
42: import org.overture.ast.definitions.AImplicitOperationDefinition;
43: import org.overture.ast.definitions.PDefinition;
44: import org.overture.ast.intf.lex.ILexNameToken;
45: import org.overture.ast.lex.LexNameList;
46: import org.overture.ast.messages.InternalException;
47: import org.overture.ast.patterns.AIdentifierPattern;
48: import org.overture.ast.patterns.PPattern;
49: import org.overture.ast.util.Utils;
50: import org.overture.interpreter.runtime.Context;
51: import org.overture.interpreter.runtime.ContextException;
52: import org.overture.interpreter.runtime.ExitException;
53: import org.overture.interpreter.values.Value;
54: import org.overture.typechecker.assistant.ITypeCheckerAssistantFactory;
55:
56: public class Delegate implements Serializable
57: {
58:         private static final long serialVersionUID = 1L;
59:         private final String name;
60:         private List<PDefinition> definitions;
61:         private static final String OVERTURE_LIB_PKG_PREFIX="org.overture.lib.";
62:
63:         public Delegate(String name, List<PDefinition> definitions)
64:         {
65:                 this.name = name;
66:                 this.definitions = definitions;
67:         }
68:
69:         private boolean delegateChecked = false;
70:         private Class<?> delegateClass = null;
71:         private Map<String, Method> delegateMethods = null;
72:         private Map<String, LexNameList> delegateArgs = null;
73:
74:         public boolean hasDelegate(ITypeCheckerAssistantFactory assistantFactory)
75:         {
76:•                if (!delegateChecked)
77:                 {
78:                         delegateChecked = true;
79:
80:                         String classname = name.replace('_', '.');
81:                         try
82:                         {
83:                                 delegateClass = this.getClass().getClassLoader().loadClass(classname);
84:                         } catch (ClassNotFoundException e)
85:                         {
86:                                 // Fine
87:                         }
88:
89:•                        if(delegateClass==null)
90:                         {
91:                                 try
92:                                 {
93:                                         delegateClass = this.getClass().getClassLoader().loadClass(OVERTURE_LIB_PKG_PREFIX+classname);
94:                                 } catch (ClassNotFoundException e)
95:                                 {
96:                                         // Fine
97:                                 }
98:                         }
99:
100:
101:•                        if(delegateClass!=null) {
102:                                 delegateMethods = new HashMap<>();
103:                                 delegateArgs = new HashMap<>();
104:                                 definitions = assistantFactory.createPDefinitionListAssistant().singleDefinitions(definitions);
105:                         }
106:                 }
107:
108:•                return delegateClass != null;
109:         }
110:
111:         public Object newInstance()
112:         {
113:                 try
114:                 {
115:                         return delegateClass.newInstance();
116:                 } catch (NullPointerException e)
117:                 {
118:                         throw new InternalException(63, "No delegate class found: " + name);
119:                 } catch (InstantiationException e)
120:                 {
121:                         throw new InternalException(54, "Cannot instantiate native object: "
122:                                         + e.getMessage());
123:                 } catch (IllegalAccessException e)
124:                 {
125:                         throw new InternalException(55, "Cannot access native object: "
126:                                         + e.getMessage());
127:                 }
128:         }
129:
130:         // gkanos:added parameters to pass the context as argument.
131:         private Method getDelegateMethod(String title, Context ctxt)
132:         {
133:                 Method m = delegateMethods.get(title);
134:
135:•                if (m == null)
136:                 {
137:                         List<PPattern> plist = null;
138:                         String mname = title.substring(0, title.indexOf('('));
139:
140:                         // FIXME: this is to handle inheritance in the same way as VDMJ did. See CSV and IO, where the subclass
141:                         // declared methods is in the tail of the list
142:                         List<PDefinition> defs = new Vector<PDefinition>(definitions);
143:                         Collections.reverse(defs);
144:
145:•                        for (PDefinition d : defs)
146:                         {
147:•                                if (d.getName().getName().equals(mname))
148:                                 {
149:                                         plist = null;
150:
151:•                                        if (ctxt.assistantFactory.createPDefinitionAssistant().isOperation(d))
152:                                         {
153:•                                                if (d instanceof AExplicitOperationDefinition)
154:                                                 {
155:                                                         AExplicitOperationDefinition e = (AExplicitOperationDefinition) d;
156:                                                         plist = e.getParameterPatterns();
157:                                                 }
158:•                                                else if (d instanceof AImplicitOperationDefinition)
159:                                                 {
160:                                                         AImplicitOperationDefinition e = (AImplicitOperationDefinition) d;
161:                                                         plist = ctxt.assistantFactory.createAImplicitOperationDefinitionAssistant().getParamPatternList(e);
162:                                                 }
163:                                         }
164:•                                        else if (ctxt.assistantFactory.createPDefinitionAssistant().isFunction(d))
165:                                         {
166:•                                                if (d instanceof AExplicitFunctionDefinition)
167:                                                 {
168:                                                         AExplicitFunctionDefinition e = (AExplicitFunctionDefinition) d;
169:                                                         plist = e.getParamPatternList().get(0);
170:                                                 }
171:•                                                else if (d instanceof AImplicitFunctionDefinition)
172:                                                 {
173:                                                         AImplicitFunctionDefinition e = (AImplicitFunctionDefinition) d;
174:                                                         plist = ctxt.assistantFactory.createAImplicitFunctionDefinitionAssistant().getParamPatternList(e).get(0);
175:                                                 }
176:                                         }
177:
178:•                                        if (toTitle(mname, plist).equals(title))
179:                                         {
180:                                                 break;
181:                                         }
182:                                 }
183:                         }
184:
185:                         LexNameList anames = new LexNameList();
186:                         List<Class<?>> ptypes = new Vector<Class<?>>();
187:
188:•                        if (plist != null)
189:                         {
190:•                                for (PPattern p : plist)
191:                                 {
192:•                                        if (p instanceof AIdentifierPattern)
193:                                         {
194:                                                 AIdentifierPattern ip = (AIdentifierPattern) p;
195:                                                 anames.add(ip.getName());
196:                                                 ptypes.add(Value.class);
197:                                         } else
198:                                         {
199:                                                 throw new InternalException(56, "Native method cannot use pattern arguments: "
200:                                                                 + title);
201:                                         }
202:                                 }
203:
204:                                 delegateArgs.put(title, anames);
205:                         } else
206:                         {
207:                                 throw new InternalException(57, "Native member not found: "
208:                                                 + title);
209:                         }
210:
211:                         // search with no context and default package + org.overture.lib
212:                         InternalException searchException = null;
213:                         Method basicMathod = null;
214:                         try {
215:                                 basicMathod = getDelegateMethod(mname, ptypes);
216:                         }catch(InternalException e)
217:                         {
218:                                 searchException = e;
219:                         }
220:
221:                         // search with context and default package + org.overture.lib this is preferred over no context
222: try {
223: ptypes.add(0,Context.class);
224: m = getJavaDelegateMethod(mname, ptypes);
225: }catch(InternalException e)
226: {
227: // Fine
228: }
229:
230:•                        if(m==null)
231:                         {
232:                                 m = basicMathod;
233:                         }
234:
235:
236:
237:•                        if(m==null && searchException!=null)
238:                         {
239:                                 throw searchException;
240:                         }
241:
242:                         delegateMethods.put(title, m);
243:                 }
244:
245:                 return m;
246:         }
247:
248:         private Method getDelegateMethod(String mname, List<Class<?>> ptypes) {
249:                 Method m = null;
250:                 InternalException searchException = null;
251:                 try {
252:                         m = getJavaDelegateMethod(mname, ptypes);
253:                 }catch(InternalException e)
254:                 {
255:                         searchException = e;
256:                 }
257:•                if(m == null)
258:                 {
259:                         try {
260:                                 m = getJavaDelegateMethod(OVERTURE_LIB_PKG_PREFIX+mname, ptypes);
261:                         }catch(InternalException e)
262:                         {
263:                                 // Fine
264:                         }
265:                 }
266:•                if(m==null && searchException!=null) {
267:                         throw searchException;
268:                 }
269:                 return m;
270:         }
271:
272:         private Method getJavaDelegateMethod(String mname, List<Class<?>> ptypes) {
273:                 Method m;
274:                 try
275: {
276: Class<?>[] array = new Class<?>[0];
277: m = delegateClass.getMethod(mname, ptypes.toArray(array));
278:
279:• if (!m.getReturnType().equals(Value.class))
280: {
281: throw new InternalException(58, "Native method does not return Value: "
282: + m);
283: }
284: } catch (SecurityException e)
285: {
286: throw new InternalException(60, "Cannot access native method: "
287: + e.getMessage());
288: } catch (NoSuchMethodException e)
289: {
290: throw new InternalException(61, "Cannot find native method: "
291: + e.getMessage());
292: }
293:                 return m;
294:         }
295:
296:         public Value invokeDelegate(Object delegateObject, Context ctxt)
297:         {
298:                 Method m = getDelegateMethod(ctxt.title, ctxt);
299:
300:•                if ((m.getModifiers() & Modifier.STATIC) == 0 && delegateObject == null)
301:                 {
302:                         throw new InternalException(64, "Native method should be static: "
303:                                         + m.getName());
304:                 }
305:
306:•                boolean useContext = m.getParameterTypes().length >0 && m.getParameterTypes()[0].equals(Context.class);
307:
308:                 LexNameList anames = delegateArgs.get(ctxt.title);
309:
310:                 int argCount = anames.size();
311:•                if(useContext)
312:                 {
313:                         argCount++;
314:                 }
315:                 Object[] avals = new Object[argCount];
316:                 int a = 0;
317:
318:•                if(useContext)
319:                 {
320:                         avals[a++] = ctxt;
321:                 }
322:
323:•                for (ILexNameToken arg : anames)
324:                 {
325:                         avals[a++] = ctxt.get(arg);
326:                 }
327:
328:                 try
329:                 {
330:                         return (Value) m.invoke(delegateObject, avals);
331:                 } catch (IllegalArgumentException e)
332:                 {
333:                         throw new InternalException(62, "Cannot invoke native method: "
334:                                         + e.getMessage());
335:                 } catch (IllegalAccessException e)
336:                 {
337:                         throw new InternalException(62, "Cannot invoke native method: "
338:                                         + e.getMessage());
339:                 } catch (InvocationTargetException e)
340:                 {
341:•                        if (e.getTargetException() instanceof ExitException)
342:                         {
343:                                 throw (ExitException) e.getTargetException();
344:                         }
345:•                        if (e.getTargetException() instanceof ContextException)
346:                         {
347:                                 throw (ContextException) e.getTargetException();
348:                         }
349:                         // if(e.getTargetException() instanceof ValueException)
350:                         // {
351:                         // throw (ValueException)e.getTargetException();
352:                         // }
353:
354: StringWriter strOut = new StringWriter();
355:                         strOut.append(e.getTargetException().getMessage()+"\n");
356:                         e.getTargetException().printStackTrace(new PrintWriter(strOut));
357:                         throw new InternalException(59, "Failed in native method: "
358:                                         + strOut);
359:                 }
360:         }
361:
362:         /**
363:          * The Method objects in the delegateMethods map cannot be serialized, which means that deep copies fail. So here,
364:          * we clear the map when serialization occurs. The map is re-build later on demand.
365:          */
366:
367:         private void writeObject(java.io.ObjectOutputStream out) throws IOException
368:         {
369:•                if (delegateMethods != null)
370:                 {
371:                         delegateMethods.clear();
372:                 }
373:
374:                 out.defaultWriteObject();
375:         }
376:
377:         private String toTitle(String mname, List<PPattern> paramPatterns)
378:         {
379:                 return mname + Utils.listToString("(", paramPatterns, ", ", ")");
380:         }
381: }