repo-reorg-2020: moved sts4-relevant spring-ide bundles from https://github.com/spring-projects/spring-ide/releases/tag/REPO-REORG-2020 into sts4 repo

This commit is contained in:
Martin Lippert
2020-09-29 14:00:01 +02:00
parent 8edfab1a16
commit de16884b60
2210 changed files with 160282 additions and 43 deletions

View File

@@ -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.8"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.springframework.ide.eclipse.boot.validation</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>

View File

@@ -0,0 +1,7 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.8

View File

@@ -0,0 +1,23 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Validation
Bundle-SymbolicName: org.springframework.ide.eclipse.boot.validation;singleton:=true
Bundle-Vendor: Pivotal Software Inc.
Bundle-Version: 4.8.1.qualifier
Bundle-Activator: org.springframework.ide.eclipse.boot.validation.BootValidationActivator
Require-Bundle: org.eclipse.core.runtime,
org.eclipse.core.resources,
org.eclipse.jdt.core,
org.springsource.ide.eclipse.commons.livexp,
org.springframework.ide.eclipse.boot,
org.eclipse.ui.workbench,
org.eclipse.ui.ide,
org.eclipse.jdt.ui,
com.google.guava,
org.springsource.ide.eclipse.commons.core,
org.springframework.ide.eclipse.editor.support,
org.eclipse.jface,
org.springsource.ide.eclipse.commons.frameworks.core
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-ActivationPolicy: lazy
Export-Package: org.springframework.ide.eclipse.boot.validation.framework

View File

@@ -0,0 +1,248 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<title>About Spring IDE</title>
<meta name="author" content="Spring IDE Developers">
</head>
<body>
<h2>About Spring IDE</h2>
<p>March 26, 2007</p>
<h3>Abstract</h3>
<p>Spring IDE is a set of plugins which provide a user interface for
<a href="https://www.springframework.org">The Spring Framework</a>'s bean
factory XML configuration files including support for Spring 2.0
namespaces, AOP configuration and Spring Web Flow.</p>
<h3>License</h3>
<p>The Spring IDE Project makes available all content in this
plug-in (&quot;Content&quot;). Unless otherwise indicated below, the
Content is provided to you under the terms and conditions of the Eclipse
Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is
available at <a href="https://www.eclipse.org/legal/epl-v10.html">https://www.eclipse.org/legal/epl-v10.html</a>.
For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
<p>If you did not receive this Content directly from the Spring IDE
Project, the Content is being redistributed by another party
(&quot;Redistributor&quot;) and different terms and conditions may apply
to your use of any object code in the Content. Check the Redistributor's
license that was provided with the Content. If no such license exists,
contact the Redistributor. Unless otherwise indicated below, the terms
and conditions of the EPL still apply to any source code in the Content
and such source code may be obtained at <a href="https://www.eclipse.org">https://www.eclipse.org</a>.</p>
<h3>Third Party Content</h3>
<p>The Content includes items that have been sourced from third
parties as set out below. If you did not receive this Content directly
from the Spring IDE Project, the following is provided for informational
purposes only, and you should look to the Redistributor's license for
terms and conditions of use.</p>
<p><em> <strong>The Spring Framework v3.0.5</strong>
<p>This product includes software developed by the Spring Framework
Project (<a href="https://www.springframework.org">https://www.springframework.org</a>).</p>
<p><em> <strong>Spring Web Flow v2.0.7.A</strong>
<p>This product includes software developed by the Spring Framework
Project (<a href="https://www.springframework.org">https://www.springframework.org</a>).</p>
<p><em> <strong>Spring Web Services v1.5.8</strong>
<p>This product includes software developed by the Spring Framework
Project (<a href="https://www.springframework.org">https://www.springframework.org</a>).</p>
<p><em> <strong>Spring Security v3.0.2</strong>
<p>This product includes software developed by the Spring Framework
Project (<a href="https://www.springframework.org">https://www.springframework.org</a>).</p>
<p><em> <strong>Spring Dynamic Modules for OSGi(TM) Runtimes v2.0.0.M2</strong>
<p>This product includes software developed by the Spring Framework
Project (<a href="https://www.springframework.org">https://www.springframework.org</a>).</p>
<p><em> <strong>Spring Batch v2.1.0</strong>
<p>This product includes software developed by the Spring Framework
Project (<a href="https://www.springframework.org">https://www.springframework.org</a>).</p>
<p><em> <strong>Commons Codec v1.3.0</strong>
<p>This product includes software developed by The Apache Software
Foundation (<a href="https://www.apache.org/">https://www.apache.org/</a>).</p>
<p><em> <strong>Commons Collections v3.2.0</strong>
<p>This product includes software developed by The Apache Software
Foundation (<a href="https://www.apache.org/">https://www.apache.org/</a>).</p>
<p><em> <strong>Commons Logging v1.1.1</strong>
<p>This product includes software developed by The Apache Software
Foundation (<a href="https://www.apache.org/">https://www.apache.org/</a>).</p>
<p><em> <strong>Apache MyFaces v1.2.2</strong>
<p>This product includes software developed by The Apache Software
Foundation (<a href="https://www.apache.org/">https://www.apache.org/</a>).</p>
<p><em> <strong>AspectJ Weaver v1.6.10</strong>
<p>This product includes software developed by The Eclipse Software
Foundation (<a href="https://www.eclipse.org/">https://www.eclipse.org/</a>).</p>
<p><em> <strong>Antlr v3.0.1</strong>
<p>Spring IDE includes a binary version of Antlr v3.0.1 (<a
href="https://www.antlr.org">https://www.antlr.org/</a>).
The source code for Antlr is available from the Antlr download site at
<a href="https://www.antlr.org/download.html">https://www.antlr.org/download.html</a>.
<p>The Antlr license is available at <a
href="https://www.antlr.org/license.html">https://www.antlr.org/license.html</a>.
The license is also reproduced here:</p>
<pre>Copyright (c) 2003-2007, Terence Parr
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions
and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions
and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name of the author nor the names of its contributors may be used to endorse or promote
products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</pre></p>
<p><em> <strong>ASM v2.2.3</strong>
<p>Spring IDE includes a binary version of ASM v2.2.3 (<a
href="https://asm.objectweb.org/index.html">https://asm.objectweb.org/</a>).
The source code for ASM is available from the ObjectWeb download site at
<a href="https://asm.objectweb.org/download/">https://asm.objectweb.org/download/</a>.
<p>The ASM license is available at <a
href="https://asm.objectweb.org/license.html">https://asm.objectweb.org/license.html</a>.
The license is also reproduced here:</p>
<pre>Copyright (c) 2000-2005 INRIA, France Telecom
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
THE POSSIBILITY OF SUCH DAMAGE.
</pre></p>
<p><em> <strong>backport-util-concurrent 3.1.0</strong>
<p>Spring IDE includes a binary version of backport-util-concurrent v3.1.0 (<a
href="https://dcl.mathcs.emory.edu/util/backport-util-concurrent/">https://dcl.mathcs.emory.edu/util/backport-util-concurrent/</a>).
The source code for backport-util-concurrent is available from the download site at
<a href="https://dcl.mathcs.emory.edu/util/backport-util-concurrent/dist/">https://dcl.mathcs.emory.edu/util/backport-util-concurrent/dist/</a>.
<p>The backport-util-concurrent license is available at <a
href="https://creativecommons.org/licenses/publicdomain">https://creativecommons.org/licenses/publicdomain</a>.
The license is also reproduced here:</p>
<pre><em>Copyright-Only Dedication (based on United States law) or Public Domain Certification</em>
The person or persons who have associated work with this document (the
"Dedicator" or "Certifier") hereby either (a) certifies that, to the
best of his knowledge, the work of authorship identified is in the public
domain of the country from which the work is published, or (b) hereby
dedicates whatever copyright the dedicators holds in the work of authorship
identified below (the "Work") to the public domain. A certifier, moreover,
dedicates any copyright interest he may have in the associated work, and
for these purposes, is described as a "dedicator" below.
A certifier has taken reasonable steps to verify the copyright status of
this work. Certifier recognizes that his good faith efforts may not shield
him from liability if in fact the work certified is not in the public domain.
Dedicator makes this dedication for the benefit of the public at large and
to the detriment of the Dedicator's heirs and successors. Dedicator intends
this dedication to be an overt act of relinquishment in perpetuity of all
present and future rights under copyright law, whether vested or contingent,
in the Work. Dedicator understands that such relinquishment of all rights
includes the relinquishment of all rights to enforce (by lawsuit or otherwise)
those copyrights in the Work.
Dedicator recognizes that, once placed in the public domain, the Work may be
freely reproduced, distributed, transmitted, used, modified, built upon, or
otherwise exploited by anyone for any purpose, commercial or non-commercial,
and in any way, including by methods that have not yet been invented or
conceived.
</pre></p>
<p><em> <strong>AOP Alliance</strong>
<p>LICENCE: all the source code provided by AOP Alliance is Public Domain.
</p>
<p><em> <strong>javax.el v1.0.0</strong>
<p>This product includes software distributed by Sun (meanwhile Oracle) under CDDL license
(<a href="https://www.sun.com/cddl/cddl.html">https://www.sun.com/cddl/cddl.html</a>).</p>
<p><em> <strong>javax.jms v1.1.0</strong>
<p>This product includes software distributed by Sun (meanwhile Oracle) under CDDL license
(<a href="https://www.sun.com/cddl/cddl.html">https://www.sun.com/cddl/cddl.html</a>).</p>
<p><em> <strong>javax.servlet v2.5.0</strong>
<p>This product includes software distributed by Sun (meanwhile Oracle) under CDDL license
(<a href="https://www.sun.com/cddl/cddl.html">https://www.sun.com/cddl/cddl.html</a>).</p>
<p><em> <strong>javax.servlet.jsp v2.1.0</strong>
<p>This product includes software distributed by Sun (meanwhile Oracle) under CDDL license
(<a href="https://www.sun.com/cddl/cddl.html">https://www.sun.com/cddl/cddl.html</a>).</p>
<p><em> <strong>javax.servlet.jsp.jstl v1.2.0</strong>
<p>This product includes software distributed by Sun (meanwhile Oracle) under CDDL license
(<a href="https://www.sun.com/cddl/cddl.html">https://www.sun.com/cddl/cddl.html</a>).</p>
<p><em> <strong>javax.activation v1.1.0</strong>
<p>This product includes software distributed by Sun (meanwhile Oracle) under CDDL license
(<a href="https://www.sun.com/cddl/cddl.html">https://www.sun.com/cddl/cddl.html</a>).</p>
<p><em> <strong>javax.annotation v1.0.0</strong>
<p>This product includes software distributed by Sun (meanwhile Oracle) under CDDL license
(<a href="https://www.sun.com/cddl/cddl.html">https://www.sun.com/cddl/cddl.html</a>).</p>
<p><em> <strong>javax.mail v1.4.0</strong>
<p>This product includes software distributed by Sun (meanwhile Oracle) under CDDL license
(<a href="https://www.sun.com/cddl/cddl.html">https://www.sun.com/cddl/cddl.html</a>).</p>
<p><em> <strong>javax.xml.stream v1.0.1</strong>
<p>This product includes software distributed by Sun (meanwhile Oracle) under CDDL license
(<a href="https://www.sun.com/cddl/cddl.html">https://www.sun.com/cddl/cddl.html</a>).</p>
<p><em> <strong>javax.xml.ws v2.1.0</strong>
<p>This product includes software distributed by Sun (meanwhile Oracle) under CDDL license
(<a href="https://www.sun.com/cddl/cddl.html">https://www.sun.com/cddl/cddl.html</a>).</p>
</em></p>
<address>Copyright (c) 2005, 2011 Spring IDE Developers</address>
</body>
</html>

View File

@@ -0,0 +1,5 @@
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.,\
plugin.xml

View File

@@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>
<extension point="org.eclipse.core.resources.markers"
id="problemmarker"
name="Spring Boot Problem">
<super type="org.eclipse.core.resources.problemmarker"/>
<super type="org.eclipse.core.resources.textmarker"/>
<attribute name="ruleId"/>
<attribute name="errorId"/>
<persistent value="true" />
</extension>
<extension point="org.eclipse.ui.ide.markerSupport">
<markerTypeCategory name="Spring Boot Problem">
<markerTypeReference id="org.springframework.ide.eclipse.boot.validation.problemmarker"/>
</markerTypeCategory>
</extension>
<extension
point="org.eclipse.ui.ide.markerResolution">
<markerResolutionGenerator
markerType="org.springframework.ide.eclipse.boot.validation.problemmarker"
class="org.springframework.ide.eclipse.boot.validation.quickfix.BootMarkerResolutionGenerator">
</markerResolutionGenerator>
</extension>
<extension
id="springbootbuilder"
name="Spring Boot Validations Builder"
point="org.eclipse.core.resources.builders">
<builder>
<run
class="org.springframework.ide.eclipse.boot.validation.framework.SpringBootProjectBuilder">
</run>
</builder>
</extension>
<extension
point="org.eclipse.ui.preferencePages">
<page
name="Java Editor"
category="org.springframework.ide.eclipse.boot.ui.preferences.BootPreferencePage"
class="org.springframework.ide.eclipse.boot.validation.preferences.BootValidationPreferencesPage"
id="org.springframework.ide.eclipse.boot.validation.preferences.BootValidationPreferencesPage">
</page>
</extension>
<extension
point="org.eclipse.ui.propertyPages">
<page
id="org.springframework.ide.eclipse.boot.validation.preferences.BootValidationProjectPropertyPage"
name="Boot Java Validation"
class="org.springframework.ide.eclipse.boot.validation.preferences.BootValidationProjectPropertyPage"
adaptable="true"
objectClass="org.eclipse.core.resources.IProject"
category="org.springsource.ide.eclipse.commons.projectPropertyPage">
<keywordReference
id="org.springframework.ide.eclipse.ui.keywords">
</keywordReference>
<enabledWhen>
<or>
<and>
<instanceof
value="org.eclipse.core.resources.IProject">
</instanceof>
<test
property="org.springsource.ide.eclipse.boot.isBootProject">
</test>
</and>
<and>
<instanceof
value="org.eclipse.jdt.core.IJavaProject">
</instanceof>
<test
property="org.springsource.ide.eclipse.boot.javaelement.isInBootProject">
</test>
</and>
</or>
</enabledWhen>
</page>
</extension>
<extension point="org.eclipse.ui.startup">
<startup class="org.springframework.ide.eclipse.boot.validation.BootValidationEnabler"/>
</extension>
</plugin>

View File

@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot.ide</groupId>
<artifactId>org.springframework.boot.ide</artifactId>
<version>4.8.1-SNAPSHOT</version>
<relativePath>../../eclipse-distribution/pom.xml</relativePath>
</parent>
<groupId>org.springframework.ide.eclipse</groupId>
<artifactId>org.springframework.ide.eclipse.boot.validation</artifactId>
<packaging>eclipse-plugin</packaging>
<build>
<plugins>
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>target-platform-configuration</artifactId>
<version>${tycho-version}</version>
<configuration>
<resolver>p2</resolver>
<pomDependencies>ignore</pomDependencies>
</configuration>
</plugin>
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-compiler-plugin</artifactId>
<version>${tycho-version}</version>
</plugin>
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-source-plugin</artifactId>
<version>${tycho-version}</version>
<executions>
<execution>
<id>plugin-source</id>
<phase>generate-sources</phase>
<goals>
<goal>plugin-source</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-p2-plugin</artifactId>
<version>${tycho-version}</version>
<executions>
<execution>
<id>second-generate-p2-metadata</id>
<goals>
<goal>p2-metadata</goal>
</goals>
<phase>verify</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,70 @@
/*******************************************************************************
* Copyright (c) 2017, 2018 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.boot.validation;
import java.util.ArrayList;
import java.util.List;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
public class BootValidationActivator implements BundleActivator {
private static BundleContext context;
static BundleContext getContext() {
return context;
}
private static List<Runnable> onStop;
/*
* (non-Javadoc)
* @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
*/
public void start(BundleContext bundleContext) throws Exception {
BootValidationActivator.context = bundleContext;
}
/*
* (non-Javadoc)
* @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
*/
public void stop(BundleContext bundleContext) throws Exception {
BootValidationActivator.context = null;
for (Runnable runnable : getStopHandlers()) {
runnable.run();
}
}
private static synchronized Runnable[] getStopHandlers() {
if (onStop==null) {
return new Runnable[0];
}
try {
return onStop.toArray(new Runnable[onStop.size()]);
} finally {
onStop = null;
}
}
public static final String PLUGIN_ID = "org.springframework.ide.eclipse.boot.validation";
// public static final String NATURE_ID = PLUGIN_ID+".springbootnature";
public static final String BUILDER_ID = PLUGIN_ID+".springbootbuilder";
public static synchronized void onStop(Runnable runnable) {
if (onStop==null) {
onStop = new ArrayList<>();
}
onStop.add(runnable);
}
}

View File

@@ -0,0 +1,115 @@
/*******************************************************************************
* Copyright (c) 2018 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.boot.validation;
import java.time.Duration;
import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IProject;
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.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jdt.core.IJavaProject;
import org.springframework.ide.eclipse.boot.core.BootPropertyTester;
import org.springsource.ide.eclipse.commons.core.SpringCoreUtils;
import org.springsource.ide.eclipse.commons.core.pstore.IScopedPropertyStore;
import org.springsource.ide.eclipse.commons.core.pstore.PropertyStoreApi;
import org.springsource.ide.eclipse.commons.core.pstore.PropertyStores;
import org.springsource.ide.eclipse.commons.frameworks.core.workspace.ClasspathListenerManager;
import org.springsource.ide.eclipse.commons.livexp.util.Log;
/**
* Watches workspace projects to detect boot projects and install spring
* boot builder that checks validation rules.
*
* @author Kris De Volder
*/
public class BootValidationEnabler implements org.eclipse.ui.IStartup {
class ValidationEnablerStartupJob extends Job {
public ValidationEnablerStartupJob() {
super("Initializing Boot Validation Enabler");
setRule(ResourcesPlugin.getWorkspace().getRuleFactory().buildRule());
setSystem(true);
}
@Override
protected IStatus run(IProgressMonitor arg0) {
Enabler enabler = new Enabler();
ClasspathListenerManager classpathListener = new ClasspathListenerManager(
enabler::checkProject,
true
);
BootValidationActivator.onStop(() -> classpathListener.close());
return Status.OK_STATUS;
}
}
private static class Enabler {
private static final String VALIDATION_INITIALIZED = "boot.validation.initialized";
private final IScopedPropertyStore<IProject> projectProperties = PropertyStores.createForProjects("org.springframework.ide.eclipse");
private void checkProject(IJavaProject jp) {
Job job = new Job("Check Project "+jp.getElementName()) {
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
IProject p = jp.getProject();
if (p.isAccessible()) {
PropertyStoreApi properties = PropertyStores.createApi(PropertyStores.createForScope(p, projectProperties));
if (
!properties.get(VALIDATION_INITIALIZED, false) &&
!hasBuilder(p, BootValidationActivator.BUILDER_ID) &&
BootPropertyTester.isBootProject(p)
) {
properties.put(VALIDATION_INITIALIZED, true); //prevents adding it back automatically a second time, if user somehow removes it.
SpringCoreUtils.addProjectBuilder(p, BootValidationActivator.BUILDER_ID, monitor);
}
}
} catch (Exception e) {
Log.log(e);
}
return Status.OK_STATUS;
}
};
job.setRule(ResourcesPlugin.getWorkspace().getRuleFactory().buildRule());
job.setSystem(true);
job.schedule();
}
private boolean hasBuilder(IProject p, String builderId) throws CoreException {
ICommand[] builderCommands = p.getDescription().getBuildSpec();
if (builderCommands!=null) {
for (ICommand cmd : builderCommands) {
if (cmd.getBuilderName().equals(builderId)) {
return true;
}
}
}
return false;
}
}
@Override
public void earlyStartup() {
//Don't do this stuff actually during startup. Its not critical and it can wait.
new ValidationEnablerStartupJob().schedule(Duration.ofMinutes(1).toMillis());
}
}

View File

@@ -0,0 +1,66 @@
/*******************************************************************************
* Copyright (c) 2015 GoPivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.boot.validation.framework;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.springframework.ide.eclipse.boot.util.Log;
import org.springsource.ide.eclipse.commons.core.MarkerUtils;
public class BootMarkerUtils {
public static IProject getProject(IMarker marker) {
IResource resource = marker.getResource();
if (resource!=null) {
return resource.getProject();
}
return null;
}
/**
* Creates an {@link IMarker validation marker} on the specified resource for the given validation problem.
* <p>
* Adds the originating resource as marker attribute with the key {@link MarkerUtils#ORIGINATING_RESOURCE_KEY}.
*/
public static void createProblemMarker(String markerId, ValidationProblem problem) {
// Use resource used during reporting of the problem as this might be
// more concise.
IResource resource = problem.getResource();
if (resource != null && resource.isAccessible()) {
try {
// Create new marker
IMarker marker = resource.createMarker(markerId);
Map<String, Object> attributes = new HashMap<String, Object>();
attributes.put(IMarker.MESSAGE, problem.getMessage());
attributes.put(IMarker.SEVERITY, new Integer(problem.getSeverity()));
int start = problem.getStart();
if (start>=0) {
attributes.put(IMarker.CHAR_START, start);
attributes.put(IMarker.CHAR_END, problem.getEnd());
}
if (problem.getErrorId() != null) {
attributes.put(IValidationProblemMarker.ERROR_ID, problem.getErrorId());
}
if (problem.getRuleId() != null) {
attributes.put(IValidationProblemMarker.RULE_ID, problem.getRuleId());
}
marker.setAttributes(attributes);
} catch (Exception e) {
Log.log(e);
}
}
}
}

View File

@@ -0,0 +1,22 @@
/*******************************************************************************
* Copyright (c) 2015 GoPivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.boot.validation.framework;
/**
* Abstract superclass for Spring Boot related validation rules. Not much here yet
* as there's only rule at the moment. As more rules are implemented common
* infrastructure can be put in this class.
*
* @author Kris De Volder
*/
public abstract class BootValidationRule implements IValidationRule {
}

View File

@@ -0,0 +1,87 @@
/*******************************************************************************
* Copyright (c) 2015 GoPivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.boot.validation.framework;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.springframework.ide.eclipse.boot.util.Log;
/**
* Model element that holds data for an {@link ICompilationUnit}.
*
* @author Kris De Volder
*/
public class CompilationUnitElement implements IModelElement {
private ICompilationUnit cu;
private IClasspathEntry[] classpath;
public CompilationUnitElement(ICompilationUnit cu) {
Assert.isNotNull(cu);
this.cu = cu;
}
public ICompilationUnit getCompilationUnit() {
return cu;
}
@Override
public IResource getElementResource() {
return cu.getResource();
}
/**
* Fetch the resolved classpath of the project this CU belong to.
*/
public IClasspathEntry[] getClasspath() {
try {
if (classpath==null) {
classpath = cu.getJavaProject().getResolvedClasspath(false);
}
} catch (Exception e) {
//silently ignore problems resolving classpath. Rules depending on classpath should
// not execute if classpath is not known, for whatever reason. Do not spam the error
// log with messages about that.
}
return classpath;
}
public static CompilationUnitElement create(IResource resource) {
try {
IJavaProject project = getJavaProject(resource);
if (project == null) {
return null;
}
if (resource.getType() == IResource.FILE) {
IJavaElement javaEl = JavaCore.create((IFile) resource);
if (javaEl instanceof ICompilationUnit) {
return new CompilationUnitElement((ICompilationUnit) javaEl);
}
}
} catch (Exception e) {
Log.log(e);
}
return null;
}
private static IJavaProject getJavaProject(IResource resource) {
IProject project = resource.getProject();
return JavaCore.create(project);
}
}

View File

@@ -0,0 +1,24 @@
/*******************************************************************************
* Copyright (c) 2017 Spring IDE Developers
* 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
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Spring IDE Developers - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.boot.validation.framework;
import org.eclipse.core.resources.IResource;
/**
* Abstraction for a 'element' that a validation rule can operate on. Typically this represents
* some type of view on an underlying resource. For example if the resource is a .java file then
* the view may be an object that implements an interface specific to inspecting a java Compilation unit.
*/
public interface IModelElement {
IResource getElementResource();
}

View File

@@ -0,0 +1,20 @@
/*******************************************************************************
* Copyright (c) 2017 Spring IDE Developers
* 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
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Spring IDE Developers - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.boot.validation.framework;
import org.eclipse.core.resources.IResource;
import org.springframework.ide.eclipse.editor.support.reconcile.ProblemType;
public interface IValidationContext {
void problem(IResource cu, ProblemType problemId, String msg, int offset, int len);
}

View File

@@ -0,0 +1,39 @@
package org.springframework.ide.eclipse.boot.validation.framework;
import org.eclipse.core.resources.IMarker;
/**
* Markers related with Spring validation problems.
* <p>
* This interface declares constants only; it is not intended to be implemented
* or extended.
* @author Torsten Juergeleit
* @author Christian Dupuis
* @since 2.0
*/
public interface IValidationProblemMarker {
int SEVERITY_WARNING = IMarker.SEVERITY_WARNING;
int SEVERITY_ERROR = IMarker.SEVERITY_ERROR;
/**
* @since 2.0.2
*/
int SEVERITY_INFO = IMarker.SEVERITY_INFO;
/**
* @since 2.3.1
*/
int SEVERITY_UNKOWN = -1;
/**
* Rule ID marker attribute (value <code>"ruleId"</code>).
*/
String RULE_ID = "ruleId";
/**
* Error ID marker attribute (value <code>"errorId"</code>).
*/
String ERROR_ID = "errorId";
}

View File

@@ -0,0 +1,19 @@
/*******************************************************************************
* Copyright (c) 2017 Spring IDE Developers
* 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
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Spring IDE Developers - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.boot.validation.framework;
import org.eclipse.core.runtime.IProgressMonitor;
public interface IValidationRule {
boolean supports(IModelElement element);
void validate(IModelElement cu, IValidationContext context, IProgressMonitor mon);
String getId();
}

View File

@@ -0,0 +1,258 @@
/*******************************************************************************
* Copyright (c) 2012,2015 Spring IDE Developers
* 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
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Spring IDE Developers - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.boot.validation.framework;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
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.IResourceVisitor;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.springframework.ide.eclipse.boot.core.BootPropertyTester;
import org.springframework.ide.eclipse.boot.validation.BootValidationActivator;
import org.springframework.ide.eclipse.boot.validation.rules.ValidationRuleDefinitions;
import org.springframework.ide.eclipse.editor.support.preferences.EditorType;
import org.springframework.ide.eclipse.editor.support.preferences.PreferencesBasedSeverityProvider;
import org.springframework.ide.eclipse.editor.support.reconcile.ProblemSeverity;
import org.springframework.ide.eclipse.editor.support.reconcile.ProblemType;
import org.springframework.ide.eclipse.editor.support.reconcile.SeverityProvider;
import org.springsource.ide.eclipse.commons.core.MarkerUtils;
import org.springsource.ide.eclipse.commons.frameworks.core.workspace.ClasspathListenerManager;
import com.google.common.collect.ImmutableMap;
/**
* @author Torsten Juergeleit
* @author Christian Dupuis
* @author Martin Lippert
* @author Kris De Volder
*/
public class SpringBootProjectBuilder extends IncrementalProjectBuilder {
public static String MARKER_ID = BootValidationActivator.PLUGIN_ID+".problemmarker";
public SpringBootProjectBuilder() {}
private static Map<String, Object> classpathChanged = new ConcurrentHashMap<String, Object>();
private static ClasspathListenerManager classpathListener;
/**
* indicate that the classpath changed for the given project since the last build
* This mirrors the same behavior as the JavaBuilder, which keeps a state between
* builds and checks for classpath changes at every build.
*
* This is triggered by a element change listener in SpringModel that keeps listening
* for classpath changes.
*
* @param projectName The name of the project
*/
private static void classpathChanged(String projectName) {
classpathChanged.put(projectName, ImmutableMap.of());
}
private static synchronized void ensureClasspathListener() {
if (classpathListener==null) {
classpathListener = new ClasspathListenerManager((jp) -> classpathChanged(jp.getElementName()));
}
}
protected final IProject[] build(final int kind, Map<String, String> args, final IProgressMonitor monitor) throws CoreException {
ensureClasspathListener();
final IProject project = getProject();
final IResourceDelta delta = getDelta(project);
// check for classpath changes (that require a full build)
Object removed = classpathChanged.remove(project.getName());
final int buildKind = removed != null ? IncrementalProjectBuilder.FULL_BUILD : kind;
Set<IResource> affectedResources = getAffectedResources(project, buildKind, delta);
List<IValidationRule> rules = ValidationRuleDefinitions.getRuleDefinitions();
if (!affectedResources.isEmpty() && !rules.isEmpty()) {
monitor.beginTask("Validation of Boot Validation Rules", affectedResources.size() * rules.size());
try {
for (IResource rsrc : affectedResources) {
IModelElement element = CompilationUnitElement.create(rsrc);
MarkerUtils.deleteAllMarkers(rsrc, MARKER_ID);
if (element!=null) {
for (IValidationRule rule : rules) {
if (rule.supports(element)) {
rule.validate(element, validationContext(rsrc, rule), new SubProgressMonitor(monitor, 1));
} else {
monitor.worked(1);
}
}
}
}
} finally {
monitor.done();
}
}
return null;
}
private IValidationContext validationContext(IResource rsrc, IValidationRule rule) {
SeverityProvider severityProvider = new PreferencesBasedSeverityProvider(rsrc.getProject(), BootValidationActivator.PLUGIN_ID, EditorType.JAVA);
return (IResource cu, ProblemType problemId, String msg, int offset, int end) -> {
ProblemSeverity severity = severityProvider.getSeverity(problemId);
if (severity==ProblemSeverity.IGNORE) {
return;
}
ValidationProblem problem = new ValidationProblem() {
public int getStart() {
return offset;
}
@Override
public int getSeverity() {
switch (severity) {
case ERROR:
return IMarker.SEVERITY_ERROR;
case WARNING:
return IMarker.SEVERITY_WARNING;
default:
throw new IllegalStateException("Missing switch case? "+severity);
}
}
@Override
public String getRuleId() {
return rule.getId();
}
@Override
public IResource getResource() {
return rsrc;
}
@Override
public String getMessage() {
return msg;
}
@Override
public int getEnd() {
return end;
}
@Override
public String getErrorId() {
return problemId.toString();
}
};
BootMarkerUtils.createProblemMarker(MARKER_ID, problem);
};
}
/**
* Create a list of affected resources from a resource tree.
*/
public static class ResourceTreeVisitor implements IResourceVisitor {
private Set<IResource> resources;
public ResourceTreeVisitor() {
this.resources = new LinkedHashSet<IResource>();
}
public Set<IResource> getResources() {
return resources;
}
public boolean visit(IResource resource) throws CoreException {
if (resource instanceof IFile) {
resources.add(resource);
} else if (resource instanceof IProject) {
resources.add(resource);
}
return true;
}
}
/**
* Collects all affected resources from the given {@link IResourceDelta}.
*/
private Set<IResource> getAffectedResources(IProject project, int kind, IResourceDelta delta) throws CoreException {
Set<IResource> affectedResources;
if (delta == null || kind == IncrementalProjectBuilder.FULL_BUILD) {
ResourceTreeVisitor visitor = new ResourceTreeVisitor();
project.accept(visitor);
affectedResources = visitor.getResources();
}
else {
ResourceDeltaVisitor visitor = new ResourceDeltaVisitor(kind);
delta.accept(visitor);
affectedResources = visitor.getResources();
}
return affectedResources;
}
/**
* Create a list of affected resources from a resource delta.
*/
public static class ResourceDeltaVisitor implements IResourceDeltaVisitor {
private Set<IResource> resources;
public ResourceDeltaVisitor(int kind) {
this.resources = new LinkedHashSet<IResource>();
}
public Set<IResource> getResources() {
return resources;
}
public boolean visit(IResourceDelta aDelta) throws CoreException {
boolean visitChildren = false;
IResource resource = aDelta.getResource();
if (resource instanceof IProject) {
// Only check projects with Spring beans nature
visitChildren = BootPropertyTester.isBootProject((IProject)resource);
if (visitChildren) {
resources.add(resource);
}
}
else if (resource instanceof IFolder) {
resources.add(resource);
visitChildren = true;
}
else if (resource instanceof IFile) {
switch (aDelta.getKind()) {
case IResourceDelta.ADDED:
case IResourceDelta.CHANGED:
resources.add(resource);
visitChildren = true;
break;
case IResourceDelta.REMOVED:
resources.add(resource);
break;
}
}
return visitChildren;
}
}
}

View File

@@ -0,0 +1,23 @@
/*******************************************************************************
* Copyright (c) 2017 Spring IDE Developers
* 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
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Spring IDE Developers - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.boot.validation.framework;
import org.eclipse.core.resources.IResource;
public interface ValidationProblem {
IResource getResource();
String getMessage();
int getSeverity();
String getErrorId();
String getRuleId();
int getStart();
int getEnd();
}

View File

@@ -0,0 +1,41 @@
/*******************************************************************************
* Copyright (c) 2017 Spring IDE Developers
* 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
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Spring IDE Developers - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.boot.validation.preferences;
import java.util.List;
import org.springframework.ide.eclipse.boot.validation.BootValidationActivator;
import org.springframework.ide.eclipse.boot.validation.rules.BootValidationProblemType;
import org.springframework.ide.eclipse.editor.support.preferences.AbstractProblemSeverityPreferencesPage;
import org.springframework.ide.eclipse.editor.support.preferences.EditorType;
import org.springframework.ide.eclipse.editor.support.preferences.ProblemSeverityPreferencesUtil;
import org.springframework.ide.eclipse.editor.support.reconcile.ProblemType;
/**
* @author Kris De Volder
*/
public class BootValidationPreferencesPage extends AbstractProblemSeverityPreferencesPage {
protected List<ProblemType> getProblemTypes() {
return BootValidationProblemType.values();
}
@Override
protected String getEnableProjectPreferencesKey() {
return ProblemSeverityPreferencesUtil.ENABLE_PROJECT_PREFERENCES(EditorType.PROP);
}
@Override
protected String getPluginId() {
return BootValidationActivator.PLUGIN_ID;
}
}

View File

@@ -0,0 +1,41 @@
/*******************************************************************************
* Copyright (c) 2015 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.boot.validation.preferences;
import java.util.List;
import org.springframework.ide.eclipse.boot.validation.BootValidationActivator;
import org.springframework.ide.eclipse.boot.validation.rules.ValidationRuleDefinitions;
import org.springframework.ide.eclipse.editor.support.preferences.AbstractProblemSeverityPreferencesPage;
import org.springframework.ide.eclipse.editor.support.preferences.EditorType;
import org.springframework.ide.eclipse.editor.support.preferences.ProblemSeverityPreferencesUtil;
import org.springframework.ide.eclipse.editor.support.reconcile.ProblemType;
/**
* @author Kris De Volder
*/
public class BootValidationProjectPropertyPage extends AbstractProblemSeverityPreferencesPage {
protected List<ProblemType> getProblemTypes() {
return ValidationRuleDefinitions.getProblemTypes();
}
@Override
protected String getEnableProjectPreferencesKey() {
return ProblemSeverityPreferencesUtil.ENABLE_PROJECT_PREFERENCES(EditorType.JAVA);
}
@Override
protected String getPluginId() {
return BootValidationActivator.PLUGIN_ID;
}
}

View File

@@ -0,0 +1,38 @@
/*******************************************************************************
* Copyright (c) 2015,2017 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.boot.validation.quickfix;
import org.eclipse.core.resources.IMarker;
import org.eclipse.ui.IMarkerResolution;
import org.eclipse.ui.IMarkerResolutionGenerator2;
public class BootMarkerResolutionGenerator implements IMarkerResolutionGenerator2 {
private MarkerResolutionRegistry registry = MarkerResolutionRegistry.DEFAULT_INSTANCE;
/**
* Override default MarkerResolutionRegistry, mainly to make this class more easy to unit test.
*/
public void setRegistry(MarkerResolutionRegistry registry) {
this.registry = registry;
}
@Override
public IMarkerResolution[] getResolutions(IMarker marker) {
return registry.generator(marker).getResolutions(marker);
}
@Override
public boolean hasResolutions(IMarker marker) {
return registry.generator(marker).hasResolutions(marker);
}
}

View File

@@ -0,0 +1,107 @@
/*******************************************************************************
* Copyright (c) 2015 GoPivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.boot.validation.quickfix;
import java.util.ArrayList;
import java.util.Arrays;
import org.eclipse.core.resources.IMarker;
import org.eclipse.ui.IMarkerResolution;
import org.eclipse.ui.IMarkerResolutionGenerator2;
/**
* Static helper methods and constants for composing {@link IMarkerResolutionGenerator2} instances
* using a 'composit' design pattern implementation.
*
* @author Kris De Volder
*/
public class GeneratorComposition {
public static final IMarkerResolution[] NO_RESOLUTIONS = {};
/**
* Marker resolution generator which never generates any marker resolutions.
*/
public static final IMarkerResolutionGenerator2 NULL_GENERATOR = new IMarkerResolutionGenerator2() {
public IMarkerResolution[] getResolutions(IMarker marker) {
return NO_RESOLUTIONS;
}
public boolean hasResolutions(IMarker marker) {
return false;
}
};
public static IMarkerResolutionGenerator2 compose(
IMarkerResolutionGenerator2 a,
IMarkerResolutionGenerator2 b) {
if (a==null || a==NULL_GENERATOR) {
return b;
} else if (b==null || b==NULL_GENERATOR) {
return a;
} else {
return new CompositeGenerator(uncompose(a), uncompose(b));
}
}
///////////////////////////////////////////////////////////////////////////////////////////////
////// implementation stuffs below... should not concern the clients using this class's helper
////// methods
private static IMarkerResolutionGenerator2[] uncompose(IMarkerResolutionGenerator2 g) {
if (g instanceof CompositeGenerator) {
return ((CompositeGenerator)g).uncompose();
}
return new IMarkerResolutionGenerator2[] {g};
}
private static class CompositeGenerator implements IMarkerResolutionGenerator2 {
private IMarkerResolutionGenerator2[] children;
public CompositeGenerator(IMarkerResolutionGenerator2[] children) {
this.children = children;
}
public CompositeGenerator(IMarkerResolutionGenerator2[] children, IMarkerResolutionGenerator2[] moreChildren) {
this.children = Arrays.copyOf(children, children.length+moreChildren.length);
System.arraycopy(moreChildren, 0, this.children, children.length, moreChildren.length);
}
@Override
public IMarkerResolution[] getResolutions(IMarker marker) {
ArrayList<IMarkerResolution> resolutions = new ArrayList<IMarkerResolution>();
for (IMarkerResolutionGenerator2 generator : children) {
IMarkerResolution[] additions = generator.getResolutions(marker);
if (additions!=null && additions.length>0) {
resolutions.addAll(Arrays.asList(additions));
}
}
return resolutions.toArray(new IMarkerResolution[resolutions.size()]);
}
@Override
public boolean hasResolutions(IMarker marker) {
for (IMarkerResolutionGenerator2 generator : children) {
if (generator.hasResolutions(marker)) {
return true;
}
}
return false;
}
public IMarkerResolutionGenerator2[] uncompose() {
return children;
}
}
}

View File

@@ -0,0 +1,80 @@
/*******************************************************************************
* Copyright (c) 2017 Spring IDE Developers
* 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
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Spring IDE Developers - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.boot.validation.quickfix;
import static org.springframework.ide.eclipse.boot.validation.quickfix.GeneratorComposition.NULL_GENERATOR;
import static org.springframework.ide.eclipse.boot.validation.quickfix.GeneratorComposition.compose;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.resources.IMarker;
import org.eclipse.ui.IMarkerResolutionGenerator2;
import org.springframework.ide.eclipse.boot.validation.framework.IValidationProblemMarker;
import org.springframework.ide.eclipse.editor.support.reconcile.ProblemType;
/**
* Manages associations quickfix ids and {@link IMarkerResolutionGenerator2} instances
*
* @author Kris De Volder
*/
public class MarkerResolutionRegistry {
public static final MarkerResolutionRegistry DEFAULT_INSTANCE = new MarkerResolutionRegistry();
/**
* Marker attribute used to associate a resolution generator via registry to
* a marker. This attribute must be set on
*/
public static final String QUICK_FIX_ID_ATTR = IValidationProblemMarker.ERROR_ID;
private Map<String, IMarkerResolutionGenerator2> registry;
/**
* Obtain the generator for the given marker. Never returns null, will return
* NULL_GENERATOR instead
*/
public synchronized IMarkerResolutionGenerator2 generator(IMarker marker) {
if (registry!=null) {
String id = marker.getAttribute(QUICK_FIX_ID_ATTR, null);
if (id!=null) {
IMarkerResolutionGenerator2 registered = registry.get(id);
if (registered!=null) {
return registered;
}
}
}
return NULL_GENERATOR;
}
/**
* Creates a quickfix id. Typically, the id identifies a problem type. The id should
* be registered by whoever/whatever generates the markers of that type. The id
* can also be used by the same entity to 'bind' the registered generator via its
* id to a specific marker.
*
* @param id
* @param generator
*/
public synchronized void register(ProblemType id, IMarkerResolutionGenerator2 generator) {
if (registry==null) {
registry = new HashMap<>();
}
IMarkerResolutionGenerator2 existing = registry.get(id);
if (existing!=null) {
registry.put(id.getId(), compose(existing, generator));
} else {
registry.put(id.getId(), generator);
}
}
}

View File

@@ -0,0 +1,70 @@
/*******************************************************************************
* Copyright (c) 2017 Spring IDE Developers
* 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
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Spring IDE Developers - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.boot.validation.rules;
import java.util.ArrayList;
import java.util.List;
import org.springframework.ide.eclipse.editor.support.reconcile.ProblemSeverity;
import org.springframework.ide.eclipse.editor.support.reconcile.ProblemType;
import com.google.common.collect.ImmutableList;
public class BootValidationProblemType implements ProblemType {
private final String id;
private final ProblemSeverity defaultSeverity;
private static final List<ProblemType> problemTypes = new ArrayList<>();
private String label;
private String description;
public static List<ProblemType> values() {
synchronized (problemTypes) {
return ImmutableList.copyOf(problemTypes);
}
}
public BootValidationProblemType(String id, ProblemSeverity defaultSeverity, String label, String description) {
this.id = id;
this.defaultSeverity = defaultSeverity;
this.label = label;
this.description = description;
synchronized (problemTypes) {
problemTypes.add(this);
}
}
@Override
public String getLabel() {
return label;
}
@Override
public String getDescription() {
return description;
}
@Override
public ProblemSeverity getDefaultSeverity() {
return defaultSeverity;
}
@Override
public String toString() {
return id;
}
public String getId() {
return id;
}
}

View File

@@ -0,0 +1,88 @@
/*******************************************************************************
* Copyright (c) 2015 GoPivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.boot.validation.rules;
import static org.eclipse.jdt.core.IClasspathEntry.CPE_LIBRARY;
import static org.eclipse.jdt.core.IClasspathEntry.CPE_PROJECT;
import static org.eclipse.jdt.core.IClasspathEntry.CPE_SOURCE;
import org.eclipse.jdt.core.IClasspathEntry;
/**
* Abstraction for matcher that checks condition on a classpath.
*
* @author Kris De Volder
*/
public abstract class ClasspathMatcher {
/**
* A 'conservative' value to return when classpath is unknown. Depending on
* what the matcher is used for this may be 'true' or 'false' (i.e. this value
* has to be chosen to avoid false positives when a rule is being checked at
* a time when classpath is in a undefined/inconsistent state.
*/
private boolean defaultValue;
private boolean isCached = false;
private IClasspathEntry[] cachedFor;
private boolean cachedValue;
public ClasspathMatcher(boolean defaultValue) {
this.defaultValue = defaultValue;
}
/**
* Perform the matcher operation on given classpath. The classpath is guaranteed to be not null.
* This method is not meant to be called by clients. (Clients should call 'match')
*/
protected abstract boolean doMatch(IClasspathEntry[] classpath);
protected boolean isProjectWithName(IClasspathEntry entry, String name) {
if (entry.getEntryKind()==CPE_PROJECT) {
return name.equals(entry.getPath().segment(0));
}
return false;
}
protected boolean isSourceFolderInProject(IClasspathEntry e, String projectName) {
if (e.getEntryKind()==CPE_SOURCE) {
return projectName.equals(e.getPath().segment(0));
}
return false;
}
protected boolean isJarNameContaining(IClasspathEntry entry, String nameFragment) {
if (entry.getEntryKind()==CPE_LIBRARY) {
return entry.getPath().toString().contains(nameFragment);
}
return false;
}
public final boolean match(IClasspathEntry[] classpathMaybe) {
if (isCached && cachedFor==classpathMaybe) {
return cachedValue;
} else {
boolean value;
if (classpathMaybe!=null) {
value = doMatch(classpathMaybe);
} else {
value = defaultValue;
}
this.cachedFor = classpathMaybe;
this.isCached = true;
this.cachedValue = value;
return cachedValue;
}
}
}

View File

@@ -0,0 +1,266 @@
/*******************************************************************************
* Copyright (c) 2015 GoPivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.boot.validation.rules;
import static org.springframework.ide.eclipse.boot.validation.framework.BootMarkerUtils.getProject;
import static org.springframework.ide.eclipse.boot.validation.quickfix.GeneratorComposition.NO_RESOLUTIONS;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jdt.core.IAnnotation;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.ISourceRange;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.ui.IMarkerResolution;
import org.eclipse.ui.IMarkerResolutionGenerator2;
import org.springframework.ide.eclipse.boot.core.BootActivator;
import org.springframework.ide.eclipse.boot.core.ISpringBootProject;
import org.springframework.ide.eclipse.boot.core.MavenCoordinates;
import org.springframework.ide.eclipse.boot.core.SpringBootCore;
import org.springframework.ide.eclipse.boot.util.Log;
import org.springframework.ide.eclipse.boot.validation.framework.BootValidationRule;
import org.springframework.ide.eclipse.boot.validation.framework.CompilationUnitElement;
import org.springframework.ide.eclipse.boot.validation.framework.IModelElement;
import org.springframework.ide.eclipse.boot.validation.framework.IValidationContext;
import org.springframework.ide.eclipse.boot.validation.quickfix.MarkerResolutionRegistry;
import org.springframework.ide.eclipse.editor.support.reconcile.ProblemSeverity;
import org.springsource.ide.eclipse.commons.livexp.util.ExceptionUtil;
/**
* Validation rule that checks
*
* if: found @ConfigurationProperties annotation
* then: spring-boot-configuration-processor jar is on the project's classpath
*
* Provides a quickfix to add spring-boot-configuration-processor to dependencies in
* pom-based project.
*
* @author Kris De Volder
*/
public class MissingConfigurationProcessorRule extends BootValidationRule {
private static final String SPRING_BOOT_CONFIGURATION_PROCESSOR = "spring-boot-configuration-processor";
public static final BootValidationProblemType PROBLEM_ID = new BootValidationProblemType("MISSING_CONFIGURATION_PROCESSOR", ProblemSeverity.WARNING,
"Missing Configuration Processor",
"When using @ConfigurationProperties, it is recommended to add the Spring Boot Configuration Processor to a project's classpath"
);
private static final MavenCoordinates DEP_CONFIGURATION_PROCESSOR =
new MavenCoordinates("org.springframework.boot", SPRING_BOOT_CONFIGURATION_PROCESSOR, null);
private static final IMarkerResolutionGenerator2 QUICK_FIX = new IMarkerResolutionGenerator2() {
@Override
public IMarkerResolution[] getResolutions(IMarker marker) {
try {
final ISpringBootProject project = SpringBootCore.create(getProject(marker));
if (project!=null) {
return new IMarkerResolution[] {
new IMarkerResolution() {
@Override
public String getLabel() {
return "Add spring-boot-configuration-processor to pom.xml";
}
@Override
public void run(IMarker marker) {
try {
project.addMavenDependency(DEP_CONFIGURATION_PROCESSOR, true, true);
project.updateProjectConfiguration(); //needed to actually enable APT, m2e does not
// automatically trigger this if a dependency gets added
} catch (Exception e) {
Log.log(e);
}
}
}
};
}
} catch (Exception e) {
Log.log(e);
}
return NO_RESOLUTIONS;
}
@Override
public boolean hasResolutions(IMarker marker) {
try {
IProject project = getProject(marker);
if (project.hasNature(SpringBootCore.M2E_NATURE)) {
return true;
}
} catch (Exception e) {
Log.log(e);
}
return false;
}
};
static {
MarkerResolutionRegistry.DEFAULT_INSTANCE.register(PROBLEM_ID, QUICK_FIX);
}
/**
* Classpath matcher that checks classpath to determine if this rule applies
*/
private static final ClasspathMatcher CLASSPATH_MATCHER = new ClasspathMatcher(false) {
@Override
protected boolean doMatch(IClasspathEntry[] classpath) {
for (IClasspathEntry e : classpath) {
if (
isJarNameContaining(e, SPRING_BOOT_CONFIGURATION_PROCESSOR) ||
isProjectWithName(e, SPRING_BOOT_CONFIGURATION_PROCESSOR) ||
isSourceFolderInProject(e, SPRING_BOOT_CONFIGURATION_PROCESSOR)
) {
//The rule is already satisfied so doesn't need to be checked
return false;
}
}
return true;
}
};
private static final String BUILDSHIP_NATURE = "org.eclipse.buildship.core.gradleprojectnature";
public static class ValidationVisitor {
private IValidationContext context;
private CompilationUnitElement cu;
public ValidationVisitor(IValidationContext context, CompilationUnitElement cu) {
this.context = context;
this.cu = cu;
}
public void visit(ICompilationUnit compilationUnit, IProgressMonitor mon) throws Exception {
if (compilationUnit.exists()) {
IType[] types = compilationUnit.getAllTypes();
mon.beginTask(compilationUnit.getElementName(), types.length);
try {
for (IType t : types) {
visit(t, new SubProgressMonitor(mon, 1));
}
} finally {
mon.done();
}
}
}
private void visit(IType t, IProgressMonitor mon) throws Exception {
IMethod[] methods = t.getMethods();
mon.beginTask(t.getElementName(), 1+methods.length);
try {
IAnnotation annot = getAnnotation(t);
if (annot!=null && annot.exists()) {
visit(annot);
mon.worked(1);
}
for (IMethod m : methods) {
visit(m, new SubProgressMonitor(mon, 1));
}
} finally {
mon.done();
}
}
private IAnnotation getAnnotation(IType t) {
try {
IAnnotation[] all = t.getAnnotations();
if (all!=null) {
for (IAnnotation a : all) {
String name = a.getElementName();
//name could be fully qualified or simple, so check for both
if ("org.springframework.boot.context.properties.ConfigurationProperties".equals(name)
|| "ConfigurationProperties".equals(name)
) {
return a;
}
}
}
} catch (JavaModelException e) {
BootActivator.log(e);
}
return null;
}
private void visit(IAnnotation annot) throws Exception {
warn("When using @ConfigurationProperties it is recommended to add 'spring-boot-configuration-processor' "
+ "to your classpath to generate configuration metadata", annot.getNameRange());
}
private void visit(IMethod m, SubProgressMonitor mon) throws Exception {
mon.beginTask(m.getElementName(), 1);
try {
IAnnotation annot = m.getAnnotation("ConfigurationProperties");
if (annot!=null && annot.exists()) {
visit(annot);
mon.worked(1);
}
} finally {
mon.done();
}
}
void warn(String msg, ISourceRange location) {
if (location!=null) {
context.problem(cu.getElementResource(), PROBLEM_ID, msg, location.getOffset(), location.getOffset()+location.getLength());
// context.addProblems(new ValidationProblem(PROBLEM_ID, IMarker.SEVERITY_WARNING,
// msg, cu.getElementResource(), location));
}
}
}
@Override
public boolean supports(IModelElement element) {
return element instanceof CompilationUnitElement;
}
@Override
public void validate(IModelElement _cu, IValidationContext context, IProgressMonitor mon) {
CompilationUnitElement cu = (CompilationUnitElement) _cu;
try{
if (cu.getCompilationUnit().getJavaProject().getProject().hasNature(BUILDSHIP_NATURE)) {
//Skip validation. We can consider re-enabling this when buildship adds support for configuring
//JDT APT (https://github.com/eclipse/buildship/issues/329). Then it will make sense to look for
//annotation processor on the eclipse processor path.
//Until then annotation processing doesn't really work in Gradle + Buildship anyway and
//validation of this rule is hard (need to ask gradle tooling api which we don't have here)...
//and counter-productive.
//See also:
// - https://github.com/spring-projects/spring-ide/issues/266
// - https://www.pivotaltracker.com/story/show/156543983
return;
}
if (CLASSPATH_MATCHER.match(cu.getClasspath())) {
ValidationVisitor visitor = new ValidationVisitor(context, cu);
visitor.visit(cu.getCompilationUnit(), mon);
}
} catch (Exception e) {
if (ExceptionUtil.getMessage(e).contains("File not found")) {
//Somewhat expected see [aer] https://www.pivotaltracker.com/story/show/133998741
Log.warn(e);
} else {
Log.log(e);
}
}
}
@Override
public String getId() {
return PROBLEM_ID.getId();
}
}

View File

@@ -0,0 +1,10 @@
package org.springframework.ide.eclipse.boot.validation.rules;
import org.springframework.ide.eclipse.boot.validation.framework.CompilationUnitElement;
import org.springframework.ide.eclipse.boot.validation.framework.IModelElement;
public interface ValidationContext {
void problem(IModelElement element, String problemId, String msg, int offset, int len);
}

View File

@@ -0,0 +1,34 @@
/*******************************************************************************
* Copyright (c) 2017 Spring IDE Developers
* 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
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Spring IDE Developers - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.boot.validation.rules;
import java.util.List;
import org.springframework.ide.eclipse.boot.validation.framework.IValidationRule;
import org.springframework.ide.eclipse.editor.support.reconcile.ProblemType;
import com.google.common.collect.ImmutableList;
public class ValidationRuleDefinitions {
public static List<ProblemType> getProblemTypes() {
return ImmutableList.copyOf(BootValidationProblemType.values());
}
private static List<IValidationRule> rules = ImmutableList.of(
(IValidationRule)new MissingConfigurationProcessorRule()
);
public static synchronized List<IValidationRule> getRuleDefinitions() {
return rules;
}
}