diff --git a/app/aem/core/build.gradle.kts b/app/aem/core/build.gradle.kts index 64a725ef9..f25155977 100644 --- a/app/aem/core/build.gradle.kts +++ b/app/aem/core/build.gradle.kts @@ -3,8 +3,6 @@ import org.gradle.jvm.tasks.Jar plugins { id("com.cognifide.aem.bundle") - kotlin("jvm") - id("org.jetbrains.kotlin.plugin.noarg") version "1.6.21" antlr groovy java @@ -33,8 +31,6 @@ aem { ).joinToString(",")) excludePackage("org.antlr.stringtemplate", "org.antlr.v4.gui") embedPackage("org.antlr:antlr4-runtime:4.7.2", "org.antlr.v4.runtime.*") - embedPackage("org.jetbrains.kotlin:kotlin-reflect:1.6.21", "kotlin.reflect.*") - embedPackage("org.jetbrains.kotlin:kotlin-stdlib:1.6.21", "kotlin.*") } } } @@ -45,9 +41,6 @@ dependencies { implementation(project(":app:aem:actions.main")) antlr("org.antlr:antlr4:4.7.2") - - compileOnly(kotlin("stdlib-jdk8")) - compileOnly(kotlin("reflect")) } sourceSets { @@ -59,10 +52,6 @@ sourceSets { } tasks { - named("compileKotlin").configure { - dependsOn("generateGrammarSource") - } - named("generateGrammarSource", AntlrTask::class).configure { maxHeapSize = "64m" arguments = arguments + listOf("-visitor", "-long-messages", "-package", "com.cognifide.apm.core.grammar.antlr") diff --git a/app/aem/core/src/main/java/com/cognifide/apm/core/actions/MapperDescriptorFactory.java b/app/aem/core/src/main/java/com/cognifide/apm/core/actions/MapperDescriptorFactory.java index 32db82d12..4e1ad88c5 100644 --- a/app/aem/core/src/main/java/com/cognifide/apm/core/actions/MapperDescriptorFactory.java +++ b/app/aem/core/src/main/java/com/cognifide/apm/core/actions/MapperDescriptorFactory.java @@ -32,11 +32,11 @@ import com.cognifide.apm.core.actions.ParameterDescriptor.FlagsParameterDescriptor; import com.cognifide.apm.core.actions.ParameterDescriptor.NamedParameterDescriptor; import com.cognifide.apm.core.actions.ParameterDescriptor.RequiredParameterDescriptor; -import com.cognifide.apm.core.grammar.ApmInteger; -import com.cognifide.apm.core.grammar.ApmList; -import com.cognifide.apm.core.grammar.ApmMap; -import com.cognifide.apm.core.grammar.ApmString; import com.cognifide.apm.core.grammar.ApmType; +import com.cognifide.apm.core.grammar.ApmType.ApmInteger; +import com.cognifide.apm.core.grammar.ApmType.ApmList; +import com.cognifide.apm.core.grammar.ApmType.ApmMap; +import com.cognifide.apm.core.grammar.ApmType.ApmString; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import java.lang.annotation.Annotation; diff --git a/app/aem/core/src/main/java/com/cognifide/apm/core/crypto/DecryptionService.java b/app/aem/core/src/main/java/com/cognifide/apm/core/crypto/DecryptionService.java new file mode 100644 index 000000000..c7b692f81 --- /dev/null +++ b/app/aem/core/src/main/java/com/cognifide/apm/core/crypto/DecryptionService.java @@ -0,0 +1,65 @@ +/*- + * ========================LICENSE_START================================= + * AEM Permission Management + * %% + * Copyright (C) 2013 Wunderman Thompson Technology + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ +package com.cognifide.apm.core.crypto; + +import com.adobe.granite.crypto.CryptoException; +import com.adobe.granite.crypto.CryptoSupport; +import com.cognifide.apm.core.Property; +import java.util.Arrays; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.apache.commons.lang.text.StrSubstitutor; +import org.apache.commons.lang3.StringUtils; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; + +@Component( + service = DecryptionService.class, + property = { + Property.DESCRIPTION + "APM Service for decryption encrypted values", + Property.VENDOR + } +) +public class DecryptionService { + + @Reference + private CryptoSupport cryptoSupport; + + public String decrypt(String text) { + Map tokens = Optional.ofNullable(StringUtils.substringsBetween(text, "{", "}")) + .map(Arrays::stream) + .orElse(Stream.empty()) + .distinct() + .collect(Collectors.toMap(Function.identity(), token -> unprotect("{" + token + "}"))); + StrSubstitutor strSubstitutor = new StrSubstitutor(tokens, "{", "}"); + return tokens.isEmpty() ? text : strSubstitutor.replace(text); + } + + protected String unprotect(String text) { + try { + return cryptoSupport.unprotect(text); + } catch (CryptoException e) { + throw new IllegalArgumentException(String.format("Unable to decrypt '%s', wrong hmac or master key", text), e); + } + } +} diff --git a/app/aem/core/src/main/java/com/cognifide/apm/core/crypto/ProtectTextForm.java b/app/aem/core/src/main/java/com/cognifide/apm/core/crypto/ProtectTextForm.java new file mode 100644 index 000000000..77ad1a8c7 --- /dev/null +++ b/app/aem/core/src/main/java/com/cognifide/apm/core/crypto/ProtectTextForm.java @@ -0,0 +1,38 @@ +/* + * ========================LICENSE_START================================= + * AEM Permission Management + * %% + * Copyright (C) 2013 Wunderman Thompson Technology + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ + +package com.cognifide.apm.core.crypto; + +import com.cognifide.apm.core.endpoints.params.RequestParameter; +import javax.inject.Inject; +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.models.annotations.Model; + +@Model(adaptables = SlingHttpServletRequest.class) +public class ProtectTextForm { + + @Inject + @RequestParameter(value = "text", optional = false) + private String text; + + public String getText() { + return text; + } +} diff --git a/app/aem/core/src/main/java/com/cognifide/apm/core/crypto/ProtectTextServlet.java b/app/aem/core/src/main/java/com/cognifide/apm/core/crypto/ProtectTextServlet.java new file mode 100644 index 000000000..697c051f5 --- /dev/null +++ b/app/aem/core/src/main/java/com/cognifide/apm/core/crypto/ProtectTextServlet.java @@ -0,0 +1,65 @@ +/* + * ========================LICENSE_START================================= + * AEM Permission Management + * %% + * Copyright (C) 2013 Wunderman Thompson Technology + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ +package com.cognifide.apm.core.crypto; + +import com.adobe.granite.crypto.CryptoException; +import com.adobe.granite.crypto.CryptoSupport; +import com.cognifide.apm.core.Property; +import com.cognifide.apm.core.endpoints.response.ResponseEntity; +import com.cognifide.apm.core.endpoints.utils.RequestProcessor; +import java.io.IOException; +import javax.servlet.Servlet; +import org.apache.commons.lang3.StringUtils; +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.api.SlingHttpServletResponse; +import org.apache.sling.api.servlets.SlingAllMethodsServlet; +import org.apache.sling.models.factory.ModelFactory; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; + +@Component( + service = Servlet.class, + property = { + Property.PATH + "/bin/apm/scripts/protect", + Property.METHOD + "POST", + Property.DESCRIPTION + "APM Encrypt Text Servlet", + Property.VENDOR + } +) +public class ProtectTextServlet extends SlingAllMethodsServlet { + + @Reference + private CryptoSupport cryptoSupport; + + @Reference + private ModelFactory modelFactory; + + @Override + protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException { + RequestProcessor.process(modelFactory, ProtectTextForm.class, request, response, (form, resourceResolver) -> { + try { + return ResponseEntity.ok("Text successfully encrypted") + .addEntry("text", cryptoSupport.protect(form.getText())); + } catch (CryptoException e) { + return ResponseEntity.badRequest(StringUtils.defaultString(e.getMessage(), "Errors while encrypting text")); + } + }); + } +} diff --git a/app/aem/core/src/main/kotlin/com/cognifide/apm/core/endpoints/DefinitionsServlet.kt b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/DefinitionsServlet.java similarity index 50% rename from app/aem/core/src/main/kotlin/com/cognifide/apm/core/endpoints/DefinitionsServlet.kt rename to app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/DefinitionsServlet.java index d4618527d..f7f9b3dd8 100644 --- a/app/aem/core/src/main/kotlin/com/cognifide/apm/core/endpoints/DefinitionsServlet.kt +++ b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/DefinitionsServlet.java @@ -7,9 +7,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -17,34 +17,35 @@ * limitations under the License. * =========================LICENSE_END================================== */ -package com.cognifide.apm.core.endpoints +package com.cognifide.apm.core.endpoints; -import com.cognifide.apm.api.services.ScriptManager -import com.cognifide.apm.core.Property -import com.cognifide.apm.core.utils.ServletUtils -import org.apache.sling.api.SlingHttpServletRequest -import org.apache.sling.api.SlingHttpServletResponse -import org.apache.sling.api.servlets.SlingAllMethodsServlet -import org.osgi.service.component.annotations.Component -import org.osgi.service.component.annotations.Reference -import javax.servlet.Servlet +import com.cognifide.apm.api.services.ScriptManager; +import com.cognifide.apm.core.Property; +import com.cognifide.apm.core.utils.ServletUtils; +import java.io.IOException; +import javax.servlet.Servlet; +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.api.SlingHttpServletResponse; +import org.apache.sling.api.servlets.SlingAllMethodsServlet; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; @Component( - service = [Servlet::class], - property = [ + service = Servlet.class, + property = { Property.PATH + "/bin/apm/definitions", Property.METHOD + "GET", Property.DESCRIPTION + "APM Definitions Servlet", Property.VENDOR - ] + } ) -class DefinitionsServlet : SlingAllMethodsServlet() { +public class DefinitionsServlet extends SlingAllMethodsServlet { - @Reference - @Transient - private lateinit var scriptManager: ScriptManager + @Reference + private ScriptManager scriptManager; - override fun doGet(request: SlingHttpServletRequest, response: SlingHttpServletResponse) { - ServletUtils.writeJson(response, scriptManager.predefinedDefinitions) - } -} \ No newline at end of file + @Override + protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException { + ServletUtils.writeJson(response, scriptManager.getPredefinedDefinitions()); + } +} diff --git a/app/aem/core/src/main/kotlin/com/cognifide/apm/core/endpoints/ReferencesServlet.kt b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/ReferencesServlet.java similarity index 51% rename from app/aem/core/src/main/kotlin/com/cognifide/apm/core/endpoints/ReferencesServlet.kt rename to app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/ReferencesServlet.java index 1026ac7bb..e59c5748b 100644 --- a/app/aem/core/src/main/kotlin/com/cognifide/apm/core/endpoints/ReferencesServlet.kt +++ b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/ReferencesServlet.java @@ -17,34 +17,35 @@ * limitations under the License. * =========================LICENSE_END================================== */ -package com.cognifide.apm.core.endpoints +package com.cognifide.apm.core.endpoints; -import com.cognifide.apm.core.Property -import com.cognifide.apm.core.actions.ActionFactory -import com.cognifide.apm.core.utils.ServletUtils -import org.apache.sling.api.SlingHttpServletRequest -import org.apache.sling.api.SlingHttpServletResponse -import org.apache.sling.api.servlets.SlingAllMethodsServlet -import org.osgi.service.component.annotations.Component -import org.osgi.service.component.annotations.Reference -import javax.servlet.Servlet +import com.cognifide.apm.core.Property; +import com.cognifide.apm.core.actions.ActionFactory; +import com.cognifide.apm.core.utils.ServletUtils; +import java.io.IOException; +import javax.servlet.Servlet; +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.api.SlingHttpServletResponse; +import org.apache.sling.api.servlets.SlingAllMethodsServlet; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; @Component( - service = [Servlet::class], - property = [ + service = Servlet.class, + property = { Property.PATH + "/bin/apm/references", Property.METHOD + "GET", Property.DESCRIPTION + "APM References Servlet", Property.VENDOR - ] + } ) -class ReferencesServlet : SlingAllMethodsServlet() { +public class ReferencesServlet extends SlingAllMethodsServlet { - @Reference - @Transient - private lateinit var actionFactory: ActionFactory + @Reference + private ActionFactory actionFactory; - override fun doGet(request: SlingHttpServletRequest, response: SlingHttpServletResponse) { - ServletUtils.writeJson(response, actionFactory.commandDescriptions) - } -} \ No newline at end of file + @Override + protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException { + ServletUtils.writeJson(response, actionFactory.getCommandDescriptions()); + } +} diff --git a/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/ScriptExecutionForm.java b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/ScriptExecutionForm.java new file mode 100644 index 000000000..ca873f710 --- /dev/null +++ b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/ScriptExecutionForm.java @@ -0,0 +1,64 @@ +/* + * ========================LICENSE_START================================= + * AEM Permission Management + * %% + * Copyright (C) 2013 Wunderman Thompson Technology + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ + +package com.cognifide.apm.core.endpoints; + +import com.cognifide.apm.api.services.ExecutionMode; +import com.cognifide.apm.core.endpoints.params.RequestParameter; +import java.util.Map; +import javax.inject.Inject; +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.models.annotations.Model; + +@Model(adaptables = SlingHttpServletRequest.class) +public class ScriptExecutionForm { + + @Inject + @RequestParameter(value = "script", optional = false) + private String script; + + @Inject + @RequestParameter(value = "executionMode", optional = false) + private ExecutionMode executionMode; + + @Inject + @RequestParameter("async") + private boolean async; + + @Inject + @RequestParameter("define") + private Map customDefinitions; + + public String getScript() { + return script; + } + + public ExecutionMode getExecutionMode() { + return executionMode; + } + + public boolean isAsync() { + return async; + } + + public Map getCustomDefinitions() { + return customDefinitions; + } +} diff --git a/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/ScriptExecutionServlet.java b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/ScriptExecutionServlet.java new file mode 100644 index 000000000..95606657f --- /dev/null +++ b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/ScriptExecutionServlet.java @@ -0,0 +1,142 @@ +/* + * ========================LICENSE_START================================= + * AEM Permission Management + * %% + * Copyright (C) 2013 Wunderman Thompson Technology + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ +package com.cognifide.apm.core.endpoints; + +import com.cognifide.apm.api.scripts.Script; +import com.cognifide.apm.api.services.ExecutionResult; +import com.cognifide.apm.api.services.ScriptFinder; +import com.cognifide.apm.api.services.ScriptManager; +import com.cognifide.apm.core.Property; +import com.cognifide.apm.core.endpoints.response.ResponseEntity; +import com.cognifide.apm.core.endpoints.utils.RequestProcessor; +import com.cognifide.apm.core.services.ResourceResolverProvider; +import com.cognifide.apm.core.services.async.AsyncScriptExecutor; +import com.cognifide.apm.core.services.async.ExecutionStatus; +import com.cognifide.apm.core.utils.sling.ResolveException; +import com.cognifide.apm.core.utils.sling.SlingHelper; +import java.io.IOException; +import javax.jcr.RepositoryException; +import javax.servlet.Servlet; +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.api.SlingHttpServletResponse; +import org.apache.sling.api.resource.PersistenceException; +import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.api.servlets.SlingAllMethodsServlet; +import org.apache.sling.models.factory.ModelFactory; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; + +@Component( + service = Servlet.class, + property = { + Property.PATH + "/bin/apm/scripts/exec", + Property.METHOD + "POST", + Property.DESCRIPTION + "APM Script Execution Servlet", + Property.VENDOR + } +) +public class ScriptExecutionServlet extends SlingAllMethodsServlet { + + @Reference + private ScriptFinder scriptFinder; + + @Reference + private ScriptManager scriptManager; + + @Reference + private AsyncScriptExecutor asyncScriptExecutor; + + @Reference + private ModelFactory modelFactory; + + @Reference + private ResourceResolverProvider resolverProvider; + + @Override + protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException { + RequestProcessor.process(modelFactory, ScriptExecutionStatusForm.class, request, response, (form, resourceResolver) -> { + ExecutionStatus status = asyncScriptExecutor.checkStatus(form.getId()); + if (status instanceof ExecutionStatus.FinishedSuccessfulExecution) { + return ResponseEntity.ok("Script successfully executed") + .addEntry("status", status.getStatus()) + .addEntry("output", ((ExecutionStatus.FinishedSuccessfulExecution) status).getEntries()) + .addEntry("path", ((ExecutionStatus.FinishedSuccessfulExecution) status).getPath()); + } else if (status instanceof ExecutionStatus.FinishedFailedExecution) { + return ResponseEntity.internalServerError("Errors while executing script") + .addEntry("status", status.getStatus()) + .addEntry("output", ((ExecutionStatus.FinishedFailedExecution) status).getEntries()) + .addEntry("path", ((ExecutionStatus.FinishedFailedExecution) status).getPath()) + .addEntry("errors", ((ExecutionStatus.FinishedFailedExecution) status).getError().getMessages()); + } else { + return ResponseEntity.ok("Script is still being processed") + .addEntry("status", status.getStatus()); + } + }); + } + + @Override + protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException { + String executor = request.getResourceResolver().getUserID(); + RequestProcessor.process(modelFactory, ScriptExecutionForm.class, request, response, (form, resourceResolver) -> { + try { + return SlingHelper.resolve(resolverProvider, resolver -> executeScript(form, resolver, executor)); + } catch (ResolveException e) { + throw new RuntimeException(e); + } + }); + } + + private ResponseEntity executeScript(ScriptExecutionForm form, ResourceResolver resourceResolver, String executor) { + try { + Script script = scriptFinder.find(form.getScript(), resourceResolver); + if (script == null) { + return ResponseEntity.notFound(String.format("Script not found: %s", form.getScript())); + } else if (!script.isLaunchEnabled()) { + return ResponseEntity.internalServerError("Script cannot be executed because it is disabled"); + } else if (!script.isValid()) { + return ResponseEntity.internalServerError("Script cannot be executed because it is invalid"); + } else if (form.isAsync()) { + return asyncExecute(script, form, executor); + } else { + return syncExecute(script, form, resourceResolver, executor); + } + } catch (RepositoryException | PersistenceException e) { + return ResponseEntity.internalServerError(String.format("Script cannot be executed because of repository error: %s", e.getMessage())); + } + } + + private ResponseEntity asyncExecute(Script script, ScriptExecutionForm form, String executor) { + String id = asyncScriptExecutor.process(script, form.getExecutionMode(), form.getCustomDefinitions(), executor); + return ResponseEntity.ok("Script successfully queued for async execution") + .addEntry("id", id); + } + + private ResponseEntity syncExecute(Script script, ScriptExecutionForm form, ResourceResolver resourceResolver, String executor) throws PersistenceException, RepositoryException { + ExecutionResult result = scriptManager.process(script, form.getExecutionMode(), form.getCustomDefinitions(), resourceResolver, executor); + if (result.isSuccess()) { + return ResponseEntity.ok("Script successfully executed") + .addEntry("output", result.getEntries()); + } else { + return ResponseEntity.internalServerError("Errors while executing script") + .addEntry("output", result.getEntries()) + .addEntry("errors", result.getLastError().getMessages()); + } + } +} diff --git a/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/ScriptExecutionStatusForm.java b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/ScriptExecutionStatusForm.java new file mode 100644 index 000000000..5009eb818 --- /dev/null +++ b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/ScriptExecutionStatusForm.java @@ -0,0 +1,38 @@ +/* + * ========================LICENSE_START================================= + * AEM Permission Management + * %% + * Copyright (C) 2013 Wunderman Thompson Technology + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ + +package com.cognifide.apm.core.endpoints; + +import com.cognifide.apm.core.endpoints.params.RequestParameter; +import javax.inject.Inject; +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.models.annotations.Model; + +@Model(adaptables = SlingHttpServletRequest.class) +public class ScriptExecutionStatusForm { + + @Inject + @RequestParameter(value = "id", optional = false) + private String id; + + public String getId() { + return id; + } +} diff --git a/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/ScriptListServlet.java b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/ScriptListServlet.java new file mode 100644 index 000000000..c24864f1e --- /dev/null +++ b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/ScriptListServlet.java @@ -0,0 +1,60 @@ +/*- + * ========================LICENSE_START================================= + * AEM Permission Management + * %% + * Copyright (C) 2013 Wunderman Thompson Technology + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ +package com.cognifide.apm.core.endpoints; + +import com.cognifide.apm.api.services.ScriptFinder; +import com.cognifide.apm.core.Property; +import com.cognifide.apm.core.endpoints.dto.ScriptDto; +import com.cognifide.apm.core.utils.ServletUtils; +import java.io.IOException; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; +import javax.servlet.Servlet; +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.api.SlingHttpServletResponse; +import org.apache.sling.api.servlets.SlingAllMethodsServlet; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; + +@Component( + service = Servlet.class, + property = { + Property.PATH + "/bin/apm/scripts", + Property.METHOD + "GET", + Property.DESCRIPTION + "APM Script List Servlet", + Property.VENDOR + } +) +public class ScriptListServlet extends SlingAllMethodsServlet { + + @Reference + private ScriptFinder scriptFinder; + + @Override + protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException { + List scripts = scriptFinder.findAll(request.getResourceResolver()) + .stream() + .map(ScriptDto::new) + .sorted(Comparator.comparing(ScriptDto::getPath)) + .collect(Collectors.toList()); + ServletUtils.writeJson(response, scripts); + } +} diff --git a/app/aem/core/src/main/kotlin/com/cognifide/apm/core/grammar/common/ListBaseVisitor.kt b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/ScriptMoveForm.java similarity index 53% rename from app/aem/core/src/main/kotlin/com/cognifide/apm/core/grammar/common/ListBaseVisitor.kt rename to app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/ScriptMoveForm.java index 590e951a5..dfb62aa28 100644 --- a/app/aem/core/src/main/kotlin/com/cognifide/apm/core/grammar/common/ListBaseVisitor.kt +++ b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/ScriptMoveForm.java @@ -18,20 +18,37 @@ * =========================LICENSE_END================================== */ -package com.cognifide.apm.core.grammar.common +package com.cognifide.apm.core.endpoints; -import com.cognifide.apm.core.grammar.antlr.ApmLangBaseVisitor +import com.cognifide.apm.core.endpoints.params.RequestParameter; +import javax.inject.Inject; +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.models.annotations.Model; -open class ListBaseVisitor : ApmLangBaseVisitor>() { +@Model(adaptables = SlingHttpServletRequest.class) +public class ScriptMoveForm { - override fun defaultResult(): MutableList { - return mutableListOf() - } + @Inject + @RequestParameter("path") + private String path; - override fun aggregateResult(aggregate: MutableList, nextResult: MutableList?): MutableList { - if (nextResult != null) { - aggregate.addAll(nextResult) - } - return aggregate - } + @Inject + @RequestParameter("dest") + private String dest; + + @Inject + @RequestParameter("rename") + private String rename; + + public String getPath() { + return path; + } + + public String getDest() { + return dest; + } + + public String getRename() { + return rename; + } } diff --git a/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/ScriptMoveServlet.java b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/ScriptMoveServlet.java new file mode 100644 index 000000000..3890a70f1 --- /dev/null +++ b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/ScriptMoveServlet.java @@ -0,0 +1,96 @@ +/* + * ========================LICENSE_START================================= + * AEM Permission Management + * %% + * Copyright (C) 2013 Wunderman Thompson Technology + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ +package com.cognifide.apm.core.endpoints; + +import com.cognifide.apm.core.Apm; +import com.cognifide.apm.core.Property; +import com.cognifide.apm.core.endpoints.response.ResponseEntity; +import com.cognifide.apm.core.endpoints.utils.RequestProcessor; +import com.day.cq.commons.jcr.JcrConstants; +import com.day.cq.commons.jcr.JcrUtil; +import java.io.IOException; +import javax.jcr.Session; +import javax.servlet.Servlet; +import org.apache.commons.lang3.StringUtils; +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.api.SlingHttpServletResponse; +import org.apache.sling.api.resource.ModifiableValueMap; +import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.api.resource.ValueMap; +import org.apache.sling.api.servlets.SlingAllMethodsServlet; +import org.apache.sling.models.factory.ModelFactory; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; + +@Component( + service = Servlet.class, + property = { + Property.PATH + "/bin/apm/scripts/move", + Property.METHOD + "POST", + Property.DESCRIPTION + "APM Script Move Servlet", + Property.VENDOR + } +) +public class ScriptMoveServlet extends SlingAllMethodsServlet { + + @Reference + private ModelFactory modelFactory; + + @Override + protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException { + RequestProcessor.process(modelFactory, ScriptMoveForm.class, request, response, (form, resourceResolver) -> { + try { + Session session = resourceResolver.adaptTo(Session.class); + String dest = StringUtils.defaultIfEmpty(form.getDest(), StringUtils.substringBeforeLast(form.getPath(), "/")); + String rename = containsExtension(form.getPath()) + ? (form.getRename() + (containsExtension(form.getRename()) ? "" : Apm.FILE_EXT)) + : JcrUtil.createValidName(form.getRename()); + String destPath = String.format("%s/%s", dest, rename); + if (!StringUtils.equals(form.getPath(), destPath)) { + destPath = createUniquePath(destPath, resourceResolver); + session.move(form.getPath(), destPath); + session.save(); + } + if (!containsExtension(form.getPath())) { + ValueMap valueMap = resourceResolver.getResource(destPath).adaptTo(ModifiableValueMap.class); + valueMap.put(JcrConstants.JCR_TITLE, form.getRename()); + } + resourceResolver.commit(); + return ResponseEntity.ok("Item successfully moved"); + } catch (Exception e) { + return ResponseEntity.badRequest(StringUtils.defaultString(e.getMessage(), "Errors while moving item")); + } + }); + } + + private boolean containsExtension(String path) { + return path.endsWith(Apm.FILE_EXT); + } + + private String createUniquePath(String pathWithExtension, ResourceResolver resolver) { + String path = StringUtils.substringBeforeLast(pathWithExtension, Apm.FILE_EXT); + String extension = containsExtension(pathWithExtension) ? Apm.FILE_EXT : ""; + int counter = 0; + while (resolver.getResource(path + (counter > 0 ? counter : "") + extension) != null) { + counter++; + } + return path + (counter > 0 ? counter : "") + extension; + } +} diff --git a/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/ScriptUploadForm.java b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/ScriptUploadForm.java new file mode 100644 index 000000000..0d01a343f --- /dev/null +++ b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/ScriptUploadForm.java @@ -0,0 +1,104 @@ +/* + * ========================LICENSE_START================================= + * AEM Permission Management + * %% + * Copyright (C) 2013 Wunderman Thompson Technology + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ + +package com.cognifide.apm.core.endpoints; + +import com.cognifide.apm.api.scripts.LaunchEnvironment; +import com.cognifide.apm.api.scripts.LaunchMode; +import com.cognifide.apm.core.endpoints.params.DateFormat; +import com.cognifide.apm.core.endpoints.params.FileName; +import com.cognifide.apm.core.endpoints.params.RequestParameter; +import com.cognifide.apm.core.scripts.LaunchMetadata; +import com.cognifide.apm.core.scripts.ScriptNode; +import java.io.InputStream; +import java.time.LocalDateTime; +import javax.inject.Inject; +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.models.annotations.Model; + +@Model(adaptables = SlingHttpServletRequest.class) +public class ScriptUploadForm { + + @Inject + @RequestParameter(value = "file", optional = false) + private InputStream file; + + @Inject + @RequestParameter(value = "file", optional = false) + @FileName + private String fileName; + + @Inject + @RequestParameter("overwrite") + private boolean overwrite; + + @Inject + @RequestParameter(ScriptNode.APM_SAVE_PATH) + private String savePath; + + @Inject + @RequestParameter(ScriptNode.APM_LAUNCH_ENABLED) + private boolean launchEnabled; + + @Inject + @RequestParameter(ScriptNode.APM_LAUNCH_MODE) + private LaunchMode launchMode; + + @Inject + @RequestParameter(ScriptNode.APM_LAUNCH_ENVIRONMENT) + private LaunchEnvironment launchEnvironment; + + @Inject + @RequestParameter(ScriptNode.APM_LAUNCH_RUN_MODES) + private String[] launchRunModes; + + @Inject + @RequestParameter(ScriptNode.APM_LAUNCH_HOOK) + private String launchHook; + + @Inject + @RequestParameter(ScriptNode.APM_LAUNCH_SCHEDULE) + @DateFormat("yyyy-MM-dd'T'HH:mm:ss") + private LocalDateTime launchSchedule; + + @Inject + @RequestParameter(ScriptNode.APM_LAUNCH_HOOK) + private String cronExpression; + + public LaunchMetadata toLaunchMetadata() { + return new LaunchMetadata(launchEnabled, launchMode, launchEnvironment, launchRunModes, launchHook, launchSchedule, cronExpression); + } + + public String getFileName() { + return fileName; + } + + public String getSavePath() { + return savePath; + } + + public InputStream getFile() { + return file; + } + + public boolean isOverwrite() { + return overwrite; + } +} diff --git a/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/ScriptUploadServlet.java b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/ScriptUploadServlet.java new file mode 100644 index 000000000..3d28347b3 --- /dev/null +++ b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/ScriptUploadServlet.java @@ -0,0 +1,79 @@ +/* + * ========================LICENSE_START================================= + * AEM Permission Management + * %% + * Copyright (C) 2013 Wunderman Thompson Technology + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ +package com.cognifide.apm.core.endpoints; + +import com.cognifide.apm.api.scripts.Script; +import com.cognifide.apm.api.services.ExecutionMode; +import com.cognifide.apm.api.services.ScriptManager; +import com.cognifide.apm.core.Property; +import com.cognifide.apm.core.endpoints.dto.ScriptDto; +import com.cognifide.apm.core.endpoints.response.ResponseEntity; +import com.cognifide.apm.core.endpoints.utils.RequestProcessor; +import com.cognifide.apm.core.scripts.ScriptStorage; +import com.cognifide.apm.core.scripts.ScriptStorageException; +import java.io.IOException; +import javax.jcr.RepositoryException; +import javax.servlet.Servlet; +import org.apache.commons.lang3.StringUtils; +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.api.SlingHttpServletResponse; +import org.apache.sling.api.resource.PersistenceException; +import org.apache.sling.api.servlets.SlingAllMethodsServlet; +import org.apache.sling.models.factory.ModelFactory; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; + +@Component( + service = Servlet.class, + property = { + Property.PATH + "/bin/apm/scripts/upload", + Property.METHOD + "POST", + Property.DESCRIPTION + "APM Script Upload Servlet", + Property.VENDOR + } +) +public class ScriptUploadServlet extends SlingAllMethodsServlet { + + @Reference + private ScriptStorage scriptStorage; + + @Reference + private ScriptManager scriptManager; + + @Reference + private ModelFactory modelFactory; + + @Override + protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException { + RequestProcessor.process(modelFactory, ScriptUploadForm.class, request, response, (form, resourceResolver) -> { + try { + Script script = scriptStorage.save(form, resourceResolver); + scriptManager.process(script, ExecutionMode.VALIDATION, resourceResolver); + return ResponseEntity.ok("File successfully saved") + .addEntry("uploadedScript", new ScriptDto(script)); + } catch (ScriptStorageException e) { + return ResponseEntity.badRequest(StringUtils.defaultString(e.getMessage(), "Errors while saving script")) + .addEntry("errors", e.getErrors()); + } catch (PersistenceException | RepositoryException e) { + throw new RuntimeException(e); + } + }); + } +} diff --git a/app/aem/core/src/main/kotlin/com/cognifide/apm/core/grammar/common/StackWithRoot.kt b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/ScriptValidationForm.java similarity index 55% rename from app/aem/core/src/main/kotlin/com/cognifide/apm/core/grammar/common/StackWithRoot.kt rename to app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/ScriptValidationForm.java index 7a7cb20c1..5fe509af2 100644 --- a/app/aem/core/src/main/kotlin/com/cognifide/apm/core/grammar/common/StackWithRoot.kt +++ b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/ScriptValidationForm.java @@ -18,24 +18,29 @@ * =========================LICENSE_END================================== */ -package com.cognifide.apm.core.grammar.common +package com.cognifide.apm.core.endpoints; -import java.util.* +import com.cognifide.apm.core.endpoints.params.RequestParameter; +import javax.inject.Inject; +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.models.annotations.Model; -class StackWithRoot(private val root: E) : Iterable { +@Model(adaptables = SlingHttpServletRequest.class) +public class ScriptValidationForm { - override fun iterator(): Iterator { - val values = mutableListOf() - values.addAll(internal) - values.add(root) - return values.iterator() - } + @Inject + @RequestParameter(value = "path", optional = false) + private String path; - private val internal: ArrayDeque = ArrayDeque() + @Inject + @RequestParameter(value = "content", optional = false) + private String content; - fun push(element: E) = internal.push(element) + public String getPath() { + return path; + } - fun pop(): E = if (internal.isEmpty()) root else internal.pop() - - fun peek(): E = if (internal.isEmpty()) root else internal.peek() -} \ No newline at end of file + public String getContent() { + return content; + } +} diff --git a/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/ScriptValidationServlet.java b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/ScriptValidationServlet.java new file mode 100644 index 000000000..55ad597df --- /dev/null +++ b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/ScriptValidationServlet.java @@ -0,0 +1,110 @@ +/*- + * ========================LICENSE_START================================= + * AEM Permission Management + * %% + * Copyright (C) 2013 Wunderman Thompson Technology + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ +package com.cognifide.apm.core.endpoints; + +import com.cognifide.apm.api.scripts.Script; +import com.cognifide.apm.api.scripts.TransientScript; +import com.cognifide.apm.api.services.ExecutionMode; +import com.cognifide.apm.api.services.ExecutionResult; +import com.cognifide.apm.api.services.ScriptManager; +import com.cognifide.apm.api.status.Status; +import com.cognifide.apm.core.Property; +import com.cognifide.apm.core.endpoints.response.ResponseEntity; +import com.cognifide.apm.core.endpoints.utils.RequestProcessor; +import com.cognifide.apm.core.logger.Position; +import com.cognifide.apm.core.logger.ProgressEntry; +import com.cognifide.apm.core.scripts.ScriptStorageException; +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import javax.jcr.RepositoryException; +import javax.servlet.Servlet; +import org.apache.commons.lang3.StringUtils; +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.api.SlingHttpServletResponse; +import org.apache.sling.api.resource.PersistenceException; +import org.apache.sling.api.servlets.SlingAllMethodsServlet; +import org.apache.sling.models.factory.ModelFactory; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; + +@Component( + service = Servlet.class, + property = { + Property.PATH + "/bin/apm/scripts/validate", + Property.METHOD + "POST", + Property.DESCRIPTION + "APM Script Validation Servlet", + Property.VENDOR + } +) +public class ScriptValidationServlet extends SlingAllMethodsServlet { + + @Reference + private ScriptManager scriptManager; + + @Reference + private ModelFactory modelFactory; + + @Override + protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException { + RequestProcessor.process(modelFactory, ScriptValidationForm.class, request, response, (form, resourceResolver) -> { + try { + Script script = TransientScript.create(form.getPath(), form.getContent()); + ExecutionResult result = scriptManager.process(script, ExecutionMode.VALIDATION, resourceResolver); + if (result.isSuccess()) { + return ResponseEntity.ok("Script passes validation") + .addEntry("valid", true); + } else { + List validationErrors = transformToValidationErrors(result); + return ResponseEntity.ok("Script does not pass validation") + .addEntry("valid", false) + .addEntry("errors", validationErrors); + } + } catch (ScriptStorageException e) { + return ResponseEntity.badRequest(StringUtils.defaultString(e.getMessage(), "Errors while saving script")) + .addEntry("errors", e.getErrors()); + } catch (PersistenceException | RepositoryException e) { + throw new RuntimeException(e); + } + }); + } + + private List transformToValidationErrors(ExecutionResult result) { + return result.getEntries() + .stream() + .filter(entry -> entry.getStatus() == Status.ERROR) + .filter(entry -> !entry.getMessages().isEmpty()) + .flatMap(this::transformToErrors) + .collect(Collectors.toList()); + } + + private Stream transformToErrors(ExecutionResult.Entry entry) { + String positionPrefix = positionPrefix(entry); + return entry.getMessages() + .stream() + .map(message -> positionPrefix + message); + } + + private String positionPrefix(ExecutionResult.Entry entry) { + Position position = entry instanceof ProgressEntry ? ((ProgressEntry) entry).getPosition() : null; + return position != null ? String.format("Invalid line %d: ", position.getLine()) : ""; + } +} diff --git a/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/dto/ScriptDto.java b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/dto/ScriptDto.java new file mode 100644 index 000000000..6acc72a4a --- /dev/null +++ b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/dto/ScriptDto.java @@ -0,0 +1,55 @@ +/*- + * ========================LICENSE_START================================= + * AEM Permission Management + * %% + * Copyright (C) 2013 Wunderman Thompson Technology + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ +package com.cognifide.apm.core.endpoints.dto; + +import com.cognifide.apm.api.scripts.Script; +import java.util.Date; +import org.apache.commons.io.FilenameUtils; + +public class ScriptDto { + + private final String name; + + private final String path; + + private final String author; + + private final boolean launchEnabled; + + private final String launchMode; + + private final Date lastModified; + + private final boolean valid; + + public ScriptDto(Script script) { + this.name = FilenameUtils.getName(script.getPath()); + this.path = script.getPath(); + this.author = script.getAuthor(); + this.launchEnabled = script.isLaunchEnabled(); + this.launchMode = script.getLaunchMode().name().toLowerCase(); + this.lastModified = script.getLastModified(); + this.valid = script.isValid(); + } + + public String getPath() { + return path; + } +} diff --git a/app/aem/core/src/main/kotlin/com/cognifide/apm/core/grammar/executioncontext/RunScript.kt b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/params/DateFormat.java similarity index 67% rename from app/aem/core/src/main/kotlin/com/cognifide/apm/core/grammar/executioncontext/RunScript.kt rename to app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/params/DateFormat.java index 0cdc76e5a..faf19aad5 100644 --- a/app/aem/core/src/main/kotlin/com/cognifide/apm/core/grammar/executioncontext/RunScript.kt +++ b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/params/DateFormat.java @@ -18,14 +18,16 @@ * =========================LICENSE_END================================== */ -package com.cognifide.apm.core.grammar.executioncontext +package com.cognifide.apm.core.endpoints.params; -import com.cognifide.apm.core.grammar.parsedscript.ParsedScript +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; -class RunScript(val parsedScript: ParsedScript) { +@Target({ElementType.FIELD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +public @interface DateFormat { - val variableHolder = VariableHolder() - - val path: String - get() = parsedScript.script.path -} \ No newline at end of file + String value(); +} diff --git a/app/aem/core/src/main/kotlin/com/cognifide/apm/core/grammar/argument/Arguments.kt b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/params/FileName.java similarity index 69% rename from app/aem/core/src/main/kotlin/com/cognifide/apm/core/grammar/argument/Arguments.kt rename to app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/params/FileName.java index d1ed6d27d..63922d354 100644 --- a/app/aem/core/src/main/kotlin/com/cognifide/apm/core/grammar/argument/Arguments.kt +++ b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/params/FileName.java @@ -18,12 +18,14 @@ * =========================LICENSE_END================================== */ -package com.cognifide.apm.core.grammar.argument +package com.cognifide.apm.core.endpoints.params; -import com.cognifide.apm.core.grammar.ApmType +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; -data class Arguments( - val required: List = listOf(), - val named: Map = mapOf(), - val flags: List = listOf() -) \ No newline at end of file +@Target({ElementType.FIELD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +public @interface FileName { +} diff --git a/app/aem/core/src/main/kotlin/com/cognifide/apm/core/endpoints/params/RequestParameter.kt b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/params/RequestParameter.java similarity index 65% rename from app/aem/core/src/main/kotlin/com/cognifide/apm/core/endpoints/params/RequestParameter.kt rename to app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/params/RequestParameter.java index 6c1bd62a3..86026dcb0 100644 --- a/app/aem/core/src/main/kotlin/com/cognifide/apm/core/endpoints/params/RequestParameter.kt +++ b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/params/RequestParameter.java @@ -18,13 +18,22 @@ * =========================LICENSE_END================================== */ -package com.cognifide.apm.core.endpoints.params +package com.cognifide.apm.core.endpoints.params; -import org.apache.sling.models.annotations.Source -import org.apache.sling.models.spi.injectorspecific.InjectAnnotation +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.apache.sling.models.annotations.Source; +import org.apache.sling.models.spi.injectorspecific.InjectAnnotation; -@Target(AnnotationTarget.FIELD, AnnotationTarget.VALUE_PARAMETER) -@Retention(AnnotationRetention.RUNTIME) +@Target({ElementType.FIELD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) @InjectAnnotation @Source("apm-request-parameter") -annotation class RequestParameter(val value: String, val optional: Boolean = true, val fileName: Boolean = false) \ No newline at end of file +public @interface RequestParameter { + + String value(); + + boolean optional() default true; +} diff --git a/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/params/RequestParameterInjector.java b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/params/RequestParameterInjector.java new file mode 100644 index 000000000..90db59490 --- /dev/null +++ b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/params/RequestParameterInjector.java @@ -0,0 +1,155 @@ +/* + * ========================LICENSE_START================================= + * AEM Permission Management + * %% + * Copyright (C) 2013 Wunderman Thompson Technology + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ + +package com.cognifide.apm.core.endpoints.params; + +import com.cognifide.apm.core.Property; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Arrays; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.models.spi.DisposalCallbackRegistry; +import org.apache.sling.models.spi.Injector; +import org.apache.sling.models.spi.injectorspecific.AbstractInjectAnnotationProcessor2; +import org.apache.sling.models.spi.injectorspecific.InjectAnnotationProcessor2; +import org.apache.sling.models.spi.injectorspecific.StaticInjectAnnotationProcessorFactory; +import org.osgi.framework.Constants; +import org.osgi.service.component.annotations.Component; + +@Component( + property = { + Constants.SERVICE_RANKING + "=" + Integer.MIN_VALUE, + Property.VENDOR + } +) +public class RequestParameterInjector implements Injector, StaticInjectAnnotationProcessorFactory { + + @Override + public String getName() { + return "apm-request-parameter"; + } + + @Override + public Object getValue(Object adaptable, String fieldName, Type type, AnnotatedElement annotatedElement, DisposalCallbackRegistry disposalCallbackRegistry) { + if (adaptable instanceof SlingHttpServletRequest) { + RequestParameter annotation = annotatedElement.getAnnotation(RequestParameter.class); + if (annotation != null) { + String parameterName = annotation.value(); + if (type instanceof ParameterizedType && ((ParameterizedType) type).getRawType() instanceof Class && Map.class.isAssignableFrom((Class) ((ParameterizedType) type).getRawType())) { + return extractParams((SlingHttpServletRequest) adaptable, parameterName); + } else if (type instanceof Class) { + return getValue((SlingHttpServletRequest) adaptable, (Class) type, parameterName, annotatedElement); + } + } + } + return null; + } + + private Object getValue(SlingHttpServletRequest request, Class type, String parameterName, AnnotatedElement annotatedElement) { + org.apache.sling.api.request.RequestParameter parameterValue = request.getRequestParameter(parameterName); + if (parameterValue == null) { + return null; + } else if (annotatedElement.isAnnotationPresent(FileName.class)) { + return parameterValue.getFileName(); + } else if (type == Integer.class || type == int.class) { + return Integer.parseInt(parameterValue.getString()); + } else if (type == Boolean.class || type == boolean.class) { + return BooleanUtils.toBoolean(parameterValue.getString()); + } else if (type == InputStream.class) { + return toInputStream(parameterValue); + } else if (type == LocalDateTime.class) { + return toLocalDateTime(annotatedElement, parameterValue); + } else if (type.isEnum()) { + return toEnum(type, parameterValue); + } else if (type == String[].class) { + return parameterValue.getString().split(","); + } + return parameterValue.getString(); + } + + private InputStream toInputStream(org.apache.sling.api.request.RequestParameter parameterValue) { + try { + return parameterValue.getInputStream(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private Object toEnum(Class type, org.apache.sling.api.request.RequestParameter parameterValue) { + return Arrays.stream(type.getEnumConstants()) + .filter(item -> StringUtils.equals(item.toString(), parameterValue.getString())) + .findFirst() + .orElse(null); + } + + private Map extractParams(SlingHttpServletRequest request, String prefix) { + return request.getParameterMap() + .entrySet() + .stream() + .filter(entry -> StringUtils.startsWith(entry.getKey(), prefix)) + .collect(Collectors.toMap( + entry -> StringUtils.uncapitalize(StringUtils.removeStart(entry.getKey(), prefix)), + entry -> entry.getValue()[0] + )); + } + + private LocalDateTime toLocalDateTime(AnnotatedElement annotatedElement, org.apache.sling.api.request.RequestParameter parameterValue) { + String dateFormat = Optional.ofNullable(annotatedElement.getAnnotation(DateFormat.class)) + .map(DateFormat::value) + .orElse(DateTimeFormatter.ISO_LOCAL_DATE_TIME.toString()); + return LocalDateTime.parse(parameterValue.getString(), DateTimeFormatter.ofPattern(dateFormat)); + } + + @Override + public InjectAnnotationProcessor2 createAnnotationProcessor(AnnotatedElement element) { + return Optional.ofNullable(element.getAnnotation(RequestParameter.class)) + .map(RequestParameterAnnotationProcessor::new) + .orElse(null); + } + + private static class RequestParameterAnnotationProcessor extends AbstractInjectAnnotationProcessor2 { + + private final RequestParameter annotation; + + public RequestParameterAnnotationProcessor(RequestParameter annotation) { + this.annotation = annotation; + } + + @Override + public String getName() { + return annotation.value(); + } + + @Override + public Boolean isOptional() { + return annotation.optional(); + } + } +} diff --git a/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/response/ResponseEntity.java b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/response/ResponseEntity.java new file mode 100644 index 000000000..4d54a387c --- /dev/null +++ b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/response/ResponseEntity.java @@ -0,0 +1,67 @@ +/* + * ========================LICENSE_START================================= + * AEM Permission Management + * %% + * Copyright (C) 2013 Wunderman Thompson Technology + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ + +package com.cognifide.apm.core.endpoints.response; + +import java.util.HashMap; +import java.util.Map; +import javax.servlet.http.HttpServletResponse; + +public class ResponseEntity { + + private final int statusCode; + + private final Map body; + + private ResponseEntity(int statusCode, String message) { + this.statusCode = statusCode; + this.body = new HashMap<>(); + addEntry("message", message); + } + + public ResponseEntity addEntry(String key, Object value) { + body.put(key, value); + return this; + } + + public int getStatusCode() { + return statusCode; + } + + public Map getBody() { + return body; + } + + public static ResponseEntity badRequest(String message) { + return new ResponseEntity(HttpServletResponse.SC_BAD_REQUEST, message); + } + + public static ResponseEntity notFound(String message) { + return new ResponseEntity(HttpServletResponse.SC_NOT_FOUND, message); + } + + public static ResponseEntity internalServerError(String message) { + return new ResponseEntity(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message); + } + + public static ResponseEntity ok(String message) { + return new ResponseEntity(HttpServletResponse.SC_OK, message); + } +} diff --git a/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/utils/RequestProcessor.java b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/utils/RequestProcessor.java new file mode 100644 index 000000000..6d9237e06 --- /dev/null +++ b/app/aem/core/src/main/java/com/cognifide/apm/core/endpoints/utils/RequestProcessor.java @@ -0,0 +1,77 @@ +/* + * ========================LICENSE_START================================= + * AEM Permission Management + * %% + * Copyright (C) 2013 Wunderman Thompson Technology + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ +package com.cognifide.apm.core.endpoints.utils; + +import com.cognifide.apm.core.endpoints.params.RequestParameter; +import com.cognifide.apm.core.endpoints.response.ResponseEntity; +import com.cognifide.apm.core.utils.ServletUtils; +import com.google.common.collect.ImmutableMap; +import java.io.IOException; +import java.util.List; +import java.util.Objects; +import java.util.function.BiFunction; +import java.util.stream.Collectors; +import javax.servlet.http.HttpServletResponse; +import org.apache.commons.lang3.StringUtils; +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.api.SlingHttpServletResponse; +import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.models.factory.MissingElementException; +import org.apache.sling.models.factory.MissingElementsException; +import org.apache.sling.models.factory.ModelFactory; + +public final class RequestProcessor { + + private RequestProcessor() { + // intentionally empty + } + + public static void process(ModelFactory modelFactory, Class formClass, SlingHttpServletRequest httpRequest, SlingHttpServletResponse httpResponse, BiFunction processFunc) throws IOException { + try { + T form = modelFactory.createModel(httpRequest, formClass); + ResponseEntity response = processFunc.apply(form, httpRequest.getResourceResolver()); + + httpResponse.setStatus(response.getStatusCode()); + ServletUtils.writeJson(httpResponse, response.getBody()); + } catch (MissingElementsException e) { + httpResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST); + ServletUtils.writeJson(httpResponse, ImmutableMap.of( + "message", "Bad request", + "errors", toErrors(e) + )); + } catch (Exception e) { + httpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + ServletUtils.writeJson(httpResponse, ImmutableMap.of( + "message", StringUtils.defaultString(e.getMessage()) + )); + } + } + + private static List toErrors(MissingElementsException e) { + return e.getMissingElements() + .stream() + .map(MissingElementException::getElement) + .filter(Objects::nonNull) + .map(element -> element.getAnnotation(RequestParameter.class)) + .filter(Objects::nonNull) + .map(annotation -> String.format("Missing required parameter: %s", annotation.value())) + .collect(Collectors.toList()); + } +} diff --git a/app/aem/core/src/main/kotlin/com/cognifide/apm/core/grammar/ActionInvoker.kt b/app/aem/core/src/main/java/com/cognifide/apm/core/grammar/ActionInvoker.java similarity index 72% rename from app/aem/core/src/main/kotlin/com/cognifide/apm/core/grammar/ActionInvoker.kt rename to app/aem/core/src/main/java/com/cognifide/apm/core/grammar/ActionInvoker.java index e05f8a0c6..5534881e0 100644 --- a/app/aem/core/src/main/kotlin/com/cognifide/apm/core/grammar/ActionInvoker.kt +++ b/app/aem/core/src/main/java/com/cognifide/apm/core/grammar/ActionInvoker.java @@ -18,13 +18,13 @@ * =========================LICENSE_END================================== */ -package com.cognifide.apm.core.grammar +package com.cognifide.apm.core.grammar; -import com.cognifide.apm.api.status.Status -import com.cognifide.apm.core.grammar.argument.Arguments -import com.cognifide.apm.core.grammar.executioncontext.ExternalExecutionContext +import com.cognifide.apm.api.status.Status; +import com.cognifide.apm.core.grammar.argument.Arguments; +import com.cognifide.apm.core.grammar.executioncontext.ExternalExecutionContext; -interface ActionInvoker { +public interface ActionInvoker { - fun runAction(executionContext: ExternalExecutionContext, commandName: String, arguments: Arguments): Status + Status runAction(ExternalExecutionContext executionContext, String commandName, Arguments arguments); } diff --git a/app/aem/core/src/main/java/com/cognifide/apm/core/grammar/ApmType.java b/app/aem/core/src/main/java/com/cognifide/apm/core/grammar/ApmType.java new file mode 100644 index 000000000..61c0fb36a --- /dev/null +++ b/app/aem/core/src/main/java/com/cognifide/apm/core/grammar/ApmType.java @@ -0,0 +1,266 @@ +/* + * ========================LICENSE_START================================= + * AEM Permission Management + * %% + * Copyright (C) 2013 Wunderman Thompson Technology + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ + +package com.cognifide.apm.core.grammar; + +import com.cognifide.apm.core.crypto.DecryptionService; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.StringUtils; + +public abstract class ApmType { + + public Object getArgument(DecryptionService decryptionService) { + return null; + } + + protected String toPrettyString(int depth, int prefixDepth) { + return null; + } + + public Integer getInteger() { + return null; + } + + public String getString() { + return null; + } + + public List getList() { + return null; + } + + public Map getMap() { + return null; + } + + @Override + public String toString() { + return toPrettyString(0, 0); + } + + public static class ApmInteger extends ApmType { + + private final Integer value; + + public ApmInteger(Integer value) { + this.value = value; + } + + @Override + public Object getArgument(DecryptionService decryptionService) { + return value; + } + + @Override + public Integer getInteger() { + return value; + } + + @Override + public String getString() { + return value.toString(); + } + + @Override + public String toPrettyString(int depth, int prefixDepth) { + return StringUtils.repeat('\t', Math.min(depth, prefixDepth)) + value; + } + } + + public static class ApmString extends ApmType { + + private final String value; + + public ApmString(String value) { + this.value = value; + } + + @Override + public Object getArgument(DecryptionService decryptionService) { + return decryptionService.decrypt(value); + } + + @Override + public String getString() { + return value; + } + + @Override + protected String toPrettyString(int depth, int prefixDepth) { + return StringUtils.repeat('\t', Math.min(depth, prefixDepth)) + "\"" + value + "\""; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof ApmString) { + ApmString that = (ApmString) obj; + return Objects.equals(value, that.value); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash(value); + } + } + + public static class ApmList extends ApmType { + + private final List values; + + public ApmList(List values) { + this.values = values; + } + + @Override + public Object getArgument(DecryptionService decryptionService) { + return values.stream() + .map(value -> value.getArgument(decryptionService)) + .collect(Collectors.toList()); + } + + @Override + public List getList() { + return values; + } + + @Override + protected String toPrettyString(int depth, int prefixDepth) { + boolean simpleList = values.stream() + .allMatch(value -> value instanceof ApmInteger || value instanceof ApmString); + if (values.isEmpty() || simpleList) { + return values.stream() + .map(ApmType::toString) + .collect(Collectors.joining( + ", ", + StringUtils.repeat('\t', prefixDepth) + "[", + "]" + )); + } else { + return values.stream() + .map(value -> value.toPrettyString(depth + 1, depth + 1)) + .collect(Collectors.joining( + ",\n", + StringUtils.repeat('\t', prefixDepth) + "[\n", + "\n" + StringUtils.repeat('\t', depth) + "]" + )); + } + } + } + + public static class ApmMap extends ApmType { + + private final Map values; + + public ApmMap(Map values) { + this.values = values; + } + + @Override + public Object getArgument(DecryptionService decryptionService) { + return values.entrySet() + .stream() + .collect(Collectors.toMap( + Map.Entry::getKey, + entry -> entry.getValue().getArgument(decryptionService) + )); + } + + @Override + public Map getMap() { + return values; + } + + @Override + protected String toPrettyString(int depth, int prefixDepth) { + ApmType firstEntry = values.values() + .stream() + .findFirst() + .orElse(new ApmEmpty()); + boolean simpleList = MapUtils.emptyIfNull(firstEntry.getMap()) + .values() + .stream() + .allMatch(value -> value instanceof ApmInteger || value instanceof ApmString); + if (values.isEmpty() || values.size() == 1 && (firstEntry instanceof ApmInteger || firstEntry instanceof ApmString || simpleList)) { + return values.entrySet() + .stream() + .map(ApmPair::new) + .map(ApmType::toString) + .collect(Collectors.joining( + ", ", + StringUtils.repeat('\t', prefixDepth) + "{", + "}" + )); + } else { + return values.entrySet() + .stream() + .map(ApmPair::new) + .map(pair -> pair.toPrettyString(depth + 1, depth + 1)) + .collect(Collectors.joining( + ",\n", + StringUtils.repeat('\t', prefixDepth) + "{\n", + "\n" + StringUtils.repeat('\t', depth) + "}" + )); + } + } + } + + public static class ApmPair extends ApmType { + + private final String key; + + private final ApmType value; + + public ApmPair(String key, ApmType value) { + this.key = key; + this.value = value; + } + + public ApmPair(Map.Entry entry) { + this.key = entry.getKey(); + this.value = entry.getValue(); + } + + public String getKey() { + return key; + } + + public ApmType getValue() { + return value; + } + + @Override + protected String toPrettyString(int depth, int prefixDepth) { + return StringUtils.repeat('\t', depth) + key + ": " + value.toPrettyString(depth, 0); + } + } + + public static class ApmEmpty extends ApmType { + + } +} diff --git a/app/aem/core/src/main/java/com/cognifide/apm/core/grammar/ReferenceFinder.java b/app/aem/core/src/main/java/com/cognifide/apm/core/grammar/ReferenceFinder.java new file mode 100644 index 000000000..646a11aba --- /dev/null +++ b/app/aem/core/src/main/java/com/cognifide/apm/core/grammar/ReferenceFinder.java @@ -0,0 +1,241 @@ +/* + * ========================LICENSE_START================================= + * AEM Permission Management + * %% + * Copyright (C) 2013 Wunderman Thompson Technology + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ + +package com.cognifide.apm.core.grammar; + +import com.cognifide.apm.api.scripts.LaunchEnvironment; +import com.cognifide.apm.api.scripts.LaunchMode; +import com.cognifide.apm.api.scripts.Script; +import com.cognifide.apm.api.services.ScriptFinder; +import com.cognifide.apm.core.grammar.antlr.ApmLangBaseVisitor; +import com.cognifide.apm.core.grammar.antlr.ApmLangParser; +import com.cognifide.apm.core.grammar.common.Functions; +import com.cognifide.apm.core.grammar.executioncontext.ExecutionContext; +import com.cognifide.apm.core.grammar.parsedscript.ParsedScript; +import com.cognifide.apm.core.progress.ProgressImpl; +import com.google.common.collect.ImmutableList; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; +import org.apache.sling.api.resource.ResourceResolver; + +public class ReferenceFinder { + + private final ScriptFinder scriptFinder; + + private final ResourceResolver resourceResolver; + + public ReferenceFinder(ScriptFinder scriptFinder, ResourceResolver resourceResolver) { + this.scriptFinder = scriptFinder; + this.resourceResolver = resourceResolver; + } + + public List