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

net.pwall.xml.XMLDirectory Maven / Gradle / Ivy

/*
 * @(#) XMLDirectory.java
 */

package net.pwall.xml;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Calendar;
import java.util.TimeZone;

import net.pwall.util.ISO8601Date;
import net.pwall.util.UserError;

import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

/**
 * Simple program to produce a file system directory listing in XML form.
 *
 * @author Peter Wall
 */
public class XMLDirectory implements Runnable {

    public static final String defaultEncoding = "UTF-8";

    public static final String directoryListElemName = "directory-list";
    public static final String directoryElemName = "directory";
    public static final String fileElemName = "file";
    public static final String pathAttrName = "path";
    public static final String titleAttrName = "title";
    public static final String nameAttrName = "name";
    public static final String hiddenAttrName = "hidden";
    public static final String modifiedAttrName = "modified";
    public static final String lengthAttrName = "length";
    public static final String trueValue = "yes";
    public static final String cdataType = "CDATA";
    public static final String nullStr = "";

    private String namespaceURI;
    private String namespacePrefix;
    private File dir;
    private OutputStream out;
    private String xslt;
    private String encoding;
    private String title;
    private int indent;

    public XMLDirectory() {
        namespaceURI = null;
        namespacePrefix = null;
        dir = null;
        out = null;
        xslt = null;
        encoding = null;
        title = null;
        indent = -1;
    }

    @Override
    public void run() {
        if (getNamespacePrefix() != null && getNamespaceURI() == null)
            throw new UserError("Namespace prefix with no namespace URI");
        run(out != null ? out : System.out);
    }

    private void run(OutputStream out) {
        try (XMLFormatter formatter = new XMLFormatter(out, XMLFormatter.Whitespace.INDENT)) {
            if (indent >= 0)
                formatter.setIndent(indent);
            if (dir == null)
                dir = new File(".");
            formatter.setEncoding(encoding != null ? encoding : defaultEncoding);
            formatter.prefix();
            formatter.xslProcessingInstruction(xslt);
            formatter.startDocument();
            AttributesImpl attributes = new AttributesImpl();
            addAttribute(attributes, pathAttrName, dir.getAbsolutePath());
            if (title != null)
                addAttribute(attributes, titleAttrName, title);
            if (namespaceURI != null)
                formatter.startPrefixMapping(namespacePrefix == null ? "" : namespacePrefix,
                        namespaceURI);
            startElement(formatter, directoryListElemName, attributes);
            outputDirectory(formatter, dir);
            endElement(formatter, directoryListElemName);
            if (namespaceURI != null)
                formatter.endPrefixMapping(namespacePrefix == null ? "" : namespacePrefix);
            formatter.endDocument();
        }
        catch (Exception e) {
            throw new RuntimeException("Unexpected exception in XMLDirectory", e);
        }
    }

    private void outputDirectory(ContentHandler ch, File dir) throws SAXException {
        AttributesImpl attributes = baseAttributes(dir);
        startElement(ch, directoryElemName, attributes);
        File[] files = dir.listFiles();
        for (File file : files) {
            if (file.isDirectory())
                outputDirectory(ch, file);
            else
                outputFile(ch, file);
        }
        endElement(ch, directoryElemName);
    }

    private void outputFile(ContentHandler ch, File file) throws SAXException {
        AttributesImpl attributes = baseAttributes(file);
        addAttribute(attributes, lengthAttrName, String.valueOf(file.length()));
        startElement(ch, fileElemName, attributes);
        endElement(ch, fileElemName);
    }

    private static AttributesImpl baseAttributes(File file) {
        AttributesImpl attributes = new AttributesImpl();
        addAttribute(attributes, nameAttrName, file.getName());
        if (file.isHidden())
            addAttribute(attributes, hiddenAttrName, trueValue);
        Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
        cal.setTimeInMillis(file.lastModified());
        String dateString = ISO8601Date.toString(cal, true,
                ISO8601Date.YEAR_MASK | ISO8601Date.MONTH_MASK | ISO8601Date.DAY_OF_MONTH_MASK |
                ISO8601Date.HOUR_OF_DAY_MASK | ISO8601Date.MINUTE_MASK |
                ISO8601Date.SECOND_MASK | ISO8601Date.ZONE_OFFSET_MASK);
        addAttribute(attributes, modifiedAttrName, dateString);
        // what about Unix permissions, owner and group?
        return attributes;
    }

    private void startElement(ContentHandler ch, String name, Attributes attributes)
            throws SAXException {
        ch.startElement(namespaceURI == null ? nullStr : namespaceURI, name,
                namespacePrefix == null ? name : namespacePrefix + ':' + name, attributes);
    }

    private void endElement(ContentHandler ch, String name) throws SAXException {
        ch.endElement(namespaceURI == null ? nullStr : namespaceURI, name,
                namespacePrefix == null ? name : namespacePrefix + ':' + name);
    }

    private static void addAttribute(AttributesImpl attributes, String qName, String value) {
        attributes.addAttribute(nullStr, nullStr, qName, cdataType, value);
    }

    public String getNamespaceURI() {
        return namespaceURI;
    }

    public void setNamespaceURI(String namespaceURI) {
        this.namespaceURI = namespaceURI;
    }

    public String getNamespacePrefix() {
        return namespacePrefix;
    }

    public void setNamespacePrefix(String namespacePrefix) {
        this.namespacePrefix = namespacePrefix;
    }

    public File getDir() {
        return dir;
    }

    public void setDir(File dir) {
        this.dir = dir;
    }

    public OutputStream getOut() {
        return out;
    }

    public void setOut(OutputStream out) {
        this.out = out;
    }

    public String getXslt() {
        return xslt;
    }

    public void setXslt(String xslt) {
        this.xslt = xslt;
    }

    public String getEncoding() {
        return encoding;
    }

    public void setEncoding(String encoding) {
        this.encoding = encoding;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public int getIndent() {
        return indent;
    }

    public void setIndent(int indent) {
        this.indent = indent;
    }

    /**
     * Main method.
     *
     * @param args command-line arguments
     */
    public static void main(String[] args) {
        try {
            XMLDirectory instance = new XMLDirectory();
            for (int i = 0; i < args.length; i++) {
                String arg = args[i];
                if (arg.equals("-dir")) {
                    if (++i >= args.length || args[i].startsWith("-"))
                        throw new UserError("-dir with no pathname");
                    if (instance.getDir() != null)
                        throw new UserError("Duplicate -dir");
                    File dir = new File(args[i]);
                    if (!dir.exists() || !dir.isDirectory())
                        throw new UserError("-dir file does not exist - " + args[i]);
                    instance.setDir(dir);
                }
                else if (arg.equals("-out")) {
                    if (++i >= args.length || args[i].startsWith("-"))
                        throw new UserError("-out with no pathname");
                    if (instance.getOut() != null)
                        throw new UserError("Duplicate -out");
                    try {
                        instance.setOut(new FileOutputStream(args[i]));
                    }
                    catch (IOException ioe) {
                        throw new UserError("Can't open output - " + args[i]);
                    }
                }
                else if (arg.equals("-xslt")) {
                    if (++i >= args.length || args[i].startsWith("-"))
                        throw new UserError("-xslt with no URL");
                    if (instance.getXslt() != null)
                        throw new UserError("Duplicate -xslt");
                    instance.setXslt(args[i]);
                }
                else if (arg.equals("-encoding")) {
                    if (++i >= args.length || args[i].startsWith("-"))
                        throw new UserError("-encoding with no name");
                    if (instance.getEncoding() != null)
                        throw new UserError("Duplicate -encoding");
                    instance.setEncoding(args[i]);
                }
                else if (arg.equals("-title")) {
                    if (++i >= args.length || args[i].startsWith("-"))
                        throw new UserError("-title with no value");
                    if (instance.getTitle() != null)
                        throw new UserError("Duplicate -title");
                    instance.setTitle(args[i]);
                }
                else if (arg.equals("-indent")) {
                    if (++i >= args.length || args[i].startsWith("-"))
                        throw new UserError("-indent with no value");
                    if (instance.getIndent() >= 0)
                        throw new UserError("Duplicate -indent");
                    try {
                        int n = Integer.parseInt(args[i]);
                        if (n < 0 || n > 100)
                            throw new UserError("Illegal -indent - " + args[i]);
                        instance.setIndent(n);
                    }
                    catch (NumberFormatException e) {
                        throw new UserError("Illegal -indent - " + args[i]);
                    }
                }
                else if (arg.equals("-nsuri")) {
                    if (++i >= args.length || args[i].startsWith("-"))
                        throw new UserError("-nsuri with no value");
                    if (instance.getNamespaceURI() != null)
                        throw new UserError("Duplicate -nsuri");
                    instance.setNamespaceURI(args[i]);
                }
                else if (arg.equals("-nspfx")) {
                    if (++i >= args.length || args[i].startsWith("-"))
                        throw new UserError("-nspfx with no value");
                    if (instance.getNamespacePrefix() != null)
                        throw new UserError("Duplicate -nspfx");
                    instance.setNamespacePrefix(args[i]);
                }
                else
                    throw new UserError("Unrecognised argument - " + arg);
            }
            instance.run();
        }
        catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy