source: trunk/docx4j/src/main/java/org/docx4j/jaxb/NamespacePrefixMapperUtils.java @ 1730

Revision 1730, 8.0 KB checked in by jharrop, 5 months ago (diff)

Jeromy Evans patch of 12 Dec 2011, modified. On OpenJDK implementation (1.6.0_23) a javax.xml.bind.PropertyException? is thrown instead, so handle this.

Line 
1package org.docx4j.jaxb;
2
3import javax.xml.bind.JAXBContext;
4import javax.xml.bind.JAXBException;
5import javax.xml.bind.Marshaller;
6
7import org.apache.log4j.Logger;
8
9public class NamespacePrefixMapperUtils {
10       
11        private static Logger log = Logger.getLogger(NamespacePrefixMapperUtils.class);         
12       
13        /*
14         * As from 2010 08 26, 
15         * both com.sun.xml.bind.marshaller.NamespacePrefixMapper
16         * and  com.sun.xml.internal.bind.marshaller.NamespacePrefixMapper
17         * are provided in the jar JAXB-NamespacePrefixMapperInterfaces.jar
18         * so that people can build docx4j without needing both JAXB
19         * implementations.
20         *
21         * But if that jar is on their classpath, testing for either
22         * of these classes will always succeed.
23         *
24         * So, we have to test for something else.  The following will do:
25         *
26         * com.sun.xml.bind.marshaller.MinimumEscapeHandler
27         * com.sun.xml.internal.bind.marshaller.MinimumEscapeHandler
28         */
29       
30        private static JAXBContext testContext;
31       
32        private static Object prefixMapper;
33        private static Object prefixMapperRels;
34       
35       
36        public static Object getPrefixMapper() throws JAXBException {
37               
38                if (prefixMapper!=null) return prefixMapper;
39               
40                if (testContext==null) {
41                       
42                        // JBOSS might use a different class loader to load JAXBContext, which causes problems,
43                        // so explicitly specify our class loader.
44                        NamespacePrefixMapperUtils tmp = new NamespacePrefixMapperUtils();
45                        java.lang.ClassLoader classLoader = tmp.getClass().getClassLoader();
46                       
47                        testContext = JAXBContext.newInstance("org.docx4j.relationships",classLoader );
48                }
49               
50                Marshaller m=testContext.createMarshaller();
51                try {
52                        // Assume use of Java 6 implementation (ie not RI)
53                        m.setProperty("com.sun.xml.internal.bind.namespacePrefixMapper", 
54                                        new NamespacePrefixMapperSunInternal() );
55                        log.info("Using NamespacePrefixMapperSunInternal, which is suitable for Java 6");
56                        prefixMapper = new NamespacePrefixMapperSunInternal();
57                        return prefixMapper;
58                } catch (java.lang.NoClassDefFoundError notJava6) {
59                        log.error(notJava6.getMessage() + " .. trying RI.");
60                        return tryUsingRI(m);                   
61                } catch (javax.xml.bind.PropertyException notJava6) {
62                        // OpenJDK (1.6.0_23) does this
63                        log.error(notJava6.getMessage() + " .. trying RI.");
64                        return tryUsingRI(m);                   
65                }
66        }
67
68
69        private static Object tryUsingRI(Marshaller m)
70                        throws JAXBException {
71                try {
72                        // Try RI suitable one
73                        m.setProperty("com.sun.xml.bind.namespacePrefixMapper", 
74                                        new NamespacePrefixMapper() );
75                        log.info("Using NamespacePrefixMapper, which is suitable for the JAXB RI");
76                        prefixMapper = new NamespacePrefixMapper();
77                        return prefixMapper;
78                } catch (java.lang.NoClassDefFoundError notRIEither) {
79                        notRIEither.printStackTrace();
80                        log.error("JAXB: neither Reference Implementation nor Java 6 implementation present?", notRIEither);
81                        throw new JAXBException("JAXB: neither Reference Implementation nor Java 6 implementation present?");
82                } catch (javax.xml.bind.PropertyException notRIEither) {
83                        notRIEither.printStackTrace();
84                        log.error("JAXB: neither Reference Implementation nor Java 6 implementation present?", notRIEither);
85                        throw new JAXBException("JAXB: neither Reference Implementation nor Java 6 implementation present?");
86                }
87        }
88
89       
90        public static Object getPrefixMapperRelationshipsPart() throws JAXBException {
91
92                if (prefixMapperRels!=null) return prefixMapperRels;
93                if (testContext==null) {
94                       
95                        // JBOSS might use a different class loader to load JAXBContext, which causes problems,
96                        // so explicitly specify our class loader.
97                        NamespacePrefixMapperUtils tmp = new NamespacePrefixMapperUtils();
98                        java.lang.ClassLoader classLoader = tmp.getClass().getClassLoader();
99                       
100                        testContext = JAXBContext.newInstance("org.docx4j.relationships",classLoader );
101                }
102               
103                Marshaller m=testContext.createMarshaller();
104                try {
105                        // Assume use of Java 6 implementation (ie not RI)
106                        m.setProperty("com.sun.xml.internal.bind.namespacePrefixMapper", 
107                                        new NamespacePrefixMapperRelationshipsPartSunInternal() );
108                        log.info("Using NamespacePrefixMapperSunInternal, which is suitable for Java 6");
109                        prefixMapperRels = new NamespacePrefixMapperRelationshipsPartSunInternal();
110                        return prefixMapperRels;
111                } catch (java.lang.NoClassDefFoundError notJava6) {
112                        // javax.xml.bind.PropertyException
113                        log.error(notJava6.getMessage() + " .. trying RI.");
114                        return tryRIforRelationshipsPart(m);
115                } catch (javax.xml.bind.PropertyException notJava6) {
116                        log.error(notJava6.getMessage() + " .. trying RI.");
117                        return tryRIforRelationshipsPart(m);
118                }
119        }
120
121
122        private static Object tryRIforRelationshipsPart(Marshaller m)
123                        throws JAXBException {
124                try {
125                        // Try RI suitable one
126                        m.setProperty("com.sun.xml.bind.namespacePrefixMapper", 
127                                        new NamespacePrefixMapperRelationshipsPart() );
128                        log.info("Using NamespacePrefixMapperRelationshipsPart, which is suitable for the JAXB RI");
129                        prefixMapperRels = new NamespacePrefixMapperRelationshipsPart();
130                        return prefixMapperRels;
131                } catch (java.lang.NoClassDefFoundError notRIEither) {
132                        notRIEither.printStackTrace();
133                        log.error("JAXB: neither Reference Implementation nor Java 6 implementation present?", notRIEither);
134                        throw new JAXBException("JAXB: neither Reference Implementation nor Java 6 implementation present?");
135                } catch (javax.xml.bind.PropertyException notRIEither) {
136                        notRIEither.printStackTrace();
137                        log.error("JAXB: neither Reference Implementation nor Java 6 implementation present?", notRIEither);
138                        throw new JAXBException("JAXB: neither Reference Implementation nor Java 6 implementation present?");
139                }
140        }
141       
142        /**
143         * setProperty on 'com.sun.xml.bind.namespacePrefixMapper' or
144         * 'com.sun.xml.internal.bind.namespacePrefixMapper', as appropriate,
145         * depending on whether JAXB reference implementation, or Java 6
146         * implementation is being used.
147         *
148         * @param marshaller
149         * @param namespacePrefixMapper
150         * @throws JAXBException
151         */
152        public static void setProperty(Marshaller marshaller, Object namespacePrefixMapper) throws JAXBException {
153               
154                try {
155                        if ( namespacePrefixMapper.getClass().getName().equals(
156                                                "org.docx4j.jaxb.NamespacePrefixMapper")
157                                        || namespacePrefixMapper.getClass().getName().equals(
158                                                        "org.docx4j.jaxb.NamespacePrefixMapperRelationshipsPart") ) {
159                       
160                                marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", 
161                                                namespacePrefixMapper ); 
162                       
163                                // Reference implementation appears to be present (in endorsed dir?)
164                                log.debug("setProperty: com.sun.xml.bind.namespacePrefixMapper");
165//                              System.out.println("setProperty: com.sun.xml.bind.namespacePrefixMapper");
166                               
167                        } else {
168                               
169                                // Use JAXB distributed in Java 6 - note 'internal'
170                                // Switch to other mapper
171                                log.debug("attempting to setProperty: com.sun.xml.INTERNAL.bind.namespacePrefixMapper");
172                                marshaller.setProperty("com.sun.xml.internal.bind.namespacePrefixMapper", namespacePrefixMapper);
173//                              System.out.println("setProperty: com.sun.xml.INTERNAL.bind.namespacePrefixMapper");
174                        }
175                       
176                } catch (javax.xml.bind.PropertyException cnfe) {
177                       
178//                      cnfe.printStackTrace();
179                        log.error(cnfe);
180                        throw cnfe;
181                       
182                }
183               
184        }
185       
186        public static String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) throws JAXBException {
187
188                Object namespacePrefixMapper = getPrefixMapper();
189               
190                if ( namespacePrefixMapper.getClass().getName().equals("org.docx4j.jaxb.NamespacePrefixMapperSunInternal") ) {
191                        // Java 6
192                        return ((NamespacePrefixMapperSunInternal)namespacePrefixMapper).getPreferredPrefix(namespaceUri, suggestion, requirePrefix); 
193                       
194                } else if (namespacePrefixMapper.getClass().getName().equals("org.docx4j.jaxb.NamespacePrefixMapper")) {
195                // JAXB Reference Implementation               
196                        return ((NamespacePrefixMapper)namespacePrefixMapper).getPreferredPrefix(namespaceUri, suggestion, requirePrefix); 
197                       
198                } else {
199                        log.warn("Namespace prefix mapper not found!");
200                        return null;
201                }
202               
203        }
204       
205}
Note: See TracBrowser for help on using the repository browser.