/******************************************************************************* * Copyright (c) 2012 VMware, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VMware, Inc. - initial API and implementation *******************************************************************************/ package org.springframework.ide.eclipse.internal.bestpractices.springiderules; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Status; import org.springframework.ide.eclipse.beans.core.model.IBean; import org.springframework.ide.eclipse.beans.core.model.validation.IBeansValidationContext; import org.springframework.ide.eclipse.bestpractices.BestPracticesPluginConstants; import org.springframework.ide.eclipse.core.model.IModelElement; import org.springframework.ide.eclipse.core.model.validation.IValidationContext; import org.springframework.ide.eclipse.core.model.validation.IValidationRule; import org.springsource.ide.eclipse.commons.core.StatusHandler; /** * This rule checks for cases where legacy XML syntax is used when there is * dedicated namespace syntax available. * Legacy namespace usage is detected by looking for the fully qualified class * name in the XML * @author Wesley Coelho * @author Christian Dupuis * @author Leo Dos Santos */ public class UseDedicatedNamespacesRule implements IValidationRule<IBean, IBeansValidationContext> { public static final String RULE_ID = "legacyxmlusage"; /** * Map of fully qualified class names to the message indicating that there * is a namespace that can be used instead of the bean definition specifying * that class. * */ private static Map<String, String> legacyXmlUsageMap = new HashMap<String, String>(); static { // JEE legacyXmlUsageMap.put("org.springframework.jndi.JndiObjectFactoryBean", "Consider using namespace syntax, e.g. <jee:jndi-lookup id=\"myId\" jndi-name=\"jdbc/MyDataSource\"/>"); legacyXmlUsageMap .put( "org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean", "Consider using namespace syntax, e.g. <jee:local-slsb id=\"simpleSlsb\" jndi-name=\"ejb/RentalServiceBean\" business-interface=\"com.foo.service.RentalService\"/>"); legacyXmlUsageMap .put( "org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean", "<jee:remote-slsb id=\"complexRemoteEjb\" jndi-name=\"ejb/MyRemoteBean\" business-interface=\"com.foo.service.RentalService\" ..."); // Util legacyXmlUsageMap.put("org.springframework.beans.factory.config.ListFactoryBean", "Consider using namespace syntax, e.g. <util:list id=\"myListId\"> <value>myValue1</value> ..."); legacyXmlUsageMap.put("org.springframework.beans.factory.config.SetFactoryBean", "Consider using namespace syntax, e.g. <util:set id=\"mySetId\"> <value>myValue1</value> ..."); legacyXmlUsageMap .put("org.springframework.beans.factory.config.MapFactoryBean", "Consider using namespace syntax, e.g. <util:map id=\"myMapId\"> <entry key=\"myKey\" value=\"myValue\"/> ..."); legacyXmlUsageMap .put("org.springframework.beans.factory.config.FieldRetrievingFactoryBean", "Consider using namespace syntax, e.g. <util:constant static-field=\"com.mydomain.MyClass.MY_CONSTANT\"/>"); // Transactions legacyXmlUsageMap .put("org.springframework.transaction.interceptor.TransactionInterceptor", "Consider using namespace syntax, e.g. <tx:advice id=\"txAdvice\" transaction-manager=\"txManager\" ..."); legacyXmlUsageMap.put("org.springframework.transaction.annotation.AnnotationTransactionAttributeSource", "Consider using namespace syntax, e.g. <tx:annotation-driven transaction-manager=\"txManager\" ..."); legacyXmlUsageMap.put("org.springframework.transaction.jta.JtaTransactionManager", "Consider using namespace syntax, e.g. <tx:jta-transaction-manager/>"); legacyXmlUsageMap .put( "org.springframework.transaction.jta.OC4JJtaTransactionManager", "Consider using namespace syntax instead of referencing OC4JJtaTransactionManager directly, e.g. <tx:jta-transaction-manager/>"); legacyXmlUsageMap .put( "org.springframework.transaction.jta.WebLogicJtaTransactionManager", "Consider using namespace syntax instead of referencing WebLogicJtaTransactionManager directly, e.g. <tx:jta-transaction-manager/>"); legacyXmlUsageMap .put( "org.springframework.transaction.jta.WebSphereUowTransactionManager", "Consider using namespace syntax instead of referencing WebSphereUowTransactionManager directly, e.g. <tx:jta-transaction-manager/>"); // Context legacyXmlUsageMap.put("org.springframework.beans.factory.config.PropertyPlaceholderConfigurer", "Consider using namespace syntax, e.g. <context:property-placeholder ..."); } /** * Returns <code>true</code> if this rule is able to validate the given * {@link IModelElement} with the specified {@link IValidationContext}. */ public boolean supports(IModelElement element, IValidationContext context) { return element instanceof IBean; } public void validate(IBean bean, IBeansValidationContext validationContext, IProgressMonitor progressMonitor) { String infoMessage = legacyXmlUsageMap.get(bean.getClassName()); if (infoMessage != null) { try { if (bean.getElementResource() != null && bean.getElementResource().isAccessible()) { String path = bean.getElementResource().getLocation().toString(); String beanDefinition = RuleUtil.getFileLines(path, bean.getElementStartLine(), bean .getElementEndLine()); if (beanDefinition.indexOf(bean.getClassName()) > 0) { validationContext.info(bean, RULE_ID + ":" + bean.getClassName(), infoMessage); } } } catch (IOException e) { StatusHandler.log(new Status(Status.ERROR, BestPracticesPluginConstants.PLUGIN_ID, "Could not read bean XML", e)); } } } }