Bug 307562 - Java EE 6 CDI support is needed for JSF 2.0 EE 6 web applications
diff --git a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/jsfappconfig/AnnotationJSFAppConfigProvider.java b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/jsfappconfig/AnnotationJSFAppConfigProvider.java
index 99bb956..92af67f 100644
--- a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/jsfappconfig/AnnotationJSFAppConfigProvider.java
+++ b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/jsfappconfig/AnnotationJSFAppConfigProvider.java
@@ -48,12 +48,20 @@
     static final String FACES_RENDERER_ANNOTATION_CLASS = "javax.faces.render.FacesRenderer"; //$NON-NLS-1$
     static final String FACES_VALIDATOR_ANNOTATION_CLASS = "javax.faces.validator.FacesValidator"; //$NON-NLS-1$
     
-    static final String VIEW_SCOPED_ANNOTATION_CLASS = "javax.faces.bean.ViewScoped"; //$NON-NLS-1$
-    static final String APPLICATION_SCOPED_ANNOTATION_CLASS = "javax.faces.bean.ApplicationScoped"; //$NON-NLS-1$
     static final String NONE_SCOPED_ANNOTATION_CLASS = "javax.faces.bean.NoneScoped"; //$NON-NLS-1$
+    static final String VIEW_SCOPED_ANNOTATION_CLASS = "javax.faces.bean.ViewScoped"; //$NON-NLS-1$
     static final String SESSION_SCOPED_ANNOTATION_CLASS = "javax.faces.bean.SessionScoped"; //$NON-NLS-1$
+    static final String APPLICATION_SCOPED_ANNOTATION_CLASS = "javax.faces.bean.ApplicationScoped"; //$NON-NLS-1$
     static final String CUSTOM_SCOPED_ANNOTATION_CLASS = "javax.faces.bean.CustomScoped";  //$NON-NLS-1$
 
+    static final String CDI_NAMED_BEAN_ANNOTATION_CLASS = "javax.inject.Named"; //$NON-NLS-1$
+    static final String CDI_MODEL_BEAN_ANNOTATION_CLASS = "javax.enterprise.inject.Model"; //$NON-NLS-1$
+
+    static final String CDI_REQUEST_SCOPED_ANNOTATION_CLASS = "javax.enterprise.context.RequestScoped"; //$NON-NLS-1$
+    static final String CDI_CONVERSATION_SCOPED_ANNOTATION_CLASS = "javax.enterprise.context.ConversationScoped"; //$NON-NLS-1$
+    static final String CDI_SESSION_SCOPED_ANNOTATION_CLASS = "javax.enterprise.context.SessionScoped"; //$NON-NLS-1$
+    static final String CDI_APPLICATION_SCOPED_ANNOTATION_CLASS = "javax.enterprise.context.ApplicationScoped"; //$NON-NLS-1$
+
     /**
      * Cached {@link FacesConfigType} instance.
      */
@@ -109,6 +117,8 @@
         pattern = orPattern(pattern, jProject.findType(FACES_CONVERTER_ANNOTATION_CLASS));
         pattern = orPattern(pattern, jProject.findType(FACES_RENDERER_ANNOTATION_CLASS));
         pattern = orPattern(pattern, jProject.findType(FACES_VALIDATOR_ANNOTATION_CLASS));
+        pattern = orPattern(pattern, jProject.findType(CDI_NAMED_BEAN_ANNOTATION_CLASS));
+        pattern = orPattern(pattern, jProject.findType(CDI_MODEL_BEAN_ANNOTATION_CLASS));
 
         if (pattern != null) {
             SearchEngine engine = new SearchEngine();
diff --git a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/jsfappconfig/AnnotationSearchRequestor.java b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/jsfappconfig/AnnotationSearchRequestor.java
index f015b7f..79f3889 100644
--- a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/jsfappconfig/AnnotationSearchRequestor.java
+++ b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/jsfappconfig/AnnotationSearchRequestor.java
@@ -17,12 +17,21 @@
 import static org.eclipse.jst.jsf.core.jsfappconfig.AnnotationJSFAppConfigProvider.FACES_CONVERTER_ANNOTATION_CLASS;
 import static org.eclipse.jst.jsf.core.jsfappconfig.AnnotationJSFAppConfigProvider.FACES_RENDERER_ANNOTATION_CLASS;
 import static org.eclipse.jst.jsf.core.jsfappconfig.AnnotationJSFAppConfigProvider.FACES_VALIDATOR_ANNOTATION_CLASS;
-import static org.eclipse.jst.jsf.core.jsfappconfig.AnnotationJSFAppConfigProvider.VIEW_SCOPED_ANNOTATION_CLASS;
-import static org.eclipse.jst.jsf.core.jsfappconfig.AnnotationJSFAppConfigProvider.APPLICATION_SCOPED_ANNOTATION_CLASS;
+
 import static org.eclipse.jst.jsf.core.jsfappconfig.AnnotationJSFAppConfigProvider.NONE_SCOPED_ANNOTATION_CLASS;
+import static org.eclipse.jst.jsf.core.jsfappconfig.AnnotationJSFAppConfigProvider.VIEW_SCOPED_ANNOTATION_CLASS;
 import static org.eclipse.jst.jsf.core.jsfappconfig.AnnotationJSFAppConfigProvider.SESSION_SCOPED_ANNOTATION_CLASS;
+import static org.eclipse.jst.jsf.core.jsfappconfig.AnnotationJSFAppConfigProvider.APPLICATION_SCOPED_ANNOTATION_CLASS;
 import static org.eclipse.jst.jsf.core.jsfappconfig.AnnotationJSFAppConfigProvider.CUSTOM_SCOPED_ANNOTATION_CLASS;
 
+import static org.eclipse.jst.jsf.core.jsfappconfig.AnnotationJSFAppConfigProvider.CDI_NAMED_BEAN_ANNOTATION_CLASS;
+import static org.eclipse.jst.jsf.core.jsfappconfig.AnnotationJSFAppConfigProvider.CDI_MODEL_BEAN_ANNOTATION_CLASS;
+
+import static org.eclipse.jst.jsf.core.jsfappconfig.AnnotationJSFAppConfigProvider.CDI_REQUEST_SCOPED_ANNOTATION_CLASS;
+import static org.eclipse.jst.jsf.core.jsfappconfig.AnnotationJSFAppConfigProvider.CDI_CONVERSATION_SCOPED_ANNOTATION_CLASS;
+import static org.eclipse.jst.jsf.core.jsfappconfig.AnnotationJSFAppConfigProvider.CDI_SESSION_SCOPED_ANNOTATION_CLASS;
+import static org.eclipse.jst.jsf.core.jsfappconfig.AnnotationJSFAppConfigProvider.CDI_APPLICATION_SCOPED_ANNOTATION_CLASS;
+
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.emf.common.util.EList;
 import org.eclipse.jdt.core.IAnnotation;
@@ -97,7 +106,11 @@
                                     addRenderer(annotations[i], type);
                                 } else if (FACES_VALIDATOR_ANNOTATION_CLASS.equals(resolvedAnnotationClassName)) {
                                     addValidator(annotations[i], type);
-                                }               
+                                } else if (CDI_NAMED_BEAN_ANNOTATION_CLASS.equals(resolvedAnnotationClassName)) {
+                                	addCDINamedBean(annotations[i], type);
+                                } else if (CDI_MODEL_BEAN_ANNOTATION_CLASS.equals(resolvedAnnotationClassName)) {
+                                	addCDIModelBean(type);
+                                }
                             }
                         }
                     }
@@ -168,14 +181,14 @@
                     String[][] resolvedAnnotationTypes = beanType.resolveType(annotationType);
                     if (resolvedAnnotationTypes != null) {
                         String resolvedAnnotationClassName = new StringBuffer(resolvedAnnotationTypes[0][0]).append('.').append(resolvedAnnotationTypes[0][1]).toString();
-                        if (APPLICATION_SCOPED_ANNOTATION_CLASS.equals(resolvedAnnotationClassName)) {
-                        	beanScopeString = "application"; //$NON-NLS-1$
+                        if (NONE_SCOPED_ANNOTATION_CLASS.equals(resolvedAnnotationClassName)) {
+                        	beanScopeString = "none"; //$NON-NLS-1$
                         } else if (VIEW_SCOPED_ANNOTATION_CLASS.equals(resolvedAnnotationClassName)) {
                         	beanScopeString = "view"; //$NON-NLS-1$
-                        } else if (NONE_SCOPED_ANNOTATION_CLASS.equals(resolvedAnnotationClassName)) {
-                        	beanScopeString = "none"; //$NON-NLS-1$
                         } else if (SESSION_SCOPED_ANNOTATION_CLASS.equals(resolvedAnnotationClassName)) {
                         	beanScopeString = "session"; //$NON-NLS-1$
+                        } else if (APPLICATION_SCOPED_ANNOTATION_CLASS.equals(resolvedAnnotationClassName)) {
+                        	beanScopeString = "application"; //$NON-NLS-1$
                         } else if (CUSTOM_SCOPED_ANNOTATION_CLASS.equals(resolvedAnnotationClassName)) {
                             IMemberValuePair[] scopePairs = annotations[i].getMemberValuePairs();
                             if (scopePairs != null && scopePairs.length == 1 && scopePairs[0].getValueKind() == IMemberValuePair.K_STRING) {
@@ -199,6 +212,7 @@
             beanScope.setTextContent(beanScopeString);
             bean.setManagedBeanScope(beanScope);
             bean.setEager(isBeanEager.booleanValue());
+            JSFAppConfigUtils.setManagedBeanSource(bean, JSFAppConfigUtils.MANAGEDBEAN_SOURCE_JSF_ANNOTATION);
             facesConfig.getManagedBean().add(bean);
         }
     }
@@ -357,4 +371,113 @@
             facesConfig.getComponent().add(component);
         }
     }
+
+    private void addCDINamedBean(IAnnotation beanAnnotation, IType beanType) throws JavaModelException {
+        IMemberValuePair[] pairs = beanAnnotation.getMemberValuePairs();
+
+        String beanNameString = null;
+        if (pairs != null) {
+            for (IMemberValuePair pair : pairs) {
+                if ("value".equals(pair.getMemberName()) && pair.getValueKind() == IMemberValuePair.K_STRING) { //$NON-NLS-1$
+                    beanNameString = (String)pair.getValue();
+                }
+            }
+        }
+        if (beanNameString == null || beanNameString.length() < 1) {
+            beanNameString = beanType.getElementName();
+            if (beanNameString != null && beanNameString.length() > 0) {
+                StringBuffer casedName = new StringBuffer(String.valueOf(beanNameString.charAt(0)).toLowerCase());
+                beanNameString = casedName.append(beanNameString.substring(1)).toString();
+            }
+        }
+
+        String beanClassName = beanType.getFullyQualifiedName();
+
+        String beanScopeString = "dependent"; //$NON-NLS-1$
+        IAnnotation[] annotations = beanType.getAnnotations();
+        if (annotations != null) {
+	        for (int i = 0, k = annotations.length; i < k; i++) {
+                if (annotations[i].exists()) {
+                    String annotationType = annotations[i].getElementName();
+                    String[][] resolvedAnnotationTypes = beanType.resolveType(annotationType);
+                    if (resolvedAnnotationTypes != null) {
+                        String resolvedAnnotationClassName = new StringBuffer(resolvedAnnotationTypes[0][0]).append('.').append(resolvedAnnotationTypes[0][1]).toString();
+                        if (CDI_REQUEST_SCOPED_ANNOTATION_CLASS.equals(resolvedAnnotationClassName)) {
+                        	beanScopeString = "request"; //$NON-NLS-1$
+                        } else if (CDI_CONVERSATION_SCOPED_ANNOTATION_CLASS.equals(resolvedAnnotationClassName)) {
+                        	beanScopeString = "conversation"; //$NON-NLS-1$
+                        } else if (CDI_SESSION_SCOPED_ANNOTATION_CLASS.equals(resolvedAnnotationClassName)) {
+                        	beanScopeString = "session"; //$NON-NLS-1$
+                        } else if (CDI_APPLICATION_SCOPED_ANNOTATION_CLASS.equals(resolvedAnnotationClassName)) {
+                        	beanScopeString = "application"; //$NON-NLS-1$
+                        }
+                    }
+                }
+	        }
+        }
+
+        if (beanNameString != null && beanClassName != null) {
+            ManagedBeanType bean = FacesConfigFactory.eINSTANCE.createManagedBeanType();
+            ManagedBeanNameType beanName = FacesConfigFactory.eINSTANCE.createManagedBeanNameType();
+            beanName.setTextContent(beanNameString);
+            bean.setManagedBeanName(beanName);
+            ManagedBeanClassType beanClass = FacesConfigFactory.eINSTANCE.createManagedBeanClassType();
+            beanClass.setTextContent(beanClassName);
+            bean.setManagedBeanClass(beanClass);
+            ManagedBeanScopeType beanScope = FacesConfigFactory.eINSTANCE.createManagedBeanScopeType();
+            beanScope.setTextContent(beanScopeString);
+            bean.setManagedBeanScope(beanScope);
+            bean.setEager(false);
+            JSFAppConfigUtils.setManagedBeanSource(bean, JSFAppConfigUtils.MANAGEDBEAN_SOURCE_CDI_ANNOTATION);
+            facesConfig.getManagedBean().add(bean);
+        }
+    }
+
+    private void addCDIModelBean(IType beanType) throws JavaModelException {
+        String beanNameString = beanType.getElementName();
+        if (beanNameString != null && beanNameString.length() > 0) {
+            StringBuffer casedName = new StringBuffer(String.valueOf(beanNameString.charAt(0)).toLowerCase());
+            beanNameString = casedName.append(beanNameString.substring(1)).toString();
+        }
+
+        String beanClassName = beanType.getFullyQualifiedName();
+
+        String beanScopeString = "request"; //$NON-NLS-1$
+        IAnnotation[] annotations = beanType.getAnnotations();
+        if (annotations != null) {
+	        for (int i = 0, k = annotations.length; i < k; i++) {
+                if (annotations[i].exists()) {
+                    String annotationType = annotations[i].getElementName();
+                    String[][] resolvedAnnotationTypes = beanType.resolveType(annotationType);
+                    if (resolvedAnnotationTypes != null) {
+                        String resolvedAnnotationClassName = new StringBuffer(resolvedAnnotationTypes[0][0]).append('.').append(resolvedAnnotationTypes[0][1]).toString();
+                        if (CDI_CONVERSATION_SCOPED_ANNOTATION_CLASS.equals(resolvedAnnotationClassName)) {
+                        	beanScopeString = "conversation"; //$NON-NLS-1$
+                        } else if (CDI_SESSION_SCOPED_ANNOTATION_CLASS.equals(resolvedAnnotationClassName)) {
+                        	beanScopeString = "session"; //$NON-NLS-1$
+                        } else if (CDI_APPLICATION_SCOPED_ANNOTATION_CLASS.equals(resolvedAnnotationClassName)) {
+                        	beanScopeString = "application"; //$NON-NLS-1$
+                        }
+                    }
+                }
+	        }
+        }
+
+        if (beanNameString != null && beanClassName != null) {
+            ManagedBeanType bean = FacesConfigFactory.eINSTANCE.createManagedBeanType();
+            ManagedBeanNameType beanName = FacesConfigFactory.eINSTANCE.createManagedBeanNameType();
+            beanName.setTextContent(beanNameString);
+            bean.setManagedBeanName(beanName);
+            ManagedBeanClassType beanClass = FacesConfigFactory.eINSTANCE.createManagedBeanClassType();
+            beanClass.setTextContent(beanClassName);
+            bean.setManagedBeanClass(beanClass);
+            ManagedBeanScopeType beanScope = FacesConfigFactory.eINSTANCE.createManagedBeanScopeType();
+            beanScope.setTextContent(beanScopeString);
+            bean.setManagedBeanScope(beanScope);
+            bean.setEager(false);
+            JSFAppConfigUtils.setManagedBeanSource(bean, JSFAppConfigUtils.MANAGEDBEAN_SOURCE_CDI_ANNOTATION);
+            facesConfig.getManagedBean().add(bean);
+        }
+    }
+
 }
\ No newline at end of file
diff --git a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/jsfappconfig/JSFAppConfigUtils.java b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/jsfappconfig/JSFAppConfigUtils.java
index 73c8004..43b0455 100644
--- a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/jsfappconfig/JSFAppConfigUtils.java
+++ b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/core/jsfappconfig/JSFAppConfigUtils.java
@@ -52,6 +52,9 @@
 import org.eclipse.jst.jsf.core.IJSFCoreConstants;
 import org.eclipse.jst.jsf.core.internal.JSFCorePlugin;
 import org.eclipse.jst.jsf.core.internal.Messages;
+import org.eclipse.jst.jsf.facesconfig.emf.FacesConfigFactory;
+import org.eclipse.jst.jsf.facesconfig.emf.ManagedBeanExtensionType;
+import org.eclipse.jst.jsf.facesconfig.emf.ManagedBeanType;
 import org.eclipse.osgi.util.NLS;
 import org.eclipse.wst.common.componentcore.resources.IVirtualFolder;
 import org.eclipse.wst.common.project.facet.core.IFacetedProject;
@@ -79,6 +82,14 @@
 	 */
 	public static final String FACES_CONFIG_IN_JAR_PATH = "META-INF/faces-config.xml"; //$NON-NLS-1$
 
+	/** ID of managed bean's description instance to indicate content identifies bean's "source" **/ 
+	public static final String MANAGEDBEAN_SOURCE_ID = "MANAGEDBEAN_SOURCE_ID"; //$NON-NLS-1$
+	/** Indicates that a managed bean was defined in a faces-config file **/
+	public static final String MANAGEDBEAN_SOURCE_FACES_CONFIG_FILE = "FACES_CONFIG_FILE"; //$NON-NLS-1$
+	/** Indicates that a managed bean was defined by a JSF annotation **/
+	public static final String MANAGEDBEAN_SOURCE_JSF_ANNOTATION = "JSF_ANNOTATION"; //$NON-NLS-1$
+	/** Indicates that a managed bean was defined by a CDI annotation **/
+	public static final String MANAGEDBEAN_SOURCE_CDI_ANNOTATION = "CDI_ANNOTATION"; //$NON-NLS-1$
     
     /**
      * @param project
@@ -402,6 +413,116 @@
 		return files;
 	}
 
+	/**
+	 * Sets the "source" (one of the MANAGEDBEAN_SOURCE_* constants) of the managed bean.
+	 * @param managedBean Managed bean instance.
+	 * @param source "Source" of the managed bean.
+	 */
+	public static void setManagedBeanSource(final ManagedBeanType managedBean, final String source) {
+		if (managedBean != null) {
+			ManagedBeanExtensionType extension = getManagedBeanSourceExtension(managedBean);
+			if (extension == null) {
+				extension = FacesConfigFactory.eINSTANCE.createManagedBeanExtensionType();
+				extension.setId(MANAGEDBEAN_SOURCE_ID);
+				managedBean.getManagedBeanExtension().add(extension);
+			}
+			final String content = extension.getTextContent();
+			if (content != null) {
+				if (!content.trim().equals(source)) {
+					extension.setTextContent(source);
+				}
+			} else {
+				extension.setTextContent(source);
+			}
+		}
+	}
+
+	/**
+	 * Gets the "source" (one of the MANAGEDBEAN_SOURCE_* constants) of the managed bean.
+	 * @param managedBean Managed bean instance.
+	 * @return "Source" of the managed bean (assumes MANAGEDBEAN_SOURCE_FACES_CONFIG_FILE if not
+	 * set on the managed bean).
+	 */
+	public static String getManagedBeanSource(final ManagedBeanType managedBean) {
+		String source = MANAGEDBEAN_SOURCE_FACES_CONFIG_FILE;
+		final ManagedBeanExtensionType extension = getManagedBeanSourceExtension(managedBean);
+		if (extension != null) {
+			source = extension.getTextContent().trim();
+		}
+		return source;
+	}
+
+	/**
+	 * Gets the managed bean instance's extension object that has ID of MANAGEDBEAN_SOURCE_ID.
+	 * @param managedBean Managed bean instance.
+	 * @return The managed bean's extension object that has ID of MANAGEDBEAN_SOURCE_ID.
+	 */
+	public static ManagedBeanExtensionType getManagedBeanSourceExtension(final ManagedBeanType managedBean) {
+		ManagedBeanExtensionType extension = null;
+		if (managedBean != null) {
+			final EList extensions = managedBean.getManagedBeanExtension();
+			for (final Object curExtObj: extensions) {
+				if (curExtObj instanceof ManagedBeanExtensionType) {
+					final ManagedBeanExtensionType curExt = (ManagedBeanExtensionType) curExtObj;
+					final String id = curExt.getId();
+					if (id != null && id.equals(MANAGEDBEAN_SOURCE_ID)) {
+						extension = curExt;
+						break;
+					}
+				}
+			}
+		}
+		return extension;
+	}
+
+	/**
+	 * Returns <code>true</code> if the managed bean is defined in a faces-config file.
+	 * @param managedBean Managed bean instance to test.
+	 * @return <code>true</code> if the managed bean is defined in a faces-config file, else
+	 * <code>false</code>.
+	 */
+	public static boolean isDefinedInFacesConfigFile(final ManagedBeanType managedBean) {
+		boolean ret = false;
+		if (managedBean != null) {
+			ret = !isDefinedByJSFAnnotation(managedBean) && !isDefinedByCDIAnnotation(managedBean);
+		}
+		return ret;
+	}
+
+	/**
+	 * Returns <code>true</code> if the managed bean is defined by a JSF annotation.
+	 * @param managedBean Managed bean instance to test.
+	 * @return <code>true</code> if the managed bean is defined by a JSF annotation, else
+	 * <code>false</code>.
+	 */
+	public static boolean isDefinedByJSFAnnotation(final ManagedBeanType managedBean) {
+		boolean ret = false;
+		if (managedBean != null) {
+			final String source = getManagedBeanSource(managedBean);
+			if (source != null && source.equals(MANAGEDBEAN_SOURCE_JSF_ANNOTATION)) {
+				ret = true;
+			}
+		}
+		return ret;
+	}
+
+	/**
+	 * Returns <code>true</code> if the managed bean is defined by a CDI annotation.
+	 * @param managedBean Managed bean instance to test.
+	 * @return <code>true</code> if the managed bean is defined by a CDI annotation, else
+	 * <code>false</code>.
+	 */
+	public static boolean isDefinedByCDIAnnotation(final ManagedBeanType managedBean) {
+		boolean ret = false;
+		if (managedBean != null) {
+			final String source = getManagedBeanSource(managedBean);
+			if (source != null && source.equals(MANAGEDBEAN_SOURCE_CDI_ANNOTATION)) {
+				ret = true;
+			}
+		}
+		return ret;
+	}
+
 
 
 	class ImplicitNavigationResourceProxyVisitor implements IResourceProxyVisitor {
diff --git a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/designtime/symbols/DefaultBeanSymbolSourceProvider.java b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/designtime/symbols/DefaultBeanSymbolSourceProvider.java
index 5464d49..61ee51d 100644
--- a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/designtime/symbols/DefaultBeanSymbolSourceProvider.java
+++ b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/designtime/symbols/DefaultBeanSymbolSourceProvider.java
@@ -224,7 +224,7 @@
         {
             additionalInfo.append("<p><b>"); //$NON-NLS-1$
             additionalInfo.append(Messages.getString("DefaultBeanSymbolSourceProvider.AdditionalInformation.Description")); //$NON-NLS-1$
-            additionalInfo.append("</b>"); //$NON-NLS-1$
+            additionalInfo.append(" </b>"); //$NON-NLS-1$
             additionalInfo.append(descBuffer);
             additionalInfo.append("</p>"); //$NON-NLS-1$
         }