PageRenderTime 23ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/atlassian-plugins-schema/src/main/java/com/atlassian/plugin/schema/spi/DocumentBasedSchema.java

https://bitbucket.org/purewind/atlassian-plugins
Java | 235 lines | 189 code | 42 blank | 4 comment | 3 complexity | 1b51859623686ff521494eaee85f9b95 MD5 | raw file
  1. package com.atlassian.plugin.schema.spi;
  2. import com.atlassian.fugue.Option;
  3. import com.atlassian.plugin.Permissions;
  4. import com.atlassian.plugin.util.resource.AlternativeResourceLoader;
  5. import com.atlassian.security.xml.SecureXmlParserFactory;
  6. import com.google.common.collect.ImmutableSet;
  7. import org.dom4j.Document;
  8. import org.dom4j.DocumentException;
  9. import org.dom4j.io.SAXReader;
  10. import java.net.URL;
  11. import static com.atlassian.fugue.Option.option;
  12. import static com.google.common.base.Preconditions.checkNotNull;
  13. import static java.util.Collections.emptySet;
  14. /**
  15. * Schema based on a XML document resource.
  16. */
  17. public final class DocumentBasedSchema implements Schema {
  18. private final String elementName;
  19. private final Option<String> name;
  20. private final Option<String> description;
  21. private final String path;
  22. private final String fileName;
  23. private final String complexType;
  24. private final String maxOccurs;
  25. private final Iterable<String> requiredPermissions;
  26. private final Iterable<String> optionalPermissions;
  27. private final AlternativeResourceLoader resourceLoader;
  28. private final SchemaTransformer schemaTransformer;
  29. private DocumentBasedSchema(String elementName,
  30. String name,
  31. String description,
  32. String path,
  33. String fileName,
  34. String complexType,
  35. String maxOccurs,
  36. Iterable<String> requiredPermissions,
  37. Iterable<String> optionalPermissions,
  38. AlternativeResourceLoader resourceLoader,
  39. SchemaTransformer schemaTransformer) {
  40. this.elementName = elementName;
  41. this.name = option(name);
  42. this.description = option(description);
  43. this.path = path;
  44. this.fileName = fileName;
  45. this.complexType = complexType;
  46. this.maxOccurs = maxOccurs;
  47. this.requiredPermissions = requiredPermissions;
  48. this.optionalPermissions = optionalPermissions;
  49. this.resourceLoader = resourceLoader;
  50. this.schemaTransformer = schemaTransformer;
  51. }
  52. @Override
  53. public String getName() {
  54. return name.getOrElse(IdUtils.dashesToTitle(elementName));
  55. }
  56. @Override
  57. public String getDescription() {
  58. return description.getOrElse("A " + name + " module");
  59. }
  60. @Override
  61. public String getFileName() {
  62. return fileName;
  63. }
  64. @Override
  65. public String getElementName() {
  66. return elementName;
  67. }
  68. @Override
  69. public String getComplexType() {
  70. return complexType;
  71. }
  72. @Override
  73. public String getMaxOccurs() {
  74. return maxOccurs;
  75. }
  76. @Override
  77. public Iterable<String> getRequiredPermissions() {
  78. return requiredPermissions;
  79. }
  80. @Override
  81. public Iterable<String> getOptionalPermissions() {
  82. return optionalPermissions;
  83. }
  84. @Override
  85. public Document getDocument() {
  86. return getDocument(resourceLoader, path, schemaTransformer);
  87. }
  88. public static DynamicSchemaBuilder builder() {
  89. return new DynamicSchemaBuilder();
  90. }
  91. public static DynamicSchemaBuilder builder(String id) {
  92. return new DynamicSchemaBuilder(id);
  93. }
  94. public static class DynamicSchemaBuilder {
  95. private String name;
  96. private String description;
  97. private String path;
  98. private String fileName;
  99. private String elementName;
  100. private String complexType;
  101. private String maxOccurs = "unbounded";
  102. // default set of permissions for modules is pretty much unrestricted access to backend and front-end code
  103. private Iterable<String> requiredPermissions = ImmutableSet.of(Permissions.EXECUTE_JAVA, Permissions.GENERATE_ANY_HTML);
  104. private Iterable<String> optionalPermissions = emptySet();
  105. private AlternativeResourceLoader resourceLoader;
  106. private SchemaTransformer schemaTransformer = SchemaTransformer.IDENTITY;
  107. public DynamicSchemaBuilder() {
  108. }
  109. public DynamicSchemaBuilder(String elementName) {
  110. this.elementName = elementName;
  111. this.fileName = elementName + ".xsd";
  112. this.path = "/xsd/" + this.fileName;
  113. this.complexType = IdUtils.dashesToCamelCase(elementName) + "Type";
  114. }
  115. public DynamicSchemaBuilder setName(String name) {
  116. this.name = name;
  117. return this;
  118. }
  119. public DynamicSchemaBuilder setDescription(String description) {
  120. this.description = description;
  121. return this;
  122. }
  123. public DynamicSchemaBuilder setPath(String path) {
  124. this.path = path;
  125. return this;
  126. }
  127. public DynamicSchemaBuilder setFileName(String fileName) {
  128. this.fileName = fileName;
  129. return this;
  130. }
  131. public DynamicSchemaBuilder setElementName(String elementName) {
  132. this.elementName = elementName;
  133. return this;
  134. }
  135. public DynamicSchemaBuilder setRequiredPermissions(Iterable<String> permissions) {
  136. this.requiredPermissions = permissions;
  137. return this;
  138. }
  139. public DynamicSchemaBuilder setOptionalPermissions(Iterable<String> permissions) {
  140. this.optionalPermissions = permissions;
  141. return this;
  142. }
  143. public DynamicSchemaBuilder setComplexType(String complexType) {
  144. this.complexType = complexType;
  145. return this;
  146. }
  147. public DynamicSchemaBuilder setMaxOccurs(String maxOccurs) {
  148. this.maxOccurs = maxOccurs;
  149. return this;
  150. }
  151. public DynamicSchemaBuilder setResourceLoader(AlternativeResourceLoader resourceLoader) {
  152. this.resourceLoader = resourceLoader;
  153. return this;
  154. }
  155. public DynamicSchemaBuilder setTransformer(SchemaTransformer schemaTransformer) {
  156. this.schemaTransformer = schemaTransformer;
  157. return this;
  158. }
  159. public boolean validate() {
  160. return resourceLoader.getResource(path) != null;
  161. }
  162. public DocumentBasedSchema build() {
  163. checkNotNull(elementName);
  164. checkNotNull(fileName);
  165. checkNotNull(complexType);
  166. checkNotNull(resourceLoader);
  167. checkNotNull(requiredPermissions);
  168. checkNotNull(optionalPermissions);
  169. return new DocumentBasedSchema(elementName, name, description, path, fileName, complexType, maxOccurs,
  170. requiredPermissions, optionalPermissions, resourceLoader,
  171. schemaTransformer);
  172. }
  173. }
  174. private static Document getDocument(AlternativeResourceLoader resourceLoader, String path, SchemaTransformer transformer) {
  175. final URL sourceUrl = resourceLoader.getResource(path);
  176. if (sourceUrl == null) {
  177. throw new IllegalStateException("Cannot find schema document " + path);
  178. }
  179. return transformer.transform(parseDocument(sourceUrl));
  180. }
  181. private static Document parseDocument(URL xmlUrl) {
  182. Document source;
  183. try {
  184. source = createSecureSaxReader().read(xmlUrl);
  185. } catch (DocumentException e) {
  186. throw new IllegalArgumentException("Unable to parse XML", e);
  187. }
  188. return source;
  189. }
  190. public static SAXReader createSecureSaxReader() {
  191. return new SAXReader(SecureXmlParserFactory.newXmlReader(), false);
  192. }
  193. }