You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by ff...@apache.org on 2013/07/24 09:55:19 UTC

svn commit: r1506430 - /cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/blueprint/

Author: ffang
Date: Wed Jul 24 07:55:19 2013
New Revision: 1506430

URL: http://svn.apache.org/r1506430
Log:
[CXF-5148]add holders for http:client blueprint configuration

Added:
    cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/blueprint/AuthorizationPolicyHolder.java
    cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/blueprint/HTTPClientPolicyHolder.java
    cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/blueprint/ProxyAuthorizationPolicyHolder.java
Modified:
    cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/blueprint/HttpConduitBPBeanDefinitionParser.java
    cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/blueprint/HttpDestinationBPBeanDefinitionParser.java

Added: cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/blueprint/AuthorizationPolicyHolder.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/blueprint/AuthorizationPolicyHolder.java?rev=1506430&view=auto
==============================================================================
--- cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/blueprint/AuthorizationPolicyHolder.java (added)
+++ cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/blueprint/AuthorizationPolicyHolder.java Wed Jul 24 07:55:19 2013
@@ -0,0 +1,127 @@
+/**
+ * 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.cxf.transport.http.blueprint;
+
+import java.io.ByteArrayInputStream;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.logging.Logger;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.w3c.dom.Element;
+
+import org.apache.cxf.common.jaxb.JAXBContextCache;
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.common.util.PackageUtils;
+import org.apache.cxf.configuration.security.AuthorizationPolicy;
+
+public class AuthorizationPolicyHolder extends AuthorizationPolicy {
+    private static final Logger LOG = LogUtils.getL7dLogger(AuthorizationPolicyHolder.class);
+
+    private String parsedElement;
+    private AuthorizationPolicy authorizationPolicy;
+
+    private JAXBContext jaxbContext;
+    private Set<Class<?>> jaxbClasses;
+
+    public AuthorizationPolicyHolder() {
+    }
+
+    public void init() {
+        try {
+
+            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
+            docFactory.setNamespaceAware(true);
+
+            Element element = docFactory.newDocumentBuilder()
+                .parse(new ByteArrayInputStream(parsedElement.getBytes())).getDocumentElement();
+
+            authorizationPolicy = (AuthorizationPolicy)getJaxbObject(element, AuthorizationPolicy.class);
+            this.setAuthorization(authorizationPolicy.getAuthorization());
+            this.setAuthorizationType(authorizationPolicy.getAuthorizationType());
+            this.setPassword(authorizationPolicy.getPassword());
+            this.setUserName(authorizationPolicy.getUserName());
+            
+        } catch (Exception e) {
+            throw new RuntimeException("Could not process configuration.", e);
+        }
+    }
+
+    public void destroy() {
+        
+    }
+
+    public String getParsedElement() {
+        return parsedElement;
+    }
+
+    public void setParsedElement(String parsedElement) {
+        this.parsedElement = parsedElement;
+    }
+
+    protected Object getJaxbObject(Element parent, Class<?> c) {
+
+        try {
+            Unmarshaller umr = getContext(c).createUnmarshaller();
+            JAXBElement<?> ele = (JAXBElement<?>) umr.unmarshal(parent);
+
+            return ele.getValue();
+        } catch (JAXBException e) {
+            LOG.warning("Unable to parse property due to " + e);
+            return null;
+        }
+    }
+
+    protected synchronized JAXBContext getContext(Class<?> cls) {
+        if (jaxbContext == null || jaxbClasses == null || !jaxbClasses.contains(cls)) {
+            try {
+                Set<Class<?>> tmp = new HashSet<Class<?>>();
+                if (jaxbClasses != null) {
+                    tmp.addAll(jaxbClasses);
+                }
+                JAXBContextCache.addPackage(tmp, PackageUtils.getPackageName(cls), 
+                                            cls == null ? getClass().getClassLoader() : cls.getClassLoader());
+                if (cls != null) {
+                    boolean hasOf = false;
+                    for (Class<?> c : tmp) {
+                        if (c.getPackage() == cls.getPackage() && "ObjectFactory".equals(c.getSimpleName())) {
+                            hasOf = true;
+                        }
+                    }
+                    if (!hasOf) {
+                        tmp.add(cls);
+                    }
+                }
+                JAXBContextCache.scanPackages(tmp);
+                JAXBContextCache.CachedContextAndSchemas ccs 
+                    = JAXBContextCache.getCachedContextAndSchemas(tmp, null, null, null, false);
+                jaxbClasses = ccs.getClasses();
+                jaxbContext = ccs.getContext();
+            } catch (JAXBException e) {
+                throw new RuntimeException(e);
+            }
+        }
+        return jaxbContext;
+    }
+}

Added: cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/blueprint/HTTPClientPolicyHolder.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/blueprint/HTTPClientPolicyHolder.java?rev=1506430&view=auto
==============================================================================
--- cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/blueprint/HTTPClientPolicyHolder.java (added)
+++ cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/blueprint/HTTPClientPolicyHolder.java Wed Jul 24 07:55:19 2013
@@ -0,0 +1,149 @@
+/**
+ * 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.cxf.transport.http.blueprint;
+
+import java.io.ByteArrayInputStream;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.logging.Logger;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.w3c.dom.Element;
+
+import org.apache.cxf.common.jaxb.JAXBContextCache;
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.common.util.PackageUtils;
+import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
+
+
+public class HTTPClientPolicyHolder extends HTTPClientPolicy {
+    private static final Logger LOG = LogUtils.getL7dLogger(HTTPClientPolicyHolder.class);
+
+    private String parsedElement;
+    private HTTPClientPolicy clientPolicy;
+
+    private JAXBContext jaxbContext;
+    private Set<Class<?>> jaxbClasses;
+
+    public HTTPClientPolicyHolder() {
+    }
+
+    public void init() {
+        try {
+
+            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
+            docFactory.setNamespaceAware(true);
+
+            Element element = docFactory.newDocumentBuilder()
+                .parse(new ByteArrayInputStream(parsedElement.getBytes())).getDocumentElement();
+
+            clientPolicy = (HTTPClientPolicy)getJaxbObject(element, HTTPClientPolicy.class);
+            
+            this.setAccept(clientPolicy.getAccept());
+            this.setAcceptEncoding(clientPolicy.getAcceptEncoding());
+            this.setAcceptLanguage(clientPolicy.getAcceptLanguage());
+            this.setAllowChunking(clientPolicy.isAllowChunking());
+            this.setAsyncExecuteTimeout(clientPolicy.getAsyncExecuteTimeout());
+            this.setAsyncExecuteTimeoutRejection(clientPolicy.isAsyncExecuteTimeoutRejection());
+            this.setAutoRedirect(clientPolicy.isAutoRedirect());
+            this.setBrowserType(clientPolicy.getBrowserType());
+            this.setCacheControl(clientPolicy.getCacheControl());
+            this.setChunkingThreshold(clientPolicy.getChunkingThreshold());
+            this.setConnection(clientPolicy.getConnection());
+            this.setConnectionTimeout(clientPolicy.getConnectionTimeout());
+            this.setContentType(clientPolicy.getContentType());
+            this.setCookie(clientPolicy.getCookie());
+            this.setDecoupledEndpoint(clientPolicy.getDecoupledEndpoint());
+            this.setHost(clientPolicy.getHost());
+            this.setMaxRetransmits(clientPolicy.getMaxRetransmits());
+            this.setNonProxyHosts(clientPolicy.getNonProxyHosts());
+            this.setProxyServer(clientPolicy.getProxyServer());
+            this.setProxyServerPort(clientPolicy.getProxyServerPort());
+            this.setProxyServerType(clientPolicy.getProxyServerType());
+            this.setReceiveTimeout(clientPolicy.getReceiveTimeout());
+            this.setReferer(clientPolicy.getReferer());
+            
+        } catch (Exception e) {
+            throw new RuntimeException("Could not process configuration.", e);
+        }
+    }
+
+    public void destroy() {
+        
+    }
+
+    public String getParsedElement() {
+        return parsedElement;
+    }
+
+    public void setParsedElement(String parsedElement) {
+        this.parsedElement = parsedElement;
+    }
+
+    protected Object getJaxbObject(Element parent, Class<?> c) {
+
+        try {
+            Unmarshaller umr = getContext(c).createUnmarshaller();
+            JAXBElement<?> ele = (JAXBElement<?>) umr.unmarshal(parent);
+
+            return ele.getValue();
+        } catch (JAXBException e) {
+            LOG.warning("Unable to parse property due to " + e);
+            return null;
+        }
+    }
+
+    protected synchronized JAXBContext getContext(Class<?> cls) {
+        if (jaxbContext == null || jaxbClasses == null || !jaxbClasses.contains(cls)) {
+            try {
+                Set<Class<?>> tmp = new HashSet<Class<?>>();
+                if (jaxbClasses != null) {
+                    tmp.addAll(jaxbClasses);
+                }
+                JAXBContextCache.addPackage(tmp, PackageUtils.getPackageName(cls), 
+                                            cls == null ? getClass().getClassLoader() : cls.getClassLoader());
+                if (cls != null) {
+                    boolean hasOf = false;
+                    for (Class<?> c : tmp) {
+                        if (c.getPackage() == cls.getPackage() && "ObjectFactory".equals(c.getSimpleName())) {
+                            hasOf = true;
+                        }
+                    }
+                    if (!hasOf) {
+                        tmp.add(cls);
+                    }
+                }
+                JAXBContextCache.scanPackages(tmp);
+                JAXBContextCache.CachedContextAndSchemas ccs 
+                    = JAXBContextCache.getCachedContextAndSchemas(tmp, null, null, null, false);
+                jaxbClasses = ccs.getClasses();
+                jaxbContext = ccs.getContext();
+            } catch (JAXBException e) {
+                throw new RuntimeException(e);
+            }
+        }
+        return jaxbContext;
+    }
+    
+}

Modified: cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/blueprint/HttpConduitBPBeanDefinitionParser.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/blueprint/HttpConduitBPBeanDefinitionParser.java?rev=1506430&r1=1506429&r2=1506430&view=diff
==============================================================================
--- cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/blueprint/HttpConduitBPBeanDefinitionParser.java (original)
+++ cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/blueprint/HttpConduitBPBeanDefinitionParser.java Wed Jul 24 07:55:19 2013
@@ -30,19 +30,19 @@ import org.apache.aries.blueprint.Parser
 import org.apache.aries.blueprint.mutable.MutableBeanMetadata;
 import org.apache.cxf.configuration.blueprint.AbstractBPBeanDefinitionParser;
 import org.apache.cxf.configuration.jsse.TLSClientParametersConfig;
-import org.apache.cxf.configuration.security.AuthorizationPolicy;
 import org.apache.cxf.configuration.security.CertificateConstraintsType;
 import org.apache.cxf.configuration.security.CipherSuites;
 import org.apache.cxf.configuration.security.FiltersType;
 import org.apache.cxf.configuration.security.KeyManagersType;
-import org.apache.cxf.configuration.security.ProxyAuthorizationPolicy;
 import org.apache.cxf.configuration.security.SecureRandomParameters;
 import org.apache.cxf.configuration.security.TLSClientParametersType;
 import org.apache.cxf.configuration.security.TrustManagersType;
+import org.apache.cxf.helpers.DOMUtils;
+import org.apache.cxf.staxutils.StaxUtils;
 import org.apache.cxf.transport.http.HTTPConduit;
 import org.apache.cxf.transport.http.MessageTrustDecider;
 import org.apache.cxf.transport.http.auth.HttpAuthSupplier;
-import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
+import org.osgi.service.blueprint.reflect.ComponentMetadata;
 import org.osgi.service.blueprint.reflect.Metadata;
 
 public class HttpConduitBPBeanDefinitionParser extends AbstractBPBeanDefinitionParser {
@@ -56,13 +56,13 @@ public class HttpConduitBPBeanDefinition
         
         bean.setRuntimeClass(HTTPConduit.class);
 
-        mapElementToJaxbProperty(context, bean, element,
-                new QName(HTTP_NS, "client"), "client", HTTPClientPolicy.class);
-        mapElementToJaxbProperty(context, bean, element,
+        mapElementToHolder(context, bean, element,
+                new QName(HTTP_NS, "client"), "client", HTTPClientPolicyHolder.class);
+        mapElementToHolder(context, bean, element,
                 new QName(HTTP_NS, "proxyAuthorization"), "proxyAuthorization", 
-                ProxyAuthorizationPolicy.class);
-        mapElementToJaxbProperty(context, bean, element,
-                new QName(HTTP_NS, "authorization"), "authorization", AuthorizationPolicy.class);
+                ProxyAuthorizationPolicyHolder.class);
+        mapElementToHolder(context, bean, element,
+                new QName(HTTP_NS, "authorization"), "authorization", AuthorizationPolicyHolder.class);
         
         parseAttributes(element, context, bean);
         parseChildElements(element, context, bean);
@@ -72,6 +72,7 @@ public class HttpConduitBPBeanDefinition
         return bean;
     }
 
+    
     @Override
     protected void processNameAttribute(Element element, ParserContext context, MutableBeanMetadata bean,
                                         String val) {
@@ -172,4 +173,30 @@ public class HttpConduitBPBeanDefinition
             bean.addProperty(elementName, createRef(ctx, beanref));
         }
     }
+    
+    private void mapElementToHolder(ParserContext ctx, MutableBeanMetadata bean, Element parent,
+                                          QName name, String propertyName, Class<?> cls) {
+        Element data = DOMUtils.getFirstChildWithName(parent, name);
+        if (data == null) {
+            return;
+        }
+        MutableBeanMetadata ef = ctx.createMetadata(MutableBeanMetadata.class);
+
+        ef.setRuntimeClass(cls);
+
+        try {
+            // Print the DOM node
+
+            String xmlString = StaxUtils.toString(data);
+            ef.addProperty("parsedElement", createValue(ctx, xmlString));
+            ef.setInitMethod("init");
+
+            ef.setActivation(ComponentMetadata.ACTIVATION_EAGER);
+            bean.addProperty(propertyName, ef);
+
+        } catch (Exception e) {
+            throw new RuntimeException("Could not process configuration.", e);
+        }
+
+    }
 }

Modified: cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/blueprint/HttpDestinationBPBeanDefinitionParser.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/blueprint/HttpDestinationBPBeanDefinitionParser.java?rev=1506430&r1=1506429&r2=1506430&view=diff
==============================================================================
--- cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/blueprint/HttpDestinationBPBeanDefinitionParser.java (original)
+++ cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/blueprint/HttpDestinationBPBeanDefinitionParser.java Wed Jul 24 07:55:19 2013
@@ -49,7 +49,8 @@ public class HttpDestinationBPBeanDefini
         
         bean.setRuntimeClass(AbstractHTTPDestination.class);
 
-        mapElementToServerPoliy(context, bean, element, new QName(HTTP_NS, "server"), "server");
+        mapElementToHolder(context, bean, element, new QName(HTTP_NS, "server"), "server", 
+                           HTTPServerPolicyHolder.class);
         mapElementToJaxbProperty(context, bean, element, new QName(HTTP_NS, "fixedParameterOrder"),
                                  "fixedParameterOrder", Boolean.class);
         mapElementToJaxbProperty(context, bean, element, new QName(HTTP_NS, "contextMatchStrategy"),
@@ -84,17 +85,18 @@ public class HttpDestinationBPBeanDefini
         }
     }
     
-    private void mapElementToServerPoliy(ParserContext ctx,
+    private void mapElementToHolder(ParserContext ctx,
                                             MutableBeanMetadata bean, Element parent, 
                                             QName name,
-                                            String propertyName) {
+                                            String propertyName,
+                                            Class<?> cls) {
         Element data = DOMUtils.getFirstChildWithName(parent, name);
         if (data == null) {
             return;
         }
         MutableBeanMetadata ef = ctx.createMetadata(MutableBeanMetadata.class);
         
-        ef.setRuntimeClass(HTTPServerPolicyHolder.class);
+        ef.setRuntimeClass(cls);
 
         try {
             // Print the DOM node

Added: cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/blueprint/ProxyAuthorizationPolicyHolder.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/blueprint/ProxyAuthorizationPolicyHolder.java?rev=1506430&view=auto
==============================================================================
--- cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/blueprint/ProxyAuthorizationPolicyHolder.java (added)
+++ cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/blueprint/ProxyAuthorizationPolicyHolder.java Wed Jul 24 07:55:19 2013
@@ -0,0 +1,127 @@
+/**
+ * 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.cxf.transport.http.blueprint;
+
+import java.io.ByteArrayInputStream;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.logging.Logger;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.w3c.dom.Element;
+
+import org.apache.cxf.common.jaxb.JAXBContextCache;
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.common.util.PackageUtils;
+import org.apache.cxf.configuration.security.ProxyAuthorizationPolicy;
+
+public class ProxyAuthorizationPolicyHolder extends ProxyAuthorizationPolicy {
+    private static final Logger LOG = LogUtils.getL7dLogger(ProxyAuthorizationPolicyHolder.class);
+
+    private String parsedElement;
+    private ProxyAuthorizationPolicy proxyAuthorizationPolicy;
+
+    private JAXBContext jaxbContext;
+    private Set<Class<?>> jaxbClasses;
+
+    public ProxyAuthorizationPolicyHolder() {
+    }
+
+    public void init() {
+        try {
+
+            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
+            docFactory.setNamespaceAware(true);
+
+            Element element = docFactory.newDocumentBuilder()
+                .parse(new ByteArrayInputStream(parsedElement.getBytes())).getDocumentElement();
+
+            proxyAuthorizationPolicy = (ProxyAuthorizationPolicy)getJaxbObject(element, ProxyAuthorizationPolicy.class);
+            this.setAuthorization(proxyAuthorizationPolicy.getAuthorization());
+            this.setAuthorizationType(proxyAuthorizationPolicy.getAuthorizationType());
+            this.setPassword(proxyAuthorizationPolicy.getPassword());
+            this.setUserName(proxyAuthorizationPolicy.getUserName());
+            
+        } catch (Exception e) {
+            throw new RuntimeException("Could not process configuration.", e);
+        }
+    }
+
+    public void destroy() {
+        
+    }
+
+    public String getParsedElement() {
+        return parsedElement;
+    }
+
+    public void setParsedElement(String parsedElement) {
+        this.parsedElement = parsedElement;
+    }
+
+    protected Object getJaxbObject(Element parent, Class<?> c) {
+
+        try {
+            Unmarshaller umr = getContext(c).createUnmarshaller();
+            JAXBElement<?> ele = (JAXBElement<?>) umr.unmarshal(parent);
+
+            return ele.getValue();
+        } catch (JAXBException e) {
+            LOG.warning("Unable to parse property due to " + e);
+            return null;
+        }
+    }
+
+    protected synchronized JAXBContext getContext(Class<?> cls) {
+        if (jaxbContext == null || jaxbClasses == null || !jaxbClasses.contains(cls)) {
+            try {
+                Set<Class<?>> tmp = new HashSet<Class<?>>();
+                if (jaxbClasses != null) {
+                    tmp.addAll(jaxbClasses);
+                }
+                JAXBContextCache.addPackage(tmp, PackageUtils.getPackageName(cls), 
+                                            cls == null ? getClass().getClassLoader() : cls.getClassLoader());
+                if (cls != null) {
+                    boolean hasOf = false;
+                    for (Class<?> c : tmp) {
+                        if (c.getPackage() == cls.getPackage() && "ObjectFactory".equals(c.getSimpleName())) {
+                            hasOf = true;
+                        }
+                    }
+                    if (!hasOf) {
+                        tmp.add(cls);
+                    }
+                }
+                JAXBContextCache.scanPackages(tmp);
+                JAXBContextCache.CachedContextAndSchemas ccs 
+                    = JAXBContextCache.getCachedContextAndSchemas(tmp, null, null, null, false);
+                jaxbClasses = ccs.getClasses();
+                jaxbContext = ccs.getContext();
+            } catch (JAXBException e) {
+                throw new RuntimeException(e);
+            }
+        }
+        return jaxbContext;
+    }
+}