diff --git a/LICENSE b/LICENSE index d372caa2..9999fef8 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright 2013 CITYTECH, Inc. +Copyright 2016 ICF Olson Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index c986326b..fbe7558c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # AEM Groovy Console -[CITYTECH, Inc.](http://www.citytechinc.com) +[ICF Olson](http://www.icfolson.com) ## Overview @@ -34,11 +34,11 @@ If you are running AEM with a context path, set the Maven property `aem.context. ## Extensions -Starting in version 7.0.0, the Groovy Console provides extension hooks to further customize script execution. The console exposes an API containing three extension provider interfaces that can be implemented as OSGi services in any bundle deployed to an AEM instance. See the default extension providers in the `com.citytechinc.aem.groovy.console.extension.impl` package for examples of how a bundle can implement these services to supply additional script bindings, metaclasses, and star imports. +Starting in version 7.0.0, the Groovy Console provides extension hooks to further customize script execution. The console exposes an API containing three extension provider interfaces that can be implemented as OSGi services in any bundle deployed to an AEM instance. See the default extension providers in the `com.icfolson.aem.groovy.console.extension.impl` package for examples of how a bundle can implement these services to supply additional script bindings, metaclasses, and star imports. ### Notifications -To provide custom notifications for script executions, bundles may implement the `com.citytechinc.aem.groovy.console.notification.NotificationService` interface (see the `com.citytechinc.aem.groovy.console.notification.impl.EmailNotificationService` class for an example). These services will be dynamically bound by the Groovy Console service and all registered notification services will be called for each script execution. +To provide custom notifications for script executions, bundles may implement the `com.icfolson.aem.groovy.console.notification.NotificationService` interface (see the `com.citytechinc.aem.groovy.console.notification.impl.EmailNotificationService` class for an example). These services will be dynamically bound by the Groovy Console service and all registered notification services will be called for each script execution. ## Notes diff --git a/pom.xml b/pom.xml index 70a9a83e..689205ae 100644 --- a/pom.xml +++ b/pom.xml @@ -2,16 +2,16 @@ - com.citytechinc.aem + com.icfolson.aem parent - 6.1.1 + 6.2.1 4.0.0 - com.citytechinc.aem.groovy.console + com.icfolson.aem.groovy.console aem-groovy-console jar - 8.0.1 + 9.0.0 AEM Groovy Console The AEM Groovy Console provides an interface for running Groovy scripts in the AEM (Adobe CQ) container. Scripts @@ -20,8 +20,8 @@ - CITYTECH, Inc. - http://www.citytechinc.com + ICF Olson + http://www.icfolson.com @@ -70,8 +70,9 @@ ${maven.build.timestamp} install admin - + true + zip.xml @@ -85,6 +86,17 @@ true + + exclude-groovy-bundle + + + exclude-groovy-bundle + + + + zip-exclude-groovy-bundle.xml + + local @@ -131,11 +143,11 @@ maven-compiler-plugin - 3.3 + 3.5 groovy-eclipse-compiler - 1.7 - 1.7 + 1.8 + 1.8 utf-8 @@ -153,7 +165,7 @@ maven-surefire-plugin - 2.18.1 + 2.19.1 **/*Spec* @@ -179,7 +191,7 @@ org.apache.felix maven-bundle-plugin - 2.5.3 + 3.0.1 true @@ -193,7 +205,7 @@ ${project.artifactId} ${project.name} ${project.organization.name} - !*.impl,com.citytechinc.aem.groovy.console.* + !*.impl,com.icfolson.aem.groovy.console.* * @@ -211,7 +223,7 @@ false - src/main/assembly/zip.xml + src/main/assembly/${assembly.descriptor.name} @@ -352,10 +364,6 @@ org.osgi org.osgi.core - - org.apache.felix - org.apache.felix.scr - org.apache.sling org.apache.sling.api @@ -365,7 +373,7 @@ org.apache.sling.jcr.api - org.apache.sling + com.adobe.granite.sling org.apache.sling.jcr.resource @@ -392,14 +400,9 @@ com.day.cq cq-mailer - - com.day.cq - cq-tagging - com.day.cq.wcm cq-wcm-taglib - [5.7.4,5.8.2] com.adobe.granite @@ -414,13 +417,13 @@ commons-lang3 - org.apache.commons - commons-email + com.day.commons.osgi.wrapper + com.day.commons.osgi.wrapper.commons-email + + + org.apache.jackrabbit + jackrabbit-api - - org.apache.jackrabbit - jackrabbit-api - @@ -433,21 +436,21 @@ org.codehaus.groovy groovy-all - 2.4.3 + 2.4.7 provided - com.citytechinc.aem.groovy.extension + com.icfolson.aem.groovy.extension aem-groovy-extension-bundle - 1.0.1 + 2.0.0 provided - com.citytechinc.aem.prosper + com.icfolson.aem.prosper prosper - 5.0.0 + 8.0.0 test diff --git a/src/main/assembly/zip-exclude-groovy-bundle.xml b/src/main/assembly/zip-exclude-groovy-bundle.xml new file mode 100644 index 00000000..94b345a1 --- /dev/null +++ b/src/main/assembly/zip-exclude-groovy-bundle.xml @@ -0,0 +1,42 @@ + + + zip + + zip + + false + + + ${basedir}/src/main/content/jcr_root + + **/.DS_Store + + jcr_root + + + ${basedir}/src/main/scripts + jcr_root/etc/groovyconsole/scripts/samples + + + ${basedir}/src/main/content/META-INF + META-INF + true + + + + + jcr_root/apps/groovyconsole/install + true + true + provided + false + + com.icfolson.aem.groovy.console:aem-groovy-console + com.icfolson.aem.groovy.extension:aem-groovy-extension-bundle + + + + \ No newline at end of file diff --git a/src/main/assembly/zip.xml b/src/main/assembly/zip.xml index f7df4228..c9abdf9e 100644 --- a/src/main/assembly/zip.xml +++ b/src/main/assembly/zip.xml @@ -34,8 +34,8 @@ provided false - com.citytechinc.aem.groovy.console:aem-groovy-console - com.citytechinc.aem.groovy.extension:aem-groovy-extension-bundle + com.icfolson.aem.groovy.console:aem-groovy-console + com.icfolson.aem.groovy.extension:aem-groovy-extension-bundle org.codehaus.groovy:groovy-all diff --git a/src/main/content/META-INF/vault/properties.xml b/src/main/content/META-INF/vault/properties.xml index ebed4286..ebfc4991 100644 --- a/src/main/content/META-INF/vault/properties.xml +++ b/src/main/content/META-INF/vault/properties.xml @@ -2,11 +2,11 @@ FileVault Package Properties - ${cq.username} + ${aem.username} ${project.artifactId} ${project.description} ${timestamp} - ${cq.username} + ${aem.username} ${timestamp} 1 ${project.version} @@ -15,5 +15,5 @@ 2 ${timestamp} - ${cq.username} + ${aem.username} \ No newline at end of file diff --git a/src/main/content/jcr_root/apps/groovyconsole/components/console/about.jsp b/src/main/content/jcr_root/apps/groovyconsole/components/console/about.jsp index 30f4be52..6332934d 100644 --- a/src/main/content/jcr_root/apps/groovyconsole/components/console/about.jsp +++ b/src/main/content/jcr_root/apps/groovyconsole/components/console/about.jsp @@ -12,7 +12,7 @@
  • Inspired by Guillaume Laforge's Groovy Web Console.
  • Implemented with Groovy version <%= groovy.lang.GroovySystem.getVersion() %> and Bootstrap.
  • Code editing capabilities provided by Ace.
  • -
  • Project hosted on GitHub for CITYTECH, Inc.
  • +
  • Project hosted on GitHub for ICF Olson
  • diff --git a/src/main/content/jcr_root/apps/groovyconsole/components/console/imports.jsp b/src/main/content/jcr_root/apps/groovyconsole/components/console/imports.jsp index d2f367f5..d8837e01 100644 --- a/src/main/content/jcr_root/apps/groovyconsole/components/console/imports.jsp +++ b/src/main/content/jcr_root/apps/groovyconsole/components/console/imports.jsp @@ -10,13 +10,13 @@ diff --git a/src/main/content/jcr_root/apps/groovyconsole/components/global.jsp b/src/main/content/jcr_root/apps/groovyconsole/components/global.jsp index c2ef7b32..7d5cddc3 100644 --- a/src/main/content/jcr_root/apps/groovyconsole/components/global.jsp +++ b/src/main/content/jcr_root/apps/groovyconsole/components/global.jsp @@ -1,4 +1,4 @@ <%@include file="/libs/foundation/global.jsp"%> -<%@taglib prefix="groovyConsole" uri="http://www.citytechinc.com/taglibs/groovyconsole"%> +<%@taglib prefix="groovyConsole" uri="http://www.icfolson.com/taglibs/groovyconsole"%> \ No newline at end of file diff --git a/src/main/content/jcr_root/etc/groovyconsole/clientlibs/css/console.css b/src/main/content/jcr_root/etc/groovyconsole/clientlibs/css/console.css index 8d0921bf..05bccea1 100644 --- a/src/main/content/jcr_root/etc/groovyconsole/clientlibs/css/console.css +++ b/src/main/content/jcr_root/etc/groovyconsole/clientlibs/css/console.css @@ -79,4 +79,8 @@ td.open-record, td.delete-record { #result-table table { background-color: #f5f5f5; +} + +.popover { + max-width: 100%; } \ No newline at end of file diff --git a/src/main/content/jcr_root/etc/groovyconsole/clientlibs/js/audit.js b/src/main/content/jcr_root/etc/groovyconsole/clientlibs/js/audit.js index 02f2b1c2..d870628f 100644 --- a/src/main/content/jcr_root/etc/groovyconsole/clientlibs/js/audit.js +++ b/src/main/content/jcr_root/etc/groovyconsole/clientlibs/js/audit.js @@ -41,6 +41,13 @@ GroovyConsole.Audit = function () { rowCallback: function (row, data) { $('td:eq(1)', row).html('' + data.date + ''); $('td:eq(2)', row).html('' + data.scriptPreview + ''); + $('td:eq(2)', row).popover({ + container: 'body', + content: '
    ' + data.script + '
    ', + html: true, + placement: 'top', + trigger: 'hover' + }); if (data.exception.length) { $('td:eq(3)', row).html('' + data.exception + ''); diff --git a/src/main/content/jcr_root/etc/groovyconsole/clientlibs/js/console.js b/src/main/content/jcr_root/etc/groovyconsole/clientlibs/js/console.js index 5c754166..cd57c135 100644 --- a/src/main/content/jcr_root/etc/groovyconsole/clientlibs/js/console.js +++ b/src/main/content/jcr_root/etc/groovyconsole/clientlibs/js/console.js @@ -219,7 +219,7 @@ var GroovyConsole = function () { hasTable = true; } catch (e) { - console.log('unable to parse JSON for table = ' + e.message); + } return hasTable; @@ -280,7 +280,7 @@ var GroovyConsole = function () { loadScript: function (scriptPath) { GroovyConsole.reset(); - $.get(CQ.shared.HTTP.getContextPath() + '/crx/server/crx.default/jcr%3aroot' + scriptPath + '/jcr%3Acontent/jcr:data').done(function (script) { + $.get(CQ.shared.HTTP.getContextPath() + scriptPath + '/jcr:content/jcr:data').done(function (script) { GroovyConsole.localStorage.saveScriptName(scriptPath); GroovyConsole.showSuccess('Script loaded successfully.'); diff --git a/src/main/groovy/com/citytechinc/aem/groovy/console/GroovyConsoleService.groovy b/src/main/groovy/com/citytechinc/aem/groovy/console/GroovyConsoleService.groovy deleted file mode 100644 index 964ebcbd..00000000 --- a/src/main/groovy/com/citytechinc/aem/groovy/console/GroovyConsoleService.groovy +++ /dev/null @@ -1,12 +0,0 @@ -package com.citytechinc.aem.groovy.console - -import com.citytechinc.aem.groovy.console.response.RunScriptResponse -import com.citytechinc.aem.groovy.console.response.SaveScriptResponse -import org.apache.sling.api.SlingHttpServletRequest - -interface GroovyConsoleService { - - RunScriptResponse runScript(SlingHttpServletRequest request) - - SaveScriptResponse saveScript(SlingHttpServletRequest request) -} diff --git a/src/main/groovy/com/citytechinc/aem/groovy/console/configuration/ConfigurationService.groovy b/src/main/groovy/com/citytechinc/aem/groovy/console/configuration/ConfigurationService.groovy deleted file mode 100644 index cf1b4944..00000000 --- a/src/main/groovy/com/citytechinc/aem/groovy/console/configuration/ConfigurationService.groovy +++ /dev/null @@ -1,14 +0,0 @@ -package com.citytechinc.aem.groovy.console.configuration - -interface ConfigurationService { - - Set getAllowedGroups() - - String getConsoleHref() - - Set getEmailRecipients() - - boolean isAuditDisabled() - - boolean isEmailEnabled() -} \ No newline at end of file diff --git a/src/main/groovy/com/citytechinc/aem/groovy/console/servlets/ScriptPostServlet.groovy b/src/main/groovy/com/citytechinc/aem/groovy/console/servlets/ScriptPostServlet.groovy deleted file mode 100755 index 5f009c1f..00000000 --- a/src/main/groovy/com/citytechinc/aem/groovy/console/servlets/ScriptPostServlet.groovy +++ /dev/null @@ -1,66 +0,0 @@ -package com.citytechinc.aem.groovy.console.servlets - -import com.citytechinc.aem.groovy.console.configuration.ConfigurationService -import com.citytechinc.aem.groovy.console.GroovyConsoleService -import groovy.util.logging.Slf4j -import org.apache.felix.scr.annotations.Activate -import org.apache.felix.scr.annotations.Deactivate -import org.apache.felix.scr.annotations.Reference -import org.apache.felix.scr.annotations.sling.SlingServlet -import org.apache.jackrabbit.api.security.user.UserManager -import org.apache.sling.api.SlingHttpServletRequest -import org.apache.sling.api.SlingHttpServletResponse -import org.apache.sling.api.resource.ResourceResolver -import org.apache.sling.api.resource.ResourceResolverFactory - -import javax.servlet.ServletException - -import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN - -@SlingServlet(paths = "/bin/groovyconsole/post") -@Slf4j("LOG") -class ScriptPostServlet extends AbstractJsonResponseServlet { - - @Reference - ConfigurationService configurationService - - @Reference - GroovyConsoleService consoleService - - @Reference - ResourceResolverFactory resourceResolverFactory - - private ResourceResolver resourceResolver - - @Override - protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws - ServletException, IOException { - if (hasPermission(request)) { - writeJsonResponse(response, consoleService.runScript(request)) - } else { - response.setStatus(SC_FORBIDDEN) - } - } - - boolean hasPermission(SlingHttpServletRequest request) { - def user = resourceResolver.adaptTo(UserManager).getAuthorizable(request.userPrincipal) - - def memberOfGroupIds = user.memberOf()*.getID() - def allowedGroupIds = configurationService.allowedGroups - - LOG.debug("member of group IDs = {}, allowed group IDs = {}", memberOfGroupIds, allowedGroupIds) - - allowedGroupIds ? memberOfGroupIds.intersect(allowedGroupIds) : true - } - - @Activate - @SuppressWarnings("deprecated") - void activate() { - resourceResolver = resourceResolverFactory.getAdministrativeResourceResolver(null) - } - - @Deactivate - void deactivate() { - resourceResolver?.close() - } -} diff --git a/src/main/groovy/com/icfolson/aem/groovy/console/GroovyConsoleService.groovy b/src/main/groovy/com/icfolson/aem/groovy/console/GroovyConsoleService.groovy new file mode 100644 index 00000000..95f7a178 --- /dev/null +++ b/src/main/groovy/com/icfolson/aem/groovy/console/GroovyConsoleService.groovy @@ -0,0 +1,14 @@ +package com.icfolson.aem.groovy.console + +import com.icfolson.aem.groovy.console.response.RunScriptResponse +import com.icfolson.aem.groovy.console.response.SaveScriptResponse +import org.apache.sling.api.SlingHttpServletRequest + +interface GroovyConsoleService { + + RunScriptResponse runScript(SlingHttpServletRequest request) + + RunScriptResponse runScriptFile(SlingHttpServletRequest request) + + SaveScriptResponse saveScript(SlingHttpServletRequest request) +} diff --git a/src/main/groovy/com/citytechinc/aem/groovy/console/api/BindingExtensionProvider.groovy b/src/main/groovy/com/icfolson/aem/groovy/console/api/BindingExtensionProvider.groovy similarity index 91% rename from src/main/groovy/com/citytechinc/aem/groovy/console/api/BindingExtensionProvider.groovy rename to src/main/groovy/com/icfolson/aem/groovy/console/api/BindingExtensionProvider.groovy index 0fc88d9b..b3ae4128 100644 --- a/src/main/groovy/com/citytechinc/aem/groovy/console/api/BindingExtensionProvider.groovy +++ b/src/main/groovy/com/icfolson/aem/groovy/console/api/BindingExtensionProvider.groovy @@ -1,4 +1,4 @@ -package com.citytechinc.aem.groovy.console.api +package com.icfolson.aem.groovy.console.api import org.apache.sling.api.SlingHttpServletRequest diff --git a/src/main/groovy/com/citytechinc/aem/groovy/console/api/ScriptMetaClassExtensionProvider.groovy b/src/main/groovy/com/icfolson/aem/groovy/console/api/ScriptMetaClassExtensionProvider.groovy similarity index 91% rename from src/main/groovy/com/citytechinc/aem/groovy/console/api/ScriptMetaClassExtensionProvider.groovy rename to src/main/groovy/com/icfolson/aem/groovy/console/api/ScriptMetaClassExtensionProvider.groovy index 7ad53a6b..0a1b09a5 100644 --- a/src/main/groovy/com/citytechinc/aem/groovy/console/api/ScriptMetaClassExtensionProvider.groovy +++ b/src/main/groovy/com/icfolson/aem/groovy/console/api/ScriptMetaClassExtensionProvider.groovy @@ -1,4 +1,4 @@ -package com.citytechinc.aem.groovy.console.api +package com.icfolson.aem.groovy.console.api import org.apache.sling.api.SlingHttpServletRequest diff --git a/src/main/groovy/com/citytechinc/aem/groovy/console/api/StarImportExtensionProvider.groovy b/src/main/groovy/com/icfolson/aem/groovy/console/api/StarImportExtensionProvider.groovy similarity index 90% rename from src/main/groovy/com/citytechinc/aem/groovy/console/api/StarImportExtensionProvider.groovy rename to src/main/groovy/com/icfolson/aem/groovy/console/api/StarImportExtensionProvider.groovy index 6ee064e3..df7bdab0 100644 --- a/src/main/groovy/com/citytechinc/aem/groovy/console/api/StarImportExtensionProvider.groovy +++ b/src/main/groovy/com/icfolson/aem/groovy/console/api/StarImportExtensionProvider.groovy @@ -1,4 +1,4 @@ -package com.citytechinc.aem.groovy.console.api +package com.icfolson.aem.groovy.console.api /** * Services may implement this interface to supply additional star imports to the compiler configuration for Groovy diff --git a/src/main/groovy/com/citytechinc/aem/groovy/console/audit/AuditRecord.groovy b/src/main/groovy/com/icfolson/aem/groovy/console/audit/AuditRecord.groovy similarity index 55% rename from src/main/groovy/com/citytechinc/aem/groovy/console/audit/AuditRecord.groovy rename to src/main/groovy/com/icfolson/aem/groovy/console/audit/AuditRecord.groovy index 10e951e9..e4422ac9 100644 --- a/src/main/groovy/com/citytechinc/aem/groovy/console/audit/AuditRecord.groovy +++ b/src/main/groovy/com/icfolson/aem/groovy/console/audit/AuditRecord.groovy @@ -1,11 +1,11 @@ -package com.citytechinc.aem.groovy.console.audit +package com.icfolson.aem.groovy.console.audit -import com.citytechinc.aem.groovy.console.response.RunScriptResponse +import com.day.text.Text +import com.icfolson.aem.groovy.console.response.RunScriptResponse import groovy.transform.ToString import javax.jcr.Node -import static com.citytechinc.aem.groovy.console.constants.GroovyConsoleConstants.AUDIT_PATH import static com.day.cq.commons.jcr.JcrConstants.JCR_CREATED @ToString(includePackage = false, includes = ["path"]) @@ -30,11 +30,27 @@ class AuditRecord { AuditRecord(Node node) { path = node.path - date = node.get(JCR_CREATED) + date = node.getProperty(JCR_CREATED).date response = RunScriptResponse.fromAuditRecordNode(node) } String getRelativePath() { - (path - AUDIT_PATH).substring(1) + (path - Text.getAbsoluteParent(path, 4)).substring(1) + } + + String getException() { + def exception = "" + + if (exceptionStackTrace) { + def firstLine = exceptionStackTrace.readLines().first() + + if (firstLine.contains(":")) { + exception = firstLine.substring(0, firstLine.indexOf(":")) + } else { + exception = firstLine + } + } + + exception } } diff --git a/src/main/groovy/com/citytechinc/aem/groovy/console/audit/AuditService.groovy b/src/main/groovy/com/icfolson/aem/groovy/console/audit/AuditService.groovy similarity index 51% rename from src/main/groovy/com/citytechinc/aem/groovy/console/audit/AuditService.groovy rename to src/main/groovy/com/icfolson/aem/groovy/console/audit/AuditService.groovy index 136f7c04..e5a29dc8 100644 --- a/src/main/groovy/com/citytechinc/aem/groovy/console/audit/AuditService.groovy +++ b/src/main/groovy/com/icfolson/aem/groovy/console/audit/AuditService.groovy @@ -1,56 +1,63 @@ -package com.citytechinc.aem.groovy.console.audit +package com.icfolson.aem.groovy.console.audit -import com.citytechinc.aem.groovy.console.response.RunScriptResponse +import com.icfolson.aem.groovy.console.response.RunScriptResponse import javax.jcr.RepositoryException +import javax.jcr.Session interface AuditService { /** * Create an audit record for the given script execution response. * + * @param session request session for the user executing the script * @param response response containing execution result or exception */ - AuditRecord createAuditRecord(RunScriptResponse response) + AuditRecord createAuditRecord(Session session, RunScriptResponse response) /** * Delete all audit records. * + * @param session request session, only audit records for the current user will be deleted * @throws RepositoryException if an error occurs while deleting audit nodes */ - void deleteAllAuditRecords() throws RepositoryException + void deleteAllAuditRecords(Session session) throws RepositoryException /** * Delete an audit record. * + * @param session request session, only audit records for the current user will be deleted * @param relativePath relative path to audit record from parent audit node * @throws RepositoryException if an error occurs while deleting the audit record node */ - void deleteAuditRecord(String relativePath) throws RepositoryException + void deleteAuditRecord(Session session, String relativePath) throws RepositoryException /** * Get all audit records. * + * @param session request session, only audit records for the current user will be retrieved * @return all audit records * @throws RepositoryException if error occurs getting audit records */ - List getAllAuditRecords() throws RepositoryException + List getAllAuditRecords(Session session) throws RepositoryException /** * Get the audit record at the given relative path. * + * @param session request session, only audit records for the current user will be retrieved * @param relativePath relative path to audit record from parent audit node * @return audit record or null if none exists */ - AuditRecord getAuditRecord(String relativePath) + AuditRecord getAuditRecord(Session session, String relativePath) /** * Get a list of audit records for the given date range. * + * @param session request session, only audit records for the current user will be retrieved * @param startDate start date * @param endDate end date * @return list of audit records in the given date range * @throws RepositoryException if error occurs getting audit records */ - List getAuditRecords(Calendar startDate, Calendar endDate) throws RepositoryException + List getAuditRecords(Session session, Calendar startDate, Calendar endDate) throws RepositoryException } diff --git a/src/main/groovy/com/citytechinc/aem/groovy/console/audit/impl/DefaultAuditService.groovy b/src/main/groovy/com/icfolson/aem/groovy/console/audit/impl/DefaultAuditService.groovy similarity index 59% rename from src/main/groovy/com/citytechinc/aem/groovy/console/audit/impl/DefaultAuditService.groovy rename to src/main/groovy/com/icfolson/aem/groovy/console/audit/impl/DefaultAuditService.groovy index 11d10ab3..788daf07 100644 --- a/src/main/groovy/com/citytechinc/aem/groovy/console/audit/impl/DefaultAuditService.groovy +++ b/src/main/groovy/com/icfolson/aem/groovy/console/audit/impl/DefaultAuditService.groovy @@ -1,9 +1,9 @@ -package com.citytechinc.aem.groovy.console.audit.impl +package com.icfolson.aem.groovy.console.audit.impl -import com.citytechinc.aem.groovy.console.audit.AuditRecord -import com.citytechinc.aem.groovy.console.audit.AuditService -import com.citytechinc.aem.groovy.console.response.RunScriptResponse import com.day.cq.commons.jcr.JcrUtil +import com.icfolson.aem.groovy.console.audit.AuditRecord +import com.icfolson.aem.groovy.console.audit.AuditService +import com.icfolson.aem.groovy.console.response.RunScriptResponse import groovy.transform.Synchronized import groovy.util.logging.Slf4j import org.apache.felix.scr.annotations.Activate @@ -17,13 +17,13 @@ import javax.jcr.Node import javax.jcr.RepositoryException import javax.jcr.Session -import static com.citytechinc.aem.groovy.console.constants.GroovyConsoleConstants.AUDIT_NODE_NAME -import static com.citytechinc.aem.groovy.console.constants.GroovyConsoleConstants.AUDIT_PATH -import static com.citytechinc.aem.groovy.console.constants.GroovyConsoleConstants.AUDIT_RECORD_NODE_PREFIX -import static com.citytechinc.aem.groovy.console.constants.GroovyConsoleConstants.PATH_CONSOLE_ROOT import static com.day.cq.commons.jcr.JcrConstants.JCR_CONTENT import static com.day.cq.commons.jcr.JcrConstants.MIX_CREATED import static com.day.cq.commons.jcr.JcrConstants.NT_UNSTRUCTURED +import static com.icfolson.aem.groovy.console.constants.GroovyConsoleConstants.AUDIT_NODE_NAME +import static com.icfolson.aem.groovy.console.constants.GroovyConsoleConstants.AUDIT_PATH +import static com.icfolson.aem.groovy.console.constants.GroovyConsoleConstants.AUDIT_RECORD_NODE_PREFIX +import static com.icfolson.aem.groovy.console.constants.GroovyConsoleConstants.PATH_CONSOLE_ROOT @Component(immediate = true) @Service(AuditService) @@ -41,14 +41,14 @@ class DefaultAuditService implements AuditService { @Reference SlingRepository repository - private Session session + private Session adminSession @Override - AuditRecord createAuditRecord(RunScriptResponse response) { + AuditRecord createAuditRecord(Session session, RunScriptResponse response) { def auditRecord = null try { - def auditRecordNode = addAuditRecordNode() + def auditRecordNode = addAuditRecordNode(session) auditRecordNode.set(AuditRecord.PROPERTY_SCRIPT, response.script) @@ -60,7 +60,7 @@ class DefaultAuditService implements AuditService { auditRecordNode.set(AuditRecord.PROPERTY_RUNNING_TIME, response.runningTime) } - session.save() + adminSession.save() auditRecord = new AuditRecord(auditRecordNode) @@ -73,28 +73,30 @@ class DefaultAuditService implements AuditService { } @Override - void deleteAllAuditRecords() throws RepositoryException { + void deleteAllAuditRecords(Session session) throws RepositoryException { try { - session.getNode(AUDIT_PATH).nodes*.remove() + if (adminSession.nodeExists("$AUDIT_PATH/${session.userID}")) { + adminSession.getNode("$AUDIT_PATH/${session.userID}").nodes*.remove() - LOG.debug("deleted all audit record nodes") + LOG.debug("deleted all audit record nodes for user = {}", session.userID) - session.save() + adminSession.save() + } } catch (RepositoryException e) { - LOG.error("error deleting audit records", e) + LOG.error("error deleting audit records for user = ${session.userID}", e) throw e } } @Override - void deleteAuditRecord(String relativePath) { + void deleteAuditRecord(Session session, String relativePath) { try { - session.getNode(AUDIT_PATH).getNode(relativePath).remove() + adminSession.getNode("$AUDIT_PATH/${session.userID}").getNode(relativePath).remove() LOG.debug("deleted audit record at relative path = {}", relativePath) - session.save() + adminSession.save() } catch (RepositoryException e) { LOG.error("error deleting audit record", e) @@ -103,13 +105,15 @@ class DefaultAuditService implements AuditService { } @Override - List getAllAuditRecords() throws RepositoryException { + List getAllAuditRecords(Session session) throws RepositoryException { def auditRecords = [] try { - session.getNode(AUDIT_PATH).recurse { Node node -> - if (node.name.startsWith(AUDIT_RECORD_NODE_PREFIX)) { - auditRecords.add(new AuditRecord(node)) + if (adminSession.nodeExists("$AUDIT_PATH/${session.userID}")) { + adminSession.getNode("$AUDIT_PATH/${session.userID}").recurse { Node node -> + if (node.name.startsWith(AUDIT_RECORD_NODE_PREFIX)) { + auditRecords.add(new AuditRecord(node)) + } } } } catch (RepositoryException e) { @@ -122,11 +126,11 @@ class DefaultAuditService implements AuditService { } @Override - AuditRecord getAuditRecord(String relativePath) { + AuditRecord getAuditRecord(Session session, String relativePath) { def auditRecord = null try { - def auditNode = session.getNode(AUDIT_PATH) + def auditNode = adminSession.getNode("$AUDIT_PATH/${session.userID}") if (auditNode.hasNode(relativePath)) { def auditRecordNode = auditNode.getNode(relativePath) @@ -143,11 +147,12 @@ class DefaultAuditService implements AuditService { } @Override - List getAuditRecords(Calendar startDate, Calendar endDate) throws RepositoryException { + List getAuditRecords(Session session, Calendar startDate, + Calendar endDate) throws RepositoryException { def auditRecords = [] try { - def auditNode = session.getNode(AUDIT_PATH) + def auditNode = adminSession.getNode("$AUDIT_PATH/${session.userID}") def currentDate = startDate @@ -178,27 +183,27 @@ class DefaultAuditService implements AuditService { @Activate @SuppressWarnings("deprecated") void activate() { - session = repository.loginAdministrative(null) + adminSession = repository.loginAdministrative(null) checkAuditNode() } @Deactivate void deactivate() { - session?.logout() + adminSession?.logout() } @Synchronized - private Node addAuditRecordNode() { - def auditNode = session.getNode(AUDIT_PATH) - + private Node addAuditRecordNode(Session session) { def date = Calendar.instance + def year = date.format(DATE_FORMAT_YEAR) + def month = date.format(DATE_FORMAT_MONTH) + def day = date.format(DATE_FORMAT_DAY) - def yearNode = auditNode.getOrAddNode(date.format(DATE_FORMAT_YEAR)) as Node - def monthNode = yearNode.getOrAddNode(date.format(DATE_FORMAT_MONTH)) as Node - def dayNode = monthNode.getOrAddNode(date.format(DATE_FORMAT_DAY)) as Node - - def auditRecordNode = JcrUtil.createUniqueNode(dayNode, AUDIT_RECORD_NODE_PREFIX, NT_UNSTRUCTURED, session) + def auditRecordParentNode = JcrUtil.createPath("$AUDIT_PATH/${session.userID}/$year/$month/$day", + NT_UNSTRUCTURED, adminSession) + def auditRecordNode = JcrUtil.createUniqueNode(auditRecordParentNode, AUDIT_RECORD_NODE_PREFIX, NT_UNSTRUCTURED, + adminSession) auditRecordNode.addMixin(MIX_CREATED) @@ -206,14 +211,14 @@ class DefaultAuditService implements AuditService { } private void checkAuditNode() { - def contentNode = session.getNode(PATH_CONSOLE_ROOT).getNode(JCR_CONTENT) + def contentNode = adminSession.getNode(PATH_CONSOLE_ROOT).getNode(JCR_CONTENT) if (!contentNode.hasNode(AUDIT_NODE_NAME)) { LOG.info("audit node does not exist, adding") contentNode.addNode(AUDIT_NODE_NAME) - session.save() + adminSession.save() } } } diff --git a/src/main/groovy/com/icfolson/aem/groovy/console/configuration/ConfigurationService.groovy b/src/main/groovy/com/icfolson/aem/groovy/console/configuration/ConfigurationService.groovy new file mode 100644 index 00000000..6afec493 --- /dev/null +++ b/src/main/groovy/com/icfolson/aem/groovy/console/configuration/ConfigurationService.groovy @@ -0,0 +1,16 @@ +package com.icfolson.aem.groovy.console.configuration + +import org.apache.sling.api.SlingHttpServletRequest + +interface ConfigurationService { + + boolean hasPermission(SlingHttpServletRequest request) + + String getConsoleHref() + + Set getEmailRecipients() + + boolean isAuditDisabled() + + boolean isEmailEnabled() +} \ No newline at end of file diff --git a/src/main/groovy/com/citytechinc/aem/groovy/console/configuration/impl/DefaultConfigurationService.groovy b/src/main/groovy/com/icfolson/aem/groovy/console/configuration/impl/DefaultConfigurationService.groovy similarity index 67% rename from src/main/groovy/com/citytechinc/aem/groovy/console/configuration/impl/DefaultConfigurationService.groovy rename to src/main/groovy/com/icfolson/aem/groovy/console/configuration/impl/DefaultConfigurationService.groovy index 4cabc4aa..bc96376f 100755 --- a/src/main/groovy/com/citytechinc/aem/groovy/console/configuration/impl/DefaultConfigurationService.groovy +++ b/src/main/groovy/com/icfolson/aem/groovy/console/configuration/impl/DefaultConfigurationService.groovy @@ -1,13 +1,19 @@ -package com.citytechinc.aem.groovy.console.configuration.impl +package com.icfolson.aem.groovy.console.configuration.impl -import com.citytechinc.aem.groovy.console.configuration.ConfigurationService +import com.icfolson.aem.groovy.console.configuration.ConfigurationService import groovy.transform.Synchronized import groovy.util.logging.Slf4j import org.apache.felix.scr.annotations.Activate import org.apache.felix.scr.annotations.Component +import org.apache.felix.scr.annotations.Deactivate import org.apache.felix.scr.annotations.Modified import org.apache.felix.scr.annotations.Property +import org.apache.felix.scr.annotations.Reference import org.apache.felix.scr.annotations.Service +import org.apache.jackrabbit.api.security.user.UserManager +import org.apache.sling.api.SlingHttpServletRequest +import org.apache.sling.api.resource.ResourceResolver +import org.apache.sling.api.resource.ResourceResolverFactory @Service(ConfigurationService) @Component(immediate = true, metatype = true, label = "Groovy Console Configuration Service") @@ -40,6 +46,11 @@ class DefaultConfigurationService implements ConfigurationService { boolValue = false) private static final String AUDIT_DISABLED = "audit.disabled" + @Reference + private ResourceResolverFactory resourceResolverFactory + + private ResourceResolver resourceResolver + boolean emailEnabled Set emailRecipients @@ -50,12 +61,30 @@ class DefaultConfigurationService implements ConfigurationService { boolean auditDisabled + @Override + boolean hasPermission(SlingHttpServletRequest request) { + def user = resourceResolver.adaptTo(UserManager).getAuthorizable(request.userPrincipal) + + def memberOfGroupIds = user.memberOf()*.ID + + LOG.debug("member of group IDs = {}, allowed group IDs = {}", memberOfGroupIds, allowedGroups) + + allowedGroups ? memberOfGroupIds.intersect(allowedGroups) : true + } + @Override String getConsoleHref() { vanityPathEnabled ? VANITY_PATH : DEFAULT_PATH } @Activate + @SuppressWarnings("deprecated") + void activate(Map properties) { + resourceResolver = resourceResolverFactory.getAdministrativeResourceResolver(null) + + modified(properties) + } + @Modified @Synchronized void modified(Map properties) { @@ -65,4 +94,9 @@ class DefaultConfigurationService implements ConfigurationService { vanityPathEnabled = properties.get(VANITY_PATH_ENABLED) ?: false auditDisabled = properties.get(AUDIT_DISABLED) ?: false } + + @Deactivate + void deactivate() { + resourceResolver?.close() + } } diff --git a/src/main/groovy/com/citytechinc/aem/groovy/console/constants/GroovyConsoleConstants.groovy b/src/main/groovy/com/icfolson/aem/groovy/console/constants/GroovyConsoleConstants.groovy similarity index 91% rename from src/main/groovy/com/citytechinc/aem/groovy/console/constants/GroovyConsoleConstants.groovy rename to src/main/groovy/com/icfolson/aem/groovy/console/constants/GroovyConsoleConstants.groovy index 0b9a3aaf..0939501f 100644 --- a/src/main/groovy/com/citytechinc/aem/groovy/console/constants/GroovyConsoleConstants.groovy +++ b/src/main/groovy/com/icfolson/aem/groovy/console/constants/GroovyConsoleConstants.groovy @@ -1,4 +1,4 @@ -package com.citytechinc.aem.groovy.console.constants +package com.icfolson.aem.groovy.console.constants import static com.day.cq.commons.jcr.JcrConstants.JCR_CONTENT diff --git a/src/main/groovy/com/citytechinc/aem/groovy/console/extension/ExtensionService.groovy b/src/main/groovy/com/icfolson/aem/groovy/console/extension/ExtensionService.groovy similarity index 73% rename from src/main/groovy/com/citytechinc/aem/groovy/console/extension/ExtensionService.groovy rename to src/main/groovy/com/icfolson/aem/groovy/console/extension/ExtensionService.groovy index 40a2a4a0..7dc55203 100644 --- a/src/main/groovy/com/citytechinc/aem/groovy/console/extension/ExtensionService.groovy +++ b/src/main/groovy/com/icfolson/aem/groovy/console/extension/ExtensionService.groovy @@ -1,7 +1,7 @@ -package com.citytechinc.aem.groovy.console.extension +package com.icfolson.aem.groovy.console.extension -import com.citytechinc.aem.groovy.console.api.BindingExtensionProvider -import com.citytechinc.aem.groovy.console.api.StarImportExtensionProvider +import com.icfolson.aem.groovy.console.api.BindingExtensionProvider +import com.icfolson.aem.groovy.console.api.StarImportExtensionProvider import org.apache.sling.api.SlingHttpServletRequest /** diff --git a/src/main/groovy/com/citytechinc/aem/groovy/console/extension/impl/DefaultBindingExtensionProvider.groovy b/src/main/groovy/com/icfolson/aem/groovy/console/extension/impl/DefaultBindingExtensionProvider.groovy similarity index 57% rename from src/main/groovy/com/citytechinc/aem/groovy/console/extension/impl/DefaultBindingExtensionProvider.groovy rename to src/main/groovy/com/icfolson/aem/groovy/console/extension/impl/DefaultBindingExtensionProvider.groovy index f83e7aa1..01ff420d 100644 --- a/src/main/groovy/com/citytechinc/aem/groovy/console/extension/impl/DefaultBindingExtensionProvider.groovy +++ b/src/main/groovy/com/icfolson/aem/groovy/console/extension/impl/DefaultBindingExtensionProvider.groovy @@ -1,10 +1,10 @@ -package com.citytechinc.aem.groovy.console.extension.impl +package com.icfolson.aem.groovy.console.extension.impl -import com.citytechinc.aem.groovy.extension.builders.NodeBuilder -import com.citytechinc.aem.groovy.extension.builders.PageBuilder -import com.citytechinc.aem.groovy.console.api.BindingExtensionProvider import com.day.cq.search.QueryBuilder import com.day.cq.wcm.api.PageManager +import com.icfolson.aem.groovy.console.api.BindingExtensionProvider +import com.icfolson.aem.groovy.extension.builders.NodeBuilder +import com.icfolson.aem.groovy.extension.builders.PageBuilder import org.apache.felix.scr.annotations.Activate import org.apache.felix.scr.annotations.Component import org.apache.felix.scr.annotations.Reference @@ -29,19 +29,17 @@ class DefaultBindingExtensionProvider implements BindingExtensionProvider { def resourceResolver = request.resourceResolver def session = resourceResolver.adaptTo(Session) - def map = [ - log : LoggerFactory.getLogger("groovyconsole"), - session : session, - slingRequest : request, - pageManager : resourceResolver.adaptTo(PageManager), + new Binding([ + log: LoggerFactory.getLogger("groovyconsole"), + session: session, + slingRequest: request, + pageManager: resourceResolver.adaptTo(PageManager), resourceResolver: resourceResolver, - queryBuilder : queryBuilder, - nodeBuilder : new NodeBuilder(session), - pageBuilder : new PageBuilder(session), - bundleContext : bundleContext - ] - - new Binding(map) + queryBuilder: queryBuilder, + nodeBuilder: new NodeBuilder(session), + pageBuilder: new PageBuilder(session), + bundleContext: bundleContext + ]) } @Activate diff --git a/src/main/groovy/com/citytechinc/aem/groovy/console/extension/impl/DefaultExtensionService.groovy b/src/main/groovy/com/icfolson/aem/groovy/console/extension/impl/DefaultExtensionService.groovy similarity index 82% rename from src/main/groovy/com/citytechinc/aem/groovy/console/extension/impl/DefaultExtensionService.groovy rename to src/main/groovy/com/icfolson/aem/groovy/console/extension/impl/DefaultExtensionService.groovy index 440ea092..35d9a5c9 100644 --- a/src/main/groovy/com/citytechinc/aem/groovy/console/extension/impl/DefaultExtensionService.groovy +++ b/src/main/groovy/com/icfolson/aem/groovy/console/extension/impl/DefaultExtensionService.groovy @@ -1,9 +1,9 @@ -package com.citytechinc.aem.groovy.console.extension.impl +package com.icfolson.aem.groovy.console.extension.impl -import com.citytechinc.aem.groovy.console.api.BindingExtensionProvider -import com.citytechinc.aem.groovy.console.api.ScriptMetaClassExtensionProvider -import com.citytechinc.aem.groovy.console.api.StarImportExtensionProvider -import com.citytechinc.aem.groovy.console.extension.ExtensionService +import com.icfolson.aem.groovy.console.api.BindingExtensionProvider +import com.icfolson.aem.groovy.console.api.ScriptMetaClassExtensionProvider +import com.icfolson.aem.groovy.console.api.StarImportExtensionProvider +import com.icfolson.aem.groovy.console.extension.ExtensionService import groovy.transform.Synchronized import groovy.util.logging.Slf4j import org.apache.felix.scr.annotations.Component @@ -46,11 +46,11 @@ class DefaultExtensionService implements ExtensionService { binding.variables.each { key, value -> if (bindings[key]) { - LOG.warn("binding variable {} is already bound to value {}, cannot assign value = {}", key, + LOG.info("binding variable {} is currently bound to value {}, overriding with value = {}", key, bindings[key], value) - } else { - bindings[key] = value } + + bindings[key] = value } } @@ -80,14 +80,14 @@ class DefaultExtensionService implements ExtensionService { void bindStarImportExtensionProvider(StarImportExtensionProvider extension) { starImportExtensionProviders.add(extension) - LOG.info("added star import extension = {}", extension.class.name) + LOG.info("added star import extension = {} with imports = {}", extension.class.name, extension.starImports) } @Synchronized void unbindStarImportExtensionProvider(StarImportExtensionProvider extension) { starImportExtensionProviders.remove(extension) - LOG.info("removed star import extension = {}", extension.class.name) + LOG.info("removed star import extension = {} with imports = {}", extension.class.name, extension.starImports) } @Synchronized diff --git a/src/main/groovy/com/citytechinc/aem/groovy/console/extension/impl/DefaultScriptMetaClassExtensionProvider.groovy b/src/main/groovy/com/icfolson/aem/groovy/console/extension/impl/DefaultScriptMetaClassExtensionProvider.groovy similarity index 83% rename from src/main/groovy/com/citytechinc/aem/groovy/console/extension/impl/DefaultScriptMetaClassExtensionProvider.groovy rename to src/main/groovy/com/icfolson/aem/groovy/console/extension/impl/DefaultScriptMetaClassExtensionProvider.groovy index 88d43eac..dcbaadee 100755 --- a/src/main/groovy/com/citytechinc/aem/groovy/console/extension/impl/DefaultScriptMetaClassExtensionProvider.groovy +++ b/src/main/groovy/com/icfolson/aem/groovy/console/extension/impl/DefaultScriptMetaClassExtensionProvider.groovy @@ -1,14 +1,13 @@ -package com.citytechinc.aem.groovy.console.extension.impl +package com.icfolson.aem.groovy.console.extension.impl -import com.citytechinc.aem.groovy.console.api.ScriptMetaClassExtensionProvider -import com.citytechinc.aem.groovy.console.table.Table import com.day.cq.replication.ReplicationActionType import com.day.cq.replication.ReplicationOptions import com.day.cq.replication.Replicator import com.day.cq.search.PredicateGroup import com.day.cq.search.QueryBuilder import com.day.cq.wcm.api.PageManager -import org.apache.felix.scr.ScrService +import com.icfolson.aem.groovy.console.api.ScriptMetaClassExtensionProvider +import com.icfolson.aem.groovy.console.table.Table import org.apache.felix.scr.annotations.Activate import org.apache.felix.scr.annotations.Component import org.apache.felix.scr.annotations.Reference @@ -26,9 +25,6 @@ class DefaultScriptMetaClassExtensionProvider implements ScriptMetaClassExtensio @Reference Replicator replicator - @Reference - ScrService scrService - @Reference QueryBuilder queryBuilder @@ -120,25 +116,6 @@ class DefaultScriptMetaClassExtensionProvider implements ScriptMetaClassExtensio replicator.replicate(session, ReplicationActionType.DEACTIVATE, path, options) } - delegate.doWhileDisabled = { String componentClassName, Closure closure -> - def component = scrService.components.find { it.className == componentClassName } - def result = null - - if (component) { - component.disable() - - try { - result = closure() - } finally { - component.enable() - } - } else { - result = closure() - } - - result - } - delegate.createQuery { Map predicates -> queryBuilder.createQuery(PredicateGroup.create(predicates), session) } diff --git a/src/main/groovy/com/citytechinc/aem/groovy/console/extension/impl/DefaultStarImportExtensionProvider.groovy b/src/main/groovy/com/icfolson/aem/groovy/console/extension/impl/DefaultStarImportExtensionProvider.groovy similarity index 81% rename from src/main/groovy/com/citytechinc/aem/groovy/console/extension/impl/DefaultStarImportExtensionProvider.groovy rename to src/main/groovy/com/icfolson/aem/groovy/console/extension/impl/DefaultStarImportExtensionProvider.groovy index d4bfb952..8b3ac644 100644 --- a/src/main/groovy/com/citytechinc/aem/groovy/console/extension/impl/DefaultStarImportExtensionProvider.groovy +++ b/src/main/groovy/com/icfolson/aem/groovy/console/extension/impl/DefaultStarImportExtensionProvider.groovy @@ -1,6 +1,6 @@ -package com.citytechinc.aem.groovy.console.extension.impl +package com.icfolson.aem.groovy.console.extension.impl -import com.citytechinc.aem.groovy.console.api.StarImportExtensionProvider +import com.icfolson.aem.groovy.console.api.StarImportExtensionProvider import org.apache.felix.scr.annotations.Component import org.apache.felix.scr.annotations.Service diff --git a/src/main/groovy/com/citytechinc/aem/groovy/console/impl/DefaultGroovyConsoleService.groovy b/src/main/groovy/com/icfolson/aem/groovy/console/impl/DefaultGroovyConsoleService.groovy similarity index 69% rename from src/main/groovy/com/citytechinc/aem/groovy/console/impl/DefaultGroovyConsoleService.groovy rename to src/main/groovy/com/icfolson/aem/groovy/console/impl/DefaultGroovyConsoleService.groovy index 5ff12d47..a2eb8179 100755 --- a/src/main/groovy/com/citytechinc/aem/groovy/console/impl/DefaultGroovyConsoleService.groovy +++ b/src/main/groovy/com/icfolson/aem/groovy/console/impl/DefaultGroovyConsoleService.groovy @@ -1,13 +1,14 @@ -package com.citytechinc.aem.groovy.console.impl - -import com.citytechinc.aem.groovy.console.GroovyConsoleService -import com.citytechinc.aem.groovy.console.audit.AuditService -import com.citytechinc.aem.groovy.console.configuration.ConfigurationService -import com.citytechinc.aem.groovy.console.extension.ExtensionService -import com.citytechinc.aem.groovy.console.notification.NotificationService -import com.citytechinc.aem.groovy.console.response.RunScriptResponse -import com.citytechinc.aem.groovy.console.response.SaveScriptResponse +package com.icfolson.aem.groovy.console.impl + import com.day.cq.commons.jcr.JcrConstants +import com.day.cq.commons.jcr.JcrUtil +import com.icfolson.aem.groovy.console.GroovyConsoleService +import com.icfolson.aem.groovy.console.audit.AuditService +import com.icfolson.aem.groovy.console.configuration.ConfigurationService +import com.icfolson.aem.groovy.console.extension.ExtensionService +import com.icfolson.aem.groovy.console.notification.NotificationService +import com.icfolson.aem.groovy.console.response.RunScriptResponse +import com.icfolson.aem.groovy.console.response.SaveScriptResponse import groovy.transform.Synchronized import groovy.util.logging.Slf4j import org.apache.commons.lang3.CharEncoding @@ -26,8 +27,8 @@ import javax.jcr.Node import javax.jcr.Session import java.util.concurrent.CopyOnWriteArrayList -import static com.citytechinc.aem.groovy.console.constants.GroovyConsoleConstants.EXTENSION_GROOVY -import static com.citytechinc.aem.groovy.console.constants.GroovyConsoleConstants.PATH_CONSOLE_ROOT +import static com.icfolson.aem.groovy.console.constants.GroovyConsoleConstants.EXTENSION_GROOVY +import static com.icfolson.aem.groovy.console.constants.GroovyConsoleConstants.PATH_CONSOLE_ROOT import static org.codehaus.groovy.control.customizers.builder.CompilerCustomizationBuilder.withConfig @Service(GroovyConsoleService) @@ -57,20 +58,68 @@ class DefaultGroovyConsoleService implements GroovyConsoleService { } @Reference - ConfigurationService configurationService + private ConfigurationService configurationService @Reference(cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE, referenceInterface = NotificationService, policy = ReferencePolicy.DYNAMIC) - List notificationServices = new CopyOnWriteArrayList<>() + private List notificationServices = new CopyOnWriteArrayList<>() @Reference - AuditService auditService + private AuditService auditService @Reference - ExtensionService extensionService + private ExtensionService extensionService @Override RunScriptResponse runScript(SlingHttpServletRequest request) { + def scriptContent = request.getRequestParameter(PARAMETER_SCRIPT)?.getString(CharEncoding.UTF_8) + + runScriptInternal(request, scriptContent) + } + + @Override + RunScriptResponse runScriptFile(SlingHttpServletRequest request) { + runScriptInternal(request, request.inputStream.text) + } + + @Override + @Synchronized + SaveScriptResponse saveScript(SlingHttpServletRequest request) { + def session = request.resourceResolver.adaptTo(Session) + def folderNode = JcrUtil.createPath("$PATH_CONSOLE_ROOT/$RELATIVE_PATH_SCRIPT_FOLDER", JcrConstants.NT_FOLDER, + session) + + def name = request.getParameter(PARAMETER_FILE_NAME) + def fileName = name.endsWith(EXTENSION_GROOVY) ? name : "$name$EXTENSION_GROOVY" + + if (folderNode.hasNode(fileName)) { + folderNode.getNode(fileName).remove() + } + + def script = request.getParameter(PARAMETER_SCRIPT) + + saveFile(session, folderNode, script, fileName, new Date(), "application/octet-stream") + + new SaveScriptResponse(fileName) + } + + @Synchronized + void bindNotificationService(NotificationService notificationService) { + notificationServices.add(notificationService) + + LOG.info("added notification service = {}", notificationService.class.name) + } + + @Synchronized + void unbindNotificationServices(NotificationService notificationService) { + notificationServices.remove(notificationService) + + LOG.info("removed notification service = {}", notificationService.class.name) + } + + // internals + + private RunScriptResponse runScriptInternal(SlingHttpServletRequest request, String scriptContent) { def stream = new ByteArrayOutputStream() def binding = extensionService.getBinding(request) @@ -80,15 +129,14 @@ class DefaultGroovyConsoleService implements GroovyConsoleService { def session = request.resourceResolver.adaptTo(Session) def configuration = createConfiguration() def shell = new GroovyShell(binding, configuration) - def scriptContent = request.getRequestParameter(PARAMETER_SCRIPT)?.getString(CharEncoding.UTF_8) def response = null try { def script = shell.parse(scriptContent) - extensionService.getScriptMetaClasses(request).each { - script.metaClass(it) + extensionService.getScriptMetaClasses(request).each { meta -> + script.metaClass(meta) } def result = null @@ -120,47 +168,9 @@ class DefaultGroovyConsoleService implements GroovyConsoleService { response } - @Override - @Synchronized - SaveScriptResponse saveScript(SlingHttpServletRequest request) { - def name = request.getParameter(PARAMETER_FILE_NAME) - def script = request.getParameter(PARAMETER_SCRIPT) - - def session = request.resourceResolver.adaptTo(Session) - - def folderNode = session.getNode(PATH_CONSOLE_ROOT).getOrAddNode(RELATIVE_PATH_SCRIPT_FOLDER, - JcrConstants.NT_FOLDER) as Node - - def fileName = name.endsWith(EXTENSION_GROOVY) ? name : "$name$EXTENSION_GROOVY" - - folderNode.removeNode(fileName) - - getScriptBinary(session, script).withBinary { Binary binary -> - saveFile(session, folderNode, fileName, new Date(), "application/octet-stream", binary) - } - - new SaveScriptResponse(fileName) - } - - @Synchronized - void bindNotificationService(NotificationService notificationService) { - notificationServices.add(notificationService) - - LOG.info("added notification service = {}", notificationService.class.name) - } - - @Synchronized - void unbindNotificationServices(NotificationService notificationService) { - notificationServices.remove(notificationService) - - LOG.info("removed notification service = {}", notificationService.class.name) - } - - // internals - private void auditAndNotify(Session session, RunScriptResponse response) { if (!configurationService.auditDisabled) { - auditService.createAuditRecord(response) + auditService.createAuditRecord(session, response) } notificationServices.each { notificationService -> @@ -168,7 +178,7 @@ class DefaultGroovyConsoleService implements GroovyConsoleService { } } - private def createConfiguration() { + private CompilerConfiguration createConfiguration() { def configuration = new CompilerConfiguration() withConfig(configuration) { @@ -178,28 +188,25 @@ class DefaultGroovyConsoleService implements GroovyConsoleService { } } - private static def getScriptBinary(Session session, String script) { - def binary = null + private void saveFile(Session session, Node folderNode, String script, String fileName, Date date, + String mimeType) { + def fileNode = folderNode.addNode(Text.escapeIllegalJcrChars(fileName), JcrConstants.NT_FILE) + def resourceNode = fileNode.addNode(JcrConstants.JCR_CONTENT, JcrConstants.NT_RESOURCE) + + resourceNode.setProperty(JcrConstants.JCR_MIMETYPE, mimeType) + resourceNode.setProperty(JcrConstants.JCR_ENCODING, CharEncoding.UTF_8) + + Binary binary = null new ByteArrayInputStream(script.getBytes(CharEncoding.UTF_8)).withStream { stream -> binary = session.valueFactory.createBinary(stream) } - binary - } - - private static void saveFile(Session session, Node folderNode, String fileName, Date date, String mimeType, - Binary binary) { - def fileNode = folderNode.addNode(Text.escapeIllegalJcrChars(fileName), JcrConstants.NT_FILE) - - def resourceNode = fileNode.addNode(JcrConstants.JCR_CONTENT, JcrConstants.NT_RESOURCE) - - resourceNode.set(JcrConstants.JCR_MIMETYPE, mimeType) - resourceNode.set(JcrConstants.JCR_ENCODING, CharEncoding.UTF_8) - resourceNode.set(JcrConstants.JCR_DATA, binary) - resourceNode.set(JcrConstants.JCR_LASTMODIFIED, date.time) - resourceNode.set(JcrConstants.JCR_LAST_MODIFIED_BY, session.userID) + resourceNode.setProperty(JcrConstants.JCR_DATA, binary) + resourceNode.setProperty(JcrConstants.JCR_LASTMODIFIED, date.time) + resourceNode.setProperty(JcrConstants.JCR_LAST_MODIFIED_BY, session.userID) session.save() + binary.dispose() } } diff --git a/src/main/groovy/com/citytechinc/aem/groovy/console/notification/NotificationService.groovy b/src/main/groovy/com/icfolson/aem/groovy/console/notification/NotificationService.groovy similarity index 77% rename from src/main/groovy/com/citytechinc/aem/groovy/console/notification/NotificationService.groovy rename to src/main/groovy/com/icfolson/aem/groovy/console/notification/NotificationService.groovy index 1c736052..21fc5577 100644 --- a/src/main/groovy/com/citytechinc/aem/groovy/console/notification/NotificationService.groovy +++ b/src/main/groovy/com/icfolson/aem/groovy/console/notification/NotificationService.groovy @@ -1,6 +1,6 @@ -package com.citytechinc.aem.groovy.console.notification +package com.icfolson.aem.groovy.console.notification -import com.citytechinc.aem.groovy.console.response.RunScriptResponse +import com.icfolson.aem.groovy.console.response.RunScriptResponse import javax.jcr.Session diff --git a/src/main/groovy/com/citytechinc/aem/groovy/console/notification/impl/EmailNotificationService.groovy b/src/main/groovy/com/icfolson/aem/groovy/console/notification/impl/EmailNotificationService.groovy similarity index 85% rename from src/main/groovy/com/citytechinc/aem/groovy/console/notification/impl/EmailNotificationService.groovy rename to src/main/groovy/com/icfolson/aem/groovy/console/notification/impl/EmailNotificationService.groovy index 2f8f49be..4e5d461c 100644 --- a/src/main/groovy/com/citytechinc/aem/groovy/console/notification/impl/EmailNotificationService.groovy +++ b/src/main/groovy/com/icfolson/aem/groovy/console/notification/impl/EmailNotificationService.groovy @@ -1,10 +1,9 @@ -package com.citytechinc.aem.groovy.console.notification.impl - -import com.citytechinc.aem.groovy.console.configuration.ConfigurationService -import com.citytechinc.aem.groovy.console.notification.NotificationService -import com.citytechinc.aem.groovy.console.response.RunScriptResponse +package com.icfolson.aem.groovy.console.notification.impl import com.day.cq.mailer.MailService +import com.icfolson.aem.groovy.console.configuration.ConfigurationService +import com.icfolson.aem.groovy.console.notification.NotificationService +import com.icfolson.aem.groovy.console.response.RunScriptResponse import groovy.text.GStringTemplateEngine import groovy.util.logging.Slf4j import org.apache.commons.lang3.CharEncoding @@ -79,17 +78,17 @@ class EmailNotificationService implements NotificationService { private static def createBinding(Session session, RunScriptResponse response) { def binding = [ - username : session.userID, + username: session.userID, timestamp: new Date().format(FORMAT_TIMESTAMP), - script : response.script + script: response.script ] if (response.exceptionStackTrace) { binding.stackTrace = response.exceptionStackTrace } else { binding.putAll([ - result : response.result, - output : response.output, + result: response.result, + output: response.output, runningTime: response.runningTime ]) } diff --git a/src/main/groovy/com/citytechinc/aem/groovy/console/response/RunScriptResponse.groovy b/src/main/groovy/com/icfolson/aem/groovy/console/response/RunScriptResponse.groovy similarity index 61% rename from src/main/groovy/com/citytechinc/aem/groovy/console/response/RunScriptResponse.groovy rename to src/main/groovy/com/icfolson/aem/groovy/console/response/RunScriptResponse.groovy index 05672d5b..adadee4f 100644 --- a/src/main/groovy/com/citytechinc/aem/groovy/console/response/RunScriptResponse.groovy +++ b/src/main/groovy/com/icfolson/aem/groovy/console/response/RunScriptResponse.groovy @@ -1,15 +1,16 @@ -package com.citytechinc.aem.groovy.console.response +package com.icfolson.aem.groovy.console.response -import com.citytechinc.aem.groovy.console.audit.AuditRecord -import com.citytechinc.aem.groovy.console.table.Table +import com.icfolson.aem.groovy.console.audit.AuditRecord +import com.icfolson.aem.groovy.console.table.Table import groovy.json.JsonBuilder import groovy.transform.Immutable import org.apache.commons.lang3.exception.ExceptionUtils +import org.apache.sling.jcr.resource.JcrPropertyMap import javax.jcr.Node -import static com.citytechinc.aem.groovy.console.audit.AuditRecord.PROPERTY_EXCEPTION_STACK_TRACE -import static com.citytechinc.aem.groovy.console.audit.AuditRecord.PROPERTY_SCRIPT +import static com.icfolson.aem.groovy.console.audit.AuditRecord.PROPERTY_EXCEPTION_STACK_TRACE +import static com.icfolson.aem.groovy.console.audit.AuditRecord.PROPERTY_SCRIPT @Immutable class RunScriptResponse { @@ -33,17 +34,19 @@ class RunScriptResponse { } static RunScriptResponse fromAuditRecordNode(Node node) { - def script = node.get(PROPERTY_SCRIPT) as String - def exceptionStackTrace = node.get(PROPERTY_EXCEPTION_STACK_TRACE) ?: "" + def properties = new JcrPropertyMap(node) + + def script = properties.get(PROPERTY_SCRIPT, "") + def exceptionStackTrace = properties.get(PROPERTY_EXCEPTION_STACK_TRACE, "") def response if (exceptionStackTrace) { response = new RunScriptResponse(script, "", "", exceptionStackTrace, "") } else { - def result = node.get(AuditRecord.PROPERTY_RESULT) ?: "" - def output = node.get(AuditRecord.PROPERTY_OUTPUT) ?: "" - def runningTime = node.get(AuditRecord.PROPERTY_RUNNING_TIME) ?: "" + def result = properties.get(AuditRecord.PROPERTY_RESULT, "") + def output = properties.get(AuditRecord.PROPERTY_OUTPUT, "") + def runningTime = properties.get(AuditRecord.PROPERTY_RUNNING_TIME, "") response = new RunScriptResponse(script, result, output, "", runningTime) } diff --git a/src/main/groovy/com/citytechinc/aem/groovy/console/response/SaveScriptResponse.groovy b/src/main/groovy/com/icfolson/aem/groovy/console/response/SaveScriptResponse.groovy similarity index 65% rename from src/main/groovy/com/citytechinc/aem/groovy/console/response/SaveScriptResponse.groovy rename to src/main/groovy/com/icfolson/aem/groovy/console/response/SaveScriptResponse.groovy index 91020ed9..297e5332 100644 --- a/src/main/groovy/com/citytechinc/aem/groovy/console/response/SaveScriptResponse.groovy +++ b/src/main/groovy/com/icfolson/aem/groovy/console/response/SaveScriptResponse.groovy @@ -1,4 +1,4 @@ -package com.citytechinc.aem.groovy.console.response +package com.icfolson.aem.groovy.console.response import groovy.transform.Immutable diff --git a/src/main/groovy/com/citytechinc/aem/groovy/console/servlets/AbstractJsonResponseServlet.groovy b/src/main/groovy/com/icfolson/aem/groovy/console/servlets/AbstractJsonResponseServlet.groovy similarity index 74% rename from src/main/groovy/com/citytechinc/aem/groovy/console/servlets/AbstractJsonResponseServlet.groovy rename to src/main/groovy/com/icfolson/aem/groovy/console/servlets/AbstractJsonResponseServlet.groovy index 6bbb3573..c853f419 100644 --- a/src/main/groovy/com/citytechinc/aem/groovy/console/servlets/AbstractJsonResponseServlet.groovy +++ b/src/main/groovy/com/icfolson/aem/groovy/console/servlets/AbstractJsonResponseServlet.groovy @@ -1,4 +1,4 @@ -package com.citytechinc.aem.groovy.console.servlets +package com.icfolson.aem.groovy.console.servlets import groovy.json.JsonBuilder import org.apache.sling.api.SlingHttpServletResponse @@ -6,7 +6,7 @@ import org.apache.sling.api.servlets.SlingAllMethodsServlet abstract class AbstractJsonResponseServlet extends SlingAllMethodsServlet { - static void writeJsonResponse(SlingHttpServletResponse response, json) { + void writeJsonResponse(SlingHttpServletResponse response, json) { response.contentType = "application/json" response.characterEncoding = "UTF-8" diff --git a/src/main/groovy/com/citytechinc/aem/groovy/console/servlets/AuditServlet.groovy b/src/main/groovy/com/icfolson/aem/groovy/console/servlets/AuditServlet.groovy similarity index 52% rename from src/main/groovy/com/citytechinc/aem/groovy/console/servlets/AuditServlet.groovy rename to src/main/groovy/com/icfolson/aem/groovy/console/servlets/AuditServlet.groovy index 3976b69a..72addf97 100644 --- a/src/main/groovy/com/citytechinc/aem/groovy/console/servlets/AuditServlet.groovy +++ b/src/main/groovy/com/icfolson/aem/groovy/console/servlets/AuditServlet.groovy @@ -1,16 +1,16 @@ -package com.citytechinc.aem.groovy.console.servlets +package com.icfolson.aem.groovy.console.servlets -import com.citytechinc.aem.groovy.console.audit.AuditRecord -import com.citytechinc.aem.groovy.console.audit.AuditService -import com.citytechinc.aem.groovy.console.configuration.ConfigurationService +import com.icfolson.aem.groovy.console.audit.AuditRecord +import com.icfolson.aem.groovy.console.audit.AuditService +import com.icfolson.aem.groovy.console.configuration.ConfigurationService import org.apache.felix.scr.annotations.Reference import org.apache.felix.scr.annotations.sling.SlingServlet import org.apache.sling.api.SlingHttpServletRequest import org.apache.sling.api.SlingHttpServletResponse -import javax.servlet.ServletException +import javax.jcr.Session -import static com.citytechinc.aem.groovy.console.constants.GroovyConsoleConstants.PARAMETER_SCRIPT +import static com.icfolson.aem.groovy.console.constants.GroovyConsoleConstants.PARAMETER_SCRIPT @SlingServlet(paths = "/bin/groovyconsole/audit") class AuditServlet extends AbstractJsonResponseServlet { @@ -24,32 +24,32 @@ class AuditServlet extends AbstractJsonResponseServlet { private static final String DATE_FORMAT_DISPLAY = "yyyy-MM-dd HH:mm:ss" @Reference - AuditService auditService + private AuditService auditService @Reference - ConfigurationService configurationService + private ConfigurationService configurationService @Override - protected void doGet(SlingHttpServletRequest request, - SlingHttpServletResponse response) throws ServletException, IOException { + protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) { + def session = request.resourceResolver.adaptTo(Session) def script = request.getParameter(PARAMETER_SCRIPT) if (script) { - writeJsonResponse(response, auditService.getAuditRecord(script) ?: [:]) + writeJsonResponse(response, auditService.getAuditRecord(session, script) ?: [:]) } else { writeJsonResponse(response, loadAuditRecords(request)) } } @Override - protected void doDelete(SlingHttpServletRequest request, - SlingHttpServletResponse response) throws ServletException, IOException { + protected void doDelete(SlingHttpServletRequest request, SlingHttpServletResponse response) { + def session = request.resourceResolver.adaptTo(Session) def script = request.getParameter(PARAMETER_SCRIPT) if (script) { - auditService.deleteAuditRecord(script) + auditService.deleteAuditRecord(session, script) } else { - auditService.deleteAllAuditRecords() + auditService.deleteAllAuditRecords(session) } } @@ -63,12 +63,12 @@ class AuditServlet extends AbstractJsonResponseServlet { def lines = auditRecord.script.readLines() def map = [ - date : auditRecord.date.format(DATE_FORMAT_DISPLAY), + date: auditRecord.date.format(DATE_FORMAT_DISPLAY), scriptPreview: lines.first() + (lines.size() > 1 ? " [...]" : ""), - script : auditRecord.script, - exception : getException(auditRecord), - link : "$consoleHref?script=${auditRecord.relativePath}", - relativePath : auditRecord.relativePath + script: auditRecord.script, + exception: auditRecord.exception, + link: "$consoleHref?script=${auditRecord.relativePath}", + relativePath: auditRecord.relativePath ] data.add(map) @@ -78,40 +78,22 @@ class AuditServlet extends AbstractJsonResponseServlet { } private List getAuditRecords(SlingHttpServletRequest request) { + def session = request.resourceResolver.adaptTo(Session) + def startDateParameter = request.getParameter(PARAMETER_START_DATE) def endDateParameter = request.getParameter(PARAMETER_END_DATE) def auditRecords if (!startDateParameter || !endDateParameter) { - auditRecords = auditService.allAuditRecords + auditRecords = auditService.getAllAuditRecords(session) } else { def startDate = Date.parse(DATE_FORMAT, startDateParameter) def endDate = Date.parse(DATE_FORMAT, endDateParameter) - auditRecords = auditService.getAuditRecords(startDate.toCalendar(), endDate.toCalendar()) + auditRecords = auditService.getAuditRecords(session, startDate.toCalendar(), endDate.toCalendar()) } auditRecords.sort { a, b -> b.date.timeInMillis <=> a.date.timeInMillis } } - - private static def getException(AuditRecord auditRecord) { - def exceptionStackTrace = auditRecord.exceptionStackTrace - - def exception - - if (exceptionStackTrace) { - def firstLine = exceptionStackTrace.readLines().first() - - if (firstLine.contains(":")) { - exception = firstLine.substring(0, firstLine.indexOf(":")) - } else { - exception = firstLine - } - } else { - exception = "" - } - - exception - } } diff --git a/src/main/groovy/com/icfolson/aem/groovy/console/servlets/ScriptFilePostServlet.groovy b/src/main/groovy/com/icfolson/aem/groovy/console/servlets/ScriptFilePostServlet.groovy new file mode 100755 index 00000000..39c9bc8d --- /dev/null +++ b/src/main/groovy/com/icfolson/aem/groovy/console/servlets/ScriptFilePostServlet.groovy @@ -0,0 +1,32 @@ +package com.icfolson.aem.groovy.console.servlets + +import com.icfolson.aem.groovy.console.GroovyConsoleService +import com.icfolson.aem.groovy.console.configuration.ConfigurationService +import org.apache.felix.scr.annotations.Reference +import org.apache.felix.scr.annotations.sling.SlingServlet +import org.apache.sling.api.SlingHttpServletRequest +import org.apache.sling.api.SlingHttpServletResponse + +import javax.servlet.ServletException + +import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN + +@SlingServlet(paths = "/bin/groovyconsole/post/file") +class ScriptFilePostServlet extends AbstractJsonResponseServlet { + + @Reference + private ConfigurationService configurationService + + @Reference + private GroovyConsoleService consoleService + + @Override + protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws + ServletException, IOException { + if (configurationService.hasPermission(request)) { + writeJsonResponse(response, consoleService.runScriptFile(request)) + } else { + response.status = SC_FORBIDDEN + } + } +} diff --git a/src/main/groovy/com/icfolson/aem/groovy/console/servlets/ScriptPostServlet.groovy b/src/main/groovy/com/icfolson/aem/groovy/console/servlets/ScriptPostServlet.groovy new file mode 100755 index 00000000..dd120956 --- /dev/null +++ b/src/main/groovy/com/icfolson/aem/groovy/console/servlets/ScriptPostServlet.groovy @@ -0,0 +1,32 @@ +package com.icfolson.aem.groovy.console.servlets + +import com.icfolson.aem.groovy.console.GroovyConsoleService +import com.icfolson.aem.groovy.console.configuration.ConfigurationService +import org.apache.felix.scr.annotations.Reference +import org.apache.felix.scr.annotations.sling.SlingServlet +import org.apache.sling.api.SlingHttpServletRequest +import org.apache.sling.api.SlingHttpServletResponse + +import javax.servlet.ServletException + +import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN + +@SlingServlet(paths = "/bin/groovyconsole/post") +class ScriptPostServlet extends AbstractJsonResponseServlet { + + @Reference + private ConfigurationService configurationService + + @Reference + private GroovyConsoleService consoleService + + @Override + protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws + ServletException, IOException { + if (configurationService.hasPermission(request)) { + writeJsonResponse(response, consoleService.runScript(request)) + } else { + response.status = SC_FORBIDDEN + } + } +} diff --git a/src/main/groovy/com/citytechinc/aem/groovy/console/servlets/ScriptSavingServlet.groovy b/src/main/groovy/com/icfolson/aem/groovy/console/servlets/ScriptSavingServlet.groovy similarity index 79% rename from src/main/groovy/com/citytechinc/aem/groovy/console/servlets/ScriptSavingServlet.groovy rename to src/main/groovy/com/icfolson/aem/groovy/console/servlets/ScriptSavingServlet.groovy index 60d36bc7..6ff300eb 100644 --- a/src/main/groovy/com/citytechinc/aem/groovy/console/servlets/ScriptSavingServlet.groovy +++ b/src/main/groovy/com/icfolson/aem/groovy/console/servlets/ScriptSavingServlet.groovy @@ -1,6 +1,6 @@ -package com.citytechinc.aem.groovy.console.servlets +package com.icfolson.aem.groovy.console.servlets -import com.citytechinc.aem.groovy.console.GroovyConsoleService +import com.icfolson.aem.groovy.console.GroovyConsoleService import org.apache.felix.scr.annotations.Reference import org.apache.felix.scr.annotations.sling.SlingServlet import org.apache.sling.api.SlingHttpServletRequest @@ -12,7 +12,7 @@ import javax.servlet.ServletException class ScriptSavingServlet extends AbstractJsonResponseServlet { @Reference - GroovyConsoleService consoleService + private GroovyConsoleService consoleService @Override protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws diff --git a/src/main/groovy/com/citytechinc/aem/groovy/console/servlets/ServicesListServlet.groovy b/src/main/groovy/com/icfolson/aem/groovy/console/servlets/ServicesListServlet.groovy similarity index 58% rename from src/main/groovy/com/citytechinc/aem/groovy/console/servlets/ServicesListServlet.groovy rename to src/main/groovy/com/icfolson/aem/groovy/console/servlets/ServicesListServlet.groovy index bbaaf21c..abefdc25 100644 --- a/src/main/groovy/com/citytechinc/aem/groovy/console/servlets/ServicesListServlet.groovy +++ b/src/main/groovy/com/icfolson/aem/groovy/console/servlets/ServicesListServlet.groovy @@ -1,4 +1,4 @@ -package com.citytechinc.aem.groovy.console.servlets +package com.icfolson.aem.groovy.console.servlets import org.apache.commons.lang3.StringUtils import org.apache.felix.scr.annotations.Activate @@ -8,19 +8,21 @@ import org.apache.sling.api.SlingHttpServletResponse import org.apache.sling.api.adapter.AdapterFactory import org.apache.sling.api.resource.ResourceResolver import org.osgi.framework.BundleContext -import org.osgi.framework.Constants -import org.osgi.service.component.ComponentConstants import javax.servlet.ServletException +import static org.apache.sling.api.adapter.AdapterFactory.ADAPTABLE_CLASSES +import static org.apache.sling.api.adapter.AdapterFactory.ADAPTER_CLASSES +import static org.osgi.framework.Constants.OBJECTCLASS + @SlingServlet(paths = "/bin/groovyconsole/services") class ServicesListServlet extends AbstractJsonResponseServlet { - def bundleContext + private BundleContext bundleContext @Override - protected void doGet(final SlingHttpServletRequest request, final SlingHttpServletResponse - response) throws ServletException, IOException { + protected void doGet(SlingHttpServletRequest request, + SlingHttpServletResponse response) throws ServletException, IOException { writeJsonResponse(response, adaptersMap + servicesMap) } @@ -29,32 +31,41 @@ class ServicesListServlet extends AbstractJsonResponseServlet { this.bundleContext = bundleContext } - private def getAdaptersMap() { + private Map getAdaptersMap() { def adapters = [:] as TreeMap - def serviceReferences = bundleContext.getServiceReferences(AdapterFactory, null).findAll { serviceReference -> - serviceReference.getProperty(AdapterFactory.ADAPTABLE_CLASSES).contains(ResourceResolver.class.name) + def serviceReferences = bundleContext.getServiceReferences(AdapterFactory.name, null).findAll { serviceReference -> + def adaptableClasses = serviceReference.getProperty(ADAPTABLE_CLASSES) as String[] + + adaptableClasses.contains(ResourceResolver.name) } serviceReferences.each { serviceReference -> - serviceReference.getProperty(AdapterFactory.ADAPTER_CLASSES).each { String adapterClassName -> - adapters[adapterClassName] = getAdapterDeclaration(adapterClassName) + def adapterClasses = serviceReference.getProperty(ADAPTER_CLASSES) + + if (adapterClasses instanceof String[]) { + adapterClasses.each { String adapterClassName -> + adapters[adapterClassName] = getAdapterDeclaration(adapterClassName) + } + } else { + adapters[adapterClasses] = getAdapterDeclaration(adapterClasses as String) } } adapters } - private def getServicesMap() { + private Map getServicesMap() { def services = [:] as TreeMap - def allServices = [:] + + Map> allServices = [:] bundleContext.getAllServiceReferences(null, null).each { serviceReference -> - def name = serviceReference.getProperty(ComponentConstants.COMPONENT_NAME) - def objectClass = serviceReference.getProperty(Constants.OBJECTCLASS) + def name = serviceReference.getProperty("component.name") as String + def objectClass = serviceReference.getProperty(OBJECTCLASS) as String[] objectClass.each { className -> - def implementationClassNames = allServices[className] ?: [] + def implementationClassNames = allServices[className] as List ?: [] if (name) { implementationClassNames.add(name) @@ -64,7 +75,7 @@ class ServicesListServlet extends AbstractJsonResponseServlet { } } - allServices.each { String className, implementationClassNames -> + allServices.each { className, implementationClassNames -> services[className] = getServiceDeclaration(className, null) if (implementationClassNames.size() > 1) { @@ -77,20 +88,20 @@ class ServicesListServlet extends AbstractJsonResponseServlet { services } - private static def getAdapterDeclaration(String className) { + private static String getAdapterDeclaration(String className) { def simpleName = className.tokenize('.').last() def variableName = StringUtils.uncapitalize(simpleName) "def $variableName = resourceResolver.adaptTo($className)" } - private static def getServiceDeclaration(String className, implementationClassName) { + private static String getServiceDeclaration(String className, implementationClassName) { def simpleName = className.tokenize('.').last() def variableName = StringUtils.uncapitalize(simpleName) def declaration if (implementationClassName) { - def filter = "(${ComponentConstants.COMPONENT_NAME}=$implementationClassName)" + def filter = "(component.name=$implementationClassName)" declaration = "def $variableName = getServices(\"$className\", \"$filter\")[0]" } else { diff --git a/src/main/groovy/com/citytechinc/aem/groovy/console/table/Table.groovy b/src/main/groovy/com/icfolson/aem/groovy/console/table/Table.groovy similarity index 95% rename from src/main/groovy/com/citytechinc/aem/groovy/console/table/Table.groovy rename to src/main/groovy/com/icfolson/aem/groovy/console/table/Table.groovy index 63293310..a36784da 100644 --- a/src/main/groovy/com/citytechinc/aem/groovy/console/table/Table.groovy +++ b/src/main/groovy/com/icfolson/aem/groovy/console/table/Table.groovy @@ -1,4 +1,4 @@ -package com.citytechinc.aem.groovy.console.table +package com.icfolson.aem.groovy.console.table class Table { diff --git a/src/main/groovy/com/citytechinc/aem/groovy/console/tags/DefineObjectsTag.groovy b/src/main/groovy/com/icfolson/aem/groovy/console/tags/DefineObjectsTag.groovy similarity index 81% rename from src/main/groovy/com/citytechinc/aem/groovy/console/tags/DefineObjectsTag.groovy rename to src/main/groovy/com/icfolson/aem/groovy/console/tags/DefineObjectsTag.groovy index de48ae50..b92c59cc 100644 --- a/src/main/groovy/com/citytechinc/aem/groovy/console/tags/DefineObjectsTag.groovy +++ b/src/main/groovy/com/icfolson/aem/groovy/console/tags/DefineObjectsTag.groovy @@ -1,17 +1,18 @@ -package com.citytechinc.aem.groovy.console.tags +package com.icfolson.aem.groovy.console.tags -import com.citytechinc.aem.groovy.console.configuration.ConfigurationService -import com.citytechinc.aem.groovy.console.audit.AuditService import com.day.cq.wcm.api.WCMMode +import com.icfolson.aem.groovy.console.audit.AuditService +import com.icfolson.aem.groovy.console.configuration.ConfigurationService import groovy.json.JsonBuilder import org.apache.sling.api.SlingHttpServletRequest import org.apache.sling.api.scripting.SlingScriptHelper +import javax.jcr.Session import javax.servlet.jsp.JspException import javax.servlet.jsp.tagext.TagSupport -import static com.citytechinc.aem.groovy.console.constants.GroovyConsoleConstants.PARAMETER_SCRIPT import static com.day.cq.wcm.tags.DefineObjectsTag.DEFAULT_SLING_NAME +import static com.icfolson.aem.groovy.console.constants.GroovyConsoleConstants.PARAMETER_SCRIPT import static javax.servlet.jsp.PageContext.REQUEST_SCOPE import static org.apache.sling.scripting.jsp.taglib.DefineObjectsTag.DEFAULT_REQUEST_NAME @@ -43,7 +44,8 @@ class DefineObjectsTag extends TagSupport { def script = request.getParameter(PARAMETER_SCRIPT) if (script) { - def auditRecord = sling.getService(AuditService).getAuditRecord(script) + def auditRecord = sling.getService(AuditService).getAuditRecord( + request.resourceResolver.adaptTo(Session), script) if (auditRecord) { pageContext.setAttribute(AUDIT_RECORD, new JsonBuilder(auditRecord).toString(), REQUEST_SCOPE) diff --git a/src/main/resources/META-INF/groovyconsole.tld b/src/main/resources/META-INF/groovyconsole.tld index 5c243f0a..cd353f54 100644 --- a/src/main/resources/META-INF/groovyconsole.tld +++ b/src/main/resources/META-INF/groovyconsole.tld @@ -6,10 +6,10 @@ ${project.version} groovyConsole - http://www.citytechinc.com/taglibs/groovyconsole + http://www.icfolson.com/taglibs/groovyconsole defineObjects - com.citytechinc.aem.groovy.console.tags.DefineObjectsTag + com.icfolson.aem.groovy.console.tags.DefineObjectsTag \ No newline at end of file diff --git a/src/main/scripts/CreateOsgiConfigurations.groovy b/src/main/scripts/CreateOsgiConfigurations.groovy index 385878cb..c6c41075 100644 --- a/src/main/scripts/CreateOsgiConfigurations.groovy +++ b/src/main/scripts/CreateOsgiConfigurations.groovy @@ -2,8 +2,7 @@ import org.osgi.service.cm.ConfigurationAdmin def loggers = [ "com.day.cq.dam": "dam", - "com.citytechinc.aem.groovy.console": "groovyconsole", - "com.citytechinc.aem.bedrock": "bedrock" + "com.icfolson.aem.groovy.console": "groovyconsole" ] def admin = getService(ConfigurationAdmin) diff --git a/src/test/groovy/com/citytechinc/aem/groovy/console/services/impl/DefaultGroovyConsoleServiceSpec.groovy b/src/test/groovy/com/citytechinc/aem/groovy/console/services/impl/DefaultGroovyConsoleServiceSpec.groovy deleted file mode 100755 index aae7f3ea..00000000 --- a/src/test/groovy/com/citytechinc/aem/groovy/console/services/impl/DefaultGroovyConsoleServiceSpec.groovy +++ /dev/null @@ -1,151 +0,0 @@ -package com.citytechinc.aem.groovy.console.services.impl - -import com.citytechinc.aem.groovy.console.configuration.ConfigurationService - -import com.citytechinc.aem.groovy.console.audit.AuditService -import com.citytechinc.aem.groovy.console.extension.impl.DefaultBindingExtensionProvider -import com.citytechinc.aem.groovy.console.extension.impl.DefaultExtensionService -import com.citytechinc.aem.groovy.console.extension.impl.DefaultScriptMetaClassExtensionProvider -import com.citytechinc.aem.groovy.console.impl.DefaultGroovyConsoleService -import com.citytechinc.aem.prosper.specs.ProsperSpec -import com.day.cq.commons.jcr.JcrConstants -import com.day.cq.replication.Replicator -import com.day.cq.search.QueryBuilder -import org.apache.felix.scr.ScrService -import org.osgi.framework.BundleContext - -import javax.jcr.RepositoryException - -import static com.citytechinc.aem.groovy.console.impl.DefaultGroovyConsoleService.PARAMETER_FILE_NAME -import static com.citytechinc.aem.groovy.console.impl.DefaultGroovyConsoleService.PARAMETER_SCRIPT -import static com.citytechinc.aem.groovy.console.impl.DefaultGroovyConsoleService.RELATIVE_PATH_SCRIPT_FOLDER - -class DefaultGroovyConsoleServiceSpec extends ProsperSpec { - - static final def SCRIPT_NAME = "Script" - - static final def SCRIPT_FILE_NAME = "${SCRIPT_NAME}.groovy" - - static final def PATH_FOLDER = "/etc/groovyconsole/$RELATIVE_PATH_SCRIPT_FOLDER" - - static final def PATH_FILE = "$PATH_FOLDER/$SCRIPT_FILE_NAME" - - static final def PATH_FILE_CONTENT = "$PATH_FILE/${JcrConstants.JCR_CONTENT}" - - def "run script"() { - setup: - def consoleService = createConsoleService() - - def request = requestBuilder.build { - parameters = this.parameterMap - } - - when: - def map = consoleService.runScript(request) - - then: - assertScriptResult(map) - } - - def "run script with additional star imports"() { - - } - - def "save script"() { - setup: - def consoleService = createConsoleService() - - def request = requestBuilder.build { - parameters = this.parameterMap - } - - and: - nodeBuilder.etc { - groovyconsole() - } - - when: - consoleService.saveScript(request) - - then: - assertNodeExists(PATH_FOLDER, JcrConstants.NT_FOLDER) - assertNodeExists(PATH_FILE, JcrConstants.NT_FILE) - assertNodeExists(PATH_FILE_CONTENT, JcrConstants.NT_RESOURCE, [(JcrConstants.JCR_MIMETYPE): "application/octet-stream"]) - - assert session.getNode(PATH_FILE_CONTENT).get(JcrConstants.JCR_DATA).stream.text == scriptAsString - - cleanup: - removeAllNodes() - } - - def "missing console root node"() { - setup: - def consoleService = createConsoleService() - - def request = requestBuilder.build { - parameters = this.parameterMap - } - - when: - consoleService.saveScript(request) - - then: - thrown(RepositoryException) - } - - void assertScriptResult(map) { - assert !map.result - assert map.output == "BEER" + System.getProperty("line.separator") - assert !map.exceptionStackTrace - assert map.runningTime - } - - private def createConsoleService() { - def extensionService = new DefaultExtensionService() - - def bindingExtensionProvider = new DefaultBindingExtensionProvider() - - bindingExtensionProvider.with { - queryBuilder = Mock(QueryBuilder) - bundleContext = Mock(BundleContext) - } - - extensionService.bindBindingExtensionProvider(bindingExtensionProvider) - - def scriptMetaClassExtensionProvider = new DefaultScriptMetaClassExtensionProvider() - - scriptMetaClassExtensionProvider.with { - replicator = Mock(Replicator) - scrService = Mock(ScrService) - queryBuilder = Mock(QueryBuilder) - bundleContext = Mock(BundleContext) - } - - extensionService.bindScriptMetaClassExtensionProvider(scriptMetaClassExtensionProvider) - - def consoleService = new DefaultGroovyConsoleService() - - with(consoleService) { - configurationService = Mock(ConfigurationService) - auditService = Mock(AuditService) - } - - consoleService.extensionService = extensionService - - consoleService - } - - private def getScriptAsString() { - def scriptAsString = null - - this.class.getResourceAsStream("/$SCRIPT_FILE_NAME").withStream { stream -> - scriptAsString = stream.text - } - - scriptAsString - } - - private def getParameterMap() { - [(PARAMETER_FILE_NAME): (SCRIPT_NAME), (PARAMETER_SCRIPT): scriptAsString] - } -} \ No newline at end of file diff --git a/src/test/groovy/com/citytechinc/aem/groovy/console/audit/impl/DefaultAuditServiceSpec.groovy b/src/test/groovy/com/icfolson/aem/groovy/console/audit/impl/DefaultAuditServiceSpec.groovy similarity index 73% rename from src/test/groovy/com/citytechinc/aem/groovy/console/audit/impl/DefaultAuditServiceSpec.groovy rename to src/test/groovy/com/icfolson/aem/groovy/console/audit/impl/DefaultAuditServiceSpec.groovy index f26d8406..f6b24102 100644 --- a/src/test/groovy/com/citytechinc/aem/groovy/console/audit/impl/DefaultAuditServiceSpec.groovy +++ b/src/test/groovy/com/icfolson/aem/groovy/console/audit/impl/DefaultAuditServiceSpec.groovy @@ -1,10 +1,9 @@ -package com.citytechinc.aem.groovy.console.audit.impl +package com.icfolson.aem.groovy.console.audit.impl -import com.citytechinc.aem.groovy.console.response.RunScriptResponse -import com.citytechinc.aem.groovy.console.audit.AuditRecord -import com.citytechinc.aem.prosper.specs.ProsperSpec +import com.icfolson.aem.groovy.console.audit.AuditRecord +import com.icfolson.aem.groovy.console.response.RunScriptResponse +import com.icfolson.aem.prosper.specs.ProsperSpec import org.apache.commons.lang3.exception.ExceptionUtils -import org.apache.sling.jcr.api.SlingRepository import spock.lang.Shared import spock.lang.Unroll @@ -12,24 +11,19 @@ import spock.lang.Unroll class DefaultAuditServiceSpec extends ProsperSpec { @Shared - DefaultAuditService auditService + DefaultAuditService auditService = new DefaultAuditService() def setupSpec() { pageBuilder.etc { groovyconsole() } - auditService = new DefaultAuditService() - - auditService.with { - repository = [loginAdministrative: { this.session }] as SlingRepository - activate() - } + slingContext.registerInjectActivateService(auditService) } def cleanup() { // remove all audit nodes - auditService.allAuditRecords*.path.each { + auditService.getAllAuditRecords(session)*.path.each { session.getNode(it).remove() } @@ -39,7 +33,7 @@ class DefaultAuditServiceSpec extends ProsperSpec { def "create audit record for script with result and output"() { when: def response = RunScriptResponse.fromResult(script, result, output, runningTime) - def auditRecord = auditService.createAuditRecord(response) + def auditRecord = auditService.createAuditRecord(session, response) then: assertNodeExists(auditRecord.path) @@ -54,12 +48,11 @@ class DefaultAuditServiceSpec extends ProsperSpec { "script content" | "result" | "output" | "running time" } - def "create audit record for script with exception"() { when: def exception = new RuntimeException("") def response = RunScriptResponse.fromException("script content", exception) - def auditRecord = auditService.createAuditRecord(response) + def auditRecord = auditService.createAuditRecord(session, response) then: assertNodeExists(auditRecord.path) @@ -76,7 +69,7 @@ class DefaultAuditServiceSpec extends ProsperSpec { when: (1..5).each { - auditRecords.add(auditService.createAuditRecord(response)) + auditRecords.add(auditService.createAuditRecord(session, response)) } then: @@ -87,14 +80,14 @@ class DefaultAuditServiceSpec extends ProsperSpec { setup: def response = RunScriptResponse.fromResult("script content", "result", "output", "running time") - auditService.createAuditRecord(response) + auditService.createAuditRecord(session, response) def date = new Date() def startDate = (date + startDateOffset).toCalendar() def endDate = (date + endDateOffset).toCalendar() expect: - auditService.getAuditRecords(startDate, endDate).size() == size + auditService.getAuditRecords(session, startDate, endDate).size() == size where: startDateOffset | endDateOffset | size diff --git a/src/test/groovy/com/citytechinc/aem/groovy/console/services/impl/DefaultExtensionServiceSpec.groovy b/src/test/groovy/com/icfolson/aem/groovy/console/services/impl/DefaultExtensionServiceSpec.groovy similarity index 76% rename from src/test/groovy/com/citytechinc/aem/groovy/console/services/impl/DefaultExtensionServiceSpec.groovy rename to src/test/groovy/com/icfolson/aem/groovy/console/services/impl/DefaultExtensionServiceSpec.groovy index 912d01e6..fc187855 100644 --- a/src/test/groovy/com/citytechinc/aem/groovy/console/services/impl/DefaultExtensionServiceSpec.groovy +++ b/src/test/groovy/com/icfolson/aem/groovy/console/services/impl/DefaultExtensionServiceSpec.groovy @@ -1,10 +1,10 @@ -package com.citytechinc.aem.groovy.console.services.impl +package com.icfolson.aem.groovy.console.services.impl -import com.citytechinc.aem.groovy.console.api.BindingExtensionProvider -import com.citytechinc.aem.groovy.console.api.ScriptMetaClassExtensionProvider -import com.citytechinc.aem.groovy.console.api.StarImportExtensionProvider -import com.citytechinc.aem.groovy.console.extension.impl.DefaultExtensionService -import com.citytechinc.aem.prosper.specs.ProsperSpec +import com.icfolson.aem.groovy.console.api.BindingExtensionProvider +import com.icfolson.aem.groovy.console.api.ScriptMetaClassExtensionProvider +import com.icfolson.aem.groovy.console.api.StarImportExtensionProvider +import com.icfolson.aem.groovy.console.extension.impl.DefaultExtensionService +import com.icfolson.aem.prosper.specs.ProsperSpec import org.apache.sling.api.SlingHttpServletRequest import java.text.SimpleDateFormat @@ -35,10 +35,10 @@ class DefaultExtensionServiceSpec extends ProsperSpec { @Override Binding getBinding(SlingHttpServletRequest request) { - def map = [parameterNames: request.parameterMap.keySet(), - selectors : request.requestPathInfo.selectors as List] - - new Binding(map) + new Binding([ + parameterNames: request.parameterMap.keySet(), + selectors: [] + ]) } } @@ -46,10 +46,10 @@ class DefaultExtensionServiceSpec extends ProsperSpec { @Override Binding getBinding(SlingHttpServletRequest request) { - def map = [path : request.requestPathInfo.resourcePath, - selectors: []] - - new Binding(map) + new Binding([ + path: request.requestPathInfo.resourcePath, + selectors: request.requestPathInfo.selectors as List + ]) } } @@ -77,15 +77,14 @@ class DefaultExtensionServiceSpec extends ProsperSpec { then: extensionService.starImports.size() == 3 - extensionService.starImports.containsAll( - [InputStream.class, SimpleDateFormat.class, BigDecimal.class]*.package.name) + extensionService.starImports.containsAll([InputStream, SimpleDateFormat, BigDecimal]*.package.name) when: extensionService.unbindStarImportExtensionProvider(firstProvider) then: extensionService.starImports.size() == 1 - extensionService.starImports[0] == BigDecimal.class.package.name + extensionService.starImports[0] == BigDecimal.package.name } def "get binding"() { @@ -109,14 +108,13 @@ class DefaultExtensionServiceSpec extends ProsperSpec { extensionService.getBinding(request)["path"] == "/" when: - extensionService.unbindBindingExtensionProvider(firstProvider) + extensionService.unbindBindingExtensionProvider(secondProvider) then: extensionService.getBinding(request)["selectors"] == [] - extensionService.getBinding(request)["path"] == "/" when: - extensionService.getBinding(request)["parameterNames"] + extensionService.getBinding(request)["path"] then: thrown(MissingPropertyException) diff --git a/src/test/groovy/com/icfolson/aem/groovy/console/services/impl/DefaultGroovyConsoleServiceSpec.groovy b/src/test/groovy/com/icfolson/aem/groovy/console/services/impl/DefaultGroovyConsoleServiceSpec.groovy new file mode 100755 index 00000000..66fd93d7 --- /dev/null +++ b/src/test/groovy/com/icfolson/aem/groovy/console/services/impl/DefaultGroovyConsoleServiceSpec.groovy @@ -0,0 +1,101 @@ +package com.icfolson.aem.groovy.console.services.impl + +import com.day.cq.commons.jcr.JcrConstants +import com.day.cq.search.QueryBuilder +import com.icfolson.aem.groovy.console.GroovyConsoleService +import com.icfolson.aem.groovy.console.audit.AuditService +import com.icfolson.aem.groovy.console.configuration.ConfigurationService +import com.icfolson.aem.groovy.console.extension.impl.DefaultBindingExtensionProvider +import com.icfolson.aem.groovy.console.extension.impl.DefaultExtensionService +import com.icfolson.aem.groovy.console.extension.impl.DefaultScriptMetaClassExtensionProvider +import com.icfolson.aem.groovy.console.impl.DefaultGroovyConsoleService +import com.icfolson.aem.prosper.specs.ProsperSpec + +import static com.icfolson.aem.groovy.console.impl.DefaultGroovyConsoleService.PARAMETER_FILE_NAME +import static com.icfolson.aem.groovy.console.impl.DefaultGroovyConsoleService.PARAMETER_SCRIPT +import static com.icfolson.aem.groovy.console.impl.DefaultGroovyConsoleService.RELATIVE_PATH_SCRIPT_FOLDER + +class DefaultGroovyConsoleServiceSpec extends ProsperSpec { + + static final def SCRIPT_NAME = "Script" + + static final def SCRIPT_FILE_NAME = "${SCRIPT_NAME}.groovy" + + static final def PATH_FOLDER = "/etc/groovyconsole/$RELATIVE_PATH_SCRIPT_FOLDER" + + static final def PATH_FILE = "$PATH_FOLDER/$SCRIPT_FILE_NAME" + + static final def PATH_FILE_CONTENT = "$PATH_FILE/${JcrConstants.JCR_CONTENT}" + + def setupSpec() { + slingContext.registerService(QueryBuilder, Mock(QueryBuilder)) + slingContext.registerService(ConfigurationService, Mock(ConfigurationService)) + slingContext.registerService(AuditService, Mock(AuditService)) + slingContext.registerInjectActivateService(new DefaultBindingExtensionProvider()) + slingContext.registerInjectActivateService(new DefaultExtensionService()) + slingContext.registerInjectActivateService(new DefaultScriptMetaClassExtensionProvider()) + slingContext.registerInjectActivateService(new DefaultGroovyConsoleService()) + } + + def "run script"() { + setup: + def consoleService = slingContext.getService(GroovyConsoleService) + + def request = requestBuilder.build { + parameters = this.parameterMap + } + + when: + def map = consoleService.runScript(request) + + then: + assertScriptResult(map) + } + + def "save script"() { + setup: + def consoleService = slingContext.getService(GroovyConsoleService) + + def request = requestBuilder.build { + parameters = this.parameterMap + } + + and: + nodeBuilder.etc { + groovyconsole() + } + + when: + consoleService.saveScript(request) + + then: + assertNodeExists(PATH_FOLDER, JcrConstants.NT_FOLDER) + assertNodeExists(PATH_FILE, JcrConstants.NT_FILE) + assertNodeExists(PATH_FILE_CONTENT, JcrConstants.NT_RESOURCE, + [(JcrConstants.JCR_MIMETYPE): "application/octet-stream"]) + + and: + assert session.getNode(PATH_FILE_CONTENT).get(JcrConstants.JCR_DATA).stream.text == scriptAsString + } + + void assertScriptResult(map) { + assert !map.result + assert map.output == "BEER" + System.getProperty("line.separator") + assert !map.exceptionStackTrace + assert map.runningTime + } + + private String getScriptAsString() { + def scriptAsString = null + + this.class.getResourceAsStream("/$SCRIPT_FILE_NAME").withStream { stream -> + scriptAsString = stream.text + } + + scriptAsString + } + + private Map getParameterMap() { + [(PARAMETER_FILE_NAME): (SCRIPT_NAME), (PARAMETER_SCRIPT): scriptAsString] + } +} \ No newline at end of file