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