All Downloads are FREE. Search and download functionalities are using the official Maven repository.

es.rickyepoderi.wbxml.tools.Xml2WbXml Maven / Gradle / Ivy

There is a newer version: 2.1.13.6
Show newest version
/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *    
 * Linking this library statically or dynamically with other modules 
 * is making a combined work based on this library. Thus, the terms and
 * conditions of the GNU General Public License cover the whole
 * combination.
 *    
 * As a special exception, the copyright holders of this library give 
 * you permission to link this library with independent modules to 
 * produce an executable, regardless of the license terms of these 
 * independent modules, and to copy and distribute the resulting 
 * executable under terms of your choice, provided that you also meet, 
 * for each linked independent module, the terms and conditions of the 
 * license of that module.  An independent module is a module which 
 * is not derived from or based on this library.  If you modify this 
 * library, you may extend this exception to your version of the 
 * library, but you are not obligated to do so.  If you do not wish 
 * to do so, delete this exception statement from your version.
 *
 * Project: github.com/rickyepoderi/wbxml-stream
 * 
 */
package es.rickyepoderi.wbxml.tools;

import es.rickyepoderi.wbxml.definition.WbXmlDefinition;
import es.rickyepoderi.wbxml.definition.WbXmlInitialization;
import es.rickyepoderi.wbxml.document.WbXmlEncoder;
import es.rickyepoderi.wbxml.stream.WbXmlOutputFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stax.StAXResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
 * 

Tool or command class that emulates the libwbxml xml2wbxml * counterpart. This command let the user convert a common XML file into a * binary WBXML file.

* *

NAME

* *

wbXml2Xml - Convert a XML text file into a common WBXML binary file

* *

SYNOPSYS

* *

java -cp wbxml-jaxb-X.X.X.jar es.rickyepoderi.wbxml.tools.WbXml2Xml * [-j --jaxb] [-t --type <TYPE>] [-k --keep] [-d --definition <NAME>] {infile} {outfile}

* *

DESCRIPTION

* *

Command that converts a text XML file into a WBXML binary file. It uses * an intermediary form to represent the structure and then normal DOM or * JAXB techniques are used. In case of JAXB the representation classes * should be provided (the wbxml-stream package does not contain * any JAXB classes, some classes were created for a few languages only for * testing purposes but they are not packaged in the library).

* *

The following arguments are used:

* *
    *
  • -j --jaxb: Use JAXB processing (object representation) * instead of normal DOM processing. As it was said JAXB classes are not part * of the wbxml-tream library.

  • *
  • -e --event: Use the event writer instead of common * stream writer implementation.

  • *
  • -t --type: The type of use of the string table in * the encoding. There are three types: IF_NEEDED (default, * only use the string table if needed), ALWAYS (use for all * the strings) and NO (no use it at all, it can report * problems if the encoding needs it).

  • *
  • -k --keep: Keep the spaces in the values (by * default all the string are trimmed).

  • *
  • -d --definition: Use a fixed language definition * for the WBXML file. If no one is provided the command tries to guess it * using the public identifier of the WBXML file. But if it is unknown (some * languages are nor standardized, like Microsoft ActiveSync) and no definition * is provided an error is reported.

    *

    A list of possible language definitions is shown in the usage of the * command.

  • *
  • infile: XML file to convert, - can be * provided to use the standard output. *

  • outfile: file to write the resulting WBXML, * - can be provided to use the standard input. *

* *

EXAMPLES

* *
 * java -cp wbxml-stream-0.1.0.jar es.rickyepoderi.wbxml.tools.Xml2WbXml si.xml si.wbxml
 *     Convert the file si.xml into WBXML and the result is placed in si.wbxml
 * 
 * java -cp wbxml-stream-0.1.0.jar es.rickyepoderi.wbxml.tools.Xml2WbXml -d "SI 1.0" si.xml si.wbxml
 *     Force definition to SI 1.0 
 * 
 * 
* * @author ricky */ final public class Xml2WbXml { /** * The input stream to read the WBXML. */ private InputStream in = null; /** * The output stream to write the XML. */ private OutputStream out = null; /** * Use DOM (default) or the stranger JAXB. */ private boolean useDom = true; /** * The definition to use in the conversion. */ private WbXmlDefinition def = null; /** * type of encoding. */ private WbXmlEncoder.StrtblType type = WbXmlEncoder.StrtblType.IF_NEEDED; /** * skip spaces. */ private boolean skipSpaces = true; /** * Use event writer. */ private boolean event = false; /** * It prints the usage of the command and the throws a IllegalArgumentException. * @param message The message to show previous of the usage part */ private void usage(String message) { StringBuilder sb = new StringBuilder(); sb.append(message); sb.append(System.getProperty("line.separator")); sb.append(System.getProperty("line.separator")); sb.append("java -cp wbxml-jaxb-X.X.X.jar "); sb.append(this.getClass().getName()); sb.append(" [-j --jaxb] [-t --type ] [-k --keep] [-d --definition ] {infile} {outfile}"); sb.append(System.getProperty("line.separator")); sb.append(" -j --jaxb: Use JAXB instead instead default DOM"); sb.append(System.getProperty("line.separator")); sb.append(" -e --event: Use XMLEventWriter instead of the default XMLStreamWriter"); sb.append(System.getProperty("line.separator")); sb.append(" In order to use JAXB the classes should be generated from the DTD (xjc)"); sb.append(System.getProperty("line.separator")); sb.append(" -t --type: Type of STR table use. Values: IF_NEEDED (default), ALWAYS, NO"); sb.append(System.getProperty("line.separator")); sb.append(" -k --keep: Keep spaces from the XML (default no)"); sb.append(System.getProperty("line.separator")); sb.append(" -d --definition: Force definition instead deriving from XML. Current definitions:"); sb.append(System.getProperty("line.separator")); for (WbXmlDefinition d: WbXmlInitialization.getDefinitions()) { sb.append(String.format(" %s", d.getName())); sb.append(System.getProperty("line.separator")); } sb.append(" infile: input XML file (\"-\" means standard input)"); sb.append(System.getProperty("line.separator")); sb.append(" outfile: output WBXML file (\"-\" means sntandard output)"); sb.append(System.getProperty("line.separator")); throw new IllegalArgumentException(sb.toString()); } /** * Method that gets the value part of a parameter if it exists. If the * array has no more elements usage is called. * @param args The list of arguments * @param i The current position * @return The string of the value */ private String getNext(String[] args, int i) { if (args.length > i) { return args[i]; } else { usage("Invalid invocation."); } return null; } /** * Constructor that creates the command using the arguments passed by the * caller. Usage is used (IllegalArgumentException) if some error * is detected in the arguments. * @param args The argument list * @throws Exception Any error */ private Xml2WbXml(String[] args) throws Exception { String infile = null; String outfile = null; int i = 0; if (args.length < 2) { usage("Invalid invocation."); } while (i < args.length) { if ("-d".equals(args[i]) || "--definition".equals(args[i])) { // use fixed definition String defName = getNext(args, ++i); this.def = WbXmlInitialization.getDefinitionByName(defName); if (this.def == null) { usage(String.format("Invalid definition specified '%s'.", defName)); } } else if ("-j".equals(args[i]) || "--jaxb".equals(args[i])) { // use JAXB instead DOM this.useDom = false; } else if ("-e".equals(args[i]) || "--event".equals(args[i])) { // Use the XMLEventWriter this.event = true; } else if ("-t".equals(args[i]) || "--type".equals(args[i])) { // the type of encoding String name = getNext(args, ++i); try { this.type = WbXmlEncoder.StrtblType.valueOf(name); } catch (Exception e) { usage(String.format("Invalid STR type '%s'.", name)); } } else if ("-k".equals(args[i]) || "--keep".equals(args[i])) { // use JAXB instead DOM this.skipSpaces = false; } else { if (args.length - i != 2) { System.err.println(args.length - i); usage("Invalid invocation."); } // the names of the infile and outfile infile = getNext(args, i); outfile = getNext(args, ++i); } i++; } // get the input stream if ("-".equals(infile)) { in = System.in; } else { File f = new File(infile); if (!f.exists() || !f.canRead()) { usage(String.format("Input XML file '%s' is not readable.", infile)); } in = new FileInputStream(f); } // get the output stream if ("-".equals(outfile)) { out = System.out; } else { File f = new File(outfile); f.createNewFile(); if (!f.canWrite()) { usage(String.format("Output WBXML file '%s' is not writable.", outfile)); } out = new FileOutputStream(f); } } /** * Method that executes the command, ie, does the conversion from WBXML * to XML. * @throws Exception Some error */ private void process() throws Exception { XMLStreamWriter xmlStreamWriter = null; XMLEventWriter xmlEventWriter = null; try { // weird parameters for xerces: // http://xerces.apache.org/xerces2-j/features.html#namespaces DocumentBuilderFactory domFact = DocumentBuilderFactory.newInstance(); domFact.setNamespaceAware(true); domFact.setIgnoringElementContentWhitespace(true); domFact.setIgnoringComments(true); domFact.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); DocumentBuilder domBuilder = domFact.newDocumentBuilder(); Document doc = domBuilder.parse(in); Element element = doc.getDocumentElement(); element.normalize(); if (def == null) { // first try using the PublicId if (doc.getDoctype() != null && doc.getDoctype().getPublicId() != null) { def = WbXmlInitialization.getDefinitionByFPI(doc.getDoctype().getPublicId()); } // if not using the root element if (def == null) { def = WbXmlInitialization.getDefinitionByRoot( element.getLocalName(), element.getNamespaceURI()); if (def == null) { usage(String.format("Definition not found for name=%s and namespace=%s. Use -d argument to force it.", element.getLocalName(), element.getNamespaceURI())); } } } // create the factory XMLOutputFactory fact = new WbXmlOutputFactory(); fact.setProperty(WbXmlOutputFactory.DEFINITION_PROPERTY, def); fact.setProperty(WbXmlOutputFactory.ENCODING_TYPE_PROPERTY, type); fact.setProperty(WbXmlOutputFactory.SKIP_SPACES_PROPERTY, skipSpaces); if (!useDom) { // use JAXB String clazz = def.getClazz(); if (clazz == null || clazz.isEmpty()) { usage(String.format("The definition '%s' does not contain a main class.", def.getName())); } JAXBContext jc = JAXBContext.newInstance(Class.forName(clazz)); Unmarshaller unmarshaller = jc.createUnmarshaller(); Object obj = unmarshaller.unmarshal(doc); Marshaller marshaller = jc.createMarshaller(); if (event) { xmlEventWriter = fact.createXMLEventWriter(out); marshaller.marshal(obj, xmlEventWriter); } else { xmlStreamWriter = fact.createXMLStreamWriter(out); marshaller.marshal(obj, xmlStreamWriter); } } else { // use common DOM processing Transformer xformer = TransformerFactory.newInstance().newTransformer(); Source domSource = new DOMSource(doc); StAXResult staxResult; if (event) { xmlEventWriter = fact.createXMLEventWriter(out); staxResult = new StAXResult(xmlEventWriter); } else { xmlStreamWriter = fact.createXMLStreamWriter(out); staxResult = new StAXResult(xmlStreamWriter); } xformer.transform(domSource, staxResult); } } finally { if (xmlStreamWriter != null) { try {xmlStreamWriter.close();} catch (Exception e) {} } if (xmlEventWriter != null) { try {xmlEventWriter.close();} catch (Exception e) {} } } } /** * It closes all the streams. */ private void close() { try {in.close();} catch(Exception e) {} try {out.close();} catch(Exception e) {} } /** * Execution of the command. Usage is used if the arguments are incorrect. * @param args The arguments to call the command * @throws Exception Some error in the invocation */ static public void main(String args[]) throws Exception { Xml2WbXml command = null; try { command = new Xml2WbXml(args); command.process(); } finally { if (command != null) { command.close(); } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy