source: trunk/docx4j/src/main/java/org/docx4j/openpackaging/parts/WordprocessingML/HeaderPart.java @ 1737

Revision 1737, 8.5 KB checked in by jharrop, 5 months ago (diff)

Reference  http://java.net/jira/browse/JAXB-874

  • Property svn:eol-style set to native
  • Property svn:executable set to *
Line 
1/*
2 *  Copyright 2007-2008, Plutext Pty Ltd.
3 *   
4 *  This file is part of docx4j.
5
6    docx4j is licensed under the Apache License, Version 2.0 (the "License");
7    you may not use this file except in compliance with the License.
8
9    You may obtain a copy of the License at
10
11        http://www.apache.org/licenses/LICENSE-2.0
12
13    Unless required by applicable law or agreed to in writing, software
14    distributed under the License is distributed on an "AS IS" BASIS,
15    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16    See the License for the specific language governing permissions and
17    limitations under the License.
18
19 */
20
21package org.docx4j.openpackaging.parts.WordprocessingML;
22
23
24import java.util.List;
25
26import javax.xml.bind.Binder;
27import javax.xml.bind.JAXBException;
28import javax.xml.bind.UnmarshalException;
29import javax.xml.bind.Unmarshaller;
30import javax.xml.parsers.DocumentBuilderFactory;
31import javax.xml.transform.Templates;
32import javax.xml.transform.dom.DOMResult;
33
34import org.apache.log4j.Logger;
35import org.docx4j.XmlUtils;
36import org.docx4j.jaxb.Context;
37import org.docx4j.jaxb.JaxbValidationEventHandler;
38import org.docx4j.openpackaging.exceptions.InvalidFormatException;
39import org.docx4j.openpackaging.parts.JaxbXmlPart;
40import org.docx4j.openpackaging.parts.PartName;
41import org.docx4j.openpackaging.parts.relationships.Namespaces;
42import org.docx4j.wml.ContentAccessor;
43import org.docx4j.wml.Hdr;
44import org.w3c.dom.Node;
45
46
47
48public final class HeaderPart extends JaxbXmlPart<Hdr>  implements ContentAccessor {
49       
50        private static Logger log = Logger.getLogger(HeaderPart.class);                 
51       
52        public HeaderPart(PartName partName) throws InvalidFormatException {
53                super(partName);               
54                init(); 
55        }
56
57        public HeaderPart() throws InvalidFormatException {
58                super(new PartName("/word/header.xml"));  // Not very useful, since normally there is more than one footer part
59                init();         
60        }                       
61       
62        public void init() {
63       
64                // Used if this Part is added to [Content_Types].xml
65                setContentType(new  org.docx4j.openpackaging.contenttype.ContentType( 
66                                org.docx4j.openpackaging.contenttype.ContentTypes.WORDPROCESSINGML_HEADER));
67
68                // Used when this Part is added to a rels
69                setRelationshipType(Namespaces.HEADER);
70        }
71       
72    /**
73     * Convenience method to getJaxbElement().getBody().getContent()
74     * @since 2.7
75     */
76    public List<Object> getContent() {
77       
78        if (this.getJaxbElement()==null) {             
79                this.setJaxbElement( Context.getWmlObjectFactory().createHdr() );
80        }
81       
82        return this.getJaxbElement().getContent();
83    }   
84       
85        private Binder<Node> binder;
86       
87       
88        /**
89         * Enables synchronization between XML infoset nodes and JAXB objects
90         * representing same XML document.
91         *
92         * An instance of this class maintains the association between XML nodes
93         * of an infoset preserving view and a JAXB representation of an XML document.
94         * Navigation between the two views is provided by the methods
95         * getXMLNode(Object) and getJAXBNode(Object) .
96         *
97         * In theory, modifications can be made to either the infoset preserving view or
98         * the JAXB representation of the document while the other view remains
99         * unmodified. The binder ought to be able to synchronize the changes made in
100         * the modified view back into the other view using the appropriate
101         * Binder update methods, #updateXML(Object, Object) or #updateJAXB(Object).
102         *
103         * But JAXB doesn't currently work as advertised .. access to this
104         * object is offered for advanced users on an experimental basis only.
105         */
106        public Binder<Node> getBinder() {
107               
108                return binder;
109        }
110       
111        /**
112         * Fetch JAXB Nodes matching an XPath (for example "//w:p").
113         *
114         * If you have modified your JAXB objects (eg added or changed a
115         * w:p paragraph), you need to update the association. The problem
116         * is that this can only be done ONCE, owing to a bug in JAXB:
117         * see https://jaxb.dev.java.net/issues/show_bug.cgi?id=459
118         *
119         * So this is left for you to choose to do via the refreshXmlFirst parameter.   
120         *
121         * @param xpathExpr
122         * @param refreshXmlFirst
123         * @return
124         * @throws JAXBException
125         */     
126        public List<Object> getJAXBNodesViaXPath(String xpathExpr, boolean refreshXmlFirst) 
127                        throws JAXBException {
128               
129                return XmlUtils.getJAXBNodesViaXPath(binder, jaxbElement, xpathExpr, refreshXmlFirst);
130        }       
131
132        /**
133         * Fetch JAXB Nodes matching an XPath (for example ".//w:p" - note the dot,
134         * which is necessary for this sort of relative path).
135         *
136         * If you have modified your JAXB objects (eg added or changed a
137         * w:p paragraph), you need to update the association. The problem
138         * is that this can only be done ONCE, owing to a bug in JAXB:
139         * see https://jaxb.dev.java.net/issues/show_bug.cgi?id=459
140         *
141         * So this is left for you to choose to do via the refreshXmlFirst parameter.   
142
143         * @param xpathExpr
144         * @param someJaxbElement
145         * @param refreshXmlFirst
146         * @return
147         * @throws JAXBException
148         */
149        public List<Object> getJAXBNodesViaXPath(String xpathExpr, Object someJaxbElement, boolean refreshXmlFirst) 
150                throws JAXBException {
151
152                return XmlUtils.getJAXBNodesViaXPath(binder, someJaxbElement, xpathExpr, refreshXmlFirst);
153        }       
154       
155       
156    /**
157     * Unmarshal XML data from the specified InputStream and return the
158     * resulting content tree.  Validation event location information may
159     * be incomplete when using this form of the unmarshal API.
160     *
161     * <p>
162     * Implements <a href="#unmarshalGlobal">Unmarshal Global Root Element</a>.
163     *
164     * @param is the InputStream to unmarshal XML data from
165     * @return the newly created root object of the java content tree
166     *
167     * @throws JAXBException
168     *     If any unexpected errors occur while unmarshalling
169     */
170        @Override
171    public Hdr unmarshal( java.io.InputStream is ) throws JAXBException {
172                try {
173                       
174                        log.info("For MDP, unmarshall via binder");
175                        // InputStream to Document
176                        javax.xml.parsers.DocumentBuilderFactory dbf
177                                = DocumentBuilderFactory.newInstance();
178                        dbf.setNamespaceAware(true);
179                        org.w3c.dom.Document doc = dbf.newDocumentBuilder().parse(is);
180
181                        //
182                        binder = jc.createBinder();
183                       
184                        JaxbValidationEventHandler eventHandler = new JaxbValidationEventHandler();
185                        eventHandler.setContinue(false);
186                        binder.setEventHandler(eventHandler);
187                       
188                        try {
189                                jaxbElement =  (Hdr) binder.unmarshal( doc );
190                        } catch (UnmarshalException ue) {
191                                log.info("encountered unexpected content; pre-processing");
192                                eventHandler.setContinue(true);
193                               
194                                // There is no JAXBResult(binder),
195                                // so use a
196                                DOMResult result = new DOMResult();
197                               
198                                Templates mcPreprocessorXslt = JaxbValidationEventHandler.getMcPreprocessor();
199                                XmlUtils.transform(doc, mcPreprocessorXslt, null, result);
200                               
201                                doc = (org.w3c.dom.Document)result.getNode();
202                                try {                           
203                                        jaxbElement =  (Hdr) binder.unmarshal( doc );
204                                } catch (ClassCastException cce) {
205                                        // Work around for issue with JAXB binder, in Java 1.6
206                                        // See  http://java.net/jira/browse/JAXB-874 and comments in MainDocumentPart.                                 
207                                        log.warn("Binder not available for this docx");
208                                        Unmarshaller u = jc.createUnmarshaller();
209                                        jaxbElement = (Hdr) u.unmarshal( doc );                                 
210                                }
211                               
212                               
213                        }
214                       
215                        return jaxbElement;
216                       
217                } catch (Exception e ) {
218                        e.printStackTrace();
219                        return null;
220                }
221    }
222
223    /**
224     * @since 2.7.1
225     */         
226        @Override
227    public Hdr unmarshal(org.w3c.dom.Element el) throws JAXBException {
228
229                try {
230
231                        binder = jc.createBinder();
232                        JaxbValidationEventHandler eventHandler = new JaxbValidationEventHandler();
233                        eventHandler.setContinue(false);
234                        binder.setEventHandler(eventHandler);
235                       
236                        try {
237                                jaxbElement =  (Hdr) binder.unmarshal( el );
238                        } catch (UnmarshalException ue) {
239                                log.info("encountered unexpected content; pre-processing");
240                                try {
241                                        org.w3c.dom.Document doc;
242                                        if (el instanceof org.w3c.dom.Document) {
243                                                doc = (org.w3c.dom.Document) el;
244                                        } else {
245                                                // Hope for the best. Dodgy though; what if this is
246                                                // being used on something deep in the tree?
247                                                // TODO: revisit
248                                                doc = el.getOwnerDocument();
249                                        }
250                                        eventHandler.setContinue(true);
251                                        DOMResult result = new DOMResult();
252                                        Templates mcPreprocessorXslt = JaxbValidationEventHandler
253                                                        .getMcPreprocessor();
254                                        XmlUtils.transform(doc, mcPreprocessorXslt, null, result);
255                                        doc = (org.w3c.dom.Document) result.getNode();
256                                        jaxbElement = (Hdr) binder
257                                                        .unmarshal(doc);
258                                } catch (Exception e) {
259                                        throw new JAXBException("Preprocessing exception", e);
260                                }
261                        }
262                        return jaxbElement;
263                       
264                } catch (JAXBException e) {
265                        log.error(e);
266                        throw e;
267                }
268        }
269       
270       
271       
272}
Note: See TracBrowser for help on using the repository browser.