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.xml.namespaces</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,43 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: org.springframework.ide.eclipse.xml.namespaces
Bundle-SymbolicName: org.springframework.ide.eclipse.xml.namespaces;singleton:=true
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Import-Package: org.eclipse.core.commands.common,
org.eclipse.core.resources,
org.eclipse.core.runtime,
org.eclipse.core.runtime.jobs,
org.eclipse.core.runtime.preferences,
org.eclipse.jdt.core,
org.eclipse.jdt.internal.core,
org.eclipse.jface.action,
org.eclipse.jface.dialogs,
org.eclipse.jface.preference,
org.eclipse.jface.resource,
org.eclipse.jface.viewers,
org.eclipse.swt,
org.eclipse.swt.events,
org.eclipse.swt.graphics,
org.eclipse.swt.layout,
org.eclipse.swt.widgets,
org.eclipse.ui.plugin,
org.eclipse.wst.common.uriresolver.internal.provisional,
org.osgi.framework,
org.osgi.service.prefs,
org.osgi.service.url,
org.springsource.ide.eclipse.commons.core,
org.springsource.ide.eclipse.commons.core.util,
org.springsource.ide.eclipse.commons.frameworks.core.util,
org.springsource.ide.eclipse.commons.ui
Bundle-Activator: org.springframework.ide.eclipse.xml.namespaces.SpringXmlNamespacesPlugin
Bundle-Version: 4.8.1.qualifier
Export-Package: org.springframework.ide.eclipse.xml.namespaces,
org.springframework.ide.eclipse.xml.namespaces.classpath,
org.springframework.ide.eclipse.xml.namespaces.internal,
org.springframework.ide.eclipse.xml.namespaces.model,
org.springframework.ide.eclipse.xml.namespaces.ui,
org.springframework.ide.eclipse.xml.namespaces.util
Bundle-ActivationPolicy: lazy
Require-Bundle: com.google.guava,
io.projectreactor.reactor-core;bundle-version="3.1.9",
org.reactivestreams.reactive-streams;bundle-version="1.0.2"

View File

@@ -0,0 +1,17 @@
===========================================================
Moving namespaces extension point?
- id: org.springframework.ide.eclipse.beans.ui.namespaces
Results from extension point search:
org.springframework.ide.eclipse.beans.ui.namespaces - org.springframework.ide.eclipse.batch
org.springframework.ide.eclipse.beans.ui.namespaces - org.springframework.ide.eclipse.beans.ui
org.springframework.ide.eclipse.beans.ui.namespaces - org.springframework.ide.eclipse.data.core
org.springframework.ide.eclipse.beans.ui.namespaces - org.springframework.ide.eclipse.integration
org.springframework.ide.eclipse.beans.ui.namespaces - org.springframework.ide.eclipse.security
org.springframework.ide.eclipse.beans.ui.namespaces - org.springframework.ide.eclipse.webflow.ui
If we move extension point to xml.namespaces plugin, the id will change
and each of the references has to be changed.
=============================================================

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,9 @@
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.,\
plugin.xml,\
icons/,\
about.html,\
schema/
src.includes = about.html

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 578 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 598 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 955 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 564 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 580 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 552 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 333 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 603 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 606 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 555 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 624 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 555 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 555 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 583 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 569 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 534 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 604 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 573 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 577 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1015 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 339 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 917 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 577 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 553 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 606 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 317 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 533 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 542 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 590 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 617 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 904 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 568 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 551 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 592 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 592 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 581 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 564 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 587 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 574 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 826 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>
<extension-point id="namespacemanager" name="namespacemanager" schema="schema/namespacemanager.exsd"/>
<extension
point="org.eclipse.wst.common.uriresolver.resolverExtensions">
<resolverExtension
class="org.springframework.ide.eclipse.xml.namespaces.internal.ProjectClasspathExtensibleUriResolver"
priority="high"
stage="postnormalization">
<!-- <projectNature
value="org.springframework.ide.eclipse.core.springnature">
</projectNature> -->
</resolverExtension>
</extension>
<extension
point="org.eclipse.ui.propertyPages">
<page
id="org.springframework.ide.eclipse.beans.ui.namespaces.projectPropertyPage"
name="Namespaces"
class="org.springframework.ide.eclipse.xml.namespaces.ui.preferences.NamespaceVersionPreferencePage"
adaptable="true"
objectClass="org.eclipse.core.resources.IProject"
category="org.springframework.ide.eclipse.beans.ui.properties.ProjectPropertyPage">
<!-- <filter
name="nature"
value="org.springframework.ide.eclipse.core.springnature">
</filter> -->
<keywordReference
id="org.springframework.ide.eclipse.beans.ui.namespaces.keywords">
</keywordReference>
</page>
</extension>
<extension point="org.eclipse.ui.keywords">
<keyword id="org.springframework.ide.eclipse.beans.ui.namespaces.keywords"
label="Spring Beans config xsd schema location version"/>
</extension>
<extension point="org.eclipse.ui.preferencePages">
<page id="org.springframework.ide.eclipse.beans.ui.namespaces.preferencePage"
name="Namespaces"
class="org.springframework.ide.eclipse.xml.namespaces.ui.preferences.NamespaceVersionPreferencePage"
category="org.springsource.ide.eclipse.commons.preferencePage">
</page>
</extension>
</plugin>

View File

@@ -0,0 +1,84 @@
<?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.xml.namespaces</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>
<dependency-resolution>
<extraRequirements>
<requirement>
<type>eclipse-plugin</type>
<id>org.eclipse.jface.text</id>
<versionRange>0.0.0</versionRange>
</requirement>
<requirement>
<type>eclipse-plugin</type>
<id>org.eclipse.ui.ide</id>
<versionRange>0.0.0</versionRange>
</requirement>
</extraRequirements>
</dependency-resolution>
</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,102 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- Schema file written by PDE -->
<schema targetNamespace="org.springframework.ide.eclipse.xml.namespaces" xmlns="http://www.w3.org/2001/XMLSchema">
<annotation>
<appinfo>
<meta.schema plugin="org.springframework.ide.eclipse.xml.namespaces" id="namespacemanager" name="namespacemanager"/>
</appinfo>
<documentation>
[Enter description of this extension point.]
</documentation>
</annotation>
<element name="extension">
<annotation>
<appinfo>
<meta.element />
</appinfo>
</annotation>
<complexType>
<sequence>
<element ref="namespacemanager"/>
</sequence>
<attribute name="point" type="string" use="required">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="id" type="string">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="name" type="string">
<annotation>
<documentation>
</documentation>
<appinfo>
<meta.attribute translatable="true"/>
</appinfo>
</annotation>
</attribute>
</complexType>
</element>
<element name="namespacemanager">
<complexType>
<attribute name="class" type="string" use="required">
<annotation>
<documentation>
</documentation>
<appinfo>
<meta.attribute kind="java" basedOn=":org.springframework.ide.eclipse.xml.namespaces.INamespaceManager"/>
</appinfo>
</annotation>
</attribute>
</complexType>
</element>
<annotation>
<appinfo>
<meta.section type="since"/>
</appinfo>
<documentation>
[Enter the first release in which this extension point appears.]
</documentation>
</annotation>
<annotation>
<appinfo>
<meta.section type="examples"/>
</appinfo>
<documentation>
[Enter extension point usage example here.]
</documentation>
</annotation>
<annotation>
<appinfo>
<meta.section type="apiinfo"/>
</appinfo>
<documentation>
[Enter API information here.]
</documentation>
</annotation>
<annotation>
<appinfo>
<meta.section type="implementation"/>
</appinfo>
<documentation>
[Enter information about supplied implementation of this extension point.]
</documentation>
</annotation>
</schema>

View File

@@ -0,0 +1,27 @@
/*******************************************************************************
* Copyright (c) 2019 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.xml.namespaces;
import java.util.concurrent.CompletableFuture;
import org.eclipse.core.resources.IProject;
import org.springframework.ide.eclipse.xml.namespaces.model.INamespaceDefinitionListener;
import org.springframework.ide.eclipse.xml.namespaces.model.INamespaceDefinitionResolver;
public interface INamespaceManager {
void unregisterNamespaceDefinitionListener(INamespaceDefinitionListener listener);
void registerNamespaceDefinitionListener(INamespaceDefinitionListener listener);
void notifyNamespaceDefinitionListeners(IProject project);
INamespaceDefinitionResolver getNamespaceDefinitionResolver();
CompletableFuture<?> nameSpaceHandlersReady();
}

View File

@@ -0,0 +1,106 @@
/*******************************************************************************
* Copyright (c) 2019 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.xml.namespaces;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.Platform;
import org.springframework.ide.eclipse.xml.namespaces.model.INamespaceDefinition;
import org.springframework.ide.eclipse.xml.namespaces.model.INamespaceDefinitionListener;
import org.springframework.ide.eclipse.xml.namespaces.model.INamespaceDefinitionResolver;
import com.google.common.collect.ImmutableSet;
/**
* Provides {@link INamespaceManager} instance loaded from
* extension point.
*
* @author Kris De Volder
*/
public class NamespaceManagerProvider {
private static String EXTENSION_POINT = SpringXmlNamespacesPlugin.PLUGIN_ID+".namespacemanager";
/**
* Dummy implementation to use when there is no contributed {@link INamespaceManager}
*/
private static INamespaceManager NULL = new INamespaceManager() {
@Override
public void unregisterNamespaceDefinitionListener(INamespaceDefinitionListener listener) {
}
@Override
public void registerNamespaceDefinitionListener(INamespaceDefinitionListener listener) {
}
@Override
public void notifyNamespaceDefinitionListeners(IProject project) {
}
@Override
public INamespaceDefinitionResolver getNamespaceDefinitionResolver() {
return new INamespaceDefinitionResolver() {
@Override
public INamespaceDefinition resolveNamespaceDefinition(String namespaceUri) {
return null;
}
@Override
public Set<INamespaceDefinition> getNamespaceDefinitions() {
return ImmutableSet.of();
}
};
}
@Override
public CompletableFuture<?> nameSpaceHandlersReady() {
return CompletableFuture.completedFuture(null);
}
};
private static INamespaceManager instance;
public static synchronized INamespaceManager get() {
if (instance==null) {
instance = create();
}
return instance;
}
private static INamespaceManager create() {
try {
IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(EXTENSION_POINT);
if (point!=null) {
IExtension[] extensions = point.getExtensions();
if (extensions!=null && extensions.length>0) {
Assert.isLegal(extensions.length==1);
IConfigurationElement[] configs = extensions[0].getConfigurationElements();
if (configs!=null) {
Assert.isLegal(configs.length==1);
return (INamespaceManager) configs[0].createExecutableExtension("class");
}
}
}
} catch (Exception e) {
SpringXmlNamespacesPlugin.log(e);
}
return NULL;
}
}

View File

@@ -0,0 +1,71 @@
/*******************************************************************************
* Copyright (c) 2014 Pivotal Software 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:
* Spring IDE Developers - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.xml.namespaces;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.osgi.service.url.AbstractURLStreamHandlerService;
import org.springframework.ide.eclipse.xml.namespaces.classpath.ProjectResourceLoaderCache;
import org.springframework.ide.eclipse.xml.namespaces.classpath.ResourceLoader;
import org.springsource.ide.eclipse.commons.core.JdtUtils;
/**
* Support for "project-aware" URL protocol. The protocol is for resources
* within JARs. The JARs are located within a Spring project.
*
* @author Alex Boyko
*
*/
public class ProjectAwareUrlStreamHandlerService extends
AbstractURLStreamHandlerService {
public static final String PROJECT_AWARE_PROTOCOL = "project-aware";
public static final String PROJECT_AWARE_PROTOCOL_HEADER = PROJECT_AWARE_PROTOCOL + "://";
@Override
public URLConnection openConnection(URL u) throws IOException {
String systemId = u.toString();
String nameAndLocation = systemId.substring(PROJECT_AWARE_PROTOCOL_HEADER.length());
String projectName = nameAndLocation.substring(0, nameAndLocation.indexOf('/'));
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
String resourceId = nameAndLocation.substring(nameAndLocation.indexOf('/') + 1);
ResourceLoader cl = ProjectResourceLoaderCache.getResourceLoader(project, null);
URL resource = cl.getResource(resourceId);
if (resource != null) {
return resource.openConnection();
}
return null;
}
/**
* Creates a string representation of a project-aware protocol URL from
* project name and a resource name
*
* @param projectName
* spring project name
* @param resourceName
* class loader resource name
* @return URL string
*/
public static String createProjectAwareUrl(String projectName, String resourceName) {
StringBuilder sb = new StringBuilder();
sb.append(ProjectAwareUrlStreamHandlerService.PROJECT_AWARE_PROTOCOL_HEADER);
sb.append(projectName);
sb.append('/');
sb.append(resourceName);
return sb.toString();
}
}

View File

@@ -0,0 +1,204 @@
/*******************************************************************************
* Copyright (c) 2004, 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.xml.namespaces;
import java.util.Hashtable;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.resource.ImageRegistry;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.url.URLConstants;
import org.osgi.service.url.URLStreamHandlerService;
import org.springframework.ide.eclipse.xml.namespaces.internal.ProjectClasspathNamespaceDefinitionResolverCache;
import org.springframework.ide.eclipse.xml.namespaces.model.INamespaceDefinitionResolver;
import org.springframework.ide.eclipse.xml.namespaces.ui.XmlNamespacesUIImages;
/**
* Central access point for the Spring Framework Core plug-in (id
* <code>"org.springframework.ide.eclipse.beans.core"</code>).
*
* @author Torsten Juergeleit
* @author Christian Dupuis
* @author Tomasz Zarna
* @author Martin Lippert
*/
public class SpringXmlNamespacesPlugin extends AbstractUIPlugin {
/**
* Plugin identifier for Spring Beans Core (value <code>org.springframework.ide.eclipse.beans.core</code>).
*/
public static final String PLUGIN_ID = "org.springframework.ide.eclipse.xml.namespaces";
/** preference key to load namespace handler by searching source folders */
public static final String DISABLE_CACHING_FOR_NAMESPACE_LOADING_ID = "disableCachingForNamespaceLoadingFromClasspath";
/** preference key to load namespace handler from classpath */
public static final String LOAD_NAMESPACEHANDLER_FROM_CLASSPATH_ID = "loadNamespaceHandlerFromClasspath";
/** preference key to specify the default namespace version */
public static final String NAMESPACE_DEFAULT_VERSION_PREFERENCE_ID = "default.version.";
/** preference key to specify if versions should be taken from the classpath */
public static final String NAMESPACE_DEFAULT_FROM_CLASSPATH_ID = "default.version.check.classpath";
/** preference key to specify the default namespace version */
public static final String NAMESPACE_PREFIX_PREFERENCE_ID = "prefix.";
/** preference key to specify whether wizards automatically convert all newly inserted namespace
* locations into https */
public static final String USE_HTTPS_FOR_SCHEMA_LOCATIONS = "use.https.for.new.namespace.locations";
/** preference key to enable namespace versions per namespace */
public static final String PROJECT_PROPERTY_ID = "enable.project.preferences";
/** preference key to suppress missing namespace handler warnings */
public static final String IGNORE_MISSING_NAMESPACEHANDLER_PROPERTY = "ignoreMissingNamespaceHandler";
public static final boolean IGNORE_MISSING_NAMESPACEHANDLER_PROPERTY_DEFAULT = false;
/** The shared instance */
private static SpringXmlNamespacesPlugin plugin;
/**
* Creates the Spring Beans Core plug-in.
* <p>
* The plug-in instance is created automatically by the Eclipse platform. Clients must not call.
*/
public SpringXmlNamespacesPlugin() {
plugin = this;
}
/**
* Monitor used for dealing with the bundle activator and synchronous bundle threads
*/
private transient final Object monitor = new Object();
/**
* flag indicating whether the context is down or not - useful during shutdown
*/
private volatile boolean isClosed = false;
private ServiceRegistration<?> projectAwareUrlService = null;
@Override
protected void initializeImageRegistry(ImageRegistry registry) {
XmlNamespacesUIImages.initializeImageRegistry(registry);
}
@Override
public void start(final BundleContext context) throws Exception {
super.start(context);
Hashtable<String, String> properties = new Hashtable<String, String>();
properties.put(URLConstants.URL_HANDLER_PROTOCOL,
ProjectAwareUrlStreamHandlerService.PROJECT_AWARE_PROTOCOL);
projectAwareUrlService = context.registerService(
URLStreamHandlerService.class.getName(),
new ProjectAwareUrlStreamHandlerService(), properties);
// executorService = Executors.newCachedThreadPool(new ThreadFactory() {
//
// public Thread newThread(Runnable runnable) {
// Version version = Version.parseVersion(getPluginVersion());
// String productId = "Spring IDE";
// IProduct product = Platform.getProduct();
// if (product != null && "com.springsource.sts".equals(product.getId()))
// productId = "STS";
// Thread reportingThread = new Thread(runnable, String.format(THREAD_NAME_TEMPLATE, threadCount.incrementAndGet(),
// productId, version.getMajor(), version.getMinor(), version.getMicro()));
// reportingThread.setDaemon(true);
// return reportingThread;
// }
// });
// getPreferenceStore().setDefault(TIMEOUT_CONFIG_LOADING_PREFERENCE_ID, 60);
getPreferenceStore().setDefault(NAMESPACE_DEFAULT_FROM_CLASSPATH_ID, true);
getPreferenceStore().setDefault(LOAD_NAMESPACEHANDLER_FROM_CLASSPATH_ID, true);
}
@Override
public void stop(BundleContext context) throws Exception {
synchronized (monitor) {
// if already closed, bail out
if (isClosed) {
return;
}
isClosed = true;
}
// model.stop();
if (projectAwareUrlService != null) {
projectAwareUrlService.unregister();
}
super.stop(context);
}
public static boolean isDebug(String option) {
String value = Platform.getDebugOption(option);
return (value != null && value.equalsIgnoreCase("true") ? true : false);
}
/**
* Returns the shared instance.
*/
public static SpringXmlNamespacesPlugin getDefault() {
return plugin;
}
/**
* Writes the message to the plug-in's log
*
* @param message the text to write to the log
*/
public static void log(String message, Throwable exception) {
IStatus status = createErrorStatus(message, exception);
getDefault().getLog().log(status);
}
public static void log(Throwable exception) {
getDefault().getLog().log(createErrorStatus("Plugin.internal_error", exception));
}
public static IStatus createErrorStatus(String message, Throwable exception) {
return createStatus(IStatus.ERROR, message, exception);
}
public static IStatus createStatus(int severity, String message, Throwable exception) {
return new Status(severity, PLUGIN_ID, 0, message == null ? "" : message, exception);
}
public static void logAsWarning(Throwable exception) {
getDefault().getLog().log(createWarningStatus("Plugin.internal_warning", exception));
}
public static IStatus createWarningStatus(String message, Throwable exception) {
return createStatus(IStatus.WARNING, message, exception);
}
public static INamespaceDefinitionResolver getNamespaceDefinitionResolver(IProject project) {
if (project != null) {
return ProjectClasspathNamespaceDefinitionResolverCache.getResolver(project);
}
return getNamespaceDefinitionResolver();
}
public static INamespaceDefinitionResolver getNamespaceDefinitionResolver() {
return NamespaceManagerProvider.get().getNamespaceDefinitionResolver();
}
}

View File

@@ -0,0 +1,73 @@
/*******************************************************************************
* Copyright (c) 2007, 2012, 2019 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.xml.namespaces;
import org.eclipse.core.resources.IProject;
import org.springsource.ide.eclipse.commons.core.SpringCorePreferences;
public class XmlNamespaceUtils {
public static boolean convertNamespaceLocationsToHttps(IProject project) {
if (SpringCorePreferences.getProjectPreferences(project, SpringXmlNamespacesPlugin.PLUGIN_ID).getBoolean(
SpringXmlNamespacesPlugin.PROJECT_PROPERTY_ID, false)) {
return SpringCorePreferences.getProjectPreferences(project, SpringXmlNamespacesPlugin.PLUGIN_ID).getBoolean(
SpringXmlNamespacesPlugin.USE_HTTPS_FOR_SCHEMA_LOCATIONS, false);
}
return SpringXmlNamespacesPlugin.getDefault().getPluginPreferences().getBoolean(
SpringXmlNamespacesPlugin.USE_HTTPS_FOR_SCHEMA_LOCATIONS);
}
/**
* Converts a given XSD schema location to https if the preference is enabled.
*/
public static String convertToHttps(IProject project, String schemaLocation) {
if (convertNamespaceLocationsToHttps(project) && schemaLocation.startsWith("http:")) {
return "https"+schemaLocation.substring(4);
}
return schemaLocation;
}
/**
* Checks if a project should load namespace handlers from the classpath or use the global catalog.
*/
@SuppressWarnings("deprecation")
public static boolean useNamespacesFromClasspath(IProject project) {
if (project == null) {
return false;
}
if (SpringCorePreferences.getProjectPreferences(project, SpringXmlNamespacesPlugin.PLUGIN_ID).getBoolean(
SpringXmlNamespacesPlugin.PROJECT_PROPERTY_ID, false)) {
return SpringCorePreferences.getProjectPreferences(project, SpringXmlNamespacesPlugin.PLUGIN_ID).getBoolean(
SpringXmlNamespacesPlugin.LOAD_NAMESPACEHANDLER_FROM_CLASSPATH_ID, false);
}
return SpringXmlNamespacesPlugin.getDefault().getPluginPreferences().getBoolean(
SpringXmlNamespacesPlugin.LOAD_NAMESPACEHANDLER_FROM_CLASSPATH_ID);
}
@SuppressWarnings("deprecation")
public static boolean disableCachingForNamespaceLoadingFromClasspath(IProject project) {
if (project == null) {
return false;
}
if (SpringCorePreferences.getProjectPreferences(project, SpringXmlNamespacesPlugin.PLUGIN_ID).getBoolean(
SpringXmlNamespacesPlugin.PROJECT_PROPERTY_ID, false)) {
return SpringCorePreferences.getProjectPreferences(project, SpringXmlNamespacesPlugin.PLUGIN_ID).getBoolean(
SpringXmlNamespacesPlugin.DISABLE_CACHING_FOR_NAMESPACE_LOADING_ID, false);
}
return SpringXmlNamespacesPlugin.getDefault().getPluginPreferences().getBoolean(
SpringXmlNamespacesPlugin.DISABLE_CACHING_FOR_NAMESPACE_LOADING_ID);
}
}

View File

@@ -0,0 +1,271 @@
/*******************************************************************************
* Copyright (c) 2019 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.xml.namespaces.classpath;
import static org.springframework.ide.eclipse.xml.namespaces.classpath.ProjectResourceLoaderCache.shouldFilter;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import org.eclipse.core.runtime.URIUtil;
import org.springframework.ide.eclipse.xml.namespaces.SpringXmlNamespacesPlugin;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import reactor.core.publisher.Flux;
public class FilteringURLResourceLoader extends ResourceLoader {
// private static Map<String, AtomicLong> jarScanned = Collections.synchronizedMap(new HashMap<String, AtomicLong>());
// private static final boolean DEBUG = false;
private static Set<String> _fetchedResources = Collections.synchronizedSet(new HashSet<>());
private static ImmutableSet<String> fetchedResources = ImmutableSet.copyOf(_fetchedResources);
private URL[] urls;
private ResourceLoader parent;
private Set<String> _indexValidFor = ImmutableSet.of();
private ImmutableSetMultimap<String, String> resourcesIndex = null;
public FilteringURLResourceLoader(URL[] directories, ResourceLoader parent) {
this.urls = directories;
this.parent = parent == null ? ResourceLoader.NULL : parent;
}
private static AtomicLong timeUsed = new AtomicLong();
private static AtomicLong request = new AtomicLong();
private static AtomicLong indexBuilt = new AtomicLong();
private static AtomicLong indexReused = new AtomicLong();
// @Override
// public URL getResource(String resourceName) {
// try {
// if (!shouldFilter(resourceName)) {
// URL fromParent = parent.getResource(resourceName);
// if (fromParent!=null) {
// return fromParent;
// }
// Collection<String> resources = getResourcesCollection(resourceName);
// if (!resources.isEmpty()) {
// return new URL(resources.iterator().next());
// }
// }
// } catch (Exception e) {
// SpringXmlNamespacesPlugin.log(e);
// }
// return null;
// }
//
/**
* Get's collection of resources from this resource loader, but excluding resources
* from the parent.
*/
private Collection<String> getResourcesCollection(String resourceName) {
if (!shouldFilter(resourceName)) {
// long start = System.currentTimeMillis();
try {
ensureIndexed(resourceName);
Collection<String> r = resourcesIndex.get(resourceName);
return r != null ? r : ImmutableList.of();
} catch (Exception e) {
SpringXmlNamespacesPlugin.log(e);
// } finally {
// long duration = System.currentTimeMillis() - start;
// long total = timeUsed.addAndGet(duration);
// long requestCount = request.incrementAndGet();
// System.out.println("Time spent finding resources:");
// System.out.println(" requests = " + requestCount);
// System.out.println(" avg = " + total / requestCount);
// System.out.println(" total = " + total);
// System.out.println(" index built/reused = " + indexBuilt.get() +" / "+indexReused.get());
// System.out.println("Jar scan counts:");
// for (Entry<String, AtomicLong> e : jarScanned.entrySet()) {
// System.out.println(" "+e.getValue().get() +": "+e.getKey());
// }
}
}
return ImmutableSet.of();
}
private synchronized void ensureIndexed(String resourceName) {
if (resourcesIndex!=null && isIndexValidFor(resourceName)) {
indexReused.incrementAndGet();
} else {
indexBuilt.incrementAndGet();
synchronized (_fetchedResources) {
if (_fetchedResources.add(resourceName)) {
fetchedResources = ImmutableSet.copyOf(_fetchedResources);
// save(_fetchedResources);
}
}
resourcesIndex = buildIndex(name -> isInterestingByDefault(name) || fetchedResources.contains(name));
_indexValidFor = fetchedResources;
}
}
private boolean isIndexValidFor(String resourceName) {
return isInterestingByDefault(resourceName) || _indexValidFor.contains(resourceName);
}
/**
* If you can predict, based on looking at a resourceName that it is likely to
* be 'interesting' for future lookups, then this method can be overridden so it returns true
* for those 'interesting' resources. This will allow the resource-loader to pre-cache
* the interesting values from the get-go, and thereby avoid rebuilding the
* index multiple times.
* <p>
* The default implementation provided here is optimised specifically for resolving
* spring .xsd schemas.
*/
protected boolean isInterestingByDefault(String resourceName) {
return resourceName.startsWith("META-INF/spring") || resourceName.endsWith(".xsd");
}
private ImmutableSetMultimap<String, String> buildIndex(Predicate<String> interestingResourceNames) {
ImmutableSetMultimap.Builder<String, String> resources = ImmutableSetMultimap.builder();
//find in our urls
for (URL url : urls) {
try {
if (isZip(url)) {
fetchResourceFromZip(interestingResourceNames, url, resources);
} else {
url.getProtocol().equals("file");
File file = URIUtil.toFile(URIUtil.toURI(url));
if (file.isDirectory()) {
fetchResourceFromDirectory(interestingResourceNames, file, resources);
} else {
fetchResourceFromZip(interestingResourceNames, url, resources);
}
}
} catch (Exception e) {
SpringXmlNamespacesPlugin.log(e);
}
}
return resources.build();
}
private void fetchResourceFromDirectory(Predicate<String> interesttingResourceNames,
File file,
ImmutableSetMultimap.Builder<String, String> resources
) {
try {
Path rootDir = file.toPath();
FileVisitor<Path> visitor = new FileVisitor<Path>() {
final FileVisitResult fvr = FileVisitResult.CONTINUE;
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
return fvr;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
if (attrs.isRegularFile()) {
String name = rootDir.relativize(file).toString();
if (interesttingResourceNames.test(name)) {
resources.put(name, file.toUri().toString());
}
}
return fvr;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
return fvr;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
return fvr;
}
};
Files.walkFileTree(rootDir, visitor);
} catch (IOException e) {
SpringXmlNamespacesPlugin.log(e);
}
}
private void fetchResourceFromZip(Predicate<String> interestingResourceNames, URL url, ImmutableSetMultimap.Builder<String, String> requestor) {
// AtomicLong counter = jarScanned.computeIfAbsent(url.toString(), s -> new AtomicLong());
// counter.incrementAndGet();
try {
try (InputStream input = url.openStream()) {
ZipInputStream zip = new ZipInputStream(input);
ZipEntry ze = zip.getNextEntry();
while (ze!=null) {
String resourceName = ze.getName();
if (interestingResourceNames.test(resourceName)) {
//Example url: jar:file:/home/kdvolder/.m2/repository/org/springframework/boot/spring-boot/2.1.4.RELEASE/spring-boot-2.1.4.RELEASE.jar!/META-INF/spring.factories
// System.out.println("FOUND "+resourceName+" in "+url);
requestor.put(resourceName, "jar:"+url+"!/"+ze);
// } else {
// System.out.println("mismatch: "+ze.getName());
}
ze = zip.getNextEntry();
}
}
} catch (Exception e) {
SpringXmlNamespacesPlugin.log(e);
}
}
private boolean isZip(URL url) {
String path = url.getPath();
return path.endsWith(".jar") || path.endsWith(".zip");
}
@Override
public Flux<URL> getResources(String resourceName) {
if (!shouldFilter(resourceName)) {
Flux<URL> localResources =
Flux.defer(() -> Flux.fromIterable(getResourcesCollection(resourceName)))
.map(resource -> {
try {
return new URL(resource);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
});
return parent.getResources(resourceName)
.concatWith(localResources);
}
return Flux.empty();
}
}

View File

@@ -0,0 +1,537 @@
/*******************************************************************************
* Copyright (c) 2009, 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.xml.namespaces.classpath;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IPathVariableManager;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
import org.eclipse.jdt.core.ElementChangedEvent;
import org.eclipse.jdt.core.IClasspathAttribute;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IElementChangedListener;
import org.eclipse.jdt.core.IJavaElementDelta;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.springframework.ide.eclipse.xml.namespaces.SpringXmlNamespacesPlugin;
import org.springsource.ide.eclipse.commons.core.JdtUtils;
/**
* Internal cache of classpath urls and corresponding resourceloaders.
* @author Christian Dupuis
* @author Martin Lippert
* @since 2.2.5
*/
@SuppressWarnings("deprecation")
public class ProjectResourceLoaderCache {
private static final String FILE_SCHEME = "file";
private static final int CACHE_SIZE = 200;
private static final List<ResourceLoaderCacheEntry> RESOURCELOADER_CACHE = new ArrayList<ResourceLoaderCacheEntry>(CACHE_SIZE);
private static final String DEBUG_OPTION = SpringXmlNamespacesPlugin.PLUGIN_ID + "/java/resourceloader/debug";
private static final boolean DEBUG_RESOURCELOADER = SpringXmlNamespacesPlugin.isDebug(DEBUG_OPTION);
private static IResourceChangeListener resourceChangeListener = null;
private static ResourceLoader addResourceLoaderToCache(IProject project, List<URL> urls, ResourceLoader parentResourceLoader) {
synchronized (RESOURCELOADER_CACHE) {
int nEntries = RESOURCELOADER_CACHE.size();
if (nEntries >= CACHE_SIZE) {
// find obsolete entries or remove entry that was least recently accessed
ResourceLoaderCacheEntry oldest = null;
List<ResourceLoaderCacheEntry> obsoleteResourceLoaders = new ArrayList<ResourceLoaderCacheEntry>(CACHE_SIZE);
for (int i = 0; i < nEntries; i++) {
ResourceLoaderCacheEntry entry = (ResourceLoaderCacheEntry) RESOURCELOADER_CACHE.get(i);
IProject curr = entry.getProject();
if (!curr.exists() || !curr.isAccessible() || !curr.isOpen()) {
obsoleteResourceLoaders.add(entry);
}
else {
if (oldest == null || entry.getLastAccess() < oldest.getLastAccess()) {
oldest = entry;
}
}
}
if (!obsoleteResourceLoaders.isEmpty()) {
for (int i = 0; i < obsoleteResourceLoaders.size(); i++) {
removeResourceLoaderEntryFromCache((ResourceLoaderCacheEntry) obsoleteResourceLoaders.get(i));
}
}
else if (oldest != null) {
removeResourceLoaderEntryFromCache(oldest);
}
}
ResourceLoaderCacheEntry newEntry = new ResourceLoaderCacheEntry(project, urls, parentResourceLoader);
RESOURCELOADER_CACHE.add(newEntry);
return newEntry.getResourceLoader();
}
}
/**
* Add {@link URL}s to the given set of <code>paths</code>.
*/
private static void addClassPathUrls(IProject project, List<URL> paths, Set<IProject> resolvedProjects) {
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
// add project to local cache to prevent adding its classpaths multiple times
if (resolvedProjects.contains(project)) {
return;
}
else {
resolvedProjects.add(project);
}
try {
if (JdtUtils.isJavaProject(project)) {
IJavaProject jp = JavaCore.create(project);
// configured classpath
IClasspathEntry[] classpath = jp.getResolvedClasspath(true);
// add class path entries
for (int i = 0; i < classpath.length; i++) {
IClasspathEntry path = classpath[i];
if (path.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
IPath entryPath = path.getPath();
File file = entryPath.toFile();
if (file.exists()) {
paths.add(file.toURI().toURL());
}
else {
// case for project relative links
String projectName = entryPath.segment(0);
IProject pathProject = root.getProject(projectName);
covertPathToUrl(pathProject, paths, entryPath);
}
}
else if (path.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
// add source path as well for non java resources
IPath sourcePath = path.getPath();
covertPathToUrl(project, paths, sourcePath);
// add source output locations for different source
// folders
IPath sourceOutputPath = path.getOutputLocation();
covertPathToUrl(project, paths, sourceOutputPath);
}
}
// add all depending java projects
for (IJavaProject p : JdtUtils.getAllDependingJavaProjects(jp)) {
addClassPathUrls(p.getProject(), paths, resolvedProjects);
}
// get default output directory
IPath outputPath = jp.getOutputLocation();
covertPathToUrl(project, paths, outputPath);
}
else {
for (IProject p : project.getReferencedProjects()) {
addClassPathUrls(p, paths, resolvedProjects);
}
}
}
catch (Exception e) {
// ignore
}
}
private static void addUri(List<URL> paths, URI uri) throws MalformedURLException {
File file = new File(uri);
// If we keep the following check, non-existing output folders will never be used for the lifetime of
// a resourceloader. this causes issues with clean projects with not-yet existing output folders.
// if (file.exists()) {
if (file.isDirectory()) {
paths.add(new URL(uri.toString() + File.separator));
}
else {
paths.add(uri.toURL());
}
// }
}
private static void covertPathToUrl(IProject project, List<URL> paths, IPath path) throws MalformedURLException {
if (path != null && project != null && path.removeFirstSegments(1) != null
&& project.findMember(path.removeFirstSegments(1)) != null) {
URI uri = project.findMember(path.removeFirstSegments(1)).getRawLocationURI();
if (uri != null) {
String scheme = uri.getScheme();
if (FILE_SCHEME.equalsIgnoreCase(scheme)) {
addUri(paths, uri);
}
else if ("sourcecontrol".equals(scheme)) {
// special case of Rational Team Concert
IPath sourceControlPath = project.findMember(path.removeFirstSegments(1)).getLocation();
File sourceControlFile = sourceControlPath.toFile();
if (sourceControlFile.exists()) {
addUri(paths, sourceControlFile.toURI());
}
}
else {
IPathVariableManager variableManager = ResourcesPlugin.getWorkspace().getPathVariableManager();
addUri(paths, variableManager.resolveURI(uri));
}
}
}
}
private static ResourceLoader findResourceLoaderInCache(IProject project, ResourceLoader parentResourceLoader) {
synchronized (RESOURCELOADER_CACHE) {
for (int i = RESOURCELOADER_CACHE.size() - 1; i >= 0; i--) {
ResourceLoaderCacheEntry entry = (ResourceLoaderCacheEntry) RESOURCELOADER_CACHE.get(i);
IProject curr = entry.getProject();
if (curr == null || !curr.exists() || !curr.isAccessible() || !curr.isOpen()) {
removeResourceLoaderEntryFromCache(entry);
if (DEBUG_RESOURCELOADER) {
System.out.println(String.format("> removing resourceloader for '%s' : total %s",
entry.getProject(), RESOURCELOADER_CACHE.size()));
}
}
else {
if (entry.matches(project, parentResourceLoader)) {
entry.markAsAccessed();
return entry.getResourceLoader();
}
}
}
}
return null;
}
/**
* Iterates all class path entries of the given <code>project</code> and all depending projects.
* <p>
* Note: if <code>useParentResourceLoader</code> is true, the Spring, AspectJ, Commons Logging and ASM bundles are
* automatically added to the paths.
* @param project the {@link IProject}
* @param useParentResourceLoader use the OSGi resourceloader as parent
* @return a set of {@link URL}s that can be used to construct a {@link URLResourceLoader}
*/
public static List<URL> getClassPathUrls(IProject project, ResourceLoader parentResourceLoader) {
// needs to be linked to preserve ordering
List<URL> paths = new ArrayList<URL>();
Set<IProject> resolvedProjects = new HashSet<IProject>();
addClassPathUrls(project, paths, resolvedProjects);
return paths;
}
/**
* Registers internal listeners that listen to changes relevant to clear out stale cache entries.
*/
private static void registerListenersIfRequired() {
if (resourceChangeListener == null) {
resourceChangeListener = new SourceAndOutputLocationResourceChangeListener();
ResourcesPlugin.getWorkspace().addResourceChangeListener(resourceChangeListener);
}
}
/**
* Removes the given {@link ResourceLoaderCacheEntry} from the internal cache.
* @param entry the entry to remove
*/
private static void removeResourceLoaderEntryFromCache(ResourceLoaderCacheEntry entry) {
synchronized (RESOURCELOADER_CACHE) {
if (DEBUG_RESOURCELOADER) {
System.out.println(String.format("> removing resourceloader for '%s' : total %s", entry.getProject()
.getName(), RESOURCELOADER_CACHE.size()));
}
entry.dispose();
RESOURCELOADER_CACHE.remove(entry);
}
}
public static boolean shouldFilter(String name) {
if ("commons-logging.properties".equals(name)) return true;
if (name != null && name.startsWith("META-INF/services/")) {
return (name.indexOf('/', 18) == -1
&& !name.startsWith("org.springframework", 18));
}
return false;
}
/**
* Returns a {@link ResourceLoader} for the given project.
*/
public static ResourceLoader getResourceLoader(IProject project, ResourceLoader parentResourceLoader) {
synchronized (ProjectResourceLoaderCache.class) {
// Setup the root class loader to be used when no explicit parent class loader is given
if (parentResourceLoader==null) {
parentResourceLoader = ResourceLoader.NULL;
}
if (project == null) {
return parentResourceLoader;
}
registerListenersIfRequired();
}
ResourceLoader classLoader = findResourceLoaderInCache(project, parentResourceLoader);
if (classLoader == null) {
List<URL> urls = getClassPathUrls(project, parentResourceLoader);
classLoader = addResourceLoaderToCache(project, urls, parentResourceLoader);
if (DEBUG_RESOURCELOADER) {
System.out.println(String.format("> creating new resourceloader for '%s' with parent '%s' : total %s",
project.getName(), parentResourceLoader, RESOURCELOADER_CACHE.size()));
}
}
return classLoader;
}
/**
* Removes any cached {@link ResourceLoaderCacheEntry} for the given {@link IProject}.
* @param project the project to remove {@link ResourceLoaderCacheEntry} for
*/
protected static void removeResourceLoaderEntryFromCache(IProject project) {
synchronized (RESOURCELOADER_CACHE) {
if (DEBUG_RESOURCELOADER) {
System.out.println(String.format("> removing resourceloader for '%s' : total %s", project.getName(),
RESOURCELOADER_CACHE.size()));
}
for (ResourceLoaderCacheEntry entry : new ArrayList<ResourceLoaderCacheEntry>(RESOURCELOADER_CACHE)) {
if (project.equals(entry.getProject())) {
entry.dispose();
RESOURCELOADER_CACHE.remove(entry);
}
}
}
}
/**
* Internal cache entry
*/
static class ResourceLoaderCacheEntry implements IElementChangedListener {
private URL[] directories;
private ResourceLoader jarResourceLoader;
private long lastAccess;
private ResourceLoader parentResourceLoader;
private IProject project;
private URL[] urls;
public ResourceLoaderCacheEntry(IProject project, List<URL> urls, ResourceLoader parentResourceLoader) {
this.project = project;
this.urls = urls.toArray(new URL[urls.size()]);
this.parentResourceLoader = parentResourceLoader;
markAsAccessed();
JavaCore.addElementChangedListener(this, ElementChangedEvent.POST_CHANGE);
}
public void dispose() {
JavaCore.removeElementChangedListener(this);
this.urls = null;
this.jarResourceLoader = null;
}
public void elementChanged(ElementChangedEvent event) {
IJavaProject javaProject = JdtUtils.getJavaProject(project);
if (javaProject != null) {
for (IJavaElementDelta delta : event.getDelta().getAffectedChildren()) {
if ((delta.getFlags() & IJavaElementDelta.F_RESOLVED_CLASSPATH_CHANGED) != 0
|| (delta.getFlags() & IJavaElementDelta.F_CLASSPATH_CHANGED) != 0) {
if (javaProject.equals(delta.getElement()) || javaProject.isOnClasspath(delta.getElement())) {
removeResourceLoaderEntryFromCache(this);
}
}
}
}
}
public ResourceLoader getResourceLoader() {
ResourceLoader parent = getJarResourceLoader();
return new FilteringURLResourceLoader(directories, parent);
}
public long getLastAccess() {
return lastAccess;
}
public IProject getProject() {
return this.project;
}
public void markAsAccessed() {
lastAccess = System.currentTimeMillis();
}
public boolean matches(IProject project, ResourceLoader parentResourceLoader) {
return this.project.equals(project)
&& ((parentResourceLoader == null && this.parentResourceLoader == null) || (parentResourceLoader != null && parentResourceLoader
.equals(this.parentResourceLoader)));
}
private synchronized ResourceLoader getJarResourceLoader() {
if (jarResourceLoader == null) {
Set<URL> jars = new LinkedHashSet<URL>();
List<URL> dirs = new ArrayList<URL>();
for (URL url : urls) {
if (shouldLoadFromParent(url)) {
jars.add(url);
}
else {
dirs.add(url);
}
}
if (parentResourceLoader == null) {
parentResourceLoader = ResourceLoader.NULL;
}
jarResourceLoader = new FilteringURLResourceLoader((URL[]) jars.toArray(new URL[jars.size()]),
parentResourceLoader);
directories = dirs.toArray(new URL[dirs.size()]);
}
return jarResourceLoader;
}
private boolean shouldLoadFromParent(URL url) {
String path = url.getPath();
if (path.endsWith(".jar") || path.endsWith(".zip")) {
return true;
}
else if (path.contains("/org.eclipse.osgi/bundles/")) {
return true;
}
return false;
}
}
/**
* {@link IResourceChangeListener} to clear the cache whenever new source or output folders are being added.
* @since 2.5.2
*/
static class SourceAndOutputLocationResourceChangeListener implements IResourceChangeListener {
private static final int VISITOR_FLAGS = IResourceDelta.ADDED | IResourceDelta.CHANGED;
/**
* {@inheritDoc}
*/
public void resourceChanged(IResourceChangeEvent event) {
if (event.getSource() instanceof IWorkspace) {
int eventType = event.getType();
switch (eventType) {
case IResourceChangeEvent.POST_CHANGE:
IResourceDelta delta = event.getDelta();
if (delta != null) {
try {
delta.accept(getVisitor(), VISITOR_FLAGS);
}
catch (CoreException e) {
SpringXmlNamespacesPlugin.log("Error while traversing resource change delta", e);
}
}
break;
}
}
else if (event.getSource() instanceof IProject) {
int eventType = event.getType();
switch (eventType) {
case IResourceChangeEvent.POST_CHANGE:
IResourceDelta delta = event.getDelta();
if (delta != null) {
try {
delta.accept(getVisitor(), VISITOR_FLAGS);
}
catch (CoreException e) {
SpringXmlNamespacesPlugin.log("Error while traversing resource change delta", e);
}
}
break;
}
}
}
protected IResourceDeltaVisitor getVisitor() {
return new SourceAndOutputLocationResourceVisitor();
}
/**
* Internal resource delta visitor.
*/
protected class SourceAndOutputLocationResourceVisitor implements IResourceDeltaVisitor {
public final boolean visit(IResourceDelta delta) throws CoreException {
IResource resource = delta.getResource();
switch (delta.getKind()) {
case IResourceDelta.ADDED:
return resourceAdded(resource);
}
return true;
}
protected boolean resourceAdded(IResource resource) {
if (resource instanceof IFolder && JdtUtils.isJavaProject(resource)) {
try {
IJavaProject javaProject = JdtUtils.getJavaProject(resource);
// Safe guard once again
if (javaProject == null) {
return false;
}
// Check the default output location
if (javaProject.getOutputLocation() != null
&& javaProject.getOutputLocation().equals(resource.getFullPath())) {
removeResourceLoaderEntryFromCache(resource.getProject());
return false;
}
// Check any source and output folder location
for (IClasspathEntry entry : javaProject.getRawClasspath()) {
if (resource.getFullPath() != null && resource.getFullPath().equals(entry.getPath())) {
removeResourceLoaderEntryFromCache(resource.getProject());
return false;
}
else if (resource.getFullPath() != null
&& resource.getFullPath().equals(entry.getOutputLocation())) {
removeResourceLoaderEntryFromCache(resource.getProject());
return false;
}
}
}
catch (JavaModelException e) {
SpringXmlNamespacesPlugin.log("Error traversing resource change delta", e);
}
}
return true;
}
}
}
}

View File

@@ -0,0 +1,101 @@
/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed 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
*
* https://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.springframework.ide.eclipse.xml.namespaces.classpath;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Properties;
import org.eclipse.core.runtime.Assert;
import org.springframework.ide.eclipse.xml.namespaces.SpringXmlNamespacesPlugin;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
/**
* Convenient utility methods for loading of {@code java.util.Properties},
* performing standard handling of input streams.
*
* <p>For more configurable properties loading, including the option of a
* customized encoding, consider using the PropertiesLoaderSupport class.
*
* @author Juergen Hoeller
* @author Rob Harrop
* @since 2.0
* @see PropertiesLoaderSupport
*/
public abstract class PropertiesLoaderUtils {
private static final String XML_FILE_EXTENSION = ".xml";
/**
* Load all properties from the specified class path resource
* (in ISO-8859-1 encoding), using the given class loader.
* <p>Merges properties if more than one resource of the same name
* found in the class path.
* @param resourceName the name of the class path resource
* @param classLoader the ClassLoader to use for loading
* (or {@code null} to use the default class loader)
* @return the populated Properties instance
* @throws IOException if loading failed
*/
public static Properties loadAllProperties(String resourceName, ResourceLoader classLoader) {
Assert.isNotNull(resourceName, "Resource name must not be null");
ResourceLoader classLoaderToUse = classLoader;
if (classLoaderToUse == null) {
classLoaderToUse = ResourceLoader.NULL;
}
Flux<URL> urls = classLoaderToUse.getResources(resourceName);
Mono<Properties> propsMono = urls.reduceWith(Properties::new,
(props, url) -> {
try {
URLConnection con = url.openConnection();
useCachesIfNecessary(con);
InputStream is = con.getInputStream();
try {
if (resourceName.endsWith(XML_FILE_EXTENSION)) {
props.loadFromXML(is);
}
else {
props.load(is);
}
}
finally {
is.close();
}
} catch (Exception e) {
SpringXmlNamespacesPlugin.log(e);
}
return props;
}
);
return propsMono.block();
}
/**
* Set the {@link URLConnection#setUseCaches "useCaches"} flag on the
* given connection, preferring {@code false} but leaving the
* flag at {@code true} for JNLP based resources.
* @param con the URLConnection to set the flag on
*/
private static void useCachesIfNecessary(URLConnection con) {
con.setUseCaches(con.getClass().getSimpleName().startsWith("JNLP"));
}
}

View File

@@ -0,0 +1,53 @@
/*******************************************************************************
* Copyright (c) 2019 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.xml.namespaces.classpath;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import reactor.core.publisher.Flux;
/**
* Subset of {@link ClassLoader} interface. Mimicks behavior of
* classloaders but only can be used to load 'resources' as data.
*
* @author Kris De Volder
*/
public abstract class ResourceLoader {
public static final ResourceLoader NULL = new ResourceLoader() {
@Override
public Flux<URL> getResources(String resourceName) {
return Flux.empty();
}
@Override
public String toString() {
return "ResourceLoader.NULL";
}
};
public final URL getResource(String resourceName) {
return getResources(resourceName).blockFirst();
}
protected abstract Flux<URL> getResources(String resourceName);
public final InputStream getResourceAsStream(String name) {
URL url = getResource(name);
try {
return url != null ? url.openStream() : null;
} catch (IOException e) {
return null;
}
}
}

View File

@@ -0,0 +1,253 @@
/******************************************************************************
* Copyright (c) 2006, 2013 VMware Inc., Oracle Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
* The Eclipse Public License is available at
* https://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0
* is available at https://www.opensource.org/licenses/apache2.0.php.
* You may elect to redistribute this code under either of these licenses.
*
* Contributors:
* VMware Inc.
* Oracle Inc.
*****************************************************************************/
package org.springframework.ide.eclipse.xml.namespaces.internal;
import java.io.IOException;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.NoSuchElementException;
import org.eclipse.core.runtime.Assert;
import org.osgi.framework.Bundle;
/**
* ClassLoader backed by an OSGi bundle. Provides the ability to use a separate
* class loader as fall back.
*
* Contains facilities for tracing class loading behaviour so that issues can be
* easily resolved.
*
* For debugging please see {@link DebugUtils}.
*
* This class is copied and modified from the original source code from the
* Eclipse Gemini Blueprint project.
*
* @author Adrian Colyer
* @author Andy Piper
* @author Costin Leau
* @author Martin Lippert
*/
public class BundleDelegatingClassLoader extends ClassLoader {
private static final String NULL_STRING = "null";
private static final Enumeration<URL> EMPTY_RESOURCES = new Enumeration<URL>() {
public boolean hasMoreElements() {
return false;
}
public URL nextElement() {
throw new NoSuchElementException();
}
};
/**
* Transparently enumerates across two enumerations.
*/
private static class CombinedEnumeration<T> implements Enumeration<T> {
private final Enumeration<T> e1;
private final Enumeration<T> e2;
public CombinedEnumeration(Enumeration<T> e1, Enumeration<T> e2) {
this.e1 = e1;
this.e2 = e2;
}
public boolean hasMoreElements() {
return e1.hasMoreElements() || e2.hasMoreElements();
}
public T nextElement() {
if (e1.hasMoreElements()) {
return e1.nextElement();
}
if (e2.hasMoreElements()) {
return e2.nextElement();
}
throw new NoSuchElementException();
}
}
private final ClassLoader bridge;
private final Bundle backingBundle;
/**
* Factory method for creating a class loader over the given bundle.
*
* @param aBundle bundle to use for class loading and resource acquisition
* @return class loader adapter over the given bundle
*/
public static BundleDelegatingClassLoader createBundleClassLoaderFor(Bundle aBundle) {
return createBundleClassLoaderFor(aBundle, null);
}
/**
* Factory method for creating a class loader over the given bundle and with
* a given class loader as fall-back. In case the bundle cannot find a class
* or locate a resource, the given class loader will be used as fall back.
*
* @param bundle bundle used for class loading and resource acquisition
* @param bridge class loader used as fall back in case the bundle cannot
* load a class or find a resource. Can be <code>null</code>
* @return class loader adapter over the given bundle and class loader
*/
public static BundleDelegatingClassLoader createBundleClassLoaderFor(final Bundle bundle, final ClassLoader bridge) {
return AccessController.doPrivileged(new PrivilegedAction<BundleDelegatingClassLoader>() {
public BundleDelegatingClassLoader run() {
return new BundleDelegatingClassLoader(bundle, bridge);
}
});
}
/**
* Private constructor.
*
* Constructs a new <code>BundleDelegatingClassLoader</code> instance.
*
* @param bundle
* @param bridgeLoader
*/
protected BundleDelegatingClassLoader(Bundle bundle, ClassLoader bridgeLoader) {
super(null);
Assert.isNotNull(bundle, "bundle should be non-null");
this.backingBundle = bundle;
this.bridge = bridgeLoader;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
return this.backingBundle.loadClass(name);
}
catch (ClassNotFoundException cnfe) {
throw new ClassNotFoundException(name + " not found from bundle [" + backingBundle.getSymbolicName() + "]",
cnfe);
}
catch (NoClassDefFoundError ncdfe) {
// This is almost always an error
// This is caused by a dependent class failure,
// so make sure we search for the right one.
NoClassDefFoundError e = new NoClassDefFoundError(name + " not found from bundle ["
+ nullSafeNameAndSymName(backingBundle) + "]");
e.initCause(ncdfe);
throw e;
}
}
@Override
protected URL findResource(String name) {
URL url = this.backingBundle.getResource(name);
return url;
}
@Override
protected Enumeration<URL> findResources(String name) throws IOException {
Enumeration<URL> enm = this.backingBundle.getResources(name);
return enm;
}
@Override
public Enumeration<URL> getResources(String name) throws IOException {
Enumeration<URL> resources = this.backingBundle.getResources(name);
if (this.bridge != null) {
Enumeration<URL> bridgeResources = this.bridge.getResources(name);
if (resources == null) {
resources = bridgeResources;
} else if (bridgeResources != null){
resources = new CombinedEnumeration<URL>(resources, bridgeResources);
}
}
// Classloader contract: Never return null but rather an empty enumeration.
return resources != null ? resources : EMPTY_RESOURCES;
}
@Override
public URL getResource(String name) {
URL resource = findResource(name);
if (bridge != null && resource == null) {
resource = bridge.getResource(name);
}
return resource;
}
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
Class<?> clazz = null;
try {
clazz = findClass(name);
}
catch (ClassNotFoundException cnfe) {
if (bridge != null)
clazz = bridge.loadClass(name);
else
throw cnfe;
}
if (resolve) {
resolveClass(clazz);
}
return clazz;
}
@Override
public String toString() {
return "BundleDelegatingClassLoader for [" + nullSafeNameAndSymName(backingBundle) + "]";
}
/**
* Returns the bundle to which this class loader delegates calls to.
*
* @return the backing bundle
*/
public Bundle getBundle() {
return backingBundle;
}
protected String nullSafeNameAndSymName(Bundle bundle) {
if (bundle == null)
return NULL_STRING;
Dictionary<String, String> dict = bundle.getHeaders();
if (dict == null)
return NULL_STRING;
StringBuilder buf = new StringBuilder();
String name = dict.get(org.osgi.framework.Constants.BUNDLE_NAME);
if (name == null)
buf.append(NULL_STRING);
else
buf.append(name);
buf.append(" (");
String sname = dict.get(org.osgi.framework.Constants.BUNDLE_SYMBOLICNAME);
if (sname == null)
buf.append(NULL_STRING);
else
buf.append(sname);
buf.append(")");
return buf.toString();
}
}

View File

@@ -0,0 +1,39 @@
/*******************************************************************************
* Copyright (c) 2013, 2014 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.xml.namespaces.internal;
import org.eclipse.core.resources.IFile;
import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolverExtension;
import org.springframework.ide.eclipse.xml.namespaces.ProjectAwareUrlStreamHandlerService;
/**
* {@link URIResolverExtension} resolves the physical location of schema files on the project classpath using the
* special project-aware protocol that {@link ProjectClasspathExtensibleUriResolver} uses.
*
* @author Martin Lippert
* @since 3.2.0
*/
@SuppressWarnings({ "restriction" })
public class ProjectClasspathExtensibleUriPhysicalLocationResolver implements URIResolverExtension {
public ProjectClasspathExtensibleUriPhysicalLocationResolver() {
}
public String resolve(IFile file, String baseLocation, String publicId, String systemId) {
if (systemId != null && systemId.startsWith(ProjectAwareUrlStreamHandlerService.PROJECT_AWARE_PROTOCOL_HEADER)) {
String nameAndLocation = systemId.substring(ProjectAwareUrlStreamHandlerService.PROJECT_AWARE_PROTOCOL_HEADER.length());
String realSystemId = nameAndLocation.substring(nameAndLocation.indexOf('/') + 1);
return realSystemId;
}
return null;
}
}

View File

@@ -0,0 +1,329 @@
/*******************************************************************************
* Copyright (c) 2010, 2014 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.xml.namespaces.internal;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
import org.eclipse.core.runtime.Preferences.PropertyChangeEvent;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
import org.eclipse.jdt.core.ElementChangedEvent;
import org.eclipse.jdt.core.IElementChangedListener;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaElementDelta;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolverExtension;
import org.springframework.ide.eclipse.xml.namespaces.ProjectAwareUrlStreamHandlerService;
import org.springframework.ide.eclipse.xml.namespaces.SpringXmlNamespacesPlugin;
import org.springframework.ide.eclipse.xml.namespaces.XmlNamespaceUtils;
import org.springframework.ide.eclipse.xml.namespaces.util.DocumentAccessor;
import org.springframework.ide.eclipse.xml.namespaces.util.DocumentAccessor.SchemaLocations;
import org.springsource.ide.eclipse.commons.core.JdtUtils;
import org.springsource.ide.eclipse.commons.core.SpringCorePreferences;
import org.w3c.dom.Document;
/**
* {@link URIResolverExtension} resolves URIs on the project classpath using the
* protocol established by <code>spring.schemas</code> files.
*
* @author Christian Dupuis
* @author Martin Lippert
* @since 2.3.1
*/
@SuppressWarnings({ "restriction", "deprecation" })
public class ProjectClasspathExtensibleUriResolver implements
URIResolverExtension, IElementChangedListener, IPropertyChangeListener,
IPreferenceChangeListener {
private static final String KEY_DISABLE_CACHING_PREFERENCE = SpringXmlNamespacesPlugin.PLUGIN_ID + "."
+ SpringXmlNamespacesPlugin.DISABLE_CACHING_FOR_NAMESPACE_LOADING_ID;
// private static Map<IProject, ProjectClasspathUriResolver> projectResolvers = new ConcurrentHashMap<IProject, ProjectClasspathUriResolver>();
private static ConcurrentMap<IProject, Future<ProjectClasspathUriResolver>> projectResolvers = new ConcurrentHashMap<IProject, Future<ProjectClasspathUriResolver>>();
public ProjectClasspathExtensibleUriResolver() {
JavaCore.addElementChangedListener(this,
ElementChangedEvent.POST_CHANGE);
SpringXmlNamespacesPlugin.getDefault().getPluginPreferences()
.addPropertyChangeListener(this);
}
/**
* {@inheritDoc}
*/
public String resolve(IFile file, String baseLocation, String publicId,
String systemId) {
// systemId is already resolved; so don't touch
if (systemId != null && systemId.startsWith("jar:")) {
return null;
}
// identify the correct project
IProject project = null;
if (file != null) {
project = getBestMatchingProject(file);
} else if (baseLocation != null
&& baseLocation.startsWith(ProjectAwareUrlStreamHandlerService.PROJECT_AWARE_PROTOCOL_HEADER)) {
String nameAndLocation = baseLocation
.substring(ProjectAwareUrlStreamHandlerService.PROJECT_AWARE_PROTOCOL_HEADER
.length());
String projectName = nameAndLocation.substring(0, nameAndLocation.indexOf('/'));
project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
}
// // continue just for identified Spring projects
// if (project == null || BeansCorePlugin.getModel().getProject(project) == null) {
// return null;
// }
if (systemId == null && file != null) {
systemId = findSystemIdFromFile(file, publicId);
}
if (systemId == null && publicId == null) {
return null;
}
ProjectClasspathUriResolver resolver = getProjectResolver(file, project);
if (resolver != null) {
String resolved = resolver.resolveOnClasspath(publicId, systemId);
if (resolved != null) {
resolved = ProjectAwareUrlStreamHandlerService.createProjectAwareUrl(project.getName(), resolved);
}
return resolved;
}
return null;
}
private IProject getBestMatchingProject(IFile file) {
IFile[] files = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(file.getLocationURI());
if (files != null && files.length == 1) {
return files[0].getProject();
}
else if (files != null && files.length > 1) {
IFile shortestPathFile = files[0];
int shortestPathSegmentCount = shortestPathFile.getFullPath().segmentCount();
for (int i = 1; i < files.length; i++) {
int segmentCount = files[i].getFullPath().segmentCount();
if (segmentCount < shortestPathSegmentCount) {
shortestPathFile = files[i];
shortestPathSegmentCount = segmentCount;
}
}
return shortestPathFile.getProject();
}
else {
return null;
}
}
private ProjectClasspathUriResolver getProjectResolver(final IFile file, final IProject project) {
// // no project resolver if not a spring project
// IBeansProject beansProject = BeansCorePlugin.getModel().getProject(project);
// if (beansProject == null) {
// return null;
// }
if (!XmlNamespaceUtils.useNamespacesFromClasspath(project)) {
return null;
}
if (file != null && !checkFileExtension(file/*, beansProject*/)) {
return null;
}
// Special case for 'pom.xml'. We can skip it entirely because it is not used to define spring beans.
// Also... m2e apparantly causes this to be called directly from the UI thread causing major hangs / annoyance.
// See: https://github.com/spring-projects/sts4/issues/318
if (file != null && "pom.xml".equals(file.getName())) {
return null;
}
while (true) {
Future<ProjectClasspathUriResolver> future = projectResolvers.get(project);
if (future == null) {
Callable<ProjectClasspathUriResolver> createResolver = new Callable<ProjectClasspathUriResolver>() {
public ProjectClasspathUriResolver call() throws InterruptedException {
ProjectClasspathUriResolver resolver = new ProjectClasspathUriResolver(
project);
SpringCorePreferences
.getProjectPreferences(project, SpringXmlNamespacesPlugin.PLUGIN_ID)
.getProjectPreferences().addPreferenceChangeListener(ProjectClasspathExtensibleUriResolver.this);
return resolver;
}
};
FutureTask<ProjectClasspathUriResolver> futureTask = new FutureTask<ProjectClasspathUriResolver>(createResolver);
future = projectResolvers.putIfAbsent(project, futureTask);
if (future == null) {
future = futureTask;
futureTask.run();
}
}
try {
return future.get();
}
catch (CancellationException e) {
projectResolvers.remove(project, future);
return null;
}
catch (ExecutionException e) {
return null;
} catch (InterruptedException e) {
return null;
}
}
}
public void elementChanged(ElementChangedEvent event) {
for (IJavaElementDelta delta : event.getDelta().getAffectedChildren()) {
if ((delta.getFlags() & IJavaElementDelta.F_RESOLVED_CLASSPATH_CHANGED) != 0
|| (delta.getFlags() & IJavaElementDelta.F_CLASSPATH_CHANGED) != 0) {
resetForChangedElement(delta.getElement());
} else if ((delta.getFlags() & IJavaElementDelta.F_CLOSED) != 0) {
resetForChangedElement(delta.getElement());
} else if ((delta.getFlags() & IJavaElementDelta.F_OPENED) != 0) {
resetForChangedElement(delta.getElement());
} else if ((delta.getKind() & IJavaElementDelta.REMOVED) != 0) {
resetForChangedElement(delta.getElement());
} else if ((delta.getKind() & IJavaElementDelta.ADDED) != 0) {
resetForChangedElement(delta.getElement());
}
}
}
public void propertyChange(PropertyChangeEvent event) {
if (SpringXmlNamespacesPlugin.DISABLE_CACHING_FOR_NAMESPACE_LOADING_ID
.equals(event.getProperty())) {
projectResolvers.clear();
}
}
public void preferenceChange(PreferenceChangeEvent event) {
if (KEY_DISABLE_CACHING_PREFERENCE.equals(event.getKey())) {
projectResolvers.clear();
}
}
private void resetForChangedElement(IJavaElement element) {
if (element instanceof IJavaProject) {
IProject project = ((IJavaProject) element).getProject();
projectResolvers.remove(project);
SpringCorePreferences
.getProjectPreferences(project, SpringXmlNamespacesPlugin.PLUGIN_ID)
.getProjectPreferences()
.removePreferenceChangeListener(this);
}
for (IProject project : projectResolvers.keySet()) {
IJavaProject javaProject = JdtUtils.getJavaProject(project);
if (javaProject != null) {
if (javaProject.isOnClasspath(element)) {
projectResolvers.remove(project);
SpringCorePreferences
.getProjectPreferences(project,
SpringXmlNamespacesPlugin.PLUGIN_ID)
.getProjectPreferences()
.removePreferenceChangeListener(this);
}
}
}
}
/**
* try to extract the system-id of the given namespace from the xml file
*
* @since 2.6.0
*/
private String findSystemIdFromFile(IFile file, String publicIc) {
InputStream contents = null;
try {
contents = file.getContents();
DocumentBuilderFactory builderFactory = DocumentBuilderFactory
.newInstance();
builderFactory.setValidating(false);
builderFactory.setNamespaceAware(true);
builderFactory.setFeature("http://xml.org/sax/features/validation", false);
builderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
builderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document doc = builder.parse(contents);
DocumentAccessor accessor = new DocumentAccessor();
accessor.pushDocument(doc);
SchemaLocations locations = accessor.getCurrentSchemaLocations();
String location = locations.getSchemaLocation(publicIc);
return location;
} catch (Exception e) {
// do nothing, systemId cannot be identified
} finally {
if (contents != null) {
try {
contents.close();
} catch (IOException e) {
// do nothing, systemId cannot be identified
}
}
}
return null;
}
/**
* Check that the file has a valid file extension.
*/
private boolean checkFileExtension(IFile file/*, IBeansProject project*/) {
if (/*project.*/getConfigSuffixes() != null) {
for (String extension : /*project.*/getConfigSuffixes()) {
if (file.getName().endsWith(extension)) {
return true;
}
}
}
if (file.getName().endsWith(".xsd")) {
return true;
}
return false;
}
private String[] getConfigSuffixes() {
return new String[]{ ".xml" };
}
}

View File

@@ -0,0 +1,325 @@
/*******************************************************************************
* Copyright (c) 2010, 2011 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.xml.namespaces.internal;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
import org.springframework.ide.eclipse.xml.namespaces.NamespaceManagerProvider;
import org.springframework.ide.eclipse.xml.namespaces.SpringXmlNamespacesPlugin;
import org.springframework.ide.eclipse.xml.namespaces.XmlNamespaceUtils;
import org.springframework.ide.eclipse.xml.namespaces.classpath.ProjectResourceLoaderCache;
import org.springframework.ide.eclipse.xml.namespaces.classpath.PropertiesLoaderUtils;
import org.springframework.ide.eclipse.xml.namespaces.classpath.ResourceLoader;
import org.springframework.ide.eclipse.xml.namespaces.model.INamespaceDefinition;
import org.springframework.ide.eclipse.xml.namespaces.model.INamespaceDefinitionListener;
import org.springframework.ide.eclipse.xml.namespaces.model.INamespaceDefinitionResolver;
import org.springframework.ide.eclipse.xml.namespaces.model.NamespaceDefinition;
import org.springframework.ide.eclipse.xml.namespaces.util.TargetNamespaceScanner;
import org.springsource.ide.eclipse.commons.core.SpringCorePreferences;
import org.springsource.ide.eclipse.commons.core.util.CollectionUtils;
import org.springsource.ide.eclipse.commons.core.util.FileCopyUtils;
import org.springsource.ide.eclipse.commons.frameworks.core.util.StringUtils;
/**
* {@link INamespaceDefinitionResolver} that resolves {@link INamespaceDefinition}s from the project's classpath as
* well.
* <p>
* Note: this implementation is currently not in use
* @author Christian Dupuis
* @author Martin Lippert
* @since 2.3.1
* @see BeansCorePlugin#getNamespaceDefinitionResolver(IProject)
*/
@SuppressWarnings("deprecation")
public class ProjectClasspathNamespaceDefinitionResolver implements INamespaceDefinitionResolver {
public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers";
public static final String DEFAULT_SCHEMA_MAPPINGS_LOCATION = "META-INF/spring.schemas";
public static final String DEFAULT_TOOLING_MAPPINGS_LOCATION = "META-INF/spring.tooling";
private Map<String, NamespaceDefinition> namespaceDefinitionRegistry = null;
private final IProject project;
private EnablementPropertyChangeListener propertyChangeListener;
private final INamespaceDefinitionResolver resolver;
public ProjectClasspathNamespaceDefinitionResolver(IProject project) {
this.project = project;
this.resolver = SpringXmlNamespacesPlugin.getNamespaceDefinitionResolver();
init();
registerListeners();
}
/**
* Dispose this resolver instance.
*/
public void dispose() {
unRegisterListeners();
}
/**
* {@inheritDoc}
*/
public Set<INamespaceDefinition> getNamespaceDefinitions() {
return new HashSet<INamespaceDefinition>(namespaceDefinitionRegistry.values());
}
/**
* {@inheritDoc}
*/
public INamespaceDefinition resolveNamespaceDefinition(String namespaceUri) {
return namespaceDefinitionRegistry.get(namespaceUri);
}
/**
* Load all {@link NamespaceDefinition}s from the project classpath. Also handle extraction of icon file.
*/
private void init() {
// long start = System.currentTimeMillis();
this.namespaceDefinitionRegistry = new ConcurrentHashMap<String, NamespaceDefinition>();
// Add in namespace definitions from the classpath
if (XmlNamespaceUtils.useNamespacesFromClasspath(project)) {
ResourceLoader cls = ProjectResourceLoaderCache.getResourceLoader(project, null);
Map<String, String> handlerMappings = new HashMap<String, String>();
Map<String, String> toolingMappings = new HashMap<String, String>();
Properties schemaMappings = new Properties();
// try {
Properties mappings = PropertiesLoaderUtils.loadAllProperties(DEFAULT_HANDLER_MAPPINGS_LOCATION, cls);
CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings);
schemaMappings = PropertiesLoaderUtils.loadAllProperties(DEFAULT_SCHEMA_MAPPINGS_LOCATION, cls);
mappings = PropertiesLoaderUtils.loadAllProperties(DEFAULT_TOOLING_MAPPINGS_LOCATION, cls);
CollectionUtils.mergePropertiesIntoMap(mappings, toolingMappings);
// }
// catch (IOException e) {
// }
for (Object xsd : schemaMappings.keySet()) {
String key = xsd.toString();
String schemaUri = schemaMappings.getProperty(key);
URL url = cls.getResource(schemaUri);
// fallback, if schema location starts with / and therefore fails to be found by classloader
if (url == null && schemaUri.startsWith("/")) {
schemaUri = schemaUri.substring(1);
url = cls.getResource(schemaUri);
}
if (url == null) {
continue;
}
String namespaceUri = TargetNamespaceScanner.getTargetNamespace(url);
if (StringUtils.hasText(namespaceUri)) {
String icon = toolingMappings.get(namespaceUri + "@icon");
String prefix = toolingMappings.get(namespaceUri + "@prefix");
String name = toolingMappings.get(namespaceUri + "@name");
if (namespaceDefinitionRegistry.containsKey(namespaceUri)) {
namespaceDefinitionRegistry.get(namespaceUri).addSchemaLocation(key);
namespaceDefinitionRegistry.get(namespaceUri).addUri(schemaUri);
}
else {
File iconFile = extractIcon(namespaceUri, icon, cls);
NamespaceDefinition namespaceDefinition = new ExternalImageNamespaceDefinition(schemaMappings,
iconFile);
namespaceDefinition.setName(name);
namespaceDefinition.setPrefix(prefix);
namespaceDefinition.setIconPath(icon);
namespaceDefinition.addSchemaLocation(key);
namespaceDefinition.setNamespaceUri(namespaceUri);
namespaceDefinition.addUri(schemaUri);
namespaceDefinitionRegistry.put(namespaceUri, namespaceDefinition);
}
}
}
}
else {
for (INamespaceDefinition namespaceDefinition : resolver.getNamespaceDefinitions()) {
namespaceDefinitionRegistry.put(namespaceDefinition.getNamespaceUri(),
(NamespaceDefinition) namespaceDefinition);
}
}
// System.out.println(String.format("-- loading of namespace definitions took '%s'ms",
// (System.currentTimeMillis() - start)));
}
/**
* Extract icon files from the given classloader and store it on the filesystem for later use.
*/
private File extractIcon(String namespaceUri, String icon, ResourceLoader cls) {
if (StringUtils.hasLength(icon)) {
try {
File iconDir = SpringXmlNamespacesPlugin.getDefault().getStateLocation().append("images").toFile();
if (!iconDir.exists()) {
iconDir.mkdirs();
iconDir.deleteOnExit();
}
int ix = icon.lastIndexOf('.');
File iconFile = null;
if (ix > 0) {
iconFile = new File(iconDir, Integer.toString(namespaceUri.hashCode()) + icon.substring(ix));
}
else {
iconFile = new File(iconDir, Integer.toString(namespaceUri.hashCode()));
}
if (iconFile.exists()) {
return iconFile;
}
FileCopyUtils.copy(cls.getResourceAsStream(icon), new FileOutputStream(iconFile));
return iconFile;
}
catch (Exception e) {
SpringXmlNamespacesPlugin.log(
String.format("Error extracting icon file '%s' for namespace '%s'", icon, namespaceUri), e);
return null;
}
}
return null;
}
/**
* Register the {@link EnablementPropertyChangeListener} listener to get notifications on changes to the project
* preferences.
*/
private void registerListeners() {
propertyChangeListener = new EnablementPropertyChangeListener();
SpringXmlNamespacesPlugin.getDefault().getPluginPreferences().addPropertyChangeListener(propertyChangeListener);
SpringCorePreferences.getProjectPreferences(project, SpringXmlNamespacesPlugin.PLUGIN_ID).getProjectPreferences()
.addPreferenceChangeListener(propertyChangeListener);
NamespaceManagerProvider.get().registerNamespaceDefinitionListener(propertyChangeListener);
}
/**
* Unregister the {@link EnablementPropertyChangeListener}.
*/
private void unRegisterListeners() {
SpringXmlNamespacesPlugin.getDefault().getPluginPreferences().removePropertyChangeListener(propertyChangeListener);
SpringCorePreferences.getProjectPreferences(project, SpringXmlNamespacesPlugin.PLUGIN_ID).getProjectPreferences()
.removePreferenceChangeListener(propertyChangeListener);
NamespaceManagerProvider.get().unregisterNamespaceDefinitionListener(propertyChangeListener);
}
/**
* {@link IPropertyChangeListener} and {@link IPreferenceChangeListener} implementation that detects changes to the
* classpath property.
* @since 2.5.0
*/
private class EnablementPropertyChangeListener implements IPropertyChangeListener, IPreferenceChangeListener,
INamespaceDefinitionListener {
private static final String KEY = SpringXmlNamespacesPlugin.PLUGIN_ID + "."
+ SpringXmlNamespacesPlugin.LOAD_NAMESPACEHANDLER_FROM_CLASSPATH_ID;
private final String nodePath = "/project/" + project.getName() + "/" + SpringXmlNamespacesPlugin.PLUGIN_ID;
/**
* {@inheritDoc}
*/
public void preferenceChange(PreferenceChangeEvent event) {
if (KEY.equals(event.getKey()) && nodePath.equals(event.getNode().absolutePath())) {
init();
}
}
/**
* {@inheritDoc}
*/
public void propertyChange(org.eclipse.core.runtime.Preferences.PropertyChangeEvent event) {
if (SpringXmlNamespacesPlugin.LOAD_NAMESPACEHANDLER_FROM_CLASSPATH_ID.equals(event.getProperty())) {
init();
}
}
/**
* {@inheritDoc}
*/
public void onNamespaceDefinitionRegistered(NamespaceDefinitionChangeEvent event) {
if (!XmlNamespaceUtils.useNamespacesFromClasspath(project)) {
init();
}
}
/**
* {@inheritDoc}
*/
public void onNamespaceDefinitionUnregistered(NamespaceDefinitionChangeEvent event) {
if (!XmlNamespaceUtils.useNamespacesFromClasspath(project)) {
init();
}
}
}
/**
* Extension to {@link NamespaceDefinition} that handles loading of referenced namespace icons from extracted files.
* @since 2.5.0
*/
private class ExternalImageNamespaceDefinition extends NamespaceDefinition {
private final File iconFile;
public ExternalImageNamespaceDefinition(Properties uriMapping, File iconFile) {
super(uriMapping);
this.iconFile = iconFile;
}
/**
* {@inheritDoc}
*/
@Override
public InputStream getIconStream() {
if (iconFile != null && iconFile.exists() && iconFile.canRead()) {
try {
return new FileInputStream(iconFile);
}
catch (FileNotFoundException e) {
return null;
}
}
return null;
}
}
}

View File

@@ -0,0 +1,162 @@
/*******************************************************************************
* Copyright (c) 2010 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.xml.namespaces.internal;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.resources.IProject;
import org.eclipse.jdt.core.ElementChangedEvent;
import org.eclipse.jdt.core.IElementChangedListener;
import org.eclipse.jdt.core.IJavaElementDelta;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.springframework.ide.eclipse.xml.namespaces.model.INamespaceDefinitionResolver;
import org.springsource.ide.eclipse.commons.core.JdtUtils;
/**
* @author Christian Dupuis
*/
public class ProjectClasspathNamespaceDefinitionResolverCache {
private static final int CACHE_SIZE = 12;
private static List<ResolvlerCacheEntry> RESOLVER_CACHE = new ArrayList<ResolvlerCacheEntry>(CACHE_SIZE);
private static INamespaceDefinitionResolver addResolverToCache(IProject project) {
synchronized (RESOLVER_CACHE) {
int nEntries = RESOLVER_CACHE.size();
if (nEntries >= CACHE_SIZE) {
// find obsolete entries or remove entry that was least recently accessed
ResolvlerCacheEntry oldest = null;
List<ResolvlerCacheEntry> obsoleteClassLoaders = new ArrayList<ResolvlerCacheEntry>(CACHE_SIZE);
for (int i = 0; i < nEntries; i++) {
ResolvlerCacheEntry entry = RESOLVER_CACHE.get(i);
IProject curr = entry.getProject();
if (!curr.exists() || !curr.isAccessible() || !curr.isOpen()) {
obsoleteClassLoaders.add(entry);
}
else {
if (oldest == null || entry.getLastAccess() < oldest.getLastAccess()) {
oldest = entry;
}
}
}
if (!obsoleteClassLoaders.isEmpty()) {
for (int i = 0; i < obsoleteClassLoaders.size(); i++) {
removeResolverEntryFromCache(obsoleteClassLoaders.get(i));
}
}
else if (oldest != null) {
removeResolverEntryFromCache(oldest);
}
}
ResolvlerCacheEntry newEntry = new ResolvlerCacheEntry(project);
RESOLVER_CACHE.add(newEntry);
return newEntry.getResolver();
}
}
private static INamespaceDefinitionResolver findResolverInCache(IProject project) {
synchronized (RESOLVER_CACHE) {
for (int i = RESOLVER_CACHE.size() - 1; i >= 0; i--) {
ResolvlerCacheEntry entry = RESOLVER_CACHE.get(i);
IProject curr = entry.getProject();
if (!curr.exists() || !curr.isAccessible() || !curr.isOpen()) {
removeResolverEntryFromCache(entry);
}
else {
if (entry.matches(project)) {
entry.markAsAccessed();
return entry.getResolver();
}
}
}
}
return null;
}
private static void removeResolverEntryFromCache(ResolvlerCacheEntry entry) {
synchronized (RESOLVER_CACHE) {
entry.dispose();
RESOLVER_CACHE.remove(entry);
}
}
public synchronized static INamespaceDefinitionResolver getResolver(IProject project) {
INamespaceDefinitionResolver resolver = findResolverInCache(project);
if (resolver == null) {
resolver = addResolverToCache(project);
}
return resolver;
}
/**
* Internal cache entry
*/
private static class ResolvlerCacheEntry implements IElementChangedListener {
private long lastAccess;
private IProject project;
private ProjectClasspathNamespaceDefinitionResolver resolver;
public ResolvlerCacheEntry(IProject project) {
this.project = project;
this.resolver = new ProjectClasspathNamespaceDefinitionResolver(project);
markAsAccessed();
JavaCore.addElementChangedListener(this, ElementChangedEvent.POST_CHANGE);
}
public void dispose() {
JavaCore.removeElementChangedListener(this);
resolver.dispose();
resolver = null;
}
public void elementChanged(ElementChangedEvent event) {
IJavaProject javaProject = JdtUtils.getJavaProject(project);
if (javaProject != null) {
for (IJavaElementDelta delta : event.getDelta().getAffectedChildren()) {
if ((delta.getFlags() & IJavaElementDelta.F_RESOLVED_CLASSPATH_CHANGED) != 0
|| (delta.getFlags() & IJavaElementDelta.F_CLASSPATH_CHANGED) != 0) {
if (javaProject.equals(delta.getElement()) || javaProject.isOnClasspath(delta.getElement())) {
removeResolverEntryFromCache(this);
}
}
}
}
}
public INamespaceDefinitionResolver getResolver() {
return resolver;
}
public long getLastAccess() {
return lastAccess;
}
public IProject getProject() {
return this.project;
}
public void markAsAccessed() {
lastAccess = System.currentTimeMillis();
}
public boolean matches(IProject project) {
return this.project.equals(project);
}
}
}

View File

@@ -0,0 +1,224 @@
/*******************************************************************************
* Copyright (c) 2011, 2019 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.xml.namespaces.internal;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import org.eclipse.core.resources.IProject;
import org.springframework.ide.eclipse.xml.namespaces.ProjectAwareUrlStreamHandlerService;
import org.springframework.ide.eclipse.xml.namespaces.SpringXmlNamespacesPlugin;
import org.springframework.ide.eclipse.xml.namespaces.XmlNamespaceUtils;
import org.springframework.ide.eclipse.xml.namespaces.classpath.ProjectResourceLoaderCache;
import org.springframework.ide.eclipse.xml.namespaces.classpath.PropertiesLoaderUtils;
import org.springframework.ide.eclipse.xml.namespaces.classpath.ResourceLoader;
import org.springframework.ide.eclipse.xml.namespaces.model.NamespaceDefinition;
import org.springframework.ide.eclipse.xml.namespaces.util.TargetNamespaceScanner;
import org.springsource.ide.eclipse.commons.core.util.CollectionUtils;
/**
* resolves URIs on the project classpath using the protocol established by
* <code>spring.schemas</code> files.
*
* @author Martin Lippert
* @since 2.7.0
*/
public class ProjectClasspathUriResolver {
private final IProject project;
private boolean disableCaching;
private Map<String, String> typePublic;
private Map<String, String> typeUri;
private Map<String, String> schemaMappings;
public ProjectClasspathUriResolver(IProject project) {
this.project = project;
this.disableCaching = XmlNamespaceUtils
.disableCachingForNamespaceLoadingFromClasspath(project);
if (!disableCaching) {
init();
}
}
/**
* Resolves the given <code>systemId</code> on the classpath configured by
* the <code>file</code>'s project.
*/
public String resolveOnClasspath(String publicId, String systemId) {
if (disableCaching) {
return resolveOnClasspathAndSourceFolders(publicId, systemId);
}
return resolveOnClasspathOnly(publicId, systemId);
}
private String resolveOnClasspathAndSourceFolders(String publicId,
String systemId) {
ResourceLoader classLoader = ProjectResourceLoaderCache.getResourceLoader(project, null);
Map<String, String> mappings = getSchemaMappings(classLoader);
if (mappings != null && systemId != null) {
if (mappings.containsKey(systemId)) {
String xsdPath = mappings.get(systemId);
return resolveXsdPathOnClasspath(xsdPath, classLoader);
}
else if (mappings.containsKey(systemId.replace("https://", "http://"))) {
String xsdPath = mappings.get(systemId.replace("https://", "http://"));
return resolveXsdPathOnClasspath(xsdPath, classLoader);
}
else if (mappings.containsKey(systemId.replace("http://", "https://"))) {
String xsdPath = mappings.get(systemId.replace("http://", "https://"));
return resolveXsdPathOnClasspath(xsdPath, classLoader);
}
}
return null;
}
private String resolveOnClasspathOnly(String publicId, String systemId) {
String resolved = null;
if (systemId != null) {
resolved = typeUri.get(systemId);
}
if (resolved == null && systemId != null && systemId.startsWith("https://")) {
resolved = typeUri.get(systemId.replace("https://", "http://"));
}
if (resolved == null && systemId != null && systemId.startsWith("http://")) {
resolved = typeUri.get(systemId.replace("http://", "https://"));
}
if (resolved == null && publicId != null) {
if (!(systemId != null && systemId.endsWith(".xsd"))) {
resolved = typePublic.get(publicId);
}
}
return resolved;
}
private void init() {
this.typePublic = new ConcurrentHashMap<String, String>();
this.typeUri = new ConcurrentHashMap<String, String>();
Map<String, NamespaceDefinition> namespaceDefinitionRegistry = new HashMap<String, NamespaceDefinition>();
ResourceLoader classLoader = ProjectResourceLoaderCache.getResourceLoader(project, null);
schemaMappings = getSchemaMappings(classLoader);
if (schemaMappings != null) {
for (String key : schemaMappings.keySet()) {
String path = schemaMappings.get(key);
// add the resolved path to the list of uris
String resolvedPath = resolveXsdPathOnClasspath(path,
classLoader);
if (resolvedPath != null) {
typeUri.put(key, resolvedPath);
// collect base information to later extract the default uri
String namespaceUri = getTargetNamespace(resolvedPath);
if (namespaceDefinitionRegistry.containsKey(namespaceUri)) {
namespaceDefinitionRegistry.get(namespaceUri)
.addSchemaLocation(key);
namespaceDefinitionRegistry.get(namespaceUri).addUri(
path);
} else {
NamespaceDefinition namespaceDefinition = new NamespaceDefinition(
null);
namespaceDefinition.addSchemaLocation(key);
namespaceDefinition.setNamespaceUri(namespaceUri);
namespaceDefinition.addUri(path);
namespaceDefinitionRegistry.put(namespaceUri,
namespaceDefinition);
}
}
}
// Add catalog entry to namespace uri
for (NamespaceDefinition definition : namespaceDefinitionRegistry
.values()) {
String namespaceKey = definition.getNamespaceUri();
String defaultUri = definition.getDefaultUri();
String resolvedPath = resolveXsdPathOnClasspath(defaultUri,
classLoader);
if (resolvedPath != null) {
typePublic.put(namespaceKey, resolvedPath);
}
}
}
}
/**
* Returns the target namespace URI of the XSD identified by the given
* <code>resolvedPath</code>.
*/
private String getTargetNamespace(String resolvedPath) {
if (resolvedPath == null) {
return null;
}
try {
URL url = new URI(
ProjectAwareUrlStreamHandlerService.createProjectAwareUrl(
project.getName(), resolvedPath)).toURL();
return TargetNamespaceScanner.getTargetNamespace(url);
} catch (URISyntaxException | IOException e) {
SpringXmlNamespacesPlugin.log(e);
}
return null;
}
/**
* Loads all schema mappings from all <code>spring.schemas</code> files on
* the project classpath.
*
* @param classLoader
* The classloader that is used to load the properties
*/
private Map<String, String> getSchemaMappings(ResourceLoader classLoader) {
Map<String, String> handlerMappings = new ConcurrentHashMap<String, String>();
// try {
Properties mappings = PropertiesLoaderUtils
.loadAllProperties(
ProjectClasspathNamespaceDefinitionResolver.DEFAULT_SCHEMA_MAPPINGS_LOCATION,
classLoader);
CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings);
// } catch (IOException ex) {
// // We can ignore this as we simply don't find the xsd file then.
// }
return handlerMappings;
}
private String resolveXsdPathOnClasspath(String xsdPath, ResourceLoader classLoader) {
URL url = classLoader.getResource(xsdPath);
// fallback, if schema location starts with / and therefore fails to be
// found by classloader
if (url == null && xsdPath.startsWith("/")) {
xsdPath = xsdPath.substring(1);
url = classLoader.getResource(xsdPath);
}
return url == null ? null : xsdPath;
}
}

View File

@@ -0,0 +1,66 @@
/*******************************************************************************
* Copyright (c) 2009, 2010 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.xml.namespaces.model;
import java.io.InputStream;
import java.util.Properties;
import java.util.Set;
/**
* Represents a Spring namespace created from reading the <code>spring.tooling</code> file in
* <code>META-INF</code>.
* @author Christian Dupuis
* @since 2.2.5
*/
public interface INamespaceDefinition {
/**
* Returns the namespace prefix this namespace is associated with.
*/
String getPrefix();
/**
* Returns the namepace name.
*/
String getName();
/**
* Returns the InputStream to a namespace icon with the bundle.
*/
InputStream getIconStream();
/**
* Returns a path to a namespace icon with the bundle.
*/
String getIconPath();
/**
* Returns the namespace uri.
*/
String getNamespaceUri();
/**
* Returns all available XSD schema locations.
*/
Set<String> getSchemaLocations();
/**
* Returns the default schema location. By default this is the XSD with the highest version in
* the file name.
*/
String getDefaultSchemaLocation();
/**
* Return the url mappings
*/
Properties getUriMapping();
}

View File

@@ -0,0 +1,52 @@
/*******************************************************************************
* Copyright (c) 2009, 2010 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.xml.namespaces.model;
import org.eclipse.core.resources.IProject;
/**
* Implementations of this interface will receive notifications when {@link INamespaceDefinition} are registered and
* unregistered.
* @author Christian Dupuis
* @since 2.3.0
*/
public interface INamespaceDefinitionListener {
/**
* Event notifying about a processed registration of a {@link INamespaceDefinition}.
*/
void onNamespaceDefinitionRegistered(NamespaceDefinitionChangeEvent event);
/**
* Event notifying about a processed un-registration of a {@link INamespaceDefinition}.
*/
void onNamespaceDefinitionUnregistered(NamespaceDefinitionChangeEvent event);
class NamespaceDefinitionChangeEvent {
private final INamespaceDefinition namespaceDefinition;
private final IProject project;
public NamespaceDefinitionChangeEvent(INamespaceDefinition namespaceDefinition, IProject project) {
this.namespaceDefinition = namespaceDefinition;
this.project = project;
}
public IProject getProject() {
return this.project;
}
public INamespaceDefinition getNamespaceDefinition() {
return namespaceDefinition;
}
}
}

Some files were not shown because too many files have changed in this diff Show More