/* * gvNIX is an open source tool for rapid application development (RAD). * Copyright (C) 2010 Generalitat Valenciana * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see <http://www.gnu.org/licenses/>. */ package org.gvnix.web.mvc.binding.roo.addon.addon; import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; import org.apache.commons.lang3.Validate; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.Service; import org.gvnix.support.OperationUtils; import org.gvnix.support.dependenciesmanager.DependenciesVersionManager; import org.gvnix.web.mvc.binding.roo.addon.annotations.GvNIXStringTrimmerBinder; import org.osgi.framework.BundleContext; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; import org.osgi.service.component.ComponentContext; import org.springframework.roo.classpath.TypeLocationService; import org.springframework.roo.classpath.TypeManagementService; import org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetails; import org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetailsBuilder; import org.springframework.roo.classpath.details.MemberFindingUtils; import org.springframework.roo.classpath.details.annotations.AnnotationAttributeValue; import org.springframework.roo.classpath.details.annotations.AnnotationMetadata; import org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder; import org.springframework.roo.classpath.details.annotations.BooleanAttributeValue; import org.springframework.roo.metadata.MetadataService; import org.springframework.roo.model.JavaSymbolName; import org.springframework.roo.model.JavaType; import org.springframework.roo.process.manager.FileManager; import org.springframework.roo.project.ProjectOperations; import org.springframework.roo.project.Property; import org.springframework.roo.project.Repository; import org.springframework.roo.support.logging.HandlerUtils; import org.springframework.roo.support.util.XmlUtils; import org.w3c.dom.Element; /** * Implementation of commands that are available via the Roo shell * * @author <a href="http://www.disid.com">DISID Corporation S.L.</a> made for <a * href="http://www.dgti.gva.es">General Directorate for Information * Technologies (DGTI)</a> * @since 0.8 */ @Component @Service public class WebBinderOperationsImpl implements WebBinderOperations { private static final Logger LOGGER = HandlerUtils .getLogger(WebBinderOperationsImpl.class); // ------------ OSGi component attributes ---------------- private BundleContext context; private OperationUtils operationUtils; protected void activate(ComponentContext cContext) { context = cContext.getBundleContext(); } /** * MetadataService offers access to Roo's metadata model, use it to retrieve * any available metadata by its MID */ @Reference private MetadataService metadataService; /** * Use ProjectOperations to install new dependencies, plugins, properties, * etc into the project configuration */ @Reference private ProjectOperations projectOperations; /** * Use TypeLocationService to find types which are annotated with a given * annotation in the project */ @Reference private TypeLocationService typeLocationService; @Reference private FileManager fileManager; @Reference private TypeManagementService typeManagementService; /** {@inheritDoc} */ public boolean isStringTrimmerAvailable() { return projectOperations.isProjectAvailable(projectOperations .getFocusedModuleName()) && getOperationUtils().isSpringMvcProject(metadataService, fileManager, projectOperations); } /** {@inheritDoc} */ public void bindStringTrimmer(JavaType controller, boolean emptyAsNull) { setup(); addBindStringTrimmer(controller, emptyAsNull); } /** {@inheritDoc} */ public void bindStringTrimmerAll(boolean emptyAsNull) { setup(); // Use the TypeLocationService to scan project for all types with a // specific annotation for (JavaType type : typeLocationService .findTypesWithAnnotation(new JavaType( "org.springframework.stereotype.Controller"))) { addBindStringTrimmer(type, emptyAsNull); } } /** * Annotate provided Java type with @GvNIXStringTrimmerBinder * * @param emptyAsNull */ private void addBindStringTrimmer(JavaType controller, boolean emptyAsNull) { // Use Roo's Assert type for null checks Validate.notNull(controller, "Java type required"); // Retrieve the Java source type the annotation is being added to ClassOrInterfaceTypeDetails mutableTypeDetails = typeLocationService .getTypeDetails(controller); // Check if provided JavaType is a @Controller class AnnotationMetadata controllerAnnotation = MemberFindingUtils .getAnnotationOfType(mutableTypeDetails.getAnnotations(), new JavaType( "org.springframework.stereotype.Controller")); if (controllerAnnotation == null) { LOGGER.warning("Java type ".concat(controller.getSimpleTypeName()) .concat(" must be annotated with @Controller")); return; } // Test if the annotation already exists on the target type if (MemberFindingUtils.getAnnotationOfType(mutableTypeDetails .getAnnotations(), new JavaType(GvNIXStringTrimmerBinder.class.getName())) == null) { // Annotation Attributes BooleanAttributeValue bav = new BooleanAttributeValue( new JavaSymbolName("emptyAsNull"), emptyAsNull); List<AnnotationAttributeValue<?>> attributes = new ArrayList<AnnotationAttributeValue<?>>(); attributes.add(bav); // Create JavaType instance for GvNIXStringTrimmerBinder annotation JavaType stringTrimmerBinder = new JavaType( GvNIXStringTrimmerBinder.class.getName()); // Create Annotation metadata AnnotationMetadataBuilder annotationBuilder = new AnnotationMetadataBuilder( stringTrimmerBinder, attributes); // Add annotation to target type and save changes to disk ClassOrInterfaceTypeDetailsBuilder detailsBuilder = new ClassOrInterfaceTypeDetailsBuilder( mutableTypeDetails); detailsBuilder.addAnnotation(annotationBuilder.build()); typeManagementService.createOrUpdateTypeOnDisk(detailsBuilder .build()); } } /** {@inheritDoc} */ public void setup() { Element configuration = XmlUtils.getConfiguration(getClass()); // Add addon repository and dependency to get annotations addAnnotations(configuration); } /** * Add addon repository and dependency to get annotations. * * @param configuration Configuration element */ private void addAnnotations(Element configuration) { // Install the add-on Google code repository and dependency needed to // get the annotations List<Element> repos = XmlUtils.findElements( "/configuration/gvnix/repositories/repository", configuration); for (Element repo : repos) { projectOperations.addRepository(projectOperations .getFocusedModuleName(), new Repository(repo)); } // Install properties List<Element> properties = XmlUtils.findElements( "/configuration/gvnix/properties/*", configuration); for (Element property : properties) { projectOperations.addProperty(projectOperations .getFocusedModuleName(), new Property(property)); } List<Element> depens = XmlUtils.findElements( "/configuration/gvnix/dependencies/dependency", configuration); DependenciesVersionManager.manageDependencyVersion(metadataService, projectOperations, depens); } public OperationUtils getOperationUtils() { if (operationUtils == null) { // Get all Services implement OperationUtils interface try { ServiceReference<?>[] references = this.context .getAllServiceReferences( OperationUtils.class.getName(), null); for (ServiceReference<?> ref : references) { operationUtils = (OperationUtils) this.context .getService(ref); return operationUtils; } return null; } catch (InvalidSyntaxException e) { LOGGER.warning("Cannot load OperationUtils on MonitoringOperationsImpl."); return null; } } else { return operationUtils; } } }