1 package org.sentrysoftware.jawk.jrt; 2 3 /*- 4 * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲ 5 * Jawk 6 * ჻჻჻჻჻჻ 7 * Copyright (C) 2006 - 2023 Sentry Software 8 * ჻჻჻჻჻჻ 9 * This program is free software: you can redistribute it and/or modify 10 * it under the terms of the GNU Lesser General Public License as 11 * published by the Free Software Foundation, either version 3 of the 12 * License, or (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Lesser Public License for more details. 18 * 19 * You should have received a copy of the GNU General Lesser Public 20 * License along with this program. If not, see 21 * <http://www.gnu.org/licenses/lgpl-3.0.html>. 22 * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱ 23 */ 24 25 import java.util.HashSet; 26 import java.util.LinkedList; 27 import java.util.List; 28 import java.util.Set; 29 30 /** 31 * An item which blocks until something useful can be 32 * done with the object. The BlockManager multiplexes 33 * BlockObjects such that unblocking one 34 * BlockObject causes the BlockManager to dispatch 35 * the notifier tag result of the BlockObject. 36 * <p> 37 * BlockObjects are chained. The BlockManager 38 * blocks on all chained BlockObjects until one 39 * is unblocked. 40 * 41 * <p> 42 * Subclasses must provide meaningful block() 43 * and getNotifierTag() routines. 44 * 45 * <p> 46 * BlockObjects do not actually perform the client 47 * blocking. This is done by the BlockManager at the 48 * AVM (interpreted) or compiled runtime environment. 49 * The AVM/compiled environments make special provision 50 * to return the head block object to the BlockManager 51 * (within _EXTENSION_ keyword processing). 52 * 53 * @see BlockManager 54 * @author Danny Daglas 55 */ 56 public abstract class BlockObject { 57 58 private BlockObject nextBlockObject = null; 59 60 /** 61 * <p>Constructor for BlockObject.</p> 62 */ 63 protected BlockObject() {} 64 65 /** 66 * Construct a meaningful notifier tag for this BlockObject. 67 * 68 * @return a {@link java.lang.String} object 69 */ 70 public abstract String getNotifierTag(); 71 72 /** 73 * Block until meaningful data is made available for 74 * the client application. This is called by the BlockManager 75 * in a way such that the BlockManager waits for one 76 * BlockObject to unblock. 77 * 78 * @throws java.lang.InterruptedException if any. 79 */ 80 public abstract void block() throws InterruptedException; 81 82 83 /** 84 * Eliminate the rest of the BlockObject chain. 85 */ 86 public final void clearNextBlockObject() { 87 this.nextBlockObject = null; 88 } 89 90 /** 91 * Chain this BlockObject to another BlockObject. 92 * The chain is linear and there is no upper bounds on 93 * the number of BlockObjects that can be supported. 94 * 95 * @param bo a {@link org.sentrysoftware.jawk.jrt.BlockObject} object 96 */ 97 public void setNextBlockObject(BlockObject bo) { 98 this.nextBlockObject = bo; 99 } 100 101 /** 102 * <p>Getter for the field <code>nextBlockObject</code>.</p> 103 * 104 * @return a {@link org.sentrysoftware.jawk.jrt.BlockObject} object 105 */ 106 protected final BlockObject getNextBlockObject() { 107 return nextBlockObject; 108 } 109 110 /** 111 * Obtain all chained BlockObjects as a List, 112 * including this one. 113 * A BlockObject chain cycle causes a runtime exception 114 * to be thrown. 115 * 116 * @return A List of chained BlockObjects, including 117 * this one. 118 * @throws org.sentrysoftware.jawk.jrt.AwkRuntimeException if the BlockObject 119 * chain contains a cycle. 120 */ 121 public List<BlockObject> getBlockObjects() { 122 List<BlockObject> retval = new LinkedList<BlockObject>(); 123 Set<BlockObject> blockObjects = new HashSet<BlockObject>(); 124 BlockObject ref = this; 125 while (ref != null) { 126 if (blockObjects.contains(ref)) { 127 throw new AwkRuntimeException("Block chain contains a cycle (duplicate) : " + ref.getClass().getName() + " / " + ref.getNotifierTag()); 128 } else { 129 blockObjects.add(ref); 130 } 131 retval.add(ref); 132 ref = ref.getNextBlockObject(); 133 } 134 return retval; 135 } 136 137 /** 138 * {@inheritDoc} 139 * 140 * Ensure non-evaluation of a BlockObject by throwing an AWK Runtime 141 * exception, in case it leaks into AWK evaluation space. 142 */ 143 @Override 144 public final String toString() { 145 throw new AwkRuntimeException("Extension Violation : Cannot AWK-evaluate a BlockObject."); 146 } 147 }