LookAndFeel Dynamisches Einlesen von LookAndFeels - NullPointerException

Status
Nicht offen für weitere Antworten.
G

Gastredner

Gast
Hallo,

ich arbeite derzeit an einer Oberflächenkomponente, die mir beim Einbau in einer Applikation die Möglichkeit geben soll, Jar-Archive per Dialog auszuwählen und alle dort enthaltenen LookAndFeels während der Laufzeit auszulesen und anzuwenden.
Ein erstes Grundgerüst steht soweit und funktioniert auch - überwiegend. Ich habe ein hartnäckiges Problem mit einer NullPointerException bei den Business-LookAndFeels aus dem Substance-Archiv (SubstanceBusinessLookAndFeel, SubstanceBusinessBlueSteelLookAndFeel, SubstanceBusinessBlackSteelLookAndFeel). Interessanterweise allerdings auch wirklich nur mit diesen dreien - alle anderen LaFs aus der Substance-Bibliothek funktionieren tadellos.
Der StackTrace der NPE:
Code:
Exception occurred during event dispatching:
java.lang.NullPointerException
	at org.jvnet.substance.painter.decoration.ImageWrapperDecorationPainter.getColorizedTile(ImageWrapperDecorationPainter.java:326)
	at org.jvnet.substance.painter.decoration.ImageWrapperDecorationPainter.tileArea(ImageWrapperDecorationPainter.java:254)
	at org.jvnet.substance.painter.decoration.ImageWrapperDecorationPainter.paintExtraBackground(ImageWrapperDecorationPainter.java:218)
	at org.jvnet.substance.painter.decoration.ImageWrapperDecorationPainter.paintDecorationArea(ImageWrapperDecorationPainter.java:109)
	at org.jvnet.substance.painter.utils.DecorationPainterUtils.paintDecorationBackground(DecorationPainterUtils.java:214)
	at org.jvnet.substance.painter.utils.DecorationPainterUtils.paintDecorationBackground(DecorationPainterUtils.java:174)
	at org.jvnet.substance.painter.utils.BackgroundPaintingUtils.update(BackgroundPaintingUtils.java:114)
	at org.jvnet.substance.SubstanceMenuBarUI.__org__jvnet__substance__SubstanceMenuBarUI__update(SubstanceMenuBarUI.java:96)
	at org.jvnet.substance.SubstanceMenuBarUI.__org__jvnet__substance__SubstanceMenuBarUI__container__update(SubstanceMenuBarUI.java)
	at org.jvnet.substance.SubstanceMenuBarUI.update(SubstanceMenuBarUI.java)
	at javax.swing.JComponent.paintComponent(JComponent.java:763)
	at javax.swing.JComponent.paint(JComponent.java:1029)
	at javax.swing.JComponent.paintChildren(JComponent.java:864)
	at javax.swing.JComponent.paint(JComponent.java:1038)
	at javax.swing.JLayeredPane.paint(JLayeredPane.java:567)
	at javax.swing.JComponent.paintChildren(JComponent.java:864)
	at javax.swing.JComponent.paintToOffscreen(JComponent.java:5131)
	at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1475)
	at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1406)
	at javax.swing.RepaintManager.paint(RepaintManager.java:1220)
	at javax.swing.JComponent.paint(JComponent.java:1015)
	at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:21)
	at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:60)
	at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:97)
	at java.awt.Container.paint(Container.java:1780)
	at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:814)
	at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:714)
	at javax.swing.RepaintManager.seqPaintDirtyRegions(RepaintManager.java:694)
	at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(SystemEventQueueUtilities.java:128)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:597)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:178)
	at java.awt.Dialog$1.run(Dialog.java:1045)
	at java.awt.Dialog$3.run(Dialog.java:1097)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.awt.Dialog.show(Dialog.java:1095)
	at java.awt.Component.show(Component.java:1563)
	at java.awt.Component.setVisible(Component.java:1515)
	at java.awt.Window.setVisible(Window.java:841)
	at java.awt.Dialog.setVisible(Dialog.java:985)
	at de.snk.snkomponents.plafchooser.Test.openDialog(Test.java:130)
	at de.snk.snkomponents.plafchooser.Test.actionPerformed(Test.java:149)
	at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
	at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
	at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
	at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
	at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
	at java.awt.Component.processMouseEvent(Component.java:6263)
	at javax.swing.JComponent.processMouseEvent(JComponent.java:3267)
	at java.awt.Component.processEvent(Component.java:6028)
	at java.awt.Container.processEvent(Container.java:2041)
	at java.awt.Component.dispatchEventImpl(Component.java:4630)
	at java.awt.Container.dispatchEventImpl(Container.java:2099)
	at java.awt.Component.dispatchEvent(Component.java:4460)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4574)
	at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4238)
	at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168)
	at java.awt.Container.dispatchEventImpl(Container.java:2085)
	at java.awt.Window.dispatchEventImpl(Window.java:2475)
	at java.awt.Component.dispatchEvent(Component.java:4460)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
Dies ist übrigens die Methode aus der Klasse ImageWrapperDecorationPainter.java:
[JAVA=323] protected Image getColorizedTile(SubstanceColorScheme scheme) {
Image result = this.colorizedTileMap.get(scheme.getDisplayName());
if (result == null) {
BufferedImage tileBi = new BufferedImage(this.originalTile
.getWidth(null), this.originalTile.getHeight(null),
BufferedImage.TYPE_INT_ARGB);
tileBi.getGraphics().drawImage(this.originalTile, 0, 0, null);
result = SubstanceImageCreator.getColorSchemeImage(tileBi, scheme,
0.0f);
this.colorizedTileMap.put(scheme.getDisplayName(), result);
}
return result;
}[/code]
Ich kann mit diesem Fehler nichts anfangen, bzw. verstehe ich nicht, wieso er nur bei der der 2 LookAndFeels aus der Bibliothek auftritt.

Desweiteren habe ich Probleme mit dem Laden eines einzelnen LookAndFeels aus einem .jar: Obwohl der Vorgang der gleiche ist wie beim Laden aller LaFs aus der gleichen Bibliothek, ist die VM anschließend nicht in der Lage, die neben der LookAndFeel-Klasse selbst benötigten Klassen aus dem Archiv zu laden. Der Code:
Java:
private Map<String, LookAndFeel> loaded; // Enthält bereits geladene LaFs

public LookAndFeel loadLookAndFeel(String className, String jar) throws LookAndFeelLoaderException {
		LookAndFeel laf = loaded.get(className);
		if (laf == null) {
			try {
				URL[] jars = { new URL("jar:file:" + jar + "!/") };
				URLClassLoader cl = new URLClassLoader(jars);
				Class<LookAndFeel> c = (Class<LookAndFeel>) cl.loadClass(className);
				if (isValidPLAFClass(c)) {
					laf = c.newInstance();
					loaded.put(className, laf);
					Thread.currentThread().setContextClassLoader(cl);
				} else {
					throw new LookAndFeelLoaderException("Can not instantiate class \"" + className + "\"!", Reason.ABSTRACT_OR_INTERFACE);
				}
			} catch (MalformedURLException e) {
				throw new LookAndFeelLoaderException("The URL for \"" + jar + "\" is not valid!", Reason.MALFORMED_URL);
			} catch (NoClassDefFoundError e) {
				throw new LookAndFeelLoaderException("The class \"" + className + "\" was not found in archive \"" + jar + "\"!", Reason.WRONG_CLASSNAME);
			} catch (ClassNotFoundException e) {
				throw new LookAndFeelLoaderException("The class \"" + className + "\" was not found in archive \"" + jar + "\"!", Reason.WRONG_CLASSNAME);
			} catch (IllegalAccessException e) {
				throw new LookAndFeelLoaderException(e, Reason.OTHER);
			} catch (InstantiationException e) {
				throw new LookAndFeelLoaderException(e, Reason.OTHER);
			}
		}
		return laf;
	}

private boolean isValidPLAFClass(Class<LookAndFeel> c) {
		return !c.isInterface() && !Modifier.isAbstract(c.getModifiers()) && Modifier.isPublic(c.getModifiers()) && c.getSimpleName().endsWith("LookAndFeel");
	}
Kurz zum Vorgang: Es wird zuerst überprüft, ob die Klasse bereits schonmal geladen worden ist. Sollte dem nicht so sein, so wird der Pfad zum Jar-Archiv zum erzeugen eines URL-Objektes genutzt und einem URLClassLoader übergeben, mit dem anschließend die gewünschte Klasse geladen wird. Dem aktuellen Thread wird anschließend der neue ClassLoader mit dem Verweis auf das Archiv bekannt gemacht und das geladene LookAndFeel zurückgegeben.
Der Vorgang wird beim Laden aller LaFs aus einem Archiv bzw. aus einer Liste von Archiven dadurch ergänzt, dass das Archiv nach Dateien mit der Endung "LookAndFeel.class" durchsucht wird. Die gefundenen Dateien werden in einer Liste gespeichert und anschließend durch den URLClassLoader geladen und instantiiert, bevor der ClassLoader dem Thread übergeben und die Liste der LaF-Objekte zurückgegeben wird.
Bei Letzterem funktioniert dies - bis auf die Probleme mit den drei Substance-LaFs und dem FH-LookAndFeel - tadellos, der oben gepostete Code erzeugt hindessen den angesprochenen Fehler:
Code:
UIDefaults.getUI() failed: no ComponentUI class for: javax.swing.JList[ /* Die ganzen Eigenschaften... */ ]
java.lang.Error
	at javax.swing.UIDefaults.getUIError(UIDefaults.java:711)
	at javax.swing.MultiUIDefaults.getUIError(MultiUIDefaults.java:133)
	at javax.swing.UIDefaults.getUI(UIDefaults.java:741)
	at javax.swing.UIManager.getUI(UIManager.java:1017)
	at javax.swing.JList.updateUI(JList.java:508)
	at javax.swing.JList.<init>(JList.java:403)
	at javax.swing.JList.<init>(JList.java:447)
	at de.snk.snkomponents.plafchooser.LoaderTest$2.run(LoaderTest.java:57)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:199)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:597)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
Abgesehen von den Problemen frage ich mich auch, inwiefern mein Vorgehen beim Laden wonöglich suboptimal bzw. fehleranfällig ist. Für etwaige Verbesserungsvorschläge wäre ich daher dankbar.

Gruß

~Gastredner
 
Zuletzt bearbeitet von einem Moderator:
G

Gastredner

Gast
So, ich habe meinen Ansatz mittlerweile etwas angeändert: Statt eines URLClassLoader verwende ich mittlerweile einen eigenen ClassLoader und habe damit auch begrenzt Erfolg.
Problematisch ist es aber weiterhin, wenn die geladenen Klassen versuchen, eine Datei aus dem Jar-Archiv zu laden. Bei Bildern funktioniert dies größtenteils reibungslos, aber bei Textdateien u. Ä. erhalte ich immer FileNotFoundExceptions mit der Meldung, dass das System den angegeben Pfad nicht finden könne. Die Datei selbst wird von den getResource-Methoden meines ClassLoaders problemlos gefunden. Hier zuerst einmal der StackTrace (wieder unter Verwendung von Substance):
Code:
Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: java.io.FileNotFoundException: E:\java\plaf\substance.jar\org\jvnet\substance\api\skin\gemini.colorschemes (Das System kann den angegebenen Pfad nicht finden)
	at org.jvnet.substance.utils.SubstanceColorSchemeUtilities.getColorSchemes(SubstanceColorSchemeUtilities.java:922)
	at org.jvnet.substance.api.SubstanceSkin.getColorSchemes(SubstanceSkin.java:1335)
	at org.jvnet.substance.api.skin.GeminiSkin.<init>(GeminiSkin.java:83)
	at org.jvnet.substance.api.skin.SubstanceGeminiLookAndFeel.<init>(SubstanceGeminiLookAndFeel.java:53)Loading: org.jvnet.substance.colorscheme.BottleGreenColorScheme

	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
	at java.lang.Class.newInstance0(Class.java:355)
	at java.lang.Class.newInstance(Class.java:308)
	at de.snk.snkomponents.plafchooser.LookAndFeelLoader.loadAllLookAndFeels(LookAndFeelLoader.java:120)
	at de.snk.snkomponents.plafchooser.LookAndFeelLoader.loadAllLookAndFeels(LookAndFeelLoader.java:62)
	at de.snk.snkomponents.plafchooser.LookAndFeelChooserPanel.init(LookAndFeelChooserPanel.java:71)
	at de.snk.snkomponents.plafchooser.LookAndFeelChooserPanel.<init>(LookAndFeelChooserPanel.java:56)
	at de.snk.snkomponents.plafchooser.Test.openDialog(Test.java:125)
	at de.snk.snkomponents.plafchooser.Test.actionPerformed(Test.java:149)
	at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
	at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
	at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
	at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
	at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
	at java.awt.Component.processMouseEvent(Component.java:6263)
	at javax.swing.JComponent.processMouseEvent(JComponent.java:3267)
	at java.awt.Component.processEvent(Component.java:6028)
	at java.awt.Container.processEvent(Container.java:2041)
	at java.awt.Component.dispatchEventImpl(Component.java:4630)
	at java.awt.Container.dispatchEventImpl(Container.java:2099)
	at java.awt.Component.dispatchEvent(Component.java:4460)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4574)
	at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4238)
	at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168)
	at java.awt.Container.dispatchEventImpl(Container.java:2085)
	at java.awt.Window.dispatchEventImpl(Window.java:2475)
	at java.awt.Component.dispatchEvent(Component.java:4460)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
Caused by: java.io.FileNotFoundException: E:\java\plaf\substance.jar\org\jvnet\substance\api\skin\gemini.colorschemes (Das System kann den angegebenen Pfad nicht finden)
	at java.util.zip.ZipFile.open(Native Method)
	at java.util.zip.ZipFile.<init>(ZipFile.java:114)
	at java.util.jar.JarFile.<init>(JarFile.java:133)
	at java.util.jar.JarFile.<init>(JarFile.java:70)
	at sun.net.www.protocol.jar.URLJarFile.<init>(URLJarFile.java:72)
	at sun.net.www.protocol.jar.URLJarFile.getJarFile(URLJarFile.java:48)
	at sun.net.www.protocol.jar.JarFileFactory.get(JarFileFactory.java:63)
	at sun.net.www.protocol.jar.JarURLConnection.connect(JarURLConnection.java:104)
	at sun.net.www.protocol.jar.JarURLConnection.getInputStream(JarURLConnection.java:132)
	at java.net.URL.openStream(URL.java:1010)
	at org.jvnet.substance.utils.SubstanceColorSchemeUtilities.getColorSchemes(SubstanceColorSchemeUtilities.java:785)
	... 40 more
Das Merkwürdige daran ist halt, dass mein ClassLoader die Datei als gefunden meldet:
Code:
getResource(org/jvnet/substance/api/skin/gemini.colorschemes)
Found URL: file:E:\java\plaf\substance.jar/org/jvnet/substance/api/skin/gemini.colorschemes!/
Ich kann mir diese Fehler leider nicht erklären.
Ein ähnlicher Fehler tritt auf, wenn ich auf das FH LookAndFeel zu wechseln versuche:
Code:
java.lang.Exception: java.lang.Error: java.io.FileNotFoundException: \\Flat_with_shadows(built-in)\.meta.xml (Die Syntax für den Dateinamen, Verzeichnisnamen oder die Datenträgerbezeichnung ist falsch)
	at com.shfarr.ui.plaf.fh.theme.Theme.<init>(Theme.java:75)
	at com.shfarr.ui.plaf.fh.theme.ThemeManager.getCurrentTheme(ThemeManager.java:587)
	at com.shfarr.ui.plaf.fh.FhLookAndFeel.getTheme(FhLookAndFeel.java:402)
	at com.shfarr.ui.plaf.fh.FhLookAndFeel.initComponentDefaults(FhLookAndFeel.java:376)
	at com.shfarr.ui.plaf.fh.FhLookAndFeel.initClassDefaults(FhLookAndFeel.java:82)
	at com.shfarr.ui.plaf.fh.FhLookAndFeel.getDefaults(FhLookAndFeel.java:59)
	at javax.swing.UIManager.setLookAndFeel(UIManager.java:542)
	at de.snk.snkomponents.plafchooser.LookAndFeelChooserPanel$1.run(LookAndFeelChooserPanel.java:102)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:597)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:178)
	at java.awt.Dialog$1.run(Dialog.java:1045)
	at java.awt.Dialog$3.run(Dialog.java:1097)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.awt.Dialog.show(Dialog.java:1095)
	at java.awt.Component.show(Component.java:1563)
	at java.awt.Component.setVisible(Component.java:1515)
	at java.awt.Window.setVisible(Window.java:841)
	at java.awt.Dialog.setVisible(Dialog.java:985)
	at de.snk.snkomponents.plafchooser.Test.openDialog(Test.java:130)
	at de.snk.snkomponents.plafchooser.Test.actionPerformed(Test.java:149)
	at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
	at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
	at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
	at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
	at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
	at java.awt.Component.processMouseEvent(Component.java:6263)
	at javax.swing.JComponent.processMouseEvent(JComponent.java:3267)
	at java.awt.Component.processEvent(Component.java:6028)
	at java.awt.Container.processEvent(Container.java:2041)
	at java.awt.Component.dispatchEventImpl(Component.java:4630)
	at java.awt.Container.dispatchEventImpl(Container.java:2099)
	at java.awt.Component.dispatchEvent(Component.java:4460)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4574)
	at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4238)
	at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168)
	at java.awt.Container.dispatchEventImpl(Container.java:2085)
	at java.awt.Window.dispatchEventImpl(Window.java:2475)
	at java.awt.Component.dispatchEvent(Component.java:4460)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
Caused by: java.lang.Error: java.io.FileNotFoundException: \\Flat_with_shadows(built-in)\.meta.xml (Die Syntax für den Dateinamen, Verzeichnisnamen oder die Datenträgerbezeichnung ist falsch)
	at com.shfarr.ui.plaf.fh.theme.Theme.loadMeta(Theme.java:224)
	at com.shfarr.ui.plaf.fh.theme.Theme.metaPalette(Theme.java:106)
	at com.shfarr.ui.plaf.fh.theme.Theme.<init>(Theme.java:72)
	... 47 more
Caused by: java.io.FileNotFoundException: \\Flat_with_shadows(built-in)\.meta.xml (Die Syntax für den Dateinamen, Verzeichnisnamen oder die Datenträgerbezeichnung ist falsch)
	at java.io.FileInputStream.open(Native Method)
	at java.io.FileInputStream.<init>(FileInputStream.java:106)
	at java.io.FileInputStream.<init>(FileInputStream.java:66)
	at sun.net.www.protocol.file.FileURLConnection.connect(FileURLConnection.java:70)
	at sun.net.www.protocol.file.FileURLConnection.getInputStream(FileURLConnection.java:161)
	at java.net.URL.openStream(URL.java:1010)
	at com.shfarr.io.IOUtils.load(IOUtils.java:134)
	at com.shfarr.io.IOUtils.xml2Object(IOUtils.java:116)
	at com.shfarr.ui.plaf.fh.theme.Theme.loadMeta(Theme.java:221)
	... 49 more
Auch hier kann ich mir den Fehler nicht erklären.

Ein dritter Fehler, der allerdings weit weniger schwer wiegt und bisher nur bei der Verwendung des TonicLF auftrat: Die Icons, die u. A. von den verschiedenen Abarten der JOptionPane genutzt werden, können offensichtlich nicht geladen werden. Der entsprechende Platz bleibt einfach leer, Fehlermeldungen gibt es keine. Die Icons des JFileChoosers hingegen werden geladen und korrekt angezeigt. Und die Icons der JOptionPane können bei anderen LaFs, z. B. LipstikLF, problemlos geladen und angezeigt werden. Irgendwer eine Idee, woher dies kommen könnte?

Hier der Code des ClassLoaders:
Java:
package tests;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class JarClassLoader extends ClassLoader {

	private JarFile jar;

	private static final int BUFFER_MAX = 0xFFFF;

	public JarClassLoader(ClassLoader parent, JarFile jar) {
		super();
		this.jar = jar;
	}

	@Override
	public Class<?> loadClass(String className) {
		Class<?> clazz = findLoadedClass(className);
		if (clazz == null) {
			try {
				clazz = super.loadClass(className);
			} catch (ClassNotFoundException cnfe) {
				JarEntry entry = jar.getJarEntry(className.replace('.', '/') + ".class");
				if (entry != null) {
					try {
						System.out.println("Loading: " + className);
						byte[] buffer = new byte[BUFFER_MAX];
						BufferedInputStream in = new BufferedInputStream(jar.getInputStream(entry));
						int i = 0;
						int size = 0;
						ByteArrayOutputStream bos = new ByteArrayOutputStream(BUFFER_MAX);
	                    while (i > -1) {
	                        i = in.read(buffer, 0, BUFFER_MAX);
	                        if (i > -1) {
	                            size = size + i;
	                            bos.write(buffer, 0, i);
	                        }
	                    }
	                    buffer = bos.toByteArray();
	                    in.close();
	                    bos.close();
	                    clazz = defineClass(className, buffer, 0, buffer.length);
						resolveClass(clazz);
					} catch (IOException ioe) {
						ioe.printStackTrace();
					}
				}
			}			
		}
		return clazz;
	}

	@Override
	public URL getResource(String name) {
		System.out.println("getResource(" + name + ")");
		URL url = null;
		url = super.getResource(name);
		if (url == null) {
			try {
				url = new URL("jar:file:" + jar.getName() + "/" + name + "!/");
			} catch (MalformedURLException e) {
				e.printStackTrace();
			}
		}
		if (url == null) {
			System.out.println("NULL VALUE: " + name);
		} else {
			System.out.println("Found URL: " + url.getPath());
		}
		return url;
	}

	@Override
	public InputStream getResourceAsStream(String name) {
		System.out.println("getResourceAsStream(" + name + ")");
		InputStream in = null;
		in = super.getResourceAsStream(name);
		if (in == null) {
			try {
				in = jar.getInputStream(jar.getJarEntry(name));
			} catch (IOException e) {
				e.printStackTrace();
			} catch (NullPointerException e) {
				System.err.println("NOT FOUND: " + name);	// LipstikLF sucht nach nicht vorhandenen Icons
			}
		}
		if (in == null) {
			System.out.println("NULL VALUE: " + name);
		} else {
			System.out.println("Found Stream for " + name);
		}
		return in;
	}
}
 
G

Gastredner

Gast
Danke für den Link - weiter geholfen hat der aber leider nur bedingt.
Das Schöne daran: Ich kann den Aufruf von [c]Thread.currentThread().setContextClassLoader(ClassLoader cl)[/c] durch das Registrieren des ClassLoaders beim UIManager ersetzen. Ansonsten hat die Methode aber leider keine Besserung gebracht: Es fehlen beim TonicLF weiterhin die OptionPane-Icons und das Laden der Substance-Bibliothek löst weiterhin bereits beim Laden der Klassen (oder kurz danach, vermutlich beim Instantiieren des SubstanceGeminiLookAndFeels) eine FileNotFoundException aus. Auch das FH LookAndFeel wirft weiterhin einen Error mit einer eingekapselten FileNotFoundException (Meldung: \\Flat_with_shadows(built-in)\.meta.xml (Die Syntax für den Dateinamen, Verzeichnisnamen oder die Datenträgerbezeichnung ist falsch)).
 
G

Gastredner

Gast
Okay, das Problem hat sich - größtenteils - erledigt.
Der Fehler, der die FileNotFoundExceptions beim Instantiieren der Substance-LookAndFeels auslöste, war ein falsch positioniertes ! in der URL:
Java:
url = new URL("jar:file:" + jar.getName() + "/" + name + "!/");
Das ! gehört aber vor den ersten Slash nach dem Pfad zum .jar, sprich:
Java:
url = new URL("jar:file:" + jar.getName() + "!/" + name);
Dummer Fehler. Substance läuft nun problemlos.

Die einzig verbleibenden Probleme bisher: Die immer noch fehlenden OptionPane-Icons des TonicLFs (die mir allerdings sowieso nicht ganz so gut gefielen) und das Error werfende FH LookAndFeel, wobei ich da von einem Einzelfall ausgehe (Fehlermeldung: java.io.FileNotFoundException: \\Flat_with_shadows(built-in)\.meta.xml (Die Syntax für den Dateinamen, Verzeichnisnamen oder die Datenträgerbezeichnung ist falsch)).

Falls jemandem noch etwas dazu einfallen sollte: Hilfe ist immer erwünscht.

Danke für die bisherige Hilfe,

~Gastredner
 
Zuletzt bearbeitet von einem Moderator:
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
U dynamisches JTree erstellen AWT, Swing, JavaFX & SWT 2
D Swing Dynamisches Dialog UI AWT, Swing, JavaFX & SWT 8
B 2D-Grafik Dynamisches Erstellen von Images und deren Animation AWT, Swing, JavaFX & SWT 4
M Swing Dynamisches Layout AWT, Swing, JavaFX & SWT 10
T dynamisches Koordinatenkreuz mit scalierung AWT, Swing, JavaFX & SWT 7
C Scollpane an dynamisches GridLayout anpassen? AWT, Swing, JavaFX & SWT 3
L Swing dynamisches Image-Panel in Layout einbinden AWT, Swing, JavaFX & SWT 10
N Swing Dynamisches Verhalten bei Änderung Fenstergröße AWT, Swing, JavaFX & SWT 6
trash Dynamisches Interface AWT, Swing, JavaFX & SWT 6
H LayoutManager Dynamisches Layout AWT, Swing, JavaFX & SWT 3
T Swing Dynamisches Bild AWT, Swing, JavaFX & SWT 8
T RCP-SWT dynamisches ScrolledComposite AWT, Swing, JavaFX & SWT 2
B dynamisches Spektrogramm in Java-Webanwendung AWT, Swing, JavaFX & SWT 3
M Dynamisches generieren und ausrichten von Komponenten AWT, Swing, JavaFX & SWT 11
T Dynamisches hinzufügen und entfernen von Bildern AWT, Swing, JavaFX & SWT 3
L Dynamisches Ändern der Größe in JPanel mit paint()-Methode AWT, Swing, JavaFX & SWT 8
J Dynamisches füllen von GridBagLayout: Größe der Komponenten AWT, Swing, JavaFX & SWT 4
S GUI, dynamisches Wechseln von JPanels in einem JFrame AWT, Swing, JavaFX & SWT 2
L Dynamisches Erzeugen eines Button AWT, Swing, JavaFX & SWT 2
M Schwieriges Label - Font - Problem "Dynamisches Label&a AWT, Swing, JavaFX & SWT 7
C Dynamisches Zuweisen von Daten an eine JTable zur Laufzeit AWT, Swing, JavaFX & SWT 4
C ActionListener für dynamisches Menü AWT, Swing, JavaFX & SWT 8
M Daten zufällig Einlesen aus einer Datei (binäres Format) AWT, Swing, JavaFX & SWT 7
N Dateien einlesen und in GUI immernoch auswählbar AWT, Swing, JavaFX & SWT 1
L Wörter zwischen zwei Grenzen einlesen. AWT, Swing, JavaFX & SWT 13
L Csv-Datei einlesen AWT, Swing, JavaFX & SWT 34
F RGB-Werte aus einem String einlesen AWT, Swing, JavaFX & SWT 26
Ksanatos Swing Bild (.jpg) einlesen und per Button wechseln AWT, Swing, JavaFX & SWT 9
Kanda Sorata Inhalt einer .txt Datei einlesen und in ein Label einfügen (JavaFX) AWT, Swing, JavaFX & SWT 2
M PDF einlesen und innerhalb Pane anzeigen AWT, Swing, JavaFX & SWT 5
J vom Dialogfenster ein Feld des Hauptfenster einlesen AWT, Swing, JavaFX & SWT 2
agent47 JavaFX TreeView Struktur dynamisch einlesen AWT, Swing, JavaFX & SWT 1
G .txt-Datei einlesen /formatieren in JTextfield ?? AWT, Swing, JavaFX & SWT 8
B ST Datei einlesen AWT, Swing, JavaFX & SWT 1
ZoXlike Wie kann man ArrayList in JTabel einlesen? [WindowBuilder] AWT, Swing, JavaFX & SWT 1
F In Action Listener TextFields einlesen und prüfen. Abbruch bei falschen Eingaben. Wie mache ich das? AWT, Swing, JavaFX & SWT 2
R einzelne Zeichen in jTable einlesen AWT, Swing, JavaFX & SWT 10
T Swing HTML Text aus JLabel ohne "HTML-Tags" in String einlesen AWT, Swing, JavaFX & SWT 5
L JavaFX: Bild in Image einlesen AWT, Swing, JavaFX & SWT 11
T Dateipfad mit GUI einlesen AWT, Swing, JavaFX & SWT 3
M Barcode Scanner einlesen AWT, Swing, JavaFX & SWT 12
B AWT Mit TextField Zahlen einlesen lassen AWT, Swing, JavaFX & SWT 34
A Swing von Textdatei einlesen und per JLabel anzeigen AWT, Swing, JavaFX & SWT 2
B Problem mit Passwort einlesen und vergleichen AWT, Swing, JavaFX & SWT 2
H * Einlesen von Text-Dateien & Zeichensatz bestimmen AWT, Swing, JavaFX & SWT 2
R Swing XML Datei in JTree, Problem mit Daten einlesen AWT, Swing, JavaFX & SWT 34
C Image einlesen AWT, Swing, JavaFX & SWT 5
D Pixel in ein Array einlesen AWT, Swing, JavaFX & SWT 2
N Swing Problem beim Einlesen von Jtable in Array AWT, Swing, JavaFX & SWT 5
K Per ComboBox Dateien einlesen AWT, Swing, JavaFX & SWT 23
W HTML-Text mit relativer URL in JEditorPane einlesen AWT, Swing, JavaFX & SWT 10
S Tutorial zum Excel Tabelle in JTable einlesen? AWT, Swing, JavaFX & SWT 4
P Fehler beim Einlesen eines JTextFields AWT, Swing, JavaFX & SWT 2
J Dateien einlesen AWT, Swing, JavaFX & SWT 3
J Einlesen aus Datei AWT, Swing, JavaFX & SWT 2
B JTable Wert in Vector einlesen AWT, Swing, JavaFX & SWT 4
K double / int einlesen? AWT, Swing, JavaFX & SWT 12
R Bild einlesen und manipulieren AWT, Swing, JavaFX & SWT 3
T JTextArea einlesen mit AWT, Swing, JavaFX & SWT 6
G JCombobox -> daten einlesen AWT, Swing, JavaFX & SWT 4
F Einlesen von text in textArea mittels for-schleife AWT, Swing, JavaFX & SWT 3
P Bild im TIFF oder BMP Format einlesen AWT, Swing, JavaFX & SWT 3
M Einlesen in JTable AWT, Swing, JavaFX & SWT 5
N Tastatur Zeichen einlesen ohne sichtbares Fenster AWT, Swing, JavaFX & SWT 8
A Datei einlesen und Inhalt in JList (Tabbed Pane) anzeigen? AWT, Swing, JavaFX & SWT 11
J DefaultTableModel einlesen aus *txt AWT, Swing, JavaFX & SWT 2
S Bild einlesen AWT, Swing, JavaFX & SWT 7
H LookAndFeel LookAndFeels mischen AWT, Swing, JavaFX & SWT 4
A Seiten für freie LookAndFeels AWT, Swing, JavaFX & SWT 3
N Unterschiedliche LookAndFeels bei zwei Frames? AWT, Swing, JavaFX & SWT 4

Ähnliche Java Themen

Neue Themen


Oben