Author: gnodet
Date: Tue Apr 12 22:10:44 2016
New Revision: 1738872

URL: http://svn.apache.org/viewvc?rev=1738872&view=rev
Log:
[ARIES-1503] Smarter fix for cxf

CXF jaxws namespace handler imports the standard cxf namespaces, but its 
namespace handler always return a url to the jaxws xsd, which is not used at 
all.
In order to work around those cases, we do allow the dynamic addition of 
namespaces while building the schema.  If a schema can’t be found, we raise a 
MissingNamespaceException which is handled by the BlueprintContainerImpl and 
keep the container in the WaitForNamespaceHandlers state.

Added:
    
aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/namespace/MissingNamespaceException.java
Modified:
    
aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintContainerImpl.java
    
aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/namespace/NamespaceHandlerRegistryImpl.java

Modified: 
aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintContainerImpl.java
URL: 
http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintContainerImpl.java?rev=1738872&r1=1738871&r2=1738872&view=diff
==============================================================================
--- 
aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintContainerImpl.java
 (original)
+++ 
aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/BlueprintContainerImpl.java
 Tue Apr 12 22:10:44 2016
@@ -54,6 +54,7 @@ import org.apache.aries.blueprint.Proces
 import org.apache.aries.blueprint.di.ExecutionContext;
 import org.apache.aries.blueprint.di.Recipe;
 import org.apache.aries.blueprint.di.Repository;
+import org.apache.aries.blueprint.namespace.MissingNamespaceException;
 import org.apache.aries.blueprint.namespace.NamespaceHandlerRegistryImpl;
 import org.apache.aries.blueprint.parser.ComponentDefinitionRegistryImpl;
 import org.apache.aries.blueprint.parser.NamespaceHandlerSet;
@@ -337,15 +338,21 @@ public class BlueprintContainerImpl
                                 }
                             }
                         }
-                        if (xmlValidation == null || 
"true".equals(xmlValidation)) {
-                            
parser.validate(handlerSet.getSchema(parser.getSchemaLocations()));
-                        } else if ("structure".equals(xmlValidation)) {
-                            
parser.validate(handlerSet.getSchema(parser.getSchemaLocations()), new 
ValidationHandler());
-                        } else if ("psvi".equals(xmlValidation)) {
-                            
parser.validatePsvi(handlerSet.getSchema(parser.getSchemaLocations()));
+                        try {
+                            if (xmlValidation == null || 
"true".equals(xmlValidation)) {
+                                
parser.validate(handlerSet.getSchema(parser.getSchemaLocations()));
+                            } else if ("structure".equals(xmlValidation)) {
+                                
parser.validate(handlerSet.getSchema(parser.getSchemaLocations()), new 
ValidationHandler());
+                            } else if ("psvi".equals(xmlValidation)) {
+                                
parser.validatePsvi(handlerSet.getSchema(parser.getSchemaLocations()));
+                            }
+                            parser.populate(handlerSet, 
componentDefinitionRegistry);
+                            state = State.Populated;
+                        } catch (MissingNamespaceException e) {
+                            // If we found a missing namespace when parsing 
the schema,
+                            // we remain in the current state
+                            namespaces.add(e.getNamespace());
                         }
-                        parser.populate(handlerSet, 
componentDefinitionRegistry);
-                        state = State.Populated;
                         break;
                     }
                     case Populated:

Added: 
aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/namespace/MissingNamespaceException.java
URL: 
http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/namespace/MissingNamespaceException.java?rev=1738872&view=auto
==============================================================================
--- 
aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/namespace/MissingNamespaceException.java
 (added)
+++ 
aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/namespace/MissingNamespaceException.java
 Tue Apr 12 22:10:44 2016
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.aries.blueprint.namespace;
+
+import java.net.URI;
+
+public class MissingNamespaceException extends RuntimeException {
+
+    private final URI namespace;
+
+    public MissingNamespaceException(URI namespace) {
+        this.namespace = namespace;
+    }
+
+    public URI getNamespace() {
+        return namespace;
+    }
+}

Modified: 
aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/namespace/NamespaceHandlerRegistryImpl.java
URL: 
http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/namespace/NamespaceHandlerRegistryImpl.java?rev=1738872&r1=1738871&r2=1738872&view=diff
==============================================================================
--- 
aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/namespace/NamespaceHandlerRegistryImpl.java
 (original)
+++ 
aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/namespace/NamespaceHandlerRegistryImpl.java
 Tue Apr 12 22:10:44 2016
@@ -249,25 +249,6 @@ public class NamespaceHandlerRegistryImp
         tracker.close();
     }
 
-    private Schema getSchema(Map<URI, NamespaceHandler> handlers,
-                             final Bundle bundle,
-                             final Properties schemaMap,
-                             Map<String, String> locations) throws 
IOException, SAXException {
-        if (schemaMap != null && !schemaMap.isEmpty()) {
-            return createSchema(handlers, bundle, schemaMap, locations);
-        }
-        // Find a schema that can handle all the requested namespaces
-        // If it contains additional namespaces, it should not be a problem 
since
-        // they won't be used at all
-        Schema schema = getExistingSchema(handlers);
-        if (schema == null) {
-            // Create schema
-            schema = createSchema(handlers, bundle, schemaMap, locations);
-            cacheSchema(handlers, schema);
-        }
-        return schema;
-    }
-
     private Schema getExistingSchema(Map<URI, NamespaceHandler> handlers) {
         synchronized (schemas) {
             for (Map<URI, NamespaceHandler> key : schemas.keySet()) {
@@ -322,51 +303,6 @@ public class NamespaceHandlerRegistryImp
         }
     }
 
-    private Schema createSchema(Map<URI, NamespaceHandler> handlers,
-                                Bundle bundle,
-                                Properties schemaMap,
-                                Map<String, String> locations) throws 
IOException, SAXException {
-        final List<StreamSource> schemaSources = new ArrayList<StreamSource>();
-        final Map<String, URI> urlToNamespace = new HashMap<String, URI>();
-        try {
-            schemaSources.add(new 
StreamSource(getClass().getResourceAsStream("/org/apache/aries/blueprint/blueprint.xsd")));
-            schemaSources.add(new 
StreamSource(getClass().getResourceAsStream("/org/apache/aries/blueprint/ext/impl/xml.xsd")));
-            // Create a schema for all namespaces known at this point
-            // It will speed things as it can be reused for all other 
blueprint containers
-            for (URI ns : handlers.keySet()) {
-                URL url = handlers.get(ns).getSchemaLocation(ns.toString());
-                if (url == null && locations != null) {
-                    String loc = locations.get(ns.toString());
-                    if (loc != null) {
-                        url = handlers.get(ns).getSchemaLocation(loc);
-                    }
-                }
-                if (url == null) {
-                    LOGGER.warn("No URL is defined for schema " + ns + ". This 
schema will not be validated");
-                } else {
-                    urlToNamespace.put(url.toExternalForm(), ns);
-                    schemaSources.add(new StreamSource(url.openStream(), 
url.toExternalForm()));
-                }
-            }
-            for (Object ns : schemaMap.values()) {
-                URL url = bundle.getResource(ns.toString());
-                if (url == null) {
-                    LOGGER.warn("No URL is defined for schema " + ns + ". This 
schema will not be validated");
-                } else {
-                    schemaSources.add(new StreamSource(url.openStream(), 
url.toExternalForm()));
-                }
-            }
-            synchronized (schemaFactory) {
-                schemaFactory.setResourceResolver(new 
BundleResourceResolver(handlers, schemaMap, bundle, schemaSources, 
urlToNamespace));
-                return schemaFactory.newSchema(schemaSources.toArray(new 
Source[schemaSources.size()]));
-            }
-        } finally {
-            for (StreamSource s : schemaSources) {
-                closeQuietly(s.getInputStream());
-            }
-        }
-    }
-
     private static void closeQuietly(Closeable closeable) {
         try {
             if (closeable != null) {
@@ -377,95 +313,6 @@ public class NamespaceHandlerRegistryImp
         }
     }
 
-    private static class BundleResourceResolver implements LSResourceResolver {
-        private final Map<URI, NamespaceHandler> handlers;
-        private final Properties schemaMap;
-        private final Bundle bundle;
-        private final List<StreamSource> schemaSources;
-        private final Map<String, URI> urlToNamespace;
-
-        public BundleResourceResolver(Map<URI, NamespaceHandler> handlers, 
Properties schemaMap, Bundle bundle, List<StreamSource> schemaSources, 
Map<String, URI> urlToNamespace) {
-            this.handlers = handlers;
-            this.schemaMap = schemaMap;
-            this.bundle = bundle;
-            this.schemaSources = schemaSources;
-            this.urlToNamespace = urlToNamespace;
-        }
-
-        public LSInput resolveResource(String type,
-                                       final String namespaceURI,
-                                       final String publicId,
-                                       String systemId,
-                                       String baseURI) {
-            URI nsUri = namespaceURI != null ? URI.create(namespaceURI) : null;
-            // Use provided schema map to find the resource
-            String loc = null;
-            if (namespaceURI != null) {
-                loc = schemaMap.getProperty(namespaceURI);
-            }
-            if (loc == null && publicId != null) {
-                loc = schemaMap.getProperty(publicId);
-            }
-            if (loc == null && systemId != null) {
-                loc = schemaMap.getProperty(systemId);
-            }
-            if (loc != null) {
-                URL url = bundle.getResource(loc);
-                if (url != null) {
-                    return createLSInput(url, nsUri);
-                }
-            }
-            // Support include-relative-path case
-            if (baseURI != null && systemId != null && 
!systemId.matches("^[a-z][-+.0-9a-z]*:.*")) {
-                URL url;
-                try {
-                    url = new URL(new URL(baseURI), systemId);
-                } catch (IOException e) {
-                    throw new RuntimeException(e);
-                }
-                return createLSInput(url, nsUri);
-            }
-            if (namespaceURI != null) {
-                String id = systemId != null ? systemId : namespaceURI;
-                // This is a namespace with a known handler
-                if (handlers.containsKey(nsUri)) {
-                    NamespaceHandler h = handlers.get(nsUri);
-                    if (h != null) {
-                        URL url = h.getSchemaLocation(id);
-                        if (url != null) {
-                            return createLSInput(url, nsUri);
-                        }
-                    }
-                }
-                // This is a resource loaded from a schema
-                if (baseURI != null && urlToNamespace.containsKey(baseURI)) {
-                    NamespaceHandler h = 
handlers.get(urlToNamespace.get(baseURI));
-                    if (h != null) {
-                        URL url = h.getSchemaLocation(id);
-                        if (url != null) {
-                            return createLSInput(url, nsUri);
-                        }
-                    }
-                }
-            }
-            return null;
-        }
-
-        private LSInput createLSInput(URL url, URI nsUri) {
-            try {
-                String systemId = url.toExternalForm();
-                final StreamSource source = new StreamSource(url.openStream(), 
systemId);
-                schemaSources.add(source);
-                if (nsUri != null) {
-                    urlToNamespace.put(systemId, nsUri);
-                }
-                return new SourceLSInput(source);
-            } catch (IOException e) {
-                throw new RuntimeException(e);
-            }
-        }
-    }
-
     private static class SourceLSInput implements LSInput {
         private final StreamSource source;
 
@@ -590,11 +437,136 @@ public class NamespaceHandlerRegistryImp
                 throw new IllegalStateException("NamespaceHandlerSet is not 
complete");
             }
             if (schema == null) {
-                schema = NamespaceHandlerRegistryImpl.this.getSchema(handlers, 
bundle, schemaMap, locations);
+                schema = doGetSchema(locations);
+            }
+            return schema;
+        }
+
+        private Schema doGetSchema(Map<String, String> locations) throws 
IOException, SAXException {
+            if (schemaMap != null && !schemaMap.isEmpty()) {
+                return createSchema(locations);
+            }
+            // Find a schema that can handle all the requested namespaces
+            // If it contains additional namespaces, it should not be a 
problem since
+            // they won't be used at all
+            Schema schema = getExistingSchema(handlers);
+            if (schema == null) {
+                // Create schema
+                schema = createSchema(locations);
+                cacheSchema(handlers, schema);
             }
             return schema;
         }
 
+        private Schema createSchema(Map<String, String> locations) throws 
IOException, SAXException {
+            final List<StreamSource> schemaSources = new 
ArrayList<StreamSource>();
+            try {
+                schemaSources.add(new 
StreamSource(getClass().getResourceAsStream("/org/apache/aries/blueprint/blueprint.xsd")));
+                schemaSources.add(new 
StreamSource(getClass().getResourceAsStream("/org/apache/aries/blueprint/ext/impl/xml.xsd")));
+                // Create a schema for all namespaces known at this point
+                // It will speed things as it can be reused for all other 
blueprint containers
+                for (URI ns : handlers.keySet()) {
+                    URL url = 
handlers.get(ns).getSchemaLocation(ns.toString());
+                    if (url == null && locations != null) {
+                        String loc = locations.get(ns.toString());
+                        if (loc != null) {
+                            url = handlers.get(ns).getSchemaLocation(loc);
+                        }
+                    }
+                    if (url == null) {
+                        LOGGER.warn("No URL is defined for schema " + ns + ". 
This schema will not be validated");
+                    } else {
+                        schemaSources.add(new StreamSource(url.openStream(), 
url.toExternalForm()));
+                    }
+                }
+                for (Object ns : schemaMap.values()) {
+                    URL url = bundle.getResource(ns.toString());
+                    if (url == null) {
+                        LOGGER.warn("No URL is defined for schema " + ns + ". 
This schema will not be validated");
+                    } else {
+                        schemaSources.add(new StreamSource(url.openStream(), 
url.toExternalForm()));
+                    }
+                }
+                LSResourceResolver resolver = new LSResourceResolver() {
+                    public LSInput resolveResource(String type,
+                                                   final String namespaceURI,
+                                                   final String publicId,
+                                                   String systemId,
+                                                   String baseURI) {
+                        URI nsUri = namespaceURI != null ? 
URI.create(namespaceURI) : null;
+                        // Use provided schema map to find the resource
+                        String loc = null;
+                        if (namespaceURI != null) {
+                            loc = schemaMap.getProperty(namespaceURI);
+                        }
+                        if (loc == null && publicId != null) {
+                            loc = schemaMap.getProperty(publicId);
+                        }
+                        if (loc == null && systemId != null) {
+                            loc = schemaMap.getProperty(systemId);
+                        }
+                        if (loc != null) {
+                            URL url = bundle.getResource(loc);
+                            if (url != null) {
+                                return createLSInput(url);
+                            }
+                        }
+                        // Support include-relative-path case
+                        if (baseURI != null && systemId != null && 
!systemId.matches("^[a-z][-+.0-9a-z]*:.*")) {
+                            URL url;
+                            try {
+                                url = new URL(new URL(baseURI), systemId);
+                            } catch (IOException e) {
+                                throw new RuntimeException(e);
+                            }
+                            return createLSInput(url);
+                        }
+                        if (namespaceURI != null) {
+                            String id = systemId != null ? systemId : 
namespaceURI;
+                            // This is a namespace with a known handler
+                            NamespaceHandler h = getNamespaceHandler(nsUri);
+                            if (h == null) {
+                                // Find a compatible namespace
+                                LOGGER.warn("Dynamically adding namespace 
handler {} to bundle {}/{}",
+                                        nsUri, bundle.getSymbolicName(), 
bundle.getVersion());
+                                h = findCompatibleNamespaceHandler(nsUri);
+                            }
+                            // Load from the handler
+                            if (h != null) {
+                                URL url = h.getSchemaLocation(id);
+                                if (url != null) {
+                                    return createLSInput(url);
+                                }
+                            } else {
+                                throw new MissingNamespaceException(nsUri);
+                            }
+                        }
+                        return null;
+                    }
+
+                    private LSInput createLSInput(URL url) {
+                        try {
+                            String systemId = url.toExternalForm();
+                            final StreamSource source = new 
StreamSource(url.openStream(), systemId);
+                            schemaSources.add(source);
+                            return new SourceLSInput(source);
+                        } catch (IOException e) {
+                            throw new RuntimeException(e);
+                        }
+                    }
+                };
+                synchronized (schemaFactory) {
+                    schemaFactory.setResourceResolver(resolver);
+                    return schemaFactory.newSchema(schemaSources.toArray(new 
Source[schemaSources.size()]));
+                }
+            } finally {
+                for (StreamSource s : schemaSources) {
+                    closeQuietly(s.getInputStream());
+                }
+            }
+        }
+
+
         public void addListener(Listener listener) {
             listeners.add(listener);
         }
@@ -668,6 +640,7 @@ public class NamespaceHandlerRegistryImp
                         }
                     }
                     if (compat) {
+                        namespaces.add(ns);
                         handlers.put(ns, h);
                         return h;
                     }


Reply via email to