Source Code Cross Referenced for TraceTranslator.java in  » UML » AndroMDA-3.2 » org » andromda » translation » ocl » testsuite » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » UML » AndroMDA 3.2 » org.andromda.translation.ocl.testsuite 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package org.andromda.translation.ocl.testsuite;
002:
003:        import javassist.CannotCompileException;
004:        import javassist.ClassPool;
005:        import javassist.CtClass;
006:        import javassist.CtField;
007:        import javassist.CtMethod;
008:        import javassist.LoaderClassPath;
009:        import javassist.NotFoundException;
010:        import org.andromda.core.common.AndroMDALogger;
011:        import org.andromda.core.common.ExceptionUtils;
012:        import org.andromda.core.common.ResourceUtils;
013:        import org.andromda.core.translation.Expression;
014:        import org.andromda.core.translation.TranslationUtils;
015:        import org.andromda.core.translation.Translator;
016:        import org.andromda.core.translation.TranslatorException;
017:        import org.andromda.translation.ocl.BaseTranslator;
018:        import org.apache.log4j.Logger;
019:
020:        import java.io.File;
021:        import java.io.IOException;
022:        import java.net.URL;
023:        import java.util.HashMap;
024:        import java.util.Iterator;
025:        import java.util.Map;
026:
027:        /**
028:         * This class allows us to trace the parsing of the expression. It is reflectively extended by Javaassist to allow the
029:         * inclusion of all "inA" and "outA" methods produced by the SableCC parser. This allows us to dynamically include all
030:         * handling code in each method without having to manual code each one. It used used during development of Translators
031:         * since it allows you to see the execution of each node.
032:         *
033:         * @author Chad Brandon
034:         */
035:        public class TraceTranslator extends BaseTranslator {
036:
037:            private static final Logger logger = Logger
038:                    .getLogger(TraceTranslator.class);
039:
040:            private static final String INA_PREFIX = "inA";
041:            private static final String OUTA_PREFIX = "outA";
042:            private static final String CASE_PREFIX = "case";
043:
044:            private Map methods = new HashMap();
045:
046:            /**
047:             * This is added to the adapted class and then checked to see if it exists to determine if we need to adapt the
048:             * class.
049:             */
050:            private static final String FIELD_ADAPTED = "adapted";
051:
052:            private ClassPool pool;
053:
054:            /**
055:             * Constructs an instance of TraceTranslator.
056:             */
057:            public TraceTranslator() {
058:            }
059:
060:            /**
061:             * Creates and returns an new Instance of this ExpressionTranslator as a Translator object. The first time this
062:             * method is called this class will dynamically be adapted to handle all parser calls.
063:             *
064:             * @return Translator
065:             */
066:            public static Translator getInstance() {
067:                final String debugMethodName = "TraceTranslator.getInstance";
068:                if (logger.isDebugEnabled()) {
069:                    logger.debug("performing " + debugMethodName);
070:                }
071:                try {
072:                    TraceTranslator oclTranslator = new TraceTranslator();
073:                    Translator translator = oclTranslator;
074:                    if (oclTranslator.needsAdaption()) {
075:
076:                        if (logger.isInfoEnabled()) {
077:                            logger
078:                                    .info(" OCL Translator has not been adapted --> adapting");
079:                        }
080:                        translator = (Translator) oclTranslator
081:                                .getAdaptedTranslationClass().newInstance();
082:                    }
083:                    return translator;
084:                } catch (Exception ex) {
085:                    String errMsg = "Error performing " + debugMethodName;
086:                    logger.error(errMsg, ex);
087:                    throw new TranslatorException(errMsg, ex);
088:                }
089:            }
090:
091:            /**
092:             * @see org.andromda.core.translation.Translator#translate(java.lang.String, java.lang.Object, java.lang.String)
093:             */
094:            public Expression translate(String translationName,
095:                    String expression, Object contextElement) {
096:                if (logger.isInfoEnabled()) {
097:                    logger
098:                            .info("======================== Tracing Expression ========================");
099:                    logger.info(TranslationUtils
100:                            .removeExtraWhitespace(expression));
101:                    logger
102:                            .info("======================== ================== ========================");
103:                }
104:                Expression expressionObj = super .translate(translationName,
105:                        expression, contextElement);
106:                if (logger.isInfoEnabled()) {
107:                    logger
108:                            .info("========================  Tracing Complete  ========================");
109:                }
110:                return expressionObj;
111:            }
112:
113:            /**
114:             * Checks to see if this class needs to be adapated If it has the "adapted" field then we know it already has been
115:             * adapted.
116:             *
117:             * @return true/false, true if it needs be be adapted.
118:             */
119:            protected boolean needsAdaption() {
120:                boolean needsAdaption = false;
121:                try {
122:                    this .getClass().getDeclaredField(FIELD_ADAPTED);
123:                } catch (NoSuchFieldException ex) {
124:                    needsAdaption = true;
125:                }
126:                return needsAdaption;
127:            }
128:
129:            /**
130:             * Creates and returns the adapted translator class.
131:             *
132:             * @return Class the new Class instance.
133:             * @throws NotFoundException
134:             * @throws CannotCompileException
135:             * @throws IOException
136:             */
137:            protected Class getAdaptedTranslationClass()
138:                    throws NotFoundException, CannotCompileException,
139:                    IOException {
140:
141:                Class this Class = this .getClass();
142:                this .pool = TranslatorClassPool.getPool(this Class
143:                        .getClassLoader());
144:
145:                CtClass ctTranslatorClass = pool.get(this Class.getName());
146:
147:                CtField adaptedField = new CtField(CtClass.booleanType,
148:                        FIELD_ADAPTED, ctTranslatorClass);
149:
150:                ctTranslatorClass.addField(adaptedField);
151:
152:                //get the "inA" methods from the analysisClass
153:                CtMethod[] analysisMethods = ctTranslatorClass.getMethods();
154:
155:                if (analysisMethods != null) {
156:
157:                    int methodNum = analysisMethods.length;
158:
159:                    for (int ctr = 0; ctr < methodNum; ctr++) {
160:                        CtMethod method = analysisMethods[ctr];
161:                        String methodName = method.getName();
162:
163:                        if (methodName.startsWith(INA_PREFIX)) {
164:                            // add the new overriden "inA" methods
165:                            this .methods.put(method, this 
166:                                    .getInAMethodBody(method));
167:                        } else if (methodName.startsWith(OUTA_PREFIX)) {
168:                            // add the new overriden "outA" methods
169:                            this .methods.put(method, this 
170:                                    .getOutAMethodBody(method));
171:                        } else if (methodName.startsWith(CASE_PREFIX)) {
172:                            // add the new overridden "case" methods
173:                            this .methods.put(method, this 
174:                                    .getCaseMethodBody(method));
175:                        }
176:                    }
177:
178:                    //now add all the methods to the class
179:                    Iterator allMethods = this .methods.keySet().iterator();
180:                    while (allMethods.hasNext()) {
181:                        CtMethod method = (CtMethod) allMethods.next();
182:                        CtMethod newMethod = new CtMethod(method,
183:                                ctTranslatorClass, null);
184:                        String methodBody = (String) this .methods.get(method);
185:                        newMethod.setBody(methodBody);
186:                        ctTranslatorClass.addMethod(newMethod);
187:                    }
188:
189:                }
190:                this .writeAdaptedClass();
191:                return ctTranslatorClass.toClass();
192:            }
193:
194:            /**
195:             * Writes the class to the directory found by the class loader (since the class is a currently existing class)
196:             */
197:            protected void writeAdaptedClass() {
198:                final String methodName = "TraceTranslator.writeAdaptedClass";
199:                if (logger.isDebugEnabled()) {
200:                    logger.debug("performing " + methodName);
201:                }
202:                try {
203:                    String className = this .getClass().getName();
204:                    File dir = this .getAdaptedClassOutputDirectory();
205:                    if (logger.isDebugEnabled()) {
206:                        logger.debug("writing className '" + className
207:                                + "' to directory --> " + "'" + dir + "'");
208:                    }
209:                    this .pool.writeFile(this .getClass().getName(), dir
210:                            .toString());
211:                } catch (Exception ex) {
212:                    String errMsg = "Error performing " + methodName;
213:                    logger.error(errMsg, ex);
214:                    throw new TranslatorException(errMsg, ex);
215:                }
216:            }
217:
218:            /**
219:             * Retrieves the output directory which the adapted class will be written to.
220:             *
221:             * @return
222:             */
223:            protected File getAdaptedClassOutputDirectory() {
224:                final String methodName = "TraceTranslator.getAdaptedClassOutputDirectory";
225:                Class this Class = this .getClass();
226:                URL classAsResource = ResourceUtils.getClassResource(this Class
227:                        .getName());
228:                File file = new File(classAsResource.getFile());
229:                File dir = file.getParentFile();
230:                if (dir == null) {
231:                    throw new TranslatorException(methodName
232:                            + " - can not retrieve directory for file '" + file
233:                            + "'");
234:                }
235:                String className = this Class.getName();
236:                int index = className.indexOf('.');
237:                String basePackage = null;
238:                if (index != -1) {
239:                    basePackage = className.substring(0, index);
240:                }
241:                if (basePackage != null) {
242:                    while (!dir.toString().endsWith(basePackage)) {
243:                        dir = dir.getParentFile();
244:                    }
245:                    dir = dir.getParentFile();
246:                }
247:                return dir;
248:            }
249:
250:            /**
251:             * Creates and returns the method body for each "caseA" method
252:             *
253:             * @param method
254:             * @return String the <code>case</code> method body
255:             */
256:            protected String getCaseMethodBody(CtMethod method) {
257:                ExceptionUtils.checkNull("method", method);
258:                StringBuffer methodBody = new StringBuffer("{");
259:                String methodName = method.getName();
260:                methodBody
261:                        .append("String methodName = \"" + methodName + "\";");
262:                methodBody.append(this .getMethodTrace(method));
263:                //add the call of the super class method, so that any methods in sub
264:                // classes
265:                //can provide functionality
266:                methodBody.append("super." + methodName + "($1);");
267:                methodBody.append("}");
268:                return methodBody.toString();
269:            }
270:
271:            /**
272:             * Creates and returns the method body for each "inA" method
273:             *
274:             * @param method
275:             * @return String the <code>inA</code> method body
276:             */
277:            protected String getInAMethodBody(CtMethod method) {
278:                ExceptionUtils.checkNull("method", method);
279:                StringBuffer methodBody = new StringBuffer("{");
280:                String methodName = method.getName();
281:                methodBody
282:                        .append("String methodName = \"" + methodName + "\";");
283:                methodBody.append(this .getMethodTrace(method));
284:                //add the call of the super class method, so that any methods in sub
285:                // classes
286:                //can provide functionality
287:                methodBody.append("super." + methodName + "($1);");
288:                methodBody.append("}");
289:                return methodBody.toString();
290:            }
291:
292:            /**
293:             * Creates and returns the method body for each "inA" method
294:             *
295:             * @param method
296:             * @return String the <code>outA</code> method body.
297:             */
298:            protected String getOutAMethodBody(CtMethod method) {
299:                ExceptionUtils.checkNull("method", method);
300:                StringBuffer methodBody = new StringBuffer("{");
301:                String methodName = method.getName();
302:                methodBody
303:                        .append("String methodName = \"" + methodName + "\";");
304:                methodBody.append(this .getMethodTrace(method));
305:                //add the call of the super class method, so that any methods in sub
306:                // classes
307:                //can provide functionality
308:                methodBody.append("super." + methodName + "($1);");
309:                methodBody.append("}");
310:                return methodBody.toString();
311:            }
312:
313:            /**
314:             * Returns the OCL fragment name that must have a matching name in the library translation template in order to be
315:             * placed into the Expression translated expression buffer.
316:             *
317:             * @param method
318:             * @return String
319:             */
320:            protected String getOclFragmentName(CtMethod method) {
321:                ExceptionUtils.checkNull("method", method);
322:                String fragment = method.getName();
323:                String prefix = this .getMethodPrefix(method);
324:                int index = fragment.indexOf(prefix);
325:                if (index != -1) {
326:                    fragment = fragment.substring(index + prefix.length(),
327:                            fragment.length());
328:                }
329:                return fragment;
330:            }
331:
332:            /**
333:             * Returns the prefix for the method (inA or outA)
334:             *
335:             * @param method
336:             * @return
337:             */
338:            protected String getMethodPrefix(CtMethod method) {
339:                ExceptionUtils.checkNull("method", method);
340:                String mName = method.getName();
341:                String prefix = INA_PREFIX;
342:                if (mName.startsWith(OUTA_PREFIX)) {
343:                    prefix = OUTA_PREFIX;
344:                }
345:                return prefix;
346:            }
347:
348:            /**
349:             * Creates the debug statement that will be output for each method
350:             *
351:             * @param method
352:             * @return @throws NotFoundException
353:             */
354:            protected String getMethodTrace(CtMethod method) {
355:                ExceptionUtils.checkNull("method", method);
356:                StringBuffer buf = new StringBuffer(
357:                        "if (logger.isInfoEnabled()) {logger.info(\"");
358:                buf.append("\" + methodName + \" --> ");
359:                //javaassist names the arguments $1,$2,$3, etc.
360:                buf
361:                        .append("'\" + org.andromda.core.translation.TranslationUtils.trimToEmpty($1) + \"'\");}");
362:                return buf.toString();
363:            }
364:
365:            /**
366:             * Extends the Javaassist class pool so that we can define our own ClassLoader to use from which to find, load and
367:             * modify and existing class.
368:             *
369:             * @author Chad Brandon
370:             */
371:            private static class TranslatorClassPool extends ClassPool {
372:
373:                private static Logger logger = Logger
374:                        .getLogger(TranslatorClassPool.class);
375:
376:                protected TranslatorClassPool() {
377:                    super (ClassPool.getDefault());
378:                    if (logger.isInfoEnabled()) {
379:                        logger.debug("instantiating new TranslatorClassPool");
380:                    }
381:                }
382:
383:                /**
384:                 * Retrieves an instance of this TranslatorClassPool using the loader to find/load any classes.
385:                 *
386:                 * @param loader
387:                 * @return
388:                 */
389:                protected static ClassPool getPool(ClassLoader loader) {
390:                    if (loader == null) {
391:                        loader = Thread.currentThread().getContextClassLoader();
392:                    }
393:                    TranslatorClassPool pool = new TranslatorClassPool();
394:                    pool.insertClassPath(new LoaderClassPath(loader));
395:                    return pool;
396:                }
397:
398:                /**
399:                 * Returns a <code>java.lang.Class</code> object. It calls <code>write()</code> to obtain a class file and then
400:                 * loads the obtained class file into the JVM. The returned <code>Class</code> object represents the loaded
401:                 * class.
402:                 * <p/>
403:                 * To load a class file, this method uses an internal class loader. Thus, that class file is not loaded by the
404:                 * system class loader, which should have loaded this <code>AspectClassPool</code> class. The internal class
405:                 * loader loads only the classes explicitly specified by this method <code>writeAsClass()</code>. The other
406:                 * classes are loaded by the parent class loader (the sytem class loader) by delegation. Thus, if a class
407:                 * <code>X</code> loaded by the internal class loader refers to a class <code>Y</code>, then the class
408:                 * <code>Y</code> is loaded by the parent class loader.
409:                 *
410:                 * @param classname a fully-qualified class name.
411:                 * @return Class the Class it writes.
412:                 * @throws NotFoundException
413:                 * @throws IOException
414:                 * @throws CannotCompileException
415:                 */
416:                public Class writeAsClass(String classname)
417:                        throws NotFoundException, IOException,
418:                        CannotCompileException {
419:                    try {
420:                        return classLoader.loadClass(classname,
421:                                write(classname));
422:                    } catch (ClassFormatError e) {
423:                        throw new CannotCompileException(e, classname);
424:                    }
425:                }
426:
427:                /**
428:                 * LocalClassLoader which allows us to dynamically construct classes on the fly using Javassist.
429:                 */
430:                static class LocalClassLoader extends ClassLoader {
431:                    /**
432:                     * Constructs an instance of LocalClassLoader.
433:                     *
434:                     * @param parent
435:                     */
436:                    public LocalClassLoader(ClassLoader parent) {
437:                        super (parent);
438:                    }
439:
440:                    /**
441:                     * Loads a class.
442:                     *
443:                     * @param name      the name
444:                     * @param classfile the bytes of the class.
445:                     * @return Class
446:                     * @throws ClassFormatError
447:                     */
448:                    public Class loadClass(String name, byte[] classfile)
449:                            throws ClassFormatError {
450:                        Class c = defineClass(name, classfile, 0,
451:                                classfile.length);
452:                        resolveClass(c);
453:                        return c;
454:                    }
455:                }
456:
457:                /**
458:                 * Create the LocalClassLoader and specify the ClassLoader for this class as the parent ClassLoader. This allows
459:                 * classes defined outside this LocalClassLoader to be loaded (i.e. classes that already exist, and aren't being
460:                 * dynamically created
461:                 */
462:                private static LocalClassLoader classLoader = new LocalClassLoader(
463:                        LocalClassLoader.class.getClassLoader());
464:            }
465:
466:            /**
467:             * This method is called by the main method during the build process, to "adapt" the class to the OCL parser.
468:             */
469:            protected static void adaptClass() {
470:                if (logger.isInfoEnabled()) {
471:                    logger.info("adapting class for OCL parser");
472:                }
473:                TraceTranslator translator = new TraceTranslator();
474:                if (translator.needsAdaption()) {
475:                    try {
476:                        translator.getAdaptedTranslationClass();
477:                    } catch (Throwable th) {
478:                        logger.error(th);
479:                    }
480:                }
481:            }
482:
483:            /**
484:             * This main method is called during the build process, to "adapt" the class to the OCL parser.
485:             *
486:             * @param args
487:             */
488:            public static void main(String args[]) {
489:                try {
490:                    AndroMDALogger.initialize();
491:                    TraceTranslator.adaptClass();
492:                } catch (Throwable th) {
493:                    logger.error(th);
494:                }
495:            }
496:
497:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.