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