alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 * 
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.core.registry.oldformats;

import org.openide.ErrorManager;
import org.openide.filesystems.FileLock;
import org.openide.filesystems.FileObject;
import org.openide.modules.ModuleInfo;
import org.openide.modules.SpecificationVersion;
import org.openide.util.Lookup;
import org.w3c.dom.*;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.netbeans.core.registry.oldformats.InstanceUtils;
import org.netbeans.core.registry.DocumentUtils;

import java.io.*;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.Stack;

/** 
 *
 * @author copy&pasted from core/settings
 */

public class SerialDataConvertor {
    
    private static final String INSTANCE_DTD_ID = "-//NetBeans//DTD Session settings 1.0//EN"; // NOI18N
    private static final String INSTANCE_DTD_WWW = "http://www.netbeans.org/dtds/sessionsettings-1_0.dtd"; // NOI18N

    // enlarged to not need do the test for negative byte values
    private final static char[] HEXDIGITS = {'0', '1', '2', '3', '4', '5', '6', '7',
                                             '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
                                             '0', '1', '2', '3', '4', '5', '6', '7'};
    
    private static final int INDENT = 8;
    private static final int BLOCK = 64;
    private static final int BUFFSIZE = INDENT + BLOCK;

    private String moduleCodeName = null;
    
    public SerialDataConvertor() {
    }

    public static Object read(org.w3c.dom.Element element, FileObject fo) throws IOException, ClassNotFoundException {
        String moduleCodeName = null;
        String instanceClass = null;
        String instanceMethod = null;
        String serialData = null;
        
        NodeList nodes = element.getChildNodes();
        for (int i = 0; i < nodes.getLength(); i++) {
            Node node = nodes.item(i);
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                Element e = (Element)node;
                if (e.getNodeName().equals("module")) {
                    moduleCodeName = e.getAttribute("name");
                }
                if (e.getNodeName().equals("instance")) {
                    instanceClass = e.getAttribute("class");
                    instanceMethod = e.getAttribute("method");
                    if (instanceMethod.length() == 0) {
                        instanceMethod = null;
                    }
                    instanceClass = org.openide.util.Utilities.translate(instanceClass);
                }
                if (e.getNodeName().equals("serialdata")) {
                    instanceClass = e.getAttribute("class");
                    serialData = DocumentUtils.getTextValue(e);
                    instanceClass = org.openide.util.Utilities.translate(instanceClass);
                }
            }
        }
        return createInstance(serialData, instanceClass, instanceMethod, fo);
    }

    public static boolean isSettingsFormat(org.w3c.dom.Element element) {
        if (element.getNodeName().equals("settings") &&
            element.getNamespaceURI() == null &&
            element.getAttribute("version").equals("1.0")) {
            return true;
        } else {
            return false;
        }
    }
    
    public static String getModuleCodeName(org.w3c.dom.Element element) {
        NodeList nodes = element.getChildNodes();
        for (int i = 0; i < nodes.getLength(); i++) {
            Node node = nodes.item(i);
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                Element e = (Element)node;
                if (e.getNodeName().equals("module")) {
                    return e.getAttribute("name");
                }
            }
        }
        return null;
    }

    
    public void write(FileObject fo, Object inst) throws IOException, UnsupportedOperationException {
        FileLock lock = fo.lock();
        OutputStream os = fo.getOutputStream(lock);
        boolean ok = false;
        try {
            PrintWriter pw = new PrintWriter (os);
            pw.println(""); // NOI18N
            pw.print(""); // NOI18N
            pw.println(""); // NOI18N

            storeModule(inst, pw);

            storeInstanceOf(inst, pw);

            // TODO: if (inst isBean) then user XMLArchiver instead of Serialization here
            storeSerialData(inst, pw);

            pw.println(""); // NOI18N
            pw.flush();
            ok = true;
        } finally {
            os.close();
            lock.releaseLock();
            if (!ok) {
                fo.delete();
            }
        }
    }
    
    private static Object createInstance(String serialData, String instanceClass, String instanceMethod, FileObject fo) throws IOException, ClassNotFoundException {
        if (serialData != null) {
            return InstanceUtils.serialValue(serialData);
        }
        if (instanceMethod != null) {
            return InstanceUtils.methodValue(instanceClass, instanceMethod, fo);
        }
        if (instanceClass != null) {
            return InstanceUtils.newValue(instanceClass);
        }
        throw new IOException("Do not know how to create instance from file XXXX");
        
    }
    
    private void storeInstanceOf (Object inst, PrintWriter pw) throws IOException {
        Iterator it = getSuperClasses(inst.getClass(), null).iterator();
        Class clazz;
        while (it.hasNext()) {
            clazz = (Class) it.next();
            pw.print("    "); // NOI18N
        }
    }
    
    private void storeModule(Object inst, PrintWriter pw) throws IOException {
        Iterator it = Lookup.getDefault().lookup(
            new Lookup.Template(ModuleInfo.class)).allInstances().iterator();
        while (it.hasNext()) {
            ModuleInfo mi = (ModuleInfo)it.next();
            if (mi.owns(inst.getClass())) {
                String modulName = mi.getCodeName();
                SpecificationVersion spec = mi.getSpecificationVersion();
                pw.print("    "); // NOI18N
                
                moduleCodeName = modulName;
                
                return;
            }
        }
        ErrorManager.getDefault().log(ErrorManager.WARNING, "ModuleInfo was not found for class "+inst.getClass());
    }
    

    // returns module code name of stored instance
    public String getModuleCodeName() {
        return moduleCodeName;
    }
    
    private void storeSerialData (Object inst, PrintWriter pw) throws IOException {
        pw.print ("    "); // NOI18N

        ByteArrayOutputStream baos = new ByteArrayOutputStream (1024);
        ObjectOutput oo = new SpecialObjectOutputStream (baos);
        oo.writeObject (inst);
        byte[] bdata = baos.toByteArray ();
        
        char[] cdata = new char[BUFFSIZE];
        for (int i=0; i < INDENT; i++ ) cdata[i] = ' ';
        
        int i = 0; // byte array pointer
        int j; // char array pointer
        int blen = bdata.length;
        
        while (i < blen) {
            int mark = INDENT + Math.min( 2*(blen-i), BLOCK );
            for (j=INDENT; j < mark; j += 2) {
                int b = ((int)bdata[i++]) + 256;
                cdata[j]   = HEXDIGITS[b >> 4];
                cdata[j+1] = HEXDIGITS[b & 15];
            }
            pw.write(cdata, 0, j);
            pw.println();
        }
        pw.println ("    "); // NOI18N
        pw.flush();
    }
    
    /** Get everything what class extends or implements. */
    private Set getSuperClasses(Class clazz, Set classes) {
        if (classes == null) {
            classes = new HashSet();
        }
        
        if (clazz == null || !classes.add(clazz)) {
            return classes;
        }
        
        Class[] cs = clazz.getInterfaces();
        
        // XXX following validation should help to identify a wrong IBM's
        // implementation of Class.getInterfaces(). The implementation for some
        // classes returns null. See issue #16257.
        if (cs != null) {
            for (int i = 0; i < cs.length; i++) {
                getSuperClasses(cs[i], classes);
            }
        } else {
            ErrorManager.getDefault().log(ErrorManager.ERROR,
                "Error: if you encounter this message, please attach " + //NOI18N
                "the class name to the issue http://www.netbeans.org/issues/show_bug.cgi?id=16257. " + //NOI18N
                "Class.getInterfaces() == null for the class: " + clazz); // NOI18N
        }
        
        return getSuperClasses(clazz.getSuperclass(), classes);
    }

    
    /** The only purpose of this object output stream subclass is to 
     * detect whether the serialized object does not return null
     * in its writeReplace method. Such an object is ignored and exception
     * is thrown. More details in issue #15563.
     */
    private static class SpecialObjectOutputStream extends org.openide.util.io.NbObjectOutputStream {

        private boolean first;
        
        public SpecialObjectOutputStream(OutputStream os) throws IOException {
            super (os);
            first = true;
        }

        public Object replaceObject (Object obj) throws IOException {
            if (first) {
                if (obj == null) {
                    // Object doesn't want to be serialized.
                    throw new NotSerializableException();
                }
                first = false;
            }
            return super.replaceObject(obj);
        }

    }

    private static class SettingsSAXHandler extends DefaultHandler {
        
        private static final String ELM_SETTING = "settings"; // NOI18N
        private static final String ATR_SETTING_VERSION = "version"; // NOI18N
        
        private static final String ELM_MODULE = "module"; // NOI18N
        private static final String ATR_MODULE_NAME = "name"; // NOI18N
        private static final String ATR_MODULE_SPEC = "spec"; // NOI18N
        private static final String ATR_MODULE_IMPL = "impl"; // NOI18N
        
        private static final String ELM_INSTANCE = "instance"; // NOI18N
        private static final String ATR_INSTANCE_CLASS = "class"; // NOI18N
        private static final String ATR_INSTANCE_METHOD = "method"; // NOI18N
        
        private static final String ELM_INSTANCEOF = "instanceof"; // NOI18N
        private static final String ATR_INSTANCEOF_CLASS = "class"; // NOI18N
        
        private static final String ELM_SERIALDATA = "serialdata"; // NOI18N
        private static final String ATR_SERIALDATA_CLASS = "class"; // NOI18N
        
        
        
        // ATR_MODULE_NAME
        private String codeName;
        // ATR_INSTANCE_CLASS
        private String instanceClass;
       
        // ATR_INSTANCEOF_CLASS
        private Set instanceOf = new HashSet();

        // ATR_INSTANCE_METHOD
        private String instanceMethod;


        // ATR_MODULE_SPEC
        private SpecificationVersion moduleSpec;
        // ATR_MODULE_IMPL
        private String moduleImpl;

        // ATR_SETTING_VERSION
        private String version;
        
        
        // ATR_SERIALDATA_CLASS
        private String serialdata;
        
        
        // module base name
        private String codeNameBase;
        
        // module base version
        private int codeNameRelease;

        
        private Stack stack;
        private CharArrayWriter chaos = null;
        
        private boolean readModuleOnly;
        
        public SettingsSAXHandler(boolean readModuleOnly) {
            stack = new Stack();
            this.readModuleOnly = readModuleOnly;
        }
        
        public org.xml.sax.InputSource resolveEntity(String publicId, String systemId) throws SAXException {
            if (INSTANCE_DTD_ID.equals(publicId)) {
                return new org.xml.sax.InputSource(new ByteArrayInputStream(new byte[0]));
            } else {
                return null; // i.e. follow advice of systemID
            }
        }
        
        public void characters(char[] values, int start, int length) throws SAXException {
            String element = (String) stack.peek();
            if (ELM_SERIALDATA.equals(element)) {
                // [PENDING] should be optimized to do not read all chars to memory
                if (chaos == null) {
                    chaos = new CharArrayWriter(length);
                }
                chaos.write(values, start, length);
            }
        }
        
        public void startElement(String uri, String localName, String qName, Attributes attribs) throws SAXException {
            stack.push(qName);
            if (ELM_SETTING.equals(qName)) {
                version = attribs.getValue(ATR_SETTING_VERSION);
            } else if (ELM_MODULE.equals(qName)) {
                codeName = attribs.getValue(ATR_MODULE_NAME);
                resolveModuleElm(codeName);
                moduleImpl = attribs.getValue(ATR_MODULE_IMPL);
                if (readModuleOnly) {
                    throw new StopSAXException();
                }
                try {
                    String spec = attribs.getValue(ATR_MODULE_SPEC);
                    moduleSpec = spec == null ? null : new SpecificationVersion(spec);
                } catch (NumberFormatException nfe) {
                    throw new SAXException(nfe);
                }
            } else if (ELM_INSTANCEOF.equals(qName)) {
                instanceOf.add(org.openide.util.Utilities.translate(attribs.getValue(ATR_INSTANCEOF_CLASS)));
            } else if (ELM_INSTANCE.equals(qName)) {
                instanceClass = attribs.getValue(ATR_INSTANCE_CLASS);
                instanceClass = org.openide.util.Utilities.translate(instanceClass);
                instanceMethod = attribs.getValue(ATR_INSTANCE_METHOD);
            } else if (ELM_SERIALDATA.equals(qName)) {
                instanceClass = attribs.getValue(ATR_SERIALDATA_CLASS);
                instanceClass = org.openide.util.Utilities.translate(instanceClass);
            }
        }
        
        /** reade codenamebase + revision */
        private void resolveModuleElm(String codeName) {
            if (codeName != null) {
                int slash = codeName.indexOf("/"); // NOI18N
                if (slash == -1) {
                    codeNameBase = codeName;
                    codeNameRelease = -1;
                } else {
                    codeNameBase = codeName.substring(0, slash);
                    try {
                        codeNameRelease = Integer.parseInt(codeName.substring(slash + 1));
                    } catch (NumberFormatException ex) {
                        ErrorManager emgr = ErrorManager.getDefault();
                        emgr.annotate(ex, "Source: XXXXX"); // NOI18N
                        emgr.notify(ErrorManager.INFORMATIONAL, ex);
                        codeNameRelease = -1;
                    }
                }
            } else {
                codeNameBase = null;
                codeNameRelease = -1;
            }
        }
        
        public void endElement(String uri, String localName, String qName) throws SAXException {
            String element = (String) stack.pop();
            if (ELM_SERIALDATA.equals(element)) {
                if (chaos != null) {
                    serialdata = chaos.toString();
                }
            }
        }
        
    }
    
    final static class StopSAXException extends SAXException {
        public StopSAXException() {
            super("Parser stopped"); // NOI18N
        }
    }
    
}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.