Skip to content

Commit

Permalink
Add MetaClassExtensions, update and publish docs
Browse files Browse the repository at this point in the history
  • Loading branch information
bdhoine committed Jan 3, 2023
1 parent 703f62e commit ba2d753
Show file tree
Hide file tree
Showing 17 changed files with 582 additions and 36 deletions.
46 changes: 46 additions & 0 deletions .github/workflows/github-pages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Publish site

on:
release:
types: [created]

# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write

# Allow one concurrent deployment
concurrency:
group: "pages"
cancel-in-progress: true

jobs:
deploy:
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Set up Maven Central Repository
uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: 11

- name: Publish site
run: mvn --batch-mode --projects bundle site

- name: Setup Pages
uses: actions/configure-pages@v2

- name: Upload artifact
uses: actions/upload-pages-artifact@v1
with:
path: './bundle/target/site/groovydocs'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v1
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- Allow to select scripts in any directory [#29](https://github.com/orbinson/aem-groovy-console/issues/29)
- Allow to select scripts in any directory: [#29](https://github.com/orbinson/aem-groovy-console/issues/29)

### Fixed

- Publish java docs to github pages: [#19](https://github.com/orbinson/aem-groovy-console/issues/19)
- Add MetaClassExtensions extensions: [#32](https://github.com/orbinson/aem-groovy-console/issues/32)

## [18.0.0] - 2022-30-01

Expand Down
4 changes: 2 additions & 2 deletions LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0
https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
limitations under the License.
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

## Overview

The AEM Groovy Console provides an interface for running [Groovy](http://www.groovy-lang.org/) scripts in Adobe
The AEM Groovy Console provides an interface for running [Groovy](https://www.groovy-lang.org) scripts in Adobe
Experience Manager. Scripts can be created to manipulate content in the JCR, call OSGi services, or execute arbitrary
code using the AEM, Sling, or JCR APIs. After installing the package in AEM (instructions below), see
the [console page](http://localhost:4502/groovyconsole) for documentation on the available bindings and methods. Sample
Expand All @@ -32,7 +32,7 @@ project [aem-groovy-console](https://github.com/CID15/aem-groovy-console)
### Requirements

* AEM author instance running on [http://localhost:4502](http://localhost:4502/)
* [Maven](http://maven.apache.org/) `>= 3.6.3`
* [Maven](https://maven.apache.org/) `>= 3.6.3`

### Installation

Expand Down Expand Up @@ -152,6 +152,10 @@ metaclasses, and star imports.
| `be.orbinson.aem.groovy.console.api.ScriptMetaClassExtensionProvider` | Add runtime metaclasses (i.e. new methods) to the underlying script class. |
| `be.orbinson.aem.groovy.console.api.StarImportExtensionProvider` | Supply additional star imports that are added to the compiler configuration for each script execution. |

## Registering Additional Metaclasses

Services implementing the `be.orbinson.aem.groovy.console.extension.MetaClassExtensionProvider` will be automatically discovered and bound by the OSGi container. These services can be implemented in any deployed bundle. The AEM Groovy Extension bundle will handle the registration and removal of supplied metaclasses as these services are activated/deactivated in the container. See the `DefaultMetaClassExtensionProvider` service for the proper closure syntax for registering metaclasses.

## Notifications

To provide custom notifications for script executions, bundles may implement
Expand Down
4 changes: 0 additions & 4 deletions all/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -181,10 +181,6 @@
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
</dependency>
<dependency>
<groupId>com.icfolson.aem.groovy.extension</groupId>
<artifactId>aem-groovy-extension-bundle</artifactId>
</dependency>
<dependency>
<groupId>be.orbinson.aem</groupId>
<artifactId>aem-groovy-console-bundle</artifactId>
Expand Down
42 changes: 38 additions & 4 deletions bundle/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,44 @@
<groupId>org.apache.sling</groupId>
<artifactId>sling-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>groovydoc</id>
<phase>site</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<taskdef name="groovydoc"
classname="org.codehaus.groovy.ant.Groovydoc"
classpathref="maven.compile.classpath"/>
<groovydoc destdir="${project.reporting.outputDirectory}/groovydocs"
sourcepath="${basedir}/src/main/groovy"
use="true"
windowtitle="${project.name}"
doctitle="${project.name}">
<link packages="com.day.cq.wcm.api."
href="https://docs.adobe.com/docs/en/aem/6-2/develop/ref/javadoc"/>
<link packages="org.apache.sling."
href="http://sling.apache.org/apidocs/sling7"/>
<link packages="javax.jcr."
href="https://docs.adobe.com/content/docs/en/spec/jsr170/javadocs/jcr-2.0/"/>
<link packages="java."
href="https://docs.oracle.com/javase/7/docs/api"/>
<link packages="javax."
href="https://docs.oracle.com/javaee/7/api"/>
<link packages="groovy.,org.codehaus.groovy."
href="http://groovy.codehaus.org/api/"/>
</groovydoc>
</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

Expand Down Expand Up @@ -197,10 +235,6 @@
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
</dependency>
<dependency>
<groupId>com.icfolson.aem.groovy.extension</groupId>
<artifactId>aem-groovy-extension-bundle</artifactId>
</dependency>

<!-- test -->
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import be.orbinson.aem.groovy.console.api.context.ScriptContext

/**
* Service that dynamically binds extensions providing additional script bindings, star imports, and script metaclasses.
* The extension service is also responsible for aggregating all metaclass extension providers and handling the
* registration and removal of metaclass closures as these provider implementations are added or removed from the
* OSGi container.
*/
interface ExtensionService extends BindingExtensionProvider, CompilationCustomizerExtensionProvider,
StarImportExtensionProvider {
Expand All @@ -18,4 +21,12 @@ interface ExtensionService extends BindingExtensionProvider, CompilationCustomiz
* @return list of metaclass closures
*/
List<Closure> getScriptMetaClasses(ScriptContext scriptContext)
}

/**
* Get the set of all classes that have associated metaclasses. This value may change as metaclass extension
* providers are added or removed from the OSGi container.
*
* @return set of classes that have associated metaclasses registered in the container
*/
Set<Class> getMetaClasses()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package be.orbinson.aem.groovy.console.extension

/**
* Services may implement this interface to register additional Groovy metaclasses in the OSGi container.
*/
interface MetaClassExtensionProvider {

/**
* Get a map containing classes with a closure that defines a metaclass.
*
* @return map of classes and their associated metaclass closure
*/
Map<Class, Closure> getMetaClasses()
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class DefaultBindingExtensionProvider implements BindingExtensionProvider {

def bindingVariables = [
log : new BindingVariable(LoggerFactory.getLogger("groovyconsole"), Logger,
"http://www.slf4j.org/api/org/slf4j/Logger.html"),
"https://www.slf4j.org/api/org/slf4j/Logger.html"),
session : new BindingVariable(session, Session,
"https://developer.adobe.com/experience-manager/reference-materials/spec/javax.jcr/javadocs/jcr-2.0/javax/jcr/Session.html"),
pageManager : new BindingVariable(resourceResolver.adaptTo(PageManager), PageManager),
Expand All @@ -46,13 +46,11 @@ class DefaultBindingExtensionProvider implements BindingExtensionProvider {
queryBuilder : new BindingVariable(queryBuilder, QueryBuilder,
"https://developer.adobe.com/experience-manager/reference-materials/6-5/javadoc/com/day/cq/search/QueryBuilder.html"),
nodeBuilder : new BindingVariable(new NodeBuilder(session), NodeBuilder,
"http://code.digitalatolson.com/aem-groovy-extension/groovydocs/com/icfolson/aem/groovy/extension" +
"/builders/NodeBuilder.html"),
" https://orbinson.github.io/aem-groovy-console/be/orbinson/aem/groovy/console/builders/NodeBuilder.html"),
pageBuilder : new BindingVariable(new PageBuilder(session), PageBuilder,
"http://code.digitalatolson.com/aem-groovy-extension/groovydocs/com/icfolson/aem/groovy/extension" +
"/builders/PageBuilder.html"),
" https://orbinson.github.io/aem-groovy-console/be/orbinson/aem/groovy/console/builders/PageBuilder.html"),
bundleContext : new BindingVariable(bundleContext, BundleContext,
"http://www.osgi.org/javadoc/r4v43/core/org/osgi/framework/BundleContext.html"),
"https://docs.osgi.org/javadoc/r4v43/core/org/osgi/framework/BundleContext.html"),
out : new BindingVariable(scriptContext.printStream, PrintStream,
"https://docs.oracle.com/javase/8/docs/api/java/io/PrintStream.html")
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import be.orbinson.aem.groovy.console.api.StarImport
import be.orbinson.aem.groovy.console.api.StarImportExtensionProvider
import be.orbinson.aem.groovy.console.api.context.ScriptContext
import be.orbinson.aem.groovy.console.extension.ExtensionService
import be.orbinson.aem.groovy.console.extension.MetaClassExtensionProvider
import groovy.transform.Synchronized
import groovy.util.logging.Slf4j
import org.codehaus.groovy.control.customizers.CompilationCustomizer
Expand All @@ -23,6 +24,8 @@ import java.util.concurrent.CopyOnWriteArrayList
@Slf4j("LOG")
class DefaultExtensionService implements ExtensionService {

private volatile List<MetaClassExtensionProvider> metaClassExtensionProviders = new CopyOnWriteArrayList<>()

private volatile List<BindingExtensionProvider> bindingExtensionProviders = new CopyOnWriteArrayList<>()

private volatile List<StarImportExtensionProvider> starImportExtensionProviders = new CopyOnWriteArrayList<>()
Expand Down Expand Up @@ -50,6 +53,56 @@ class DefaultExtensionService implements ExtensionService {
bindingVariables
}

@Override
Set<Class> getMetaClasses() {
def metaClasses = [] as LinkedHashSet

metaClassExtensionProviders.each { provider ->
metaClasses.addAll(provider.metaClasses.keySet())
}

metaClasses
}

@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
@Synchronized
void bindMetaClassExtensionProvider(MetaClassExtensionProvider extension) {
metaClassExtensionProviders.add(extension)

LOG.info("added metaclass extension provider = {}", extension.class.name)

extension.metaClasses.each { clazz, metaClassClosure ->
clazz.metaClass(metaClassClosure)

LOG.info("added metaclass for class = {}", clazz.name)
}
}

@Synchronized
void unbindMetaClassExtensionProvider(MetaClassExtensionProvider extension) {
metaClassExtensionProviders.remove(extension)

LOG.info("removed metaclass extension provider = {}", extension.class.name)

// remove metaclass from registry for each mapped class
extension.metaClasses.each { clazz, closure ->
InvokerHelper.metaRegistry.removeMetaClass(clazz)

LOG.info("removed metaclass for class = {}", clazz.name)

// ensure that valid metaclasses are still registered
metaClassExtensionProviders.each {
def metaClassClosure = it.metaClasses[clazz]

if (metaClassClosure) {
LOG.info("retaining metaclass for class = {} from service = {}", clazz.name, it.class.name)

clazz.metaClass(metaClassClosure)
}
}
}
}

@Override
List<Closure> getScriptMetaClasses(ScriptContext scriptContext) {
scriptMetaClassExtensionProviders*.getScriptMetaClass(scriptContext)
Expand Down Expand Up @@ -136,4 +189,4 @@ class DefaultExtensionService implements ExtensionService {

LOG.info("removed compilation customizer extension : {}", extension.class.name)
}
}
}
Loading

0 comments on commit ba2d753

Please sign in to comment.