001 // This file is part of the program FRYSK. 002 // 003 // Copyright 2005, Red Hat Inc. 004 // 005 // FRYSK is free software; you can redistribute it and/or modify it 006 // under the terms of the GNU General Public License as published by 007 // the Free Software Foundation; version 2 of the License. 008 // 009 // FRYSK is distributed in the hope that it will be useful, but 010 // WITHOUT ANY WARRANTY; without even the implied warranty of 011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 // General Public License for more details. 013 // 014 // You should have received a copy of the GNU General Public License 015 // along with FRYSK; if not, write to the Free Software Foundation, 016 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 017 // 018 // In addition, as a special exception, Red Hat, Inc. gives You the 019 // additional right to link the code of FRYSK with code not covered 020 // under the GNU General Public License ("Non-GPL Code") and to 021 // distribute linked combinations including the two, subject to the 022 // limitations in this paragraph. Non-GPL Code permitted under this 023 // exception must only link to the code of FRYSK through those well 024 // defined interfaces identified in the file named EXCEPTION found in 025 // the source code files (the "Approved Interfaces"). The files of 026 // Non-GPL Code may instantiate templates or use macros or inline 027 // functions from the Approved Interfaces without causing the 028 // resulting work to be covered by the GNU General Public 029 // License. Only Red Hat, Inc. may make changes or additions to the 030 // list of Approved Interfaces. You must obey the GNU General Public 031 // License in all respects for all of the FRYSK code and other code 032 // used in conjunction with FRYSK except the Non-GPL Code covered by 033 // this exception. If you modify this file, you may extend this 034 // exception to your version of the file, but you are not obligated to 035 // do so. If you do not wish to provide this exception without 036 // modification, you must delete this exception statement from your 037 // version and license this file solely under the GPL without 038 // exception. 039 040 041 package frysk.gui.monitor.observers; 042 043 import java.util.Iterator; 044 import java.util.List; 045 import java.util.logging.Level; 046 047 import org.jdom.Element; 048 049 import frysk.gui.dialogs.DialogManager; 050 import frysk.gui.monitor.Combo; 051 import frysk.gui.monitor.EventLogger; 052 import frysk.gui.monitor.GuiObject; 053 import frysk.gui.monitor.GuiTask; 054 import frysk.gui.monitor.ObservableLinkedList; 055 import frysk.gui.monitor.SaveableXXX; 056 import frysk.gui.monitor.actions.ActionPoint; 057 import frysk.gui.monitor.actions.GenericActionPoint; 058 import frysk.gui.monitor.eventviewer.EventManager; 059 import frysk.gui.monitor.filters.Filter; 060 import frysk.gui.monitor.filters.FilterPoint; 061 import frysk.proc.Action; 062 import frysk.proc.Task; 063 import frysk.proc.TaskObserver; 064 065 /** 066 * A more sophisticated implementer of Observer. provides name and tool tip 067 * strings for GUI display purposes. Takes Action objects that can be used by 068 * clients to customize behaviour. 069 */ 070 public class ObserverRoot 071 extends GuiObject 072 implements TaskObserver, SaveableXXX 073 { 074 075 private ObservableLinkedList actions; 076 077 private String info; 078 079 private ObservableLinkedList filterPoints; 080 081 private ObservableLinkedList actionPoints; 082 083 private final String baseName; 084 085 public GenericActionPoint genericActionPoint; 086 087 private frysk.proc.Action returnAction; 088 089 protected ObserverRoot () 090 { 091 super(); 092 093 this.actions = new ObservableLinkedList(); 094 this.info = new String(); 095 this.filterPoints = new ObservableLinkedList(); 096 this.actionPoints = new ObservableLinkedList(); 097 this.baseName = ""; 098 099 this.returnAction = Action.CONTINUE; 100 101 this.genericActionPoint = new GenericActionPoint(" ", 102 "Actions that dont take any arguments"); 103 this.addActionPoint(genericActionPoint); 104 } 105 106 protected ObserverRoot (String name, String toolTip) 107 { 108 super(name, toolTip); 109 110 this.actions = new ObservableLinkedList(); 111 this.info = new String(); 112 this.filterPoints = new ObservableLinkedList(); 113 this.actionPoints = new ObservableLinkedList(); 114 this.baseName = name; 115 116 this.returnAction = Action.CONTINUE; 117 118 this.genericActionPoint = new GenericActionPoint(" ", 119 "Actions that dont take any arguments"); 120 this.addActionPoint(genericActionPoint); 121 } 122 123 protected ObserverRoot (ObserverRoot other) 124 { 125 super(other); 126 127 this.actions = new ObservableLinkedList(other.actions, true); 128 this.info = new String(other.info); 129 this.filterPoints = new ObservableLinkedList(); // do not copy.. 130 this.actionPoints = new ObservableLinkedList(); // ... because children 131 // will readd items 132 this.baseName = other.baseName; 133 134 this.returnAction = other.returnAction; 135 136 this.genericActionPoint = new GenericActionPoint(other.genericActionPoint); 137 this.addActionPoint(genericActionPoint); 138 } 139 140 public void addFailed (Object o, Throwable w) 141 { 142 143 EventLogger.logAddFailed("addFailed(Object o, Throwable w)", o); 144 throw new RuntimeException("Failed to add " + this + " to " + o, w); 145 } 146 147 /** 148 * Could be called by an action during the update call to get print 149 * generic information about the event that just occurred format (as 150 * currently used by logger): PID 123 did action ACTION on Host HOST 151 */ 152 public String getInfo () 153 { 154 return info; 155 } 156 157 /** 158 * Should be called whent the observer has fired. Every time this is 159 * called it sends a message to the logs, so it should only be called 160 * once every time the information changes 161 * 162 * @param info info string to be set 163 */ 164 protected void setInfo (String info) 165 { 166 EventLogger.theLogger.getEventLogger().log(Level.INFO, info); 167 this.info = info; 168 } 169 170 protected void runActions () 171 { 172 this.genericActionPoint.runActions(this); 173 } 174 175 public ObservableLinkedList getFilterPoints () 176 { 177 return this.filterPoints; 178 } 179 180 public ObservableLinkedList getActionPoints () 181 { 182 return this.actionPoints; 183 } 184 185 protected void addFilterPoint (FilterPoint filterPoint) 186 { 187 this.filterPoints.add(filterPoint); 188 } 189 190 protected void addActionPoint (ActionPoint actionPoint) 191 { 192 this.actionPoints.add(actionPoint); 193 } 194 195 public String getBaseName () 196 { 197 return baseName; 198 } 199 200 private void saveReturnAction (Element node) 201 { 202 if (this.getCurrentAction() == null) 203 { 204 node.setAttribute("returnAction", "null"); 205 return; 206 } 207 if (this.getCurrentAction() == Action.BLOCK) 208 { 209 node.setAttribute("returnAction", Action.BLOCK.toString()); 210 return; 211 } 212 if (this.getCurrentAction() == Action.CONTINUE) 213 { 214 node.setAttribute("returnAction", Action.CONTINUE.toString()); 215 return; 216 } 217 } 218 219 private Action loadReturnAction (Element node) 220 { 221 String actionString = node.getAttributeValue("returnAction"); 222 223 if (actionString.equals("null")) 224 { 225 return null; 226 } 227 if (actionString.equals(Action.BLOCK.toString())) 228 { 229 return Action.BLOCK; 230 } 231 if (actionString.equals(Action.CONTINUE.toString())) 232 { 233 return Action.CONTINUE; 234 } 235 236 throw new RuntimeException("Error while loading observer: unkown action"); 237 } 238 239 public void save (Element node) 240 { 241 super.save(node); 242 243 this.saveReturnAction(node); 244 245 // actions 246 Element actionPointsXML = new Element("actionPoints"); 247 248 Iterator iterator = this.getActionPoints().iterator(); 249 while (iterator.hasNext()) 250 { 251 ActionPoint actionPoint = (ActionPoint) iterator.next(); 252 Element actionPointXML = new Element("actionPoint"); 253 actionPoint.save(actionPointXML); 254 actionPointsXML.addContent(actionPointXML); 255 } 256 node.addContent(actionPointsXML); 257 258 // filters 259 260 Element filterPointsXML = new Element("filterPoints"); 261 262 iterator = this.getFilterPoints().iterator(); 263 while (iterator.hasNext()) 264 { 265 FilterPoint filterPoint = (FilterPoint) iterator.next(); 266 Element filterPointXML = new Element("filterPoint"); 267 filterPoint.save(filterPointXML); 268 filterPointsXML.addContent(filterPointXML); 269 } 270 node.addContent(filterPointsXML); 271 272 } 273 274 public void load (Element node) 275 { 276 super.load(node); 277 278 this.setReturnAction(this.loadReturnAction(node)); 279 280 // actions 281 Element actionPointsXML = node.getChild("actionPoints"); 282 List list = (List) (actionPointsXML.getChildren("actionPoint")); 283 Iterator i = list.iterator(); 284 Iterator j = this.getActionPoints().iterator(); 285 286 while (i.hasNext()) 287 { 288 ((ActionPoint) j.next()).load(((Element) i.next())); 289 } 290 291 // filters 292 Element filterPointsXML = node.getChild("filterPoints"); 293 list = (List) filterPointsXML.getChildren("filterPoint"); 294 i = list.iterator(); 295 j = this.getFilterPoints().iterator(); 296 297 while (i.hasNext()) 298 { 299 ((FilterPoint) j.next()).load(((Element) i.next())); 300 } 301 } 302 303 protected GuiObject getCopy () 304 { 305 return new ObserverRoot(this); 306 } 307 308 /** 309 * Returns combo objects representing the currently applied filters. 310 * 311 * @see Combo. 312 * @return List of combos. 313 */ 314 public ObservableLinkedList getCurrentFilterCombos () 315 { 316 ObservableLinkedList combos = new ObservableLinkedList(); 317 318 Iterator i = this.getFilterPoints().iterator(); 319 while (i.hasNext()) 320 { 321 FilterPoint filterPoint = (FilterPoint) i.next(); 322 Iterator j = filterPoint.getItems().iterator(); 323 while (j.hasNext()) 324 { 325 Filter filter = (Filter) j.next(); 326 combos.add(new Combo(filterPoint, filter)); 327 } 328 } 329 return combos; 330 } 331 332 /** 333 * Returns combo objects representing the currently applied actions. 334 * 335 * @see Combo. 336 * @return List of combos. 337 */ 338 public ObservableLinkedList getCurrentActionCombos () 339 { 340 ObservableLinkedList combos = new ObservableLinkedList(); 341 342 Iterator i = this.getActionPoints().iterator(); 343 while (i.hasNext()) 344 { 345 ActionPoint actionPoint = (ActionPoint) i.next(); 346 Iterator j = actionPoint.getItems().iterator(); 347 while (j.hasNext()) 348 { 349 frysk.gui.monitor.actions.Action action = (frysk.gui.monitor.actions.Action) j.next(); 350 combos.add(new Combo(actionPoint, action)); 351 } 352 } 353 return combos; 354 } 355 356 /** 357 * Used to set which action is taken by the observer with respect to 358 * resuming execution of the observed thread after all the actions are 359 * executed. acceptable values are Action.BLOCK to block the process. 360 * Action.CONTINUE to continue the process. and null to pop-up a dialog 361 * and ask the user for action. 362 */ 363 public void setReturnAction (frysk.proc.Action action) 364 { 365 this.returnAction = action; 366 } 367 368 /** 369 * Should be used by inheriting observers to get the desired Action with 370 * respect to stoping/resumeing execution of the observed thread. 371 * 372 * @return 373 */ 374 protected frysk.proc.Action whatActionShouldBeReturned () 375 { 376 if (this.returnAction != null) 377 { 378 return this.returnAction; 379 } 380 else 381 { 382 if (DialogManager.showQueryDialog(this.getName() 383 + ": would you like to resume thread execution ?")) 384 { 385 return Action.CONTINUE; 386 } 387 else 388 { 389 return Action.BLOCK; 390 } 391 } 392 } 393 394 public frysk.proc.Action getCurrentAction () 395 { 396 return this.returnAction; 397 } 398 399 public void addedTo (Object observable) 400 { 401 EventManager.theManager.observerAdded( 402 GuiTask.GuiTaskFactory.getGuiTask((Task) observable), 403 this); 404 } 405 406 public void deletedFrom (Object observable) 407 { 408 EventManager.theManager.observerAdded( 409 GuiTask.GuiTaskFactory.getGuiTask((Task) observable), 410 this); 411 } 412 413 }