| 1 | package org.docx4j.jaxb; |
|---|
| 2 | |
|---|
| 3 | import javax.xml.bind.JAXBContext; |
|---|
| 4 | import javax.xml.bind.JAXBException; |
|---|
| 5 | import javax.xml.bind.Marshaller; |
|---|
| 6 | |
|---|
| 7 | import org.apache.log4j.Logger; |
|---|
| 8 | |
|---|
| 9 | public 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 | } |
|---|