Initial check-in of a DS builder.
Error reporting is intended to be extensible using EMF Validation.
This bundle may one day be merged with org.eclipse.pde.ds...
diff --git a/modeling/plugins/org.eclipse.pde.ds.builder/.classpath b/modeling/plugins/org.eclipse.pde.ds.builder/.classpath
new file mode 100644
index 0000000..ad32c83
--- /dev/null
+++ b/modeling/plugins/org.eclipse.pde.ds.builder/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/modeling/plugins/org.eclipse.pde.ds.builder/.project b/modeling/plugins/org.eclipse.pde.ds.builder/.project
new file mode 100644
index 0000000..1e877e8
--- /dev/null
+++ b/modeling/plugins/org.eclipse.pde.ds.builder/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.pde.ds.builder</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/modeling/plugins/org.eclipse.pde.ds.builder/.settings/org.eclipse.core.resources.prefs b/modeling/plugins/org.eclipse.pde.ds.builder/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..c397d82
--- /dev/null
+++ b/modeling/plugins/org.eclipse.pde.ds.builder/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,4 @@
+#Fri Feb 13 20:59:04 CET 2009
+eclipse.preferences.version=1
+encoding//model/scr-1.1.ecorediag=UTF-8
+encoding/<project>=ISO-8859-1
diff --git a/modeling/plugins/org.eclipse.pde.ds.builder/.settings/org.eclipse.jdt.core.prefs b/modeling/plugins/org.eclipse.pde.ds.builder/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..8d63816
--- /dev/null
+++ b/modeling/plugins/org.eclipse.pde.ds.builder/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,12 @@
+#Wed Feb 04 21:58:11 CET 2009
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/modeling/plugins/org.eclipse.pde.ds.builder/.settings/org.eclipse.jdt.ui.prefs b/modeling/plugins/org.eclipse.pde.ds.builder/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..d1ba458
--- /dev/null
+++ b/modeling/plugins/org.eclipse.pde.ds.builder/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,60 @@
+#Sun Jun 28 23:45:10 CEST 2009
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_core
+formatter_settings_version=11
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=;
+org.eclipse.jdt.ui.ondemandthreshold=3
+org.eclipse.jdt.ui.staticondemandthreshold=99
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.make_local_variable_final=false
+sp_cleanup.make_parameters_final=false
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=false
+sp_cleanup.organize_imports=true
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_trailing_whitespaces=false
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=false
+sp_cleanup.remove_unused_imports=false
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=false
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=false
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
diff --git a/modeling/plugins/org.eclipse.pde.ds.builder/.settings/org.eclipse.pde.core.prefs b/modeling/plugins/org.eclipse.pde.ds.builder/.settings/org.eclipse.pde.core.prefs
new file mode 100644
index 0000000..bf5ddf9
--- /dev/null
+++ b/modeling/plugins/org.eclipse.pde.ds.builder/.settings/org.eclipse.pde.core.prefs
@@ -0,0 +1,3 @@
+#Wed Jul 01 17:32:55 CEST 2009
+eclipse.preferences.version=1
+resolve.requirebundle=false
diff --git a/modeling/plugins/org.eclipse.pde.ds.builder/.settings/org.eclipse.pde.prefs b/modeling/plugins/org.eclipse.pde.ds.builder/.settings/org.eclipse.pde.prefs
new file mode 100644
index 0000000..3a83987
--- /dev/null
+++ b/modeling/plugins/org.eclipse.pde.ds.builder/.settings/org.eclipse.pde.prefs
@@ -0,0 +1,13 @@
+#Wed Mar 29 03:57:21 EST 2006
+compilers.p.build=1
+compilers.p.deprecated=1
+compilers.p.no-required-att=0
+compilers.p.not-externalized-att=1
+compilers.p.unknown-attribute=1
+compilers.p.unknown-class=1
+compilers.p.unknown-element=1
+compilers.p.unknown-resource=1
+compilers.p.unresolved-ex-points=0
+compilers.p.unresolved-import=0
+compilers.use-project=true
+eclipse.preferences.version=1
diff --git a/modeling/plugins/org.eclipse.pde.ds.builder/META-INF/MANIFEST.MF b/modeling/plugins/org.eclipse.pde.ds.builder/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..34058ea
--- /dev/null
+++ b/modeling/plugins/org.eclipse.pde.ds.builder/META-INF/MANIFEST.MF
@@ -0,0 +1,13 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.pde.ds.builder;singleton:=true
+Bundle-Version: 0.1.0.qualifier
+Bundle-Activator: org.eclipse.pde.ds.builder.internal.Activator
+Require-Bundle: org.eclipse.emf.transaction;bundle-version="1.3.0"
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Import-Package: org.eclipse.jdt.core,
+ org.eclipse.pde.core.plugin
diff --git a/modeling/plugins/org.eclipse.pde.ds.builder/build.properties b/modeling/plugins/org.eclipse.pde.ds.builder/build.properties
new file mode 100644
index 0000000..c3cc651
--- /dev/null
+++ b/modeling/plugins/org.eclipse.pde.ds.builder/build.properties
@@ -0,0 +1,9 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               plugin.xml,\
+               plugin.properties
+additional.bundles = org.eclipse.pde.core,\
+                     org.eclipse.jdt.core,\
+                     org.eclipse.pde.ds.edit
diff --git a/modeling/plugins/org.eclipse.pde.ds.builder/plugin.properties b/modeling/plugins/org.eclipse.pde.ds.builder/plugin.properties
new file mode 100644
index 0000000..fe54dc6
--- /dev/null
+++ b/modeling/plugins/org.eclipse.pde.ds.builder/plugin.properties
@@ -0,0 +1,14 @@
+# Copyright (c) 2009 Anyware Technologies 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:
+#     Anyware Technologies - initial API and implementation
+#
+# $Id: plugin.properties,v 1.2 2009/02/15 00:42:42 bcabe Exp $
+
+pluginName = Declarative Services Builder
+providerName = Eclipse.org
+
diff --git a/modeling/plugins/org.eclipse.pde.ds.builder/plugin.xml b/modeling/plugins/org.eclipse.pde.ds.builder/plugin.xml
new file mode 100644
index 0000000..83000b7
--- /dev/null
+++ b/modeling/plugins/org.eclipse.pde.ds.builder/plugin.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+   <extension
+         id="scrBuilder"
+         name="Scr Model Validator"
+         point="org.eclipse.core.resources.builders">
+      <builder
+            isConfigurable="true">
+         <run
+               class="org.eclipse.pde.ds.builder.internal.validation.ScrBuilder">
+         </run>
+      </builder>
+   </extension>
+   <extension
+         point="org.eclipse.emf.validation.constraintProviders">
+      <category
+            id="org.eclipse.pde.ds.builder.validation"
+            mandatory="true"
+            name="Declarative Services Validation">
+      </category>
+      <constraintProvider
+            cache="true"
+            mode="Batch">
+         <package
+               namespaceUri="http://www.osgi.org/xmlns/scr/v1.1.0">
+         </package>
+         <constraints
+               categories="org.eclipse.pde.ds.builder.validation">
+            <constraint
+                  class="org.eclipse.pde.ds.builder.internal.validation.constraints.ComponentImplementationTypeIsOnClasspath"
+                  id="org.eclipse.pde.ds.builder.constraintComponentMethodsAreValidAndAccessible"
+                  lang="Java"
+                  mode="Batch"
+                  name="Components methods validation"
+                  severity="ERROR"
+                  statusCode="2">
+               <message>
+                  {0} method can't be found
+               </message>
+               <target
+                     class="Component">
+               </target>
+            </constraint>
+            <constraint
+                  class="org.eclipse.pde.ds.builder.internal.validation.constraints.ComponentImplementationTypeIsOnClasspath"
+                  id="org.eclipse.pde.ds.builder.constraintComponentImplementationTypeIsOnClasspath"
+                  lang="Java"
+                  mode="Batch"
+                  name="Java types validation"
+                  severity="ERROR"
+                  statusCode="1">
+               <message>
+                  {0} is not in the plug-in&apos;s classpath
+               </message>
+               <target
+                     class="Implementation">
+               </target>
+            </constraint>
+         </constraints>
+      </constraintProvider>
+   </extension>
+   <extension
+         point="org.eclipse.emf.validation.constraintBindings">
+      <clientContext
+            default="false"
+            id="org.eclipse.pde.ds.builder.validationContext">
+         <enablement>
+            <instanceof
+                  value="java.lang.Object">
+            </instanceof></enablement>
+      </clientContext>
+      <binding
+            context="org.eclipse.pde.ds.builder.validationContext"
+            category="org.eclipse.pde.ds.builder.validation"/>
+   </extension>    >
+</plugin>
diff --git a/modeling/plugins/org.eclipse.pde.ds.builder/src/org/eclipse/pde/ds/builder/internal/Activator.java b/modeling/plugins/org.eclipse.pde.ds.builder/src/org/eclipse/pde/ds/builder/internal/Activator.java
new file mode 100644
index 0000000..55a606e
--- /dev/null
+++ b/modeling/plugins/org.eclipse.pde.ds.builder/src/org/eclipse/pde/ds/builder/internal/Activator.java
@@ -0,0 +1,111 @@
+package org.eclipse.pde.ds.builder.internal;
+
+import java.lang.reflect.InvocationTargetException;
+import org.eclipse.core.runtime.*;
+import org.eclipse.emf.ecore.EValidator;
+import org.eclipse.pde.ds.builder.internal.validation.AdvancedScrValidator;
+import org.eclipse.pde.ds.scr.ScrPackage;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator extends Plugin {
+
+	// The plug-in ID
+	public static final String PLUGIN_ID = "org.eclipse.pde.ds.builder";
+
+	// The shared instance
+	private static Activator plugin;
+
+	/**
+	 * The constructor
+	 */
+	public Activator() {
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.eclipse.core.runtime.Plugin#start(org.osgi.framework.BundleContext )
+	 */
+	public void start(BundleContext context) throws Exception {
+		super.start(context);
+		plugin = this;
+
+		// TODO register the extended validator in a better way
+		EValidator.Registry.INSTANCE.put(ScrPackage.eINSTANCE,
+				new EValidator.Descriptor() {
+					public EValidator getEValidator() {
+						return new AdvancedScrValidator();
+					}
+				});
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext )
+	 */
+	public void stop(BundleContext context) throws Exception {
+		plugin = null;
+		super.stop(context);
+	}
+
+	/**
+	 * Returns the shared instance
+	 * 
+	 * @return the shared instance
+	 */
+	public static Activator getDefault() {
+		return plugin;
+	}
+
+	public static void log(IStatus status) {
+		if (status != null)
+			getDefault().getLog().log(status);
+	}
+
+	public static void log(Throwable e) {
+		if (e instanceof InvocationTargetException)
+			e = ((InvocationTargetException) e).getTargetException();
+		IStatus status = null;
+		if (e instanceof CoreException) {
+			status = ((CoreException) e).getStatus();
+		} else if (e.getMessage() != null) {
+			status = new Status(IStatus.ERROR, PLUGIN_ID, IStatus.OK, e
+					.getMessage(), e);
+		}
+		log(status);
+	}
+
+	public static void logErrorMessage(String message) {
+		log(new Status(IStatus.ERROR, PLUGIN_ID, IStatus.ERROR, message, null));
+	}
+
+	public static void logException(Throwable e) {
+		logException(e, null);
+	}
+
+	public static void logException(Throwable e, String message) {
+		if (e instanceof InvocationTargetException) {
+			e = ((InvocationTargetException) e).getTargetException();
+		}
+		IStatus status = null;
+		if (e instanceof CoreException)
+			status = ((CoreException) e).getStatus();
+		else {
+			if (message == null)
+				message = e.getMessage();
+			if (message == null)
+				message = e.toString();
+			status = new Status(IStatus.ERROR, PLUGIN_ID, IStatus.OK, message,
+					e);
+		}
+		log(status);
+	}
+
+}
diff --git a/modeling/plugins/org.eclipse.pde.ds.builder/src/org/eclipse/pde/ds/builder/internal/validation/AdvancedScrValidator.java b/modeling/plugins/org.eclipse.pde.ds.builder/src/org/eclipse/pde/ds/builder/internal/validation/AdvancedScrValidator.java
new file mode 100644
index 0000000..3fdc75b
--- /dev/null
+++ b/modeling/plugins/org.eclipse.pde.ds.builder/src/org/eclipse/pde/ds/builder/internal/validation/AdvancedScrValidator.java
@@ -0,0 +1,169 @@
+/**
+ * Copyright (c) 2009 Anyware Technologies 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:
+ *     Anyware Technologies - initial API and implementation
+ *
+ * $Id: ScrAdapterFactory.java,v 1.1 2009/02/12 17:06:39 bcabe Exp $
+ */
+package org.eclipse.pde.ds.builder.internal.validation;
+
+import java.util.Map;
+import org.eclipse.core.runtime.*;
+import org.eclipse.emf.common.util.BasicDiagnostic;
+import org.eclipse.emf.common.util.DiagnosticChain;
+import org.eclipse.emf.ecore.*;
+import org.eclipse.emf.validation.model.EvaluationMode;
+import org.eclipse.emf.validation.model.IConstraintStatus;
+import org.eclipse.emf.validation.service.IBatchValidator;
+import org.eclipse.emf.validation.service.ModelValidationService;
+import org.eclipse.pde.ds.scr.util.ScrValidator;
+
+/**
+ * An extension of the basic Scr validation using the EMF Model Validation
+ * Service API.
+ */
+public class AdvancedScrValidator extends ScrValidator {
+	/**
+	 * Initializes me.
+	 */
+	public AdvancedScrValidator() {
+		super();
+	}
+
+	@Override
+	public boolean validate(EObject eObject, DiagnosticChain diagnostics,
+			Map<Object, Object> context) {
+		return validate(eObject.eClass(), eObject, diagnostics, context);
+	}
+
+	/**
+	 * Implements validation by delegation to the EMF validation framework.
+	 */
+	@Override
+	public boolean validate(EClass eClass, EObject eObject,
+			DiagnosticChain diagnostics, Map<Object, Object> context) {
+		IBatchValidator batchValidator = ModelValidationService.getInstance()
+				.newValidator(EvaluationMode.BATCH);
+		batchValidator.setIncludeLiveConstraints(true);
+		batchValidator.setReportSuccesses(false);
+
+		// first, do whatever the basic EcoreValidator does
+		super.validate(eClass, eObject, diagnostics, context);
+
+		IStatus status = Status.OK_STATUS;
+
+		// no point in validating if we can't report results
+		if (diagnostics != null) {
+			// if EMF Mode Validation Service already covered the sub-tree,
+			// which it does for efficient computation and error reporting,
+			// then don't repeat (the Diagnostician does the recursion
+			// externally). If there is no context map, then we can't
+			// help it
+			if (!hasProcessed(eObject, context)) {
+				status = batchValidator.validate(eObject,
+						new NullProgressMonitor());
+
+				processed(eObject, context, status);
+
+				appendDiagnostics(status, diagnostics);
+			}
+		}
+
+		return status.isOK();
+	}
+
+	/**
+	 * Direct validation of {@link EDataType}s is not supported by the EMF
+	 * validation framework; they are validated indirectly via the
+	 * {@link EObject}s that hold their values.
+	 */
+	@Override
+	public boolean validate(EDataType eDataType, Object value,
+			DiagnosticChain diagnostics, Map<Object, Object> context) {
+		return super.validate(eDataType, value, diagnostics, context);
+	}
+
+	/**
+	 * If we have a context map, record this object's <code>status</code> in it
+	 * so that we will know later that we have processed it and its sub-tree.
+	 * 
+	 * @param eObject
+	 *            an element that we have validated
+	 * @param context
+	 *            the context (may be <code>null</code>)
+	 * @param status
+	 *            the element's validation status
+	 */
+	private void processed(EObject eObject, Map<Object, Object> context,
+			IStatus status) {
+		if (context != null) {
+			context.put(eObject, status);
+		}
+	}
+
+	/**
+	 * Determines whether we have processed this <code>eObject</code> before, by
+	 * automatic recursion of the EMF Model Validation Service. This is only
+	 * possible if we do, indeed, have a context.
+	 * 
+	 * @param eObject
+	 *            an element to be validated (we hope not)
+	 * @param context
+	 *            the context (may be <code>null</code>)
+	 * @return <code>true</code> if the context is not <code>null</code> and the
+	 *         <code>eObject</code> or one of its containers has already been
+	 *         validated; <code>false</code>, otherwise
+	 */
+	private boolean hasProcessed(EObject eObject, Map<Object, Object> context) {
+		boolean result = false;
+
+		if (context != null) {
+			// this is O(NlogN) but there's no helping it
+			while (eObject != null) {
+				if (context.containsKey(eObject)) {
+					result = true;
+					eObject = null;
+				} else {
+					eObject = eObject.eContainer();
+				}
+			}
+		}
+
+		return result;
+	}
+
+	/**
+	 * Converts a status result from the EMF validation service to diagnostics.
+	 * 
+	 * @param status
+	 *            the EMF validation service's status result
+	 * @param diagnostics
+	 *            a diagnostic chain to accumulate results on
+	 */
+	private void appendDiagnostics(IStatus status, DiagnosticChain diagnostics) {
+		if (status.isMultiStatus()) {
+			IStatus[] children = status.getChildren();
+
+			for (IStatus element : children) {
+				appendDiagnostics(element, diagnostics);
+			}
+		} else if (status instanceof IEnhancedConstraintStatus) {
+			diagnostics.add(new BasicDiagnostic(status.getSeverity(), status
+					.getPlugin(), status.getCode(), status.getMessage(),
+					new Object[] {
+							((IConstraintStatus) status).getResultLocus()
+									.toArray()[0],
+							((IEnhancedConstraintStatus) status)
+									.getResultStructuralFeature() }));
+		} else if (status instanceof IConstraintStatus) {
+			diagnostics.add(new BasicDiagnostic(status.getSeverity(), status
+					.getPlugin(), status.getCode(), status.getMessage(),
+					((IConstraintStatus) status).getResultLocus().toArray()));
+		}
+	}
+}
diff --git a/modeling/plugins/org.eclipse.pde.ds.builder/src/org/eclipse/pde/ds/builder/internal/validation/EMFHelper.java b/modeling/plugins/org.eclipse.pde.ds.builder/src/org/eclipse/pde/ds/builder/internal/validation/EMFHelper.java
new file mode 100644
index 0000000..0d1e2bd
--- /dev/null
+++ b/modeling/plugins/org.eclipse.pde.ds.builder/src/org/eclipse/pde/ds/builder/internal/validation/EMFHelper.java
@@ -0,0 +1,44 @@
+package org.eclipse.pde.ds.builder.internal.validation;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.emf.common.util.URI;
+
+/**
+ * A set of helper methods for EMF
+ */
+public final class EMFHelper {
+	private static final String PLATFORM_SCHEME = "platform"; //$NON-NLS-1$
+
+	private static final String FILE_SCHEME = "file"; //$NON-NLS-1$
+
+	private static final String RESOURCE_SEGMENT = "resource"; //$NON-NLS-1$
+
+	public static IFile getIFile(URI uri) {
+		IFile file = null;
+
+		if (PLATFORM_SCHEME.equals(uri.scheme()) && uri.segmentCount() > 1
+				&& RESOURCE_SEGMENT.equals(uri.segment(0))) {
+			StringBuffer platformResourcePath = new StringBuffer();
+			for (int j = 1, size = uri.segmentCount(); j < size; ++j) {
+				platformResourcePath.append('/');
+				platformResourcePath.append(URI.decode(uri.segment(j)));
+			}
+
+			file = ResourcesPlugin.getWorkspace().getRoot().getFile(
+					new Path(platformResourcePath.toString()));
+		} else if (FILE_SCHEME.equals(uri.scheme())) {
+			StringBuffer fileResourcePath = new StringBuffer();
+			for (int j = 1, size = uri.segmentCount(); j < size; ++j) {
+				fileResourcePath.append('/');
+				fileResourcePath.append(URI.decode(uri.segment(j)));
+			}
+
+			file = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(
+					new Path(fileResourcePath.toString()));
+		}
+
+		return file;
+	}
+}
diff --git a/modeling/plugins/org.eclipse.pde.ds.builder/src/org/eclipse/pde/ds/builder/internal/validation/EnhancedConstraintStatus.java b/modeling/plugins/org.eclipse.pde.ds.builder/src/org/eclipse/pde/ds/builder/internal/validation/EnhancedConstraintStatus.java
new file mode 100644
index 0000000..def35f3
--- /dev/null
+++ b/modeling/plugins/org.eclipse.pde.ds.builder/src/org/eclipse/pde/ds/builder/internal/validation/EnhancedConstraintStatus.java
@@ -0,0 +1,29 @@
+package org.eclipse.pde.ds.builder.internal.validation;
+
+import java.util.Set;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.validation.model.ConstraintStatus;
+import org.eclipse.emf.validation.model.IModelConstraint;
+
+public class EnhancedConstraintStatus extends ConstraintStatus implements
+		IEnhancedConstraintStatus {
+
+	private EStructuralFeature _resultStructuralFeature;
+
+	public EnhancedConstraintStatus(IModelConstraint constraint,
+			EObject target, int severity, int code, String message,
+			Set<? extends EObject> resultLocus) {
+		super(constraint, target, severity, code, message, resultLocus);
+	}
+
+	public void setResultStructuralFeature(
+			EStructuralFeature resultStructuralFeature) {
+		_resultStructuralFeature = resultStructuralFeature;
+	}
+
+	public EStructuralFeature getResultStructuralFeature() {
+		return this._resultStructuralFeature;
+	}
+
+}
diff --git a/modeling/plugins/org.eclipse.pde.ds.builder/src/org/eclipse/pde/ds/builder/internal/validation/IEnhancedConstraintStatus.java b/modeling/plugins/org.eclipse.pde.ds.builder/src/org/eclipse/pde/ds/builder/internal/validation/IEnhancedConstraintStatus.java
new file mode 100644
index 0000000..b7e2db3
--- /dev/null
+++ b/modeling/plugins/org.eclipse.pde.ds.builder/src/org/eclipse/pde/ds/builder/internal/validation/IEnhancedConstraintStatus.java
@@ -0,0 +1,8 @@
+package org.eclipse.pde.ds.builder.internal.validation;
+
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.validation.model.IConstraintStatus;
+
+public interface IEnhancedConstraintStatus extends IConstraintStatus {
+	EStructuralFeature getResultStructuralFeature();
+}
diff --git a/modeling/plugins/org.eclipse.pde.ds.builder/src/org/eclipse/pde/ds/builder/internal/validation/IncrementalModelBuilder.java b/modeling/plugins/org.eclipse.pde.ds.builder/src/org/eclipse/pde/ds/builder/internal/validation/IncrementalModelBuilder.java
new file mode 100644
index 0000000..7c733b0
--- /dev/null
+++ b/modeling/plugins/org.eclipse.pde.ds.builder/src/org/eclipse/pde/ds/builder/internal/validation/IncrementalModelBuilder.java
@@ -0,0 +1,160 @@
+package org.eclipse.pde.ds.builder.internal.validation;
+
+import org.eclipse.pde.core.plugin.IPluginModelBase;
+
+import org.eclipse.pde.internal.core.PDECore;
+
+import org.eclipse.pde.internal.core.PluginModelManager;
+
+import org.eclipse.pde.internal.core.text.bundle.BundleModel;
+
+import org.eclipse.core.runtime.URIUtil;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceDeltaVisitor;
+import org.eclipse.core.resources.IncrementalProjectBuilder;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.emf.common.command.BasicCommandStack;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
+import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
+import org.eclipse.pde.internal.core.ICoreConstants;
+import org.eclipse.pde.internal.core.natures.PDE;
+
+/**
+ * An abstract class to subclass to launch background jobs on the modified model
+ */
+public abstract class IncrementalModelBuilder extends IncrementalProjectBuilder {
+	protected class ModelFileDeltaVisitor implements IResourceDeltaVisitor {
+		private Map<Resource, IResource> modifiedResources = new HashMap<Resource, IResource>();
+
+		public ModelFileDeltaVisitor() {
+			// Do nothing
+		}
+
+		public Map<Resource, IResource> getModifiedResources() {
+			return modifiedResources;
+		}
+
+		/**
+		 * @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse
+		 *      .core.resources.IResourceDelta)
+		 */
+		public boolean visit(IResourceDelta delta) throws CoreException {
+			IResource resource = delta.getResource();
+			switch (delta.getKind()) {
+			case IResourceDelta.ADDED:
+			case IResourceDelta.REMOVED:
+				// Do nothing
+				break;
+			case IResourceDelta.CHANGED:
+				if(resource instanceof IProject)
+					return true;
+				// handle changed resource
+				URI resourceURI = URI.createPlatformResourceURI(resource
+						.getFullPath().toString(), true);
+				Resource modelResource = new AdapterFactoryEditingDomain(new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE),new BasicCommandStack())
+						.getResourceSet().getResource(resourceURI, true);
+				if (modelResource != null && modelResource.isLoaded()
+						&& !modifiedResources.containsKey(modelResource)) {
+					modifiedResources.put(modelResource, resource);
+				}
+				break;
+			}
+			// return true to continue visiting children.
+			return true;
+		}
+	}
+
+	/**
+	 * @see org.eclipse.core.resources.IncrementalProjectBuilder#build(int,
+	 *      java.util.Map, org.eclipse.core.runtime.IProgressMonitor)
+	 */
+	@SuppressWarnings("unchecked")
+	@Override
+	protected IProject[] build(int kind, Map args, IProgressMonitor monitor)
+			throws CoreException {
+		switch (kind) {
+		case FULL_BUILD:
+			fullBuild(monitor);
+			break;
+		case CLEAN_BUILD:
+			clean(monitor);
+			break;
+		default:
+			IResourceDelta delta = getDelta(getProject());
+			if (delta == null) {
+				fullBuild(monitor);
+			} else {
+				incrementalBuild(delta, monitor);
+			}
+
+			break;
+		}
+		return null;
+	}
+
+	@Override
+	protected void clean(IProgressMonitor monitor) throws CoreException {
+		// Subclasses must override this method
+	}
+
+	protected void incrementalBuild(IResourceDelta delta,
+			IProgressMonitor monitor) throws CoreException {
+		if (monitor == null) {
+			monitor = new NullProgressMonitor();
+		}
+		// the visitor does the work.
+		ModelFileDeltaVisitor visitor = new ModelFileDeltaVisitor();
+		delta.accept(visitor);
+
+		Map<Resource, IResource> modifiedResources = visitor
+				.getModifiedResources();
+
+		monitor.beginTask("Incremental Build", modifiedResources.size());
+
+		for (Resource modelResource : modifiedResources.keySet()) {
+			build(modelResource.getContents().get(0), modifiedResources
+					.get(modelResource), false, new SubProgressMonitor(monitor,
+					1));
+		}
+
+		monitor.done();
+
+	}
+
+	protected void fullBuild(IProgressMonitor monitor) throws CoreException {
+		if (monitor == null) {
+			monitor = new NullProgressMonitor();
+		}
+
+		if (PDE.hasPluginNature(getProject())) {
+			IFile manifestFile = getProject().getFile(ICoreConstants.BUNDLE_FILENAME_DESCRIPTOR);
+
+			IPluginModelBase bundle = PDECore.getDefault().getModelManager().findModel(getProject());
+			
+			// TODO analyze every component referenced in the Service-Component header
+			// build(project, getProject(), true, new SubProgressMonitor(monitor,1));
+			URI res = URI.createPlatformResourceURI(getProject().getFile("component.xml").getFullPath().toString());
+			Resource modelResource = new AdapterFactoryEditingDomain(new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE),new BasicCommandStack())
+			.getResourceSet().getResource(res, true);
+			build(modelResource.getContents().get(0), getProject().getFile("component.xml"), true, new SubProgressMonitor(monitor,1));
+			
+			
+		}
+	}
+
+	protected abstract void build(EObject modelObject, IResource resource,
+			boolean force, IProgressMonitor monitor) throws CoreException;
+}
diff --git a/modeling/plugins/org.eclipse.pde.ds.builder/src/org/eclipse/pde/ds/builder/internal/validation/MarkerHelper.java b/modeling/plugins/org.eclipse.pde.ds.builder/src/org/eclipse/pde/ds/builder/internal/validation/MarkerHelper.java
new file mode 100644
index 0000000..d20626a
--- /dev/null
+++ b/modeling/plugins/org.eclipse.pde.ds.builder/src/org/eclipse/pde/ds/builder/internal/validation/MarkerHelper.java
@@ -0,0 +1,133 @@
+package org.eclipse.pde.ds.builder.internal.validation;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.emf.common.util.Diagnostic;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EValidator;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+
+/**
+ * Helper class to manage markers : clean, creation...
+ */
+public final class MarkerHelper {
+
+	public static final String VALIDATION_MARKER_TYPE = "org.eclipse.core.resources.problemmarker"; //$NON-NLS-1$
+
+	public static void cleanMarkers(IContainer container) throws CoreException {
+		if (container != null) {
+			String markerType = MarkerHelper.VALIDATION_MARKER_TYPE;
+			container.deleteMarkers(markerType, true, IResource.DEPTH_INFINITE);
+		}
+	}
+
+	public static void cleanMarkers(IFile file) throws CoreException {
+		if (file != null) {
+			String markerType = MarkerHelper.VALIDATION_MARKER_TYPE;
+			file.deleteMarkers(markerType, true, IResource.DEPTH_ZERO);
+		}
+	}
+
+	private static void createMarker(Diagnostic diagnostic,
+			Map<URI, IFile> visitedResources) throws CoreException {
+		String markerType = MarkerHelper.VALIDATION_MARKER_TYPE;
+
+		EObject target = (EObject) diagnostic.getData().get(0);
+		Resource r = target.eResource();
+		URI resourceUri = r.getURI();
+
+		// Normalize the URI to something that we can deal with like file or
+		// platform scheme
+		resourceUri = r.getResourceSet().getURIConverter().normalize(
+				resourceUri);
+
+		IFile file = visitedResources.get(resourceUri);
+
+		if (file == null) {
+			file = EMFHelper.getIFile(resourceUri);
+
+			if (file != null) {
+				file.deleteMarkers(markerType, true, IResource.DEPTH_ZERO);
+				visitedResources.put(resourceUri, file);
+			}
+		}
+
+		if (file != null) {
+
+			IMarker marker = file.createMarker(markerType);
+
+			marker.setAttribute(IMarker.SOURCE_ID, diagnostic.getCode());
+			marker.setAttribute(EValidator.URI_ATTRIBUTE, EcoreUtil.getURI(
+					target).toString());
+
+			switch (diagnostic.getSeverity()) {
+			case IStatus.INFO:
+				marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_INFO);
+				marker.setAttribute(IMarker.PRIORITY, IMarker.PRIORITY_LOW);
+				break;
+			case IStatus.WARNING:
+				marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_WARNING);
+				marker.setAttribute(IMarker.PRIORITY, IMarker.PRIORITY_NORMAL);
+				break;
+			case IStatus.ERROR:
+			case IStatus.CANCEL:
+				marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
+				marker.setAttribute(IMarker.PRIORITY, IMarker.PRIORITY_HIGH);
+				break;
+			}
+
+			marker.setAttribute(IMarker.MESSAGE, diagnostic.getMessage());
+		}
+	}
+
+	public static void createMarkers(final Diagnostic validationDiagnostic,
+			IProgressMonitor monitor) throws CoreException {
+		if (validationDiagnostic.getSeverity() == Diagnostic.OK) {
+			return;
+		}
+		if (monitor == null) {
+			monitor = new NullProgressMonitor();
+		}
+
+		IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
+			public void run(IProgressMonitor m) throws CoreException {
+				final Map<URI, IFile> visitedResources = new HashMap<URI, IFile>();
+
+				if (!validationDiagnostic.getChildren().isEmpty()) {
+					m.beginTask("Create validation markers",
+							validationDiagnostic.getChildren().size());
+					for (Diagnostic diagnostic : validationDiagnostic
+							.getChildren()) {
+						List<?> data = diagnostic.getData();
+						if (data != null && !data.isEmpty()
+								&& data.get(0) instanceof EObject) {
+							createMarker(diagnostic, visitedResources);
+						}
+
+						m.worked(1);
+					}
+				} else {
+					createMarker(validationDiagnostic, visitedResources);
+				}
+
+				m.done();
+			}
+		};
+
+		ResourcesPlugin.getWorkspace().run(runnable, monitor);
+	}
+}
diff --git a/modeling/plugins/org.eclipse.pde.ds.builder/src/org/eclipse/pde/ds/builder/internal/validation/ScrBuilder.java b/modeling/plugins/org.eclipse.pde.ds.builder/src/org/eclipse/pde/ds/builder/internal/validation/ScrBuilder.java
new file mode 100644
index 0000000..d8e333c
--- /dev/null
+++ b/modeling/plugins/org.eclipse.pde.ds.builder/src/org/eclipse/pde/ds/builder/internal/validation/ScrBuilder.java
@@ -0,0 +1,109 @@
+package org.eclipse.pde.ds.builder.internal.validation;
+
+import java.util.Map;
+import org.eclipse.core.resources.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.emf.common.notify.AdapterFactory;
+import org.eclipse.emf.common.util.BasicDiagnostic;
+import org.eclipse.emf.common.util.Diagnostic;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.util.Diagnostician;
+import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
+import org.eclipse.emf.edit.provider.IItemLabelProvider;
+import org.eclipse.emf.transaction.RunnableWithResult;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.pde.ds.builder.internal.Activator;
+
+public class ScrBuilder extends IncrementalModelBuilder {
+	public static final String ID = "org.eclipse.pde.ds.builder.scrBuilder";
+
+	protected void incrementalBuild(IResourceDelta delta,
+			IProgressMonitor monitor) throws CoreException {
+		if (monitor == null) {
+			monitor = new NullProgressMonitor();
+		}
+		// the visitor does the work.
+		ModelFileDeltaVisitor visitor = new ModelFileDeltaVisitor();
+		delta.accept(visitor);
+
+		Map<Resource, IResource> modifiedResources = visitor
+				.getModifiedResources();
+
+		// If one resource is changed in the project, all the project must be
+		// validated
+		if (modifiedResources.size() > 0) {
+			fullBuild(monitor);
+		}
+
+	}
+
+	protected void build(EObject modelObject, IResource resource,
+			boolean force, IProgressMonitor monitor) throws CoreException {
+		if (monitor == null) {
+			monitor = new NullProgressMonitor();
+		}
+
+		monitor.beginTask("Model Validation", 4);
+
+		monitor.subTask("Validation");
+
+		Diagnostic diagnostic = validate(modelObject);
+
+		monitor.worked(3);
+
+		if (resource instanceof IContainer) {
+			MarkerHelper.cleanMarkers((IContainer) resource);
+		} else if (resource instanceof IFile) {
+			MarkerHelper.cleanMarkers((IFile) resource);
+		}
+
+		MarkerHelper.createMarkers(diagnostic, new SubProgressMonitor(monitor,
+				1));
+
+		monitor.done();
+	}
+
+	private Diagnostic validate(final EObject modelObject) {
+		TransactionalEditingDomain domain = TransactionalEditingDomain.Factory.INSTANCE
+				.createEditingDomain();
+		final AdapterFactory adapterFactory = domain instanceof AdapterFactoryEditingDomain ? ((AdapterFactoryEditingDomain) domain)
+				.getAdapterFactory()
+				: null;
+
+		try {
+			return (Diagnostic) domain
+					.runExclusive(new RunnableWithResult.Impl<Diagnostic>() {
+						public void run() {
+
+							Diagnostic diagnostic = new Diagnostician() {
+
+								@Override
+								public String getObjectLabel(EObject eObject) {
+									if (adapterFactory != null
+											&& !eObject.eIsProxy()) {
+										IItemLabelProvider itemLabelProvider = (IItemLabelProvider) adapterFactory
+												.adapt(
+														eObject,
+														IItemLabelProvider.class);
+										if (itemLabelProvider != null) {
+											return itemLabelProvider
+													.getText(eObject);
+										}
+									}
+
+									return super.getObjectLabel(eObject);
+								}
+							}.validate(modelObject);
+							setResult(diagnostic);
+						}
+					});
+		} catch (InterruptedException ie) {
+			// Log and return the exception in a diagnostic
+			Activator.log(ie);
+			return new BasicDiagnostic(Diagnostic.ERROR, "ModelChecker", 0, ie
+					.getMessage(), new Object[] { modelObject });
+		}
+
+	}
+}
diff --git a/modeling/plugins/org.eclipse.pde.ds.builder/src/org/eclipse/pde/ds/builder/internal/validation/constraints/ComponentImplementationTypeIsOnClasspath.java b/modeling/plugins/org.eclipse.pde.ds.builder/src/org/eclipse/pde/ds/builder/internal/validation/constraints/ComponentImplementationTypeIsOnClasspath.java
new file mode 100644
index 0000000..c8ab458
--- /dev/null
+++ b/modeling/plugins/org.eclipse.pde.ds.builder/src/org/eclipse/pde/ds/builder/internal/validation/constraints/ComponentImplementationTypeIsOnClasspath.java
@@ -0,0 +1,44 @@
+package org.eclipse.pde.ds.builder.internal.validation.constraints;
+
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.emf.validation.AbstractModelConstraint;
+import org.eclipse.emf.validation.IValidationContext;
+import org.eclipse.emf.validation.model.ConstraintStatus;
+import org.eclipse.jdt.core.*;
+import org.eclipse.pde.ds.builder.internal.validation.EnhancedConstraintStatus;
+import org.eclipse.pde.ds.scr.Implementation;
+import org.eclipse.pde.ds.scr.ScrPackage;
+
+public class ComponentImplementationTypeIsOnClasspath extends
+		AbstractModelConstraint {
+
+	public ComponentImplementationTypeIsOnClasspath() {
+	}
+
+	@Override
+	public IStatus validate(IValidationContext ctx) {
+		Implementation impl = (Implementation) ctx.getTarget();
+		IJavaProject project = JavaCore.create(ResourcesPlugin.getWorkspace()
+				.getRoot().getProject("/a"));
+		IType type;
+		try {
+			type = project.findType(impl.getClass_());
+			if (type == null || !type.exists()) {
+				ConstraintStatus s = (ConstraintStatus) ctx
+						.createFailureStatus(impl.getClass_());
+				EnhancedConstraintStatus enhancedStatus = new EnhancedConstraintStatus(
+						s.getConstraint(), s.getTarget(), s.getSeverity(), s
+								.getCode(), s.getMessage(), s.getResultLocus());
+				enhancedStatus
+						.setResultStructuralFeature(ScrPackage.Literals.IMPLEMENTATION__CLASS);
+				return enhancedStatus;
+			} else
+				return ctx.createSuccessStatus();
+		} catch (JavaModelException e) {
+			return ctx.createFailureStatus(impl);
+		}
+
+	}
+
+}
diff --git a/modeling/plugins/org.eclipse.pde.ds.builder/src/org/eclipse/pde/ds/builder/internal/validation/constraints/ComponentMethodsAreValidAndAccessible.java b/modeling/plugins/org.eclipse.pde.ds.builder/src/org/eclipse/pde/ds/builder/internal/validation/constraints/ComponentMethodsAreValidAndAccessible.java
new file mode 100644
index 0000000..9091072
--- /dev/null
+++ b/modeling/plugins/org.eclipse.pde.ds.builder/src/org/eclipse/pde/ds/builder/internal/validation/constraints/ComponentMethodsAreValidAndAccessible.java
@@ -0,0 +1,56 @@
+package org.eclipse.pde.ds.builder.internal.validation.constraints;
+
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.emf.validation.AbstractModelConstraint;
+import org.eclipse.emf.validation.IValidationContext;
+import org.eclipse.emf.validation.model.ConstraintStatus;
+import org.eclipse.jdt.core.*;
+import org.eclipse.pde.ds.builder.internal.validation.EnhancedConstraintStatus;
+import org.eclipse.pde.ds.scr.Component;
+import org.eclipse.pde.ds.scr.ScrPackage;
+
+public class ComponentMethodsAreValidAndAccessible extends
+		AbstractModelConstraint {
+
+	public ComponentMethodsAreValidAndAccessible() {
+	}
+
+	@Override
+	public IStatus validate(IValidationContext ctx) {
+		Component comp = (Component) ctx.getTarget();
+		IJavaProject project = JavaCore.create(ResourcesPlugin.getWorkspace()
+				.getRoot().getProject("/a"));
+		IType type;
+		try {
+			type = project.findType(comp.getImplementation().getClass_());
+			if (type != null && type.exists()) {
+				// validate 'activate' method
+				if (comp.getActivate() != null) {
+					String activateMethod = comp.getActivate();
+					IMethod m = type
+							.getMethod(
+									activateMethod,
+									new String[] { "Qorg.osgi.service.component.ComponentContext;" });
+					if (m != null
+							&& (Flags.isPublic(m.getFlags()) || Flags
+									.isProtected(m.getFlags()))) {
+						return ctx.createSuccessStatus();
+					}
+				}
+
+				ConstraintStatus s = (ConstraintStatus) ctx
+						.createFailureStatus(comp);
+				EnhancedConstraintStatus enhancedStatus = new EnhancedConstraintStatus(
+						s.getConstraint(), s.getTarget(), s.getSeverity(), s
+								.getCode(), s.getMessage(), s.getResultLocus());
+				enhancedStatus
+						.setResultStructuralFeature(ScrPackage.Literals.IMPLEMENTATION__CLASS);
+				return enhancedStatus;
+			} else
+				return ctx.createSuccessStatus();
+		} catch (JavaModelException e) {
+			return ctx.createFailureStatus(comp);
+		}
+	}
+}