PageRenderTime 46ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/impl/src/main/java/org/geomajas/spring/DependencyCheckPostProcessor.java

https://github.com/mostafa-java/geomajas-project-server
Java | 280 lines | 182 code | 27 blank | 71 comment | 50 complexity | deb4469560fdc7da36008e835c17a198 MD5 | raw file
Possible License(s): AGPL-3.0
  1. /*
  2. * This is part of Geomajas, a GIS framework, http://www.geomajas.org/.
  3. *
  4. * Copyright 2008-2014 Geosparc nv, http://www.geosparc.com/, Belgium.
  5. *
  6. * The program is available in open source according to the GNU Affero
  7. * General Public License. All contributions in this program are covered
  8. * by the Geomajas Contributors License Agreement. For full licensing
  9. * details, see LICENSE.txt in the project root.
  10. */
  11. package org.geomajas.spring;
  12. import java.util.HashMap;
  13. import java.util.List;
  14. import java.util.Map;
  15. import javax.annotation.PostConstruct;
  16. import org.geomajas.global.ExceptionCode;
  17. import org.geomajas.global.GeomajasException;
  18. import org.geomajas.global.PluginInfo;
  19. import org.geomajas.global.PluginVersionInfo;
  20. import org.geomajas.service.TestRecorder;
  21. import org.springframework.beans.factory.annotation.Autowired;
  22. import org.springframework.stereotype.Component;
  23. /**
  24. * Spring configuration post-processor which verifies that all registered plug-ins (including the back-end), have their
  25. * their declared dependency requirements met.
  26. *
  27. * @author Joachim Van der Auwera
  28. */
  29. @Component
  30. public class DependencyCheckPostProcessor {
  31. /** Group name for recorder. */
  32. protected static final String GROUP = "depcheck";
  33. /** Value which needs to be recorded. */
  34. protected static final String VALUE = "done";
  35. private static final String EXPR_START = "$";
  36. @Autowired(required = false)
  37. protected Map<String, PluginInfo> declaredPlugins;
  38. @Autowired
  39. private TestRecorder recorder;
  40. /**
  41. * Finish initializing.
  42. *
  43. * @throws GeomajasException oops
  44. */
  45. @PostConstruct
  46. protected void checkPluginDependencies() throws GeomajasException {
  47. if ("true".equals(System.getProperty("skipPluginDependencyCheck"))) {
  48. return;
  49. }
  50. if (null == declaredPlugins) {
  51. return;
  52. }
  53. // start by going through all plug-ins to build a map of versions for plug-in keys
  54. // includes verification that each key is only used once
  55. Map<String, String> versions = new HashMap<String, String>();
  56. for (PluginInfo plugin : declaredPlugins.values()) {
  57. String name = plugin.getVersion().getName();
  58. String version = plugin.getVersion().getVersion();
  59. // check for multiple plugin with same name but different versions (duplicates allowed for jar+source dep)
  60. if (null != version) {
  61. String otherVersion = versions.get(name);
  62. if (null != otherVersion) {
  63. if (!version.startsWith(EXPR_START)) {
  64. if (!otherVersion.startsWith(EXPR_START) && !otherVersion.equals(version)) {
  65. throw new GeomajasException(ExceptionCode.DEPENDENCY_CHECK_INVALID_DUPLICATE,
  66. name, version, versions.get(name));
  67. }
  68. versions.put(name, version);
  69. }
  70. } else {
  71. versions.put(name, version);
  72. }
  73. }
  74. }
  75. // Check dependencies
  76. StringBuilder message = new StringBuilder();
  77. String backendVersion = versions.get("Geomajas");
  78. for (PluginInfo plugin : declaredPlugins.values()) {
  79. String name = plugin.getVersion().getName();
  80. message.append(checkVersion(name, "Geomajas back-end", plugin.getBackendVersion(), backendVersion));
  81. List<PluginVersionInfo> dependencies = plugin.getDependencies();
  82. if (null != dependencies) {
  83. for (PluginVersionInfo dependency : plugin.getDependencies()) {
  84. String depName = dependency.getName();
  85. message.append(checkVersion(name, depName, dependency.getVersion(), versions.get(depName)));
  86. }
  87. }
  88. dependencies = plugin.getOptionalDependencies();
  89. if (null != dependencies) {
  90. for (PluginVersionInfo dependency : dependencies) {
  91. String depName = dependency.getName();
  92. String availableVersion = versions.get(depName);
  93. if (null != availableVersion) {
  94. message.append(checkVersion(name, depName, dependency.getVersion(), versions.get(depName)));
  95. }
  96. }
  97. }
  98. }
  99. if (message.length() > 0) {
  100. throw new GeomajasException(ExceptionCode.DEPENDENCY_CHECK_FAILED, message.toString());
  101. }
  102. recorder.record(GROUP, VALUE);
  103. }
  104. /**
  105. * Check the version to assure it is allowed.
  106. *
  107. * @param pluginName plugin name which needs the dependency
  108. * @param dependency dependency which needs to be verified
  109. * @param requestedVersion requested/minimum version
  110. * @param availableVersion available version
  111. * @return version check problem or empty string when all is fine
  112. */
  113. String checkVersion(String pluginName, String dependency, String requestedVersion, String availableVersion) {
  114. if (null == availableVersion) {
  115. return "Dependency " + dependency + " not found for " + pluginName + ", version " + requestedVersion +
  116. " or higher needed.\n";
  117. }
  118. if (requestedVersion.startsWith(EXPR_START) || availableVersion.startsWith(EXPR_START)) {
  119. return "";
  120. }
  121. Version requested = new Version(requestedVersion);
  122. Version available = new Version(availableVersion);
  123. if (requested.getMajor() != available.getMajor()) {
  124. return "Dependency " + dependency + " is provided in a incompatible API version for plug-in " +
  125. pluginName + ", which requests version " + requestedVersion +
  126. ", but version " + availableVersion + " supplied.\n";
  127. }
  128. if (requested.after(available)) {
  129. return "Dependency " + dependency + " too old for " + pluginName + ", version " + requestedVersion +
  130. " or higher needed, but version " + availableVersion + " supplied.\n";
  131. }
  132. return "";
  133. }
  134. /** Parsed version representation. */
  135. public static class Version {
  136. private int major, minor, revision;
  137. private String qualifier;
  138. /**
  139. * Construct a version from a version string.
  140. *
  141. * @param version version string
  142. */
  143. public Version(String version) {
  144. int pos;
  145. String part;
  146. pos = getSeparatorPosition(version);
  147. part = version.substring(0, pos);
  148. version = getRest(version, pos);
  149. try {
  150. major = Integer.parseInt(part);
  151. } catch (NumberFormatException nfe) {
  152. qualifier = part;
  153. return;
  154. }
  155. pos = getSeparatorPosition(version);
  156. part = version.substring(0, pos);
  157. version = getRest(version, pos);
  158. try {
  159. minor = Integer.parseInt(part);
  160. } catch (NumberFormatException nfe) {
  161. qualifier = part;
  162. return;
  163. }
  164. pos = getSeparatorPosition(version);
  165. part = version.substring(0, pos);
  166. version = getRest(version, pos);
  167. try {
  168. revision = Integer.parseInt(part);
  169. } catch (NumberFormatException nfe) {
  170. qualifier = part;
  171. return;
  172. }
  173. qualifier = version;
  174. }
  175. private int getSeparatorPosition(String str) {
  176. int pos1 = str.indexOf('.');
  177. int pos2 = str.indexOf('-');
  178. if (pos1 >= 0) {
  179. if (pos2 >= 0) {
  180. return Math.min(pos1, pos2);
  181. }
  182. return pos1;
  183. }
  184. if (pos2 >= 0) {
  185. return pos2;
  186. }
  187. return str.length();
  188. }
  189. private String getRest(String str, int pos) {
  190. if (str.length() > pos) {
  191. return str.substring(pos + 1);
  192. }
  193. return "";
  194. }
  195. /**
  196. * Check whether this version is more recent as the other version.
  197. * Note that we explicitly allow intermediate milestone releases.
  198. * When there is a qualifier, we order them alphabetically. This way a 1.0.0-M1 precedes 1.0.0-SNAPSHOT which
  199. * precedes 1.0.0-ZZZ.
  200. *
  201. * @param other version to compare with
  202. * @return false when other is older or equal, true when other is younger
  203. */
  204. public boolean after(Version other) {
  205. if (major > other.major) {
  206. return true;
  207. }
  208. if (major == other.major && minor > other.minor) {
  209. return true;
  210. }
  211. if (major == other.major && minor == other.minor && revision > other.revision) {
  212. return true;
  213. }
  214. if (major == other.major && minor == other.minor && revision == other.revision) {
  215. return ("".equals(qualifier) && !("".equals(other.qualifier))) ||
  216. (!"".equals(other.qualifier) && qualifier.compareTo(other.qualifier) > 0);
  217. }
  218. return false;
  219. }
  220. /**
  221. * Get major version number, the 1 in 1.2.3-SNAPSHOT.
  222. *
  223. * @return major version number
  224. */
  225. public int getMajor() {
  226. return major;
  227. }
  228. /**
  229. * Get minor version number, the 2 in 1.2.3-SNAPSHOT.
  230. *
  231. * @return minor version number
  232. */
  233. public int getMinor() {
  234. return minor;
  235. }
  236. /**
  237. * Get revision, the 3 in 1.2.3-SNAPSHOT.
  238. *
  239. * @return revision
  240. */
  241. public int getRevision() {
  242. return revision;
  243. }
  244. /**
  245. * Get qualifier, the SNAPSHOT in 1.2.3-SNAPSHOT.
  246. *
  247. * @return qualifier or ""
  248. */
  249. public String getQualifier() {
  250. return qualifier;
  251. }
  252. }
  253. }