1 package org.daisy.pipeline.modules.impl;
2
3 import java.net.URI;
4 import java.net.URL;
5 import java.nio.file.NoSuchFileException;
6 import java.util.LinkedList;
7
8 import org.daisy.pipeline.modules.Component;
9 import org.daisy.pipeline.modules.Module;
10 import org.daisy.pipeline.modules.ModuleRegistry;
11 import org.daisy.pipeline.modules.ResolutionException;
12 import org.daisy.pipeline.xmlcatalog.XmlCatalogParser;
13 import org.osgi.service.component.annotations.Activate;
14 import org.osgi.service.component.annotations.Reference;
15 import org.osgi.service.component.annotations.ReferenceCardinality;
16 import org.osgi.service.component.annotations.ReferencePolicy;
17 import org.slf4j.Logger;
18 import org.slf4j.LoggerFactory;
19 import org.slf4j.helpers.NOPLogger;
20
21 @org.osgi.service.component.annotations.Component(
22 name = "org.daisy.pipeline.modules.impl.Module_dtbook_utils",
23 service = { Module.class }
24 )
25 public class Module_dtbook_utils extends Module {
26
27 private static final Logger logger = LoggerFactory.getLogger(Module_dtbook_utils.class);
28
29 private boolean initialized = false;
30 private XmlCatalogParser catalogParser;
31 private ModuleRegistry moduleRegistry;
32 private final LinkedList<Component> componentsToAdd;
33 private final LinkedList<Component> componentsBeingAdded;
34
35 public Module_dtbook_utils() {
36 super("dtbook-utils",
37 "5.1.1",
38 "DAISY Pipeline 2 module :: DTBook Utils");
39 componentsToAdd = new LinkedList<>();
40 componentsBeingAdded = new LinkedList<>();
41 }
42
43 @Reference(
44 name = "XmlCatalogParser",
45 unbind = "-",
46 service = XmlCatalogParser.class,
47 cardinality = ReferenceCardinality.MANDATORY,
48 policy = ReferencePolicy.STATIC
49 )
50 public void setParser(XmlCatalogParser parser) {
51 catalogParser = parser;
52 }
53
54 @Reference(
55 name = "ModuleRegistry",
56 unbind = "-",
57 service = ModuleRegistry.class,
58 cardinality = ReferenceCardinality.MANDATORY,
59 policy = ReferencePolicy.STATIC
60 )
61 public void setModuleRegistry(ModuleRegistry registry) {
62 moduleRegistry = registry;
63 }
64
65 private void tryResolveComponent(String uri, String versionRange) throws ResolutionException {
66 if (moduleRegistry.getModuleByComponent(URI.create(uri), versionRange) == null)
67 throw new ResolutionException("Unresolved dependency " + uri + " with version=" + versionRange);
68 }
69
70 @Activate
71 protected void init() {
72 logger.debug("Initializing module " + getName());
73 Module tmpModule = new Module(getName(), getVersion(), getTitle()) {
74 @Override public void resolveDependencies() {}
75 @Override public Logger getLogger() { return NOPLogger.NOP_LOGGER; }
76 };
77 Module.parseCatalog(tmpModule, catalogParser);
78 for (String e : tmpModule.getEntities()) {
79 addEntity(tmpModule.getEntity(e));
80 logger.debug("Loaded entity: " + e);
81 }
82 for (URI c : tmpModule.getComponents()) {
83 components.put(c, () -> null);
84 componentsToAdd.add(tmpModule.getComponent(c));
85 }
86 logger.debug("Module " + getName() + " initialized, but dependencies have not been resolved yet");
87 }
88
89
90
91
92
93
94 @Override
95 public void resolveDependencies() {
96 if (!initialized) {
97 boolean recursive = !componentsBeingAdded.isEmpty();
98 if (recursive)
99 logger.debug("Resolving dependencies of module " + getName() + " (continuing in recursive call)");
100 else
101 logger.debug("Resolving dependencies of module " + getName());
102 while (true) {
103 if (componentsToAdd.isEmpty()) {
104 if (componentsBeingAdded.isEmpty())
105 break;
106 componentsToAdd.addAll(componentsBeingAdded);
107 componentsBeingAdded.clear();
108 }
109 Component c = componentsToAdd.poll();
110 componentsBeingAdded.add(c);
111 if (addComponent(c))
112 logger.debug("Loaded component: " + c.getURI());
113 componentsBeingAdded.remove(c);
114 componentsToAdd.remove(c);
115 }
116 if (!initialized)
117 logger.debug("Done resolving dependencies of module " + getName());
118 initialized = true;
119 }
120 }
121
122 @Override
123 protected boolean addComponent(Component component) {
124 String name = component.getURI().toString();
125 try {
126 if ("http://www.daisy.org/pipeline/modules/dtbook-utils/library.xpl".equals(name)) {
127 tryResolveComponent("http://www.daisy.org/pipeline/modules/mediatype-utils/library.xpl",
128 "[2.0.2,3.0.0)");
129 tryResolveComponent("http://www.daisy.org/pipeline/modules/css-utils/library.xpl",
130 "[6.0.0,7.0.0)");
131 tryResolveComponent("http://www.daisy.org/pipeline/modules/file-utils/library.xsl",
132 "[4.3.1,5.0.0)");
133 tryResolveComponent("http://www.daisy.org/pipeline/modules/fileset-utils/library.xpl",
134 "[6.1.4,7.0.0)");
135 tryResolveComponent("http://www.daisy.org/pipeline/modules/validation-utils/library.xpl",
136 "[2.0.1,3.0.0)");
137 tryResolveComponent("http://www.daisy.org/pipeline/modules/common-utils/library.xpl",
138 "[3.1.2,4.0.0)");
139 tryResolveComponent("http://www.daisy.org/pipeline/modules/mathml-utils/mathml2.rng",
140 "[1.0.3,2.0.0)");
141 tryResolveComponent("http://www.daisy.org/pipeline/modules/mathml-utils/mathml3.rng",
142 "[1.0.3,2.0.0)");
143 }
144 } catch (ResolutionException re) {
145 logger.warn("Component " + component.getURI() + " can not be loaded: " + re.getMessage());
146 return false;
147 }
148 return super.addComponent(component);
149 }
150
151 private void tryResolveXPathExtensionFunction(String className) throws ResolutionException {
152 try {
153 getResource("../" + className.replace('.', '/') + ".class");
154 return;
155 } catch (NoSuchFileException e) {
156 }
157
158 try {
159 Class.forName(className);
160 return;
161 } catch (Throwable e) {
162 }
163 throw new ResolutionException(
164 "Unresolved Java dependency: no class " + className + " found on the class path");
165 }
166
167 private URL resource1 = null;
168
169 @Override
170 public URL getResource(String path) throws NoSuchFileException {
171 URL url = super.getResource(path);
172 try {
173 if (resource1 == null)
174 resource1 = super.getResource("../xml/fix-dtbook/dtbook-cleaner.script.xpl");
175 if (url.equals(resource1)) {
176 tryResolveComponent("http://www.daisy.org/pipeline/modules/mediatype-utils/library.xpl",
177 "[2.0.2,3.0.0)");
178 tryResolveComponent("http://www.daisy.org/pipeline/modules/css-utils/library.xpl",
179 "[6.0.0,7.0.0)");
180 tryResolveComponent("http://www.daisy.org/pipeline/modules/file-utils/library.xsl",
181 "[4.3.1,5.0.0)");
182 tryResolveXPathExtensionFunction("org.daisy.pipeline.dtbook.saxon.impl.DTBookCleanerLibrary");
183 tryResolveComponent("http://www.daisy.org/pipeline/modules/fileset-utils/library.xpl",
184 "[6.1.4,7.0.0)");
185 tryResolveComponent("http://www.daisy.org/pipeline/modules/dtbook-break-detection/library.xpl",
186 "[2.0.6,3.0.0)");
187 tryResolveComponent("http://www.daisy.org/pipeline/modules/validation-utils/library.xpl",
188 "[2.0.1,3.0.0)");
189 tryResolveComponent("http://www.daisy.org/pipeline/modules/common-utils/library.xpl",
190 "[3.1.2,4.0.0)");
191 tryResolveComponent("http://www.daisy.org/pipeline/modules/mathml-utils/mathml2.rng",
192 "[1.0.3,2.0.0)");
193 tryResolveComponent("http://www.daisy.org/pipeline/modules/mathml-utils/mathml3.rng",
194 "[1.0.3,2.0.0)");
195 return url;
196 }
197 } catch (ResolutionException re) {
198 throw new NoSuchFileException(
199 "Resource " + path + " in module " + getName() + " can not be loaded: " + re.getMessage());
200 }
201 return url;
202 }
203 }