blob: c9b392a3e91a991f5404b0f7b48be8eb200a04e3 [file] [log] [blame]
/*
* 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.felix.scrplugin.processing;
import java.util.List;
import org.apache.felix.scr.annotations.sling.SlingFilter;
import org.apache.felix.scr.annotations.sling.SlingFilterScope;
import org.apache.felix.scr.annotations.sling.SlingServlet;
import org.apache.felix.scrplugin.SCRDescriptorException;
import org.apache.felix.scrplugin.SCRDescriptorFailureException;
import org.apache.felix.scrplugin.annotations.AnnotationProcessor;
import org.apache.felix.scrplugin.annotations.ClassAnnotation;
import org.apache.felix.scrplugin.annotations.ScannedClass;
import org.apache.felix.scrplugin.description.ClassDescription;
import org.apache.felix.scrplugin.description.ComponentConfigurationPolicy;
import org.apache.felix.scrplugin.description.ComponentDescription;
import org.apache.felix.scrplugin.description.PropertyDescription;
import org.apache.felix.scrplugin.description.PropertyType;
import org.apache.felix.scrplugin.description.ServiceDescription;
import org.apache.felix.scrplugin.helper.StringUtils;
/**
* This is the processor for the Apache Felix Sling annotations.
*/
public class SlingAnnotationProcessor implements AnnotationProcessor {
/**
* @see org.apache.felix.scrplugin.annotations.AnnotationProcessor#getName()
*/
@Override
public String getName() {
return "Apache Sling Annotation Processor";
}
/**
* @see org.apache.felix.scrplugin.annotations.AnnotationProcessor#process(org.apache.felix.scrplugin.annotations.ScannedClass, org.apache.felix.scrplugin.description.ClassDescription)
*/
@Override
public void process(final ScannedClass scannedClass,
final ClassDescription describedClass)
throws SCRDescriptorFailureException, SCRDescriptorException {
final List<ClassAnnotation> servlets = scannedClass.getClassAnnotations(SlingServlet.class.getName());
scannedClass.processed(servlets);
for(final ClassAnnotation cad : servlets) {
processSlingServlet(cad, describedClass);
}
final List<ClassAnnotation> filters = scannedClass.getClassAnnotations(SlingFilter.class.getName());
scannedClass.processed(filters);
for(final ClassAnnotation cad : filters) {
processSlingFilter(cad, describedClass);
}
}
/**
* @see org.apache.felix.scrplugin.annotations.AnnotationProcessor#getRanking()
*/
@Override
public int getRanking() {
return 500;
}
/**
* Process SlingServlet
*/
private void processSlingServlet(final ClassAnnotation cad, final ClassDescription classDescription) {
// generate ComponentDescription if required
final boolean generateComponent = cad.getBooleanValue("generateComponent", true);
final boolean metatype = cad.getBooleanValue("metatype", !generateComponent);
if (generateComponent) {
final ComponentDescription cd = new ComponentDescription(cad);
cd.setName(cad.getStringValue("name", classDescription.getDescribedClass().getName()));
cd.setConfigurationPolicy(ComponentConfigurationPolicy.OPTIONAL);
cd.setLabel(cad.getStringValue("label", null));
cd.setDescription(cad.getStringValue("description", null));
cd.setCreateMetatype(metatype);
cd.setCreatePid(false); // always set to false
classDescription.add(cd);
}
// generate ServiceDescription if required
final boolean generateService = cad.getBooleanValue("generateService", true);
if (generateService) {
final ServiceDescription sd = new ServiceDescription(cad);
sd.addInterface("javax.servlet.Servlet");
classDescription.add(sd);
}
// generate PropertyDescriptions
// {@see org.apache.sling.servlets.resolver.internal.ServletResolverConstants.SLING_SERVLET_PATHS}
generateStringPropertyDescriptor(cad, classDescription, metatype, "paths", "sling.servlet.paths");
// {@see org.apache.sling.servlets.resolver.internal.ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES}
generateStringPropertyDescriptor(cad, classDescription, metatype, "resourceTypes",
"sling.servlet.resourceTypes");
// {@see org.apache.sling.servlets.resolver.internal.ServletResolverConstants.SLING_SERVLET_SELECTORS}
generateStringPropertyDescriptor(cad, classDescription, metatype, "selectors", "sling.servlet.selectors");
// {@see org.apache.sling.servlets.resolver.internal.ServletResolverConstants.SLING_SERVLET_EXTENSIONS}
generateStringPropertyDescriptor(cad, classDescription, metatype, "extensions", "sling.servlet.extensions");
// {@see org.apache.sling.servlets.resolver.internal.ServletResolverConstants.SLING_SERVLET_METHODS}
generateStringPropertyDescriptor(cad, classDescription, metatype, "methods", "sling.servlet.methods");
}
/**
* Generates a property descriptor of type {@link PropertyType#String}
*/
private void generateStringPropertyDescriptor(final ClassAnnotation cad, final ClassDescription classDescription,
final boolean metatype, String annotationName, String propertyDescriptorName) {
final String[] values = (String[]) cad.getValue(annotationName);
if (values == null) {
return;
}
final PropertyDescription pd = new PropertyDescription(cad);
pd.setName(propertyDescriptorName);
pd.setMultiValue(values);
pd.setType(PropertyType.String);
if (metatype) {
pd.setPrivate(true);
}
classDescription.add(pd);
}
/**
* Process SlingFilter
*/
private void processSlingFilter(final ClassAnnotation cad, final ClassDescription classDescription) {
// generate ComponentDescription if required
final boolean generateComponent = cad.getBooleanValue("generateComponent", true);
final boolean metatype = cad.getBooleanValue("metatype", !generateComponent);
if (generateComponent) {
final ComponentDescription cd = new ComponentDescription(cad);
cd.setName(cad.getStringValue("name", classDescription.getDescribedClass().getName()));
cd.setConfigurationPolicy(ComponentConfigurationPolicy.OPTIONAL);
cd.setLabel(cad.getStringValue("label", null));
cd.setDescription(cad.getStringValue("description", null));
cd.setCreateMetatype(metatype);
classDescription.add(cd);
}
// generate ServiceDescription if required
final boolean generateService = cad.getBooleanValue("generateService", true);
if (generateService) {
final ServiceDescription sd = new ServiceDescription(cad);
sd.addInterface("javax.servlet.Filter");
classDescription.add(sd);
}
// generate PropertyDescriptions
// property order = service.ranking
final int order = cad.getIntegerValue("order", 0);
final PropertyDescription pd = new PropertyDescription(cad);
pd.setName("service.ranking");
pd.setValue(String.valueOf(order));
pd.setType(PropertyType.Integer);
if (metatype) {
pd.setPrivate(true);
}
classDescription.add(pd);
// property pattern = sling.filter.pattern
final String pattern = cad.getStringValue("pattern", "");
if(!StringUtils.isEmpty(pattern)) {
final PropertyDescription pdPattern = new PropertyDescription(cad);
pdPattern.setName("sling.filter.pattern");
pdPattern.setValue(pattern);
pdPattern.setType(PropertyType.String);
if (metatype) {
pdPattern.setPrivate(true);
}
classDescription.add(pdPattern);
}
// property scope
final String[] scopes;
final Object val = cad.getValue("scope");
if ( val != null ) {
if ( val instanceof String[] ) {
final String[] arr = (String[])val;
scopes = new String[arr.length / 2];
int i = 0;
int index = 0;
while ( i < arr.length) {
scopes[index] = arr[i];
i+=2;
index++;
}
} else if ( val instanceof String[][] ) {
final String[][] arr = (String[][])val;
scopes = new String[arr.length];
int index = 0;
while ( index < arr.length) {
scopes[index] = arr[index][1];
index++;
}
} else {
scopes = new String[] { val.toString()};
}
} else {
scopes = new String[] {SlingFilterScope.REQUEST.getScope()};
}
final PropertyDescription pd2 = new PropertyDescription(cad);
pd2.setName("sling.filter.scope");
if ( scopes.length == 1 ) {
pd2.setValue(scopes[0]);
} else {
pd2.setMultiValue(scopes);
}
pd2.setType(PropertyType.String);
if (metatype) {
pd2.setPrivate(true);
}
classDescription.add(pd2);
}
}