Author: rombert
Date: Fri May 23 12:07:17 2014
New Revision: 1597070
URL: http://svn.apache.org/r1597070
Log:
SLING-3550 - Inspect bundles for deployment for well-known errors
Add a BundleProjectValidator which inspects the Service-Component
header.
Added:
sling/trunk/tooling/ide/eclipse-core/src/org/apache/sling/ide/eclipse/internal/
sling/trunk/tooling/ide/eclipse-core/src/org/apache/sling/ide/eclipse/internal/validation/
sling/trunk/tooling/ide/eclipse-core/src/org/apache/sling/ide/eclipse/internal/validation/BundleProjectValidator.java
(with props)
sling/trunk/tooling/ide/eclipse-core/src/org/apache/sling/ide/eclipse/internal/validation/ServiceComponentHeaderValidator.java
(with props)
sling/trunk/tooling/ide/eclipse-test/src/org/apache/sling/ide/test/impl/ServiceComponentHeaderValidatorTest.java
(with props)
Modified:
sling/trunk/tooling/ide/eclipse-core/META-INF/MANIFEST.MF
sling/trunk/tooling/ide/eclipse-core/plugin.xml
sling/trunk/tooling/ide/eclipse-test/src/org/apache/sling/ide/test/impl/helpers/EclipseResourceMatchers.java
sling/trunk/tooling/ide/eclipse-test/src/org/apache/sling/ide/test/impl/helpers/HasFileMatcher.java
Modified: sling/trunk/tooling/ide/eclipse-core/META-INF/MANIFEST.MF
URL:
http://svn.apache.org/viewvc/sling/trunk/tooling/ide/eclipse-core/META-INF/MANIFEST.MF?rev=1597070&r1=1597069&r2=1597070&view=diff
==============================================================================
--- sling/trunk/tooling/ide/eclipse-core/META-INF/MANIFEST.MF (original)
+++ sling/trunk/tooling/ide/eclipse-core/META-INF/MANIFEST.MF Fri May 23
12:07:17 2014
@@ -38,8 +38,10 @@ Import-Package: org.apache.commons.httpc
org.eclipse.wst.server.core,
org.eclipse.wst.server.core.model,
org.eclipse.wst.server.core.util,
+ org.eclipse.wst.validation,
org.json,
org.osgi.service.component;version="1.1.0"
Export-Package: org.apache.sling.ide.eclipse.core,
org.apache.sling.ide.eclipse.core.internal,
- org.apache.sling.ide.eclipse.core.debug
+ org.apache.sling.ide.eclipse.core.debug,
+
org.apache.sling.ide.eclipse.internal.validation;x-friends:=org.apache.sling.ide.eclipse-test
Modified: sling/trunk/tooling/ide/eclipse-core/plugin.xml
URL:
http://svn.apache.org/viewvc/sling/trunk/tooling/ide/eclipse-core/plugin.xml?rev=1597070&r1=1597069&r2=1597070&view=diff
==============================================================================
--- sling/trunk/tooling/ide/eclipse-core/plugin.xml (original)
+++ sling/trunk/tooling/ide/eclipse-core/plugin.xml Fri May 23 12:07:17 2014
@@ -181,5 +181,20 @@
properties="canBeExported,canBeImported"
class="org.apache.sling.ide.eclipse.core.internal.ContentResourceTester">
</propertyTester>
- </extension>
+ </extension>
+
+ <extension
+ id="bundleValidator"
+ point="org.eclipse.wst.validation.validatorV2"
+ name="Sling Bundle Validator">
+ <validator
class="org.apache.sling.ide.eclipse.internal.validation.BundleProjectValidator">
+ <include>
+ <rules>
+ <facet
+ id="sling.bundle">
+ </facet>
+ </rules>
+ </include>
+ </validator>
+ </extension>
</plugin>
Added:
sling/trunk/tooling/ide/eclipse-core/src/org/apache/sling/ide/eclipse/internal/validation/BundleProjectValidator.java
URL:
http://svn.apache.org/viewvc/sling/trunk/tooling/ide/eclipse-core/src/org/apache/sling/ide/eclipse/internal/validation/BundleProjectValidator.java?rev=1597070&view=auto
==============================================================================
---
sling/trunk/tooling/ide/eclipse-core/src/org/apache/sling/ide/eclipse/internal/validation/BundleProjectValidator.java
(added)
+++
sling/trunk/tooling/ide/eclipse-core/src/org/apache/sling/ide/eclipse/internal/validation/BundleProjectValidator.java
Fri May 23 12:07:17 2014
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.ide.eclipse.internal.validation;
+
+import org.apache.sling.ide.eclipse.core.debug.PluginLogger;
+import org.apache.sling.ide.eclipse.core.internal.Activator;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.validation.AbstractValidator;
+import org.eclipse.wst.validation.ValidationEvent;
+import org.eclipse.wst.validation.ValidationResult;
+import org.eclipse.wst.validation.ValidationState;
+import org.eclipse.wst.validation.ValidatorMessage;
+
+public class BundleProjectValidator extends AbstractValidator {
+
+ private final ServiceComponentHeaderValidator scValidator = new
ServiceComponentHeaderValidator();
+
+ @Override
+ public ValidationResult validate(ValidationEvent event, ValidationState
state, IProgressMonitor monitor) {
+
+ ValidationResult res = new ValidationResult();
+
+ IResource resource = event.getResource();
+
+ if (!resource.getName().equals("MANIFEST.MF") || resource.getType() !=
IResource.FILE) {
+ return res;
+ }
+
+ IFile m = (IFile) resource;
+
+ PluginLogger pluginLogger = Activator.getDefault() .getPluginLogger();
+
+ try {
+
+ for (IFile descriptor : scValidator.findMissingScrDescriptors(m)) {
+ ValidatorMessage dsMessage = ValidatorMessage.create(
+ "No DS descriptor found at path " +
descriptor.getProjectRelativePath(), m);
+ dsMessage.setAttribute(IMarker.LOCATION, m.getName());
+ dsMessage.setAttribute(IMarker.SEVERITY,
IMarker.SEVERITY_ERROR);
+
+ res.add(dsMessage);
+
+ }
+
+ } catch (CoreException e) {
+ pluginLogger.warn("Failed validating project " +
resource.getFullPath(), e);
+ }
+
+ return res;
+ }
+}
Propchange:
sling/trunk/tooling/ide/eclipse-core/src/org/apache/sling/ide/eclipse/internal/validation/BundleProjectValidator.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sling/trunk/tooling/ide/eclipse-core/src/org/apache/sling/ide/eclipse/internal/validation/BundleProjectValidator.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision Rev URL
Added:
sling/trunk/tooling/ide/eclipse-core/src/org/apache/sling/ide/eclipse/internal/validation/ServiceComponentHeaderValidator.java
URL:
http://svn.apache.org/viewvc/sling/trunk/tooling/ide/eclipse-core/src/org/apache/sling/ide/eclipse/internal/validation/ServiceComponentHeaderValidator.java?rev=1597070&view=auto
==============================================================================
---
sling/trunk/tooling/ide/eclipse-core/src/org/apache/sling/ide/eclipse/internal/validation/ServiceComponentHeaderValidator.java
(added)
+++
sling/trunk/tooling/ide/eclipse-core/src/org/apache/sling/ide/eclipse/internal/validation/ServiceComponentHeaderValidator.java
Fri May 23 12:07:17 2014
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.ide.eclipse.internal.validation;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.jar.Manifest;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.sling.ide.eclipse.core.debug.PluginLogger;
+import org.apache.sling.ide.eclipse.core.internal.Activator;
+import org.apache.sling.ide.eclipse.core.internal.ProjectHelper;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jdt.core.IJavaProject;
+
+public class ServiceComponentHeaderValidator {
+
+ /**
+ * Finds missing SCR descriptor files referenced in the manifest
+ *
+ * <p>
+ * Only acts if the Manifest is located under the project's output
directory at
+ * </p>
+ *
+ * @param manifest the location of the manifest to parse for the
Service-Component header
+ * @return a list of missing files, empty if no problems are found
+ * @throws CoreException any errors
+ */
+ public List<IFile> findMissingScrDescriptors(IFile manifest) throws
CoreException {
+
+ IProject project = manifest.getProject();
+
+ PluginLogger pluginLogger = Activator.getDefault().getPluginLogger();
+
+ IJavaProject javaProject = ProjectHelper.asJavaProject(project);
+
+ IFolder outputFolder = (IFolder)
project.getWorkspace().getRoot().findMember(javaProject.getOutputLocation());
+
+ if (!outputFolder.getFullPath().isPrefixOf(manifest.getFullPath())) {
+ pluginLogger.trace("Ignoring manifest found at {0} since it is not
under the output directory at {1}",
+ manifest.getFullPath(), outputFolder.getFullPath());
+ return Collections.emptyList();
+ }
+
+ List<IFile> missingDescriptors = new ArrayList<IFile>();
+
+ InputStream contents = manifest.getContents();
+ try {
+ Manifest mf = new Manifest(contents);
+ String serviceComponentHeader =
mf.getMainAttributes().getValue("Service-Component");
+ if (serviceComponentHeader != null) {
+ String[] entries = serviceComponentHeader.split(",");
+ for (String entry : entries) {
+ entry = entry.trim();
+
+ if (entry.contains("*")) {
+ pluginLogger.trace("Ignoring wildcard
Service-Component entry {0}", entry);
+ continue;
+ }
+
+ IFile descriptor = outputFolder.getFile(entry);
+
+ if (descriptor.exists()) {
+ pluginLogger.trace("Found matching resource for
Service-Component entry {0}", entry);
+ continue;
+ }
+
+ missingDescriptors.add(descriptor);
+
+ pluginLogger.trace("Raising error for missing DS
descriptor entry {0}", entry);
+ }
+ }
+ } catch (IOException e) {
+ throw new CoreException(new Status(IStatus.ERROR,
Activator.PLUGIN_ID, "Unable to access "
+ + manifest.getFullPath(), e));
+ } finally {
+ IOUtils.closeQuietly(contents);
+ }
+
+ return missingDescriptors;
+ }
+}
Propchange:
sling/trunk/tooling/ide/eclipse-core/src/org/apache/sling/ide/eclipse/internal/validation/ServiceComponentHeaderValidator.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sling/trunk/tooling/ide/eclipse-core/src/org/apache/sling/ide/eclipse/internal/validation/ServiceComponentHeaderValidator.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision Rev URL
Added:
sling/trunk/tooling/ide/eclipse-test/src/org/apache/sling/ide/test/impl/ServiceComponentHeaderValidatorTest.java
URL:
http://svn.apache.org/viewvc/sling/trunk/tooling/ide/eclipse-test/src/org/apache/sling/ide/test/impl/ServiceComponentHeaderValidatorTest.java?rev=1597070&view=auto
==============================================================================
---
sling/trunk/tooling/ide/eclipse-test/src/org/apache/sling/ide/test/impl/ServiceComponentHeaderValidatorTest.java
(added)
+++
sling/trunk/tooling/ide/eclipse-test/src/org/apache/sling/ide/test/impl/ServiceComponentHeaderValidatorTest.java
Fri May 23 12:07:17 2014
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.ide.test.impl;
+
+import static
org.apache.sling.ide.test.impl.helpers.EclipseResourceMatchers.hasFile;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+import
org.apache.sling.ide.eclipse.internal.validation.ServiceComponentHeaderValidator;
+import org.apache.sling.ide.test.impl.helpers.OsgiBundleManifest;
+import org.apache.sling.ide.test.impl.helpers.Poller;
+import org.apache.sling.ide.test.impl.helpers.ProjectAdapter;
+import org.apache.sling.ide.test.impl.helpers.TemporaryProject;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.JavaCore;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class ServiceComponentHeaderValidatorTest {
+
+ @Rule
+ public TemporaryProject projectRule = new TemporaryProject();
+ private ProjectAdapter project;
+ private Poller poller;
+
+ @Test
+ public void missingDescriptorIsReported() throws CoreException,
IOException, InterruptedException {
+
+ String sch = "OSGI-INF/descriptor1.xml, OSGI-INF/descriptor2.xml";
+
+ createJavaProject(sch);
+
+ ServiceComponentHeaderValidator validator = new
ServiceComponentHeaderValidator();
+ List<IFile> missingDescriptors =
validator.findMissingScrDescriptors(projectRule.getProject().getFile(
+ "bin/META-INF/MANIFEST.MF"));
+
+ assertThat("missingDescriptors.size", missingDescriptors.size(),
equalTo(2));
+ assertThat("missingDescriptors[0].projectRelativePath",
missingDescriptors.get(0).getProjectRelativePath(),
+
equalTo(Path.fromPortableString("bin/OSGI-INF/descriptor1.xml")));
+ assertThat("missingDescriptors[0].projectRelativePath",
missingDescriptors.get(1).getProjectRelativePath(),
+
equalTo(Path.fromPortableString("bin/OSGI-INF/descriptor2.xml")));
+ }
+
+ private void createJavaProject(String serviceComponentHeader) throws
CoreException, IOException,
+ InterruptedException {
+
+ project = new ProjectAdapter(projectRule.getProject());
+ project.addNatures(JavaCore.NATURE_ID);
+ project.configureAsJavaProject();
+
+ OsgiBundleManifest mf = new
OsgiBundleManifest("com.example.bundle001").version("1.0.0").serviceComponent(
+ serviceComponentHeader);
+
+ project.createOsgiBundleManifest(mf);
+
+ poller = new Poller();
+ poller.pollUntil(new Callable<IProject>() {
+
+ @Override
+ public IProject call() throws Exception {
+ return projectRule.getProject();
+ }
+ }, hasFile("bin/META-INF/MANIFEST.MF"));
+ }
+
+ @Test
+ public void wildCardHeaderIsIgnored() throws CoreException, IOException,
InterruptedException {
+
+ createJavaProject("OSGI-INF/*.xml");
+
+ ServiceComponentHeaderValidator validator = new
ServiceComponentHeaderValidator();
+ List<IFile> missingDescriptors =
validator.findMissingScrDescriptors(projectRule.getProject().getFile(
+ "bin/META-INF/MANIFEST.MF"));
+
+ assertThat("missingDescriptors.size", missingDescriptors.size(),
equalTo(0));
+ }
+
+ @Test
+ public void presentDescriptorIsNotReported() throws CoreException,
IOException, InterruptedException {
+
+ createJavaProject("OSGI-INF/descriptor.xml");
+
+
project.createOrUpdateFile(Path.fromPortableString("src/OSGI-INF/descriptor.xml"),
new ByteArrayInputStream(
+ "<!-- does not matter -->".getBytes()));
+
+ poller.pollUntil(new Callable<IProject>() {
+
+ @Override
+ public IProject call() throws Exception {
+ return projectRule.getProject();
+ }
+ }, hasFile("bin/OSGI-INF/descriptor.xml"));
+
+ ServiceComponentHeaderValidator validator = new
ServiceComponentHeaderValidator();
+ List<IFile> missingDescriptors =
validator.findMissingScrDescriptors(projectRule.getProject().getFile(
+ "bin/META-INF/MANIFEST.MF"));
+
+ assertThat("missingDescriptors.size", missingDescriptors.size(),
equalTo(0));
+ }
+
+ @Test
+ public void manifestNotUnderOutputDirectoryIsIgnored() throws
CoreException, IOException, InterruptedException {
+
+ createJavaProject("OSGI-INF/descriptor.xml");
+
+ ServiceComponentHeaderValidator validator = new
ServiceComponentHeaderValidator();
+ List<IFile> missingDescriptors =
validator.findMissingScrDescriptors(projectRule.getProject().getFile(
+ "src/META-INF/MANIFEST.MF"));
+
+ assertThat("missingDescriptors.size", missingDescriptors.size(),
equalTo(0));
+ }
+
+}
Propchange:
sling/trunk/tooling/ide/eclipse-test/src/org/apache/sling/ide/test/impl/ServiceComponentHeaderValidatorTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sling/trunk/tooling/ide/eclipse-test/src/org/apache/sling/ide/test/impl/ServiceComponentHeaderValidatorTest.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision Rev URL
Modified:
sling/trunk/tooling/ide/eclipse-test/src/org/apache/sling/ide/test/impl/helpers/EclipseResourceMatchers.java
URL:
http://svn.apache.org/viewvc/sling/trunk/tooling/ide/eclipse-test/src/org/apache/sling/ide/test/impl/helpers/EclipseResourceMatchers.java?rev=1597070&r1=1597069&r2=1597070&view=diff
==============================================================================
---
sling/trunk/tooling/ide/eclipse-test/src/org/apache/sling/ide/test/impl/helpers/EclipseResourceMatchers.java
(original)
+++
sling/trunk/tooling/ide/eclipse-test/src/org/apache/sling/ide/test/impl/helpers/EclipseResourceMatchers.java
Fri May 23 12:07:17 2014
@@ -25,6 +25,10 @@ public class EclipseResourceMatchers {
return new HasFileMatcher(path, contents);
}
+ public static Matcher<IProject> hasFile(String path) {
+ return new HasFileMatcher(path, null);
+ }
+
public static Matcher<IProject> hasFolder(String path) {
return new HasFolderMatcher(path);
}
Modified:
sling/trunk/tooling/ide/eclipse-test/src/org/apache/sling/ide/test/impl/helpers/HasFileMatcher.java
URL:
http://svn.apache.org/viewvc/sling/trunk/tooling/ide/eclipse-test/src/org/apache/sling/ide/test/impl/helpers/HasFileMatcher.java?rev=1597070&r1=1597069&r2=1597070&view=diff
==============================================================================
---
sling/trunk/tooling/ide/eclipse-test/src/org/apache/sling/ide/test/impl/helpers/HasFileMatcher.java
(original)
+++
sling/trunk/tooling/ide/eclipse-test/src/org/apache/sling/ide/test/impl/helpers/HasFileMatcher.java
Fri May 23 12:07:17 2014
@@ -31,10 +31,6 @@ import org.hamcrest.TypeSafeMatcher;
public class HasFileMatcher extends TypeSafeMatcher<IProject> {
- public static final HasFileMatcher hasFile(String filePath, byte[]
contents) {
- return new HasFileMatcher(filePath, contents);
- }
-
private final String fileName;
private final byte[] contents;
@@ -66,6 +62,10 @@ public class HasFileMatcher extends Type
return false;
}
+ if (contents == null) {
+ return true;
+ }
+
IFile file = (IFile) maybeFile;
ByteArrayOutputStream out = new ByteArrayOutputStream();