|
View:
New views
12 Messages
—
Rating Filter:
Alert me
|
|
|
Some scala-swing ideasAs part of an application I'm writing, I wrote some code, part of
which may be useful for scala-swing. It's not very polished, but I'm copy-pasting some code that I wrote so more eyes will see it. Please comment! Components: package chavrusa.frontend import scala.swing._ import scala.collection.mutable.Map import java.awt.{Font, Dimension} /** * A component, with control of get/setComponentZOrder. * Uses OverlayLayout. */ trait ZOrdered extends Component with SequentialContainer.Wrapper { override lazy val peer: javax.swing.JPanel = { val p = new javax.swing.JPanel with SuperMixin p.setLayout(new javax.swing.OverlayLayout(p)) p } lazy val zOrder: Map[Component, Int] = new Map[Component, Int] { def -=(c: Component) { _contents -= c } def update(c: Component, z: Int) = { peer.add(c.peer) peer.setComponentZOrder(c.peer, z) } def get(c: Component) = Some(peer.getComponentZOrder(c.peer)) def size = contents.size def elements: Iterator[(Component, Int)] = contents.elements map {c => (c, apply(c))} } def toFront(c: Component) = zOrder(c) = 0 def toBack(c: Component) = zOrder(c) = -1 } /** * A JLayeredPane wrapper using OverlayLayout */ class OverlayLayeredPane extends SequentialContainer.Wrapper { override lazy val peer: javax.swing.JLayeredPane = { val lp = new javax.swing.JLayeredPane with SuperMixin lp.setLayout(new javax.swing.OverlayLayout(lp)) lp } lazy val layer: Map[Component, (Int,Int)] = new Map[Component, (Int, Int)] { def -=(c: Component) { _contents -= c } def update(c: Component, i: (Int,Int)) = { i match { case (layer, pos) => peer.setLayer(c.peer, layer) peer.add(c.peer) peer.setPosition(c.peer, pos) } } def get(c: Component) = Some((peer.getLayer(c.peer), peer.getPosition(c.peer))) def size = contents.size def elements: Iterator[(Component, (Int,Int))] = contents.elements map {c => (c, apply(c))} } def toFront(c: Component) = { println(peer.getComponents contains c.peer) peer.moveToFront(c.peer) } } /** * Default settings for this particular kiosk. * Big font */ trait Defaults extends Component { xLayoutAlignment = 0.5 font = new Font("SansSerif", java.awt.Font.PLAIN, 30) } /** * Big margins */ trait ButtonDefaults extends Button with Defaults { margin = new java.awt.Insets(5,5,5,5) } trait StretchFull extends Component { maximumSize = new Dimension(Math.MAX_INT, Math.MAX_INT) } /** * Adds a round red rectangle when not valid, and fires events */ trait ValidationDecorated extends Component with Publisher { case class Valid(source: Component) extends event.ComponentEvent case class Invalid(source: Component) extends event.ComponentEvent private var _valid = true def valid_=(v:Boolean) { val old = _valid _valid = v // if(old != v) { if(v) publish(Valid(this)) else publish(Invalid(this)) // } repaint } def valid = _valid override def paint(g: java.awt.Graphics) = g match { case g: java.awt.Graphics2D => super.paint(g) if(!valid) { g.setPaint(new java.awt.Color(1f,0f,0f,.75f)) g.setStroke(new java.awt.BasicStroke(3f)) g.drawRoundRect(0,0,size.width-1,size.height-1, 20,20) } } } /** * Wrapper for SwingX JXTitledPanel */ class TitledPanel extends Component { import org.jdesktop.swingx.JXTitledPanel override lazy val peer: JXTitledPanel = new JXTitledPanel def title = peer.getTitle def title_=(t: String) = peer.setTitle(t) def titleFont = peer.getTitleFont def titleFont_=(f: Font) = peer.setTitleFont(f) def content = peer.getContentContainer.asInstanceOf[javax.swing.JComponent].getClientProperty("scala.swingWrapper").asInstanceOf[Component] def content_=(c: Component) = peer.setContentContainer(c.peer) } Effects: (take advantage of traits) package chavrusa.frontend import java.awt.Graphics2D import java.awt.image.BufferedImage import scala.swing._ trait EffectPainting extends Component { import java.awt.image.BufferedImage var paintingEffect = false var paintingBackground = true override def paint(g: java.awt.Graphics) = g match { case g: Graphics2D => if(!paintingEffect) { super.paint(g) } else { val bi = new BufferedImage(size.width, size.height, BufferedImage.TYPE_4BYTE_ABGR) val gBi = bi.createGraphics if(paintingBackground) { gBi.setPaint(background) gBi.fillRect(0,0,size.width,size.height) } /*else { gBi.clearRect(0,0,size.width,size.height) }*/ super.paint(gBi) paintEffect(bi, g) } } // override def paintComponent(g: Graphics) {} def paintEffect(bi: BufferedImage, g: Graphics2D) } trait Translucent extends EffectPainting { private var _opacity = 1f def opacity = _opacity def opacity_=(v: Float) = { _opacity = v repaint } def paintEffect(bi: java.awt.image.BufferedImage, g: Graphics2D) { val oldComposite = g.getComposite g.setComposite(java.awt.AlphaComposite.getInstance( java.awt.AlphaComposite.SRC_OVER, Math.min(1,Math.max(0,opacity)) )) g.drawImage(bi,0,0,null) g.setComposite(oldComposite) } } trait TransitionEffect extends EffectPainting { var initialImage: Option[BufferedImage] = None var transitionValue = 0f } trait FadeTransition extends TransitionEffect { def paintEffect(bi: BufferedImage, g0: Graphics2D) { val g = g0.create.asInstanceOf[Graphics2D] initialImage match { case Some(img) => g.drawImage(img,0,0,null) g.setComposite(java.awt.AlphaComposite.getInstance( java.awt.AlphaComposite.SRC_OVER, Math.min(1,Math.max(0,transitionValue)) )) case None => } g.drawImage(bi,0,0,null) } } |
|
|
Re: Some scala-swing ideasNo comments?
On Mon, Oct 5, 2009 at 3:28 PM, Naftoli Gugenheim <naftoligug@...> wrote: As part of an application I'm writing, I wrote some code, part of |
|
|
Re: Re: Some scala-swing ideasSorry Naftoli...
I'm trying to track swing stuff as closely as I can, and this one is on my todo list. But new job, and a baby, and some fun maven+udson+scala stuff I'm playing with right now, I seem to be a little over-committed :) You're not being ignored though! On Mon, Oct 12, 2009 at 8:31 PM, Naftoli Gugenheim <naftoligug@...> wrote: > No comments? > > On Mon, Oct 5, 2009 at 3:28 PM, Naftoli Gugenheim <naftoligug@...> > wrote: >> >> As part of an application I'm writing, I wrote some code, part of >> which may be useful for scala-swing. It's not very polished, but I'm >> copy-pasting some code that I wrote so more eyes will see it. Please >> comment! >> >> Components: >> >> package chavrusa.frontend >> >> import scala.swing._ >> >> import scala.collection.mutable.Map >> >> import java.awt.{Font, Dimension} >> >> /** >> * A component, with control of get/setComponentZOrder. >> * Uses OverlayLayout. >> */ >> trait ZOrdered extends Component with SequentialContainer.Wrapper { >> override lazy val peer: javax.swing.JPanel = { >> val p = new javax.swing.JPanel with SuperMixin >> p.setLayout(new javax.swing.OverlayLayout(p)) >> p >> } >> lazy val zOrder: Map[Component, Int] = new Map[Component, Int] { >> def -=(c: Component) { _contents -= c } >> def update(c: Component, z: Int) = { >> peer.add(c.peer) >> peer.setComponentZOrder(c.peer, z) >> } >> def get(c: Component) = Some(peer.getComponentZOrder(c.peer)) >> def size = contents.size >> def elements: Iterator[(Component, Int)] = >> contents.elements map {c => (c, apply(c))} >> } >> def toFront(c: Component) = zOrder(c) = 0 >> def toBack(c: Component) = zOrder(c) = -1 >> } >> >> /** >> * A JLayeredPane wrapper using OverlayLayout >> */ >> class OverlayLayeredPane extends SequentialContainer.Wrapper { >> override lazy val peer: javax.swing.JLayeredPane = { >> val lp = new javax.swing.JLayeredPane with SuperMixin >> lp.setLayout(new javax.swing.OverlayLayout(lp)) >> lp >> } >> >> lazy val layer: Map[Component, (Int,Int)] = new Map[Component, (Int, >> Int)] { >> def -=(c: Component) { _contents -= c } >> def update(c: Component, i: (Int,Int)) = { >> i match { >> case (layer, pos) => >> peer.setLayer(c.peer, layer) >> peer.add(c.peer) >> peer.setPosition(c.peer, pos) >> } >> } >> def get(c: Component) = Some((peer.getLayer(c.peer), >> peer.getPosition(c.peer))) >> def size = contents.size >> def elements: Iterator[(Component, (Int,Int))] = >> contents.elements map {c => (c, apply(c))} >> } >> >> def toFront(c: Component) = { >> println(peer.getComponents contains c.peer) >> peer.moveToFront(c.peer) >> } >> >> } >> >> >> /** >> * Default settings for this particular kiosk. >> * Big font >> */ >> trait Defaults extends Component { >> xLayoutAlignment = 0.5 >> font = new Font("SansSerif", java.awt.Font.PLAIN, 30) >> } >> /** >> * Big margins >> */ >> trait ButtonDefaults extends Button with Defaults { >> margin = new java.awt.Insets(5,5,5,5) >> } >> >> trait StretchFull extends Component { >> maximumSize = new Dimension(Math.MAX_INT, Math.MAX_INT) >> } >> >> >> /** >> * Adds a round red rectangle when not valid, and fires events >> */ >> trait ValidationDecorated extends Component with Publisher { >> case class Valid(source: Component) extends event.ComponentEvent >> case class Invalid(source: Component) extends event.ComponentEvent >> private var _valid = true >> def valid_=(v:Boolean) { >> val old = _valid >> _valid = v >> // if(old != v) { >> if(v) publish(Valid(this)) else publish(Invalid(this)) >> // } >> repaint >> } >> def valid = _valid >> >> override def paint(g: java.awt.Graphics) = g match { >> case g: java.awt.Graphics2D => >> super.paint(g) >> if(!valid) { >> g.setPaint(new java.awt.Color(1f,0f,0f,.75f)) >> g.setStroke(new java.awt.BasicStroke(3f)) >> g.drawRoundRect(0,0,size.width-1,size.height-1, 20,20) >> } >> } >> } >> >> /** >> * Wrapper for SwingX JXTitledPanel >> */ >> class TitledPanel extends Component { >> import org.jdesktop.swingx.JXTitledPanel >> override lazy val peer: JXTitledPanel = new JXTitledPanel >> >> def title = peer.getTitle >> def title_=(t: String) = peer.setTitle(t) >> >> def titleFont = peer.getTitleFont >> def titleFont_=(f: Font) = peer.setTitleFont(f) >> >> def content = >> >> peer.getContentContainer.asInstanceOf[javax.swing.JComponent].getClientProperty("scala.swingWrapper").asInstanceOf[Component] >> def content_=(c: Component) = peer.setContentContainer(c.peer) >> } >> >> >> >> >> >> >> Effects: (take advantage of traits) >> package chavrusa.frontend >> >> import java.awt.Graphics2D >> import java.awt.image.BufferedImage >> >> import scala.swing._ >> >> >> trait EffectPainting extends Component { >> import java.awt.image.BufferedImage >> var paintingEffect = false >> var paintingBackground = true >> >> override def paint(g: java.awt.Graphics) = g match { >> case g: Graphics2D => >> if(!paintingEffect) { >> super.paint(g) >> } else { >> val bi = new BufferedImage(size.width, size.height, >> BufferedImage.TYPE_4BYTE_ABGR) >> val gBi = bi.createGraphics >> if(paintingBackground) { >> gBi.setPaint(background) >> gBi.fillRect(0,0,size.width,size.height) >> } /*else { >> gBi.clearRect(0,0,size.width,size.height) >> }*/ >> super.paint(gBi) >> paintEffect(bi, g) >> } >> } >> // override def paintComponent(g: Graphics) {} >> >> def paintEffect(bi: BufferedImage, g: Graphics2D) >> } >> trait Translucent extends EffectPainting { >> private var _opacity = 1f >> def opacity = _opacity >> def opacity_=(v: Float) = { >> _opacity = v >> repaint >> } >> >> def paintEffect(bi: java.awt.image.BufferedImage, g: Graphics2D) { >> val oldComposite = g.getComposite >> g.setComposite(java.awt.AlphaComposite.getInstance( >> java.awt.AlphaComposite.SRC_OVER, >> Math.min(1,Math.max(0,opacity)) >> )) >> g.drawImage(bi,0,0,null) >> g.setComposite(oldComposite) >> } >> } >> >> trait TransitionEffect extends EffectPainting { >> var initialImage: Option[BufferedImage] = None >> var transitionValue = 0f >> } >> trait FadeTransition extends TransitionEffect { >> def paintEffect(bi: BufferedImage, g0: Graphics2D) { >> val g = g0.create.asInstanceOf[Graphics2D] >> initialImage match { >> case Some(img) => >> g.drawImage(img,0,0,null) >> g.setComposite(java.awt.AlphaComposite.getInstance( >> java.awt.AlphaComposite.SRC_OVER, >> Math.min(1,Math.max(0,transitionValue)) >> )) >> case None => >> } >> g.drawImage(bi,0,0,null) >> } >> } > > |
|
|
Scala-Interpreter OddityI just did a small experiment on the command line:
* $ scala Welcome to Scala version 2.7.6.final (Java HotSpot(TM) Client VM, Java 1.6.0_16). Type in expressions to have them evaluated. Type :help for more information. scala> class A defined class A scala> println(classOf[A]) class line1$object$$iw$$iw$A scala> println(classOf[A].getName) line1$object$$iw$$iw$A scala> println(classOf[A].getCanonicalName) java.lang.ClassNotFoundException: $iw at scala.tools.nsc.interpreter.AbstractFileClassLoader.findClass(AbstractFileClassLoader.scala:27) at java.lang.ClassLoader.loadClass(ClassLoader.java:307) at java.lang.ClassLoader.loadClass(ClassLoader.java:252) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320) at java.lang.Class.getDeclaringClass(Native Method) at java.lang.... scala> * I define a class `A' and use `toString' and `getName' it, both of which work. But then, `classOf[A].getCanonicalName)' yields in a `CNFE'. What gives? ---Ph. |
|
|
Re: Scala-Interpreter Oddity -- General Class-Name CurioTo elaborate on my question, the following code surfaces the same problem:
val name = "scala.xml.pull.ProducerConsumerIterator$$anonfun$fillBuffer$1" val c = Class.forName(name) // Works println(c.getName) // Works, will print `scala.xml.pull.ProducerConsumerIterator$$anonfun$fillBuffer$1' println(c.getCanonicalName) Here, `getCanonicalName' will yield an `IncompatibleClassChangeError': Exception in thread "main" java.lang.IncompatibleClassChangeError: scala.xml.pull.ProducerConsumerIterator and scala.xml.pull.ProducerConsumerIterator$$anonfun$fillBuffer$1 disagree on InnerClasses attribute at java.lang.Class.getDeclaringClass(Native Method) at java.lang.Class.getEnclosingClass(Class.java:1085) at java.lang.Class.getCanonicalName(Class.java:1169) at com.phrood.sack.Sack.run(Sack.scala:48) at com.phrood.sack.Sack$.main(Sack.scala:25) at com.phrood.sack.Sack.main(Sack.scala) The same thing happens if I use `Class.getSimpleName'. This effectively means that it is no longer safe to use `Class.getCanonicalName' and `Class.getSimpleName' on classes that have already been successfully loaded. Maybe we need a new and smarter JDK implementation of `Class.getEnclosingClass' to make it Scala-ready? I guess most code around will deal with `ClassNotFoundException' after calling `Class.forName' since it is a checked exception, but I don't think anyone would expect `getCanonicalName' and `getSimpleName' to fail for an existing `Class' instance. This problem not just might but *will* break existing programs, especially class-analyzing tools. It looks like this little innocent dollar sign in class names poses more problems that one would initially expect. It also broke the AspectJ weaver, which will have a patch as of version 1.6.7. I cannot cite the JLS by heart here, but I seem to remember that dollar signs in class names (more generally, in identifiers) are legal, albeit unrecommended Java, so the JDK should be able to deal with it. Cheers ---Ph. |
|
|
Re: Scala-Interpreter Oddity -- General Class-Name CurioI think this could be a bug in the Scala backend.
First, here is a simpler example: trait Test { def testFunc(i:Int) = ((i:Int) => i + 5)(i) } And here the console session: Welcome to Scala version 2.7.4.final (OpenJDK 64-Bit Server VM, Java 1.6.0_0). Type in expressions to have them evaluated. Type :help for more information. scala> Class.forName("Test$$anonfun$testFunc$1") res0: java.lang.Class[_] = class Test$$anonfun$testFunc$1 scala> res0.getSimpleName java.lang.IncompatibleClassChangeError: Test and Test$$anonfun$testFunc$1 disagree on InnerClasses attribute at java.lang.Class.getDeclaringClass(Native Method) at java.lang.Class.getEnclosingClass(Class.java:1102) at java.lang.Class.getSimpleBinaryName(Class.java:1237) at java.lang.Class.getSimpleName(Class.java:1129) at .<init>(<console>:6) at .<clinit>(<console>) at RequestR... And here the relevant part of the javap output: % javap -v Test\$\$anonfun\$testFunc\$1 Compiled from "test.scala" public final class Test$$anonfun$testFunc$1 extends java.lang.Object implements scala.Function1,scala.ScalaObject,java.io.Serializable SourceFile: "test.scala" Scala: length = 0x InnerClass: public final #72= #32 of #71; //$anonfun$testFunc$1=class Test$$anonfun$testFunc$1 of class Test If I understand the JVM spec correctly, there are several problems at once: * Scala's compilation strategy for traits is to generate an interface (Test) and another class containing the implementations (Test$class). The anonymous function being an implementation detail is therefore an inner class of Test$class and not of Test. So the InnerClass entry refers to the wrong class. If one looks at the Test and Test$class one can see that it actually _is_ declared in Test$class with exactly the same InnerClass entry as here (outer class = Test), which is kind of paradox. * That aside, InnerClass entries for anonymous classes are compiled differently in Java: Name and OuterClass are null and only the innerClass member of the InnerClass data structure should be set. The real back-reference is made through an EnclosingMethod entry. [1] For reference I appended a small Java example useful to examine the differences when compiling inner/nested classes. That said, I should add as an disclaimer, that since I wasn't involved in implementing Scala's backend at all, there may be reasons for generating class-files like that. Johannes BTW: I'm not sure if your last mail is a result of the same bug or another problem with the interpreter's classpath. [1] From JVM Spec §4.7.5: "If C is anonymous, the value of the inner_name_index item must be zero." and "If C is not a member, the value of the outer_class_info_index item must be zero." On Tue, Oct 13, 2009 at 9:08 AM, Philip Köster <philip.koester@...> wrote: > To elaborate on my question, the following code surfaces the same problem: > > val name = > "scala.xml.pull.ProducerConsumerIterator$$anonfun$fillBuffer$1" > val c = Class.forName(name) // Works > println(c.getName) // Works, will print > `scala.xml.pull.ProducerConsumerIterator$$anonfun$fillBuffer$1' > println(c.getCanonicalName) > > Here, `getCanonicalName' will yield an `IncompatibleClassChangeError': > > Exception in thread "main" java.lang.IncompatibleClassChangeError: > scala.xml.pull.ProducerConsumerIterator and > scala.xml.pull.ProducerConsumerIterator$$anonfun$fillBuffer$1 disagree on > InnerClasses attribute > at java.lang.Class.getDeclaringClass(Native Method) > at java.lang.Class.getEnclosingClass(Class.java:1085) > at java.lang.Class.getCanonicalName(Class.java:1169) > at com.phrood.sack.Sack.run(Sack.scala:48) > at com.phrood.sack.Sack$.main(Sack.scala:25) > at com.phrood.sack.Sack.main(Sack.scala) > > The same thing happens if I use `Class.getSimpleName'. > > This effectively means that it is no longer safe to use > `Class.getCanonicalName' and `Class.getSimpleName' on classes that have > already been successfully loaded. Maybe we need a new and smarter JDK > implementation of `Class.getEnclosingClass' to make it Scala-ready? > > I guess most code around will deal with `ClassNotFoundException' after > calling `Class.forName' since it is a checked exception, but I don't think > anyone would expect `getCanonicalName' and `getSimpleName' to fail for an > existing `Class' instance. This problem not just might but *will* break > existing programs, especially class-analyzing tools. > > It looks like this little innocent dollar sign in class names poses more > problems that one would initially expect. It also broke the AspectJ weaver, > which will have a patch as of version 1.6.7. I cannot cite the JLS by heart > here, but I seem to remember that dollar signs in class names (more > generally, in identifiers) are legal, albeit unrecommended Java, so the JDK > should be able to deal with it. > > Cheers > ---Ph. > -- Johannes ----------------------------------------------- Johannes Rudolph http://virtual-void.net [test.java] class JavaTest{ static class InnerStaticClass{} class InnerClass{} public static void staticTest(){ class InnerMethodClass{}; new Object(){}; } } |
|
|
|
|
|
Re: Scala-Interpreter Oddity -- General Class-Name CurioHere are two related tickets:
http://lampsvn.epfl.ch/trac/scala/ticket/1167 is a consequent bug of this issue and was closed because a workaround was available. http://lampsvn.epfl.ch/trac/scala/ticket/1572 there are some interesting comments how inner classes should be generated. It would be interesting to know if the current behaviour is just an oversight and sloppy implementation of the JVM specs or if there is some deeper rational behind. In the end it is questionable if this issue has any practical relevance at all (apart having to deal with crashes in unexpected situations). Is there any real use for this metadata? Johannes On Tue, Oct 13, 2009 at 12:11 PM, <philip.koester@...> wrote: >> BTW: I'm not sure if your last mail is a result of the same bug or >> another problem with the interpreter's classpath. > > Me neither. In the Scala console, a `ClassNotFoundException' was raised, and in the example I ran in Eclipse, as well as in yours, it was an `IncompatibleClassChangeError'. I don't know if these are two separate problems or if they eventually boil down to the same implementation issue in `java.lang.Class' or elsewhere. > > Anyway, something has got to give. :) Either this is an essential bug in the Scala-generated bytecode, or the JRE's `Class' needs a fix on the Java or native side. > > Who feels responsible or should be contacted? > > ---Ph. > -- Johannes ----------------------------------------------- Johannes Rudolph http://virtual-void.net |
|
|
|
|
|
Re: Scala-Interpreter Oddity -- General Class-Name CurioOn Wed, Oct 14, 2009 at 10:36 AM, <philip.koester@...> wrote:
>> http://lampsvn.epfl.ch/trac/scala/ticket/1167 > > why was the ticket closed? I see no discussion about an existing work-around. I thought it was closed because of the comment "Changing the one line to [...] Makes the problem go away. " but as it turned out, it was closed because of a fix that was committed and which is exactly the fix I proposed in one of the earlier mails. Unfortunately this fix was removed later on in another commit and the problem seems to reappear. >> http://lampsvn.epfl.ch/trac/scala/ticket/1572 > > In Eclipse, I'm using Scala Library 2.8.0.r19052, and in the console it's 2.8.0.r18462 (with `maven-scala-plugin'). Maybe the fix that is mentioned in ticket # 1572 is included in 19052, but I still get this `IncompatibleClassChangeError' in both environments. The solution to this particular issue is not a fix for your bug. I added it just for some background. > I think something as simple as `scala> class A; classOf[A].getCanonicalName' just may not fail. This reveals there is something shaky at the very bottom of the class layout. Your are generally right, but what I wanted to say is that the very long period this bug went undiscovered is evidence for its relative unimportance. -- Johannes ----------------------------------------------- Johannes Rudolph http://virtual-void.net |
|
|
|
|
|
Re: Scala-Interpreter Oddity -- General Class-Name CurioOn Wed, Oct 14, 2009 at 4:13 AM, <philip.koester@...> wrote:
>> Your are generally right, but what I wanted to say is that the very >> long period this bug went undiscovered is evidence for its relative >> unimportance. > > You have a point here. I guess this bug is likely to surface as more and more libraries written in Scala become available. > > Addendum: `Class.getDeclaringClass' and `Class.getEnclosingClass' don't work reliably either. I no longer think this is a bagatelle. I hate to revisit an old thread, but this issue has come up for me twice in the past month. The first time, I could find a workaround, but this time I cannot. I'm using a third-party library which does some simple reflection, and I'm getting: java.lang.IncompatibleClassChangeError: scala.collection.Map and scala.collection.Map$$anon$5 disagree on InnerClasses attribute at java.lang.Class.getDeclaringClass(Native Method) at java.lang.Class.getEnclosingClass(Class.java:1085) [...] Is there any fix for this? Any workaround? Neither the offending code nor the client code are under my control. Seems like bug 1167 is still sitting there... Anybody? Thanks... Matt |
| Free embeddable forum powered by Nabble | Forum Help |