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-2002 Sun
 * Microsystems, Inc. All Rights Reserved.
 */
package org.netbeans.mdr.handlers;

import org.netbeans.api.mdr.JMIStreamFactory;
import org.netbeans.lib.jmi.mapping.ClassFileMapper;
import org.netbeans.mdr.handlers.gen.TagSupport;
import org.netbeans.mdr.storagemodel.StorableObject;
import org.netbeans.mdr.util.DebugException;
import org.netbeans.mdr.util.Logger;
import org.netbeans.mdr.util.MOFConstants;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.security.AllPermission;
import java.security.PermissionCollection;
import java.security.Permissions;
import java.security.ProtectionDomain;
import java.util.*;

/**
 *
 * @author  Martin Matula
 */
class MDRClassLoader extends ClassLoader {
    private static final ProtectionDomain pd;
    private static final HashMap suffixes;
    private final JMIStreamFactory streamFactory = new StreamFactory();

    static {
        PermissionCollection pc = new Permissions();
        pc.add(new AllPermission());
        pd = new ProtectionDomain(null, pc);

        suffixes = new HashMap(3, 1);
        suffixes.put(MOFConstants.SH_MODEL_CLASS, MOFConstants.SH_MODEL_CLASS);
        suffixes.put(MOFConstants.SH_MODEL_PACKAGE, MOFConstants.SH_MODEL_PACKAGE);
        suffixes.put(MOFConstants.SH_MODEL_ASSOCIATION, ""); //NOI18N
    }

    private final ClassLoaderProvider provider;
    private Delegator parent;

    private final HashMap packages = new HashMap();

    // class caches
    private final HashMap proxyClasses = new HashMap();
    private final HashMap instanceClasses = new HashMap();

    /** Creates a new instance of MDRClassLoader */
    MDRClassLoader(ClassLoaderProvider provider) {
        super();
        this.provider = provider;
    }

    private Delegator getDelegator() {
        if (parent == null) {
            parent = new Delegator(provider);
        }
        return (parent = parent.getDelegator());
    }

    protected Class defineClass(String className, byte[] classFile) {
        Class result;
        // try to define class using ClassLoaderProvider
        // if the method returned null, define the class in this classloader
        if (provider == null || (result = provider.defineClass(className, classFile))== null) {
            int i = className.lastIndexOf('.');
            String pkgName = className.substring(0, i);
            Package pkg = getPackage(pkgName);
            if (pkg == null) {
                definePackage(pkgName, null, null, null, null, null, null, null);
            }
            result = defineClass(className, classFile, 0, classFile.length, pd);
        }
        return result;
    }

    /** Resolves JMI interface for a repository object represented by a storable.
     * If the interface cannot be found on the classpath, it will be dynamicaly
     * generated based on the metamodel.
     * @param s storable object representing the repository object.
     * @param proxy indicates whether the interface to be generated corresponds to a proxy
     * @return JMI interface for a given object.
     */
    protected Class resolveInterface(StorableObject s, boolean proxy) {
        String key = s.getMofId().toString();
        Map classes = proxy ? proxyClasses : instanceClasses;
        Class result = null;

        // [PENDING] synchronize on repository rather than on particular storages
        synchronized (s.getMdrStorage().getStorageByMofId(s.getMofId())) {
            result = (Class) classes.get(key);
            if (result == null) try {
                String metaName = (String) s.getMetaObject().getAttribute(MOFConstants.SH_MODEL_MODEL_ELEMENT_NAME);
                String suffix = proxy ? (String) suffixes.get(metaName) : ""; //NOI18N
                String ifcName = TagSupport.getTypeFullName(s) + suffix;
                try {
                    result = loadClass(ifcName);
                } catch (ClassNotFoundException e) {
                    Logger.getDefault().log(Logger.WARNING, "Metamodel specific JMI class " + ifcName + " not found. Using bytecode generation to create it.");
                    new ClassFileMapper(streamFactory).visitRefBaseObject(s.getMdrStorage().getRepository().getHandler(s.getOutermostPackage()));
                    result = loadClass(ifcName);
                }
                classes.put(key, result);
            } catch (Exception e) {
                throw (DebugException) Logger.getDefault().annotate(new DebugException(), e);
            }
        }
        return result;
    }

    protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
        Class c = findLoadedClass(name);
        if (c == null) {
            try {
                c = getDelegator().accessibleLoadClass(name, false);
            } catch (ClassNotFoundException e) {
                // this will always throw exception in this implementation
                // (all the classes should be loaded by calling defineClass directly)
                c = findClass(name);
            }
        }
        if (resolve) {
            resolveClass(c);
        }
        return c;
    }

    public URL getResource(String name) {
        URL url;
        url = getDelegator().getResource(name);
        if (url == null) {
            // will always return null in this implementation
            url = findResource(name);
        }
        return url;
    }

    protected Enumeration findResources(String name) throws IOException {
        return getDelegator().getResources(name);
    }

    protected Package getPackage(String name) {
    synchronized (packages) {
        Package pkg = (Package) packages.get(name);
        if (pkg == null) {
                pkg = getDelegator().accessibleGetPackage(name);
        if (pkg != null) {
            packages.put(name, pkg);
        }
        }
        return pkg;
    }
    }

    protected Package[] getPackages() {
        Map map;
        synchronized (packages) {
            map = (Map) packages.clone();
        }
        Package[] pkgs;
        pkgs = getDelegator().accessibleGetPackages();
        if (pkgs != null) {
            for (int i = 0; i < pkgs.length; i++) {
                String pkgName = pkgs[i].getName();
                if (map.get(pkgName) == null) {
                    map.put(pkgName, pkgs[i]);
                }
            }
        }
        return (Package[]) map.values().toArray(new Package[map.size()]);
    }

    protected Package definePackage(String name, String specTitle, String specVersion, String specVendor, String implTitle, String implVersion, String implVendor, URL sealBase) throws IllegalArgumentException {
        synchronized (packages) {
            Package pkg = getPackage(name);
            if (pkg != null) {
                throw new IllegalArgumentException(name);
            }
            pkg = super.definePackage(name, specTitle, specVersion, specVendor, implTitle, implVersion, implVendor, sealBase);
            packages.put(name, pkg);
            return pkg;
        }
    }

    private final class ClassOutputStream extends ByteArrayOutputStream {
        private final String className;

        ClassOutputStream(List pkg, String className) {
            StringBuffer temp = new StringBuffer(32);
            for (Iterator it = pkg.iterator(); it.hasNext();) {
                temp.append(it.next() + ".");
            }
            temp.append(className);
            this.className = temp.toString();
        }

        public void close() throws IOException {
            try {
                loadClass(className);
            } catch (ClassNotFoundException e) {
                Logger.getDefault().log("Generating bytecode for JMI class: " + className);
                defineClass(className, this.toByteArray());
            }
            super.close();
        }
    }

    private static final class Delegator extends ClassLoader {
        private final ClassLoaderProvider provider;
        private final ClassLoader parent;

        Delegator(ClassLoaderProvider provider) {
            super(provider == null ? Delegator.class.getClassLoader() : provider.getClassLoader());
            this.parent = (provider == null ? Delegator.class.getClassLoader() : provider.getClassLoader());
            this.provider = provider;
        }

        Delegator getDelegator() {
            return ((provider == null || provider.getClassLoader() == parent) ? this : new Delegator(provider));
        }

        Class accessibleLoadClass(String name, boolean param) throws ClassNotFoundException {
            return this.loadClass(name, param);
        }

        Package accessibleGetPackage(String name) {
            return this.getPackage(name);
        }

        Package[] accessibleGetPackages() {
            return this.getPackages();
        }
    }

    private final class StreamFactory extends JMIStreamFactory {
        public OutputStream createStream(List pkg, String className, String extension) throws IOException {
            if (!JMIStreamFactory.EXT_CLASS.equals(extension)) {
                throw new IllegalArgumentException("ERROR: Wrong extension of the generated data: " + extension + ". Only bytecode data (i.e. extension \"class\" is accepted.");
            }
            return new ClassOutputStream(pkg, className);
        }
    }
}
... 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.