001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.make;
031:
032: import com.caucho.loader.DynamicClassLoader;
033: import com.caucho.util.Alarm;
034: import com.caucho.util.Log;
035: import com.caucho.vfs.Dependency;
036:
037: import java.util.ArrayList;
038: import java.util.logging.Logger;
039:
040: /**
041: * Contains a set of dependencies.
042: */
043: public class DependencyContainer implements Dependency {
044: private static Logger _log;
045:
046: private ArrayList<Dependency> _dependencyList = new ArrayList<Dependency>();
047:
048: // Marks if the last check returned modified
049: private boolean _isModified;
050: // Marks if the modification has been logged
051: private boolean _isModifiedLog;
052:
053: // The interval for checking for a dependency.
054: private long _checkInterval = 2000L;
055:
056: // When the dependency check last occurred
057: private long _lastCheckTime = 0;
058:
059: private volatile boolean _isChecking;
060:
061: public DependencyContainer() {
062: ClassLoader loader = Thread.currentThread()
063: .getContextClassLoader();
064:
065: _checkInterval = DynamicClassLoader
066: .getGlobalDependencyCheckInterval();
067:
068: for (; loader != null; loader = loader.getParent()) {
069: if (loader instanceof DynamicClassLoader) {
070: _checkInterval = ((DynamicClassLoader) loader)
071: .getDependencyCheckInterval();
072: break;
073: }
074: }
075: }
076:
077: /**
078: * Adds a dependency.
079: */
080: public DependencyContainer add(Dependency dependency) {
081: if (dependency == this )
082: throw new IllegalArgumentException(
083: "Can't add self as a dependency.");
084:
085: if (!_dependencyList.contains(dependency))
086: _dependencyList.add(dependency);
087:
088: // server/1d0w
089: // XXX: _lastCheckTime = 0;
090:
091: return this ;
092: }
093:
094: /**
095: * Removes a dependency.
096: */
097: public DependencyContainer remove(Dependency dependency) {
098: if (dependency == this )
099: throw new IllegalArgumentException(
100: "Can't remove self as a dependency.");
101:
102: _dependencyList.remove(dependency);
103:
104: return this ;
105: }
106:
107: public int size() {
108: return _dependencyList.size();
109: }
110:
111: /**
112: * Sets the check modification check interval in milliseconds.
113: * Negative values mean never check. 0 means always check.
114: *
115: * @param checkInterval how often the dependency should be checked
116: */
117: public void setCheckInterval(long checkInterval) {
118: if (checkInterval < 0 || checkInterval > Long.MAX_VALUE / 2)
119: _checkInterval = Long.MAX_VALUE / 2;
120: else
121: _checkInterval = checkInterval;
122:
123: _lastCheckTime = 0;
124: }
125:
126: /**
127: * Gets the check modification check interval.
128: * Negative values mean never check. 0 means always check.
129: */
130: public long getCheckInterval() {
131: return _checkInterval;
132: }
133:
134: /**
135: * Sets the modified.
136: */
137: public void setModified(boolean isModified) {
138: _isModified = isModified;
139: _lastCheckTime = 0;
140:
141: if (!isModified)
142: _isModifiedLog = false;
143: }
144:
145: /**
146: * Resets the check interval.
147: */
148: public void resetDependencyCheckInterval() {
149: _lastCheckTime = 0;
150: }
151:
152: /**
153: * Clears the modified flag and sets the last check time to now.
154: */
155: public void clearModified() {
156: _isModified = false;
157: _lastCheckTime = Alarm.getCurrentTime();
158: _isModifiedLog = false;
159: }
160:
161: /**
162: * Returns true if the underlying dependencies have changed.
163: */
164: public boolean isModified() {
165: synchronized (this ) {
166: if (_isChecking || _isModified) {
167: return _isModified;
168: }
169:
170: _isChecking = true;
171: }
172:
173: try {
174: long now = Alarm.getCurrentTime();
175:
176: if (now < _lastCheckTime + _checkInterval) {
177: return _isModified;
178: }
179:
180: _lastCheckTime = now;
181:
182: for (int i = _dependencyList.size() - 1; i >= 0; i--) {
183: Dependency dependency = _dependencyList.get(i);
184:
185: if (dependency.isModified()) {
186: _isModified = true;
187:
188: return _isModified;
189: }
190: }
191:
192: // _isModified = false;
193:
194: return _isModified;
195: } finally {
196: _isChecking = false;
197: }
198: }
199:
200: /**
201: * Logs the reason for modification.
202: */
203: public boolean logModified(Logger log) {
204: if (_isModifiedLog)
205: return true;
206:
207: for (int i = _dependencyList.size() - 1; i >= 0; i--) {
208: Dependency dependency = _dependencyList.get(i);
209:
210: if (dependency.logModified(log)) {
211: _isModifiedLog = true;
212: return true;
213: }
214: }
215:
216: return false;
217: }
218:
219: /**
220: * Returns true if the underlying dependencies have changed, forcing a check.
221: */
222: public boolean isModifiedNow() {
223: _lastCheckTime = 0;
224:
225: return isModified();
226: }
227:
228: private Logger log() {
229: if (_log == null)
230: _log = Logger
231: .getLogger(DependencyContainer.class.getName());
232:
233: return _log;
234: }
235:
236: public String toString() {
237: return "DependencyContainer" + _dependencyList;
238: }
239: }
|