Bug 476691 - Warn when Service-Component used without activation

When a bundle has a Service-Component header, it needs to have a
Bundle-ActivationPolicy: lazy header as well or otherwise Declarative
Services won't load any components automatically.

Add a warning and a quick-fix to be able to resolve such errors if they
occur.

Change-Id: Idb2bd050897d8fd170bc4463f1e3312053341ae9
Signed-off-by: Alex Blewitt <alex.blewitt@gmail.com>
diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/PDECoreMessages.java b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/PDECoreMessages.java
index 4416983..3740507 100644
--- a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/PDECoreMessages.java
+++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/PDECoreMessages.java
@@ -198,6 +198,7 @@
 	public static String BundleErrorReporter_headerMissing;
 	public static String BundleErrorReporter_NoSymbolicName;
 	public static String BundleErrorReporter_illegalManifestVersion;
+	public static String BundleErrorReporter_serviceComponentLazyStart;
 	public static String BundleErrorReporter_ClasspathNotEmpty;
 	public static String BundleErrorReporter_fragmentActivator;
 	public static String BundleErrorReporter_NoExist;
diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/builders/BundleErrorReporter.java b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/builders/BundleErrorReporter.java
index b964131..9ba9b47 100644
--- a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/builders/BundleErrorReporter.java
+++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/builders/BundleErrorReporter.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 IBM Corporation and others.
  * 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
@@ -95,6 +95,7 @@
 		validateEclipseBundleShape();
 		validateEclipseGenericCapability();
 		validateEclipseGenericRequire();
+		validateServiceComponent();
 	}
 
 	private boolean validateBundleManifestVersion() {
@@ -404,6 +405,7 @@
 			return;
 		}
 
+		@SuppressWarnings("deprecation")
 		IHeader header = getHeader(Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT);
 		if (header == null)
 			return;
@@ -1253,4 +1255,20 @@
 			} catch (CoreException e) {
 			}
 	}
-}
\ No newline at end of file
+
+	/**
+	 * Verifies that if a Service-Component exists then a corresponding Bundle-ActivationPolicy is present.
+	 */
+	private void validateServiceComponent() {
+		IHeader header = getHeader(ICoreConstants.SERVICE_COMPONENT);
+		if (header == null) {
+			return;
+		}
+
+		if (getHeader(Constants.BUNDLE_ACTIVATIONPOLICY) != null) {
+			return;
+		}
+
+		report(PDECoreMessages.BundleErrorReporter_serviceComponentLazyStart, header.getLineNumber() + 1, CompilerFlags.WARNING, PDEMarkerFactory.M_SERVICECOMPONENT_MISSING_LAZY, PDEMarkerFactory.CAT_OTHER);
+	}
+}
diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/builders/PDEMarkerFactory.java b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/builders/PDEMarkerFactory.java
index 47bfa15..aeaf449 100644
--- a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/builders/PDEMarkerFactory.java
+++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/builders/PDEMarkerFactory.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 IBM Corporation and others.
  * 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
@@ -64,6 +64,7 @@
 	public static final int M_DISCOURAGED_CLASS = 0x1023; //other problem
 	public static final int M_NO_LINE_TERMINATION = 0x1024; // fatal problem
 	public static final int M_R4_SYNTAX_IN_R3_BUNDLE = 0x1025; // other problem
+	public static final int M_SERVICECOMPONENT_MISSING_LAZY = 0x1026; // other problem
 
 	// build properties fixes
 	public static final int B_APPEND_SLASH_FOLDER_ENTRY = 0x2001;
diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/pderesources.properties b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/pderesources.properties
index f3b181a..46b14ea 100644
--- a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/pderesources.properties
+++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/pderesources.properties
@@ -194,6 +194,7 @@
 BundleErrorReporter_unecessaryDependencyDueToFragmentHost=The ''{0}'' dependency is not necessary as it is already specified in Fragment-Host header
 BundleErrorReporter_localization_properties_file_not_exist=no valid properties files exist in the localization directory specified
 BundleErrorReporter_illegalManifestVersion=The bundle manifest version is invalid. Valid ranges are 1-2.
+BundleErrorReporter_serviceComponentLazyStart=Bundles with a Service-Component should set the Bundle-ActivationPolicy to lazy.
 BundleManifestSourceLocationManager_problemProcessBundleManifestHeaderAttributeMissing=Problem processing bundle manifest header in source bundle {0}, plugin name and version must both be specified.
 BundleValidationOperation_multiple_singletons={0} versions of singleton ''{1}'' exist
 
diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/PDEUIMessages.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/PDEUIMessages.java
index 7ce8998..64aec48 100644
--- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/PDEUIMessages.java
+++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/PDEUIMessages.java
@@ -2382,6 +2382,10 @@
 
 	public static String UpdateActivationResolution_lazyStart_label;
 
+	public static String UpdateActivationResolution_bundleActivationPolicyAdd_desc;
+
+	public static String UpdateActivationResolution_bundleActivationPolicyAdd_label;
+
 	public static String AddSingleon_dir_label;
 
 	public static String AddSingleon_att_label;
diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/correction/AddActivationPolicyResolution.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/correction/AddActivationPolicyResolution.java
new file mode 100644
index 0000000..876d1a2
--- /dev/null
+++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/correction/AddActivationPolicyResolution.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Alex Blewitt and others.
+ * 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:
+ *     Alex Blewitt <alex.blewitt@gmail.com> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.pde.internal.ui.correction;
+
+import org.eclipse.pde.internal.core.ibundle.IBundle;
+import org.eclipse.pde.internal.core.ibundle.IManifestHeader;
+import org.eclipse.pde.internal.core.text.bundle.Bundle;
+import org.eclipse.pde.internal.core.text.bundle.BundleModel;
+import org.eclipse.pde.internal.ui.PDEUIMessages;
+import org.osgi.framework.Constants;
+
+public class AddActivationPolicyResolution extends AbstractManifestMarkerResolution {
+
+	public AddActivationPolicyResolution(int type) {
+		super(type);
+	}
+
+	@Override
+	protected void createChange(BundleModel model) {
+		IBundle bundle = model.getBundle();
+		if (bundle instanceof Bundle) {
+			Bundle bun = (Bundle) bundle;
+			IManifestHeader header = bun.getManifestHeader(Constants.BUNDLE_ACTIVATIONPOLICY);
+			if (header == null) {
+				bundle.setHeader(Constants.BUNDLE_ACTIVATIONPOLICY, Constants.ACTIVATION_LAZY);
+			}
+		}
+	}
+
+	@Override
+	public String getDescription() {
+		return PDEUIMessages.UpdateActivationResolution_bundleActivationPolicyAdd_desc;
+	}
+
+	@Override
+	public String getLabel() {
+		return PDEUIMessages.UpdateActivationResolution_bundleActivationPolicyAdd_label;
+	}
+}
diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/correction/ResolutionGenerator.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/correction/ResolutionGenerator.java
index 443fdcc..b0c1b6a 100644
--- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/correction/ResolutionGenerator.java
+++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/correction/ResolutionGenerator.java
@@ -111,6 +111,9 @@
 				return new IMarkerResolution[] {new NoLineTerminationResolution(AbstractPDEMarkerResolution.REMOVE_TYPE)};
 			case PDEMarkerFactory.M_R4_SYNTAX_IN_R3_BUNDLE :
 				return new IMarkerResolution[] {new AddBundleManifestVersionResolution()};
+		case PDEMarkerFactory.M_SERVICECOMPONENT_MISSING_LAZY:
+			return new IMarkerResolution[] {
+					new AddActivationPolicyResolution(AbstractPDEMarkerResolution.CREATE_TYPE) };
 		}
 		return NO_RESOLUTIONS;
 	}
diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/pderesources.properties b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/pderesources.properties
index 28be78e..62a1ae9 100644
--- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/pderesources.properties
+++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/pderesources.properties
@@ -1574,6 +1574,8 @@
 UpdateActivationResolution_bundleActivationPolicy_label=Convert to Bundle-ActivationPolicy
 UpdateActivationResolution_lazyStart_desc=Rename the deprecated Eclipse-AutoStart to Eclipse-LazyStart.  The semantics of the header remain the same.
 UpdateActivationResolution_lazyStart_label=rename to Eclipse-LazyStart
+UpdateActivationResolution_bundleActivationPolicyAdd_desc=Add the ''Bundle-ActivationPolicy: lazy'' header to enable components to be loaded by declarative services
+UpdateActivationResolution_bundleActivationPolicyAdd_label=Add Bundle-ActivationPolicy: lazy
 
 ######### Category Editor ####################################
 CategoryPage_header = Category Definition