KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sourceforge > cruisecontrol > BuildQueue


1 /********************************************************************************
2  * CruiseControl, a Continuous Integration Toolkit
3  * Copyright (c) 2001-2003, ThoughtWorks, Inc.
4  * 651 W Washington Ave. Suite 600
5  * Chicago, IL 60661 USA
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * + Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * + Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following
17  * disclaimer in the documentation and/or other materials provided
18  * with the distribution.
19  *
20  * + Neither the name of ThoughtWorks, Inc., CruiseControl, nor the
21  * names of its contributors may be used to endorse or promote
22  * products derived from this software without specific prior
23  * written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
29  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  ********************************************************************************/

37 package net.sourceforge.cruisecontrol;
38
39 import java.util.ArrayList JavaDoc;
40 import java.util.EventListener JavaDoc;
41 import java.util.Iterator JavaDoc;
42 import java.util.LinkedList JavaDoc;
43 import java.util.List JavaDoc;
44
45 import net.sourceforge.cruisecontrol.util.threadpool.ThreadQueue;
46
47 import org.apache.log4j.Logger;
48
49 /**
50  * Provides an independent thread of execution that knows how to
51  * build Projects. Passes {@link Project} objects to a thread
52  * queue. The number of worker threads is defined in config.xml
53  *
54  * @author Peter Mei <pmei@users.sourceforge.net>
55  * @author jfredrick
56  * @author Jared Richardson <jared.richardson@sas.com>
57  */

58 public class BuildQueue implements Runnable JavaDoc {
59     private static final Logger LOG = Logger.getLogger(BuildQueue.class);
60
61     private final LinkedList JavaDoc queue = new LinkedList JavaDoc();
62     private boolean waiting = false;
63     private Thread JavaDoc buildQueueThread;
64
65     private List JavaDoc listeners = new ArrayList JavaDoc();
66
67     /**
68      * @param project
69      */

70     public void requestBuild(Project project) {
71         LOG.debug("BuildQueue.requestBuild Thread = " + Thread.currentThread().getName());
72
73         notifyListeners();
74         synchronized (queue) {
75             queue.add(project);
76             queue.notify();
77         }
78     }
79
80     /**
81      * @param project The project to find in the queues
82      * @return String representing this project's position in the various queues, e.g. IDLE[ 5 / 24 ]
83      */

84     public String JavaDoc findPosition(Project project) {
85         int position;
86         int length;
87         synchronized (queue) {
88             position = queue.indexOf(project);
89             length = queue.size();
90         }
91         if (position < 0) {
92             return ThreadQueue.findPosition(project.getName());
93         }
94         // position is 0-based, make it 1-based for human reporting
95
return "BUILD_REQUESTED[ " + (position + 1) + " / " + length + " ]";
96     }
97
98     void serviceQueue() {
99         while (!queue.isEmpty()) {
100             Project nextProject;
101             synchronized (queue) {
102                 nextProject = (Project) queue.remove(0);
103             }
104             if (nextProject != null) {
105                 LOG.info("now adding to the thread queue: " + nextProject.getName());
106                 ProjectWrapper pw = new ProjectWrapper(nextProject);
107                 // let's not add the task more than once
108
String JavaDoc name = nextProject.getName();
109                 if (ThreadQueue.isActive(name)) {
110                   // it's already there... don't re-add it.
111
// later, we'll need to add it to a queued up list
112
// so we don't 'forget' about the new build request
113
} else {
114                   ThreadQueue.addTask(pw);
115                 }
116             }
117         }
118     }
119
120     public void run() {
121         try {
122             LOG.info("BuildQueue started");
123             while (true) {
124                 synchronized (queue) {
125                     if (queue.isEmpty()) {
126                         waiting = true;
127                         queue.wait();
128                     }
129                     waiting = false;
130                 }
131                 serviceQueue();
132             }
133         } catch (InterruptedException JavaDoc e) {
134             String JavaDoc message = "BuildQueue.run() interrupted. Stopping?";
135             LOG.debug(message, e);
136         } catch (Throwable JavaDoc e) {
137             LOG.error("BuildQueue.run()", e);
138         } finally {
139             waiting = false;
140             LOG.info("BuildQueue thread is no longer alive");
141         }
142     }
143
144     void start() {
145         buildQueueThread = new Thread JavaDoc(this, "BuildQueueThread");
146         buildQueueThread.setDaemon(false);
147         buildQueueThread.start();
148         while (!buildQueueThread.isAlive()) {
149             try {
150                 Thread.sleep(500);
151             } catch (InterruptedException JavaDoc e) {
152                 String JavaDoc message = "BuildQueue.start() interrupted";
153                 LOG.error(message, e);
154                 throw new RuntimeException JavaDoc(message);
155             }
156         }
157     }
158
159     void stop() {
160         LOG.info("Stopping BuildQueue");
161         buildQueueThread.interrupt();
162         synchronized (queue) {
163             queue.notify();
164         }
165     }
166
167     public boolean isAlive() {
168         return true;
169     }
170
171     public boolean isWaiting() {
172         return waiting;
173     }
174     
175     public void addListener(Listener listener) {
176         listeners.add(listener);
177     }
178
179     private void notifyListeners() {
180         Iterator JavaDoc toNotify = listeners.iterator();
181         while (toNotify.hasNext()) {
182             try {
183                 ((Listener) toNotify.next()).buildRequested();
184             } catch (Exception JavaDoc e) {
185                 LOG.error("exception notifying listener before project queued", e);
186             }
187         }
188
189     }
190
191     public static interface Listener extends EventListener JavaDoc {
192         void buildRequested();
193     }
194 }
195
Popular Tags