⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 packagecompilationdata.java

📁 jboss规则引擎
💻 JAVA
字号:
package org.drools.rule;

/*
 * Copyright 2005 JBoss Inc
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Externalizable;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.drools.CheckedDroolsException;
import org.drools.RuntimeDroolsException;
import org.drools.common.ObjectInputStreamWithLoader;
import org.drools.spi.Consequence;
import org.drools.spi.EvalExpression;
import org.drools.spi.PredicateExpression;
import org.drools.spi.ReturnValueExpression;

public class PackageCompilationData
    implements
    Externalizable {

    /**
     * 
     */
    private static final long            serialVersionUID = -4351259299237235523L;

    private Map                          invokerLookups   = new HashMap();

    private Object                       AST;

    private Map                          store            = new HashMap();

    private transient PackageClassLoader classLoader;

    private transient ClassLoader        parentClassLoader;

    public PackageCompilationData() {
        this( null );
    }

    public PackageCompilationData(final ClassLoader parentClassLoader) {
        init( parentClassLoader );
    }

    private void init(ClassLoader parentClassLoader) {
        if ( parentClassLoader == null ) {
            parentClassLoader = Thread.currentThread().getContextClassLoader();

            if ( parentClassLoader == null ) {
                parentClassLoader = getClass().getClassLoader();
            }
        }

        this.parentClassLoader = parentClassLoader;
        this.classLoader = new PackageClassLoader( this.parentClassLoader );
    }

    /**
     * Handles the write serialization of the PackageCompilationData. Patterns in Rules may reference generated data which cannot be serialized by 
     * default methods. The PackageCompilationData holds a reference to the generated bytecode. The generated bytecode must be restored before any Rules.
     * 
     */
    public void writeExternal(final ObjectOutput stream) throws IOException {
        stream.writeObject( this.store );
        stream.writeObject( this.AST );

        // Rules must be restored by an ObjectInputStream that can resolve using a given ClassLoader to handle seaprately by storing as
        // a byte[]        
        final ByteArrayOutputStream bos = new ByteArrayOutputStream();
        final ObjectOutput out = new ObjectOutputStream( bos );
        out.writeObject( this.invokerLookups );
        stream.writeObject( bos.toByteArray() );
    }

    /**
     * Handles the read serialization of the PackageCompilationData. Patterns in Rules may reference generated data which cannot be serialized by 
     * default methods. The PackageCompilationData holds a reference to the generated bytecode; which must be restored before any Rules.
     * A custom ObjectInputStream, able to resolve classes against the bytecode, is used to restore the Rules.
     * 
     */
    public void readExternal(final ObjectInput stream) throws IOException,
                                                      ClassNotFoundException {
        init( null );

        this.store = (Map) stream.readObject();
        this.AST = stream.readObject();

        // Return the rules stored as a byte[]
        final byte[] bytes = (byte[]) stream.readObject();

        //  Use a custom ObjectInputStream that can resolve against a given classLoader
        final ObjectInputStreamWithLoader streamWithLoader = new ObjectInputStreamWithLoader( new ByteArrayInputStream( bytes ),
                                                                                              this.classLoader );
        this.invokerLookups = (Map) streamWithLoader.readObject();
    }

    public ClassLoader getClassLoader() {
        return this.classLoader;
    }

    public byte[] read(final String resourceName) {
        final byte[] bytes = null;

        if ( this.store != null ) {
            return (byte[]) this.store.get( resourceName.replace( '.',
                                                                  '/' ) + ".class" );
        }
        return bytes;
    }

    public void write(final String resourceName,
                      final byte[] clazzData) throws RuntimeDroolsException {
        if ( this.store.put( resourceName.replace( '.',
                                                   '/' ) + ".class",
                             clazzData ) != null ) {
            // we are updating an existing class so reload();
            reload();
        } else {
            try {
                wire( resourceName );
            } catch ( final Exception e ) {
                throw new RuntimeDroolsException( e );
            }
        }

    }

    public void remove(final String resourceName) throws RuntimeDroolsException {
        this.invokerLookups.remove( resourceName );
        if ( this.store.remove( resourceName.replace( '.',
                                                      '/' ) + ".class" ) != null ) {
            // we need to make sure the class is removed from the classLoader
            reload();
        }
    }

    public String[] list() {
        if ( this.store == null ) {
            return new String[0];
        }
        final List names = new ArrayList();

        for ( final Iterator it = this.store.keySet().iterator(); it.hasNext(); ) {
            final String name = (String) it.next();
            names.add( name.replace( '/',
                                     '.' ).substring( 0,
                                                      name.length() - 6 ) );
        }

        return (String[]) names.toArray( new String[this.store.size()] );
    }

    /**
     * This class drops the classLoader and reloads it. During this process  it must re-wire all the invokeables.
     * @throws CheckedDroolsException
     */
    public void reload() throws RuntimeDroolsException {
        // drops the classLoader and adds a new one
        this.classLoader = new PackageClassLoader( this.parentClassLoader );

        // Wire up invokers
        try {
            for ( final Iterator it = this.invokerLookups.keySet().iterator(); it.hasNext(); ) {
                wire( (String) it.next() );
            }
        } catch ( final ClassNotFoundException e ) {
            throw new RuntimeDroolsException( e );
        } catch ( final InstantiationError e ) {
            throw new RuntimeDroolsException( e );
        } catch ( final IllegalAccessException e ) {
            throw new RuntimeDroolsException( e );
        } catch ( final InstantiationException e ) {
            throw new RuntimeDroolsException( e );
        }
    }

    public void clear() {
        this.store.clear();
        this.invokerLookups.clear();
        this.AST = null;
        reload();
    }

    public void wire(final String className) throws ClassNotFoundException,
                                            InstantiationException,
                                            IllegalAccessException {
        final Object invoker = this.invokerLookups.get( className );
        wire( className,
              invoker );
    }

    public void wire(final String className,
                     final Object invoker) throws ClassNotFoundException,
                                          InstantiationException,
                                          IllegalAccessException {
        final Class clazz = this.classLoader.findClass( className );
        if ( invoker instanceof ReturnValueConstraint ) {
            ((ReturnValueConstraint) invoker).setReturnValueExpression( (ReturnValueExpression) clazz.newInstance() );
        } else if ( invoker instanceof PredicateConstraint ) {
            ((PredicateConstraint) invoker).setPredicateExpression( (PredicateExpression) clazz.newInstance() );
        } else if ( invoker instanceof EvalCondition ) {
            ((EvalCondition) invoker).setEvalExpression( (EvalExpression) clazz.newInstance() );
        } else if ( invoker instanceof Rule ) {
            ((Rule) invoker).setConsequence( (Consequence) clazz.newInstance() );
        }
    }

    public String toString() {
        return this.getClass().getName() + this.store.toString();
    }

    public void putInvoker(final String className,
                           final Object invoker) {
        this.invokerLookups.put( className,
                                 invoker );
    }

    public void putAllInvokers(final Map invokers) {
        this.invokerLookups.putAll( invokers );

    }

    public Map getInvokers() {
        return this.invokerLookups;
    }

    public void removeInvoker(final String className) {
        this.invokerLookups.remove( className );
    }

    public Object getAST() {
        return this.AST;
    }

    public void setAST(final Object ast) {
        this.AST = ast;
    }

    /**
     * Lifted and adapted from Jakarta commons-jci
     * 
     * @author mproctor
     *
     */
    public class PackageClassLoader extends ClassLoader {

        public PackageClassLoader(final ClassLoader parentClassLoader) {
            super( parentClassLoader );
        }

        public Class fastFindClass(final String name) {
            final Class clazz = findLoadedClass( name );

            if ( clazz == null ) {
                final byte[] clazzBytes = read( name );
                if ( clazzBytes != null ) {
                    return defineClass( name,
                                        clazzBytes,
                                        0,
                                        clazzBytes.length );
                }
            }

            return clazz;
        }

        /**
         * Javadocs recommend that this method not be overloaded. We overload this so that we can prioritise the fastFindClass 
         * over method calls to parent.loadClass(name, false); and c = findBootstrapClass0(name); which the default implementation
         * would first - hence why we call it "fastFindClass" instead of standard findClass, this indicates that we give it a 
         * higher priority than normal.
         * 
         */
        protected synchronized Class loadClass(final String name,
                                               final boolean resolve) throws ClassNotFoundException {
            Class clazz = fastFindClass( name );

            if ( clazz == null ) {
                final ClassLoader parent = getParent();
                if ( parent != null ) {
                    clazz = parent.loadClass( name );
                } else {
                    throw new ClassNotFoundException( name );
                }
            }

            if ( resolve ) {
                resolveClass( clazz );
            }

            return clazz;
        }

        protected Class findClass(final String name) throws ClassNotFoundException {
            final Class clazz = fastFindClass( name );
            if ( clazz == null ) {
                throw new ClassNotFoundException( name );
            }
            return clazz;
        }

        public InputStream getResourceAsStream(final String name) {
            final byte[] bytes = (byte[]) PackageCompilationData.this.store.get( name );
            if ( bytes != null ) {
                return new ByteArrayInputStream( bytes );
            } else {
                InputStream input = this.getParent().getResourceAsStream( name );
                if( input == null ){
                    input = super.getResourceAsStream( name );
                }
                return input;
            }
        }
    }

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -