You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/11/07 09:17:15 UTC
[sling-maven-sling-plugin] 02/06: SLING-2313 - creating a new
adapter annotations module and enhancing the sling plugin to generate the
adapter JSON file
This is an automated email from the ASF dual-hosted git repository.
rombert pushed a commit to annotated tag maven-sling-plugin-2.1.0
in repository https://gitbox.apache.org/repos/asf/sling-maven-sling-plugin.git
commit c609e548beeb018dcde20dd8c3e4bf327ecd965a
Author: Justin Edelson <ju...@apache.org>
AuthorDate: Fri Dec 2 02:51:45 2011 +0000
SLING-2313 - creating a new adapter annotations module and enhancing the sling plugin to generate the adapter JSON file
git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/maven/maven-sling-plugin@1209336 13f79535-47bb-0310-9956-ffa450edef68
---
pom.xml | 15 ++
.../bundlesupport/GenerateAdapterMetadataMojo.java | 243 +++++++++++++++++++++
2 files changed, 258 insertions(+)
diff --git a/pom.xml b/pom.xml
index 1499e96..291a0f9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -108,5 +108,20 @@
<artifactId>maven-archiver</artifactId>
<version>2.0</version>
</dependency>
+ <dependency>
+ <groupId>net.sf.scannotation</groupId>
+ <artifactId>scannotation</artifactId>
+ <version>1.0.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>adapter-annotations</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>asm</groupId>
+ <artifactId>asm-all</artifactId>
+ <version>3.3.1</version>
+ </dependency>
</dependencies>
</project>
diff --git a/src/main/java/org/apache/sling/maven/bundlesupport/GenerateAdapterMetadataMojo.java b/src/main/java/org/apache/sling/maven/bundlesupport/GenerateAdapterMetadataMojo.java
new file mode 100644
index 0000000..04639b6
--- /dev/null
+++ b/src/main/java/org/apache/sling/maven/bundlesupport/GenerateAdapterMetadataMojo.java
@@ -0,0 +1,243 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.sling.maven.bundlesupport;
+
+import static org.objectweb.asm.ClassReader.*;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.maven.model.Resource;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.project.MavenProject;
+import org.apache.sling.adapter.annotations.Adaptable;
+import org.apache.sling.commons.json.JSONException;
+import org.apache.sling.commons.json.JSONObject;
+import org.codehaus.plexus.util.IOUtil;
+import org.codehaus.plexus.util.StringUtils;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.AnnotationNode;
+import org.objectweb.asm.tree.ClassNode;
+import org.scannotation.AnnotationDB;
+
+/**
+ * @goal generate-adapter-metadata
+ * @phase process-classes
+ * @threadSafe
+ * @description Build Adapter Metadata from Annotated Classes
+ * @requiresDependencyResolution compile
+ */
+public class GenerateAdapterMetadataMojo extends AbstractMojo {
+
+ private static final int JSON_INDENTATION = 4;
+
+ private static final String ADAPTABLE_DESC = "L" + Adaptable.class.getName().replace('.', '/') + ";";
+
+ private static final String DEFAULT_CONDITION = "If the adaptable is a %s.";
+
+ private static String getSimpleName(final ClassNode clazz) {
+ final String internalName = clazz.name;
+ final int idx = internalName.lastIndexOf('/');
+ if (idx == -1) {
+ return internalName;
+ } else {
+ return internalName.substring(idx + 1);
+ }
+ }
+
+ /**
+ * @parameter expression="${project.build.outputDirectory}"
+ * @required
+ * @readonly
+ */
+ private File buildOutputDirectory;
+
+ /**
+ * Name of the generated descriptor file.
+ *
+ * @parameter expression="${adapter.descriptor.name}"
+ * default-value="SLING-INF/adapters.json"
+ */
+ private String fileName;
+
+ /**
+ * @parameter
+ * expression="${project.build.directory}/adapter-plugin-generated"
+ * @required
+ * @readonly
+ */
+ private File outputDirectory;
+
+ /**
+ * The Maven project.
+ *
+ * @parameter expression="${project}"
+ * @required
+ * @readonly
+ */
+ private MavenProject project;
+
+ public void execute() throws MojoExecutionException, MojoFailureException {
+ try {
+ final JSONObject descriptor = new JSONObject();
+
+ final AnnotationDB annotationDb = new AnnotationDB();
+ annotationDb.scanArchives(buildOutputDirectory.toURI().toURL());
+
+ final Set<String> annotatedClassNames = annotationDb.getAnnotationIndex().get(Adaptable.class.getName());
+ if (annotatedClassNames.isEmpty()) {
+ getLog().debug("No classes found with adaptable annotations.");
+ }
+
+ for (final String annotatedClassName : annotatedClassNames) {
+ getLog().info(String.format("found adaptable annotation on %s", annotatedClassName));
+ final String pathToClassFile = annotatedClassName.replace('.', '/') + ".class";
+ final File classFile = new File(buildOutputDirectory, pathToClassFile);
+ final FileInputStream input = new FileInputStream(classFile);
+ final ClassReader classReader;
+ try {
+ classReader = new ClassReader(input);
+ } finally {
+ input.close();
+ }
+ final ClassNode classNode = new ClassNode();
+ classReader.accept(classNode, SKIP_CODE | SKIP_DEBUG | SKIP_FRAMES);
+
+ @SuppressWarnings("unchecked")
+ final List<AnnotationNode> annotations = classNode.invisibleAnnotations;
+ for (final AnnotationNode annotation : annotations) {
+ if (ADAPTABLE_DESC.equals(annotation.desc)) {
+ parseAdaptableAnnotation(annotation, classNode, descriptor);
+ }
+ }
+
+ }
+
+ final File outputFile = new File(outputDirectory, fileName);
+ outputFile.getParentFile().mkdirs();
+ final FileWriter writer = new FileWriter(outputFile);
+ try {
+ IOUtil.copy(descriptor.toString(JSON_INDENTATION), writer);
+ } finally {
+ IOUtil.close(writer);
+ }
+ addResource();
+
+ } catch (IOException e) {
+ throw new MojoExecutionException("Unable to generate metadata", e);
+ } catch (JSONException e) {
+ throw new MojoExecutionException("Unable to generate metadata", e);
+ }
+
+ }
+
+ private void addResource() {
+ final String ourRsrcPath = this.outputDirectory.getAbsolutePath();
+ boolean found = false;
+ @SuppressWarnings("unchecked")
+ final Iterator<Resource> rsrcIterator = this.project.getResources().iterator();
+ while (!found && rsrcIterator.hasNext()) {
+ final Resource rsrc = rsrcIterator.next();
+ found = rsrc.getDirectory().equals(ourRsrcPath);
+ }
+ if (!found) {
+ final Resource resource = new Resource();
+ resource.setDirectory(this.outputDirectory.getAbsolutePath());
+ this.project.addResource(resource);
+ }
+
+ }
+
+ @SuppressWarnings("unchecked")
+ private void parseAdaptableAnnotation(final AnnotationNode annotation, final ClassNode annotatedClass,
+ final JSONObject descriptor) throws JSONException {
+ String adaptableClassName = null;
+ List<AnnotationNode> adapters = null;
+
+ final List<?> values = annotation.values;
+
+ final Iterator<?> it = values.iterator();
+ while (it.hasNext()) {
+ Object name = it.next();
+ Object value = it.next();
+
+ if ("adaptableClass".equals(name)) {
+ adaptableClassName = ((Type) value).getClassName();
+ } else if ("adapters".equals(name)) {
+ adapters = (List<AnnotationNode>) value;
+ }
+ }
+
+ if (adaptableClassName == null || adapters == null) {
+ throw new IllegalArgumentException(
+ "Adaptable annotation is malformed. Expecting a classname and a list of adapter annotation.");
+ }
+
+ JSONObject adaptableDescription;
+ if (descriptor.has(adaptableClassName)) {
+ adaptableDescription = descriptor.getJSONObject(adaptableClassName);
+ } else {
+ adaptableDescription = new JSONObject();
+ descriptor.put(adaptableClassName, adaptableDescription);
+ }
+
+ for (final AnnotationNode adapter : adapters) {
+ parseAdapterAnnotation(adapter, annotatedClass, adaptableDescription);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void parseAdapterAnnotation(final AnnotationNode annotation, final ClassNode annotatedClass,
+ final JSONObject adaptableDescription) throws JSONException {
+ String condition = null;
+ List<Type> adapterClasses = null;
+
+ final List<?> values = annotation.values;
+
+ final Iterator<?> it = values.iterator();
+ while (it.hasNext()) {
+ final Object name = it.next();
+ final Object value = it.next();
+
+ if (StringUtils.isEmpty(condition)) {
+ condition = String.format(DEFAULT_CONDITION, getSimpleName(annotatedClass));
+ }
+
+ if ("condition".equals(name)) {
+ condition = (String) value;
+ } else if ("value".equals(name)) {
+ adapterClasses = (List<Type>) value;
+ }
+ }
+
+ if (adapterClasses == null) {
+ throw new IllegalArgumentException("Adapter annotation is malformed. Expecting a list of adapter classes");
+ }
+
+ for (final Type adapterClass : adapterClasses) {
+ adaptableDescription.accumulate(condition, adapterClass.getClassName());
+ }
+ }
+}
--
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.