Skip to content

Commit 28f470f

Browse files
committed
Added validation for duplicate REST service extensions and transforms.
1 parent dd02623 commit 28f470f

File tree

5 files changed

+260
-6
lines changed

5 files changed

+260
-6
lines changed

marklogic-data-hub/src/main/java/com/marklogic/hub/Scaffolding.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,11 @@ private static void writeFile(String srcFile, Path dstFile)
103103
}
104104

105105
public static void createRestExtension(String entityName, String extensionName,
106-
FlowType flowType, PluginFormat pluginFormat, File userlandDir) throws IOException {
106+
FlowType flowType, PluginFormat pluginFormat, File userlandDir) throws IOException, ScaffoldingValidationException {
107107
LOGGER.info(extensionName);
108+
if(!ScaffoldingValidator.isUniqueRestServiceExtension(userlandDir, extensionName)) {
109+
throw new ScaffoldingValidationException("A rest service extension with the same name as " + extensionName + " already exists.");
110+
}
108111
String scaffoldRestServicesPath = "scaffolding/rest/services/";
109112
String fileContent = getFileContent(scaffoldRestServicesPath + pluginFormat + "/template." + pluginFormat, extensionName);
110113
File dstFile = createEmptyRestExtensionFile(entityName, extensionName, flowType, pluginFormat, userlandDir);
@@ -113,8 +116,11 @@ public static void createRestExtension(String entityName, String extensionName,
113116
}
114117

115118
public static void createRestTransform(String entityName, String transformName,
116-
FlowType flowType, PluginFormat pluginFormat, File userlandDir) throws IOException {
119+
FlowType flowType, PluginFormat pluginFormat, File userlandDir) throws IOException, ScaffoldingValidationException {
117120
LOGGER.info(transformName);
121+
if(!ScaffoldingValidator.isUniqueRestTransform(userlandDir, transformName)) {
122+
throw new ScaffoldingValidationException("A rest transform with the same name as " + transformName + " already exists.");
123+
}
118124
String scaffoldRestTransformsPath = "scaffolding/rest/transforms/";
119125
String fileContent = getFileContent(scaffoldRestTransformsPath + pluginFormat + "/template." + pluginFormat, transformName);
120126
File dstFile = createEmptyRestTransformFile(entityName, transformName, flowType, pluginFormat, userlandDir);
@@ -204,4 +210,13 @@ private static String getFileContent(String srcFile, String placeholder) throws
204210
}
205211
return output.toString();
206212
}
213+
214+
public static String getAbsolutePath(String first, String... more) {
215+
StringBuilder absolutePath = new StringBuilder(first);
216+
for (String path : more) {
217+
absolutePath.append(File.separator);
218+
absolutePath.append(path);
219+
}
220+
return absolutePath.toString();
221+
}
207222
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright 2012-2016 MarkLogic Corporation
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.marklogic.hub;
17+
18+
public class ScaffoldingValidationException extends Exception {
19+
20+
private static final long serialVersionUID = 3058767542162618337L;
21+
22+
public ScaffoldingValidationException(String message) {
23+
super(message);
24+
}
25+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package com.marklogic.hub;
2+
3+
import java.io.File;
4+
import java.util.regex.Pattern;
5+
6+
import com.marklogic.hub.flow.FlowType;
7+
8+
public class ScaffoldingValidator {
9+
10+
public static boolean isUniqueRestServiceExtension(File pluginsDir, String name) {
11+
String entityNameFilter = "[a-zA-Z0-9_.-]+";
12+
String flowTypeFilter = "(" + FlowType.INPUT + "|" + FlowType.CONFORMANCE + ")";
13+
String pluginFormatFilter = "(" + PluginFormat.XQUERY + "|" + PluginFormat.JAVASCRIPT + ")";
14+
String absoluteFilePathFilter = Scaffolding.getAbsolutePath(pluginsDir.getAbsolutePath(), "entities", entityNameFilter, flowTypeFilter, "REST", "services", name + "." + pluginFormatFilter);
15+
return !checkIfFileExists(pluginsDir, absoluteFilePathFilter);
16+
}
17+
18+
private static boolean checkIfFileExists(File rootDirectory, String absoluteFilePathFilter) {
19+
File[] list = rootDirectory.listFiles();
20+
if (list != null) {
21+
for (File file : list) {
22+
if (file.isDirectory()) {
23+
if(checkIfFileExists(file, absoluteFilePathFilter)) {
24+
return true;
25+
}
26+
} else {
27+
if(Pattern.matches(absoluteFilePathFilter,file.getAbsolutePath())) {
28+
return true;
29+
}
30+
}
31+
}
32+
}
33+
return false;
34+
}
35+
36+
public boolean checkIfFolderExists(File rootDirectory, String absoluteFilePathFilter) {
37+
File[] list = rootDirectory.listFiles();
38+
if (list != null) {
39+
for (File file : list) {
40+
if (file.isDirectory()) {
41+
if(Pattern.matches(absoluteFilePathFilter,file.getAbsolutePath())) {
42+
return true;
43+
}
44+
checkIfFileExists(file, absoluteFilePathFilter);
45+
}
46+
}
47+
}
48+
return false;
49+
}
50+
51+
public static boolean isUniqueRestTransform(File pluginsDir, String name) {
52+
String entityNameFilter = "[a-zA-Z0-9_.-]+";
53+
String flowTypeFilter = "(" + FlowType.INPUT + "|" + FlowType.CONFORMANCE + ")";
54+
String pluginFormatFilter = "(" + PluginFormat.XQUERY + "|" + PluginFormat.JAVASCRIPT + ")";
55+
String absoluteFilePathFilter = Scaffolding.getAbsolutePath(pluginsDir.getAbsolutePath(), "entities", entityNameFilter, flowTypeFilter, "REST", "transforms", name + "." + pluginFormatFilter);
56+
return !checkIfFileExists(pluginsDir, absoluteFilePathFilter);
57+
}
58+
59+
}

marklogic-data-hub/src/test/java/com/marklogic/hub/ScaffoldingTest.java

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.apache.commons.io.IOUtils;
1414
import org.custommonkey.xmlunit.XMLUnit;
1515
import org.junit.After;
16+
import org.junit.Assert;
1617
import org.junit.BeforeClass;
1718
import org.junit.Test;
1819
import org.xml.sax.SAXException;
@@ -161,7 +162,11 @@ public void createXqyRestExtension() throws IOException {
161162
String extensionName = "myExtension";
162163
FlowType flowType = FlowType.CONFORMANCE;
163164
PluginFormat pluginFormat = PluginFormat.XQUERY;
164-
Scaffolding.createRestExtension(entityName, extensionName, flowType, pluginFormat, pluginsDir);
165+
try {
166+
Scaffolding.createRestExtension(entityName, extensionName, flowType, pluginFormat, pluginsDir);
167+
} catch (ScaffoldingValidationException e) {
168+
Assert.fail(e.getMessage());
169+
}
165170
File restDir = new File(pluginsDir.getAbsolutePath() + "/entities/"+ entityName + "/"+ flowType.name() +"/REST");
166171
assertTrue(restDir.exists());
167172
File restServicesDir = new File(restDir, "services");
@@ -180,7 +185,11 @@ public void createSjsRestExtension() throws IOException {
180185
String extensionName = "myExtension";
181186
FlowType flowType = FlowType.INPUT;
182187
PluginFormat pluginFormat = PluginFormat.JAVASCRIPT;
183-
Scaffolding.createRestExtension(entityName, extensionName, flowType, pluginFormat, pluginsDir);
188+
try {
189+
Scaffolding.createRestExtension(entityName, extensionName, flowType, pluginFormat, pluginsDir);
190+
} catch (ScaffoldingValidationException e) {
191+
Assert.fail(e.getMessage());
192+
}
184193
File restDir = new File(pluginsDir.getAbsolutePath() + "/entities/"+ entityName + "/"+ flowType.name() +"/REST");
185194
assertTrue(restDir.exists());
186195
File restServicesDir = new File(restDir, "services");
@@ -199,7 +208,11 @@ public void createXqyRestTransform() throws IOException {
199208
String transformName = "myTransform";
200209
FlowType flowType = FlowType.CONFORMANCE;
201210
PluginFormat pluginFormat = PluginFormat.XQUERY;
202-
Scaffolding.createRestTransform(entityName, transformName, flowType, pluginFormat, pluginsDir);
211+
try {
212+
Scaffolding.createRestTransform(entityName, transformName, flowType, pluginFormat, pluginsDir);
213+
} catch (ScaffoldingValidationException e) {
214+
Assert.fail(e.getMessage());
215+
}
203216
File restDir = new File(pluginsDir.getAbsolutePath() + "/entities/"+ entityName + "/"+ flowType.name() +"/REST");
204217
assertTrue(restDir.exists());
205218
File restTransformDir = new File(restDir, "transforms");
@@ -214,7 +227,11 @@ public void createSjsRestTransform() throws IOException {
214227
String transformName = "myTransform";
215228
FlowType flowType = FlowType.CONFORMANCE;
216229
PluginFormat pluginFormat = PluginFormat.JAVASCRIPT;
217-
Scaffolding.createRestTransform(entityName, transformName, flowType, pluginFormat, pluginsDir);
230+
try {
231+
Scaffolding.createRestTransform(entityName, transformName, flowType, pluginFormat, pluginsDir);
232+
} catch (ScaffoldingValidationException e) {
233+
Assert.fail(e.getMessage());
234+
}
218235
File restDir = new File(pluginsDir.getAbsolutePath() + "/entities/"+ entityName + "/"+ flowType.name() +"/REST");
219236
assertTrue(restDir.exists());
220237
File restTransformDir = new File(restDir, "transforms");
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
package com.marklogic.hub;
2+
3+
import static org.junit.Assert.*;
4+
5+
import java.io.File;
6+
import java.io.IOException;
7+
import java.io.InputStream;
8+
import java.nio.file.Files;
9+
import java.nio.file.Path;
10+
import java.nio.file.Paths;
11+
import java.util.ArrayList;
12+
import java.util.List;
13+
14+
import org.apache.commons.io.FileUtils;
15+
import org.custommonkey.xmlunit.XMLUnit;
16+
import org.junit.After;
17+
import org.junit.Assert;
18+
import org.junit.Before;
19+
import org.junit.BeforeClass;
20+
import org.junit.Test;
21+
22+
import com.marklogic.hub.flow.FlowType;
23+
24+
public class ScaffoldingValidatorTest extends HubTestBase {
25+
26+
private static final String pluginPath = "./test-plugins";
27+
private static final File pluginsDir = new File(pluginPath);
28+
private static final String TEST_ENTITY_NAME = "test-entity";
29+
30+
@BeforeClass
31+
public static void setupClass() throws IOException {
32+
XMLUnit.setIgnoreWhitespace(true);
33+
}
34+
35+
@Before
36+
public void setup() throws IOException {
37+
PluginFormat pluginFormat = PluginFormat.XQUERY;
38+
createPlugins(TEST_ENTITY_NAME, FlowType.INPUT, pluginFormat);
39+
createPlugins(TEST_ENTITY_NAME, FlowType.CONFORMANCE, pluginFormat);
40+
}
41+
42+
@After
43+
public void teardown() throws IOException {
44+
FileUtils.deleteDirectory(pluginsDir);
45+
}
46+
47+
private void createPlugins(String entityName, FlowType flowType, PluginFormat pluginFormat) throws IOException {
48+
49+
String flowName = entityName + flowType + "-flow";
50+
String flowTypePath = Scaffolding.getAbsolutePath(pluginPath, "entities", entityName, flowType.toString());
51+
String flowPath = Scaffolding.getAbsolutePath(flowTypePath, flowName);
52+
53+
List<Plugin> plugins = new ArrayList<>();
54+
if (flowType.equals(FlowType.CONFORMANCE)) {
55+
plugins.add(createPluginObj(flowPath, "collector", flowType, pluginFormat));
56+
}
57+
plugins.add(createPluginObj(flowPath, "content", flowType, pluginFormat));
58+
plugins.add(createPluginObj(flowPath, "headers", flowType, pluginFormat));
59+
plugins.add(createPluginObj(flowPath, "triples", flowType, pluginFormat));
60+
61+
for (Plugin plugin : plugins) {
62+
createFile(plugin.getParentDirectory(), plugin.getFilename(), plugin.getTemplateFilePath());
63+
}
64+
}
65+
66+
private Plugin createPluginObj(String flowPath, String pluginType, FlowType flowType, PluginFormat pluginFormat) {
67+
String parentDirectory = Scaffolding.getAbsolutePath(flowPath, pluginType);
68+
String filename = pluginType + "." + pluginFormat;
69+
String templateFilePath = "scaffolding/" + flowType + "/" + pluginFormat + "/" + pluginType + "." + pluginFormat;
70+
return new Plugin(parentDirectory, filename, templateFilePath);
71+
}
72+
73+
private class Plugin {
74+
75+
private String parentDirectory;
76+
private String filename;
77+
private String templateFilePath;
78+
79+
public Plugin(String parentDirectory, String filename, String templateFilePath) {
80+
this.parentDirectory = parentDirectory;
81+
this.filename = filename;
82+
this.templateFilePath = templateFilePath;
83+
}
84+
85+
public String getParentDirectory() {
86+
return parentDirectory;
87+
}
88+
89+
public String getFilename() {
90+
return filename;
91+
}
92+
93+
public String getTemplateFilePath() {
94+
return templateFilePath;
95+
}
96+
}
97+
98+
private static void createFile(String parentDirectory, String filename, String templateFilePath) throws IOException {
99+
File parentDirectoryFile = new File(parentDirectory);
100+
parentDirectoryFile.mkdirs();
101+
writeFile(templateFilePath, Paths.get(parentDirectoryFile.getPath(), filename));
102+
}
103+
104+
private static void writeFile(String srcFile, Path dstFile)
105+
throws IOException {
106+
InputStream inputStream = Scaffolding.class.getClassLoader()
107+
.getResourceAsStream(srcFile);
108+
Files.copy(inputStream, dstFile);
109+
}
110+
111+
@Test
112+
public void testIsUniqueRestServiceExtension() throws IOException {
113+
String restServiceExtensionName = "test-rest-service";
114+
boolean isUnique = ScaffoldingValidator.isUniqueRestServiceExtension(pluginsDir, restServiceExtensionName);
115+
assertTrue("The rest service extension "+ restServiceExtensionName + " is not yet existing so it should be unique.", isUnique);
116+
try {
117+
Scaffolding.createRestExtension(TEST_ENTITY_NAME, restServiceExtensionName, FlowType.CONFORMANCE, PluginFormat.XQUERY, pluginsDir);
118+
} catch (ScaffoldingValidationException e) {
119+
Assert.fail(e.getMessage());
120+
}
121+
isUnique = ScaffoldingValidator.isUniqueRestServiceExtension(pluginsDir, restServiceExtensionName);
122+
assertFalse("At this point, the rest service extension "+ restServiceExtensionName + " is already existing so it should not be unique.", isUnique);
123+
}
124+
125+
@Test
126+
public void testIsUniqueRestTransform() throws IOException {
127+
String restTransformName = "test-rest-transform";
128+
boolean isUnique = ScaffoldingValidator.isUniqueRestTransform(pluginsDir, restTransformName);
129+
assertTrue("The rest transform "+ restTransformName + " is not yet existing so it should be unique.", isUnique);
130+
try {
131+
Scaffolding.createRestTransform(TEST_ENTITY_NAME, restTransformName, FlowType.CONFORMANCE, PluginFormat.XQUERY, pluginsDir);
132+
} catch (ScaffoldingValidationException e) {
133+
Assert.fail(e.getMessage());
134+
}
135+
isUnique = ScaffoldingValidator.isUniqueRestTransform(pluginsDir, restTransformName);
136+
assertFalse("At this point, the rest service extension "+ restTransformName + " is already existing so it should not be unique.", isUnique);
137+
}
138+
}

0 commit comments

Comments
 (0)