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.core.compiler;

import java.util.LinkedList;
import java.util.List;
import java.util.Collection;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.Hashtable;
import java.util.Enumeration;

import org.openide.ErrorManager;
import org.openide.compiler.DependencyException;
import org.openide.compiler.CompilationEngine;
import org.openide.compiler.CompilerTask;
import org.openide.compiler.CompilerGroup;
import org.openide.compiler.CompilerJob;
import org.openide.compiler.CompilerGroupException;
import org.openide.compiler.CompilerListener;

/** A class that makes compiling.
*
* @author Ales Novak
*/
public class CompilationEngineImpl extends CompilationEngine {

    /** a queue */
    private LinkedList queue;
    /** a thread */
    private CompilerThread t;
    /** an event listener */
    CompilerDisplayer displayer;

    /** new CompilationEngineImpl */
    public CompilationEngineImpl() {
        queue = new LinkedList();
        displayer = new CompilerDisplayer();
        t = new CompilerThread(queue, displayer);
        t.start();
    }

    /** Starts asynchronous compilation of a compiler job.
     * It supports nested jobs, if they are invoked from within a 
     * CompilerGroup.
     *
    * @param job the job to compile
    * @return the task object, one can wait for it to finish
    *    and obtain its results
    */
    protected CompilerTask start(CompilerJob job) {
        CompilerTaskImpl task = null;
        synchronized (queue) {
            Object[] twins = new Object[2];
            twins[0] = job;
            task = new CompilerTaskImpl(job, this, twins);
            twins[1] = task;
            if (!t.isAlive()) {
                (t = new CompilerThread(queue, displayer)).start();
            }
                Thread current = Thread.currentThread();
                if (current.getClass() == CompilerThread.GroupCompiler.class) {
                // contact the compiler thread
                t.runNested(twins);
            } else {
                queue.addLast(twins);
                queue.notify();
            }
        }
        /* To implement synch compilation (would be useful for scripting etc.):
            task.waitFinished();
        */
        return task;
    }

    // not API inherited methods - user must cast to this Class

    /** Restarts compiler thread. */
    public void stop() {
        synchronized (queue) {
            t.stopIt();
            CompilerThread.GroupCompiler.interruptAll();
            Iterator it = queue.iterator();
            while (it.hasNext()) {
                ((CompilerTaskImpl) ((Object[]) it.next())[1]).done();
            }
            queue.clear();
            queue.notify();
            t = new CompilerThread(queue, displayer);
            t.start();
        }
    }

    /** @return true if compiling is executed */
    public boolean isCompiling() {
        return CompilerThread.GroupCompiler.all.size() > 0;
    }

    /** stops specified job */
    void stopTask(CompilerTaskImpl job) {
        synchronized (queue) {
            if (queue.remove(job.ref)) {
                return;
            } else {
                stop();
            }
        }
    }

    /** makes it public */
    static List createLevels(CompilerJob job) throws DependencyException {
        return createComputationLevels(job);
    }

    static Collection createGroups(Collection c) throws CompilerGroupException {
        return createCompilerGroups(c);
    }

    /** A thread of control that compiles. */
    protected static class CompilerThread extends Thread {
        /** a queue */
        public LinkedList queue;
        /** an EventListener */
        public CompilerDisplayer displayer;
        /** stop flag */
        private boolean stop;
        /** current job */
        public CompilerJob currentJob;
        /** current task */
        public CompilerTaskImpl currentTask;

        /** new thread */
        public CompilerThread(LinkedList queue, CompilerDisplayer displayer) {
            setName("Compilation"); // NOI18N
            setPriority(2);
            setDaemon(true);
            this.queue = queue;
            this.displayer = displayer;
        }

        /** stops the thread */
        public void stopIt() {
            stop = true;
        }

        /** @return next CompilerJob from the queue */
        private void nextJobAndTask() throws InterruptedException {
            synchronized (queue) {
                currentJob = null;
                while (queue.size() == 0) {
                    queue.wait();
                }
                Object[] twins = (Object[]) queue.removeFirst();
                currentJob = (CompilerJob) twins[0];
                currentTask = (CompilerTaskImpl) twins[1];
            }
        }

        /** a run method */
        public void run() {
            for (;!stop;) {
                boolean uptodate = true;
                try {
                    nextJobAndTask();  // set currentTask and currentJob
                    displayer.compilationStarted(currentTask);
                    uptodate = processJob();
                } catch (Exception e) {
                    ErrorManager.getDefault().notify(ErrorManager.EXCEPTION, e);
                    currentTask.success = false;
                } catch (ThreadDeath td) {
                    stop = true;
                } finally {
                    displayer.compilationFinished(currentTask, uptodate & currentTask.success);
                    currentJob = null;
                    currentTask = null;
                }
            }
        }

        void runNested(Object[] twins) {
            CompilerJob saveJob = currentJob;
            CompilerTaskImpl saveTask = currentTask;

            try {
                // set the current job/task manually instead of calling
                // nextJobAndTask.
                currentJob = (CompilerJob)twins[0];
                currentTask = (CompilerTaskImpl)twins[1];
                processJob();
            } finally {
                currentJob = saveJob;
                currentTask = saveTask;
            }
        }
        
        /**
         * @return true, if some CompilerGroup was created/run
         */
        boolean processJob() {
            CompilerGroup[] groups;
            GroupCompiler compiler;
            boolean success;
            boolean uptodate = true;
            ListIterator iterator;
                try {
                    iterator = createLevels(currentJob).listIterator();
                groups = new CompilerGroup[0];
                    success = true;
                    while (iterator.hasNext() && success) { // through levels  // if one level fails - stop it
                        groups = (CompilerGroup[]) createGroups((Collection) iterator.next()).toArray(groups);
                        // an array of groups - do parallel compilation
                        compiler = null;
                        uptodate &= (groups.length == 0);
                        for (int i = 0; i < groups.length; i++) {
                            if (groups[i] == null) break;
                            groups[i].addCompilerListener(displayer);
                            compiler = new GroupCompiler(groups[i], compiler);
                        }
                        if (compiler != null) {  // is not upToDate
                            success &= compiler.stay(displayer);  // wait for one level
                        }
                    }
                    currentTask.success = success;
                } catch (Exception e) {
                    ErrorManager.getDefault().notify(ErrorManager.EXCEPTION, e);
                    currentTask.success = false;
                } finally {
                    if (currentTask != null) {
                        currentTask.done();
                    //displayer.compilationFinished(currentTask, uptodate & currentTask.success);
                }
            }
            return uptodate;
        }

        /** Compiles CompilerGroup */
        protected static class GroupCompiler extends Thread {

            static Hashtable all = new Hashtable(11);

            public CompilerGroup grp;
            public GroupCompiler parent;
            public boolean status;
            public GroupCompiler(CompilerGroup grp, GroupCompiler parent) {
                this.grp = grp;
                this.parent = parent;
                status = true;  // OK
                this.start();
            }

            /* called by compilation thread */
            public boolean stay(CompilerListener listener) throws InterruptedException {
                try {
                    all.put(this, this);
                    join();
                    grp.removeCompilerListener(listener);
                    if (parent != null) {
                        return parent.stay(listener) && status;
                    } else {
                        return status;
                    }
                } finally {
                    all.remove(this);
                }
            }

            public void run() {
                try {
                    status = grp.start();
                } catch (ThreadDeath t) {
                    ErrorManager.getDefault().notify(ErrorManager.EXCEPTION, t);
                    status = false;
                } catch (RuntimeException re) {
                    ErrorManager.getDefault().notify(ErrorManager.EXCEPTION, re);
                    status = false;
                }
            }

            /** interrupts all groups threads */
            static void interruptAll() {
                Enumeration e = all.keys();
                while (e.hasMoreElements()) {
                    Thread tt = (Thread) e.nextElement();
                    tt.interrupt();
                }
            }
        }
    }


}
... 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.