PageRenderTime 16ms CodeModel.GetById 2ms app.highlight 4ms RepoModel.GetById 1ms app.codeStats 3ms

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