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.modules.convertor;

import java.io.IOException;
import java.io.InputStream;
import java.lang.ClassLoader;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import org.netbeans.api.convertor.ConvertorDescriptor;
import org.netbeans.api.convertor.ConvertorException;
import org.netbeans.api.convertor.Convertors;
import org.netbeans.spi.convertor.Convertor;
import org.openide.ErrorManager;
import org.openide.modules.ModuleInfo;
import org.openide.util.Lookup;
import org.openide.util.LookupEvent;
import org.openide.util.LookupListener;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

/** 
 *
 * @author  David Konecny
 */
public class ConvertorsPool implements LookupListener {

    private static final ConvertorsPool DEFAULT = new ConvertorsPool();
    
    private Set convertorDescriptors = new HashSet();
    
    private boolean initialized = false;

    private Lookup.Result modules;
    
    private ConvertorsPool() {
        modules = Lookup.getDefault().lookup(new Lookup.Template(ModuleInfo.class)); 
        modules.addLookupListener(this);
    }

    public static ConvertorsPool getDefault() {
        return DEFAULT;
    }
    
    public ConvertorDescriptor getReadConvertor(String namespace, String element) {
        assert namespace != null && element != null;
        initConvertors();
        Iterator it = convertorDescriptors.iterator();
        while (it.hasNext()) {
            ConvertorDescriptor cd = (ConvertorDescriptor)it.next();
            if (namespace.equals(cd.getNamespace()) &&
                element.equals(cd.getElementName())) {
                return cd;
            }
        }
        return null;
    }

    public ConvertorDescriptor getWriteConvertor(Object o) {
        initConvertors();
        Convertor convertor = null;
        Class clazz = o.getClass();
        Iterator it = convertorDescriptors.iterator();
        while (it.hasNext()) {
            ConvertorDescriptor cd = (ConvertorDescriptor)it.next();
            if (cd.getClassName() == null || (!cd.getClassName().equals(o.getClass().getName()))) {
                continue;
            }
            Class cls;
            try {
                cls = InstanceUtils.findClass(cd.getClassName());
                if (!(cls.getClassLoader().loadClass(o.getClass().getName()) == o.getClass())) {
                    ErrorManager.getDefault().log(ErrorManager.WARNING, "Object "+o+" cannot be stored by convertor "+cd+", because of classloader mismatch. Skipping convertor.");
                    continue;
                }
            } catch (Exception e) {
                ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
                continue;
            }
            
            if (clazz.equals(cls)) {
                return cd;
            }
        }
        return null;
    }
    
    public Set getDescriptors() {
        initConvertors();
        return new HashSet(convertorDescriptors);
    }
    
    private synchronized void initConvertors() {
        if (initialized) {
            return;
        }
        loadConvertors();
        initialized = true;
    }
    
    public synchronized void resultChanged(LookupEvent ev) {
        loadConvertors();
    }
    
    private void loadConvertors() {
        Set old = convertorDescriptors;
            
        ClassLoader currentClassLoader = (ClassLoader)Lookup.getDefault().lookup(ClassLoader.class);
        Set convs = new HashSet();
        Enumeration en = null;
        try {
            en = currentClassLoader.getResources("META-INF/MANIFEST.MF");
        } catch (IOException ex) {
            ex.printStackTrace();
            ErrorManager.getDefault().notify(ErrorManager.ERROR, ex);
            return;
        }
        while (en.hasMoreElements ()) {
            URL u = (URL)en.nextElement();
            Manifest mf;

            try {
                InputStream is = u.openStream();
                try {
                    mf = new Manifest(is);
                    loadConvertors(mf, convs);
                } finally {
                    is.close();
                }
            } catch (IOException ex) {
                ErrorManager.getDefault().log(ErrorManager.ERROR, "Cannot read file "+u+". The file will be ignored.");
            }

        }
        convertorDescriptors = convs;
            
        Accessor.DEFAULT.firePropertyChange(Convertors.CONVERTOR_DESCRIPTORS, old, new HashSet(convertorDescriptors));
    }

    private void loadConvertors(Manifest m, Set convs) {
        Iterator it = m.getEntries().entrySet().iterator(); // Iterator>
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry)it.next();
            String name = (String)entry.getKey();
            Attributes attrs = (Attributes)entry.getValue();
            if (attrs.getValue("NetBeans-Convertor") != null) {
                String convertor = getClassName(name);
                String conv;
                int index = 0;
                while (null != (conv = attrs.getValue(appendNumber("NetBeans-Convertor", index)))) {
                    // parse following format:  "{namespace}element, class"
                    int endOfNamespace = conv.indexOf('}');
                    if (endOfNamespace == -1) {
                        ErrorManager.getDefault().log(ErrorManager.WARNING, "Attribute "+
                            appendNumber("NetBeans-Convertor", index)+
                            " of convertor "+convertor+
                            " does not contain namespace: "+conv);
                        break;
                    }
                    int startOfClass = conv.indexOf(',');
                    String namespace = conv.substring(1, endOfNamespace);
                    String rootElement;
                    if (startOfClass == -1) {
                        rootElement = conv.substring(endOfNamespace+1);
                    } else {
                        rootElement = conv.substring(endOfNamespace+1, startOfClass);
                    }
                    rootElement = rootElement.trim();
                    if (rootElement.length() == 0) {
                        ErrorManager.getDefault().log(ErrorManager.WARNING, "Attribute "+
                            appendNumber("NetBeans-Convertor", index)+
                            " of convertor "+convertor+
                            " does not contain element: "+conv);
                        break;
                    }
                    String writes = null;
                    if (startOfClass != -1) {
                        writes = conv.substring(startOfClass+1).trim();
                    }
                    convs.add(Accessor.DEFAULT.createConvertorDescriptor(
                        new ProxyConvertor(convertor, namespace, rootElement, writes), namespace, rootElement, writes));
                    index++;
                }
            }
            if (attrs.getValue("NetBeans-Simply-Convertible") != null) {
                String conv = attrs.getValue("NetBeans-Simply-Convertible");
                String convertor = "PropertiesConvertor";
                // parse following format:  "{namespace}element"
                int endOfNamespace = conv.indexOf('}');
                if (endOfNamespace == -1) {
                    ErrorManager.getDefault().log(ErrorManager.WARNING, "Attribute"+
                        " NetBeans-Simply-Convertible"+
                        " for class "+name+
                        " does not contain namespace: "+conv);
                    continue;
                }
                String namespace = conv.substring(1, endOfNamespace);
                String rootElement = conv.substring(endOfNamespace+1);
                rootElement = rootElement.trim();
                if (rootElement.length() == 0) {
                    ErrorManager.getDefault().log(ErrorManager.WARNING, "Attribute "+
                        " NetBeans-Simply-Convertible"+
                        " for class "+name+
                        " does not contain element: "+conv);
                    continue;
                }
                String writes = getClassName(name);
                convs.add(Accessor.DEFAULT.createConvertorDescriptor(
                    new ProxyConvertor(convertor, namespace, rootElement, writes), namespace, rootElement, writes));
            }
        }
    }
    
    private String getClassName(String className) {
        className = className.replace('/', '.');
        // this will remove ".class" and everything behind it
        className = className.substring(0, className.indexOf(".class"));
        return className;
    }
    
    private String appendNumber(String name, int number) {
        if (number == 0) {
            return name;
        } else {
            return name + "-" + Integer.toString(number+1);
        }
    }
    
    private static class ProxyConvertor implements Convertor {
        
        private String convertor;
        private String namespace;
        private String rootElement;
        private String writes;

        private Convertor delegate;
        
        public ProxyConvertor(String convertor, String namespace, String rootElement, String writes) {
            this.convertor = convertor;
            this.namespace = namespace;
            this.rootElement = rootElement;
            this.writes = writes;
        }
        
        public Object read(Element e) {
            loadRealConvertor();
            if (delegate == null) {
                throw new ConvertorException("Cannot read element. The convertor class "+convertor+" cannot be instantiated.");
            }
            return delegate.read(e);
        }
        
        public Element write(Document doc, Object inst) {
            loadRealConvertor();
            if (delegate == null) {
                throw new ConvertorException("Cannot persist object. The convertor class "+convertor+" cannot be instantiated.");
            }
            return delegate.write(doc, inst);
        }
        
        private synchronized void loadRealConvertor() {
            if (delegate == null) {
                if (convertor.equals("PropertiesConvertor")) {
                    delegate = new PropertiesConvertor(namespace, rootElement, writes);
                } else {
                    try {
                        Class c = InstanceUtils.findClass(convertor);
                        delegate = (Convertor)c.newInstance();
                    } catch (Exception e) {
                        ErrorManager.getDefault().log(ErrorManager.WARNING, e.toString());
                    }
                }
            }
        }
        
        public String toString() {
            return "ProxyConvertor[convertor="+convertor+", namespace="+namespace+", rootElement="+
                rootElement+", writes="+writes+", delegate="+delegate+"] " + super.toString(); // 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.