[Issue 476] New - Glazed Lists 1.8.0 breaks classloader (ECJ)

View: New views
2 Messages — Rating Filter:   Alert me  

[Issue 476] New - Glazed Lists 1.8.0 breaks classloader (ECJ)

by actualsystems :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

https://glazedlists.dev.java.net/issues/show_bug.cgi?id=476
                 Issue #|476
                 Summary|Glazed Lists 1.8.0 breaks classloader (ECJ)
               Component|glazedlists
                 Version|current
                Platform|PC
              OS/Version|Windows XP
                     URL|
                  Status|NEW
       Status whiteboard|
                Keywords|
              Resolution|
              Issue type|DEFECT
                Priority|P3
            Subcomponent|core
             Assigned to|jessewilson
             Reported by|actualsystems






------- Additional comments from actualsystems@... Mon Jun  1 11:44:22 +0000 2009 -------
We don't know that this is an issue with glazed-lists, although upgrading to
1.8.0 (from 1.7.0) caused the problem to surface. An InvalidJarIndexException is
thrown at run-time.

We have a test case that does not use any classes from Glazed lists, but does
use Jasperreports which can use ECJ internally to compile Java code. When the
glazedlists-1.8.0.jar file is appended to the classpath, ECJ throws the
exception, causing the program to error. (Tested on XP and Vista using Java
1.6.0u13).

We have managed to reduce the problem to a test case. The problem seems to be
related to glazed lists, but we are not sure how. The classloader throws an
exception when navigating the the package of the test case; it loads the "com"
package correctly, but throws an InvalidJarException when trying to load the
"com.actual_systems" package (an ancestor package of the test case).

The problem occurs when the test case is in a sub-package at least three levels
deep, and when using glazedlists-1.8.0-java15.jar on the classpath. Replacing
glazedlists-1.8.0-java15.jar with 1.7.0-java15.jar, or removing it completely,
causes the error to go away and the program then works as expected. The program
also works as expected when placed in the main package or the "com" package.

The program can also be made to work by changing the text-field expression not
to include a reference back to the class (although this isn't a good workaround
for us).

The program also works if ECJ is removed from the classpath and
Glazedlists-1.8.0. is added (although the program won't then run without a Java
compiler, e.g. when run over web start). We have also tried different versions
of ECJ.

The test case is:

package com.actual_systems.p2.client.GUI.ReportPreview.TableReport;

import net.sf.jasperreports.engine.design.*;
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.data.JRTableModelDataSource;
import net.sf.jasperreports.view.JasperViewer;

import javax.swing.*;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
import javax.swing.table.DefaultTableModel;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.sql.Timestamp;

/**
 * JasperDesign to setup a report based on a JTable
 */
public class TableJasperDesign extends JasperDesign {
    private static final int LANDSCAPE_TOTAL_PAGE_WIDTH = 791;
    private static final int LANDSCAPE_TOTAL_PAGE_HEIGHT = 595;
    private static final int LANDSCAPE_MARGIN_HEIGHT = 40;
    private static final int LANDSCAPE_MARGIN_WIDTH = 50;

    /**
     * the printable area of the page (the width of the page minus the right and
left margins)
     */
    public static final int PORTRAIT_PRINTABLE_PAGE_WIDTH = 595 - (2 * 40);

    /**
     * the printable area of the page (the width of the page minus the right and
left margins)
     */
    public static final int LANDSCAPE_PRINTABLE_PAGE_WIDTH = 791 - (2 * 50);

    private static final int SPACE_BETWEEN_COLUMNS = 5;

    /**
     * Scaling factor from JTable width to report width
     */
    private final double widthScale;

    public static final String REPORT_TITLE_KEY = "ReportTitle";
    private static final String REPORT_CLASSNAME = "DynamicReport";
    private TableColumnModel columnModel;
    private TableModel dataModel;

    /**
     * Construct the report
     *
     * @param table      JTable containing data and column models to use
     * @throws JRException on error
     */
    public TableJasperDesign(JTable table) throws JRException {
        this.columnModel = table.getColumnModel();
        this.dataModel = table.getModel();

        widthScale = (double) LANDSCAPE_PRINTABLE_PAGE_WIDTH / (double)
columnModel.getTotalColumnWidth();
        setOrientation(JasperDesign.ORIENTATION_LANDSCAPE);

        setupPage();
        setupDetailBand();
    }

    /**
     * Sets up the detail band, which shows the data
     */
    private void setupDetailBand() {
        // Create a band and set the height.
        JRDesignBand band = new JRDesignBand();
        band.setHeight(14);

        for (int col = 0, xPos = 0; col < columnModel.getColumnCount(); ++col) {

            // get the column width from the table model
            int colWidth = getScaledColWidth(col);

            // Create the designTextField and place the field type
            // make sure these values can overflow
            JRDesignTextField textField = new JRDesignTextField();
            textField.setStretchWithOverflow(true);
            textField.setX(xPos);
            textField.setY(2);
            textField.setWidth(colWidth);
            textField.setHeight(12);
            textField.setPositionType(JRElement.POSITION_TYPE_FLOAT);

            JRDesignExpression expression = new JRDesignExpression();
            Class type = String.class;
            expression.setValueClass(type);
            expression.setText(getClass().getName() +
".stripHTML(\"<html><b>TEST</b></html>\")");
            textField.setExpression(expression);
            band.addElement(textField);

            xPos += colWidth + SPACE_BETWEEN_COLUMNS;
        }

        setDetail(band);
    }

    /**
     * Scale a column from a JTable into the report
     *
     * @param col Column Index
     * @return colWidth
     */
    private int getScaledColWidth(int col) {
        int colWidth = columnModel.getColumn(col).getWidth();
        colWidth = (int) (colWidth * widthScale);
        colWidth -= SPACE_BETWEEN_COLUMNS;
        return colWidth;
    }

    /**
     * Setup the page settings (page height, width, margins etc.)
     */
    private void setupPage() {
        setName(REPORT_CLASSNAME);
        setPageWidth(LANDSCAPE_TOTAL_PAGE_WIDTH);
        setPageHeight(LANDSCAPE_TOTAL_PAGE_HEIGHT);
        setColumnWidth(LANDSCAPE_PRINTABLE_PAGE_WIDTH);
        setLeftMargin(LANDSCAPE_MARGIN_WIDTH);
        setRightMargin(LANDSCAPE_MARGIN_WIDTH);
        setTopMargin(LANDSCAPE_MARGIN_HEIGHT);
        setBottomMargin(LANDSCAPE_MARGIN_HEIGHT);
        setColumnSpacing(0);
    }

    /**
     * Return the table data
     *
     * @return rtn
     */
    public JRTableModelDataSource getTableModel() {
        return new JRTableModelDataSource(dataModel) {
            private final DateFormat dateFormetter = new SimpleDateFormat("dd/MM");

            public Object getFieldValue(JRField jrField) throws JRException {
                Object rtn = super.getFieldValue(jrField);
                if (rtn == null) {
                    rtn = "-";
                } else if (rtn instanceof Date) {
                    rtn = dateFormetter.format((Date) rtn);
                }
                return rtn.toString();
            }
        };
    }

    /**
     * Compile the report and use JasperFillManager to fill the report with the
required data.
     *
     * @return printed - the completed report
     * @throws JRException on error
     */
    public JasperPrint compileAndPrintReport() throws JRException {
        JRTableModelDataSource tableModel = getTableModel();
        JasperReport report = JasperCompileManager.compileReport(this);
        return JasperFillManager.fillReport(report, new HashMap<String,
Object>(), tableModel);
    }


    /*
    In Jtables it is easier to render mul;tilines using the HTMLCell renderer.
    Unfortunately this does not work for JasperReports printing tables
    so we need to translate the HTML into equivalent eg <BR> to "\n"
    */
    public static String stripHTML(String htmlString) {

        String value = htmlString;
        if (value.toUpperCase().indexOf("<HTML>") != -1) {
            if (value.toUpperCase().indexOf("<BR>") != -1) {
                value = htmlString.replaceAll("<[bB][rR]>", "\n");
            }
            value = value.replaceAll("<.*?>", "");
            // if (logger.isDebugEnabled()) logger.debug("value = " + value);
        }
        return value;
    }


    // Test methods:

    public static void main(String args[]) throws JRException {
        // set up the map for testing purposes.
        JTable table = makeTestData();
        TableJasperDesign jasperDesign = new TableJasperDesign(table);
        JasperPrint printed = jasperDesign.compileAndPrintReport();
        JasperViewer.viewReport(printed);
    }

    private static JTable makeTestData() {
        Vector<String> colNames = new Vector<String>();
        colNames.add("Id");
        colNames.add("FirstName");
        colNames.add("LastName");
        colNames.add("Street Address etc.");
        colNames.add("City");
        colNames.add("Country");
        colNames.add("Telephone Number");
        colNames.add("Postcode");
        colNames.add("Date");

        DateFormat df = new SimpleDateFormat();
        Timestamp time = new Timestamp(System.currentTimeMillis());
        String date = df.format(time);

        TableModel rtn = new DefaultTableModel(colNames, 50);
        int i = 1;
        for (; i <= rtn.getRowCount(); ++i) {
            //data.add(new TestVO(Integer.valueOf(i), "FirstName " + i,
"LastName " + i, "Street " + i));
            rtn.setValueAt(i, i - 1, 0);
            rtn.setValueAt("<html>First Name " + i + "</html>", i - 1, 1);
            rtn.setValueAt("<html>Last<br>Name " + i + "</html>", i - 1, 2);
            rtn.setValueAt("Street Address " + i, i - 1, 3);
            rtn.setValueAt("City " + i, i - 1, 4);
            rtn.setValueAt("Country" + i, i - 1, 5);
            rtn.setValueAt("Telephone Number" + i, i - 1, 6);
            rtn.setValueAt("PCode " + i, i - 1, 7);
            rtn.setValueAt(date, i - 1, 8);
        }
        return new JTable(rtn);
    }

}



The error reported is:

Exception in thread "main" net.sf.jasperreports.engine.JRException: Error
compiling report design.
        at
net.sf.jasperreports.engine.design.JRAbstractCompiler.compileReport(JRAbstractCompiler.java:231)
        at
net.sf.jasperreports.engine.JasperCompileManager.compileReport(JasperCompileManager.java:219)
        at
com.actualsystems.p2.client.GUI.ReportPreview.TableReport.TableJasperDesign.compileAndPrintReport(TableJasperDesign.java:158)
        at
com.actualsystems.p2.client.GUI.ReportPreview.TableReport.TableJasperDesign.main(TableJasperDesign.java:188)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at com.intellij.rt.execution.application.AppMain.main(AppMain.java:90)
Caused by: sun.misc.InvalidJarIndexException: Invalid index
        at sun.misc.URLClassPath$JarLoader.getResource(URLClassPath.java:854)
        at sun.misc.URLClassPath$JarLoader.getResource(URLClassPath.java:762)
        at sun.misc.URLClassPath$JarLoader.findResource(URLClassPath.java:732)
        at sun.misc.URLClassPath.findResource(URLClassPath.java:145)
        at java.net.URLClassLoader$2.run(URLClassLoader.java:362)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findResource(URLClassLoader.java:359)
        at java.lang.ClassLoader.getResource(ClassLoader.java:978)
        at java.lang.ClassLoader.getResourceAsStream(ClassLoader.java:1168)
        at
net.sf.jasperreports.engine.design.JRJdtCompiler.getResource(JRJdtCompiler.java:567)
        at
net.sf.jasperreports.engine.design.JRJdtCompiler$1.findType(JRJdtCompiler.java:271)
        at
net.sf.jasperreports.engine.design.JRJdtCompiler$1.findType(JRJdtCompiler.java:229)
        at
org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment.askForType(LookupEnvironment.java:119)
        at
org.eclipse.jdt.internal.compiler.lookup.PackageBinding.getTypeOrPackage(PackageBinding.java:178)
        at
org.eclipse.jdt.internal.compiler.lookup.BlockScope.getBinding(BlockScope.java:397)
        at
org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference.resolveType(QualifiedNameReference.java:874)
        at
org.eclipse.jdt.internal.compiler.ast.MessageSend.resolveType(MessageSend.java:258)
        at
org.eclipse.jdt.internal.compiler.ast.CastExpression.resolveType(CastExpression.java:392)
        at
org.eclipse.jdt.internal.compiler.ast.Assignment.resolveType(Assignment.java:181)
        at org.eclipse.jdt.internal.compiler.ast.Expression.resolve(Expression.java:829)
        at org.eclipse.jdt.internal.compiler.ast.Block.resolve(Block.java:101)
        at org.eclipse.jdt.internal.compiler.ast.Statement.resolveCase(Statement.java:140)
        at
org.eclipse.jdt.internal.compiler.ast.SwitchStatement.resolve(SwitchStatement.java:279)
        at
org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration.resolveStatements(AbstractMethodDeclaration.java:418)
        at
org.eclipse.jdt.internal.compiler.ast.MethodDeclaration.resolveStatements(MethodDeclaration.java:178)
        at
org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration.resolve(AbstractMethodDeclaration.java:396)
        at
org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.resolve(TypeDeclaration.java:1072)
        at
org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.resolve(TypeDeclaration.java:1121)
        at
org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration.resolve(CompilationUnitDeclaration.java:305)
        at org.eclipse.jdt.internal.compiler.Compiler.process(Compiler.java:512)
        at org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:329)
        at
net.sf.jasperreports.engine.design.JRJdtCompiler.compileUnits(JRJdtCompiler.java:192)
        at
net.sf.jasperreports.engine.design.JRAbstractCompiler.compileReport(JRAbstractCompiler.java:190)
        ... 8 more


The third-party JAR versions we are using are:

commons-collections-3.1.jar
commons-digester-1.7.jar
commons-javaflow-20060411.jar
commons-logging.jar (unknown version)
ireport.jar (unknown version)
itext-1.4.jar
jasperreports-3.0.0.jar
jdt-compiler-3.1.1.jar (ECJ; we have also tried newer versions without success)
commons-collections-3.1.jar

All obtained through the Jasper Reports website
http://jasperforge.org/projects/jasperreports

---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@...
For additional commands, e-mail: issues-help@...


[Issue 476] Glazed Lists 1.8.0 breaks classloader (ECJ)

by BRANDS-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

https://glazedlists.dev.java.net/issues/show_bug.cgi?id=476






------- Additional comments from brands@... Mon Jun  1 20:40:40 +0000 2009 -------
seems to be related to issue
https://glazedlists.dev.java.net/issues/show_bug.cgi?id=463
which was discovered and fixed after the 1.8.0 release.
You could try to regenerate the jar index of the Glazed Lists 1.8 jar file:
jar i <GL-jarfile>

Let us know if this helps.

---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@...
For additional commands, e-mail: issues-help@...