KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > jasperreports > engine > design > JRJdtCompiler


1 /*
2  * ============================================================================
3  * GNU Lesser General Public License
4  * ============================================================================
5  *
6  * JasperReports - Free Java report-generating library.
7  * Copyright (C) 2001-2006 JasperSoft Corporation http://www.jaspersoft.com
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library 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 GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
22  *
23  * JasperSoft Corporation
24  * 303 Second Street, Suite 450 North
25  * San Francisco, CA 94107
26  * http://www.jaspersoft.com
27  */

28 package net.sf.jasperreports.engine.design;
29
30 import java.io.ByteArrayOutputStream JavaDoc;
31 import java.io.File JavaDoc;
32 import java.io.IOException JavaDoc;
33 import java.io.InputStream JavaDoc;
34 import java.lang.reflect.Constructor JavaDoc;
35 import java.lang.reflect.InvocationTargetException JavaDoc;
36 import java.util.Enumeration JavaDoc;
37 import java.util.HashMap JavaDoc;
38 import java.util.Iterator JavaDoc;
39 import java.util.List JavaDoc;
40 import java.util.Locale JavaDoc;
41 import java.util.Map JavaDoc;
42 import java.util.Properties JavaDoc;
43
44 import net.sf.jasperreports.engine.JRException;
45 import net.sf.jasperreports.engine.JRReport;
46 import net.sf.jasperreports.engine.JRRuntimeException;
47 import net.sf.jasperreports.engine.util.JRClassLoader;
48 import net.sf.jasperreports.engine.util.JRProperties;
49
50 import org.apache.commons.logging.Log;
51 import org.apache.commons.logging.LogFactory;
52 import org.eclipse.jdt.core.compiler.IProblem;
53 import org.eclipse.jdt.internal.compiler.ClassFile;
54 import org.eclipse.jdt.internal.compiler.CompilationResult;
55 import org.eclipse.jdt.internal.compiler.Compiler;
56 import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
57 import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
58 import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
59 import org.eclipse.jdt.internal.compiler.IProblemFactory;
60 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
61 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
62 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
63 import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
64 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
65 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
66 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
67
68 /**
69  * @author Teodor Danciu (teodord@users.sourceforge.net)
70  * @version $Id: JRJdtCompiler.java 1413 2006-09-28 13:47:40 +0300 (Thu, 28 Sep 2006) teodord $
71  */

72 public class JRJdtCompiler extends JRAbstractJavaCompiler
73 {
74     private static final String JavaDoc JDT_PROPERTIES_PREFIX = "org.eclipse.jdt.core.";
75     
76     /**
77      *
78      */

79     static final Log log = LogFactory.getLog(JRJdtCompiler.class);
80     
81     private final ClassLoader JavaDoc classLoader;
82
83     Constructor JavaDoc constrNameEnvAnsBin;
84     Constructor JavaDoc constrNameEnvAnsCompUnit;
85     
86     boolean is2ArgsConstr;
87     Constructor JavaDoc constrNameEnvAnsBin2Args;
88     Constructor JavaDoc constrNameEnvAnsCompUnit2Args;
89
90     public JRJdtCompiler ()
91     {
92         super(false);
93         
94         classLoader = getClassLoader();
95
96         boolean success;
97         try //FIXME remove support for pre 3.1 jdt
98
{
99             Class JavaDoc classAccessRestriction = loadClass("org.eclipse.jdt.internal.compiler.env.AccessRestriction");
100             constrNameEnvAnsBin2Args = NameEnvironmentAnswer.class.getConstructor(new Class JavaDoc[]{IBinaryType.class, classAccessRestriction});
101             constrNameEnvAnsCompUnit2Args = NameEnvironmentAnswer.class.getConstructor(new Class JavaDoc[]{ICompilationUnit.class, classAccessRestriction});
102             is2ArgsConstr = true;
103             success = true;
104         }
105         catch (NoSuchMethodException JavaDoc e)
106         {
107             success = false;
108         }
109         catch (ClassNotFoundException JavaDoc ex)
110         {
111             success = false;
112         }
113         
114         if (!success)
115         {
116             try
117             {
118                 constrNameEnvAnsBin = NameEnvironmentAnswer.class.getConstructor(new Class JavaDoc[]{IBinaryType.class});
119                 constrNameEnvAnsCompUnit = NameEnvironmentAnswer.class.getConstructor(new Class JavaDoc[]{ICompilationUnit.class});
120                 is2ArgsConstr = false;
121             }
122             catch (NoSuchMethodException JavaDoc ex)
123             {
124                 throw new JRRuntimeException("Not able to load JDT classes", ex);
125             }
126         }
127     }
128     
129     
130     /**
131      *
132      */

133     protected String JavaDoc compileUnits(final JRCompilationUnit[] units, String JavaDoc classpath, File JavaDoc tempDirFile)
134     {
135         final StringBuffer JavaDoc problemBuffer = new StringBuffer JavaDoc();
136
137
138         class CompilationUnit implements ICompilationUnit
139         {
140             protected String JavaDoc srcCode;
141             protected String JavaDoc className;
142
143             public CompilationUnit(String JavaDoc srcCode, String JavaDoc className)
144             {
145                 this.srcCode = srcCode;
146                 this.className = className;
147             }
148
149             public char[] getFileName()
150             {
151                 return className.toCharArray();
152             }
153
154             public char[] getContents()
155             {
156                 return srcCode.toCharArray();
157             }
158
159             public char[] getMainTypeName()
160             {
161                 return className.toCharArray();
162             }
163
164             public char[][] getPackageName()
165             {
166                 return new char[0][0];
167             }
168         }
169
170         
171         final INameEnvironment env = new INameEnvironment()
172         {
173             public NameEnvironmentAnswer findType(char[][] compoundTypeName)
174             {
175                 StringBuffer JavaDoc result = new StringBuffer JavaDoc();
176                 String JavaDoc sep = "";
177                 for (int i = 0; i < compoundTypeName.length; i++) {
178                     result.append(sep);
179                     result.append(compoundTypeName[i]);
180                     sep = ".";
181                 }
182                 return findType(result.toString());
183             }
184
185             public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName)
186             {
187                 StringBuffer JavaDoc result = new StringBuffer JavaDoc();
188                 String JavaDoc sep = "";
189                 for (int i = 0; i < packageName.length; i++) {
190                     result.append(sep);
191                     result.append(packageName[i]);
192                     sep = ".";
193                 }
194                 result.append(sep);
195                 result.append(typeName);
196                 return findType(result.toString());
197             }
198
199             private int getClassIndex(String JavaDoc className)
200             {
201                 int classIdx;
202                 for (classIdx = 0; classIdx < units.length; ++classIdx)
203                 {
204                     if (className.equals(units[classIdx].getName()))
205                     {
206                         break;
207                     }
208                 }
209                 
210                 if (classIdx >= units.length)
211                 {
212                     classIdx = -1;
213                 }
214
215                 return classIdx;
216             }
217             
218             private NameEnvironmentAnswer findType(String JavaDoc className)
219             {
220                 try
221                 {
222                     int classIdx = getClassIndex(className);
223                     
224                     if (classIdx >= 0)
225                     {
226                         ICompilationUnit compilationUnit =
227                             new CompilationUnit(
228                                 units[classIdx].getSourceCode(), className);
229                         if (is2ArgsConstr)
230                         {
231                             return (NameEnvironmentAnswer) constrNameEnvAnsCompUnit2Args.newInstance(new Object JavaDoc[] { compilationUnit, null });
232                         }
233
234                         return (NameEnvironmentAnswer) constrNameEnvAnsCompUnit.newInstance(new Object JavaDoc[] { compilationUnit });
235                     }
236                     
237                     String JavaDoc resourceName = className.replace('.', '/') + ".class";
238                     InputStream JavaDoc is = getResource(resourceName);
239                     if (is != null)
240                     {
241                         byte[] classBytes;
242                         byte[] buf = new byte[8192];
243                         ByteArrayOutputStream JavaDoc baos = new ByteArrayOutputStream JavaDoc(buf.length);
244                         int count;
245                         while ((count = is.read(buf, 0, buf.length)) > 0)
246                         {
247                             baos.write(buf, 0, count);
248                         }
249                         baos.flush();
250                         classBytes = baos.toByteArray();
251                         char[] fileName = className.toCharArray();
252                         ClassFileReader classFileReader =
253                             new ClassFileReader(classBytes, fileName, true);
254                         
255                         if (is2ArgsConstr)
256                         {
257                             return (NameEnvironmentAnswer) constrNameEnvAnsBin2Args.newInstance(new Object JavaDoc[] { classFileReader, null });
258                         }
259
260                         return (NameEnvironmentAnswer) constrNameEnvAnsBin.newInstance(new Object JavaDoc[] { classFileReader });
261                     }
262                 }
263                 catch (IOException JavaDoc exc)
264                 {
265                     log.error("Compilation error", exc);
266                 }
267                 catch (org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException exc)
268                 {
269                     log.error("Compilation error", exc);
270                 }
271                 catch (InvocationTargetException JavaDoc e)
272                 {
273                     throw new JRRuntimeException("Not able to create NameEnvironmentAnswer", e);
274                 }
275                 catch (IllegalArgumentException JavaDoc e)
276                 {
277                     throw new JRRuntimeException("Not able to create NameEnvironmentAnswer", e);
278                 }
279                 catch (InstantiationException JavaDoc e)
280                 {
281                     throw new JRRuntimeException("Not able to create NameEnvironmentAnswer", e);
282                 }
283                 catch (IllegalAccessException JavaDoc e)
284                 {
285                     throw new JRRuntimeException("Not able to create NameEnvironmentAnswer", e);
286                 }
287                 return null;
288             }
289
290             private boolean isPackage(String JavaDoc result)
291             {
292                 int classIdx = getClassIndex(result);
293                 if (classIdx >= 0)
294                 {
295                     return false;
296                 }
297                 
298                 String JavaDoc resourceName = result.replace('.', '/') + ".class";
299
300                 boolean isPackage = true;
301
302                 InputStream JavaDoc is = getResource(resourceName);
303                 
304                 if (is != null)// cannot just test for null; need to read from "is" to avoid bug
305
{ // with sun.plugin.cache.EmptyInputStream on JRE 1.5 plugin
306
try // http://sourceforge.net/tracker/index.php?func=detail&aid=1478460&group_id=36382&atid=416703
307
{
308                         isPackage = (is.read() > 0);
309                     }
310                     catch(IOException JavaDoc e)
311                     {
312                         //ignore
313
}
314                     finally
315                     {
316                         try
317                         {
318                             is.close();
319                         }
320                         catch(IOException JavaDoc e)
321                         {
322                             //ignore
323
}
324                     }
325                 }
326                 
327                 return isPackage;
328             }
329
330             public boolean isPackage(char[][] parentPackageName, char[] packageName)
331             {
332                 StringBuffer JavaDoc result = new StringBuffer JavaDoc();
333                 String JavaDoc sep = "";
334                 if (parentPackageName != null)
335                 {
336                     for (int i = 0; i < parentPackageName.length; i++)
337                     {
338                         result.append(sep);
339                         result.append(parentPackageName[i]);
340                         sep = ".";
341                     }
342                 }
343                 if (Character.isUpperCase(packageName[0]))
344                 {
345                     if (!isPackage(result.toString()))
346                     {
347                         return false;
348                     }
349                 }
350                 result.append(sep);
351                 result.append(packageName);
352                 return isPackage(result.toString());
353             }
354
355             public void cleanup()
356             {
357             }
358
359         };
360
361         final IErrorHandlingPolicy policy =
362             DefaultErrorHandlingPolicies.proceedWithAllProblems();
363
364         final Map JavaDoc settings = getJdtSettings();
365
366         final IProblemFactory problemFactory =
367             new DefaultProblemFactory(Locale.getDefault());
368
369         final ICompilerRequestor requestor =
370             new ICompilerRequestor()
371             {
372                 public void acceptResult(CompilationResult result)
373                 {
374                     String JavaDoc className = ((CompilationUnit) result.getCompilationUnit()).className;
375                     
376                     int classIdx;
377                     for (classIdx = 0; classIdx < units.length; ++classIdx)
378                     {
379                         if (className.equals(units[classIdx].getName()))
380                         {
381                             break;
382                         }
383                     }
384                     
385                     if (result.hasErrors())
386                     {
387                         String JavaDoc sourceCode = units[classIdx].getSourceCode();
388                         
389                         IProblem[] problems = result.getErrors();
390                         for (int i = 0; i < problems.length; i++)
391                         {
392                             IProblem problem = problems[i];
393                             //if (problem.isError())
394
{
395                                 problemBuffer.append(i + 1);
396                                 problemBuffer.append(". ");
397                                 problemBuffer.append(problem.getMessage());
398
399                                 if (
400                                     problem.getSourceStart() >= 0
401                                     && problem.getSourceEnd() >= 0
402                                     )
403                                 {
404                                     int problemStartIndex = sourceCode.lastIndexOf("\n", problem.getSourceStart()) + 1;
405                                     int problemEndIndex = sourceCode.indexOf("\n", problem.getSourceEnd());
406                                     if (problemEndIndex < 0)
407                                     {
408                                         problemEndIndex = sourceCode.length();
409                                     }
410                                     
411                                     problemBuffer.append("\n");
412                                     problemBuffer.append(
413                                         sourceCode.substring(
414                                             problemStartIndex,
415                                             problemEndIndex
416                                             )
417                                         );
418                                     problemBuffer.append("\n");
419                                     for(int j = problemStartIndex; j < problem.getSourceStart(); j++)
420                                     {
421                                         problemBuffer.append(" ");
422                                     }
423                                     if (problem.getSourceStart() == problem.getSourceEnd())
424                                     {
425                                         problemBuffer.append("^");
426                                     }
427                                     else
428                                     {
429                                         problemBuffer.append("<");
430                                         for(int j = problem.getSourceStart() + 1; j < problem.getSourceEnd(); j++)
431                                         {
432                                             problemBuffer.append("-");
433                                         }
434                                         problemBuffer.append(">");
435                                     }
436                                 }
437
438                                 problemBuffer.append("\n");
439                             }
440                         }
441                         problemBuffer.append(problems.length);
442                         problemBuffer.append(" errors\n");
443                     }
444                     if (problemBuffer.length() == 0)
445                     {
446                         ClassFile[] resultClassFiles = result.getClassFiles();
447                         for (int i = 0; i < resultClassFiles.length; i++)
448                         {
449                             units[classIdx].setCompileData(resultClassFiles[i].getBytes());
450                         }
451                     }
452                 }
453             };
454
455         ICompilationUnit[] compilationUnits = new ICompilationUnit[units.length];
456         for (int i = 0; i < compilationUnits.length; i++)
457         {
458             compilationUnits[i] = new CompilationUnit(units[i].getSourceCode(), units[i].getName());
459         }
460
461         Compiler JavaDoc compiler =
462             new Compiler JavaDoc(env, policy, settings, requestor, problemFactory);
463         compiler.compile(compilationUnits);
464
465         if (problemBuffer.length() > 0)
466         {
467             return problemBuffer.toString();
468         }
469
470         return null;
471     }
472
473
474     protected Map JavaDoc getJdtSettings()
475     {
476         final Map JavaDoc settings = new HashMap JavaDoc();
477         settings.put(CompilerOptions.OPTION_LineNumberAttribute, CompilerOptions.GENERATE);
478         settings.put(CompilerOptions.OPTION_SourceFileAttribute, CompilerOptions.GENERATE);
479         settings.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.IGNORE);
480 // if (ctxt.getOptions().getJavaEncoding() != null)
481
// {
482
// settings.put(CompilerOptions.OPTION_Encoding, ctxt.getOptions().getJavaEncoding());
483
// }
484
// if (ctxt.getOptions().getClassDebugInfo())
485
// {
486
// settings.put(CompilerOptions.OPTION_LocalVariableAttribute, CompilerOptions.GENERATE);
487
// }
488

489         List JavaDoc properties = JRProperties.getProperties(JDT_PROPERTIES_PREFIX);
490         for (Iterator JavaDoc it = properties.iterator(); it.hasNext();)
491         {
492             JRProperties.PropertySuffix property = (JRProperties.PropertySuffix) it.next();
493             String JavaDoc propVal = property.getValue();
494             if (propVal != null && propVal.length() > 0)
495             {
496                 settings.put(property.getKey(), propVal);
497             }
498         }
499         
500         Properties JavaDoc systemProps = System.getProperties();
501         for (Enumeration JavaDoc it = systemProps.propertyNames(); it.hasMoreElements();)
502         {
503             String JavaDoc propName = (String JavaDoc) it.nextElement();
504             if (propName.startsWith(JDT_PROPERTIES_PREFIX))
505             {
506                 String JavaDoc propVal = systemProps.getProperty(propName);
507                 if (propVal != null && propVal.length() > 0)
508                 {
509                     settings.put(propName, propVal);
510                 }
511             }
512         }
513         
514         return settings;
515     }
516
517     
518     /**
519      *
520      */

521     private ClassLoader JavaDoc getClassLoader()
522     {
523         ClassLoader JavaDoc clsLoader = Thread.currentThread().getContextClassLoader();
524
525         if (clsLoader != null)
526         {
527             try
528             {
529                 Class.forName(JRJdtCompiler.class.getName(), true, clsLoader);
530             }
531             catch (ClassNotFoundException JavaDoc e)
532             {
533                 clsLoader = null;
534                 //if (log.isWarnEnabled())
535
// log.warn("Failure using Thread.currentThread().getContextClassLoader() in JRJdtCompiler class. Using JRJdtCompiler.class.getClassLoader() instead.");
536
}
537         }
538     
539         if (clsLoader == null)
540         {
541             clsLoader = JRClassLoader.class.getClassLoader();
542         }
543
544         return clsLoader;
545     }
546     
547     protected InputStream JavaDoc getResource (String JavaDoc resourceName)
548     {
549         if (classLoader == null)
550         {
551             return JRJdtCompiler.class.getResourceAsStream("/" + resourceName);
552         }
553         return classLoader.getResourceAsStream(resourceName);
554     }
555     
556     
557     protected Class JavaDoc loadClass (String JavaDoc className) throws ClassNotFoundException JavaDoc
558     {
559         if (classLoader == null)
560         {
561             return Class.forName(className);
562         }
563         return classLoader.loadClass(className);
564     }
565
566     
567     protected void checkLanguage(String JavaDoc language) throws JRException
568     {
569         if (!JRReport.LANGUAGE_JAVA.equals(language))
570         {
571             throw
572                 new JRException(
573                     "Language \"" + language
574                     + "\" not supported by this report compiler.\n"
575                     + "Expecting \"java\" instead."
576                     );
577         }
578     }
579
580     
581     protected String JavaDoc generateSourceCode(JRSourceCompileTask sourceTask) throws JRException
582     {
583         return JRClassGenerator.generateClass(sourceTask);
584     }
585
586     protected String JavaDoc getSourceFileName(String JavaDoc unitName)
587     {
588         return unitName + ".java";
589     }
590
591
592     protected String JavaDoc getCompilerClass()
593     {
594         return JRJavacCompiler.class.getName();
595     }
596 }
597
Popular Tags