View Javadoc
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 }