1 /* 2 * Copyright (c) 2017 Helmut Neemann 3 * Use of this source code is governed by the GPL v3 license 4 * that can be found in the LICENSE file. 5 */ 6 package de.neemann.digital.draw.library; 7 8 import de.neemann.digital.core.element.ElementTypeDescription; 9 import de.neemann.digital.draw.shapes.ShapeFactory; 10 import de.neemann.digital.lang.Lang; 11 12 import java.io.File; 13 import java.io.IOException; 14 import java.net.URL; 15 import java.net.URLClassLoader; 16 import java.util.ArrayList; 17 import java.util.Iterator; 18 import java.util.jar.Attributes; 19 import java.util.jar.JarFile; 20 import java.util.jar.Manifest; 21 22 /** 23 * Used to attach custom components 24 */ 25 public class JarComponentManager implements ComponentManager, Iterable<JarComponentManager.AdditionalShape> { 26 private ElementLibrary library; 27 private ArrayList<AdditionalShape> additionalShapes; 28 JarComponentManager(ElementLibrary library)29 JarComponentManager(ElementLibrary library) { 30 this.library = library; 31 additionalShapes = new ArrayList<>(); 32 } 33 34 @Override addComponent(String nodePath, ElementTypeDescription description)35 public void addComponent(String nodePath, ElementTypeDescription description) throws InvalidNodeException { 36 library.findNode(nodePath).add(description); 37 } 38 39 @Override addComponent(String nodePath, ElementTypeDescription description, ShapeFactory.Creator shape)40 public void addComponent(String nodePath, ElementTypeDescription description, ShapeFactory.Creator shape) throws InvalidNodeException { 41 library.findNode(nodePath).add(description); 42 additionalShapes.add(new AdditionalShape(description, shape)); 43 } 44 45 @Override iterator()46 public Iterator<AdditionalShape> iterator() { 47 return additionalShapes.iterator(); 48 } 49 50 51 /** 52 * Loads the components from a jar file 53 * 54 * @param file the jar file 55 * @throws IOException IOException 56 * @throws InvalidNodeException InvalidNodeException 57 */ loadJar(File file)58 public void loadJar(File file) throws IOException, InvalidNodeException { 59 Manifest manifest; 60 try (JarFile jarFile = new JarFile(file)) { 61 manifest = jarFile.getManifest(); 62 } 63 if (manifest == null) 64 throw new IOException(Lang.get("err_noManifestFound")); 65 Attributes attr = manifest.getMainAttributes(); 66 String main = attr.getValue("Main-Class"); 67 if (main == null) 68 throw new IOException(Lang.get("err_noMainFoundInManifest")); 69 70 URLClassLoader cl = new URLClassLoader(new URL[]{file.toURI().toURL()}); 71 72 try { 73 Class<?> c = cl.loadClass(main); 74 ComponentSource cs = (ComponentSource) c.newInstance(); 75 cs.registerComponents(this); 76 } catch (ClassNotFoundException e) { 77 throw new IOException(Lang.get("err_mainClass_N_NotFound", main)); 78 } catch (IllegalAccessException | InstantiationException e) { 79 throw new IOException(Lang.get("err_couldNotInitializeMainClass_N", main)); 80 } 81 } 82 83 /** 84 * A additional shape 85 */ 86 public static class AdditionalShape { 87 private final ElementTypeDescription description; 88 private final ShapeFactory.Creator shape; 89 AdditionalShape(ElementTypeDescription description, ShapeFactory.Creator shape)90 AdditionalShape(ElementTypeDescription description, ShapeFactory.Creator shape) { 91 this.description = description; 92 this.shape = shape; 93 } 94 95 /** 96 * @return the description of the component 97 */ getDescription()98 public ElementTypeDescription getDescription() { 99 return description; 100 } 101 102 /** 103 * @return the shape to use 104 */ getShape()105 public ShapeFactory.Creator getShape() { 106 return shape; 107 } 108 } 109 } 110