001: /*
002: * ============================================================================
003: * GNU Lesser General Public License
004: * ============================================================================
005: *
006: * JasperReports - Free Java report-generating library.
007: * Copyright (C) 2001-2006 JasperSoft Corporation http://www.jaspersoft.com
008: *
009: * This library is free software; you can redistribute it and/or
010: * modify it under the terms of the GNU Lesser General Public
011: * License as published by the Free Software Foundation; either
012: * version 2.1 of the License, or (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017: * Lesser General Public License for more details.
018: *
019: * You should have received a copy of the GNU Lesser General Public
020: * License along with this library; if not, write to the Free Software
021: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
022: *
023: * JasperSoft Corporation
024: * 303 Second Street, Suite 450 North
025: * San Francisco, CA 94107
026: * http://www.jaspersoft.com
027: */
028:
029: /*
030: * Contributors:
031: * Peter Severin - peter_p_s@users.sourceforge.net
032: */
033: package net.sf.jasperreports.compilers;
034:
035: import groovyjarjarasm.asm.ClassVisitor;
036: import groovyjarjarasm.asm.ClassWriter;
037:
038: import java.io.ByteArrayInputStream;
039: import java.io.File;
040: import java.io.Serializable;
041: import java.util.HashMap;
042: import java.util.Map;
043:
044: import net.sf.jasperreports.engine.JRException;
045: import net.sf.jasperreports.engine.JRReport;
046: import net.sf.jasperreports.engine.design.JRAbstractJavaCompiler;
047: import net.sf.jasperreports.engine.design.JRCompilationSourceCode;
048: import net.sf.jasperreports.engine.design.JRCompilationUnit;
049: import net.sf.jasperreports.engine.design.JRDefaultCompilationSourceCode;
050: import net.sf.jasperreports.engine.design.JRSourceCompileTask;
051:
052: import org.codehaus.groovy.ast.ClassNode;
053: import org.codehaus.groovy.control.CompilationFailedException;
054: import org.codehaus.groovy.control.CompilationUnit;
055: import org.codehaus.groovy.control.CompilerConfiguration;
056: import org.codehaus.groovy.control.Phases;
057:
058: /**
059: * Calculator compiler that uses groovy to compile expressions.
060: *
061: * @author Teodor Danciu (teodord@users.sourceforge.net), Peter Severin (peter_p_s@users.sourceforge.net)
062: * @version $Id: JRGroovyCompiler.java 1828 2007-08-24 13:58:43Z teodord $
063: */
064: public class JRGroovyCompiler extends JRAbstractJavaCompiler {
065:
066: public JRGroovyCompiler() {
067: super (false);
068: }
069:
070: protected String compileUnits(JRCompilationUnit[] units,
071: String classpath, File tempDirFile) throws JRException {
072: CompilerConfiguration config = new CompilerConfiguration();
073: config.setUseNewGroovy(true);
074: //config.setClasspath(classpath);
075: CompilationUnit unit = new CompilationUnit(config);
076:
077: for (int i = 0; i < units.length; i++) {
078: unit.addSource("calculator_" + units[i].getName(),
079: new ByteArrayInputStream(units[i].getSourceCode()
080: .getBytes()));
081: }
082:
083: ClassCollector collector = new ClassCollector();
084: unit.setClassgenCallback(collector);
085: try {
086: unit.compile(Phases.CLASS_GENERATION);
087: } catch (CompilationFailedException e) {
088: throw new JRException(
089: "Errors were encountered when compiling report expressions class file:\n"
090: + e.toString());
091: }
092:
093: if (collector.classes.size() < units.length) {
094: throw new JRException(
095: "Too few groovy class were generated.");
096: } else if (collector.classCount > units.length) {
097: throw new JRException(
098: "Too many groovy classes were generated.\n"
099: + "Please make sure that you don't use Groovy features such as closures that are not supported by this report compiler.\n");
100: }
101:
102: for (int i = 0; i < units.length; i++) {
103: units[i].setCompileData((Serializable) collector.classes
104: .get(units[i].getName()));
105: }
106:
107: return null;
108: }
109:
110: /**
111: *
112: */
113: private static class ClassCollector extends
114: CompilationUnit.ClassgenCallback {
115: public Map classes = new HashMap();
116: public int classCount;
117:
118: /**
119: * @see org.codehaus.groovy.control.CompilationUnit.ClassgenCallback#call(
120: * groovyjarjarasm.asm.ClassVisitor,
121: * org.codehaus.groovy.ast.ClassNode)
122: */
123: public void call(ClassVisitor writer, ClassNode node)
124: throws CompilationFailedException {
125: classCount++;
126: String name = node.getName();
127: if (!classes.containsKey(name)) {
128: byte[] bytes = ((ClassWriter) writer).toByteArray();
129: classes.put(name, bytes);
130: }
131: }
132: }
133:
134: protected void checkLanguage(String language) throws JRException {
135: if (!JRReport.LANGUAGE_GROOVY.equals(language)
136: && !JRReport.LANGUAGE_JAVA.equals(language)) {
137: throw new JRException("Language \"" + language
138: + "\" not supported by this report compiler.\n"
139: + "Expecting \"groovy\" or \"java\" instead.");
140: }
141: }
142:
143: protected JRCompilationSourceCode generateSourceCode(
144: JRSourceCompileTask sourceTask) throws JRException {
145: return new JRDefaultCompilationSourceCode(JRGroovyGenerator
146: .generateClass(sourceTask), null);
147: }
148:
149: protected String getSourceFileName(String unitName) {
150: return unitName + ".groovy";
151: }
152:
153: }
|