PageRenderTime 56ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/wheels/vendor/javaloader/JavaCompiler.cfc

http://cfwheels.googlecode.com/
ColdFusion CFScript | 178 lines | 139 code | 33 blank | 6 comment | 4 complexity | b1888188145e000f2678c69fb31805c7 MD5 | raw file
Possible License(s): Apache-2.0, CPL-1.0
  1. <cfcomponent hint="Compiles Java source dirs to an array of .jar files." output="false">
  2. <!------------------------------------------- PUBLIC ------------------------------------------->
  3. <cffunction name="init" hint="Constructor" access="public" returntype="JavaCompiler" output="false">
  4. <cfargument name="jarDirectory" hint="the directory to build the .jar file in, defaults to ./tmp" type="string" required="No" default="#getDirectoryFromPath(getMetadata(this).path)#/tmp">
  5. <cfscript>
  6. var data = {};
  7. var defaultCompiler = "com.sun.tools.javac.api.JavacTool";
  8. //we have to manually go looking for the compiler
  9. try
  10. {
  11. data.compiler = getPageContext().getClass().getClassLoader().loadClass(defaultCompiler).newInstance();
  12. }
  13. catch(any exc)
  14. {
  15. println("Error loading compiler:");
  16. println(exc.toString());
  17. }
  18. /*
  19. If not by THIS point do we have a compiler, then throw an exception
  20. */
  21. if(NOT StructKeyExists(data, "compiler"))
  22. {
  23. throwException("javaCompiler.NoCompilerAvailableException",
  24. "No Java Compiler is available",
  25. "There is no Java Compiler available. Make sure tools.jar is in your classpath and you are running Java 1.6+");
  26. }
  27. setCompiler(data.compiler);
  28. setJarDirectory(arguments.jarDirectory);
  29. return this;
  30. </cfscript>
  31. </cffunction>
  32. <cffunction name="compile" hint="compiles Java to bytecode, and returns a JAR" access="public" returntype="any" output="false">
  33. <cfargument name="directoryArray" hint="array of directories to compile" type="array" required="Yes">
  34. <cfargument name="classLoader" hint="a optional URLClassloader to use as the parent for compilation" type="any" required="false">
  35. <cfargument name="jarName" hint="The name of the jar file. Defaults to a UUID" type="string" required="false" default="#createUUID()#.jar">
  36. <cfscript>
  37. //setup file manager with default exception handler, default locale, and default character set
  38. var fileManager = getCompiler().getStandardFileManager(JavaCast("null", ""), JavaCast("null", ""), JavaCast("null", ""));
  39. var qFiles = 0;
  40. var fileArray = [];
  41. var directoryToCompile = 0;
  42. var fileObjects = 0;
  43. var osw = createObject("java", "java.io.StringWriter").init();
  44. var options = [];
  45. var compilePass = 0;
  46. var jarPath = getJarDirectory() & "/" & arguments.jarName;
  47. </cfscript>
  48. <cfloop array="#arguments.directoryArray#" index="directoryToCompile">
  49. <cfdirectory action="list" directory="#directoryToCompile#" name="qFiles" recurse="true" filter="*.java">
  50. <cfloop query="qFiles">
  51. <cfscript>
  52. ArrayAppend(fileArray, qFiles.directory & "/" & qFiles.name);
  53. </cfscript>
  54. </cfloop>
  55. <cfscript>
  56. if(structKeyExists(arguments, "classLoader"))
  57. {
  58. options = addClassLoaderFiles(options, arguments.classLoader, arguments.directoryArray);
  59. }
  60. fileObjects = fileManager.getJavaFileObjectsFromStrings(fileArray);
  61. </cfscript>
  62. </cfloop>
  63. <cfscript>
  64. //does the compilation
  65. compilePass = getCompiler().getTask(osw, fileManager, JavaCast("null", ""), options, JavaCast("null", ""), fileObjects).call();
  66. if(NOT compilePass)
  67. {
  68. throwException("javacompiler.SourceCompilationException", "There was an error compiling your source code", osw.toString());
  69. }
  70. </cfscript>
  71. <!--- wrap it up in a jar --->
  72. <cfloop array="#arguments.directoryArray#" index="directoryToCompile">
  73. <!--- do this again, as if there ARE files in it, we should create a .jar --->
  74. <cfdirectory action="list" directory="#directoryToCompile#" name="qFiles">
  75. <!--- can't do zips on empty directories --->
  76. <cfif qFiles.recordCount>
  77. <cfzip action="zip" file="#jarPath#" recurse="yes" source="#directoryToCompile#" overwrite="no">
  78. </cfif>
  79. </cfloop>
  80. <!--- we won't bother with an manifest, as we don't really need one --->
  81. <cfreturn jarPath />
  82. </cffunction>
  83. <cffunction name="getVersion" hint="returns the version number" access="public" returntype="string" output="false">
  84. <cfreturn "0.1.b" />
  85. </cffunction>
  86. <!------------------------------------------- PACKAGE ------------------------------------------->
  87. <!------------------------------------------- PRIVATE ------------------------------------------->
  88. <cffunction name="addClassLoaderFiles" hint="adds a set of files to the file manager from the urlclassloader" access="private" returntype="array" output="false">
  89. <cfargument name="options" hint="the options array" type="array" required="Yes">
  90. <cfargument name="classLoader" hint="URLClassloader to use as the parent for compilation" type="any" required="true">
  91. <cfargument name="directoryArray" hint="array of directories to compile" type="array" required="Yes">
  92. <cfscript>
  93. var urls = 0;
  94. var uri = 0;
  95. var classPaths = createObject("java", "java.lang.StringBuilder").init();
  96. var File = createObject("java", "java.io.File");
  97. var path = 0;
  98. </cfscript>
  99. <!--- add in the classloader, and all its parents --->
  100. <cfloop condition="#structKeyExists(arguments, "classLoader")#">
  101. <cfset urls = arguments.classLoader.getURLs()>
  102. <cfloop array="#urls#" index="uri">
  103. <cfscript>
  104. classPaths.append(uri.getFile()).append(File.pathSeparator);
  105. </cfscript>
  106. </cfloop>
  107. <cfset arguments.classLoader = arguments.classLoader.getParent()>
  108. </cfloop>
  109. <!--- add in the folders we are compiling from --->
  110. <cfloop array="#arguments.directoryArray#" index="path">
  111. <cfset classPaths.append(path).append(File.pathSeparator)>
  112. </cfloop>
  113. <cfscript>
  114. ArrayAppend(arguments.options, "-classpath");
  115. ArrayAppend(arguments.options, classPaths.toString());
  116. return arguments.options;
  117. </cfscript>
  118. </cffunction>
  119. <cffunction name="getCompiler" access="private" returntype="any" output="false">
  120. <cfreturn instance.Compiler />
  121. </cffunction>
  122. <cffunction name="setCompiler" access="private" returntype="void" output="false">
  123. <cfargument name="Compiler" type="any" required="true">
  124. <cfset instance.Compiler = arguments.Compiler />
  125. </cffunction>
  126. <cffunction name="getJarDirectory" access="private" returntype="string" output="false">
  127. <cfreturn instance.jarDirectory />
  128. </cffunction>
  129. <cffunction name="setJarDirectory" access="private" returntype="void" output="false">
  130. <cfargument name="jarDirectory" type="string" required="true">
  131. <cfset instance.jarDirectory = arguments.jarDirectory />
  132. </cffunction>
  133. <cffunction name="throwException" access="private" hint="Throws an Exception" output="false">
  134. <cfargument name="type" hint="The type of exception" type="string" required="Yes">
  135. <cfargument name="message" hint="The message to accompany the exception" type="string" required="Yes">
  136. <cfargument name="detail" type="string" hint="The detail message for the exception" required="No" default="">
  137. <cfthrow type="#arguments.type#" message="#arguments.message#" detail="#arguments.detail#">
  138. </cffunction>
  139. <cffunction name="println" hint="" access="private" returntype="void" output="false">
  140. <cfargument name="str" hint="" type="string" required="Yes">
  141. <cfscript>
  142. createObject("Java", "java.lang.System").out.println(arguments.str);
  143. </cfscript>
  144. </cffunction>
  145. </cfcomponent>